From ceed844b5284aeabbdfe25ccf099e7ebeeb14a9b Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Thu, 2 Nov 2023 17:10:33 +0100 Subject: gccrs: Add visibility to trait item The compiler shall parse visibility modifiers on trait items and reject those at a later stage (ast validation). gcc/rust/ChangeLog: * ast/rust-item.h (struct Visibility): Move Visibility from here... * ast/rust-ast.h (struct Visibility): ...to here. * parse/rust-parse-impl.h (Parser::parse_trait_item): Parse visibility before giving it back to the item parsing function. (Parser::parse_trait_type): Add visibility modifier. * parse/rust-parse.h (RUST_PARSE_H): Change function prototype. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/ast/rust-ast.h | 248 ++++++++++++++++++++------------------- gcc/rust/ast/rust-item.h | 5 +- gcc/rust/parse/rust-parse-impl.h | 10 +- gcc/rust/parse/rust-parse.h | 3 +- 4 files changed, 140 insertions(+), 126 deletions(-) diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 67ae92f..4dc7f97 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -490,6 +490,126 @@ operator!= (const SimplePath &lhs, const std::string &rhs) // forward decl for Attribute class AttrInput; +// Visibility of item - if the item has it, then it is some form of public +struct Visibility +{ +public: + enum VisType + { + PRIV, + PUB, + PUB_CRATE, + PUB_SELF, + PUB_SUPER, + PUB_IN_PATH + }; + +private: + VisType vis_type; + // Only assigned if vis_type is IN_PATH + SimplePath in_path; + location_t locus; + + // should this store location info? + +public: + // Creates a Visibility - TODO make constructor protected or private? + Visibility (VisType vis_type, SimplePath in_path, location_t locus) + : vis_type (vis_type), in_path (std::move (in_path)), locus (locus) + {} + + VisType get_vis_type () const { return vis_type; } + + // Returns whether visibility is in an error state. + bool is_error () const + { + return vis_type == PUB_IN_PATH && in_path.is_empty (); + } + + // Returns whether a visibility has a path + bool has_path () const { return !is_error () && vis_type >= PUB_CRATE; } + + // Returns whether visibility is public or not. + bool is_public () const { return vis_type != PRIV && !is_error (); } + + location_t get_locus () const { return locus; } + + // empty? + // Creates an error visibility. + static Visibility create_error () + { + return Visibility (PUB_IN_PATH, SimplePath::create_empty (), + UNDEF_LOCATION); + } + + // Unique pointer custom clone function + /*std::unique_ptr clone_visibility() const { + return std::unique_ptr(clone_visibility_impl()); + }*/ + + /* TODO: think of a way to only allow valid Visibility states - polymorphism + * is one idea but may be too resource-intensive. */ + + // Creates a public visibility with no further features/arguments. + // empty? + static Visibility create_public (location_t pub_vis_location) + { + return Visibility (PUB, SimplePath::create_empty (), pub_vis_location); + } + + // Creates a public visibility with crate-relative paths + static Visibility create_crate (location_t crate_tok_location, + location_t crate_vis_location) + { + return Visibility (PUB_CRATE, + SimplePath::from_str ("crate", crate_tok_location), + crate_vis_location); + } + + // Creates a public visibility with self-relative paths + static Visibility create_self (location_t self_tok_location, + location_t self_vis_location) + { + return Visibility (PUB_SELF, + SimplePath::from_str ("self", self_tok_location), + self_vis_location); + } + + // Creates a public visibility with parent module-relative paths + static Visibility create_super (location_t super_tok_location, + location_t super_vis_location) + { + return Visibility (PUB_SUPER, + SimplePath::from_str ("super", super_tok_location), + super_vis_location); + } + + // Creates a private visibility + static Visibility create_private () + { + return Visibility (PRIV, SimplePath::create_empty (), UNDEF_LOCATION); + } + + // Creates a public visibility with a given path or whatever. + static Visibility create_in_path (SimplePath in_path, + location_t in_path_vis_location) + { + return Visibility (PUB_IN_PATH, std::move (in_path), in_path_vis_location); + } + + std::string as_string () const; + const SimplePath &get_path () const { return in_path; } + SimplePath &get_path () { return in_path; } + +protected: + // Clone function implementation - not currently virtual but may be if + // polymorphism used + /*virtual*/ Visibility *clone_visibility_impl () const + { + return new Visibility (*this); + } +}; + // aka Attr // Attribute AST representation struct Attribute @@ -1042,125 +1162,6 @@ protected: Item *clone_stmt_impl () const final override { return clone_item_impl (); } }; -// Visibility of item - if the item has it, then it is some form of public -struct Visibility -{ -public: - enum VisType - { - PRIV, - PUB, - PUB_CRATE, - PUB_SELF, - PUB_SUPER, - PUB_IN_PATH - }; - -private: - VisType vis_type; - // Only assigned if vis_type is IN_PATH - SimplePath in_path; - location_t locus; - - // should this store location info? - -public: - // Creates a Visibility - TODO make constructor protected or private? - Visibility (VisType vis_type, SimplePath in_path, location_t locus) - : vis_type (vis_type), in_path (std::move (in_path)), locus (locus) - {} - - VisType get_vis_type () const { return vis_type; } - - // Returns whether visibility is in an error state. - bool is_error () const - { - return vis_type == PUB_IN_PATH && in_path.is_empty (); - } - - // Returns whether a visibility has a path - bool has_path () const { return !is_error () && vis_type >= PUB_CRATE; } - - // Returns whether visibility is public or not. - bool is_public () const { return vis_type != PRIV && !is_error (); } - - location_t get_locus () const { return locus; } - - // empty? - // Creates an error visibility. - static Visibility create_error () - { - return Visibility (PUB_IN_PATH, SimplePath::create_empty (), - UNDEF_LOCATION); - } - - // Unique pointer custom clone function - /*std::unique_ptr clone_visibility() const { - return std::unique_ptr(clone_visibility_impl()); - }*/ - - /* TODO: think of a way to only allow valid Visibility states - polymorphism - * is one idea but may be too resource-intensive. */ - - // Creates a public visibility with no further features/arguments. - // empty? - static Visibility create_public (location_t pub_vis_location) - { - return Visibility (PUB, SimplePath::create_empty (), pub_vis_location); - } - - // Creates a public visibility with crate-relative paths - static Visibility create_crate (location_t crate_tok_location, - location_t crate_vis_location) - { - return Visibility (PUB_CRATE, - SimplePath::from_str ("crate", crate_tok_location), - crate_vis_location); - } - - // Creates a public visibility with self-relative paths - static Visibility create_self (location_t self_tok_location, - location_t self_vis_location) - { - return Visibility (PUB_SELF, - SimplePath::from_str ("self", self_tok_location), - self_vis_location); - } - - // Creates a public visibility with parent module-relative paths - static Visibility create_super (location_t super_tok_location, - location_t super_vis_location) - { - return Visibility (PUB_SUPER, - SimplePath::from_str ("super", super_tok_location), - super_vis_location); - } - - // Creates a private visibility - static Visibility create_private () - { - return Visibility (PRIV, SimplePath::create_empty (), UNDEF_LOCATION); - } - - // Creates a public visibility with a given path or whatever. - static Visibility create_in_path (SimplePath in_path, - location_t in_path_vis_location) - { - return Visibility (PUB_IN_PATH, std::move (in_path), in_path_vis_location); - } - - std::string as_string () const; - const SimplePath &get_path () const { return in_path; } - SimplePath &get_path () { return in_path; } - -protected: - // Clone function implementation - not currently virtual but may be if - // polymorphism used - /*virtual*/ Visibility *clone_visibility_impl () const - { - return new Visibility (*this); - } -}; // Item that supports visibility - abstract base class class VisItem : public Item { @@ -1649,13 +1650,20 @@ class TraitItem : virtual public AssociatedItem { protected: TraitItem (location_t locus) - : node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus) + : node_id (Analysis::Mappings::get ()->get_next_node_id ()), + vis (Visibility::create_private ()), locus (locus) + {} + + TraitItem (Visibility vis, location_t locus) + : node_id (Analysis::Mappings::get ()->get_next_node_id ()), vis (vis), + locus (locus) {} // Clone function implementation as pure virtual method virtual TraitItem *clone_associated_item_impl () const override = 0; NodeId node_id; + Visibility vis; location_t locus; public: diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 8b53bc6..2c0e459 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -3048,8 +3048,9 @@ public: TraitItemType (Identifier name, std::vector> type_param_bounds, - std::vector outer_attrs, location_t locus) - : TraitItem (locus), outer_attrs (std::move (outer_attrs)), + std::vector outer_attrs, Visibility vis, + location_t locus) + : TraitItem (vis, locus), outer_attrs (std::move (outer_attrs)), name (std::move (name)), type_param_bounds (std::move (type_param_bounds)) {} diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index fd648c53..0ae89dc 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -22,6 +22,7 @@ /* DO NOT INCLUDE ANYWHERE - this is automatically included with rust-parse.h * This is also the reason why there are no include guards. */ +#include "rust-item.h" #include "rust-token.h" #define INCLUDE_ALGORITHM #include "rust-diagnostics.h" @@ -5012,12 +5013,14 @@ Parser::parse_trait_item () // parse outer attributes (if they exist) AST::AttrVec outer_attrs = parse_outer_attributes (); + AST::Visibility vis = parse_visibility (); + // lookahead to determine what type of trait item to parse const_TokenPtr tok = lexer.peek_token (); switch (tok->get_id ()) { case TYPE: - return parse_trait_type (std::move (outer_attrs)); + return parse_trait_type (std::move (outer_attrs), vis); case CONST: // disambiguate with function qualifier if (lexer.peek_token (1)->get_id () == IDENTIFIER) @@ -5176,7 +5179,8 @@ Parser::parse_trait_item () // Parse a typedef trait item. template std::unique_ptr -Parser::parse_trait_type (AST::AttrVec outer_attrs) +Parser::parse_trait_type (AST::AttrVec outer_attrs, + AST::Visibility vis) { location_t locus = lexer.peek_token ()->get_locus (); skip_token (TYPE); @@ -5208,7 +5212,7 @@ Parser::parse_trait_type (AST::AttrVec outer_attrs) return std::unique_ptr ( new AST::TraitItemType (std::move (ident), std::move (bounds), - std::move (outer_attrs), locus)); + std::move (outer_attrs), vis, locus)); } // Parses a constant trait item. diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 9e924e0..08e6ce0 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -17,6 +17,7 @@ along with GCC; see the file COPYING3. If not see #ifndef RUST_PARSE_H #define RUST_PARSE_H +#include "rust-item.h" #include "rust-lex.h" #include "rust-ast-full.h" #include "rust-diagnostics.h" @@ -331,7 +332,7 @@ private: std::unique_ptr parse_trait (AST::Visibility vis, AST::AttrVec outer_attrs); std::unique_ptr - parse_trait_type (AST::AttrVec outer_attrs); + parse_trait_type (AST::AttrVec outer_attrs, AST::Visibility); std::unique_ptr parse_trait_const (AST::AttrVec outer_attrs); std::unique_ptr parse_self_param (); -- cgit v1.1 From bf47346052c22e067fe49070524bd0fb90c51628 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Thu, 2 Nov 2023 17:29:16 +0100 Subject: gccrs: Add a test to highlight public trait type parsing This new test highlight the parser's behavior around public trait types. gcc/testsuite/ChangeLog: * rust/compile/trait_pub_type.rs: New test. Signed-off-by: Pierre-Emmanuel Patry --- gcc/testsuite/rust/compile/trait_pub_type.rs | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 gcc/testsuite/rust/compile/trait_pub_type.rs diff --git a/gcc/testsuite/rust/compile/trait_pub_type.rs b/gcc/testsuite/rust/compile/trait_pub_type.rs new file mode 100644 index 0000000..85f6462 --- /dev/null +++ b/gcc/testsuite/rust/compile/trait_pub_type.rs @@ -0,0 +1,6 @@ +fn main() {} + +#[cfg(FALSE)] +trait T { + pub type X; +} -- cgit v1.1 From ca16a3ee232dac565cb18ea5e0b84c4ad54f727e Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Wed, 15 Nov 2023 11:08:09 +0100 Subject: gccrs: Fix error emission for self pointers Self pointer checking loop condition was inverted, the latter was therefore never executed. gcc/rust/ChangeLog: * parse/rust-parse-impl.h (Parser::parse_self_param): Fix the loop exit condition. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/parse/rust-parse-impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 0ae89dc..1ebe1ed 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -7129,7 +7129,7 @@ Parser::parse_self_param () for (auto &s : ptrs) { size_t i = 0; - for (i = 0; i > s.size (); i++) + for (i = 0; i < s.size (); i++) if (lexer.peek_token (i)->get_id () != s[i]) break; if (i == s.size ()) -- cgit v1.1 From 3e450ae1bb99d0111f6ca5f34ac8d6ea308c13d6 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Wed, 15 Nov 2023 13:02:28 +0100 Subject: gccrs: Report self parameter parsing error kind Self parameter parsing errors may come from different situations, which should not be handled in the same way. It is now possible to differentiate a missing self parameter from a self pointer or a parsing error. gcc/rust/ChangeLog: * parse/rust-parse-impl.h (Parser::parse_function): Early return on unrecoverable errors. (Parser::parse_trait_item): Likewise. (Parser::parse_self_param): Update return type. * parse/rust-parse.h (enum ParseSelfError): Add enumeration to describe different self parameter parsing errors. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/parse/rust-parse-impl.h | 72 +++++++++++++++++++++++++--------------- gcc/rust/parse/rust-parse.h | 12 ++++++- 2 files changed, 56 insertions(+), 28 deletions(-) diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 1ebe1ed..de17412 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -2880,8 +2880,13 @@ Parser::parse_function (AST::Visibility vis, return nullptr; } - std::unique_ptr initial_param = parse_self_param (); - if (initial_param != nullptr) + auto initial_param = parse_self_param (); + + if (!initial_param.has_value () + && initial_param.error () != ParseSelfError::NOT_SELF) + return nullptr; + + if (initial_param.has_value ()) skip_token (COMMA); // parse function parameters (only if next token isn't right paren) @@ -2891,9 +2896,9 @@ Parser::parse_function (AST::Visibility vis, function_params = parse_function_params ([] (TokenId id) { return id == RIGHT_PAREN; }); - if (initial_param != nullptr) + if (initial_param.has_value ()) function_params.insert (function_params.begin (), - std::move (initial_param)); + std::move (*initial_param)); if (!skip_token (RIGHT_PAREN)) { @@ -5063,13 +5068,15 @@ Parser::parse_trait_item () /* now for function vs method disambiguation - method has opening * "self" param */ - std::unique_ptr initial_param = parse_self_param (); + auto initial_param = parse_self_param (); + if (!initial_param.has_value () && initial_param.error () != NOT_SELF) + return nullptr; /* FIXME: ensure that self param doesn't accidently consume tokens for * a function */ bool is_method = false; - if (initial_param != nullptr) + if (initial_param.has_value ()) { - if (initial_param->is_self ()) + if ((*initial_param)->is_self ()) is_method = true; /* skip comma so function and method regular params can be parsed @@ -5089,9 +5096,9 @@ Parser::parse_trait_item () return nullptr; } - if (initial_param != nullptr) + if (initial_param.has_value ()) function_params.insert (function_params.begin (), - std::move (initial_param)); + std::move (*initial_param)); // parse return type (optional) std::unique_ptr return_type = parse_function_return_type (); @@ -5609,14 +5616,18 @@ Parser::parse_inherent_impl_function_or_method ( // now for function vs method disambiguation - method has opening "self" // param - std::unique_ptr initial_param = parse_self_param (); + auto initial_param = parse_self_param (); + + if (!initial_param.has_value () && initial_param.error () != NOT_SELF) + return nullptr; + /* FIXME: ensure that self param doesn't accidently consume tokens for a * function one idea is to lookahead up to 4 tokens to see whether self is * one of them */ bool is_method = false; - if (initial_param != nullptr) + if (initial_param.has_value ()) { - if (initial_param->is_self ()) + if ((*initial_param)->is_self ()) is_method = true; /* skip comma so function and method regular params can be parsed in @@ -5629,9 +5640,9 @@ Parser::parse_inherent_impl_function_or_method ( std::vector> function_params = parse_function_params ([] (TokenId id) { return id == RIGHT_PAREN; }); - if (initial_param != nullptr) + if (initial_param.has_value ()) function_params.insert (function_params.begin (), - std::move (initial_param)); + std::move (*initial_param)); if (!skip_token (RIGHT_PAREN)) { @@ -5817,13 +5828,17 @@ Parser::parse_trait_impl_function_or_method ( // now for function vs method disambiguation - method has opening "self" // param - std::unique_ptr initial_param = parse_self_param (); + auto initial_param = parse_self_param (); + + if (!initial_param.has_value () && initial_param.error () != NOT_SELF) + return nullptr; + // FIXME: ensure that self param doesn't accidently consume tokens for a // function bool is_method = false; - if (initial_param != nullptr) + if (initial_param.has_value ()) { - if (initial_param->is_self ()) + if ((*initial_param)->is_self ()) is_method = true; // skip comma so function and method regular params can be parsed in @@ -5861,9 +5876,9 @@ Parser::parse_trait_impl_function_or_method ( } } - if (initial_param != nullptr) + if (initial_param.has_value ()) function_params.insert (function_params.begin (), - std::move (initial_param)); + std::move (*initial_param)); // DEBUG rust_debug ("successfully parsed function params in function or method " @@ -7112,7 +7127,7 @@ Parser::parse_qualified_path_in_type () // Parses a self param. Also handles self param not existing. template -std::unique_ptr +tl::expected, ParseSelfError> Parser::parse_self_param () { bool has_reference = false; @@ -7133,8 +7148,11 @@ Parser::parse_self_param () if (lexer.peek_token (i)->get_id () != s[i]) break; if (i == s.size ()) - rust_error_at (lexer.peek_token ()->get_locus (), - "cannot pass % by raw pointer"); + { + rust_error_at (lexer.peek_token ()->get_locus (), + "cannot pass % by raw pointer"); + return tl::make_unexpected (ParseSelfError::SELF_PTR); + } } // Trying to find those patterns: @@ -7154,7 +7172,7 @@ Parser::parse_self_param () is_self = true; if (!is_self) - return nullptr; + return tl::make_unexpected (ParseSelfError::NOT_SELF); // test if self is a reference parameter if (lexer.peek_token ()->get_id () == AMP) @@ -7175,7 +7193,7 @@ Parser::parse_self_param () add_error (std::move (error)); // skip after somewhere? - return nullptr; + return tl::make_unexpected (ParseSelfError::PARSING); } } } @@ -7193,7 +7211,7 @@ Parser::parse_self_param () if (self_tok->get_id () != SELF) { // skip after somewhere? - return nullptr; + return tl::make_unexpected (ParseSelfError::NOT_SELF); } lexer.skip_token (); @@ -7212,7 +7230,7 @@ Parser::parse_self_param () add_error (std::move (error)); // skip after somewhere? - return nullptr; + return tl::make_unexpected (ParseSelfError::PARSING); } } @@ -7225,7 +7243,7 @@ Parser::parse_self_param () add_error (std::move (error)); // skip after somewhere? - return nullptr; + return tl::make_unexpected (ParseSelfError::PARSING); } if (has_reference) diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 08e6ce0..e873d52 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -22,6 +22,8 @@ along with GCC; see the file COPYING3. If not see #include "rust-ast-full.h" #include "rust-diagnostics.h" +#include "expected.h" + namespace Rust { /* HACK: used to resolve the expression-or-statement problem at the end of a * block by allowing either to be returned (technically). Tagged union would @@ -93,6 +95,12 @@ struct ParseRestrictions bool allow_close_after_expr_stmt = false; }; +enum ParseSelfError +{ + SELF_PTR, + PARSING, + NOT_SELF, +}; // Parser implementation for gccrs. // TODO: if updated to C++20, ManagedTokenSource would be useful as a concept template class Parser @@ -335,7 +343,9 @@ private: parse_trait_type (AST::AttrVec outer_attrs, AST::Visibility); std::unique_ptr parse_trait_const (AST::AttrVec outer_attrs); - std::unique_ptr parse_self_param (); + + tl::expected, ParseSelfError> parse_self_param (); + std::unique_ptr parse_impl (AST::Visibility vis, AST::AttrVec outer_attrs); std::unique_ptr -- cgit v1.1 From 08999fb0354ee94e5902fd43bd8c43d9b9b3c74a Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Wed, 15 Nov 2023 13:53:23 +0100 Subject: gccrs: Add new test for parsing errors on self pointers Add new tests to highlight the behavior of errors thrown when meeting a self pointer. gcc/testsuite/ChangeLog: * rust/compile/self_const_ptr.rs: New test. * rust/compile/self_mut_ptr.rs: New test. * rust/compile/self_ptr.rs: New test. Signed-off-by: Pierre-Emmanuel Patry --- gcc/testsuite/rust/compile/self_const_ptr.rs | 8 ++++++++ gcc/testsuite/rust/compile/self_mut_ptr.rs | 8 ++++++++ gcc/testsuite/rust/compile/self_ptr.rs | 8 ++++++++ 3 files changed, 24 insertions(+) create mode 100644 gcc/testsuite/rust/compile/self_const_ptr.rs create mode 100644 gcc/testsuite/rust/compile/self_mut_ptr.rs create mode 100644 gcc/testsuite/rust/compile/self_ptr.rs diff --git a/gcc/testsuite/rust/compile/self_const_ptr.rs b/gcc/testsuite/rust/compile/self_const_ptr.rs new file mode 100644 index 0000000..014fe1b --- /dev/null +++ b/gcc/testsuite/rust/compile/self_const_ptr.rs @@ -0,0 +1,8 @@ +struct MyStruct; + +impl MyStruct { + pub fn do_something(*const self) {} + // { dg-error "cannot pass .self. by raw pointer" "" { target *-*-* } .-1 } + // { dg-error "failed to parse inherent impl item in inherent impl" "" { target *-*-* } .-2 } + // { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 } +} diff --git a/gcc/testsuite/rust/compile/self_mut_ptr.rs b/gcc/testsuite/rust/compile/self_mut_ptr.rs new file mode 100644 index 0000000..2a127b7 --- /dev/null +++ b/gcc/testsuite/rust/compile/self_mut_ptr.rs @@ -0,0 +1,8 @@ +struct MyStruct; + +impl MyStruct { + pub fn do_something(*mut self) {} + // { dg-error "cannot pass .self. by raw pointer" "" { target *-*-* } .-1 } + // { dg-error "failed to parse inherent impl item in inherent impl" "" { target *-*-* } .-2 } + // { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 } +} diff --git a/gcc/testsuite/rust/compile/self_ptr.rs b/gcc/testsuite/rust/compile/self_ptr.rs new file mode 100644 index 0000000..fd7ff6c --- /dev/null +++ b/gcc/testsuite/rust/compile/self_ptr.rs @@ -0,0 +1,8 @@ +struct MyStruct; + +impl MyStruct { + pub fn do_something(*self) {} + // { dg-error "cannot pass .self. by raw pointer" "" { target *-*-* } .-1 } + // { dg-error "failed to parse inherent impl item in inherent impl" "" { target *-*-* } .-2 } + // { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 } +} -- cgit v1.1 From c5925f349231155e48fa649f47b3c699ef4ba3b0 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 17 Aug 2023 14:05:49 +0200 Subject: gccrs: ast: Change *Path nodes API gcc/rust/ChangeLog: * ast/rust-ast.h: Change Path API to be more consistent. * ast/rust-path.h: Likewise. * ast/rust-ast-collector.cc (TokenCollector::visit): Use new API. * resolve/rust-ast-resolve-item.cc (ResolveItem::visit): Likewise. * resolve/rust-ast-resolve-path.cc (ResolvePath::resolve_path): Likewise. * resolve/rust-forever-stack.hxx: Likewise. --- gcc/rust/ast/rust-ast-collector.cc | 2 +- gcc/rust/ast/rust-ast.h | 2 +- gcc/rust/ast/rust-path.h | 9 +++++++++ gcc/rust/resolve/rust-ast-resolve-item.cc | 2 +- gcc/rust/resolve/rust-ast-resolve-path.cc | 2 +- gcc/rust/resolve/rust-forever-stack.hxx | 7 ++++--- 6 files changed, 17 insertions(+), 7 deletions(-) diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index cb8dfd8..7d3d3e2 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -191,7 +191,7 @@ TokenCollector::visit (SimplePathSegment &segment) { push (Rust::Token::make (SUPER, segment.get_locus ())); } - else if (segment.is_lower_self ()) + else if (segment.is_lower_self_seg ()) { push (Rust::Token::make (SELF, segment.get_locus ())); } diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 4dc7f97..47c02d6 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -399,7 +399,7 @@ public: { return as_string ().compare ("crate") == 0; } - bool is_lower_self () const { return as_string ().compare ("self") == 0; } + bool is_lower_self_seg () const { return as_string ().compare ("self") == 0; } bool is_big_self () const { return as_string ().compare ("Self") == 0; } }; diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index b76664f..ccac630 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -536,6 +536,7 @@ public: { return !has_generic_args () && get_ident_segment ().is_crate_segment (); } + bool is_lower_self_seg () const { return !has_generic_args () && get_ident_segment ().is_lower_self (); @@ -646,6 +647,14 @@ public: outer_attrs = std::move (new_attrs); } + NodeId get_pattern_node_id () const { return get_node_id (); } + + PathExprSegment &get_final_segment () { return get_segments ().back (); } + const PathExprSegment &get_final_segment () const + { + return get_segments ().back (); + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc index 1fc6b92..eaee5bc 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.cc +++ b/gcc/rust/resolve/rust-ast-resolve-item.cc @@ -1031,7 +1031,7 @@ ResolveItem::visit (AST::UseDeclaration &use_item) if (!ok) continue; - const AST::SimplePathSegment &final_seg = path.get_final_segment (); + const AST::SimplePathSegment &final_seg = path.get_segments ().back (); auto decl = CanonicalPath::new_seg (resolved_node_id, final_seg.as_string ()); diff --git a/gcc/rust/resolve/rust-ast-resolve-path.cc b/gcc/rust/resolve/rust-ast-resolve-path.cc index fd2a844..9e982d0 100644 --- a/gcc/rust/resolve/rust-ast-resolve-path.cc +++ b/gcc/rust/resolve/rust-ast-resolve-path.cc @@ -367,7 +367,7 @@ ResolvePath::resolve_path (AST::SimplePath *expr) // is_first_segment ? "true" : "false", // is_final_segment ? "true" : "false"); if (resolved_node_id == UNKNOWN_NODEID && !is_first_segment - && is_final_segment && segment.is_lower_self ()) + && is_final_segment && segment.is_lower_self_seg ()) { resolved_node_id = previous_resolved_node_id; } diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index 8bdda67..5acdf06 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -313,7 +313,8 @@ ForeverStack::find_starting_point ( for (; !is_last (iterator, segments); iterator++) { auto seg = *iterator; - auto is_self_or_crate = seg.is_crate_path_seg () || seg.is_lower_self (); + auto is_self_or_crate + = seg.is_crate_path_seg () || seg.is_lower_self_seg (); // if we're after the first path segment and meet `self` or `crate`, it's // an error - we should only be seeing `super` keywords at this point @@ -327,7 +328,7 @@ ForeverStack::find_starting_point ( iterator++; break; } - if (seg.is_lower_self ()) + if (seg.is_lower_self_seg ()) { // do nothing and exit iterator++; @@ -371,7 +372,7 @@ ForeverStack::resolve_segments ( // check that we don't encounter *any* leading keywords afterwards if (check_leading_kw_at_start (seg, seg.is_crate_path_seg () || seg.is_super_path_seg () - || seg.is_lower_self ())) + || seg.is_lower_self_seg ())) return tl::nullopt; tl::optional::Node &> child = tl::nullopt; -- cgit v1.1 From f7d8356a6ea2952574487596e66185a96a7f5d58 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 17 Aug 2023 14:06:50 +0200 Subject: gccrs: rib: Add Namespace enum gcc/rust/ChangeLog: * resolve/rust-rib.h: Add Namespace enum. --- gcc/rust/resolve/rust-rib.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/gcc/rust/resolve/rust-rib.h b/gcc/rust/resolve/rust-rib.h index 37bd90f..4ffd00a 100644 --- a/gcc/rust/resolve/rust-rib.h +++ b/gcc/rust/resolve/rust-rib.h @@ -28,6 +28,31 @@ namespace Rust { namespace Resolver2_0 { /** + +pub enum Namespace { + /// The type namespace includes `struct`s, `enum`s, `union`s, `trait`s, and +`mod`s + /// (and, by extension, crates). + /// + /// Note that the type namespace includes other items; this is not an + /// exhaustive list. + TypeNS, + /// The value namespace includes `fn`s, `const`s, `static`s, and local +variables (including function arguments). ValueNS, + /// The macro namespace includes `macro_rules!` macros, declarative `macro`s, + /// procedural macros, attribute macros, `derive` macros, and non-macro +attributes + /// like `#[inline]` and `#[rustfmt::skip]`. + MacroNS, +} + +*/ + +// FIXME: There's no `labels` namespace, not sure if we need one or how to keep +// one +// FIXME: And where are things like loop labels kept? + +/** * All namespaces that Rust's name resolution needs to handle */ // TODO: Move to `rust-forever-stack.h`? -- cgit v1.1 From 446ab9b265554b8e20ff386466f119fcf9e11093 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Mon, 21 Aug 2023 15:52:06 +0200 Subject: gccrs: forever-stack: Fix basic get logic gcc/rust/ChangeLog: * resolve/rust-forever-stack.h: Improve resolve_path API. * resolve/rust-forever-stack.hxx: Likewise and fix implementation. --- gcc/rust/resolve/rust-forever-stack.h | 19 +++++++++-------- gcc/rust/resolve/rust-forever-stack.hxx | 38 ++++++++++++++++----------------- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h index 7ee0849..349d097 100644 --- a/gcc/rust/resolve/rust-forever-stack.h +++ b/gcc/rust/resolve/rust-forever-stack.h @@ -473,7 +473,7 @@ public: * @return a valid option with the NodeId if the path is present in the * current map, an empty one otherwise. */ - tl::optional resolve_path (const AST::SimplePath &path); + template tl::optional resolve_path (const P &path); std::string as_debug_string (); @@ -550,18 +550,19 @@ private: /* Helper types and functions for `resolve_path` */ - using SegIterator = std::vector::const_iterator; + template + using SegIterator = typename std::vector::const_iterator; Node &find_closest_module (Node &starting_point); - tl::optional - find_starting_point (const std::vector &segments, - Node &starting_point); + template + tl::optional> + find_starting_point (const std::vector &segments, Node &starting_point); - tl::optional - resolve_segments (Node &starting_point, - const std::vector &segments, - SegIterator iterator); + template + tl::optional resolve_segments (Node &starting_point, + const std::vector &segments, + SegIterator iterator); }; } // namespace Resolver2_0 diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index 5acdf06..806745e 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -208,15 +208,8 @@ ForeverStack::update_cursor (Node &new_cursor) } template -tl::optional -ForeverStack::get (const Identifier &name) -{ - return tl::nullopt; -} - -template <> inline tl::optional -ForeverStack::get (const Identifier &name) +ForeverStack::get (const Identifier &name) { tl::optional resolved_node = tl::nullopt; @@ -226,9 +219,9 @@ ForeverStack::get (const Identifier &name) return candidate.map_or ( [&resolved_node] (NodeId found) { - // macro resolving does not need to care about various ribs - they are - // available from all contexts if defined in the current scope, or an - // outermore one. so if we do have a candidate, we can return it + // for most namespaces, we do not need to care about various ribs - they + // are available from all contexts if defined in the current scope, or + // an outermore one. so if we do have a candidate, we can return it // directly and stop iterating resolved_node = found; @@ -278,9 +271,9 @@ ForeverStack::find_closest_module (Node &starting_point) /* If a the given condition is met, emit an error about misused leading path * segments */ +template static inline bool -check_leading_kw_at_start (const AST::SimplePathSegment &segment, - bool condition) +check_leading_kw_at_start (const S &segment, bool condition) { if (condition) rust_error_at ( @@ -297,9 +290,10 @@ check_leading_kw_at_start (const AST::SimplePathSegment &segment, // `super` segment, we go back to the cursor's parent until we reach the // correct one or the root. template -tl::optional::const_iterator> -ForeverStack::find_starting_point ( - const std::vector &segments, Node &starting_point) +template +tl::optional::const_iterator> +ForeverStack::find_starting_point (const std::vector &segments, + Node &starting_point) { auto iterator = segments.begin (); @@ -357,10 +351,11 @@ ForeverStack::find_starting_point ( } template +template tl::optional::Node &> ForeverStack::resolve_segments ( - Node &starting_point, const std::vector &segments, - std::vector::const_iterator iterator) + Node &starting_point, const std::vector &segments, + typename std::vector::const_iterator iterator) { auto *current_node = &starting_point; for (; !is_last (iterator, segments); iterator++) @@ -407,9 +402,14 @@ ForeverStack::resolve_segments ( } template +template tl::optional -ForeverStack::resolve_path (const AST::SimplePath &path) +ForeverStack::resolve_path (const P &path) { + // if there's only one segment, we just use `get` + if (path.get_segments ().size () == 1) + return get (path.get_final_segment ().as_string ()); + auto starting_point = cursor (); auto &segments = path.get_segments (); -- cgit v1.1 From eec00ae27522438d6021c01501489cada87812dc Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Mon, 21 Aug 2023 16:05:22 +0200 Subject: gccrs: foreverstack: Specialize `get` for Namespace::Labels gcc/rust/ChangeLog: * resolve/rust-forever-stack.hxx: Add specific behavior for `ForeverStack::get` when dealing with labels. --- gcc/rust/resolve/rust-forever-stack.hxx | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index 806745e..211979f 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -208,7 +208,7 @@ ForeverStack::update_cursor (Node &new_cursor) } template -inline tl::optional +tl::optional ForeverStack::get (const Identifier &name) { tl::optional resolved_node = tl::nullopt; @@ -234,6 +234,33 @@ ForeverStack::get (const Identifier &name) return resolved_node; } +template <> +tl::optional inline ForeverStack::get ( + const Identifier &name) +{ + tl::optional resolved_node = tl::nullopt; + + reverse_iter ([&resolved_node, &name] (Node ¤t) { + // looking up for labels cannot go through function ribs + // TODO: What other ribs? + if (current.rib.kind == Rib::Kind::Function) + return KeepGoing::No; + + auto candidate = current.rib.get (name.as_string ()); + + // FIXME: Factor this in a function with the generic `get` + return candidate.map_or ( + [&resolved_node] (NodeId found) { + resolved_node = found; + + return KeepGoing::No; + }, + KeepGoing::Yes); + }); + + return resolved_node; +} + /* Check if an iterator points to the last element */ template static bool -- cgit v1.1 From 5fd3de11508e7205e39b5fe00d8b4fd4789aeb86 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 21 Sep 2023 15:55:03 +0200 Subject: gccrs: forever stack: Fix resolve_path signature gcc/rust/ChangeLog: * resolve/rust-forever-stack.h: Fix `ForeverStack::resolve_path` signature. * resolve/rust-forever-stack.hxx: Likewise. * resolve/rust-early-name-resolver-2.0.cc (Early::visit): Use new API. (Early::visit_attributes): Likewise. --- gcc/rust/resolve/rust-early-name-resolver-2.0.cc | 8 +++++--- gcc/rust/resolve/rust-forever-stack.h | 5 ++++- gcc/rust/resolve/rust-forever-stack.hxx | 17 +++++++++-------- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc index 57a3807..2245ba3 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc @@ -131,7 +131,7 @@ Early::visit (AST::MacroInvocation &invoc) // we won't have changed `definition` from `nullopt` if there are more // than one segments in our path if (!definition.has_value ()) - definition = ctx.macros.resolve_path (path); + definition = ctx.macros.resolve_path (path.get_segments ()); // if the definition still does not have a value, then it's an error if (!definition.has_value ()) @@ -188,7 +188,8 @@ Early::visit_attributes (std::vector &attrs) auto traits = attr.get_traits_to_derive (); for (auto &trait : traits) { - auto definition = ctx.macros.resolve_path (trait.get ()); + auto definition + = ctx.macros.resolve_path (trait.get ().get_segments ()); if (!definition.has_value ()) { // FIXME: Change to proper error message @@ -210,7 +211,8 @@ Early::visit_attributes (std::vector &attrs) ->lookup_builtin (name) .is_error ()) // Do not resolve builtins { - auto definition = ctx.macros.resolve_path (attr.get_path ()); + auto definition + = ctx.macros.resolve_path (attr.get_path ().get_segments ()); if (!definition.has_value ()) { // FIXME: Change to proper error message diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h index 349d097..ec469a9 100644 --- a/gcc/rust/resolve/rust-forever-stack.h +++ b/gcc/rust/resolve/rust-forever-stack.h @@ -470,10 +470,13 @@ public: /** * Resolve a path to its definition in the current `ForeverStack` * + * // TODO: Add documentation for `segments` + * * @return a valid option with the NodeId if the path is present in the * current map, an empty one otherwise. */ - template tl::optional resolve_path (const P &path); + template + tl::optional resolve_path (const std::vector &segments); std::string as_debug_string (); diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index 211979f..8f0ab66 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -429,24 +429,25 @@ ForeverStack::resolve_segments ( } template -template +template tl::optional -ForeverStack::resolve_path (const P &path) +ForeverStack::resolve_path (const std::vector &segments) { + // TODO: What to do if segments.empty() ? + // if there's only one segment, we just use `get` - if (path.get_segments ().size () == 1) - return get (path.get_final_segment ().as_string ()); + if (segments.size () == 1) + return get (segments.back ().as_string ()); auto starting_point = cursor (); - auto &segments = path.get_segments (); return find_starting_point (segments, starting_point) .and_then ([this, &segments, &starting_point] ( - std::vector::const_iterator iterator) { + typename std::vector::const_iterator iterator) { return resolve_segments (starting_point, segments, iterator); }) - .and_then ([&path] (Node final_node) { - return final_node.rib.get (path.get_final_segment ().as_string ()); + .and_then ([&segments] (Node final_node) { + return final_node.rib.get (segments.back ().as_string ()); }); } -- cgit v1.1 From 66e8a1614e4cc9d3eb92f1288cf19a805b21ac1a Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Wed, 23 Aug 2023 13:50:16 +0200 Subject: gccrs: forever stack: Improve resolve_path implementation gcc/rust/ChangeLog: * resolve/rust-forever-stack.hxx: Do not copy segment when dereferencing iterator in `find_starting_point`. --- gcc/rust/resolve/rust-forever-stack.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index 8f0ab66..642135c 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -333,7 +333,7 @@ ForeverStack::find_starting_point (const std::vector &segments, for (; !is_last (iterator, segments); iterator++) { - auto seg = *iterator; + auto &seg = *iterator; auto is_self_or_crate = seg.is_crate_path_seg () || seg.is_lower_self_seg (); -- cgit v1.1 From 12b2dcb088104c0682f501d0c87ba0b640bbb86b Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 25 Aug 2023 13:40:44 +0200 Subject: gccrs: foreverstack: Add `to_canonical_path` method gcc/rust/ChangeLog: * resolve/rust-forever-stack.h: New method. * resolve/rust-forever-stack.hxx: Likewise. --- gcc/rust/resolve/rust-forever-stack.h | 25 +++++++-- gcc/rust/resolve/rust-forever-stack.hxx | 90 ++++++++++++++++++++++++++++++++- 2 files changed, 110 insertions(+), 5 deletions(-) diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h index ec469a9..37277dd 100644 --- a/gcc/rust/resolve/rust-forever-stack.h +++ b/gcc/rust/resolve/rust-forever-stack.h @@ -396,7 +396,10 @@ template class ForeverStack { public: ForeverStack () - : root (Node (Rib (Rib::Kind::Normal))), cursor_reference (root) + // FIXME: Is that valid? Do we use the root? If yes, we should give the + // crate's node id to ForeverStack's constructor + : root (Node (Rib (Rib::Kind::Normal), UNKNOWN_NODEID)), + cursor_reference (root) { rust_assert (root.is_root ()); rust_assert (root.is_leaf ()); @@ -478,6 +481,12 @@ public: template tl::optional resolve_path (const std::vector &segments); + // FIXME: Documentation + tl::optional to_canonical_path (NodeId id); + + // FIXME: Documentation + tl::optional to_rib (NodeId rib_id); + std::string as_debug_string (); private: @@ -509,8 +518,10 @@ private: class Node { public: - Node (Rib rib) : rib (rib) {} - Node (Rib rib, Node &parent) : rib (rib), parent (parent) {} + Node (Rib rib, NodeId id) : rib (rib), id (id) {} + Node (Rib rib, NodeId id, Node &parent) + : rib (rib), id (id), parent (parent) + {} bool is_root () const; bool is_leaf () const; @@ -520,6 +531,8 @@ private: Rib rib; // this is the "value" of the node - the data it keeps. std::map children; // all the other nodes it links to + NodeId id; // The node id of the Node's scope + tl::optional parent; // `None` only if the node is a root }; @@ -566,6 +579,12 @@ private: tl::optional resolve_segments (Node &starting_point, const std::vector &segments, SegIterator iterator); + + /* Helper functions for forward resolution (to_canonical_path, to_rib...) */ + + // FIXME: Documentation + tl::optional> dfs (Node &starting_point, + NodeId to_find); }; } // namespace Resolver2_0 diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index 642135c..4e06da235 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -66,8 +66,8 @@ ForeverStack::push_inner (Rib rib, Link link) // the iterator and a boolean. If the value already exists, the iterator // points to it. Otherwise, it points to the newly emplaced value, so we can // just update our cursor(). - auto emplace - = cursor ().children.emplace (std::make_pair (link, Node (rib, cursor ()))); + auto emplace = cursor ().children.emplace ( + std::make_pair (link, Node (rib, link.id, cursor ()))); auto it = emplace.first; auto existed = !emplace.second; @@ -452,6 +452,92 @@ ForeverStack::resolve_path (const std::vector &segments) } template +tl::optional::Node &, std::string>> +ForeverStack::dfs (ForeverStack::Node &starting_point, NodeId to_find) +{ + auto &values = starting_point.rib.get_values (); + + for (auto &kv : values) + if (kv.second == to_find) + return {{starting_point, kv.first}}; + + for (auto &child : starting_point.children) + { + auto candidate = dfs (child.second, to_find); + + if (candidate.has_value ()) + return candidate; + } + + return tl::nullopt; +} + +template +tl::optional +ForeverStack::to_canonical_path (NodeId id) +{ + // find the id in the current forever stack, starting from the root, + // performing either a BFS or DFS once the Node containing the ID is found, go + // back up to the root (parent().parent().parent()...) accumulate link + // segments reverse them that's your canonical path + + return dfs (root, id).map ([this, id] (std::pair tuple) { + auto containing_node = tuple.first; + auto name = tuple.second; + + auto segments = std::vector (); + + reverse_iter (containing_node, [&segments] (Node ¤t) { + if (current.is_root ()) + return KeepGoing::No; + + auto children = current.parent.value ().children; + const Link *outer_link = nullptr; + + for (auto &kv : children) + { + auto &link = kv.first; + auto &child = kv.second; + + if (link.id == child.id) + { + outer_link = &link; + break; + } + } + + rust_assert (outer_link); + + outer_link->path.map ([&segments, outer_link] (Identifier path) { + segments.emplace (segments.begin (), + Resolver::CanonicalPath::new_seg (outer_link->id, + path.as_string ())); + }); + + return KeepGoing::Yes; + }); + + auto path = Resolver::CanonicalPath::create_empty (); + for (const auto &segment : segments) + path = path.append (segment); + + // Finally, append the name + path = path.append (Resolver::CanonicalPath::new_seg (id, name)); + rust_debug ("[ARTHUR] found path: %s. Size: %lu", path.get ().c_str (), + segments.size ()); + + return path; + }); +} + +template +tl::optional +ForeverStack::to_rib (NodeId rib_id) +{ + return tl::nullopt; +} + +template void ForeverStack::stream_rib (std::stringstream &stream, const Rib &rib, const std::string &next, -- cgit v1.1 From 232f94af30dc99f7618c8d7c83c0224a5750f203 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 25 Aug 2023 14:19:31 +0200 Subject: gccrs: foreverstack: Add `to_rib` method gcc/rust/ChangeLog: * resolve/rust-forever-stack.h: New method. * resolve/rust-forever-stack.hxx: Likewise. --- gcc/rust/resolve/rust-forever-stack.h | 2 ++ gcc/rust/resolve/rust-forever-stack.hxx | 20 +++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h index 37277dd..a540e68 100644 --- a/gcc/rust/resolve/rust-forever-stack.h +++ b/gcc/rust/resolve/rust-forever-stack.h @@ -585,6 +585,8 @@ private: // FIXME: Documentation tl::optional> dfs (Node &starting_point, NodeId to_find); + // FIXME: Documentation + tl::optional dfs_rib (Node &starting_point, NodeId to_find); }; } // namespace Resolver2_0 diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index 4e06da235..6579617 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -532,12 +532,30 @@ ForeverStack::to_canonical_path (NodeId id) template tl::optional -ForeverStack::to_rib (NodeId rib_id) +ForeverStack::dfs_rib (ForeverStack::Node &starting_point, NodeId to_find) { + if (starting_point.id == to_find) + return starting_point.rib; + + for (auto &child : starting_point.children) + { + auto candidate = dfs_rib (child.second, to_find); + + if (candidate.has_value ()) + return candidate; + } + return tl::nullopt; } template +tl::optional +ForeverStack::to_rib (NodeId rib_id) +{ + return dfs_rib (root, rib_id); +} + +template void ForeverStack::stream_rib (std::stringstream &stream, const Rib &rib, const std::string &next, -- cgit v1.1 From cbd0a9ce03ce3068ccdb1a515962817e242dae46 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 21 Nov 2023 11:13:59 +0100 Subject: gccrs: resolve: Format if properly gcc/rust/ChangeLog: * resolve/rust-ast-resolve-path.cc (ResolvePath::resolve_path): Format. --- gcc/rust/resolve/rust-ast-resolve-path.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/gcc/rust/resolve/rust-ast-resolve-path.cc b/gcc/rust/resolve/rust-ast-resolve-path.cc index 9e982d0..56c352e 100644 --- a/gcc/rust/resolve/rust-ast-resolve-path.cc +++ b/gcc/rust/resolve/rust-ast-resolve-path.cc @@ -368,9 +368,7 @@ ResolvePath::resolve_path (AST::SimplePath *expr) // is_final_segment ? "true" : "false"); if (resolved_node_id == UNKNOWN_NODEID && !is_first_segment && is_final_segment && segment.is_lower_self_seg ()) - { - resolved_node_id = previous_resolved_node_id; - } + resolved_node_id = previous_resolved_node_id; // final check if (resolved_node_id == UNKNOWN_NODEID) -- cgit v1.1 From 478ac287e75da1a3dffda6595051850a1c929f3c Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 21 Nov 2023 11:14:12 +0100 Subject: gccrs: forever stack: Remove development debug info gcc/rust/ChangeLog: * resolve/rust-forever-stack.hxx: Remove debug log. --- gcc/rust/resolve/rust-forever-stack.hxx | 2 -- 1 file changed, 2 deletions(-) diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index 6579617..867144a 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -523,8 +523,6 @@ ForeverStack::to_canonical_path (NodeId id) // Finally, append the name path = path.append (Resolver::CanonicalPath::new_seg (id, name)); - rust_debug ("[ARTHUR] found path: %s. Size: %lu", path.get ().c_str (), - segments.size ()); return path; }); -- cgit v1.1 From b1b744fc467a3cee4af0f85a8d8fb2b68f68b2d3 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Mon, 20 Nov 2023 13:43:48 +0100 Subject: gccrs: Reject auto traits with generic parameters Generic parameters are not allowed on auto traits, the compiler should emit an error. gcc/rust/ChangeLog: * checks/errors/rust-ast-validation.cc (ASTValidation::visit): Add check for generics on auto traits. * checks/errors/rust-ast-validation.h: Add visit function prototype. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/checks/errors/rust-ast-validation.cc | 14 ++++++++++++++ gcc/rust/checks/errors/rust-ast-validation.h | 1 + 2 files changed, 15 insertions(+) diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc index f6ce45e..37d3668 100644 --- a/gcc/rust/checks/errors/rust-ast-validation.cc +++ b/gcc/rust/checks/errors/rust-ast-validation.cc @@ -96,4 +96,18 @@ ASTValidation::visit (AST::Function &function) AST::ContextualASTVisitor::visit (function); } +void +ASTValidation::visit (AST::Trait &trait) +{ + if (trait.is_auto ()) + { + if (trait.has_generics ()) + rust_error_at (trait.get_generic_params ()[0]->get_locus (), + ErrorCode::E0567, + "auto traits cannot have generic parameters"); + } + + AST::ContextualASTVisitor::visit (trait); +} + } // namespace Rust diff --git a/gcc/rust/checks/errors/rust-ast-validation.h b/gcc/rust/checks/errors/rust-ast-validation.h index 44995eb..49133ee 100644 --- a/gcc/rust/checks/errors/rust-ast-validation.h +++ b/gcc/rust/checks/errors/rust-ast-validation.h @@ -38,6 +38,7 @@ public: virtual void visit (AST::LoopLabel &label); virtual void visit (AST::ExternalFunctionItem &item); virtual void visit (AST::Function &function); + virtual void visit (AST::Trait &trait); }; } // namespace Rust -- cgit v1.1 From 3e0e74f3e9cee9db52ef40ccacc4bc667a569455 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Mon, 20 Nov 2023 13:53:51 +0100 Subject: gccrs: Add regression test for generic auto traits Generics are forbidden on auto traits and an error should be emitted. This commit highlight this behavior. gcc/testsuite/ChangeLog: * rust/compile/generic_auto_trait.rs: New test. Signed-off-by: Pierre-Emmanuel Patry --- gcc/testsuite/rust/compile/generic_auto_trait.rs | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 gcc/testsuite/rust/compile/generic_auto_trait.rs diff --git a/gcc/testsuite/rust/compile/generic_auto_trait.rs b/gcc/testsuite/rust/compile/generic_auto_trait.rs new file mode 100644 index 0000000..ae6a51d --- /dev/null +++ b/gcc/testsuite/rust/compile/generic_auto_trait.rs @@ -0,0 +1,2 @@ +auto trait IsCooler {} +// { dg-error "auto traits cannot have generic parameters .E0567." "" { target *-*-* } .-1 } -- cgit v1.1 From d8c1a756c426c2aba1ef0662cf49bb2760edbb3c Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Mon, 20 Nov 2023 14:04:35 +0100 Subject: gccrs: Reject auto traits with super trait Reject auto traits containing a super trait bound during AST validation pass. gcc/rust/ChangeLog: * checks/errors/rust-ast-validation.cc (ASTValidation::visit): Reject auto traits with super traits. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/checks/errors/rust-ast-validation.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc index 37d3668..aeae603 100644 --- a/gcc/rust/checks/errors/rust-ast-validation.cc +++ b/gcc/rust/checks/errors/rust-ast-validation.cc @@ -105,6 +105,10 @@ ASTValidation::visit (AST::Trait &trait) rust_error_at (trait.get_generic_params ()[0]->get_locus (), ErrorCode::E0567, "auto traits cannot have generic parameters"); + if (trait.has_type_param_bounds ()) + rust_error_at (trait.get_type_param_bounds ()[0]->get_locus (), + ErrorCode::E0568, + "auto traits cannot have super traits"); } AST::ContextualASTVisitor::visit (trait); -- cgit v1.1 From 84e06bb631424cba3ee47f522c9629b104019ec9 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Mon, 20 Nov 2023 14:16:41 +0100 Subject: gccrs: Add a regression test for super trait on auto trait Add a new regression test to highlight the error behavior with a super trait on an auto trait. gcc/testsuite/ChangeLog: * rust/compile/auto_trait_super_trait.rs: New test. Signed-off-by: Pierre-Emmanuel Patry --- gcc/testsuite/rust/compile/auto_trait_super_trait.rs | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 gcc/testsuite/rust/compile/auto_trait_super_trait.rs diff --git a/gcc/testsuite/rust/compile/auto_trait_super_trait.rs b/gcc/testsuite/rust/compile/auto_trait_super_trait.rs new file mode 100644 index 0000000..1080afb --- /dev/null +++ b/gcc/testsuite/rust/compile/auto_trait_super_trait.rs @@ -0,0 +1,4 @@ +trait Cold {} + +auto trait IsCool: Cold {} +// { dg-error "auto traits cannot have super traits .E0568." "" { target *-*-* } .-1 } -- cgit v1.1 From 685491f232459f6182899893a7326582e153f11e Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Mon, 20 Nov 2023 14:59:56 +0100 Subject: gccrs: Add check for associated items on auto traits Reject rust code with associated items on auto traits. gcc/rust/ChangeLog: * checks/errors/rust-ast-validation.cc (ASTValidation::visit): Add auto trait associated item check in AST validation pass. * parse/rust-parse-impl.h: Remove old error emission done during parsing pass. gcc/testsuite/ChangeLog: * rust/compile/auto_trait_invalid.rs: Update old test with updated error message. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/checks/errors/rust-ast-validation.cc | 7 +++++++ gcc/rust/parse/rust-parse-impl.h | 12 ------------ gcc/testsuite/rust/compile/auto_trait_invalid.rs | 5 +++-- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc index aeae603..6732909 100644 --- a/gcc/rust/checks/errors/rust-ast-validation.cc +++ b/gcc/rust/checks/errors/rust-ast-validation.cc @@ -109,6 +109,13 @@ ASTValidation::visit (AST::Trait &trait) rust_error_at (trait.get_type_param_bounds ()[0]->get_locus (), ErrorCode::E0568, "auto traits cannot have super traits"); + if (trait.has_trait_items ()) + { + rust_error_at (trait.get_identifier ().get_locus (), ErrorCode::E0380, + "auto traits cannot have methods or associated items"); + for (const auto &item : trait.get_trait_items ()) + Error::Hint (item->get_locus (), "remove this item").emit (); + } } AST::ContextualASTVisitor::visit (trait); diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index de17412..45c72e4 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -4989,18 +4989,6 @@ Parser::parse_trait (AST::Visibility vis, return nullptr; } - if (is_auto_trait && !trait_items.empty ()) - { - add_error (Error (locus, ErrorCode::E0380, - "auto traits cannot have associated items")); - - // FIXME: unsure if this should be done at parsing time or not - for (const auto &item : trait_items) - add_error (Error::Hint (item->get_locus (), "remove this item")); - - return nullptr; - } - trait_items.shrink_to_fit (); return std::unique_ptr ( new AST::Trait (std::move (ident), is_unsafe, is_auto_trait, diff --git a/gcc/testsuite/rust/compile/auto_trait_invalid.rs b/gcc/testsuite/rust/compile/auto_trait_invalid.rs index 66e4553..3be2acb 100644 --- a/gcc/testsuite/rust/compile/auto_trait_invalid.rs +++ b/gcc/testsuite/rust/compile/auto_trait_invalid.rs @@ -2,7 +2,9 @@ #![feature(optin_builtin_traits)] -unsafe auto trait Invalid { // { dg-error "auto traits cannot have associated items" } +auto trait Invalid { + // { dg-error "auto traits cannot have methods or associated items" "" { target *-*-* } .-1 } + fn foo(); // { dg-message "remove this item" } fn bar() {} // { dg-message "remove this item" } @@ -13,4 +15,3 @@ unsafe auto trait Invalid { // { dg-error "auto traits cannot have associated it const BAR: i32 = 15; // { dg-message "remove this item" } } -// { dg-error "failed to parse item in crate" "" {target *-*-* } .+1 } -- cgit v1.1 From 162137fd260b31633f1dfca850704309e2a2f6f6 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Mon, 20 Nov 2023 11:19:46 +0100 Subject: gccrs: Emit an error on variadic non extern functions Variadic regular functions were recently added in the parser as they should be rejected in the ast validation pass. This commit add the ast validation pass rejecting this kind of variadic arguments. gcc/rust/ChangeLog: * checks/errors/rust-ast-validation.cc (ASTValidation::visit): Add ast validation pass to reject variadic arguments on regular functions. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/checks/errors/rust-ast-validation.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc index 6732909..4142cc6 100644 --- a/gcc/rust/checks/errors/rust-ast-validation.cc +++ b/gcc/rust/checks/errors/rust-ast-validation.cc @@ -93,6 +93,11 @@ ASTValidation::visit (AST::Function &function) function.get_self_param ()->get_locus (), "% parameter is only allowed in associated functions"); + if (function.is_variadic ()) + rust_error_at ( + function.get_function_params ().back ()->get_locus (), + "only foreign or % functions may be C-variadic"); + AST::ContextualASTVisitor::visit (function); } -- cgit v1.1 From 4f45c715b83b91fe3c5a326a3474c7cebeefc09f Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Mon, 20 Nov 2023 11:37:12 +0100 Subject: gccrs: Add a test regular variadic functions errors Add a new regression test for the error message in regular function variadic errors during ast validation pass. gcc/testsuite/ChangeLog: * rust/compile/non_foreign_variadic_function.rs: New test. Signed-off-by: Pierre-Emmanuel Patry --- gcc/testsuite/rust/compile/non_foreign_variadic_function.rs | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 gcc/testsuite/rust/compile/non_foreign_variadic_function.rs diff --git a/gcc/testsuite/rust/compile/non_foreign_variadic_function.rs b/gcc/testsuite/rust/compile/non_foreign_variadic_function.rs new file mode 100644 index 0000000..2a4d309 --- /dev/null +++ b/gcc/testsuite/rust/compile/non_foreign_variadic_function.rs @@ -0,0 +1,4 @@ +pub fn toto(a: i32, ...) {} +// { dg-error "only foreign or .unsafe extern .C.. functions may be C-variadic" "" { target *-*-* } .-1 } + +fn main() {} -- cgit v1.1 From 72792563e60fb56b42c2e96b3ae27d28e09c2e7d Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Mon, 20 Nov 2023 15:41:39 +0100 Subject: gccrs: Add ast validation check on union variant number Unions with zero fields are forbidden. Add regression test for empty unions. gcc/rust/ChangeLog: * checks/errors/rust-ast-validation.cc (ASTValidation::visit): Add zero field check during ast validation pass. * checks/errors/rust-ast-validation.h: Add union visit function prototype. gcc/testsuite/ChangeLog: * rust/compile/const_generics_8.rs: Fill the union with dummy values. * rust/compile/empty_union.rs: New test. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/checks/errors/rust-ast-validation.cc | 10 ++++++++++ gcc/rust/checks/errors/rust-ast-validation.h | 2 ++ gcc/testsuite/rust/compile/const_generics_8.rs | 7 ++++++- gcc/testsuite/rust/compile/empty_union.rs | 2 ++ 4 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/rust/compile/empty_union.rs diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc index 4142cc6..dad7f5e 100644 --- a/gcc/rust/checks/errors/rust-ast-validation.cc +++ b/gcc/rust/checks/errors/rust-ast-validation.cc @@ -18,6 +18,7 @@ #include "rust-ast-validation.h" #include "rust-diagnostics.h" +#include "rust-item.h" #include "rust-keyword-values.h" namespace Rust { @@ -82,6 +83,15 @@ ASTValidation::visit (AST::ExternalFunctionItem &item) } void +ASTValidation::visit (AST::Union &item) +{ + if (item.get_variants ().empty ()) + rust_error_at (item.get_locus (), "unions cannot have zero fields"); + + AST::ContextualASTVisitor::visit (item); +} + +void ASTValidation::visit (AST::Function &function) { std::set valid_context diff --git a/gcc/rust/checks/errors/rust-ast-validation.h b/gcc/rust/checks/errors/rust-ast-validation.h index 49133ee..1052168 100644 --- a/gcc/rust/checks/errors/rust-ast-validation.h +++ b/gcc/rust/checks/errors/rust-ast-validation.h @@ -21,6 +21,7 @@ #include "rust-ast-visitor.h" #include "rust-ast-full.h" +#include "rust-item.h" namespace Rust { @@ -37,6 +38,7 @@ public: virtual void visit (AST::Lifetime &lifetime); virtual void visit (AST::LoopLabel &label); virtual void visit (AST::ExternalFunctionItem &item); + virtual void visit (AST::Union &item); virtual void visit (AST::Function &function); virtual void visit (AST::Trait &trait); }; diff --git a/gcc/testsuite/rust/compile/const_generics_8.rs b/gcc/testsuite/rust/compile/const_generics_8.rs index c781083..bb34652 100644 --- a/gcc/testsuite/rust/compile/const_generics_8.rs +++ b/gcc/testsuite/rust/compile/const_generics_8.rs @@ -8,7 +8,12 @@ enum Bidoule {} type Bipboupe = Bidule; trait Fooable {} -union Bidoulepe {} // { dg-error "default values for const generic parameters are not allowed in .union. items" } +union Bidoulepe { + // { dg-error "default values for const generic parameters are not allowed in .union. items" "" {target *-*-* } .-1 } + int: i32, + float: f32, +} + fn const_default() {} // { dg-error "default values for const generic parameters are not allowed in .function. items" } // Note - missing generic parameter - needs name resolution on const generics diff --git a/gcc/testsuite/rust/compile/empty_union.rs b/gcc/testsuite/rust/compile/empty_union.rs new file mode 100644 index 0000000..6114df5 --- /dev/null +++ b/gcc/testsuite/rust/compile/empty_union.rs @@ -0,0 +1,2 @@ +#[repr(C)] +union MyUnion {} // { dg-error "unions cannot have zero fields" } -- cgit v1.1 From 7f6319671e348bfd64cd1f468d19db3be50b5a93 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Wed, 15 Nov 2023 16:24:56 +0100 Subject: gccrs: Replace TOK suffix with KW TOK suffix was chosen to disambiguate some identifiers with c++ reserved keyword. Even though this list lies within the rust-token header, this macro is used in many context sometimes unrelated with the lexer and tokens. This TOK suffix may appear surprising in such context. gcc/rust/ChangeLog: * lex/rust-token.h (enum PrimitiveCoreType): Change keyword suffix from tok to kw. * ast/rust-ast-collector.cc (TokenCollector::visit): Update suffix to match the new declaration. * lex/rust-lex.cc (Lexer::parse_raw_identifier): Likewise. * parse/rust-parse-impl.h (can_tok_start_type): Likewise. (Parser::parse_item): Likewise. (Parser::parse_vis_item): Likewise. (Parser::parse_extern_crate): Likewise. (Parser::parse_function): Likewise. (Parser::parse_function_qualifiers): Likewise. (Parser::parse_struct): Likewise. (Parser::parse_enum): Likewise. (Parser::parse_static_item): Likewise. (Parser::parse_trait_item): Likewise. (Parser::parse_inherent_impl_item): Likewise. (Parser::parse_trait_impl_item): Likewise. (Parser::parse_extern_block): Likewise. (Parser::parse_external_item): Likewise. (Parser::parse_stmt): Likewise. (Parser::parse_return_expr): Likewise. (Parser::parse_match_expr): Likewise. (Parser::parse_type): Likewise. (Parser::parse_for_prefixed_type): Likewise. (Parser::parse_type_no_bounds): Likewise. (Parser::parse_stmt_or_expr): Likewise. * parse/rust-parse.cc (peculiar_fragment_match_compatible): Likewie. * util/rust-token-converter.cc (convert): Likewise. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/ast/rust-ast-collector.cc | 30 ++++---- gcc/rust/lex/rust-lex.cc | 2 +- gcc/rust/lex/rust-token.h | 20 ++--- gcc/rust/parse/rust-parse-impl.h | 134 +++++++++++++++++----------------- gcc/rust/parse/rust-parse.cc | 18 ++--- gcc/rust/util/rust-token-converter.cc | 18 ++--- 6 files changed, 111 insertions(+), 111 deletions(-) diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index 7d3d3e2..8f394e5 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -332,7 +332,7 @@ TokenCollector::visit (FunctionQualifiers &qualifiers) push (Rust::Token::make (UNSAFE, qualifiers.get_locus ())); if (qualifiers.is_extern ()) { - push (Rust::Token::make (EXTERN_TOK, qualifiers.get_locus ())); + push (Rust::Token::make (EXTERN_KW, qualifiers.get_locus ())); if (qualifiers.has_abi ()) { push (Rust::Token::make_string (UNDEF_LOCATION, @@ -1323,7 +1323,7 @@ TokenCollector::visit (RangeToInclExpr &expr) void TokenCollector::visit (ReturnExpr &expr) { - push (Rust::Token::make (RETURN_TOK, expr.get_locus ())); + push (Rust::Token::make (RETURN_KW, expr.get_locus ())); if (expr.has_returned_expr ()) visit (expr.get_returned_expr ()); } @@ -1463,7 +1463,7 @@ TokenCollector::visit (MatchCase &match_case) void TokenCollector::visit (MatchExpr &expr) { - push (Rust::Token::make (MATCH_TOK, expr.get_locus ())); + push (Rust::Token::make (MATCH_KW, expr.get_locus ())); visit (expr.get_scrutinee_expr ()); push (Rust::Token::make (LEFT_CURLY, UNDEF_LOCATION)); newline (); @@ -1609,7 +1609,7 @@ void TokenCollector::visit (ExternCrate &crate) { visit_items_as_lines (crate.get_outer_attrs ()); - push (Rust::Token::make (EXTERN_TOK, crate.get_locus ())); + push (Rust::Token::make (EXTERN_KW, crate.get_locus ())); push (Rust::Token::make (CRATE, UNDEF_LOCATION)); auto ref = crate.get_referenced_crate (); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (ref))); @@ -1717,7 +1717,7 @@ TokenCollector::visit (Function &function) auto qualifiers = function.get_qualifiers (); visit (qualifiers); - push (Rust::Token::make (FN_TOK, function.get_locus ())); + push (Rust::Token::make (FN_KW, function.get_locus ())); auto name = function.get_function_name ().as_string (); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (name))); if (function.has_generics ()) @@ -1778,7 +1778,7 @@ TokenCollector::visit (StructStruct &struct_item) if (struct_item.has_visibility ()) visit (struct_item.get_visibility ()); auto struct_name = struct_item.get_identifier ().as_string (); - push (Rust::Token::make (STRUCT_TOK, struct_item.get_locus ())); + push (Rust::Token::make (STRUCT_KW, struct_item.get_locus ())); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (struct_name))); if (struct_item.has_generics ()) @@ -1800,7 +1800,7 @@ TokenCollector::visit (TupleStruct &tuple_struct) { visit_items_as_lines (tuple_struct.get_outer_attrs ()); auto struct_name = tuple_struct.get_identifier ().as_string (); - push (Rust::Token::make (STRUCT_TOK, tuple_struct.get_locus ())); + push (Rust::Token::make (STRUCT_KW, tuple_struct.get_locus ())); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (struct_name))); if (tuple_struct.has_generics ()) visit (tuple_struct.get_generic_params ()); @@ -1856,7 +1856,7 @@ TokenCollector::visit (Enum &enumeration) visit_items_as_lines (enumeration.get_outer_attrs ()); if (enumeration.has_visibility ()) visit (enumeration.get_visibility ()); - push (Rust::Token::make (ENUM_TOK, enumeration.get_locus ())); + push (Rust::Token::make (ENUM_KW, enumeration.get_locus ())); auto id = enumeration.get_identifier ().as_string (); push ( Rust::Token::make_identifier (enumeration.get_locus (), std::move (id))); @@ -1915,7 +1915,7 @@ void TokenCollector::visit (StaticItem &item) { visit_items_as_lines (item.get_outer_attrs ()); - push (Rust::Token::make (STATIC_TOK, item.get_locus ())); + push (Rust::Token::make (STATIC_KW, item.get_locus ())); if (item.is_mutable ()) push (Rust::Token::make (MUT, UNDEF_LOCATION)); @@ -1961,7 +1961,7 @@ TokenCollector::visit (TraitItemFunc &item) auto func = item.get_trait_function_decl (); auto id = func.get_identifier ().as_string (); - push (Rust::Token::make (FN_TOK, item.get_locus ())); + push (Rust::Token::make (FN_KW, item.get_locus ())); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION)); @@ -2000,7 +2000,7 @@ TokenCollector::visit (TraitItemMethod &item) auto method = item.get_trait_method_decl (); auto id = method.get_identifier ().as_string (); - push (Rust::Token::make (FN_TOK, item.get_locus ())); + push (Rust::Token::make (FN_KW, item.get_locus ())); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION)); @@ -2112,7 +2112,7 @@ TokenCollector::visit (ExternalStaticItem &item) visit_items_as_lines (item.get_outer_attrs ()); if (item.has_visibility ()) visit (item.get_visibility ()); - push (Rust::Token::make (STATIC_TOK, item.get_locus ())); + push (Rust::Token::make (STATIC_KW, item.get_locus ())); if (item.is_mut ()) push (Rust::Token::make (MUT, UNDEF_LOCATION)); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); @@ -2131,7 +2131,7 @@ TokenCollector::visit (ExternalFunctionItem &function) auto id = function.get_identifier ().as_string (); - push (Rust::Token::make (FN_TOK, function.get_locus ())); + push (Rust::Token::make (FN_KW, function.get_locus ())); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); if (function.has_generics ()) visit (function.get_generic_params ()); @@ -2152,7 +2152,7 @@ void TokenCollector::visit (ExternBlock &block) { visit_items_as_lines (block.get_outer_attrs ()); - push (Rust::Token::make (EXTERN_TOK, block.get_locus ())); + push (Rust::Token::make (EXTERN_KW, block.get_locus ())); if (block.has_abi ()) { @@ -2821,7 +2821,7 @@ TokenCollector::visit (BareFunctionType &type) visit (type.get_function_qualifiers ()); - push (Rust::Token::make (FN_TOK, type.get_locus ())); + push (Rust::Token::make (FN_KW, type.get_locus ())); push (Rust::Token::make (LEFT_PAREN, UNDEF_LOCATION)); visit_items_joined_by_separator (type.get_function_params (), COMMA); diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc index 107dbad..2d41c11 100644 --- a/gcc/rust/lex/rust-lex.cc +++ b/gcc/rust/lex/rust-lex.cc @@ -1940,7 +1940,7 @@ Lexer::parse_raw_identifier (location_t loc) using namespace Rust::Values; std::set invalid{ - Keywords::CRATE, Keywords::EXTERN_TOK, Keywords::SELF, + Keywords::CRATE, Keywords::EXTERN_KW, Keywords::SELF, Keywords::SUPER, Keywords::SELF_ALIAS, }; diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h index 5da8b6c..50513ac 100644 --- a/gcc/rust/lex/rust-token.h +++ b/gcc/rust/lex/rust-token.h @@ -162,11 +162,11 @@ enum PrimitiveCoreType RS_TOKEN_KEYWORD (DO, "do") /* unused */ \ RS_TOKEN_KEYWORD (DYN, "dyn") \ RS_TOKEN_KEYWORD (ELSE, "else") \ - RS_TOKEN_KEYWORD (ENUM_TOK, "enum") \ - RS_TOKEN_KEYWORD (EXTERN_TOK, "extern") \ + RS_TOKEN_KEYWORD (ENUM_KW, "enum") \ + RS_TOKEN_KEYWORD (EXTERN_KW, "extern") \ RS_TOKEN_KEYWORD (FALSE_LITERAL, "false") \ - RS_TOKEN_KEYWORD (FINAL_TOK, "final") /* unused */ \ - RS_TOKEN_KEYWORD (FN_TOK, "fn") \ + RS_TOKEN_KEYWORD (FINAL_KW, "final") /* unused */ \ + RS_TOKEN_KEYWORD (FN_KW, "fn") \ RS_TOKEN_KEYWORD (FOR, "for") \ RS_TOKEN_KEYWORD (IF, "if") \ RS_TOKEN_KEYWORD (IMPL, "impl") \ @@ -174,20 +174,20 @@ enum PrimitiveCoreType RS_TOKEN_KEYWORD (LET, "let") \ RS_TOKEN_KEYWORD (LOOP, "loop") \ RS_TOKEN_KEYWORD (MACRO, "macro") \ - RS_TOKEN_KEYWORD (MATCH_TOK, "match") \ + RS_TOKEN_KEYWORD (MATCH_KW, "match") \ RS_TOKEN_KEYWORD (MOD, "mod") \ RS_TOKEN_KEYWORD (MOVE, "move") \ RS_TOKEN_KEYWORD (MUT, "mut") \ - RS_TOKEN_KEYWORD (OVERRIDE_TOK, "override") /* unused */ \ - RS_TOKEN_KEYWORD (PRIV, "priv") /* unused */ \ + RS_TOKEN_KEYWORD (OVERRIDE_KW, "override") /* unused */ \ + RS_TOKEN_KEYWORD (PRIV, "priv") /* unused */ \ RS_TOKEN_KEYWORD (PUB, "pub") \ RS_TOKEN_KEYWORD (REF, "ref") \ - RS_TOKEN_KEYWORD (RETURN_TOK, "return") \ + RS_TOKEN_KEYWORD (RETURN_KW, "return") \ RS_TOKEN_KEYWORD (SELF_ALIAS, \ "Self") /* mrustc does not treat this as a reserved word*/ \ RS_TOKEN_KEYWORD (SELF, "self") \ - RS_TOKEN_KEYWORD (STATIC_TOK, "static") \ - RS_TOKEN_KEYWORD (STRUCT_TOK, "struct") \ + RS_TOKEN_KEYWORD (STATIC_KW, "static") \ + RS_TOKEN_KEYWORD (STRUCT_KW, "struct") \ RS_TOKEN_KEYWORD (SUPER, "super") \ RS_TOKEN_KEYWORD (TRAIT, "trait") \ RS_TOKEN_KEYWORD (TRUE_LITERAL, "true") \ diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 45c72e4..8b00614 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -160,8 +160,8 @@ can_tok_start_type (TokenId id) case ASYNC: case CONST: case UNSAFE: - case EXTERN_TOK: - case FN_TOK: + case EXTERN_KW: + case FN_KW: case IMPL: case DYN: case QUESTION_MARK: @@ -1114,14 +1114,14 @@ Parser::parse_item (bool called_from_statement) return nullptr; case PUB: case MOD: - case EXTERN_TOK: + case EXTERN_KW: case USE: - case FN_TOK: + case FN_KW: case TYPE: - case STRUCT_TOK: - case ENUM_TOK: + case STRUCT_KW: + case ENUM_KW: case CONST: - case STATIC_TOK: + case STATIC_KW: case AUTO: case TRAIT: case IMPL: @@ -1302,7 +1302,7 @@ Parser::parse_vis_item (AST::AttrVec outer_attrs) { case MOD: return parse_module (std::move (vis), std::move (outer_attrs)); - case EXTERN_TOK: + case EXTERN_KW: // lookahead to resolve syntactical production t = lexer.peek_token (1); @@ -1310,7 +1310,7 @@ Parser::parse_vis_item (AST::AttrVec outer_attrs) { case CRATE: return parse_extern_crate (std::move (vis), std::move (outer_attrs)); - case FN_TOK: // extern function + case FN_KW: // extern function return parse_function (std::move (vis), std::move (outer_attrs)); case LEFT_CURLY: // extern block return parse_extern_block (std::move (vis), std::move (outer_attrs)); @@ -1320,7 +1320,7 @@ Parser::parse_vis_item (AST::AttrVec outer_attrs) switch (t->get_id ()) { - case FN_TOK: + case FN_KW: return parse_function (std::move (vis), std::move (outer_attrs)); case LEFT_CURLY: return parse_extern_block (std::move (vis), @@ -1345,13 +1345,13 @@ Parser::parse_vis_item (AST::AttrVec outer_attrs) } case USE: return parse_use_decl (std::move (vis), std::move (outer_attrs)); - case FN_TOK: + case FN_KW: return parse_function (std::move (vis), std::move (outer_attrs)); case TYPE: return parse_type_alias (std::move (vis), std::move (outer_attrs)); - case STRUCT_TOK: + case STRUCT_KW: return parse_struct (std::move (vis), std::move (outer_attrs)); - case ENUM_TOK: + case ENUM_KW: return parse_enum (std::move (vis), std::move (outer_attrs)); // TODO: implement union keyword but not really because of // context-dependence case UNION: crappy hack to do union "keyword" @@ -1376,8 +1376,8 @@ Parser::parse_vis_item (AST::AttrVec outer_attrs) case UNDERSCORE: return parse_const_item (std::move (vis), std::move (outer_attrs)); case UNSAFE: - case EXTERN_TOK: - case FN_TOK: + case EXTERN_KW: + case FN_KW: return parse_function (std::move (vis), std::move (outer_attrs)); default: add_error ( @@ -1388,7 +1388,7 @@ Parser::parse_vis_item (AST::AttrVec outer_attrs) lexer.skip_token (1); // TODO: is this right thing to do? return nullptr; } - case STATIC_TOK: + case STATIC_KW: return parse_static_item (std::move (vis), std::move (outer_attrs)); case AUTO: case TRAIT: @@ -1404,8 +1404,8 @@ Parser::parse_vis_item (AST::AttrVec outer_attrs) case AUTO: case TRAIT: return parse_trait (std::move (vis), std::move (outer_attrs)); - case EXTERN_TOK: - case FN_TOK: + case EXTERN_KW: + case FN_KW: return parse_function (std::move (vis), std::move (outer_attrs)); case IMPL: return parse_impl (std::move (vis), std::move (outer_attrs)); @@ -2482,7 +2482,7 @@ Parser::parse_extern_crate (AST::Visibility vis, AST::AttrVec outer_attrs) { location_t locus = lexer.peek_token ()->get_locus (); - if (!skip_token (EXTERN_TOK)) + if (!skip_token (EXTERN_KW)) { skip_after_semicolon (); return nullptr; @@ -2854,7 +2854,7 @@ Parser::parse_function (AST::Visibility vis, // Get qualifiers for function if they exist AST::FunctionQualifiers qualifiers = parse_function_qualifiers (); - skip_token (FN_TOK); + skip_token (FN_KW); // Save function name token const_TokenPtr function_name_tok = expect_token (IDENTIFIER); @@ -2962,7 +2962,7 @@ Parser::parse_function_qualifiers () has_unsafe = true; } - if (lexer.peek_token ()->get_id () == EXTERN_TOK) + if (lexer.peek_token ()->get_id () == EXTERN_KW) { lexer.skip_token (); has_extern = true; @@ -4193,7 +4193,7 @@ Parser::parse_struct (AST::Visibility vis, /* Tuple struct <- 'struct' IDENTIFIER generic_params? '(' tuple_fields? ')' * where_clause? ';' */ location_t locus = lexer.peek_token ()->get_locus (); - skip_token (STRUCT_TOK); + skip_token (STRUCT_KW); // parse struct name const_TokenPtr name_tok = expect_token (IDENTIFIER); @@ -4521,7 +4521,7 @@ Parser::parse_enum (AST::Visibility vis, AST::AttrVec outer_attrs) { location_t locus = lexer.peek_token ()->get_locus (); - skip_token (ENUM_TOK); + skip_token (ENUM_KW); // parse enum name const_TokenPtr enum_name_tok = expect_token (IDENTIFIER); @@ -4856,7 +4856,7 @@ Parser::parse_static_item (AST::Visibility vis, AST::AttrVec outer_attrs) { location_t locus = lexer.peek_token ()->get_locus (); - skip_token (STATIC_TOK); + skip_token (STATIC_KW); // determine whether static item is mutable bool is_mut = false; @@ -5024,8 +5024,8 @@ Parser::parse_trait_item () // TODO: find out how to disable gcc "implicit fallthrough" error gcc_fallthrough (); case UNSAFE: - case EXTERN_TOK: - case FN_TOK: { + case EXTERN_KW: + case FN_KW: { /* function and method can't be disambiguated by lookahead alone * (without a lot of work and waste), so either make a * "parse_trait_function_or_method" or parse here mostly and pass in @@ -5035,7 +5035,7 @@ Parser::parse_trait_item () // parse function or method qualifiers AST::FunctionQualifiers qualifiers = parse_function_qualifiers (); - skip_token (FN_TOK); + skip_token (FN_KW); // parse function or method name const_TokenPtr ident_tok = expect_token (IDENTIFIER); @@ -5484,9 +5484,9 @@ Parser::parse_inherent_impl_item () // TODO: is a recursive call to parse_inherent_impl_item better? switch (lexer.peek_token ()->get_id ()) { - case EXTERN_TOK: + case EXTERN_KW: case UNSAFE: - case FN_TOK: + case FN_KW: // function or method return parse_inherent_impl_function_or_method (std::move (vis), std::move ( @@ -5503,8 +5503,8 @@ Parser::parse_inherent_impl_item () return parse_const_item (std::move (vis), std::move (outer_attrs)); case UNSAFE: - case EXTERN_TOK: - case FN_TOK: + case EXTERN_KW: + case FN_KW: return parse_inherent_impl_function_or_method (std::move (vis), std::move ( outer_attrs)); @@ -5526,9 +5526,9 @@ Parser::parse_inherent_impl_item () return nullptr; } } - case EXTERN_TOK: + case EXTERN_KW: case UNSAFE: - case FN_TOK: + case FN_KW: // function or method return parse_inherent_impl_function_or_method ( AST::Visibility::create_private (), std::move (outer_attrs)); @@ -5544,8 +5544,8 @@ Parser::parse_inherent_impl_item () return parse_const_item (AST::Visibility::create_private (), std::move (outer_attrs)); case UNSAFE: - case EXTERN_TOK: - case FN_TOK: + case EXTERN_KW: + case FN_KW: return parse_inherent_impl_function_or_method ( AST::Visibility::create_private (), std::move (outer_attrs)); default: @@ -5583,7 +5583,7 @@ Parser::parse_inherent_impl_function_or_method ( // parse function or method qualifiers AST::FunctionQualifiers qualifiers = parse_function_qualifiers (); - skip_token (FN_TOK); + skip_token (FN_KW); // parse function or method name const_TokenPtr ident_tok = expect_token (IDENTIFIER); @@ -5720,9 +5720,9 @@ Parser::parse_trait_impl_item () return parse_macro_invocation_semi (std::move (outer_attrs)); case TYPE: return parse_type_alias (visibility, std::move (outer_attrs)); - case EXTERN_TOK: + case EXTERN_KW: case UNSAFE: - case FN_TOK: + case FN_KW: // function or method return parse_trait_impl_function_or_method (visibility, std::move (outer_attrs)); @@ -5737,8 +5737,8 @@ Parser::parse_trait_impl_item () case UNDERSCORE: return parse_const_item (visibility, std::move (outer_attrs)); case UNSAFE: - case EXTERN_TOK: - case FN_TOK: + case EXTERN_KW: + case FN_KW: return parse_trait_impl_function_or_method (visibility, std::move (outer_attrs)); default: @@ -5786,7 +5786,7 @@ Parser::parse_trait_impl_function_or_method ( // parse function or method qualifiers AST::FunctionQualifiers qualifiers = parse_function_qualifiers (); - skip_token (FN_TOK); + skip_token (FN_KW); // parse function or method name const_TokenPtr ident_tok = expect_token (IDENTIFIER); @@ -5931,7 +5931,7 @@ Parser::parse_extern_block (AST::Visibility vis, AST::AttrVec outer_attrs) { location_t locus = lexer.peek_token ()->get_locus (); - skip_token (EXTERN_TOK); + skip_token (EXTERN_KW); // detect optional abi name std::string abi; @@ -6167,7 +6167,7 @@ Parser::parse_external_item () { case IDENTIFIER: return parse_macro_invocation_semi (outer_attrs); - case STATIC_TOK: { + case STATIC_KW: { // parse extern static item lexer.skip_token (); @@ -6217,7 +6217,7 @@ Parser::parse_external_item () has_mut, std::move (vis), std::move (outer_attrs), locus)); } - case FN_TOK: + case FN_KW: return parse_external_function_item (std::move (vis), std::move (outer_attrs)); case TYPE: @@ -6266,14 +6266,14 @@ Parser::parse_stmt (ParseRestrictions restrictions) return parse_let_stmt (std::move (outer_attrs), restrictions); case PUB: case MOD: - case EXTERN_TOK: + case EXTERN_KW: case USE: - case FN_TOK: + case FN_KW: case TYPE: - case STRUCT_TOK: - case ENUM_TOK: + case STRUCT_KW: + case ENUM_KW: case CONST: - case STATIC_TOK: + case STATIC_KW: case AUTO: case TRAIT: case IMPL: @@ -7675,7 +7675,7 @@ Parser::parse_return_expr (AST::AttrVec outer_attrs, if (locus == UNKNOWN_LOCATION) { locus = lexer.peek_token ()->get_locus (); - skip_token (RETURN_TOK); + skip_token (RETURN_KW); } // parse expression to return, if it exists @@ -8448,7 +8448,7 @@ Parser::parse_match_expr (AST::AttrVec outer_attrs, if (locus == UNKNOWN_LOCATION) { locus = lexer.peek_token ()->get_locus (); - skip_token (MATCH_TOK); + skip_token (MATCH_KW); } /* parse scrutinee expression, which is required (and HACK to prevent struct @@ -9246,8 +9246,8 @@ Parser::parse_type (bool save_errors) case ASYNC: case CONST: case UNSAFE: - case EXTERN_TOK: - case FN_TOK: + case EXTERN_KW: + case FN_KW: // bare function type (with no for lifetimes) return parse_bare_function_type (std::vector ()); case IMPL: @@ -9563,8 +9563,8 @@ Parser::parse_for_prefixed_type () case ASYNC: case CONST: case UNSAFE: - case EXTERN_TOK: - case FN_TOK: + case EXTERN_KW: + case FN_KW: return parse_bare_function_type (std::move (for_lifetimes)); case SCOPE_RESOLUTION: case IDENTIFIER: @@ -9686,7 +9686,7 @@ Parser::parse_bare_function_type ( AST::FunctionQualifiers qualifiers = parse_function_qualifiers (); - if (!skip_token (FN_TOK)) + if (!skip_token (FN_KW)) return nullptr; if (!skip_token (LEFT_PAREN)) @@ -10072,8 +10072,8 @@ Parser::parse_type_no_bounds () case ASYNC: case CONST: case UNSAFE: - case EXTERN_TOK: - case FN_TOK: + case EXTERN_KW: + case FN_KW: // bare function type (with no for lifetimes) return parse_bare_function_type (std::vector ()); case IMPL: @@ -11632,14 +11632,14 @@ Parser::parse_stmt_or_expr () } case PUB: case MOD: - case EXTERN_TOK: + case EXTERN_KW: case USE: - case FN_TOK: + case FN_KW: case TYPE: - case STRUCT_TOK: - case ENUM_TOK: + case STRUCT_KW: + case ENUM_KW: case CONST: - case STATIC_TOK: + case STATIC_KW: case AUTO: case TRAIT: case IMPL: { @@ -11670,8 +11670,8 @@ Parser::parse_stmt_or_expr () parse_vis_item (std::move (outer_attrs))); return ExprOrStmt (std::move (item)); } - case EXTERN_TOK: - case FN_TOK: { + case EXTERN_KW: + case FN_KW: { // unsafe function std::unique_ptr item ( parse_vis_item (std::move (outer_attrs))); @@ -12535,7 +12535,7 @@ Parser::null_denotation_not_path ( case DOT_DOT_EQ: // range to inclusive expr return parse_range_to_inclusive_expr (tok, std::move (outer_attrs)); - case RETURN_TOK: + case RETURN_KW: // FIXME: is this really a null denotation expression? return parse_return_expr (std::move (outer_attrs), tok->get_locus ()); case BREAK: @@ -12578,7 +12578,7 @@ Parser::null_denotation_not_path ( case FOR: return parse_for_loop_expr (std::move (outer_attrs), AST::LoopLabel::error ()); - case MATCH_TOK: + case MATCH_KW: // also an expression with block return parse_match_expr (std::move (outer_attrs), tok->get_locus ()); case LEFT_SQUARE: diff --git a/gcc/rust/parse/rust-parse.cc b/gcc/rust/parse/rust-parse.cc index 0f91c7f..504a409 100644 --- a/gcc/rust/parse/rust-parse.cc +++ b/gcc/rust/parse/rust-parse.cc @@ -194,11 +194,11 @@ peculiar_fragment_match_compatible (const AST::MacroMatchFragment &last_match, DO, DYN, ELSE, - ENUM_TOK, - EXTERN_TOK, + ENUM_KW, + EXTERN_KW, FALSE_LITERAL, - FINAL_TOK, - FN_TOK, + FINAL_KW, + FN_KW, FOR, IF, IMPL, @@ -206,18 +206,18 @@ peculiar_fragment_match_compatible (const AST::MacroMatchFragment &last_match, LET, LOOP, MACRO, - MATCH_TOK, + MATCH_KW, MOD, MOVE, MUT, - OVERRIDE_TOK, + OVERRIDE_KW, PUB, REF, - RETURN_TOK, + RETURN_KW, SELF_ALIAS, SELF, - STATIC_TOK, - STRUCT_TOK, + STATIC_KW, + STRUCT_KW, SUPER, TRAIT, TRUE_LITERAL, diff --git a/gcc/rust/util/rust-token-converter.cc b/gcc/rust/util/rust-token-converter.cc index 537bca3..41f8105 100644 --- a/gcc/rust/util/rust-token-converter.cc +++ b/gcc/rust/util/rust-token-converter.cc @@ -134,10 +134,10 @@ convert (const std::vector &tokens) case DO: case DYN: case ELSE: - case ENUM_TOK: - case EXTERN_TOK: - case FINAL_TOK: - case FN_TOK: + case ENUM_KW: + case EXTERN_KW: + case FINAL_KW: + case FN_KW: case FOR: case IF: case IMPL: @@ -145,19 +145,19 @@ convert (const std::vector &tokens) case LET: case LOOP: case MACRO: - case MATCH_TOK: + case MATCH_KW: case MOD: case MOVE: case MUT: - case OVERRIDE_TOK: + case OVERRIDE_KW: case PRIV: case PUB: case REF: - case RETURN_TOK: + case RETURN_KW: case SELF_ALIAS: case SELF: - case STATIC_TOK: - case STRUCT_TOK: + case STATIC_KW: + case STRUCT_KW: case SUPER: case TRAIT: case TRY: -- cgit v1.1 From c23db3e0c2e7717cedcdc1ff14f2aba563de2178 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Thu, 16 Nov 2023 11:42:35 +0100 Subject: gccrs: Add edition separation for keywords It might be required in the future to get only the keywords from a specific edition. To do so we need a mean to differentiate keywords based on their edition. This commit changes the existing keyword macro to allow such behavior. gcc/rust/ChangeLog: * lex/rust-token.h (enum PrimitiveCoreType): Change enum macro calls. (RS_TOKEN_KEYWORD): Remove generic token keyword macro. (RS_TOKEN_KEYWORD_2015): Introduce keywords for edition 2015. (RS_TOKEN_KEYWORD_2018): Likewise with edition 2018. * lex/rust-token.cc (RS_TOKEN_KEYWORD): Remove old macro definition. (RS_TOKEN_KEYWORD_2015): Replace with 2015 definition... (RS_TOKEN_KEYWORD_2018): ... and 2018 definition. * util/rust-keyword-values.cc (RS_TOKEN_KEYWORD): Likewise. (RS_TOKEN_KEYWORD_2015): Likewise. (RS_TOKEN_KEYWORD_2018): Likewise. * util/rust-keyword-values.h (RS_TOKEN_KEYWORD): Likewise. (RS_TOKEN_KEYWORD_2015): Likewise. (RS_TOKEN_KEYWORD_2018): Likewise. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/lex/rust-token.cc | 24 +++++--- gcc/rust/lex/rust-token.h | 114 ++++++++++++++++++----------------- gcc/rust/util/rust-keyword-values.cc | 6 +- gcc/rust/util/rust-keyword-values.h | 6 +- 4 files changed, 82 insertions(+), 68 deletions(-) diff --git a/gcc/rust/lex/rust-token.cc b/gcc/rust/lex/rust-token.cc index ea35505..7bb3273 100644 --- a/gcc/rust/lex/rust-token.cc +++ b/gcc/rust/lex/rust-token.cc @@ -31,9 +31,11 @@ get_token_description (TokenId id) #define RS_TOKEN(name, descr) \ case name: \ return descr; -#define RS_TOKEN_KEYWORD(x, y) RS_TOKEN (x, y) +#define RS_TOKEN_KEYWORD_2015(x, y) RS_TOKEN (x, y) +#define RS_TOKEN_KEYWORD_2018 RS_TOKEN_KEYWORD_2015 RS_TOKEN_LIST -#undef RS_TOKEN_KEYWORD +#undef RS_TOKEN_KEYWORD_2015 +#undef RS_TOKEN_KEYWORD_2018 #undef RS_TOKEN default: rust_unreachable (); @@ -50,9 +52,11 @@ token_id_to_str (TokenId id) #define RS_TOKEN(name, _) \ case name: \ return #name; -#define RS_TOKEN_KEYWORD(x, y) RS_TOKEN (x, y) +#define RS_TOKEN_KEYWORD_2015(x, y) RS_TOKEN (x, y) +#define RS_TOKEN_KEYWORD_2018 RS_TOKEN_KEYWORD_2015 RS_TOKEN_LIST -#undef RS_TOKEN_KEYWORD +#undef RS_TOKEN_KEYWORD_2015 +#undef RS_TOKEN_KEYWORD_2018 #undef RS_TOKEN default: rust_unreachable (); @@ -65,10 +69,12 @@ token_id_is_keyword (TokenId id) { switch (id) { -#define RS_TOKEN_KEYWORD(name, _) case name: +#define RS_TOKEN_KEYWORD_2015(name, _) case name: +#define RS_TOKEN_KEYWORD_2018 RS_TOKEN_KEYWORD_2015 #define RS_TOKEN(a, b) RS_TOKEN_LIST return true; -#undef RS_TOKEN_KEYWORD +#undef RS_TOKEN_KEYWORD_2015 +#undef RS_TOKEN_KEYWORD_2018 #undef RS_TOKEN default: return false; @@ -81,15 +87,17 @@ token_id_keyword_string (TokenId id) { switch (id) { -#define RS_TOKEN_KEYWORD(id, str_ptr) \ +#define RS_TOKEN_KEYWORD_2015(id, str_ptr) \ case id: { \ static const std::string str (str_ptr); \ return str; \ } \ rust_unreachable (); +#define RS_TOKEN_KEYWORD_2018 RS_TOKEN_KEYWORD_2015 #define RS_TOKEN(a, b) RS_TOKEN_LIST -#undef RS_TOKEN_KEYWORD +#undef RS_TOKEN_KEYWORD_2015 +#undef RS_TOKEN_KEYWORD_2018 #undef RS_TOKEN default: rust_unreachable (); diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h index 50513ac..df32100 100644 --- a/gcc/rust/lex/rust-token.h +++ b/gcc/rust/lex/rust-token.h @@ -59,8 +59,8 @@ enum PrimitiveCoreType }; // RS_TOKEN(name, description) -// RS_TOKEN_KEYWORD(name, identifier) -// +// RS_TOKEN_KEYWORD_{2015,2018}(name, identifier) + // Keep RS_TOKEN_KEYWORD sorted /* note that abstract, async, become, box, do, final, macro, override, priv, @@ -148,68 +148,70 @@ enum PrimitiveCoreType RS_TOKEN (INNER_DOC_COMMENT, "#![doc]") \ RS_TOKEN (OUTER_DOC_COMMENT, "#[doc]") \ /* have "weak" union and 'static keywords? */ \ - RS_TOKEN_KEYWORD (ABSTRACT, "abstract") /* unused */ \ - RS_TOKEN_KEYWORD (AS, "as") \ - RS_TOKEN_KEYWORD (ASYNC, "async") /* unused */ \ - RS_TOKEN_KEYWORD (AUTO, "auto") \ - RS_TOKEN_KEYWORD (BECOME, "become") /* unused */ \ - RS_TOKEN_KEYWORD (BOX, "box") /* unused */ \ - RS_TOKEN_KEYWORD (BREAK, "break") \ - RS_TOKEN_KEYWORD (CONST, "const") \ - RS_TOKEN_KEYWORD (CONTINUE, "continue") \ - RS_TOKEN_KEYWORD (CRATE, "crate") \ + RS_TOKEN_KEYWORD_2015 (ABSTRACT, "abstract") /* unused */ \ + RS_TOKEN_KEYWORD_2015 (AS, "as") \ + RS_TOKEN_KEYWORD_2018 (ASYNC, "async") /* unused */ \ + RS_TOKEN_KEYWORD_2015 (AUTO, "auto") \ + RS_TOKEN_KEYWORD_2015 (BECOME, "become") /* unused */ \ + RS_TOKEN_KEYWORD_2015 (BOX, "box") /* unused */ \ + RS_TOKEN_KEYWORD_2015 (BREAK, "break") \ + RS_TOKEN_KEYWORD_2015 (CONST, "const") \ + RS_TOKEN_KEYWORD_2015 (CONTINUE, "continue") \ + RS_TOKEN_KEYWORD_2015 (CRATE, "crate") \ /* FIXME: Do we need to add $crate (DOLLAR_CRATE) as a reserved kw? */ \ - RS_TOKEN_KEYWORD (DO, "do") /* unused */ \ - RS_TOKEN_KEYWORD (DYN, "dyn") \ - RS_TOKEN_KEYWORD (ELSE, "else") \ - RS_TOKEN_KEYWORD (ENUM_KW, "enum") \ - RS_TOKEN_KEYWORD (EXTERN_KW, "extern") \ - RS_TOKEN_KEYWORD (FALSE_LITERAL, "false") \ - RS_TOKEN_KEYWORD (FINAL_KW, "final") /* unused */ \ - RS_TOKEN_KEYWORD (FN_KW, "fn") \ - RS_TOKEN_KEYWORD (FOR, "for") \ - RS_TOKEN_KEYWORD (IF, "if") \ - RS_TOKEN_KEYWORD (IMPL, "impl") \ - RS_TOKEN_KEYWORD (IN, "in") \ - RS_TOKEN_KEYWORD (LET, "let") \ - RS_TOKEN_KEYWORD (LOOP, "loop") \ - RS_TOKEN_KEYWORD (MACRO, "macro") \ - RS_TOKEN_KEYWORD (MATCH_KW, "match") \ - RS_TOKEN_KEYWORD (MOD, "mod") \ - RS_TOKEN_KEYWORD (MOVE, "move") \ - RS_TOKEN_KEYWORD (MUT, "mut") \ - RS_TOKEN_KEYWORD (OVERRIDE_KW, "override") /* unused */ \ - RS_TOKEN_KEYWORD (PRIV, "priv") /* unused */ \ - RS_TOKEN_KEYWORD (PUB, "pub") \ - RS_TOKEN_KEYWORD (REF, "ref") \ - RS_TOKEN_KEYWORD (RETURN_KW, "return") \ - RS_TOKEN_KEYWORD (SELF_ALIAS, \ - "Self") /* mrustc does not treat this as a reserved word*/ \ - RS_TOKEN_KEYWORD (SELF, "self") \ - RS_TOKEN_KEYWORD (STATIC_KW, "static") \ - RS_TOKEN_KEYWORD (STRUCT_KW, "struct") \ - RS_TOKEN_KEYWORD (SUPER, "super") \ - RS_TOKEN_KEYWORD (TRAIT, "trait") \ - RS_TOKEN_KEYWORD (TRUE_LITERAL, "true") \ - RS_TOKEN_KEYWORD (TRY, "try") /* unused */ \ - RS_TOKEN_KEYWORD (TYPE, "type") \ - RS_TOKEN_KEYWORD (TYPEOF, "typeof") /* unused */ \ - RS_TOKEN_KEYWORD (UNSAFE, "unsafe") \ - RS_TOKEN_KEYWORD (UNSIZED, "unsized") /* unused */ \ - RS_TOKEN_KEYWORD (USE, "use") \ - RS_TOKEN_KEYWORD (VIRTUAL, "virtual") /* unused */ \ - RS_TOKEN_KEYWORD (WHERE, "where") \ - RS_TOKEN_KEYWORD (WHILE, "while") \ - RS_TOKEN_KEYWORD (YIELD, "yield") /* unused */ \ + RS_TOKEN_KEYWORD_2015 (DO, "do") /* unused */ \ + RS_TOKEN_KEYWORD_2018 (DYN, "dyn") \ + RS_TOKEN_KEYWORD_2015 (ELSE, "else") \ + RS_TOKEN_KEYWORD_2015 (ENUM_KW, "enum") \ + RS_TOKEN_KEYWORD_2015 (EXTERN_KW, "extern") \ + RS_TOKEN_KEYWORD_2015 (FALSE_LITERAL, "false") \ + RS_TOKEN_KEYWORD_2015 (FINAL_KW, "final") /* unused */ \ + RS_TOKEN_KEYWORD_2015 (FN_KW, "fn") \ + RS_TOKEN_KEYWORD_2015 (FOR, "for") \ + RS_TOKEN_KEYWORD_2015 (IF, "if") \ + RS_TOKEN_KEYWORD_2015 (IMPL, "impl") \ + RS_TOKEN_KEYWORD_2015 (IN, "in") \ + RS_TOKEN_KEYWORD_2015 (LET, "let") \ + RS_TOKEN_KEYWORD_2015 (LOOP, "loop") \ + RS_TOKEN_KEYWORD_2015 (MACRO, "macro") \ + RS_TOKEN_KEYWORD_2015 (MATCH_KW, "match") \ + RS_TOKEN_KEYWORD_2015 (MOD, "mod") \ + RS_TOKEN_KEYWORD_2015 (MOVE, "move") \ + RS_TOKEN_KEYWORD_2015 (MUT, "mut") \ + RS_TOKEN_KEYWORD_2015 (OVERRIDE_KW, "override") /* unused */ \ + RS_TOKEN_KEYWORD_2015 (PRIV, "priv") /* unused */ \ + RS_TOKEN_KEYWORD_2015 (PUB, "pub") \ + RS_TOKEN_KEYWORD_2015 (REF, "ref") \ + RS_TOKEN_KEYWORD_2015 (RETURN_KW, "return") \ + RS_TOKEN_KEYWORD_2015 ( \ + SELF_ALIAS, "Self") /* mrustc does not treat this as a reserved word*/ \ + RS_TOKEN_KEYWORD_2015 (SELF, "self") \ + RS_TOKEN_KEYWORD_2015 (STATIC_KW, "static") \ + RS_TOKEN_KEYWORD_2015 (STRUCT_KW, "struct") \ + RS_TOKEN_KEYWORD_2015 (SUPER, "super") \ + RS_TOKEN_KEYWORD_2015 (TRAIT, "trait") \ + RS_TOKEN_KEYWORD_2015 (TRUE_LITERAL, "true") \ + RS_TOKEN_KEYWORD_2015 (TRY, "try") /* unused */ \ + RS_TOKEN_KEYWORD_2015 (TYPE, "type") \ + RS_TOKEN_KEYWORD_2015 (TYPEOF, "typeof") /* unused */ \ + RS_TOKEN_KEYWORD_2015 (UNSAFE, "unsafe") \ + RS_TOKEN_KEYWORD_2015 (UNSIZED, "unsized") /* unused */ \ + RS_TOKEN_KEYWORD_2015 (USE, "use") \ + RS_TOKEN_KEYWORD_2015 (VIRTUAL, "virtual") /* unused */ \ + RS_TOKEN_KEYWORD_2015 (WHERE, "where") \ + RS_TOKEN_KEYWORD_2015 (WHILE, "while") \ + RS_TOKEN_KEYWORD_2015 (YIELD, "yield") /* unused */ \ RS_TOKEN (LAST_TOKEN, "") // Contains all token types. Crappy implementation via x-macros. enum TokenId { #define RS_TOKEN(name, _) name, -#define RS_TOKEN_KEYWORD(x, y) RS_TOKEN (x, y) +#define RS_TOKEN_KEYWORD_2015(x, y) RS_TOKEN (x, y) +#define RS_TOKEN_KEYWORD_2018 RS_TOKEN_KEYWORD_2015 RS_TOKEN_LIST -#undef RS_TOKEN_KEYWORD +#undef RS_TOKEN_KEYWORD_2015 +#undef RS_TOKEN_KEYWORD_2018 #undef RS_TOKEN }; diff --git a/gcc/rust/util/rust-keyword-values.cc b/gcc/rust/util/rust-keyword-values.cc index 58a404d..8aa5ef1 100644 --- a/gcc/rust/util/rust-keyword-values.cc +++ b/gcc/rust/util/rust-keyword-values.cc @@ -28,9 +28,11 @@ get_keywords () { std::map m = { #define RS_TOKEN(x, y) -#define RS_TOKEN_KEYWORD(tok, key) {key, tok}, +#define RS_TOKEN_KEYWORD_2015(tok, key) {key, tok}, +#define RS_TOKEN_KEYWORD_2018 RS_TOKEN_KEYWORD_2015 RS_TOKEN_LIST -#undef RS_TOKEN_KEYWORD +#undef RS_TOKEN_KEYWORD_2015 +#undef RS_TOKEN_KEYWORD_2018 #undef RS_TOKEN }; return m; diff --git a/gcc/rust/util/rust-keyword-values.h b/gcc/rust/util/rust-keyword-values.h index 3edae55..769b210 100644 --- a/gcc/rust/util/rust-keyword-values.h +++ b/gcc/rust/util/rust-keyword-values.h @@ -33,9 +33,11 @@ public: // Rust keyword values public: #define RS_TOKEN(x, y) -#define RS_TOKEN_KEYWORD(tok, key) static constexpr auto &tok = key; +#define RS_TOKEN_KEYWORD_2015(tok, key) static constexpr auto &tok = key; +#define RS_TOKEN_KEYWORD_2018 RS_TOKEN_KEYWORD_2015 RS_TOKEN_LIST -#undef RS_TOKEN_KEYWORD +#undef RS_TOKEN_KEYWORD_2015 +#undef RS_TOKEN_KEYWORD_2018 #undef RS_TOKEN }; -- cgit v1.1 From 3b853501e7b9d97c35950af6e561761cf9d11cf4 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Thu, 16 Nov 2023 12:39:37 +0100 Subject: gccrs: Treat underscore as a keyword Make the underscore token a 2015 keyword. gcc/rust/ChangeLog: * lex/rust-token.h (enum PrimitiveCoreType): Change macro for underscore in token list. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/lex/rust-token.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h index df32100..401452f 100644 --- a/gcc/rust/lex/rust-token.h +++ b/gcc/rust/lex/rust-token.h @@ -120,8 +120,6 @@ enum PrimitiveCoreType RS_TOKEN (SCOPE_RESOLUTION, "::") /* dodgy */ \ RS_TOKEN (SINGLE_QUOTE, "'") /* should i differentiate from lifetime? */ \ RS_TOKEN (DOUBLE_QUOTE, "\"") \ - RS_TOKEN (UNDERSCORE, \ - "_") /* TODO: treat as reserved word like mrustc instead? */ \ RS_TOKEN (IDENTIFIER, "identifier") \ RS_TOKEN (INT_LITERAL, \ "integer literal") /* do different int and float types need \ @@ -194,6 +192,7 @@ enum PrimitiveCoreType RS_TOKEN_KEYWORD_2015 (TRY, "try") /* unused */ \ RS_TOKEN_KEYWORD_2015 (TYPE, "type") \ RS_TOKEN_KEYWORD_2015 (TYPEOF, "typeof") /* unused */ \ + RS_TOKEN_KEYWORD_2015 (UNDERSCORE, "_") \ RS_TOKEN_KEYWORD_2015 (UNSAFE, "unsafe") \ RS_TOKEN_KEYWORD_2015 (UNSIZED, "unsized") /* unused */ \ RS_TOKEN_KEYWORD_2015 (USE, "use") \ -- cgit v1.1 From ad2ff326cce7519587973c22e87288783e8f5e57 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Thu, 16 Nov 2023 13:11:33 +0100 Subject: gccrs: Add await keyword The 2018 edition await keyword was missing from the keyword list. gcc/rust/ChangeLog: * lex/rust-token.h (enum PrimitiveCoreType): Add await keyword definition. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/lex/rust-token.h | 1 + 1 file changed, 1 insertion(+) diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h index 401452f..e38c3cf 100644 --- a/gcc/rust/lex/rust-token.h +++ b/gcc/rust/lex/rust-token.h @@ -150,6 +150,7 @@ enum PrimitiveCoreType RS_TOKEN_KEYWORD_2015 (AS, "as") \ RS_TOKEN_KEYWORD_2018 (ASYNC, "async") /* unused */ \ RS_TOKEN_KEYWORD_2015 (AUTO, "auto") \ + RS_TOKEN_KEYWORD_2018 (AWAIT, "await") \ RS_TOKEN_KEYWORD_2015 (BECOME, "become") /* unused */ \ RS_TOKEN_KEYWORD_2015 (BOX, "box") /* unused */ \ RS_TOKEN_KEYWORD_2015 (BREAK, "break") \ -- cgit v1.1 From f1c7ce7e185444f498f8cb17a3c0f813a83fe3f3 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Thu, 16 Nov 2023 13:41:46 +0100 Subject: gccrs: Replace some keyword raw values Raw values cannot be understood easily by most tools. This commit replace some raw values with their variable counterpart. gcc/rust/ChangeLog: * ast/rust-ast-collector.cc (TokenCollector::visit): Replace raw value with keyword call. * ast/rust-ast.h: Likewise. * parse/rust-parse-impl.h (Parser::parse_path_ident_segment): Likewise. (Parser::parse_macro_match_fragment): Likewise. (Parser::parse_extern_crate): Likewise. (Parser::parse_use_tree): Likewise. (Parser::parse_const_item): Likewise. (Parser::parse_literal_expr): Likewise. (Parser::parse_maybe_named_param): Likewise. (Parser::parse_pattern_no_alt): Likewise. (Parser::left_denotation): Likewise. (Parser::parse_path_in_expression_pratt): Likewise. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/ast/rust-ast-collector.cc | 13 +++++----- gcc/rust/ast/rust-ast.h | 24 +++++++++++++----- gcc/rust/parse/rust-parse-impl.h | 52 +++++++++++++++++++++----------------- 3 files changed, 53 insertions(+), 36 deletions(-) diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index 8f394e5..5b12875 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -17,6 +17,7 @@ // . #include "rust-ast-collector.h" #include "rust-item.h" +#include "rust-keyword-values.h" namespace Rust { namespace AST { @@ -461,11 +462,11 @@ TokenCollector::visit (Lifetime &lifetime) break; case Lifetime::LifetimeType::STATIC: push (Rust::Token::make_lifetime (lifetime.get_locus (), - std::move ("static"))); + Values::Keywords::STATIC_KW)); break; case Lifetime::LifetimeType::WILDCARD: - push ( - Rust::Token::make_lifetime (lifetime.get_locus (), std::move ("_"))); + push (Rust::Token::make_lifetime (lifetime.get_locus (), + Values::Keywords::UNDERSCORE)); break; } } @@ -787,9 +788,9 @@ TokenCollector::visit (Literal &lit, location_t locus) lit.get_type_hint ())); break; case Literal::LitType::BOOL: { - if (value == "false") + if (value == Values::Keywords::FALSE_LITERAL) push (Rust::Token::make (FALSE_LITERAL, locus)); - else if (value == "true") + else if (value == Values::Keywords::TRUE_LITERAL) push (Rust::Token::make (TRUE_LITERAL, locus)); else rust_unreachable (); // Not a boolean @@ -1484,7 +1485,7 @@ TokenCollector::visit (AwaitExpr &expr) visit (expr.get_awaited_expr ()); push (Rust::Token::make (DOT, expr.get_locus ())); // TODO: Check status of await keyword (Context dependant ?) - push (Rust::Token::make_identifier (UNDEF_LOCATION, "await")); + push (Rust::Token::make_identifier (UNDEF_LOCATION, Values::Keywords::AWAIT)); } void diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 47c02d6..4049e4d 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -25,6 +25,7 @@ #include "rust-token.h" #include "rust-location.h" #include "rust-diagnostics.h" +#include "rust-keyword-values.h" namespace Rust { // TODO: remove typedefs and make actual types for these @@ -393,14 +394,20 @@ public: const std::string &get_segment_name () const { return segment_name; } bool is_super_path_seg () const { - return as_string ().compare ("super") == 0; + return as_string ().compare (Values::Keywords::SUPER) == 0; } bool is_crate_path_seg () const { - return as_string ().compare ("crate") == 0; + return as_string ().compare (Values::Keywords::CRATE) == 0; + } + bool is_lower_self_seg () const + { + return as_string ().compare (Values::Keywords::SELF) == 0; + } + bool is_big_self () const + { + return as_string ().compare (Values::Keywords::SELF_ALIAS) == 0; } - bool is_lower_self_seg () const { return as_string ().compare ("self") == 0; } - bool is_big_self () const { return as_string ().compare ("Self") == 0; } }; // A simple path without generic or type arguments @@ -562,7 +569,8 @@ public: location_t crate_vis_location) { return Visibility (PUB_CRATE, - SimplePath::from_str ("crate", crate_tok_location), + SimplePath::from_str (Values::Keywords::CRATE, + crate_tok_location), crate_vis_location); } @@ -571,7 +579,8 @@ public: location_t self_vis_location) { return Visibility (PUB_SELF, - SimplePath::from_str ("self", self_tok_location), + SimplePath::from_str (Values::Keywords::SELF, + self_tok_location), self_vis_location); } @@ -580,7 +589,8 @@ public: location_t super_vis_location) { return Visibility (PUB_SUPER, - SimplePath::from_str ("super", super_tok_location), + SimplePath::from_str (Values::Keywords::SUPER, + super_tok_location), super_vis_location); } diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 8b00614..2865906 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -743,19 +743,20 @@ Parser::parse_path_ident_segment () case SUPER: lexer.skip_token (); - return AST::PathIdentSegment ("super", t->get_locus ()); + return AST::PathIdentSegment (Values::Keywords::SUPER, t->get_locus ()); case SELF: lexer.skip_token (); - return AST::PathIdentSegment ("self", t->get_locus ()); + return AST::PathIdentSegment (Values::Keywords::SELF, t->get_locus ()); case SELF_ALIAS: lexer.skip_token (); - return AST::PathIdentSegment ("Self", t->get_locus ()); + return AST::PathIdentSegment (Values::Keywords::SELF_ALIAS, + t->get_locus ()); case CRATE: lexer.skip_token (); - return AST::PathIdentSegment ("crate", t->get_locus ()); + return AST::PathIdentSegment (Values::Keywords::CRATE, t->get_locus ()); case DOLLAR_SIGN: if (lexer.peek_token (1)->get_id () == CRATE) { @@ -2141,7 +2142,7 @@ Parser::parse_macro_match_fragment () Identifier ident; auto identifier = lexer.peek_token (); if (identifier->get_id () == UNDERSCORE) - ident = {"_", identifier->get_locus ()}; + ident = {Values::Keywords::UNDERSCORE, identifier->get_locus ()}; else ident = {identifier}; @@ -2506,7 +2507,7 @@ Parser::parse_extern_crate (AST::Visibility vis, lexer.skip_token (); break; case SELF: - crate_name = "self"; + crate_name = Values::Keywords::SELF; lexer.skip_token (); break; default: @@ -2547,7 +2548,7 @@ Parser::parse_extern_crate (AST::Visibility vis, lexer.skip_token (); break; case UNDERSCORE: - as_name = "_"; + as_name = Values::Keywords::UNDERSCORE; lexer.skip_token (); break; default: @@ -2806,7 +2807,8 @@ Parser::parse_use_tree () return std::unique_ptr ( new AST::UseTreeRebind (AST::UseTreeRebind::WILDCARD, std::move (path), locus, - {"_", t->get_locus ()})); + {Values::Keywords::UNDERSCORE, + t->get_locus ()})); default: add_error (Error ( t->get_locus (), @@ -4788,7 +4790,7 @@ Parser::parse_const_item (AST::Visibility vis, * wildcard */ const_TokenPtr ident_tok = lexer.peek_token (); // make default identifier the underscore wildcard one - std::string ident ("_"); + std::string ident (Values::Keywords::UNDERSCORE); switch (ident_tok->get_id ()) { case IDENTIFIER: @@ -7640,12 +7642,12 @@ Parser::parse_literal_expr (AST::AttrVec outer_attrs) // use true and false keywords rather than "bool literal" Rust terminology case TRUE_LITERAL: type = AST::Literal::BOOL; - literal_value = "true"; + literal_value = Values::Keywords::TRUE_LITERAL; lexer.skip_token (); break; case FALSE_LITERAL: type = AST::Literal::BOOL; - literal_value = "false"; + literal_value = Values::Keywords::FALSE_LITERAL; lexer.skip_token (); break; default: @@ -9654,7 +9656,7 @@ Parser::parse_maybe_named_param (AST::AttrVec outer_attrs) else if (current->get_id () == UNDERSCORE && next->get_id () == COLON) { // wildcard param - name = {"_", current->get_locus ()}; + name = {Values::Keywords::UNDERSCORE, current->get_locus ()}; kind = AST::MaybeNamedParam::WILDCARD; lexer.skip_token (1); } @@ -10548,12 +10550,14 @@ Parser::parse_pattern_no_alt () case TRUE_LITERAL: lexer.skip_token (); return std::unique_ptr ( - new AST::LiteralPattern ("true", AST::Literal::BOOL, t->get_locus (), + new AST::LiteralPattern (Values::Keywords::TRUE_LITERAL, + AST::Literal::BOOL, t->get_locus (), t->get_type_hint ())); case FALSE_LITERAL: lexer.skip_token (); return std::unique_ptr ( - new AST::LiteralPattern ("false", AST::Literal::BOOL, t->get_locus (), + new AST::LiteralPattern (Values::Keywords::FALSE_LITERAL, + AST::Literal::BOOL, t->get_locus (), t->get_type_hint ())); case CHAR_LITERAL: case BYTE_CHAR_LITERAL: @@ -12383,12 +12387,14 @@ Parser::null_denotation_not_path ( tok->get_type_hint (), {}, tok->get_locus ())); case TRUE_LITERAL: return std::unique_ptr ( - new AST::LiteralExpr ("true", AST::Literal::BOOL, tok->get_type_hint (), - {}, tok->get_locus ())); + new AST::LiteralExpr (Values::Keywords::TRUE_LITERAL, + AST::Literal::BOOL, tok->get_type_hint (), {}, + tok->get_locus ())); case FALSE_LITERAL: return std::unique_ptr ( - new AST::LiteralExpr ("false", AST::Literal::BOOL, - tok->get_type_hint (), {}, tok->get_locus ())); + new AST::LiteralExpr (Values::Keywords::FALSE_LITERAL, + AST::Literal::BOOL, tok->get_type_hint (), {}, + tok->get_locus ())); case LEFT_PAREN: return parse_grouped_or_tuple_expr (std::move (outer_attrs), tok->get_locus ()); @@ -12877,7 +12883,7 @@ Parser::left_denotation (const_TokenPtr tok, const_TokenPtr next_tok = lexer.peek_token (); if (next_tok->get_id () == IDENTIFIER - && next_tok->get_str () == "await") + && next_tok->get_str () == Values::Keywords::AWAIT) { // await expression return parse_await_expr (tok, std::move (left), @@ -14367,16 +14373,16 @@ Parser::parse_path_in_expression_pratt (const_TokenPtr tok) initial_str = tok->get_str (); break; case SUPER: - initial_str = "super"; + initial_str = Values::Keywords::SUPER; break; case SELF: - initial_str = "self"; + initial_str = Values::Keywords::SELF; break; case SELF_ALIAS: - initial_str = "Self"; + initial_str = Values::Keywords::SELF_ALIAS; break; case CRATE: - initial_str = "crate"; + initial_str = Values::Keywords::CRATE; break; case DOLLAR_SIGN: if (lexer.peek_token ()->get_id () == CRATE) -- cgit v1.1 From 2fe5baf3dc1a563834b696b0aa63b68cffd27b56 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Thu, 16 Nov 2023 15:02:11 +0100 Subject: gccrs: Add a list of weak keyword Retrieving a weak keyword value is done using raw values. Introducing a list of weak keywords means this could change. gcc/rust/ChangeLog: * util/rust-keyword-values.h (class WeakKeywords): Add new class with weak keyword constexpr. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/util/rust-keyword-values.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/gcc/rust/util/rust-keyword-values.h b/gcc/rust/util/rust-keyword-values.h index 769b210..4a6f1df 100644 --- a/gcc/rust/util/rust-keyword-values.h +++ b/gcc/rust/util/rust-keyword-values.h @@ -41,6 +41,20 @@ public: #undef RS_TOKEN }; +class WeakKeywords +{ +public: + static constexpr auto &AUTO = "auto"; + static constexpr auto &BUILTIN = "builtin"; + static constexpr auto &CATCH = "catch"; + static constexpr auto &DEFAULT = "default"; + static constexpr auto &GEN = "gen"; + static constexpr auto &MACRO_RULES = "macro_rules"; + static constexpr auto &RAW = "raw"; + static constexpr auto &UNION = "union"; + static constexpr auto &YEET = "yeet"; +}; + } // namespace Values } // namespace Rust -- cgit v1.1 From 28652f21e5560123c658d3e11d638957cb344641 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Thu, 16 Nov 2023 15:18:41 +0100 Subject: gccrs: Replace some weak keyword raw value with constexpr Raw values may have typos or contain error, replacing those will improve the codebase. gcc/rust/ChangeLog: * ast/rust-ast-collector.cc (TokenCollector::visit): Replace raw value. * parse/rust-parse-impl.h (Parser::is_macro_rules_def): Likewise. (Parser::parse_item): Likewise. (Parser::parse_vis_item): Likewise. (Parser::parse_macro_rules_def): Likewise. (Parser::parse_union): Likewise. (Parser::parse_trait_impl_item): Likewise. (Parser::parse_stmt): Likewise. (Parser::parse_stmt_or_expr): Likewise. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/ast/rust-ast-collector.cc | 6 ++++-- gcc/rust/parse/rust-parse-impl.h | 24 +++++++++++++----------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index 5b12875..3e3a959 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -1875,7 +1875,8 @@ TokenCollector::visit (Union &union_item) { visit_items_as_lines (union_item.get_outer_attrs ()); auto id = union_item.get_identifier ().as_string (); - push (Rust::Token::make_identifier (union_item.get_locus (), "union")); + push (Rust::Token::make_identifier (union_item.get_locus (), + Values::WeakKeywords::UNION)); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); if (union_item.has_generics ()) @@ -2256,7 +2257,8 @@ TokenCollector::visit (MacroRulesDefinition &rules_def) auto rule_name = rules_def.get_rule_name ().as_string (); - push (Rust::Token::make_identifier (rules_def.get_locus (), "macro_rules")); + push (Rust::Token::make_identifier (rules_def.get_locus (), + Values::WeakKeywords::MACRO_RULES)); push (Rust::Token::make (EXCLAM, UNDEF_LOCATION)); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (rule_name))); diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 2865906..37eddc1 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -1085,7 +1085,7 @@ Parser::is_macro_rules_def (const_TokenPtr t) bool allowed_macro_name = (macro_name == IDENTIFIER || macro_name == TRY); - return t->get_str () == "macro_rules" + return t->get_str () == Values::WeakKeywords::MACRO_RULES && lexer.peek_token (1)->get_id () == EXCLAM && allowed_macro_name; } @@ -1146,13 +1146,13 @@ Parser::parse_item (bool called_from_statement) // crappy hack to do union "keyword" case IDENTIFIER: // TODO: ensure std::string and literal comparison works - if (t->get_str () == "union" + if (t->get_str () == Values::WeakKeywords::UNION && lexer.peek_token (1)->get_id () == IDENTIFIER) { return parse_vis_item (std::move (outer_attrs)); // or should this go straight to parsing union? } - else if (t->get_str () == "default" + else if (t->get_str () == Values::WeakKeywords::DEFAULT && lexer.peek_token (1)->get_id () != EXCLAM) { add_error (Error (t->get_locus (), @@ -1357,7 +1357,7 @@ Parser::parse_vis_item (AST::AttrVec outer_attrs) // TODO: implement union keyword but not really because of // context-dependence case UNION: crappy hack to do union "keyword" case IDENTIFIER: - if (t->get_str () == "union" + if (t->get_str () == Values::WeakKeywords::UNION && lexer.peek_token (1)->get_id () == IDENTIFIER) { return parse_union (std::move (vis), std::move (outer_attrs)); @@ -1436,7 +1436,8 @@ Parser::parse_macro_rules_def (AST::AttrVec outer_attrs) { // ensure that first token is identifier saying "macro_rules" const_TokenPtr t = lexer.peek_token (); - if (t->get_id () != IDENTIFIER || t->get_str () != "macro_rules") + if (t->get_id () != IDENTIFIER + || t->get_str () != Values::WeakKeywords::MACRO_RULES) { Error error ( t->get_locus (), @@ -4734,7 +4735,7 @@ Parser::parse_union (AST::Visibility vis, /* hack - "weak keyword" by finding identifier called "union" (lookahead in * item switch) */ const_TokenPtr union_keyword = expect_token (IDENTIFIER); - rust_assert (union_keyword->get_str () == "union"); + rust_assert (union_keyword->get_str () == Values::WeakKeywords::UNION); location_t locus = union_keyword->get_locus (); // parse actual union name @@ -5715,7 +5716,7 @@ Parser::parse_trait_impl_item () // semi return parse_macro_invocation_semi (std::move (outer_attrs)); case IDENTIFIER: - if (lexer.peek_token ()->get_str () == "default") + if (lexer.peek_token ()->get_str () == Values::WeakKeywords::DEFAULT) return parse_trait_impl_function_or_method (visibility, std::move (outer_attrs)); else @@ -5779,7 +5780,8 @@ Parser::parse_trait_impl_function_or_method ( auto is_default = false; auto t = lexer.peek_token (); - if (t->get_id () == IDENTIFIER && t->get_str () == "default") + if (t->get_id () == IDENTIFIER + && t->get_str () == Values::WeakKeywords::DEFAULT) { is_default = true; lexer.skip_token (); @@ -6300,7 +6302,7 @@ Parser::parse_stmt (ParseRestrictions restrictions) break; // crappy hack to do union "keyword" case IDENTIFIER: - if (t->get_str () == "union" + if (t->get_str () == Values::WeakKeywords::UNION && lexer.peek_token (1)->get_id () == IDENTIFIER) { return parse_vis_item (std::move (outer_attrs)); @@ -11704,7 +11706,7 @@ Parser::parse_stmt_or_expr () // crappy hack to do union "keyword" case IDENTIFIER: - if (t->get_str () == "union" + if (t->get_str () == Values::WeakKeywords::UNION && lexer.peek_token (1)->get_id () == IDENTIFIER) { std::unique_ptr item ( @@ -11712,7 +11714,7 @@ Parser::parse_stmt_or_expr () return ExprOrStmt (std::move (item)); // or should this go straight to parsing union? } - else if (t->get_str () == "macro_rules" + else if (t->get_str () == Values::WeakKeywords::MACRO_RULES && lexer.peek_token (1)->get_id () == EXCLAM) { // macro_rules! macro item -- cgit v1.1 From 2c843a047dd3c596b4daabe247e52e1d6475e4d6 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Thu, 16 Nov 2023 16:20:49 +0100 Subject: gccrs: Introduce a proper keyword list The old "keyword" list was used for the lexer, and could therefore not be used with keyword spanning over multiple tokens as those tokens should remain lexed as is. Hence the introduction of a new list macro for keyword exclusive tasks. This also means we can no longer match a token id for each keyword. The token id map has been renamed to keep it's properties. gcc/rust/ChangeLog: * lex/rust-lex.cc (Lexer::classify_keyword): Update keyword map name. * lex/rust-token.h (enum PrimitiveCoreType): Remove some deprecated comments. * util/rust-keyword-values.cc (get_keywords): Update the keyword map name. (RS_TOKEN): Define as empty (RS_TOKEN_KEYWORD_2015): Add the emission value. (RS_TOKEN_KEYWORD_2018): Likewise. * util/rust-keyword-values.h (RS_KEYWORD_LIST): Introduce the keyword list. (RS_TOKEN_KEYWORD_2018): Define multiple new keywords. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/lex/rust-lex.cc | 2 +- gcc/rust/lex/rust-token.h | 2 -- gcc/rust/util/rust-keyword-values.cc | 13 ++++++++++++- gcc/rust/util/rust-keyword-values.h | 13 +++++++++++-- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc index 2d41c11..5bff2d9 100644 --- a/gcc/rust/lex/rust-lex.cc +++ b/gcc/rust/lex/rust-lex.cc @@ -260,7 +260,7 @@ Lexer::replace_current_token (TokenPtr replacement) TokenId Lexer::classify_keyword (const std::string &str) { - auto &keywords = Rust::Values::Keywords::keywords; + auto &keywords = Rust::Values::Keywords::keywords_tokens; auto keyword = keywords.find (str); if (keyword == keywords.end ()) diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h index e38c3cf..438b29b 100644 --- a/gcc/rust/lex/rust-token.h +++ b/gcc/rust/lex/rust-token.h @@ -145,7 +145,6 @@ enum PrimitiveCoreType /* Doc Comments */ \ RS_TOKEN (INNER_DOC_COMMENT, "#![doc]") \ RS_TOKEN (OUTER_DOC_COMMENT, "#[doc]") \ - /* have "weak" union and 'static keywords? */ \ RS_TOKEN_KEYWORD_2015 (ABSTRACT, "abstract") /* unused */ \ RS_TOKEN_KEYWORD_2015 (AS, "as") \ RS_TOKEN_KEYWORD_2018 (ASYNC, "async") /* unused */ \ @@ -157,7 +156,6 @@ enum PrimitiveCoreType RS_TOKEN_KEYWORD_2015 (CONST, "const") \ RS_TOKEN_KEYWORD_2015 (CONTINUE, "continue") \ RS_TOKEN_KEYWORD_2015 (CRATE, "crate") \ - /* FIXME: Do we need to add $crate (DOLLAR_CRATE) as a reserved kw? */ \ RS_TOKEN_KEYWORD_2015 (DO, "do") /* unused */ \ RS_TOKEN_KEYWORD_2018 (DYN, "dyn") \ RS_TOKEN_KEYWORD_2015 (ELSE, "else") \ diff --git a/gcc/rust/util/rust-keyword-values.cc b/gcc/rust/util/rust-keyword-values.cc index 8aa5ef1..9e1d2bc 100644 --- a/gcc/rust/util/rust-keyword-values.cc +++ b/gcc/rust/util/rust-keyword-values.cc @@ -38,7 +38,18 @@ get_keywords () return m; } -const std::map Keywords::keywords = get_keywords (); +const std::map Keywords::keywords_tokens + = get_keywords (); + +const std::set Keywords::keywords = { +#define RS_TOKEN(x, y) +#define RS_TOKEN_KEYWORD_2015(tok, key) {key}, +#define RS_TOKEN_KEYWORD_2018 RS_TOKEN_KEYWORD_2015 + RS_KEYWORD_LIST +#undef RS_TOKEN_KEYWORD_2015 +#undef RS_TOKEN_KEYWORD_2018 +#undef RS_TOKEN +}; } // namespace Values } // namespace Rust diff --git a/gcc/rust/util/rust-keyword-values.h b/gcc/rust/util/rust-keyword-values.h index 4a6f1df..01c98a2 100644 --- a/gcc/rust/util/rust-keyword-values.h +++ b/gcc/rust/util/rust-keyword-values.h @@ -21,6 +21,14 @@ #include "rust-token.h" +// Append keywords made from multiple tokens to the existing token-keyword list +#define RS_KEYWORD_LIST \ + RS_TOKEN_LIST \ + RS_TOKEN_KEYWORD_2015 (DOLLAR_CRATE, "$crate") \ + RS_TOKEN_KEYWORD_2015 (PATH_ROOT, "{{root}}") \ + RS_TOKEN_KEYWORD_2015 (STATIC_LIFETIME, "'static") \ + RS_TOKEN_KEYWORD_2015 (UNDERSCORE_LIFETIME, "'_") + namespace Rust { namespace Values { @@ -28,14 +36,15 @@ namespace Values { class Keywords { public: - const static std::map keywords; + const static std::map keywords_tokens; + const static std::set keywords; // Rust keyword values public: #define RS_TOKEN(x, y) #define RS_TOKEN_KEYWORD_2015(tok, key) static constexpr auto &tok = key; #define RS_TOKEN_KEYWORD_2018 RS_TOKEN_KEYWORD_2015 - RS_TOKEN_LIST + RS_KEYWORD_LIST #undef RS_TOKEN_KEYWORD_2015 #undef RS_TOKEN_KEYWORD_2018 #undef RS_TOKEN -- cgit v1.1 From d5c582396c66e9e0499ecee67129f1ff1dd55889 Mon Sep 17 00:00:00 2001 From: M V V S Manoj Kumar Date: Tue, 21 Nov 2023 22:04:24 +0530 Subject: gccrs: Added support to Parse ASYNC function Fixes issue #2650 The parser now parses ASYNC functions. Added ASYNC case to parse_item Added a new function parse_async_item which is called in parse_vis_item to handle the ASYNC case. Parse_async_item also checks the current Rust edition and generates an error if the edition is 2015 gcc/rust/ChangeLog: * parse/rust-parse-impl.h (Parser::parse_item): Likewise. (Parser::parse_vis_item): Likewise. (Parser::parse_async_item): Likewise. * parse/rust-parse.h: Made declaration for parse_async_item. gcc/testsuite/ChangeLog: * rust/compile/issue-2650-1.rs: New test.(edition=2018) * rust/compile/issue-2650-2.rs: New test.(edition=2015) Signed-off-by: M V V S Manoj Kumar --- gcc/rust/parse/rust-parse-impl.h | 40 ++++++++++++++++++++++++++++++ gcc/rust/parse/rust-parse.h | 2 ++ gcc/testsuite/rust/compile/issue-2650-1.rs | 5 ++++ gcc/testsuite/rust/compile/issue-2650-2.rs | 5 ++++ 4 files changed, 52 insertions(+) create mode 100644 gcc/testsuite/rust/compile/issue-2650-1.rs create mode 100644 gcc/testsuite/rust/compile/issue-2650-2.rs diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 37eddc1..53b3839 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -30,6 +30,7 @@ #include "rust-dir-owner.h" #include "rust-attribute-values.h" #include "rust-keyword-values.h" +#include "rust-session-manager.h" #include "optional.h" @@ -1113,6 +1114,8 @@ Parser::parse_item (bool called_from_statement) add_error (std::move (error)); } return nullptr; + + case ASYNC: case PUB: case MOD: case EXTERN_KW: @@ -1389,6 +1392,10 @@ Parser::parse_vis_item (AST::AttrVec outer_attrs) lexer.skip_token (1); // TODO: is this right thing to do? return nullptr; } + // for async functions + case ASYNC: + return parse_async_item (std::move (vis), std::move (outer_attrs)); + case STATIC_KW: return parse_static_item (std::move (vis), std::move (outer_attrs)); case AUTO: @@ -1429,6 +1436,39 @@ Parser::parse_vis_item (AST::AttrVec outer_attrs) return nullptr; } +template +std::unique_ptr +Parser::parse_async_item (AST::Visibility vis, + AST::AttrVec outer_attrs) +{ + const_TokenPtr t = lexer.peek_token (); + if (Session::get_instance ().options.get_edition () + == CompileOptions::Edition::E2015) + { + add_error (Error (t->get_locus (), ErrorCode::E0670, + "% is not permitted in Rust 2015")); + add_error ( + Error::Hint (t->get_locus (), + "to use %, switch to Rust 2018 or later")); + } + + t = lexer.peek_token (1); + + switch (t->get_id ()) + { + case UNSAFE: + case FN_KW: + return parse_function (std::move (vis), std::move (outer_attrs)); + + default: + add_error ( + Error (t->get_locus (), "expected item, found keyword %")); + + lexer.skip_token (1); + return nullptr; + } +} + // Parses a macro rules definition syntax extension whatever thing. template std::unique_ptr diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index e873d52..d371846 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -357,6 +357,8 @@ private: std::unique_ptr parse_extern_block (AST::Visibility vis, AST::AttrVec outer_attrs); std::unique_ptr parse_method (); + std::unique_ptr parse_async_item (AST::Visibility vis, + AST::AttrVec outer_attrs); // Expression-related (Pratt parsed) std::unique_ptr diff --git a/gcc/testsuite/rust/compile/issue-2650-1.rs b/gcc/testsuite/rust/compile/issue-2650-1.rs new file mode 100644 index 0000000..381398e --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-2650-1.rs @@ -0,0 +1,5 @@ +// { dg-additional-options "-frust-edition=2018" } + +pub async fn a() -> u32 { + 1 +} diff --git a/gcc/testsuite/rust/compile/issue-2650-2.rs b/gcc/testsuite/rust/compile/issue-2650-2.rs new file mode 100644 index 0000000..5132e6e --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-2650-2.rs @@ -0,0 +1,5 @@ +// { dg-additional-options "-frust-edition=2015" } + +pub async fn a() -> u32 { // { dg-error "'async fn' is not permitted in Rust 2015" } + 1 +} -- cgit v1.1 From d9b7a3d0f4ebb0c4874ef8f680c875f5e19a0923 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 17 Aug 2023 14:07:27 +0200 Subject: gccrs: ctx: Add Labels ForeverStack to the resolver. Not sure if dealing with "labels" is the proper way of doing so, so we might eventually change this to use `resolver.values` later on. gcc/rust/ChangeLog: * resolve/rust-name-resolution-context.h: Add a Labels stack. --- gcc/rust/resolve/rust-name-resolution-context.h | 1 + 1 file changed, 1 insertion(+) diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h index 64db5d1..6d14be3 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.h +++ b/gcc/rust/resolve/rust-name-resolution-context.h @@ -173,6 +173,7 @@ public: ForeverStack values; ForeverStack types; ForeverStack macros; + ForeverStack labels; }; } // namespace Resolver2_0 -- cgit v1.1 From f726875f9785d8d2d8255437d25373d5eceddbf3 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Fri, 23 Jun 2023 16:37:51 +0200 Subject: gccrs: nr2.0: Add base for late name resolution gcc/rust/ChangeLog: * Make-lang.in: Compile late name resolver. * resolve/rust-late-name-resolver-2.0.cc: New file. * resolve/rust-late-name-resolver-2.0.h: New file. --- gcc/rust/Make-lang.in | 1 + gcc/rust/resolve/rust-late-name-resolver-2.0.cc | 105 ++++++++++++++++++++++++ gcc/rust/resolve/rust-late-name-resolver-2.0.h | 57 +++++++++++++ 3 files changed, 163 insertions(+) create mode 100644 gcc/rust/resolve/rust-late-name-resolver-2.0.cc create mode 100644 gcc/rust/resolve/rust-late-name-resolver-2.0.h diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index f2cadd5..47cc877 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -116,6 +116,7 @@ GRS_OBJS = \ rust/rust-default-resolver.o \ rust/rust-toplevel-name-resolver-2.0.o \ rust/rust-early-name-resolver-2.0.o \ + rust/rust-late-name-resolver-2.0.o \ rust/rust-early-name-resolver.o \ rust/rust-name-resolver.o \ rust/rust-ast-resolve.o \ diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc new file mode 100644 index 0000000..352d59b --- /dev/null +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -0,0 +1,105 @@ +// Copyright (C) 2020-2023 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 +// . + +#include "rust-ast-full.h" +#include "rust-late-name-resolver-2.0.h" +#include "rust-default-resolver.h" + +namespace Rust { +namespace Resolver2_0 { + +Late::Late (NameResolutionContext &ctx) : DefaultResolver (ctx) {} + +void +Late::go (AST::Crate &crate) +{ + for (auto &item : crate.items) + item->accept_vis (*this); +} + +void +Late::new_label (Identifier name, NodeId id) +{ + // labels can always shadow, so `insert` should never fail. if it does, we're + // in big trouble! + auto ok = ctx.labels.insert (name, id); + + rust_assert (ok); +} + +void +Late::visit (AST::LetStmt &let) +{ + // so we don't need that method + DefaultResolver::visit (let); + + // how do we deal with the fact that `let a = blipbloup` should look for a + // label and cannot go through function ribs, but `let a = blipbloup()` can? + + // how do we insert ribs here, and only pop them when we exit the current + // function? + // keep a list of ribs to pop when a scope exits? so only for blocks? + // how do we pop ribs that need to be popped not in order? + // I think it's not important if we have shadowing, correct? + + // if we have shadowing, it should work! we'll see + + // ctx.insert(Identifier name, NodeId id, Namespace ns) + // ctx.scoped (Rib::Kind::Normal /* FIXME: Is that valid? */, + // Namespace::Labels, + // let.get_node_id (), [] () {}); +} + +void +Late::visit (AST::IdentifierPattern &identifier) +{ + // do we insert in labels or in values + // but values does not allow shadowing... since functions cannot shadow + // do we insert functions in labels as well? + new_label (identifier.get_ident (), identifier.get_node_id ()); +} + +void +Late::visit (AST::IdentifierExpr &expr) +{ + // TODO: same thing as visit(PathInExpression) here? + + auto label = ctx.labels.get (expr.get_ident ()); + auto value = ctx.values.get (expr.get_ident ()); + + rust_debug ("[ARTHUR] label: %d", label ? *label : -1); + rust_debug ("[ARTHUR] value: %d", value ? *value : -1); +} + +void +Late::visit (AST::PathInExpression &expr) +{ + // TODO: How do we have a nice error with `can't capture dynamic environment + // in a function item` error here? + // do we emit it in `get`? + + auto label = ctx.labels.resolve_path (expr.get_segments ()); + + auto value = ctx.values.resolve_path (expr.get_segments ()); + + rust_debug ("[ARTHUR] label: %d", label ? *label : -1); + rust_debug ("[ARTHUR] value: %d", value ? *value : -1); +} + +} // namespace Resolver2_0 +} // namespace Rust diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h b/gcc/rust/resolve/rust-late-name-resolver-2.0.h new file mode 100644 index 0000000..12540c0 --- /dev/null +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h @@ -0,0 +1,57 @@ +// Copyright (C) 2020-2023 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_LATE_NAME_RESOLVER_2_0_H +#define RUST_LATE_NAME_RESOLVER_2_0_H + +#include "rust-ast-full.h" +#include "rust-default-resolver.h" + +namespace Rust { +namespace Resolver2_0 { + +class Late : public DefaultResolver +{ + using DefaultResolver::visit; + +public: + Late (NameResolutionContext &ctx); + + void go (AST::Crate &crate); + + void new_label (Identifier name, NodeId id); + + // some more label declarations + void visit (AST::LetStmt &) override; + // TODO: Do we need this? + // void visit (AST::Method &) override; + void visit (AST::IdentifierPattern &) override; + + // resolutions + void visit (AST::IdentifierExpr &) override; + void visit (AST::PathInExpression &) override; + +private: +}; + +// TODO: Add missing mappings and data structures + +} // namespace Resolver2_0 +} // namespace Rust + +#endif // ! RUST_LATE_NAME_RESOLVER_2_0_H -- cgit v1.1 From 1ee01fd1572b46324c72d2380bedc58dfddd469d Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Wed, 15 Nov 2023 11:33:25 +0100 Subject: gccrs: toplevel: Use DefaultResolver for Function gcc/rust/ChangeLog: * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit): Use the DefaultResolver in the toplevel visitor. --- gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc index fc62db7..fbded3e 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -185,10 +185,7 @@ TopLevel::visit (AST::Function &function) insert_or_error_out (function.get_function_name (), function, Namespace::Values); - auto def_fn - = [this, &function] () { function.get_definition ()->accept_vis (*this); }; - - ctx.scoped (Rib::Kind::Function, function.get_node_id (), def_fn); + DefaultResolver::visit (function); } void -- cgit v1.1 From cb3a12f3ee26de1f51d9c900d4056fc4bcf6974f Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 22 Aug 2023 15:40:25 +0200 Subject: gccrs: nr2.0: Store mappings in NameResolutionContext gcc/rust/ChangeLog: * resolve/rust-name-resolution-context.h: Store a reference to the mappings. * resolve/rust-name-resolution-context.cc (NameResolutionContext::NameResolutionContext): Likewise. --- gcc/rust/resolve/rust-name-resolution-context.cc | 4 ++++ gcc/rust/resolve/rust-name-resolution-context.h | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/gcc/rust/resolve/rust-name-resolution-context.cc b/gcc/rust/resolve/rust-name-resolution-context.cc index 82771cd..8bb7a9a 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.cc +++ b/gcc/rust/resolve/rust-name-resolution-context.cc @@ -21,6 +21,10 @@ namespace Rust { namespace Resolver2_0 { +NameResolutionContext::NameResolutionContext () + : mappings (*Analysis::Mappings::get ()) +{} + tl::expected NameResolutionContext::insert (Identifier name, NodeId id, Namespace ns) { diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h index 6d14be3..d63ee33 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.h +++ b/gcc/rust/resolve/rust-name-resolution-context.h @@ -21,6 +21,7 @@ #include "optional.h" #include "rust-forever-stack.h" +#include "rust-hir-map.h" namespace Rust { namespace Resolver2_0 { @@ -136,6 +137,8 @@ correct class NameResolutionContext { public: + NameResolutionContext (); + /** * Insert a new value in the current rib. * @@ -174,6 +177,8 @@ public: ForeverStack types; ForeverStack macros; ForeverStack labels; + + Analysis::Mappings &mappings; }; } // namespace Resolver2_0 -- cgit v1.1 From df6eadda5ef181525fc013e7ded9ca0761929c2e Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 22 Aug 2023 16:58:28 +0200 Subject: gccrs: late: Start setting up builtin types gcc/rust/ChangeLog: * resolve/rust-late-name-resolver-2.0.cc (Late::setup_builtin_types): New function. (Late::go): Setup builtin types. * resolve/rust-late-name-resolver-2.0.h: * resolve/rust-name-resolution-context.cc (NameResolutionContext::map_usage): New function. * resolve/rust-name-resolution-context.h: Likewise. --- gcc/rust/resolve/rust-late-name-resolver-2.0.cc | 42 ++++++++++++++++++++++++ gcc/rust/resolve/rust-late-name-resolver-2.0.h | 2 ++ gcc/rust/resolve/rust-name-resolution-context.cc | 9 +++++ gcc/rust/resolve/rust-name-resolution-context.h | 8 ++++- 4 files changed, 60 insertions(+), 1 deletion(-) diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index 352d59b..3236886 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -16,9 +16,12 @@ // along with GCC; see the file COPYING3. If not see // . +#include "optional.h" #include "rust-ast-full.h" #include "rust-late-name-resolver-2.0.h" #include "rust-default-resolver.h" +#include "rust-tyty.h" +#include "rust-hir-type-check.h" namespace Rust { namespace Resolver2_0 { @@ -26,8 +29,47 @@ namespace Resolver2_0 { Late::Late (NameResolutionContext &ctx) : DefaultResolver (ctx) {} void +Late::setup_builtin_types () +{ + auto next_id = [this] () { return ctx.mappings.get_next_hir_id (); }; + + static const std::pair builtins[] = { + {"u8", new TyTy::UintType (next_id (), TyTy::UintType::U8)}, + {"u16", new TyTy::UintType (next_id (), TyTy::UintType::U16)}, + {"u32", new TyTy::UintType (next_id (), TyTy::UintType::U32)}, + {"u64", new TyTy::UintType (next_id (), TyTy::UintType::U64)}, + {"u128", new TyTy::UintType (next_id (), TyTy::UintType::U128)}, + {"i8", new TyTy::IntType (next_id (), TyTy::IntType::I8)}, + {"i16", new TyTy::IntType (next_id (), TyTy::IntType::I16)}, + {"i32", new TyTy::IntType (next_id (), TyTy::IntType::I32)}, + {"i64", new TyTy::IntType (next_id (), TyTy::IntType::I64)}, + {"i128", new TyTy::IntType (next_id (), TyTy::IntType::I128)}, + {"f32", new TyTy::FloatType (next_id (), TyTy::FloatType::F32)}, + {"f64", new TyTy::FloatType (next_id (), TyTy::FloatType::F64)}, + {"usize", new TyTy::USizeType (next_id ())}, + {"isize", new TyTy::ISizeType (next_id ())}, + // missing char, str, never, () + // does name resolution play a part for this? or is it all at typechecking? + // yeah it seems to be name resolution as well, which makes sense + }; + + for (const auto &builtin : builtins) + { + // we should be able to use `insert_at_root` or `insert` here, since we're + // at the root :) hopefully! + auto ok + = ctx.types.insert (builtin.first, builtin.second->get_ref () + /* FIXME: Invalid! This returns an *HirId* */); + + rust_assert (ok); + } +} + +void Late::go (AST::Crate &crate) { + setup_builtin_types (); + for (auto &item : crate.items) item->accept_vis (*this); } diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h b/gcc/rust/resolve/rust-late-name-resolver-2.0.h index 12540c0..f54bbf2 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h @@ -47,6 +47,8 @@ public: void visit (AST::PathInExpression &) override; private: + /* Setup Rust's builtin types (u8, i32, !...) in the resolver */ + void setup_builtin_types (); }; // TODO: Add missing mappings and data structures diff --git a/gcc/rust/resolve/rust-name-resolution-context.cc b/gcc/rust/resolve/rust-name-resolution-context.cc index 8bb7a9a..f71ef91 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.cc +++ b/gcc/rust/resolve/rust-name-resolution-context.cc @@ -44,6 +44,15 @@ NameResolutionContext::insert (Identifier name, NodeId id, Namespace ns) } void +NameResolutionContext::map_usage (NodeId usage, NodeId definition) +{ + auto inserted = resolved_nodes.emplace (usage, definition).second; + + // is that valid? + rust_assert (inserted); +} + +void NameResolutionContext::scoped (Rib rib, NodeId id, std::function lambda, tl::optional path) diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h index d63ee33..7a19245 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.h +++ b/gcc/rust/resolve/rust-name-resolution-context.h @@ -19,7 +19,6 @@ #ifndef RUST_NAME_RESOLVER_2_0_H #define RUST_NAME_RESOLVER_2_0_H -#include "optional.h" #include "rust-forever-stack.h" #include "rust-hir-map.h" @@ -179,6 +178,13 @@ public: ForeverStack labels; Analysis::Mappings &mappings; + + // TODO: Rename + void map_usage (NodeId usage, NodeId definition); + +private: + /* Map of "usage" nodes which have been resolved to a "definition" node */ + std::map resolved_nodes; }; } // namespace Resolver2_0 -- cgit v1.1 From 0f0ec052b4ad1fb7250a5ad1ec00d276fdc29a09 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 22 Aug 2023 17:29:05 +0200 Subject: gccrs: late: Start storing mappings properly in the resolver gcc/rust/ChangeLog: * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Store mappings after having resolved them. * resolve/rust-late-name-resolver-2.0.h: Add `TypePath` visitor. --- gcc/rust/resolve/rust-late-name-resolver-2.0.cc | 33 +++++++++++++++++++++---- gcc/rust/resolve/rust-late-name-resolver-2.0.h | 1 + 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index 3236886..5f70f57 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -20,6 +20,7 @@ #include "rust-ast-full.h" #include "rust-late-name-resolver-2.0.h" #include "rust-default-resolver.h" +#include "rust-path.h" #include "rust-tyty.h" #include "rust-hir-type-check.h" @@ -121,11 +122,24 @@ Late::visit (AST::IdentifierExpr &expr) { // TODO: same thing as visit(PathInExpression) here? + tl::optional resolved = tl::nullopt; auto label = ctx.labels.get (expr.get_ident ()); auto value = ctx.values.get (expr.get_ident ()); - rust_debug ("[ARTHUR] label: %d", label ? *label : -1); - rust_debug ("[ARTHUR] value: %d", value ? *value : -1); + if (label) + resolved = label; + else if (value) + resolved = value; + // TODO: else emit error? + + ctx.map_usage (expr.get_node_id (), *resolved); + + // in the old resolver, resolutions are kept in the resolver, not the mappings + // :/ how do we deal with that? + // ctx.mappings.insert_resolved_name(expr, resolved); + + // For empty types, do we perform a lookup in ctx.types or should the + // toplevel instead insert a name in ctx.values? (like it currently does) } void @@ -136,11 +150,20 @@ Late::visit (AST::PathInExpression &expr) // do we emit it in `get`? auto label = ctx.labels.resolve_path (expr.get_segments ()); - auto value = ctx.values.resolve_path (expr.get_segments ()); +} + +void +Late::visit (AST::TypePath &type) +{ + // should we add type path resolution in `ForeverStack` directly? Since it's + // quite more complicated. + // maybe we can overload `resolve_path` to only do + // typepath-like path resolution? that sounds good + + auto resolved = ctx.types.get (type.get_segments ().back ()->as_string ()); - rust_debug ("[ARTHUR] label: %d", label ? *label : -1); - rust_debug ("[ARTHUR] value: %d", value ? *value : -1); + ctx.map_usage (type.get_node_id (), *resolved); } } // namespace Resolver2_0 diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h b/gcc/rust/resolve/rust-late-name-resolver-2.0.h index f54bbf2..15940d0 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h @@ -45,6 +45,7 @@ public: // resolutions void visit (AST::IdentifierExpr &) override; void visit (AST::PathInExpression &) override; + void visit (AST::TypePath &) override; private: /* Setup Rust's builtin types (u8, i32, !...) in the resolver */ -- cgit v1.1 From 53d979f361f214ead438c62d74a9adb2c4383651 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Mon, 21 Aug 2023 16:52:48 +0200 Subject: gccrs: early: Resolve paths properly gcc/rust/ChangeLog: * resolve/rust-early-name-resolver-2.0.cc (Early::insert_once): New function. (Early::visit): Likewise. * resolve/rust-early-name-resolver-2.0.h: Likewise. --- gcc/rust/resolve/rust-early-name-resolver-2.0.cc | 30 ++++++++++++++++++++++++ gcc/rust/resolve/rust-early-name-resolver-2.0.h | 10 ++++++++ 2 files changed, 40 insertions(+) diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc index 2245ba3..48bb4c6 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc @@ -27,6 +27,33 @@ namespace Resolver2_0 { Early::Early (NameResolutionContext &ctx) : DefaultResolver (ctx) {} void +Early::insert_once (AST::MacroInvocation &invocation, NodeId resolved) +{ + // TODO: Should we use `ctx.mark_resolved()`? + AST::MacroRulesDefinition *definition; + auto ok = ctx.mappings.lookup_macro_def (resolved, &definition); + + rust_assert (ok); + + AST::MacroRulesDefinition *existing; + auto exists = ctx.mappings.lookup_macro_invocation (invocation, &existing); + + if (!exists) + ctx.mappings.insert_macro_invocation (invocation, definition); +} + +void +Early::insert_once (AST::MacroRulesDefinition &def) +{ + // TODO: Should we use `ctx.mark_resolved()`? + AST::MacroRulesDefinition *definition; + auto exists = ctx.mappings.lookup_macro_def (def.get_node_id (), &definition); + + if (!exists) + ctx.mappings.insert_macro_def (&def); +} + +void Early::go (AST::Crate &crate) { // First we go through TopLevel resolution to get all our declared items @@ -89,6 +116,7 @@ Early::visit (AST::MacroRulesDefinition &def) DefaultResolver::visit (def); textual_scope.insert (def.get_rule_name ().as_string (), def.get_node_id ()); + insert_once (def); } void @@ -141,6 +169,8 @@ Early::visit (AST::MacroInvocation &invoc) return; } + insert_once (invoc, *definition); + // now do we need to keep mappings or something? or insert "uses" into our // ForeverStack? can we do that? are mappings simpler? auto mappings = Analysis::Mappings::get (); diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.h b/gcc/rust/resolve/rust-early-name-resolver-2.0.h index dc27319..46c4b93 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.h @@ -61,6 +61,16 @@ private: void visit_attributes (std::vector &attrs); /** + * Insert a resolved macro invocation into the mappings once, meaning that we + * can call this function each time the early name resolution pass is underway + * and it will not trigger assertions for already resolved invocations. + */ + // TODO: Rename + void insert_once (AST::MacroInvocation &invocation, NodeId resolved); + // TODO: Rename + void insert_once (AST::MacroRulesDefinition &definition); + + /** * Macros can either be resolved through textual scoping or regular path * scoping - which this class represents. Textual scoping works similarly to a * "simple" name resolution algorith, with the addition of "shadowing". Each -- cgit v1.1 From 0a5cc7a4cb2d379f17f75491fae8428dec901e1c Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Tue, 22 Aug 2023 17:29:56 +0200 Subject: gccrs: toplevel: Add comment about running the collector twice gcc/rust/ChangeLog: * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::insert_or_error_out): Add documentation comment. (TopLevel::go): Likewise. --- gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc index fbded3e..b9d0bc7 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -43,6 +43,9 @@ TopLevel::insert_or_error_out (const Identifier &identifier, const T &node, if (!result) { + // can we do something like check if the node id is the same? if it is the + // same, it's not an error, just the resolver running multiple times? + rich_location rich_loc (line_table, loc); rich_loc.add_range (node_locations[result.error ().existing]); @@ -54,6 +57,11 @@ TopLevel::insert_or_error_out (const Identifier &identifier, const T &node, void TopLevel::go (AST::Crate &crate) { + // we do not include builtin types in the top-level definition collector, as + // they are not used until `Late`. furthermore, we run this visitor multiple + // times in a row in a fixed-point fashion, so it would make the code + // responsible for this ugly and perfom a lot of error checking. + for (auto &item : crate.items) item->accept_vis (*this); } -- cgit v1.1 From 1133c1c671d91243b54dd5f6d2fed658ce1f8d9a Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Wed, 23 Aug 2023 13:49:24 +0200 Subject: gccrs: ast: Add NodeId to UseTree base class gcc/rust/ChangeLog: * ast/rust-item.h (class UseTree): Add `node_id` member. --- gcc/rust/ast/rust-item.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 2c0e459..3480d12 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -940,6 +940,7 @@ protected: class UseTree { location_t locus; + NodeId node_id; public: enum Kind @@ -975,6 +976,7 @@ public: virtual Kind get_kind () const = 0; location_t get_locus () const { return locus; } + NodeId get_node_id () const { return node_id; } virtual void accept_vis (ASTVisitor &vis) = 0; @@ -982,7 +984,9 @@ protected: // Clone function implementation as pure virtual method virtual UseTree *clone_use_tree_impl () const = 0; - UseTree (location_t locus) : locus (locus) {} + UseTree (location_t locus) + : locus (locus), node_id (Analysis::Mappings::get ()->get_next_node_id ()) + {} }; // Use tree with a glob (wildcard) operator @@ -1182,7 +1186,7 @@ public: Kind get_kind () const override { return Rebind; } - SimplePath get_path () const + const SimplePath &get_path () const { rust_assert (has_path ()); return path; -- cgit v1.1 From 17da301e2aef5f6617341e461826f096d56145c0 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Wed, 23 Aug 2023 13:50:54 +0200 Subject: gccrs: early: Move `use` declaration resolving to TopLevel gcc/rust/ChangeLog: * resolve/rust-early-name-resolver-2.0.cc (Early::visit): Remove visitors. * resolve/rust-early-name-resolver-2.0.h: Likewise. --- gcc/rust/resolve/rust-early-name-resolver-2.0.cc | 16 ---------------- gcc/rust/resolve/rust-early-name-resolver-2.0.h | 5 +---- 2 files changed, 1 insertion(+), 20 deletions(-) diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc index 48bb4c6..a5d5b19 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc @@ -189,22 +189,6 @@ Early::visit (AST::MacroInvocation &invoc) } void -Early::visit (AST::UseDeclaration &use) -{} - -void -Early::visit (AST::UseTreeRebind &use) -{} - -void -Early::visit (AST::UseTreeList &use) -{} - -void -Early::visit (AST::UseTreeGlob &use) -{} - -void Early::visit_attributes (std::vector &attrs) { auto mappings = Analysis::Mappings::get (); diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.h b/gcc/rust/resolve/rust-early-name-resolver-2.0.h index 46c4b93..d9f985f 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.h @@ -50,10 +50,7 @@ public: void visit (AST::Module &) override; void visit (AST::MacroInvocation &) override; - void visit (AST::UseDeclaration &) override; - void visit (AST::UseTreeRebind &) override; - void visit (AST::UseTreeList &) override; - void visit (AST::UseTreeGlob &) override; + void visit (AST::Function &) override; void visit (AST::StructStruct &) override; -- cgit v1.1 From 8fa748692cfbe08e658236fbe69d1b06f2f0b5af Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Wed, 23 Aug 2023 13:51:06 +0200 Subject: gccrs: toplevel: Resolve `use` declarations gcc/rust/ChangeLog: * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::insert_or_error_out): New functions. (TopLevel::handle_use_dec): New function. (flatten_rebind): Likewise. (flatten_list): Likewise. (flatten_glob): Likewise. (flatten): Likewise. (TopLevel::visit): Visit various `use` declaration nodes. * resolve/rust-toplevel-name-resolver-2.0.h: Declare functions and visitors. --- .../resolve/rust-toplevel-name-resolver-2.0.cc | 187 ++++++++++++++++++++- gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h | 11 ++ 2 files changed, 194 insertions(+), 4 deletions(-) diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc index b9d0bc7..46113a8 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -17,6 +17,7 @@ // . #include "rust-toplevel-name-resolver-2.0.h" +#include "optional.h" #include "rust-ast-full.h" #include "rust-hir-map.h" #include "rust-attribute-values.h" @@ -33,11 +34,16 @@ void TopLevel::insert_or_error_out (const Identifier &identifier, const T &node, Namespace ns) { - auto loc = node.get_locus (); - auto node_id = node.get_node_id (); + insert_or_error_out (identifier, node.get_locus (), node.get_node_id (), ns); +} +void +TopLevel::insert_or_error_out (const Identifier &identifier, + const location_t &locus, const NodeId &node_id, + Namespace ns) +{ // keep track of each node's location to provide useful errors - node_locations.emplace (node_id, loc); + node_locations.emplace (node_id, locus); auto result = ctx.insert (identifier, node_id, ns); @@ -46,7 +52,7 @@ TopLevel::insert_or_error_out (const Identifier &identifier, const T &node, // can we do something like check if the node id is the same? if it is the // same, it's not an error, just the resolver running multiple times? - rich_location rich_loc (line_table, loc); + rich_location rich_loc (line_table, locus); rich_loc.add_range (node_locations[result.error ().existing]); rust_error_at (rich_loc, ErrorCode::E0428, "%qs defined multiple times", @@ -308,5 +314,178 @@ TopLevel::visit (AST::ConstantItem &const_item) ctx.scoped (Rib::Kind::ConstantItem, const_item.get_node_id (), expr_vis); } +bool +TopLevel::handle_use_dec (AST::SimplePath path) +{ + // TODO: Glob imports can get shadowed by regular imports and regular items. + // So we need to store them in a specific way in the ForeverStack - which can + // also probably be used by labels and macros etc. Like store it as a + // `Shadowable(NodeId)` instead of just a `NodeId` + + auto locus = path.get_final_segment ().get_locus (); + auto declared_name = path.get_final_segment ().as_string (); + + // in what namespace do we perform path resolution? All of them? see which one + // matches? Error out on ambiguities? + // so, apparently, for each one that matches, add it to the proper namespace + // :( + + auto found = false; + + auto resolve_and_insert = [this, &found, &declared_name, + locus] (Namespace ns, + const AST::SimplePath &path) { + tl::optional resolved = tl::nullopt; + + // FIXME: resolve_path needs to return an `expected` so + // that we can improve it with hints or location or w/ever. and maybe + // only emit it the first time. + switch (ns) + { + case Namespace::Values: + resolved = ctx.values.resolve_path (path.get_segments ()); + break; + case Namespace::Types: + resolved = ctx.types.resolve_path (path.get_segments ()); + break; + case Namespace::Macros: + resolved = ctx.macros.resolve_path (path.get_segments ()); + break; + case Namespace::Labels: + // TODO: Is that okay? + rust_unreachable (); + } + + // FIXME: Ugly + (void) resolved.map ([this, &found, &declared_name, locus, ns] (NodeId id) { + found = true; + + // what do we do with the id? + insert_or_error_out (declared_name, locus, id, ns); + + return id; + }); + }; + + // do this for all namespaces (even Labels?) + + resolve_and_insert (Namespace::Values, path); + resolve_and_insert (Namespace::Types, path); + resolve_and_insert (Namespace::Macros, path); + + // TODO: No labels? No, right? + + return found; +} + +static void +flatten_rebind (const AST::UseTreeRebind &glob, + std::vector &paths); +static void +flatten_list (const AST::UseTreeList &glob, + std::vector &paths); +static void +flatten_glob (const AST::UseTreeGlob &glob, + std::vector &paths); + +static void +flatten (const AST::UseTree *tree, std::vector &paths) +{ + switch (tree->get_kind ()) + { + case AST::UseTree::Rebind: { + auto rebind = static_cast (tree); + flatten_rebind (*rebind, paths); + break; + } + case AST::UseTree::List: { + auto list = static_cast (tree); + flatten_list (*list, paths); + break; + } + case AST::UseTree::Glob: { + rust_sorry_at (tree->get_locus (), "cannot resolve glob imports yet"); + auto glob = static_cast (tree); + flatten_glob (*glob, paths); + break; + } + break; + } +} + +static void +flatten_rebind (const AST::UseTreeRebind &rebind, + std::vector &paths) +{ + auto path = rebind.get_path (); + + // FIXME: Do we want to emplace the rebind here as well? + if (rebind.has_identifier ()) + { + auto rebind_path = path; + auto new_seg = rebind.get_identifier (); + + // Add the identifier as a new path + rebind_path.get_segments ().back () + = AST::SimplePathSegment (new_seg.as_string (), UNDEF_LOCATION); + + paths.emplace_back (rebind_path); + } + else + { + paths.emplace_back (path); + } +} + +static void +flatten_list (const AST::UseTreeList &list, std::vector &paths) +{ + auto prefix = AST::SimplePath::create_empty (); + if (list.has_path ()) + prefix = list.get_path (); + + for (const auto &tree : list.get_trees ()) + { + auto sub_paths = std::vector (); + flatten (tree.get (), sub_paths); + + for (auto &sub_path : sub_paths) + { + auto new_path = prefix; + std::copy (sub_path.get_segments ().begin (), + sub_path.get_segments ().end (), + std::back_inserter (new_path.get_segments ())); + + paths.emplace_back (new_path); + } + } +} + +static void +flatten_glob (const AST::UseTreeGlob &glob, std::vector &paths) +{ + if (glob.has_path ()) + paths.emplace_back (glob.get_path ()); +} + +void +TopLevel::visit (AST::UseDeclaration &use) +{ + auto paths = std::vector (); + + // FIXME: How do we handle `use foo::{self}` imports? Some beforehand cleanup? + // How do we handle module imports in general? Should they get added to all + // namespaces? + + const auto &tree = use.get_tree (); + flatten (tree.get (), paths); + + for (auto &path : paths) + if (!handle_use_dec (path)) + rust_error_at (path.get_final_segment ().get_locus (), ErrorCode::E0433, + "could not resolve import %qs", + path.as_string ().c_str ()); +} + } // namespace Resolver2_0 } // namespace Rust diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h index 95187d7..996899b 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h @@ -53,6 +53,9 @@ private: template void insert_or_error_out (const Identifier &identifier, const T &node, Namespace ns); + void insert_or_error_out (const Identifier &identifier, + const location_t &locus, const NodeId &id, + Namespace ns); // FIXME: Do we move these to our mappings? std::unordered_map node_locations; @@ -73,6 +76,14 @@ private: void visit (AST::Union &union_item) override; void visit (AST::ConstantItem &const_item) override; void visit (AST::ExternCrate &crate) override; + + // FIXME: Documentation + // Call this on all the paths of a UseDec - so each flattened path in a + // UseTreeList for example + // FIXME: Should that return `found`? + bool handle_use_dec (AST::SimplePath path); + + void visit (AST::UseDeclaration &use) override; }; } // namespace Resolver2_0 -- cgit v1.1 From b71668068b1d7bf912fc345252bbc5f9ed6d3927 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Tue, 3 Oct 2023 17:50:14 -0400 Subject: gccrs: Create base class for TupleStructItems and TuplePatternItems gcc/rust/ChangeLog: * hir/tree/rust-hir-pattern.h (class TupleItems): New. (class TupleStructItems): Inherit from TupleItems. (class TuplePatternItems): Likewise. Signed-off-by: Owen Avery --- gcc/rust/hir/tree/rust-hir-pattern.h | 47 ++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/gcc/rust/hir/tree/rust-hir-pattern.h b/gcc/rust/hir/tree/rust-hir-pattern.h index 33025bf..e65a62f 100644 --- a/gcc/rust/hir/tree/rust-hir-pattern.h +++ b/gcc/rust/hir/tree/rust-hir-pattern.h @@ -777,8 +777,8 @@ protected: } }; -// Base abstract class for patterns used in TupleStructPattern -class TupleStructItems : public FullVisitable +// Base abstract class for TupleStructItems and TuplePatternItems +class TupleItems : public FullVisitable { public: enum ItemType @@ -787,25 +787,38 @@ public: RANGED, }; - virtual ~TupleStructItems () {} + virtual ~TupleItems () {} // TODO: should this store location data? // Unique pointer custom clone function - std::unique_ptr clone_tuple_struct_items () const + std::unique_ptr clone_tuple_items () const { - return std::unique_ptr (clone_tuple_items_impl ()); + return std::unique_ptr (clone_tuple_items_impl ()); } + virtual ItemType get_item_type () const = 0; + virtual std::string as_string () const = 0; - virtual void accept_vis (HIRFullVisitor &vis) = 0; +protected: + // pure virtual clone implementation + virtual TupleItems *clone_tuple_items_impl () const = 0; +}; - virtual ItemType get_item_type () const = 0; +// Base abstract class for patterns used in TupleStructPattern +class TupleStructItems : public TupleItems +{ +public: + // Unique pointer custom clone function + std::unique_ptr clone_tuple_struct_items () const + { + return std::unique_ptr (clone_tuple_items_impl ()); + } protected: // pure virtual clone implementation - virtual TupleStructItems *clone_tuple_items_impl () const = 0; + virtual TupleStructItems *clone_tuple_items_impl () const override = 0; }; // Class for non-ranged tuple struct pattern patterns @@ -1011,32 +1024,18 @@ protected: }; // Base abstract class representing TuplePattern patterns -class TuplePatternItems : public FullVisitable +class TuplePatternItems : public TupleItems { public: - enum ItemType - { - MULTIPLE, - RANGED, - }; - - virtual ~TuplePatternItems () {} - - // TODO: should this store location data? - // Unique pointer custom clone function std::unique_ptr clone_tuple_pattern_items () const { return std::unique_ptr (clone_tuple_items_impl ()); } - virtual std::string as_string () const = 0; - - virtual ItemType get_item_type () const = 0; - protected: // pure virtual clone implementation - virtual TuplePatternItems *clone_tuple_items_impl () const = 0; + virtual TuplePatternItems *clone_tuple_items_impl () const override = 0; }; // Class representing TuplePattern patterns where there are multiple patterns -- cgit v1.1 From 7a4c2f8e43fca4e18e821fc2df24b6949d09be36 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Tue, 21 Nov 2023 17:56:10 +0100 Subject: gccrs: Add unsafety member to modules The rust syntax allows unsafe module even if those are rejected at a later stage. gcc/rust/ChangeLog: * ast/rust-item.h: Add safety status to Modules in the AST. * parse/rust-parse-impl.h (Parser::parse_module): Adapt constructors. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/ast/rust-item.h | 13 ++++++++----- gcc/rust/parse/rust-parse-impl.h | 8 +++++--- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 3480d12..6c3715e 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -736,6 +736,7 @@ private: Identifier module_name; location_t locus; ModuleKind kind; + Unsafety safety; // Name of the file including the module std::string outer_filename; @@ -766,11 +767,12 @@ public: // Unloaded module constructor Module (Identifier module_name, Visibility visibility, - std::vector outer_attrs, location_t locus, + std::vector outer_attrs, location_t locus, Unsafety safety, std::string outer_filename, std::vector module_scope) : VisItem (std::move (visibility), std::move (outer_attrs)), module_name (module_name), locus (locus), kind (ModuleKind::UNLOADED), - outer_filename (outer_filename), inner_attrs (std::vector ()), + safety (safety), outer_filename (outer_filename), + inner_attrs (std::vector ()), items (std::vector> ()), module_scope (std::move (module_scope)) {} @@ -779,18 +781,19 @@ public: Module (Identifier name, location_t locus, std::vector> items, Visibility visibility = Visibility::create_error (), + Unsafety safety = Unsafety::Normal, std::vector inner_attrs = std::vector (), std::vector outer_attrs = std::vector ()) : VisItem (std::move (visibility), std::move (outer_attrs)), module_name (name), locus (locus), kind (ModuleKind::LOADED), - outer_filename (std::string ()), inner_attrs (std::move (inner_attrs)), - items (std::move (items)) + safety (safety), outer_filename (std::string ()), + inner_attrs (std::move (inner_attrs)), items (std::move (items)) {} // Copy constructor with vector clone Module (Module const &other) : VisItem (other), module_name (other.module_name), locus (other.locus), - kind (other.kind), inner_attrs (other.inner_attrs), + kind (other.kind), safety (other.safety), inner_attrs (other.inner_attrs), module_scope (other.module_scope) { // We need to check whether we are copying a loaded module or an unloaded diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 53b3839..2e24a66 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -22,6 +22,7 @@ /* DO NOT INCLUDE ANYWHERE - this is automatically included with rust-parse.h * This is also the reason why there are no include guards. */ +#include "rust-common.h" #include "rust-item.h" #include "rust-token.h" #define INCLUDE_ALGORITHM @@ -2446,8 +2447,8 @@ Parser::parse_module (AST::Visibility vis, // Construct an external module return std::unique_ptr ( new AST::Module (std::move (name), std::move (vis), - std::move (outer_attrs), locus, lexer.get_filename (), - inline_module_stack)); + std::move (outer_attrs), locus, Unsafety::Normal, + lexer.get_filename (), inline_module_stack)); case LEFT_CURLY: { lexer.skip_token (); @@ -2503,7 +2504,8 @@ Parser::parse_module (AST::Visibility vis, return std::unique_ptr ( new AST::Module (std::move (name), locus, std::move (items), - std::move (vis), std::move (inner_attrs), + std::move (vis), Unsafety::Normal, + std::move (inner_attrs), std::move (outer_attrs))); // module name? } default: -- cgit v1.1 From d6a0d96559b30ffac3dba5be675272f0d8e12a1e Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Tue, 21 Nov 2023 18:28:30 +0100 Subject: gccrs: Parse module safety Unsafe module are rejected at a later stage but could not be parsed properly. This commit changes the parser in order to allow unsafe module in the AST. gcc/rust/ChangeLog: * parse/rust-parse-impl.h (Parser::parse_vis_item): Dispatch to parse module when meeting an unsafe module. (Parser::parse_module): Set unsafe status when the parser encounter an unsafe keyword. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/parse/rust-parse-impl.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 2e24a66..8087e0c 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -1418,6 +1418,8 @@ Parser::parse_vis_item (AST::AttrVec outer_attrs) return parse_function (std::move (vis), std::move (outer_attrs)); case IMPL: return parse_impl (std::move (vis), std::move (outer_attrs)); + case MOD: + return parse_module (std::move (vis), std::move (outer_attrs)); default: add_error ( Error (t->get_locus (), @@ -2427,6 +2429,13 @@ std::unique_ptr Parser::parse_module (AST::Visibility vis, AST::AttrVec outer_attrs) { + Unsafety safety = Unsafety::Normal; + if (lexer.peek_token ()->get_id () == UNSAFE) + { + safety = Unsafety::Unsafe; + skip_token (UNSAFE); + } + location_t locus = lexer.peek_token ()->get_locus (); skip_token (MOD); @@ -2447,7 +2456,7 @@ Parser::parse_module (AST::Visibility vis, // Construct an external module return std::unique_ptr ( new AST::Module (std::move (name), std::move (vis), - std::move (outer_attrs), locus, Unsafety::Normal, + std::move (outer_attrs), locus, safety, lexer.get_filename (), inline_module_stack)); case LEFT_CURLY: { lexer.skip_token (); @@ -2504,8 +2513,7 @@ Parser::parse_module (AST::Visibility vis, return std::unique_ptr ( new AST::Module (std::move (name), locus, std::move (items), - std::move (vis), Unsafety::Normal, - std::move (inner_attrs), + std::move (vis), safety, std::move (inner_attrs), std::move (outer_attrs))); // module name? } default: -- cgit v1.1 From 5959f32d28ff76b3e9c177914f034aae72c9a835 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Tue, 21 Nov 2023 18:51:21 +0100 Subject: gccrs: Emit an error on unsafe modules An error should be emitted on unsafe modules during the AST validation pass as the syntax allows those even though they're not alowed later down the line. gcc/rust/ChangeLog: * ast/rust-item.h: Add safety getter to modules. * checks/errors/rust-ast-validation.cc (ASTValidation::visit): Check a module's safety and emit an error when meeting an unsafe module. * checks/errors/rust-ast-validation.h: Add function prototype. * parse/rust-parse-impl.h (Parser::parse_module): Move the module locus to the first token instead of the mod keyword. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/ast/rust-item.h | 2 ++ gcc/rust/checks/errors/rust-ast-validation.cc | 10 ++++++++++ gcc/rust/checks/errors/rust-ast-validation.h | 1 + gcc/rust/parse/rust-parse-impl.h | 3 ++- 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 6c3715e..3bf023b 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -840,6 +840,8 @@ public: // Returns the kind of the module enum ModuleKind get_kind () const { return kind; } + Unsafety get_unsafety () const { return safety; } + // TODO: think of better way to do this - mutable getter seems dodgy const std::vector &get_inner_attrs () const { return inner_attrs; } std::vector &get_inner_attrs () { return inner_attrs; } diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc index dad7f5e..4b20990 100644 --- a/gcc/rust/checks/errors/rust-ast-validation.cc +++ b/gcc/rust/checks/errors/rust-ast-validation.cc @@ -17,6 +17,7 @@ // . #include "rust-ast-validation.h" +#include "rust-common.h" #include "rust-diagnostics.h" #include "rust-item.h" #include "rust-keyword-values.h" @@ -136,4 +137,13 @@ ASTValidation::visit (AST::Trait &trait) AST::ContextualASTVisitor::visit (trait); } +void +ASTValidation::visit (AST::Module &module) +{ + if (module.get_unsafety () == Unsafety::Unsafe) + rust_error_at (module.get_locus (), "module cannot be declared unsafe"); + + AST::ContextualASTVisitor::visit (module); +} + } // namespace Rust diff --git a/gcc/rust/checks/errors/rust-ast-validation.h b/gcc/rust/checks/errors/rust-ast-validation.h index 1052168..01d923c 100644 --- a/gcc/rust/checks/errors/rust-ast-validation.h +++ b/gcc/rust/checks/errors/rust-ast-validation.h @@ -34,6 +34,7 @@ public: void check (AST::Crate &crate) { AST::ContextualASTVisitor::visit (crate); } + virtual void visit (AST::Module &module); virtual void visit (AST::ConstantItem &const_item); virtual void visit (AST::Lifetime &lifetime); virtual void visit (AST::LoopLabel &label); diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 8087e0c..f83cc12 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -2429,6 +2429,8 @@ std::unique_ptr Parser::parse_module (AST::Visibility vis, AST::AttrVec outer_attrs) { + location_t locus = lexer.peek_token ()->get_locus (); + Unsafety safety = Unsafety::Normal; if (lexer.peek_token ()->get_id () == UNSAFE) { @@ -2436,7 +2438,6 @@ Parser::parse_module (AST::Visibility vis, skip_token (UNSAFE); } - location_t locus = lexer.peek_token ()->get_locus (); skip_token (MOD); const_TokenPtr module_name = expect_token (IDENTIFIER); -- cgit v1.1 From 088e3b0b7af1b6a38057c8717227867831d00c5e Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Tue, 21 Nov 2023 19:34:36 +0100 Subject: gccrs: Add a regression test for unsafe module validation Add a new test to check for unsafe modules during AST validation pass. gcc/testsuite/ChangeLog: * rust/compile/unsafe_module.rs: New test. Signed-off-by: Pierre-Emmanuel Patry --- gcc/testsuite/rust/compile/unsafe_module.rs | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 gcc/testsuite/rust/compile/unsafe_module.rs diff --git a/gcc/testsuite/rust/compile/unsafe_module.rs b/gcc/testsuite/rust/compile/unsafe_module.rs new file mode 100644 index 0000000..74bc170 --- /dev/null +++ b/gcc/testsuite/rust/compile/unsafe_module.rs @@ -0,0 +1,2 @@ +unsafe mod toto {} +// { dg-error "module cannot be declared unsafe" "" { target *-*-* } .-1 } -- cgit v1.1 From b4fc851e3a01e708819ebfe1bfe4f2dc2ae9e5e7 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 2 Oct 2023 18:41:33 +0100 Subject: gccrs: Remove backend dependancy on resolution rib information When making more desugaring for the HIR we can need to add new Let bindings which will require namesolution information but also rib information for which block the let binding is associated which was very unnessecary. This patch simply updates the BLOCK_CONTEXT of the current scope as we are compiling and encounter HIR::LetStmts instead of trying to do it all upfront which lots of wierd checks gcc/rust/ChangeLog: * backend/rust-compile-base.cc (HIRCompileBase::compile_locals_for_block): removed * backend/rust-compile-base.h: update header * backend/rust-compile-block.cc (CompileBlock::visit): remove old logic * backend/rust-compile-expr.cc (CompileExpr::generate_closure_function): likewise * backend/rust-compile-stmt.cc (CompileStmt::visit): likewise * backend/rust-compile-var-decl.h: ensure we setup tuple bindings correctly Signed-off-by: Philip Herron --- gcc/rust/backend/rust-compile-base.cc | 51 +---------------------- gcc/rust/backend/rust-compile-base.h | 3 -- gcc/rust/backend/rust-compile-block.cc | 13 +----- gcc/rust/backend/rust-compile-expr.cc | 5 +-- gcc/rust/backend/rust-compile-stmt.cc | 16 ++++++-- gcc/rust/backend/rust-compile-var-decl.h | 69 +++++++++++++++++++++++++------- 6 files changed, 71 insertions(+), 86 deletions(-) diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc index ae9f670..fcab75b 100644 --- a/gcc/rust/backend/rust-compile-base.cc +++ b/gcc/rust/backend/rust-compile-base.cc @@ -564,35 +564,6 @@ HIRCompileBase::indirect_expression (tree expr, location_t locus) return build_fold_indirect_ref_loc (locus, expr); } -std::vector -HIRCompileBase::compile_locals_for_block (Context *ctx, Resolver::Rib &rib, - tree fndecl) -{ - std::vector locals; - for (auto it : rib.get_declarations ()) - { - NodeId node_id = it.first; - HirId ref = UNKNOWN_HIRID; - if (!ctx->get_mappings ()->lookup_node_to_hir (node_id, &ref)) - continue; - - // we only care about local patterns - HIR::Pattern *pattern = ctx->get_mappings ()->lookup_hir_pattern (ref); - if (pattern == nullptr) - continue; - - // lookup the type - TyTy::BaseType *tyty = nullptr; - if (!ctx->get_tyctx ()->lookup_type (ref, &tyty)) - continue; - - // compile the local - tree type = TyTyResolveCompile::compile (ctx, tyty); - CompileVarDecl::compile (fndecl, type, pattern, locals, ctx); - } - return locals; -} - void HIRCompileBase::compile_function_body (tree fndecl, HIR::BlockExpr &function_body, @@ -750,21 +721,11 @@ HIRCompileBase::compile_function ( if (!Backend::function_set_parameters (fndecl, param_vars)) return error_mark_node; - // lookup locals - auto body_mappings = function_body->get_mappings (); - Resolver::Rib *rib = nullptr; - bool ok - = ctx->get_resolver ()->find_name_rib (body_mappings.get_nodeid (), &rib); - rust_assert (ok); - - std::vector locals - = compile_locals_for_block (ctx, *rib, fndecl); - tree enclosing_scope = NULL_TREE; location_t start_location = function_body->get_locus (); location_t end_location = function_body->get_end_locus (); - tree code_block = Backend::block (fndecl, enclosing_scope, locals, + tree code_block = Backend::block (fndecl, enclosing_scope, {} /*locals*/, start_location, end_location); ctx->push_block (code_block); @@ -820,7 +781,6 @@ HIRCompileBase::compile_constant_item ( tree fndecl = Backend::function (compiled_fn_type, ident, "", 0, locus); TREE_READONLY (fndecl) = 1; - std::vector locals; tree enclosing_scope = NULL_TREE; location_t start_location = const_value_expr->get_locus (); location_t end_location = const_value_expr->get_locus (); @@ -830,16 +790,9 @@ HIRCompileBase::compile_constant_item ( = static_cast (const_value_expr); start_location = function_body->get_locus (); end_location = function_body->get_end_locus (); - - Resolver::Rib *rib = nullptr; - bool ok = ctx->get_resolver ()->find_name_rib ( - function_body->get_mappings ().get_nodeid (), &rib); - rust_assert (ok); - - locals = compile_locals_for_block (ctx, *rib, fndecl); } - tree code_block = Backend::block (fndecl, enclosing_scope, locals, + tree code_block = Backend::block (fndecl, enclosing_scope, {} /*locals*/, start_location, end_location); ctx->push_block (code_block); diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h index 6529123..c581658 100644 --- a/gcc/rust/backend/rust-compile-base.h +++ b/gcc/rust/backend/rust-compile-base.h @@ -145,9 +145,6 @@ protected: static bool mark_addressable (tree, location_t); - static std::vector - compile_locals_for_block (Context *ctx, Resolver::Rib &rib, tree fndecl); - static tree named_constant_expression (tree type_tree, const std::string &name, tree const_val, location_t location); diff --git a/gcc/rust/backend/rust-compile-block.cc b/gcc/rust/backend/rust-compile-block.cc index 83ecc67..10a7099 100644 --- a/gcc/rust/backend/rust-compile-block.cc +++ b/gcc/rust/backend/rust-compile-block.cc @@ -42,20 +42,9 @@ CompileBlock::visit (HIR::BlockExpr &expr) tree fndecl = fnctx.fndecl; location_t start_location = expr.get_locus (); location_t end_location = expr.get_end_locus (); - auto body_mappings = expr.get_mappings (); - - Resolver::Rib *rib = nullptr; - if (!ctx->get_resolver ()->find_name_rib (body_mappings.get_nodeid (), &rib)) - { - rust_fatal_error (expr.get_locus (), "failed to setup locals per block"); - return; - } - - std::vector locals - = compile_locals_for_block (ctx, *rib, fndecl); tree enclosing_scope = ctx->peek_enclosing_scope (); - tree new_block = Backend::block (fndecl, enclosing_scope, locals, + tree new_block = Backend::block (fndecl, enclosing_scope, {} /*locals*/, start_location, end_location); ctx->push_block (new_block); diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index 870ecab..e0917f6 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -2310,7 +2310,6 @@ CompileExpr::generate_closure_function (HIR::ClosureExpr &expr, bool is_block_expr = function_body->get_expression_type () == HIR::Expr::ExprType::Block; - std::vector locals = {}; if (is_block_expr) { auto body_mappings = function_body->get_mappings (); @@ -2319,8 +2318,6 @@ CompileExpr::generate_closure_function (HIR::ClosureExpr &expr, = ctx->get_resolver ()->find_name_rib (body_mappings.get_nodeid (), &rib); rust_assert (ok); - - locals = compile_locals_for_block (ctx, *rib, fndecl); } tree enclosing_scope = NULL_TREE; @@ -2333,7 +2330,7 @@ CompileExpr::generate_closure_function (HIR::ClosureExpr &expr, end_location = body->get_end_locus (); } - tree code_block = Backend::block (fndecl, enclosing_scope, locals, + tree code_block = Backend::block (fndecl, enclosing_scope, {} /*locals*/, start_location, end_location); ctx->push_block (code_block); diff --git a/gcc/rust/backend/rust-compile-stmt.cc b/gcc/rust/backend/rust-compile-stmt.cc index c006f4a..e7ba370 100644 --- a/gcc/rust/backend/rust-compile-stmt.cc +++ b/gcc/rust/backend/rust-compile-stmt.cc @@ -19,6 +19,8 @@ #include "rust-compile-pattern.h" #include "rust-compile-stmt.h" #include "rust-compile-expr.h" +#include "rust-compile-type.h" +#include "rust-compile-var-decl.h" namespace Rust { namespace Compile { @@ -44,10 +46,6 @@ CompileStmt::visit (HIR::ExprStmt &stmt) void CompileStmt::visit (HIR::LetStmt &stmt) { - // nothing to do - if (!stmt.has_init_expr ()) - return; - HIR::Pattern &stmt_pattern = *stmt.get_pattern (); HirId stmt_id = stmt_pattern.get_mappings ().get_hirid (); @@ -60,6 +58,16 @@ CompileStmt::visit (HIR::LetStmt &stmt) return; } + // setup var decl nodes + fncontext fnctx = ctx->peek_fn (); + tree fndecl = fnctx.fndecl; + tree translated_type = TyTyResolveCompile::compile (ctx, ty); + CompileVarDecl::compile (fndecl, translated_type, &stmt_pattern, ctx); + + // nothing to do + if (!stmt.has_init_expr ()) + return; + tree init = CompileExpr::Compile (stmt.get_init_expr ().get (), ctx); // FIXME use error_mark_node, check that CompileExpr returns error_mark_node // on failure and make this an assertion diff --git a/gcc/rust/backend/rust-compile-var-decl.h b/gcc/rust/backend/rust-compile-var-decl.h index 370e939..45ca01d 100644 --- a/gcc/rust/backend/rust-compile-var-decl.h +++ b/gcc/rust/backend/rust-compile-var-decl.h @@ -30,11 +30,12 @@ class CompileVarDecl : public HIRCompileBase, public HIR::HIRPatternVisitor using HIR::HIRPatternVisitor::visit; public: - static void compile (tree fndecl, tree translated_type, HIR::Pattern *pattern, - std::vector &locals, Context *ctx) + static std::vector compile (tree fndecl, tree translated_type, + HIR::Pattern *pattern, Context *ctx) { - CompileVarDecl compiler (ctx, fndecl, translated_type, locals); + CompileVarDecl compiler (ctx, fndecl, translated_type); pattern->accept_vis (compiler); + return compiler.vars; } void visit (HIR::IdentifierPattern &pattern) override @@ -42,15 +43,58 @@ public: if (!pattern.is_mut ()) translated_type = Backend::immutable_type (translated_type); - Bvariable *var - = Backend::local_variable (fndecl, pattern.get_identifier ().as_string (), - translated_type, NULL /*decl_var*/, - pattern.get_locus ()); + tree bind_tree = ctx->peek_enclosing_scope (); + std::string identifier = pattern.get_identifier ().as_string (); + tree decl + = build_decl (pattern.get_locus (), VAR_DECL, + Backend::get_identifier_node (identifier), translated_type); + DECL_CONTEXT (decl) = fndecl; + + gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR); + tree block_tree = BIND_EXPR_BLOCK (bind_tree); + gcc_assert (TREE_CODE (block_tree) == BLOCK); + DECL_CHAIN (decl) = BLOCK_VARS (block_tree); + BLOCK_VARS (block_tree) = decl; + BIND_EXPR_VARS (bind_tree) = BLOCK_VARS (block_tree); + + rust_preserve_from_gc (decl); + Bvariable *var = new Bvariable (decl); HirId stmt_id = pattern.get_mappings ().get_hirid (); ctx->insert_var_decl (stmt_id, var); - locals.push_back (var); + vars.push_back (var); + } + + void visit (HIR::TuplePattern &pattern) override + { + switch (pattern.get_items ()->get_item_type ()) + { + case HIR::TuplePatternItems::ItemType::MULTIPLE: { + rust_assert (TREE_CODE (translated_type) == RECORD_TYPE); + auto &items = static_cast ( + *pattern.get_items ()); + + size_t offs = 0; + for (auto &sub : items.get_patterns ()) + { + tree sub_ty = error_mark_node; + tree field = TYPE_FIELDS (translated_type); + for (size_t i = 0; i < offs; i++) + { + field = DECL_CHAIN (field); + gcc_assert (field != NULL_TREE); + } + sub_ty = TREE_TYPE (field); + CompileVarDecl::compile (fndecl, sub_ty, sub.get (), ctx); + offs++; + } + } + break; + + default: + break; + } } // Empty visit for unused Pattern HIR nodes. @@ -62,21 +106,18 @@ public: void visit (HIR::ReferencePattern &) override {} void visit (HIR::SlicePattern &) override {} void visit (HIR::StructPattern &) override {} - void visit (HIR::TuplePattern &) override {} void visit (HIR::TupleStructPattern &) override {} void visit (HIR::WildcardPattern &) override {} private: - CompileVarDecl (Context *ctx, tree fndecl, tree translated_type, - std::vector &locals) - : HIRCompileBase (ctx), fndecl (fndecl), translated_type (translated_type), - locals (locals) + CompileVarDecl (Context *ctx, tree fndecl, tree translated_type) + : HIRCompileBase (ctx), fndecl (fndecl), translated_type (translated_type) {} tree fndecl; tree translated_type; - std::vector &locals; + std::vector vars; }; } // namespace Compile -- cgit v1.1 From f84e564243915e729f22a5b6e4d1e4fb902f94f9 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Tue, 28 Nov 2023 01:07:00 -0500 Subject: gccrs: Remove class AST::InherentImplItem gcc/rust/ChangeLog: * ast/rust-ast-full-decls.h (class InherentImplItem): Remove. * ast/rust-ast.h (class InherentImplItem): Remove. (class SingleASTNode): Store pointer to AssociatedItem instead of InherentImplItem. * ast/rust-ast.cc (SingleASTNode::SingleASTNode): Use clone_associated_item instead of clone_inherent_impl_item. (SingleASTNode::operator=): Likewise. * ast/rust-item.h (class InherentImpl): Use AssociatedItem rather than InherentImplItem. (class Function): Likewise. (class ConstantItem): Likewise. * ast/rust-macro.h (class MacroInvocation): Likewise. * expand/rust-expand-visitor.cc (ExpandVisitor::visit): Likewise. * parse/rust-parse-impl.h (Parser::parse_impl): Likewise. (Parser::parse_inherent_impl_item): Likewise. (Parser::parse_inherent_impl_function_or_method): Likewise. * parse/rust-parse.h (Parser::parse_inherent_impl_item): Likewise. (Parser::parse_inherent_impl_function_or_method): Likewise. Signed-off-by: Owen Avery --- gcc/rust/ast/rust-ast-full-decls.h | 1 - gcc/rust/ast/rust-ast.cc | 4 ++-- gcc/rust/ast/rust-ast.h | 22 +++------------------- gcc/rust/ast/rust-item.h | 18 ++++++++++-------- gcc/rust/ast/rust-macro.h | 2 +- gcc/rust/expand/rust-expand-visitor.cc | 2 +- gcc/rust/parse/rust-parse-impl.h | 8 ++++---- gcc/rust/parse/rust-parse.h | 4 ++-- 8 files changed, 23 insertions(+), 38 deletions(-) diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h index e2d05ba..5bfaaa8 100644 --- a/gcc/rust/ast/rust-ast-full-decls.h +++ b/gcc/rust/ast/rust-ast-full-decls.h @@ -52,7 +52,6 @@ class GenericParam; class LifetimeParam; class ConstGenericParam; class TraitItem; -class InherentImplItem; class TraitImplItem; struct Crate; class PathExpr; diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index 43820d3..17f82d6 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -64,7 +64,7 @@ SingleASTNode::SingleASTNode (SingleASTNode const &other) break; case IMPL: - impl_item = other.impl_item->clone_inherent_impl_item (); + impl_item = other.impl_item->clone_associated_item (); break; case TRAIT_IMPL: @@ -104,7 +104,7 @@ SingleASTNode::operator= (SingleASTNode const &other) break; case IMPL: - impl_item = other.impl_item->clone_inherent_impl_item (); + impl_item = other.impl_item->clone_associated_item (); break; case TRAIT_IMPL: diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 4049e4d..b193c67 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -1687,22 +1687,6 @@ public: location_t get_locus () const override { return locus; } }; -/* Abstract base class for items used within an inherent impl block (the impl - * name {} one) */ -class InherentImplItem : virtual public AssociatedItem -{ -protected: - // Clone function implementation as pure virtual method - virtual InherentImplItem *clone_associated_item_impl () const override = 0; - -public: - // Unique pointer custom clone function - std::unique_ptr clone_inherent_impl_item () const - { - return std::unique_ptr (clone_associated_item_impl ()); - } -}; - // Abstract base class for items used in a trait impl class TraitImplItem : virtual public AssociatedItem { @@ -1860,7 +1844,7 @@ private: std::unique_ptr stmt; std::unique_ptr external_item; std::unique_ptr trait_item; - std::unique_ptr impl_item; + std::unique_ptr impl_item; std::unique_ptr trait_impl_item; std::unique_ptr type; @@ -1885,7 +1869,7 @@ public: : kind (TRAIT), trait_item (std::move (item)) {} - SingleASTNode (std::unique_ptr item) + SingleASTNode (std::unique_ptr item) : kind (IMPL), impl_item (std::move (item)) {} @@ -1959,7 +1943,7 @@ public: return std::move (external_item); } - std::unique_ptr take_impl_item () + std::unique_ptr take_impl_item () { rust_assert (!is_error ()); return std::move (impl_item); diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 3bf023b..b34aca0 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -1285,7 +1285,9 @@ protected: class LetStmt; // Rust function declaration AST node -class Function : public VisItem, public InherentImplItem, public TraitImplItem +class Function : public VisItem, + virtual public AssociatedItem, + public TraitImplItem { FunctionQualifiers qualifiers; Identifier function_name; @@ -2308,7 +2310,7 @@ protected: /* "Constant item" AST node - used for constant, compile-time expressions * within module scope (like constexpr) */ class ConstantItem : public VisItem, - public InherentImplItem, + virtual public AssociatedItem, public TraitImplItem { // either has an identifier or "_" - maybe handle in identifier? @@ -3408,7 +3410,7 @@ protected: class InherentImpl : public Impl { // bool has_impl_items; - std::vector> impl_items; + std::vector> impl_items; public: std::string as_string () const override; @@ -3417,7 +3419,7 @@ public: bool has_impl_items () const { return !impl_items.empty (); } // Mega-constructor - InherentImpl (std::vector> impl_items, + InherentImpl (std::vector> impl_items, std::vector> generic_params, std::unique_ptr trait_type, WhereClause where_clause, Visibility vis, std::vector inner_attrs, @@ -3433,7 +3435,7 @@ public: { impl_items.reserve (other.impl_items.size ()); for (const auto &e : other.impl_items) - impl_items.push_back (e->clone_inherent_impl_item ()); + impl_items.push_back (e->clone_associated_item ()); } // Overloaded assignment operator with vector clone @@ -3443,7 +3445,7 @@ public: impl_items.reserve (other.impl_items.size ()); for (const auto &e : other.impl_items) - impl_items.push_back (e->clone_inherent_impl_item ()); + impl_items.push_back (e->clone_associated_item ()); return *this; } @@ -3455,11 +3457,11 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: think of better way to do this - const std::vector> &get_impl_items () const + const std::vector> &get_impl_items () const { return impl_items; } - std::vector> &get_impl_items () + std::vector> &get_impl_items () { return impl_items; } diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h index b3fdcf7..41c21cf 100644 --- a/gcc/rust/ast/rust-macro.h +++ b/gcc/rust/ast/rust-macro.h @@ -599,7 +599,7 @@ class MacroInvocation : public TypeNoBounds, public Item, public TraitItem, public TraitImplItem, - public InherentImplItem, + virtual public AssociatedItem, public ExternalItem, public ExprWithoutBlock { diff --git a/gcc/rust/expand/rust-expand-visitor.cc b/gcc/rust/expand/rust-expand-visitor.cc index 3f598b7..1745af0 100644 --- a/gcc/rust/expand/rust-expand-visitor.cc +++ b/gcc/rust/expand/rust-expand-visitor.cc @@ -1180,7 +1180,7 @@ ExpandVisitor::visit (AST::InherentImpl &impl) if (impl.has_where_clause ()) expand_where_clause (impl.get_where_clause ()); - std::function (AST::SingleASTNode)> + std::function (AST::SingleASTNode)> extractor = [] (AST::SingleASTNode node) { return node.take_impl_item (); }; expand_macro_children (MacroExpander::ContextType::IMPL, diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index f83cc12..a9af7dc 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -5388,12 +5388,12 @@ Parser::parse_impl (AST::Visibility vis, AST::AttrVec inner_attrs = parse_inner_attributes (); // parse inherent impl items - std::vector> impl_items; + std::vector> impl_items; const_TokenPtr t = lexer.peek_token (); while (t->get_id () != RIGHT_CURLY) { - std::unique_ptr impl_item + std::unique_ptr impl_item = parse_inherent_impl_item (); if (impl_item == nullptr) @@ -5512,7 +5512,7 @@ Parser::parse_impl (AST::Visibility vis, // Parses a single inherent impl item (item inside an inherent impl block). template -std::unique_ptr +std::unique_ptr Parser::parse_inherent_impl_item () { // parse outer attributes (if they exist) @@ -5629,7 +5629,7 @@ Parser::parse_inherent_impl_item () // InherentImplItem is this specialisation of the template while TraitImplItem // will be the other. template -std::unique_ptr +std::unique_ptr Parser::parse_inherent_impl_function_or_method ( AST::Visibility vis, AST::AttrVec outer_attrs) { diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index d371846..4291e41 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -170,7 +170,7 @@ public: std::unique_ptr parse_type (bool save_errors = true); std::unique_ptr parse_external_item (); std::unique_ptr parse_trait_item (); - std::unique_ptr parse_inherent_impl_item (); + std::unique_ptr parse_inherent_impl_item (); std::unique_ptr parse_trait_impl_item (); AST::PathInExpression parse_path_in_expression (); std::vector> parse_lifetime_params (); @@ -348,7 +348,7 @@ private: std::unique_ptr parse_impl (AST::Visibility vis, AST::AttrVec outer_attrs); - std::unique_ptr + std::unique_ptr parse_inherent_impl_function_or_method (AST::Visibility vis, AST::AttrVec outer_attrs); std::unique_ptr -- cgit v1.1 From 12844c82dec296c8530594211a65b55875797b43 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Tue, 21 Nov 2023 10:29:35 +0100 Subject: gccrs: Split async and const function qualifiers A function cannot be both async and const, however this should not be handled in the parser but rather at a later stage in the compiler. This commit change the AsyncConstStatus in the AST and the HIR to allows a function to be both async and const. gcc/rust/ChangeLog: * ast/rust-ast-builder.cc (AstBuilder::fn_qualifiers): Change constructor to match the new arguments. * ast/rust-ast-collector.cc (TokenCollector::visit): Change behavior to handle both const and async specifiers at the same time. * ast/rust-ast.cc (FunctionQualifiers::as_string): Likewise. * ast/rust-item.h (class FunctionQualifiers): Remove AsyncConstStatus and replace it with both Async and Const status. Also change the safety arguments to use an enum instead of a boolean. * hir/rust-ast-lower-base.cc (ASTLoweringBase::lower_qualifiers): Update constructor call. * hir/tree/rust-hir-item.h: Add Const and Async status, remove AsyncConstStatus, update the constructor. * hir/tree/rust-hir.cc (FunctionQualifiers::as_string): Update with the new status. * parse/rust-parse-impl.h (Parser::parse_function_qualifiers): Update constructor call. * util/rust-common.h (enum Mutability): Make an enum class. (enum class): Add Async and Const enum class to avoid booleans. (enum Unsafety): Change to an enum class. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/ast/rust-ast-builder.cc | 2 +- gcc/rust/ast/rust-ast-collector.cc | 16 ++++--------- gcc/rust/ast/rust-ast.cc | 21 ++++------------- gcc/rust/ast/rust-item.h | 22 ++++++++++-------- gcc/rust/hir/rust-ast-lower-base.cc | 3 ++- gcc/rust/hir/tree/rust-hir-item.h | 14 ++++++----- gcc/rust/hir/tree/rust-hir.cc | 25 +++++--------------- gcc/rust/parse/rust-parse-impl.h | 46 ++++++++++++++++++++++--------------- gcc/rust/util/rust-common.h | 16 +++++++++++-- 9 files changed, 80 insertions(+), 85 deletions(-) diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc index e2d3eea..fd6f519 100644 --- a/gcc/rust/ast/rust-ast-builder.cc +++ b/gcc/rust/ast/rust-ast-builder.cc @@ -46,7 +46,7 @@ AstBuilder::tuple_idx (std::string receiver, int idx) FunctionQualifiers AstBuilder::fn_qualifiers () { - return FunctionQualifiers (loc, AsyncConstStatus::NONE, false); + return FunctionQualifiers (loc, Async::No, Const::No, Unsafety::Normal); } PathExprSegment diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index 3e3a959..647724b 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -317,18 +317,10 @@ TokenCollector::visit (FunctionQualifiers &qualifiers) // `const`? `async`? `unsafe`? (`extern` Abi?)? // unsafe? (extern Abi?)? - switch (qualifiers.get_const_status ()) - { - case NONE: - break; - case CONST_FN: - push (Rust::Token::make (CONST, qualifiers.get_locus ())); - break; - case ASYNC_FN: - push (Rust::Token::make (ASYNC, qualifiers.get_locus ())); - break; - } - + if (qualifiers.is_async ()) + push (Rust::Token::make (ASYNC, qualifiers.get_locus ())); + if (qualifiers.is_const ()) + push (Rust::Token::make (CONST, qualifiers.get_locus ())); if (qualifiers.is_unsafe ()) push (Rust::Token::make (UNSAFE, qualifiers.get_locus ())); if (qualifiers.is_extern ()) diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index 17f82d6..607f079 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -2333,22 +2333,11 @@ FunctionQualifiers::as_string () const { std::string str; - switch (const_status) - { - case NONE: - // do nothing - break; - case CONST_FN: - str += "const "; - break; - case ASYNC_FN: - str += "async "; - break; - default: - return "ERROR_MARK_STRING: async-const status failure"; - } - - if (has_unsafe) + if (is_async ()) + str += "async "; + if (is_const ()) + str += "const "; + if (is_unsafe ()) str += "unsafe "; if (has_extern) diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index b34aca0..9a83f3d 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -533,19 +533,20 @@ public: // Qualifiers for function, i.e. const, unsafe, extern etc. class FunctionQualifiers { - AsyncConstStatus const_status; - bool has_unsafe; + Async async_status; + Const const_status; + Unsafety unsafe_status; bool has_extern; std::string extern_abi; location_t locus; public: - FunctionQualifiers (location_t locus, AsyncConstStatus const_status, - bool has_unsafe, bool has_extern = false, + FunctionQualifiers (location_t locus, Async async_status, Const const_status, + Unsafety unsafe_status, bool has_extern = false, std::string extern_abi = std::string ()) - : const_status (const_status), has_unsafe (has_unsafe), - has_extern (has_extern), extern_abi (std::move (extern_abi)), - locus (locus) + : async_status (async_status), const_status (const_status), + unsafe_status (unsafe_status), has_extern (has_extern), + extern_abi (std::move (extern_abi)), locus (locus) { if (!this->extern_abi.empty ()) { @@ -556,11 +557,14 @@ public: std::string as_string () const; - AsyncConstStatus get_const_status () const { return const_status; } - bool is_unsafe () const { return has_unsafe; } + bool is_unsafe () const { return unsafe_status == Unsafety::Unsafe; } bool is_extern () const { return has_extern; } + bool is_const () const { return const_status == Const::Yes; } + bool is_async () const { return async_status == Async::Yes; } std::string get_extern_abi () const { return extern_abi; } bool has_abi () const { return !extern_abi.empty (); } + Const get_const_status () const { return const_status; } + Async get_async_status () const { return async_status; } location_t get_locus () const { return locus; } }; diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc index f5eed25..f843855 100644 --- a/gcc/rust/hir/rust-ast-lower-base.cc +++ b/gcc/rust/hir/rust-ast-lower-base.cc @@ -721,7 +721,8 @@ ASTLoweringBase::lower_qualifiers (const AST::FunctionQualifiers &qualifiers) "invalid ABI: found %qs", extern_abi.c_str ()); } - return HIR::FunctionQualifiers (qualifiers.get_const_status (), unsafety, + return HIR::FunctionQualifiers (qualifiers.get_async_status (), + qualifiers.get_const_status (), unsafety, has_extern, abi); } diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index 6cd4189..f72d8c8 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -481,24 +481,26 @@ public: struct FunctionQualifiers { private: - AsyncConstStatus const_status; + Async async_status; + Const const_status; Unsafety unsafety; bool has_extern; ABI abi; public: - FunctionQualifiers (AsyncConstStatus const_status, Unsafety unsafety, + FunctionQualifiers (Async async_status, Const const_status, Unsafety unsafety, bool has_extern, ABI abi) - : const_status (const_status), unsafety (unsafety), has_extern (has_extern), - abi (abi) + : async_status (async_status), const_status (const_status), + unsafety (unsafety), has_extern (has_extern), abi (abi) {} std::string as_string () const; - AsyncConstStatus get_status () const { return const_status; } + Const get_const_status () const { return const_status; } - bool is_const () const { return const_status == AsyncConstStatus::CONST_FN; } + bool is_const () const { return const_status == Const::Yes; } bool is_unsafe () const { return unsafety == Unsafety::Unsafe; } + bool is_async () const { return async_status == Async::Yes; } ABI get_abi () const { return abi; } }; diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc index 66f626b..fb0a9c3 100644 --- a/gcc/rust/hir/tree/rust-hir.cc +++ b/gcc/rust/hir/tree/rust-hir.cc @@ -1947,25 +1947,12 @@ FunctionQualifiers::as_string () const { std::string str; - switch (const_status) - { - case NONE: - // do nothing - break; - case CONST_FN: - str += "const "; - break; - case ASYNC_FN: - str += "async "; - break; - default: - return "ERROR_MARK_STRING: async-const status failure"; - } - - if (unsafety == Unsafety::Unsafe) - { - str += "unsafe "; - } + if (is_const ()) + str += "const "; + if (is_async ()) + str += "async "; + if (is_unsafe ()) + str += "unsafe "; if (has_extern) { diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index a9af7dc..a1ad4f1 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -24,6 +24,7 @@ #include "rust-common.h" #include "rust-item.h" +#include "rust-common.h" #include "rust-token.h" #define INCLUDE_ALGORITHM #include "rust-diagnostics.h" @@ -2987,33 +2988,40 @@ template AST::FunctionQualifiers Parser::parse_function_qualifiers () { - AsyncConstStatus const_status = NONE; - bool has_unsafe = false; + Async async_status = Async::No; + Const const_status = Const::No; + Unsafety unsafe_status = Unsafety::Normal; bool has_extern = false; std::string abi; + const_TokenPtr t; + location_t locus; // Check in order of const, unsafe, then extern - const_TokenPtr t = lexer.peek_token (); - location_t locus = t->get_locus (); - switch (t->get_id ()) + for (int i = 0; i < 2; i++) { - case CONST: - lexer.skip_token (); - const_status = CONST_FN; - break; - case ASYNC: - lexer.skip_token (); - const_status = ASYNC_FN; - break; - default: - // const status is still none - break; + t = lexer.peek_token (); + locus = t->get_locus (); + + switch (t->get_id ()) + { + case CONST: + lexer.skip_token (); + const_status = Const::Yes; + break; + case ASYNC: + lexer.skip_token (); + async_status = Async::Yes; + break; + default: + // const status is still none + break; + } } if (lexer.peek_token ()->get_id () == UNSAFE) { lexer.skip_token (); - has_unsafe = true; + unsafe_status = Unsafety::Unsafe; } if (lexer.peek_token ()->get_id () == EXTERN_KW) @@ -3030,8 +3038,8 @@ Parser::parse_function_qualifiers () } } - return AST::FunctionQualifiers (locus, const_status, has_unsafe, has_extern, - std::move (abi)); + return AST::FunctionQualifiers (locus, async_status, const_status, + unsafe_status, has_extern, std::move (abi)); } // Parses generic (lifetime or type) params inside angle brackets (optional). diff --git a/gcc/rust/util/rust-common.h b/gcc/rust/util/rust-common.h index fc8ba6e..299ae71 100644 --- a/gcc/rust/util/rust-common.h +++ b/gcc/rust/util/rust-common.h @@ -25,18 +25,30 @@ namespace Rust { -enum Mutability +enum class Mutability { Imm, Mut }; -enum Unsafety +enum class Unsafety { Unsafe, Normal }; +enum class Const +{ + Yes, + No, +}; + +enum class Async +{ + Yes, + No +}; + enum BoundPolarity { RegularBound, -- cgit v1.1 From 68990dbeadc5f4b90c0aa14387cb80d0f411aa43 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Wed, 22 Nov 2023 10:35:44 +0100 Subject: gccrs: Allow const and async specifiers in functions We need to account for const specifiers in async parsing as const can be used in the syntax before the async keyword. gcc/rust/ChangeLog: * parse/rust-parse-impl.h (Parser::parse_vis_item): Allow parsing async items in const. (Parser::parse_async_item): Account for const offset during async lookahead. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/parse/rust-parse-impl.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index a1ad4f1..acceec3 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -1383,6 +1383,8 @@ Parser::parse_vis_item (AST::AttrVec outer_attrs) return parse_const_item (std::move (vis), std::move (outer_attrs)); case UNSAFE: case EXTERN_KW: + case ASYNC: + return parse_async_item (std::move (vis), std::move (outer_attrs)); case FN_KW: return parse_function (std::move (vis), std::move (outer_attrs)); default: @@ -1445,7 +1447,9 @@ std::unique_ptr Parser::parse_async_item (AST::Visibility vis, AST::AttrVec outer_attrs) { - const_TokenPtr t = lexer.peek_token (); + auto offset = (lexer.peek_token ()->get_id () == CONST) ? 1 : 0; + const_TokenPtr t = lexer.peek_token (offset); + if (Session::get_instance ().options.get_edition () == CompileOptions::Edition::E2015) { @@ -1456,7 +1460,7 @@ Parser::parse_async_item (AST::Visibility vis, "to use %, switch to Rust 2018 or later")); } - t = lexer.peek_token (1); + t = lexer.peek_token (offset + 1); switch (t->get_id ()) { -- cgit v1.1 From 04b3089a47c5ccfb86b29a9c64157d5d4f755c1c Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Wed, 22 Nov 2023 10:44:08 +0100 Subject: gccrs: Add async const function ast validation pass Add a check during AST validation pass to ensure functions are either const or async but not both. gcc/rust/ChangeLog: * checks/errors/rust-ast-validation.cc (ASTValidation::visit): Add async const check. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/checks/errors/rust-ast-validation.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc index 4b20990..54276e8 100644 --- a/gcc/rust/checks/errors/rust-ast-validation.cc +++ b/gcc/rust/checks/errors/rust-ast-validation.cc @@ -98,6 +98,11 @@ ASTValidation::visit (AST::Function &function) std::set valid_context = {Context::INHERENT_IMPL, Context::TRAIT_IMPL}; + const auto &qualifiers = function.get_qualifiers (); + if (qualifiers.is_async () && qualifiers.is_const ()) + rust_error_at (function.get_locus (), + "functions cannot be both % and %"); + if (valid_context.find (context.back ()) == valid_context.end () && function.has_self_param ()) rust_error_at ( -- cgit v1.1 From ac501a75b263a7dd7fa437c01aae53d41e30a515 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Wed, 22 Nov 2023 11:12:05 +0100 Subject: gccrs: Add a regression test for async const functions Functions that are both async and const shall be rejected during the AST validation pass. This new test highlight this behavior. gcc/testsuite/ChangeLog: * rust/compile/const_async_function.rs: New test. Signed-off-by: Pierre-Emmanuel Patry --- gcc/testsuite/rust/compile/const_async_function.rs | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 gcc/testsuite/rust/compile/const_async_function.rs diff --git a/gcc/testsuite/rust/compile/const_async_function.rs b/gcc/testsuite/rust/compile/const_async_function.rs new file mode 100644 index 0000000..fb1c4dd --- /dev/null +++ b/gcc/testsuite/rust/compile/const_async_function.rs @@ -0,0 +1,3 @@ +// { dg-additional-options "-frust-edition=2018" } +const async fn weird_function() {} +// { dg-error "functions cannot be both .const. and .async." "" { target *-*-* } .-1 } -- cgit v1.1 From 9279483f6e87258e36345c355720860925a75e3e Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Wed, 22 Nov 2023 13:08:13 +0100 Subject: gccrs: Add AST validation check for const in trait Add a new check in AST validation pass that checks that no function declaration in traits are declared const. gcc/rust/ChangeLog: * checks/errors/rust-ast-validation.cc (ASTValidation::visit): Add const check. * checks/errors/rust-ast-validation.h: Add visit function prototype. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/checks/errors/rust-ast-validation.cc | 10 ++++++++++ gcc/rust/checks/errors/rust-ast-validation.h | 1 + 2 files changed, 11 insertions(+) diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc index 54276e8..2743eb0 100644 --- a/gcc/rust/checks/errors/rust-ast-validation.cc +++ b/gcc/rust/checks/errors/rust-ast-validation.cc @@ -118,6 +118,16 @@ ASTValidation::visit (AST::Function &function) } void +ASTValidation::visit (AST::TraitFunctionDecl &decl) +{ + const auto &qualifiers = decl.get_qualifiers (); + + if (context.back () == Context::TRAIT && qualifiers.is_const ()) + rust_error_at (decl.get_identifier ().get_locus (), ErrorCode::E0379, + "functions in traits cannot be declared const"); +} + +void ASTValidation::visit (AST::Trait &trait) { if (trait.is_auto ()) diff --git a/gcc/rust/checks/errors/rust-ast-validation.h b/gcc/rust/checks/errors/rust-ast-validation.h index 01d923c..963357f 100644 --- a/gcc/rust/checks/errors/rust-ast-validation.h +++ b/gcc/rust/checks/errors/rust-ast-validation.h @@ -42,6 +42,7 @@ public: virtual void visit (AST::Union &item); virtual void visit (AST::Function &function); virtual void visit (AST::Trait &trait); + virtual void visit (AST::TraitFunctionDecl &decl); }; } // namespace Rust -- cgit v1.1 From ab257dcd66cd2532beb0c74b836147d02a9ed3bb Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Wed, 22 Nov 2023 13:22:42 +0100 Subject: gccrs: Add regression test for const fn in trait Const fn declaration in trait declarations shall emit an error. This new test highlight this behavior. gcc/testsuite/ChangeLog: * rust/compile/const_trait_fn.rs: New test. Signed-off-by: Pierre-Emmanuel Patry --- gcc/testsuite/rust/compile/const_trait_fn.rs | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 gcc/testsuite/rust/compile/const_trait_fn.rs diff --git a/gcc/testsuite/rust/compile/const_trait_fn.rs b/gcc/testsuite/rust/compile/const_trait_fn.rs new file mode 100644 index 0000000..cff2f5f --- /dev/null +++ b/gcc/testsuite/rust/compile/const_trait_fn.rs @@ -0,0 +1,4 @@ +trait Osterkz { + const fn x(); + // { dg-error "functions in traits cannot be declared const .E0379." "" { target *-*-* } .-1 } +} -- cgit v1.1 From 9f6d3010047d417f54c439db42f111fa61b216df Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Fri, 24 Nov 2023 11:17:52 +0100 Subject: gccrs: Make feature gate visitor inherit from default one The feature gating behavior may be shortened and kept cleaner using the default visitor. This means less maintenance on visit functions as the traversal is shared by multiple visitors. gcc/rust/ChangeLog: * checks/errors/rust-feature-gate.cc (FeatureGate::visit): Add a visit function for the crate level. (FeatureGate::check): Add call to crate visit. * checks/errors/rust-feature-gate.h (class FeatureGate): Remove now useless visit functions (traversal only). Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/checks/errors/rust-feature-gate.cc | 37 +++++++---------------------- gcc/rust/checks/errors/rust-feature-gate.h | 7 +++--- 2 files changed, 13 insertions(+), 31 deletions(-) diff --git a/gcc/rust/checks/errors/rust-feature-gate.cc b/gcc/rust/checks/errors/rust-feature-gate.cc index a531d037..3c94302 100644 --- a/gcc/rust/checks/errors/rust-feature-gate.cc +++ b/gcc/rust/checks/errors/rust-feature-gate.cc @@ -18,12 +18,19 @@ #include "rust-feature-gate.h" #include "rust-abi.h" +#include "rust-ast-visitor.h" namespace Rust { void FeatureGate::check (AST::Crate &crate) { + visit (crate); +} + +void +FeatureGate::visit (AST::Crate &crate) +{ valid_features.clear (); for (const auto &attr : crate.inner_attrs) @@ -56,12 +63,7 @@ FeatureGate::check (AST::Crate &crate) } } - auto &items = crate.items; - for (auto it = items.begin (); it != items.end (); it++) - { - auto &item = *it; - item->accept_vis (*this); - } + AST::DefaultASTVisitor::visit (crate); } void @@ -103,10 +105,7 @@ FeatureGate::visit (AST::ExternBlock &block) gate (Feature::Name::INTRINSICS, block.get_locus (), "intrinsics are subject to change"); } - for (const auto &item : block.get_extern_items ()) - { - item->accept_vis (*this); - } + AST::DefaultASTVisitor::visit (block); } void @@ -130,24 +129,6 @@ FeatureGate::visit (AST::MacroRulesDefinition &rules_def) } void -FeatureGate::visit (AST::InherentImpl &impl) -{ - for (const auto &item : impl.get_impl_items ()) - { - item->accept_vis (*this); - } -} - -void -FeatureGate::visit (AST::TraitImpl &impl) -{ - for (const auto &item : impl.get_impl_items ()) - { - item->accept_vis (*this); - } -} - -void FeatureGate::visit (AST::Function &function) { check_rustc_attri (function.get_outer_attrs ()); diff --git a/gcc/rust/checks/errors/rust-feature-gate.h b/gcc/rust/checks/errors/rust-feature-gate.h index 1ebd3c9..8d1a26a 100644 --- a/gcc/rust/checks/errors/rust-feature-gate.h +++ b/gcc/rust/checks/errors/rust-feature-gate.h @@ -25,12 +25,15 @@ namespace Rust { -class FeatureGate : public AST::ASTVisitor +class FeatureGate : public AST::DefaultASTVisitor { public: FeatureGate () {} + using AST::DefaultASTVisitor::visit; + void check (AST::Crate &crate); + void visit (AST::Crate &crate) override; void visit (AST::Token &tok) override {} void visit (AST::DelimTokenTree &delim_tok_tree) override {} @@ -127,8 +130,6 @@ public: void visit (AST::TraitItemConst &item) override {} void visit (AST::TraitItemType &item) override {} void visit (AST::Trait &trait) override {} - void visit (AST::InherentImpl &impl) override; - void visit (AST::TraitImpl &impl) override; void visit (AST::ExternalTypeItem &item) override; void visit (AST::ExternalStaticItem &item) override {} void visit (AST::ExternalFunctionItem &item) override {} -- cgit v1.1 From 1761af6b2a3618ad0edcadc630e1763ba84d14c0 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Fri, 24 Nov 2023 14:09:23 +0100 Subject: gccrs: Change the attribute checker visitor to default one Make the attribute checker visitor inherit from the default visitor in order to keep visit behavior shared. gcc/rust/ChangeLog: * util/rust-attributes.cc (AttributeChecker::visit): Add visit function for crates. * util/rust-attributes.h (class AttributeChecker): Update function prototypes. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/util/rust-attributes.cc | 23 ++- gcc/rust/util/rust-attributes.h | 319 ++++++++++++++++++++------------------- 2 files changed, 171 insertions(+), 171 deletions(-) diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc index 981bc73..a1e2308 100644 --- a/gcc/rust/util/rust-attributes.cc +++ b/gcc/rust/util/rust-attributes.cc @@ -16,6 +16,7 @@ // along with GCC; see the file COPYING3. If not see // . +#include "rust-ast-visitor.h" #include "rust-system.h" #include "rust-session-manager.h" #include "rust-attributes.h" @@ -95,6 +96,12 @@ AttributeChecker::AttributeChecker () {} void AttributeChecker::go (AST::Crate &crate) { + visit (crate); +} + +void +AttributeChecker::visit (AST::Crate &crate) +{ check_attributes (crate.get_inner_attrs ()); for (auto &item : crate.items) @@ -468,8 +475,8 @@ AttributeChecker::visit (AST::BlockExpr &expr) check_proc_macro_non_root (item->get_outer_attrs (), item->get_locus ()); } - stmt->accept_vis (*this); } + AST::DefaultASTVisitor::visit (expr); } void @@ -513,12 +520,6 @@ AttributeChecker::visit (AST::ReturnExpr &) {} void -AttributeChecker::visit (AST::UnsafeBlockExpr &expr) -{ - expr.get_block_expr ()->accept_vis (*this); -} - -void AttributeChecker::visit (AST::LoopExpr &) {} @@ -582,8 +583,8 @@ AttributeChecker::visit (AST::Module &module) for (auto &item : module.get_items ()) { check_proc_macro_non_root (item->get_outer_attrs (), item->get_locus ()); - item->accept_vis (*this); } + AST::DefaultASTVisitor::visit (module); } void @@ -754,16 +755,14 @@ void AttributeChecker::visit (AST::InherentImpl &impl) { check_proc_macro_non_function (impl.get_outer_attrs ()); - for (auto &item : impl.get_impl_items ()) - item->accept_vis (*this); + AST::DefaultASTVisitor::visit (impl); } void AttributeChecker::visit (AST::TraitImpl &impl) { check_proc_macro_non_function (impl.get_outer_attrs ()); - for (auto &item : impl.get_impl_items ()) - item->accept_vis (*this); + AST::DefaultASTVisitor::visit (impl); } void diff --git a/gcc/rust/util/rust-attributes.h b/gcc/rust/util/rust-attributes.h index 9db371e..eecc4c0 100644 --- a/gcc/rust/util/rust-attributes.h +++ b/gcc/rust/util/rust-attributes.h @@ -77,7 +77,7 @@ private: * as checking the "arguments" or input given to these attributes, making sure * it is appropriate and valid. */ -class AttributeChecker : public AST::ASTVisitor +class AttributeChecker : public AST::DefaultASTVisitor { public: AttributeChecker (); @@ -88,6 +88,7 @@ public: void go (AST::Crate &crate); private: + using AST::DefaultASTVisitor::visit; /* Check the validity of a given attribute */ void check_attribute (const AST::Attribute &attribute); @@ -95,178 +96,178 @@ private: void check_attributes (const AST::AttrVec &attributes); // rust-ast.h - void visit (AST::Token &tok); - void visit (AST::DelimTokenTree &delim_tok_tree); - void visit (AST::AttrInputMetaItemContainer &input); - void visit (AST::IdentifierExpr &ident_expr); - void visit (AST::Lifetime &lifetime); - void visit (AST::LifetimeParam &lifetime_param); - void visit (AST::ConstGenericParam &const_param); + void visit (AST::Crate &crate) override; + void visit (AST::Token &tok) override; + void visit (AST::DelimTokenTree &delim_tok_tree) override; + void visit (AST::AttrInputMetaItemContainer &input) override; + void visit (AST::IdentifierExpr &ident_expr) override; + void visit (AST::Lifetime &lifetime) override; + void visit (AST::LifetimeParam &lifetime_param) override; + void visit (AST::ConstGenericParam &const_param) override; // rust-path.h - void visit (AST::PathInExpression &path); - void visit (AST::TypePathSegment &segment); - void visit (AST::TypePathSegmentGeneric &segment); - void visit (AST::TypePathSegmentFunction &segment); - void visit (AST::TypePath &path); - void visit (AST::QualifiedPathInExpression &path); - void visit (AST::QualifiedPathInType &path); + void visit (AST::PathInExpression &path) override; + void visit (AST::TypePathSegment &segment) override; + void visit (AST::TypePathSegmentGeneric &segment) override; + void visit (AST::TypePathSegmentFunction &segment) override; + void visit (AST::TypePath &path) override; + void visit (AST::QualifiedPathInExpression &path) override; + void visit (AST::QualifiedPathInType &path) override; // rust-expr.h - void visit (AST::LiteralExpr &expr); - void visit (AST::AttrInputLiteral &attr_input); - void visit (AST::AttrInputMacro &attr_input); - void visit (AST::MetaItemLitExpr &meta_item); - void visit (AST::MetaItemPathLit &meta_item); - void visit (AST::BorrowExpr &expr); - void visit (AST::DereferenceExpr &expr); - void visit (AST::ErrorPropagationExpr &expr); - void visit (AST::NegationExpr &expr); - void visit (AST::ArithmeticOrLogicalExpr &expr); - void visit (AST::ComparisonExpr &expr); - void visit (AST::LazyBooleanExpr &expr); - void visit (AST::TypeCastExpr &expr); - void visit (AST::AssignmentExpr &expr); - void visit (AST::CompoundAssignmentExpr &expr); - void visit (AST::GroupedExpr &expr); - void visit (AST::ArrayElemsValues &elems); - void visit (AST::ArrayElemsCopied &elems); - void visit (AST::ArrayExpr &expr); - void visit (AST::ArrayIndexExpr &expr); - void visit (AST::TupleExpr &expr); - void visit (AST::TupleIndexExpr &expr); - void visit (AST::StructExprStruct &expr); - void visit (AST::StructExprFieldIdentifier &field); - void visit (AST::StructExprFieldIdentifierValue &field); - void visit (AST::StructExprFieldIndexValue &field); - void visit (AST::StructExprStructFields &expr); - void visit (AST::StructExprStructBase &expr); - void visit (AST::CallExpr &expr); - void visit (AST::MethodCallExpr &expr); - void visit (AST::FieldAccessExpr &expr); - void visit (AST::ClosureExprInner &expr); - void visit (AST::BlockExpr &expr); - void visit (AST::ClosureExprInnerTyped &expr); - void visit (AST::ContinueExpr &expr); - void visit (AST::BreakExpr &expr); - void visit (AST::RangeFromToExpr &expr); - void visit (AST::RangeFromExpr &expr); - void visit (AST::RangeToExpr &expr); - void visit (AST::RangeFullExpr &expr); - void visit (AST::RangeFromToInclExpr &expr); - void visit (AST::RangeToInclExpr &expr); - void visit (AST::ReturnExpr &expr); - void visit (AST::UnsafeBlockExpr &expr); - void visit (AST::LoopExpr &expr); - void visit (AST::WhileLoopExpr &expr); - void visit (AST::WhileLetLoopExpr &expr); - void visit (AST::ForLoopExpr &expr); - void visit (AST::IfExpr &expr); - void visit (AST::IfExprConseqElse &expr); - void visit (AST::IfLetExpr &expr); - void visit (AST::IfLetExprConseqElse &expr); - void visit (AST::MatchExpr &expr); - void visit (AST::AwaitExpr &expr); - void visit (AST::AsyncBlockExpr &expr); + void visit (AST::LiteralExpr &expr) override; + void visit (AST::AttrInputLiteral &attr_input) override; + void visit (AST::AttrInputMacro &attr_input) override; + void visit (AST::MetaItemLitExpr &meta_item) override; + void visit (AST::MetaItemPathLit &meta_item) override; + void visit (AST::BorrowExpr &expr) override; + void visit (AST::DereferenceExpr &expr) override; + void visit (AST::ErrorPropagationExpr &expr) override; + void visit (AST::NegationExpr &expr) override; + void visit (AST::ArithmeticOrLogicalExpr &expr) override; + void visit (AST::ComparisonExpr &expr) override; + void visit (AST::LazyBooleanExpr &expr) override; + void visit (AST::TypeCastExpr &expr) override; + void visit (AST::AssignmentExpr &expr) override; + void visit (AST::CompoundAssignmentExpr &expr) override; + void visit (AST::GroupedExpr &expr) override; + void visit (AST::ArrayElemsValues &elems) override; + void visit (AST::ArrayElemsCopied &elems) override; + void visit (AST::ArrayExpr &expr) override; + void visit (AST::ArrayIndexExpr &expr) override; + void visit (AST::TupleExpr &expr) override; + void visit (AST::TupleIndexExpr &expr) override; + void visit (AST::StructExprStruct &expr) override; + void visit (AST::StructExprFieldIdentifier &field) override; + void visit (AST::StructExprFieldIdentifierValue &field) override; + void visit (AST::StructExprFieldIndexValue &field) override; + void visit (AST::StructExprStructFields &expr) override; + void visit (AST::StructExprStructBase &expr) override; + void visit (AST::CallExpr &expr) override; + void visit (AST::MethodCallExpr &expr) override; + void visit (AST::FieldAccessExpr &expr) override; + void visit (AST::ClosureExprInner &expr) override; + void visit (AST::BlockExpr &expr) override; + void visit (AST::ClosureExprInnerTyped &expr) override; + void visit (AST::ContinueExpr &expr) override; + void visit (AST::BreakExpr &expr) override; + void visit (AST::RangeFromToExpr &expr) override; + void visit (AST::RangeFromExpr &expr) override; + void visit (AST::RangeToExpr &expr) override; + void visit (AST::RangeFullExpr &expr) override; + void visit (AST::RangeFromToInclExpr &expr) override; + void visit (AST::RangeToInclExpr &expr) override; + void visit (AST::ReturnExpr &expr) override; + void visit (AST::LoopExpr &expr) override; + void visit (AST::WhileLoopExpr &expr) override; + void visit (AST::WhileLetLoopExpr &expr) override; + void visit (AST::ForLoopExpr &expr) override; + void visit (AST::IfExpr &expr) override; + void visit (AST::IfExprConseqElse &expr) override; + void visit (AST::IfLetExpr &expr) override; + void visit (AST::IfLetExprConseqElse &expr) override; + void visit (AST::MatchExpr &expr) override; + void visit (AST::AwaitExpr &expr) override; + void visit (AST::AsyncBlockExpr &expr) override; // rust-item.h - void visit (AST::TypeParam ¶m); - void visit (AST::LifetimeWhereClauseItem &item); - void visit (AST::TypeBoundWhereClauseItem &item); - void visit (AST::Module &module); - void visit (AST::ExternCrate &crate); - void visit (AST::UseTreeGlob &use_tree); - void visit (AST::UseTreeList &use_tree); - void visit (AST::UseTreeRebind &use_tree); - void visit (AST::UseDeclaration &use_decl); - void visit (AST::Function &function); - void visit (AST::TypeAlias &type_alias); - void visit (AST::StructStruct &struct_item); - void visit (AST::TupleStruct &tuple_struct); - void visit (AST::EnumItem &item); - void visit (AST::EnumItemTuple &item); - void visit (AST::EnumItemStruct &item); - void visit (AST::EnumItemDiscriminant &item); - void visit (AST::Enum &enum_item); - void visit (AST::Union &union_item); - void visit (AST::ConstantItem &const_item); - void visit (AST::StaticItem &static_item); - void visit (AST::TraitItemFunc &item); - void visit (AST::TraitItemMethod &item); - void visit (AST::TraitItemConst &item); - void visit (AST::TraitItemType &item); - void visit (AST::Trait &trait); - void visit (AST::InherentImpl &impl); - void visit (AST::TraitImpl &impl); - void visit (AST::ExternalTypeItem &item); - void visit (AST::ExternalStaticItem &item); - void visit (AST::ExternalFunctionItem &item); - void visit (AST::ExternBlock &block); + void visit (AST::TypeParam ¶m) override; + void visit (AST::LifetimeWhereClauseItem &item) override; + void visit (AST::TypeBoundWhereClauseItem &item) override; + void visit (AST::Module &module) override; + void visit (AST::ExternCrate &crate) override; + void visit (AST::UseTreeGlob &use_tree) override; + void visit (AST::UseTreeList &use_tree) override; + void visit (AST::UseTreeRebind &use_tree) override; + void visit (AST::UseDeclaration &use_decl) override; + void visit (AST::Function &function) override; + void visit (AST::TypeAlias &type_alias) override; + void visit (AST::StructStruct &struct_item) override; + void visit (AST::TupleStruct &tuple_struct) override; + void visit (AST::EnumItem &item) override; + void visit (AST::EnumItemTuple &item) override; + void visit (AST::EnumItemStruct &item) override; + void visit (AST::EnumItemDiscriminant &item) override; + void visit (AST::Enum &enum_item) override; + void visit (AST::Union &union_item) override; + void visit (AST::ConstantItem &const_item) override; + void visit (AST::StaticItem &static_item) override; + void visit (AST::TraitItemFunc &item) override; + void visit (AST::TraitItemMethod &item) override; + void visit (AST::TraitItemConst &item) override; + void visit (AST::TraitItemType &item) override; + void visit (AST::Trait &trait) override; + void visit (AST::InherentImpl &impl) override; + void visit (AST::TraitImpl &impl) override; + void visit (AST::ExternalTypeItem &item) override; + void visit (AST::ExternalStaticItem &item) override; + void visit (AST::ExternalFunctionItem &item) override; + void visit (AST::ExternBlock &block) override; // rust-macro.h - void visit (AST::MacroMatchFragment &match); - void visit (AST::MacroMatchRepetition &match); - void visit (AST::MacroMatcher &matcher); - void visit (AST::MacroRulesDefinition &rules_def); - void visit (AST::MacroInvocation ¯o_invoc); - void visit (AST::MetaItemPath &meta_item); - void visit (AST::MetaItemSeq &meta_item); - void visit (AST::MetaWord &meta_item); - void visit (AST::MetaNameValueStr &meta_item); - void visit (AST::MetaListPaths &meta_item); - void visit (AST::MetaListNameValueStr &meta_item); + void visit (AST::MacroMatchFragment &match) override; + void visit (AST::MacroMatchRepetition &match) override; + void visit (AST::MacroMatcher &matcher) override; + void visit (AST::MacroRulesDefinition &rules_def) override; + void visit (AST::MacroInvocation ¯o_invoc) override; + void visit (AST::MetaItemPath &meta_item) override; + void visit (AST::MetaItemSeq &meta_item) override; + void visit (AST::MetaWord &meta_item) override; + void visit (AST::MetaNameValueStr &meta_item) override; + void visit (AST::MetaListPaths &meta_item) override; + void visit (AST::MetaListNameValueStr &meta_item) override; // rust-pattern.h - void visit (AST::LiteralPattern &pattern); - void visit (AST::IdentifierPattern &pattern); - void visit (AST::WildcardPattern &pattern); - void visit (AST::RestPattern &pattern); - // void visit(RangePatternBound& bound); - void visit (AST::RangePatternBoundLiteral &bound); - void visit (AST::RangePatternBoundPath &bound); - void visit (AST::RangePatternBoundQualPath &bound); - void visit (AST::RangePattern &pattern); - void visit (AST::ReferencePattern &pattern); - // void visit(StructPatternField& field); - void visit (AST::StructPatternFieldTuplePat &field); - void visit (AST::StructPatternFieldIdentPat &field); - void visit (AST::StructPatternFieldIdent &field); - void visit (AST::StructPattern &pattern); - // void visit(TupleStructItems& tuple_items); - void visit (AST::TupleStructItemsNoRange &tuple_items); - void visit (AST::TupleStructItemsRange &tuple_items); - void visit (AST::TupleStructPattern &pattern); - // void visit(TuplePatternItems& tuple_items); - void visit (AST::TuplePatternItemsMultiple &tuple_items); - void visit (AST::TuplePatternItemsRanged &tuple_items); - void visit (AST::TuplePattern &pattern); - void visit (AST::GroupedPattern &pattern); - void visit (AST::SlicePattern &pattern); - void visit (AST::AltPattern &pattern); + void visit (AST::LiteralPattern &pattern) override; + void visit (AST::IdentifierPattern &pattern) override; + void visit (AST::WildcardPattern &pattern) override; + void visit (AST::RestPattern &pattern) override; + // void visit(RangePatternBound& bound) override; + void visit (AST::RangePatternBoundLiteral &bound) override; + void visit (AST::RangePatternBoundPath &bound) override; + void visit (AST::RangePatternBoundQualPath &bound) override; + void visit (AST::RangePattern &pattern) override; + void visit (AST::ReferencePattern &pattern) override; + // void visit(StructPatternField& field) override; + void visit (AST::StructPatternFieldTuplePat &field) override; + void visit (AST::StructPatternFieldIdentPat &field) override; + void visit (AST::StructPatternFieldIdent &field) override; + void visit (AST::StructPattern &pattern) override; + // void visit(TupleStructItems& tuple_items) override; + void visit (AST::TupleStructItemsNoRange &tuple_items) override; + void visit (AST::TupleStructItemsRange &tuple_items) override; + void visit (AST::TupleStructPattern &pattern) override; + // void visit(TuplePatternItems& tuple_items) override; + void visit (AST::TuplePatternItemsMultiple &tuple_items) override; + void visit (AST::TuplePatternItemsRanged &tuple_items) override; + void visit (AST::TuplePattern &pattern) override; + void visit (AST::GroupedPattern &pattern) override; + void visit (AST::SlicePattern &pattern) override; + void visit (AST::AltPattern &pattern) override; // rust-stmt.h - void visit (AST::EmptyStmt &stmt); - void visit (AST::LetStmt &stmt); - void visit (AST::ExprStmt &stmt); + void visit (AST::EmptyStmt &stmt) override; + void visit (AST::LetStmt &stmt) override; + void visit (AST::ExprStmt &stmt) override; // rust-type.h - void visit (AST::TraitBound &bound); - void visit (AST::ImplTraitType &type); - void visit (AST::TraitObjectType &type); - void visit (AST::ParenthesisedType &type); - void visit (AST::ImplTraitTypeOneBound &type); - void visit (AST::TraitObjectTypeOneBound &type); - void visit (AST::TupleType &type); - void visit (AST::NeverType &type); - void visit (AST::RawPointerType &type); - void visit (AST::ReferenceType &type); - void visit (AST::ArrayType &type); - void visit (AST::SliceType &type); - void visit (AST::InferredType &type); - void visit (AST::BareFunctionType &type); - void visit (AST::FunctionParam ¶m); - void visit (AST::VariadicParam ¶m); - void visit (AST::SelfParam ¶m); + void visit (AST::TraitBound &bound) override; + void visit (AST::ImplTraitType &type) override; + void visit (AST::TraitObjectType &type) override; + void visit (AST::ParenthesisedType &type) override; + void visit (AST::ImplTraitTypeOneBound &type) override; + void visit (AST::TraitObjectTypeOneBound &type) override; + void visit (AST::TupleType &type) override; + void visit (AST::NeverType &type) override; + void visit (AST::RawPointerType &type) override; + void visit (AST::ReferenceType &type) override; + void visit (AST::ArrayType &type) override; + void visit (AST::SliceType &type) override; + void visit (AST::InferredType &type) override; + void visit (AST::BareFunctionType &type) override; + void visit (AST::FunctionParam ¶m) override; + void visit (AST::VariadicParam ¶m) override; + void visit (AST::SelfParam ¶m) override; }; } // namespace Analysis -- cgit v1.1 From 4cd0315aa91c70f7129833671cedb12a7b45e199 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Mon, 27 Nov 2023 15:39:24 +0100 Subject: gccrs: Make early name resolver inherit from default one Many visit functions in the early name resolver are just plain old traversal visit functions like the ones from the default visitor. gcc/rust/ChangeLog: * resolve/rust-early-name-resolver.cc (EarlyNameResolver::resolve_generic_args): Move function. (EarlyNameResolver::resolve_qualified_path_type): Likewise. (EarlyNameResolver::visit): Add a top level visit function for crate and remove duplicated code. * resolve/rust-early-name-resolver.h (class EarlyNameResolver): Update overriden function list. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/resolve/rust-early-name-resolver.cc | 683 +-------------------------- gcc/rust/resolve/rust-early-name-resolver.h | 94 +--- 2 files changed, 28 insertions(+), 749 deletions(-) diff --git a/gcc/rust/resolve/rust-early-name-resolver.cc b/gcc/rust/resolve/rust-early-name-resolver.cc index 38a1640..422dd92 100644 --- a/gcc/rust/resolve/rust-early-name-resolver.cc +++ b/gcc/rust/resolve/rust-early-name-resolver.cc @@ -80,6 +80,31 @@ EarlyNameResolver::EarlyNameResolver () void EarlyNameResolver::go (AST::Crate &crate) { + visit (crate); +} + +void +EarlyNameResolver::resolve_generic_args (AST::GenericArgs &generic_args) +{ + for (auto &arg : generic_args.get_generic_args ()) + arg.accept_vis (*this); + + for (auto &arg : generic_args.get_binding_args ()) + arg.get_type ()->accept_vis (*this); +} + +void +EarlyNameResolver::resolve_qualified_path_type (AST::QualifiedPathType &path) +{ + path.get_type ()->accept_vis (*this); + + if (path.has_as_clause ()) + path.get_as_type_path ().accept_vis (*this); +} + +void +EarlyNameResolver::visit (AST::Crate &crate) +{ std::vector> new_items; auto items = crate.take_items (); @@ -107,29 +132,6 @@ EarlyNameResolver::go (AST::Crate &crate) } void -EarlyNameResolver::resolve_generic_args (AST::GenericArgs &generic_args) -{ - for (auto &arg : generic_args.get_generic_args ()) - arg.accept_vis (*this); - - for (auto &arg : generic_args.get_binding_args ()) - arg.get_type ()->accept_vis (*this); -} - -void -EarlyNameResolver::resolve_qualified_path_type (AST::QualifiedPathType &path) -{ - path.get_type ()->accept_vis (*this); - - if (path.has_as_clause ()) - path.get_as_type_path ().accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::Token &) -{} - -void EarlyNameResolver::visit (AST::DelimTokenTree &) {} @@ -142,10 +144,6 @@ EarlyNameResolver::visit (AST::IdentifierExpr &) {} void -EarlyNameResolver::visit (AST::Lifetime &) -{} - -void EarlyNameResolver::visit (AST::LifetimeParam &) {} @@ -164,10 +162,6 @@ EarlyNameResolver::visit (AST::PathInExpression &path) } void -EarlyNameResolver::visit (AST::TypePathSegment &) -{} - -void EarlyNameResolver::visit (AST::TypePathSegmentGeneric &segment) { if (segment.has_generic_args ()) @@ -175,22 +169,6 @@ EarlyNameResolver::visit (AST::TypePathSegmentGeneric &segment) } void -EarlyNameResolver::visit (AST::TypePathSegmentFunction &segment) -{ - for (auto &type : segment.get_type_path_function ().get_params ()) - type->accept_vis (*this); - - segment.get_type_path_function ().get_return_type ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::TypePath &path) -{ - for (auto &seg : path.get_segments ()) - seg->accept_vis (*this); -} - -void EarlyNameResolver::visit (AST::QualifiedPathInExpression &path) { resolve_qualified_path_type (path.get_qualified_path_type ()); @@ -230,117 +208,6 @@ EarlyNameResolver::visit (AST::MetaItemPathLit &) {} void -EarlyNameResolver::visit (AST::BorrowExpr &expr) -{ - expr.get_borrowed_expr ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::DereferenceExpr &expr) -{ - expr.get_dereferenced_expr ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::ErrorPropagationExpr &expr) -{ - expr.get_propagating_expr ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::NegationExpr &expr) -{ - expr.get_negated_expr ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::ArithmeticOrLogicalExpr &expr) -{ - expr.get_left_expr ()->accept_vis (*this); - expr.get_right_expr ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::ComparisonExpr &expr) -{ - expr.get_left_expr ()->accept_vis (*this); - expr.get_right_expr ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::LazyBooleanExpr &expr) -{ - expr.get_left_expr ()->accept_vis (*this); - expr.get_right_expr ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::TypeCastExpr &expr) -{ - expr.get_casted_expr ()->accept_vis (*this); - expr.get_type_to_cast_to ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::AssignmentExpr &expr) -{ - expr.get_left_expr ()->accept_vis (*this); - expr.get_right_expr ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::CompoundAssignmentExpr &expr) -{ - expr.get_left_expr ()->accept_vis (*this); - expr.get_right_expr ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::GroupedExpr &expr) -{ - expr.get_expr_in_parens ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::ArrayElemsValues &elems) -{ - for (auto &expr : elems.get_values ()) - expr->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::ArrayElemsCopied &elems) -{ - elems.get_elem_to_copy ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::ArrayExpr &expr) -{ - expr.get_array_elems ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::ArrayIndexExpr &expr) -{ - expr.get_array_expr ()->accept_vis (*this); - expr.get_index_expr ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::TupleExpr &expr) -{ - for (auto &elem : expr.get_tuple_elems ()) - elem->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::TupleIndexExpr &expr) -{ - expr.get_tuple_expr ()->accept_vis (*this); -} - -void EarlyNameResolver::visit (AST::StructExprStruct &) {} @@ -349,61 +216,10 @@ EarlyNameResolver::visit (AST::StructExprFieldIdentifier &) {} void -EarlyNameResolver::visit (AST::StructExprFieldIdentifierValue &field) -{ - field.get_value ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::StructExprFieldIndexValue &field) -{ - field.get_value ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::StructExprStructFields &expr) -{ - for (auto &field : expr.get_fields ()) - field->accept_vis (*this); -} - -void EarlyNameResolver::visit (AST::StructExprStructBase &) {} void -EarlyNameResolver::visit (AST::CallExpr &expr) -{ - expr.get_function_expr ()->accept_vis (*this); - for (auto ¶m : expr.get_params ()) - param->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::MethodCallExpr &expr) -{ - expr.get_receiver_expr ()->accept_vis (*this); - for (auto ¶m : expr.get_params ()) - param->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::FieldAccessExpr &expr) -{ - expr.get_receiver_expr ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::ClosureExprInner &expr) -{ - expr.get_definition_expr ()->accept_vis (*this); - - for (auto ¶m : expr.get_params ()) - if (param.has_type_given ()) - param.get_type ()->accept_vis (*this); -} - -void EarlyNameResolver::visit (AST::BlockExpr &expr) { scoped (expr.get_node_id (), [&expr, this] () { @@ -416,95 +232,14 @@ EarlyNameResolver::visit (AST::BlockExpr &expr) } void -EarlyNameResolver::visit (AST::ClosureExprInnerTyped &expr) -{ - expr.get_definition_block ()->accept_vis (*this); - - for (auto ¶m : expr.get_params ()) - param.get_type ()->accept_vis (*this); -} - -void EarlyNameResolver::visit (AST::ContinueExpr &) {} void -EarlyNameResolver::visit (AST::BreakExpr &expr) -{ - if (expr.has_break_expr ()) - expr.get_break_expr ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::RangeFromToExpr &expr) -{ - expr.get_from_expr ()->accept_vis (*this); - expr.get_to_expr ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::RangeFromExpr &expr) -{ - expr.get_from_expr ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::RangeToExpr &expr) -{ - expr.get_to_expr ()->accept_vis (*this); -} - -void EarlyNameResolver::visit (AST::RangeFullExpr &) {} void -EarlyNameResolver::visit (AST::RangeFromToInclExpr &expr) -{ - expr.get_from_expr ()->accept_vis (*this); - expr.get_to_expr ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::RangeToInclExpr &expr) -{ - expr.get_to_expr ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::ReturnExpr &expr) -{ - if (expr.has_returned_expr ()) - expr.get_returned_expr ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::UnsafeBlockExpr &expr) -{ - expr.get_block_expr ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::LoopExpr &expr) -{ - expr.get_loop_block ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::WhileLoopExpr &expr) -{ - expr.get_predicate_expr ()->accept_vis (*this); - expr.get_loop_block ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::WhileLetLoopExpr &expr) -{ - expr.get_scrutinee_expr ()->accept_vis (*this); - expr.get_loop_block ()->accept_vis (*this); -} - -void EarlyNameResolver::visit (AST::ForLoopExpr &expr) { scoped (expr.get_node_id (), [&expr, this] () { @@ -515,21 +250,6 @@ EarlyNameResolver::visit (AST::ForLoopExpr &expr) } void -EarlyNameResolver::visit (AST::IfExpr &expr) -{ - expr.get_condition_expr ()->accept_vis (*this); - expr.get_if_block ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::IfExprConseqElse &expr) -{ - expr.get_condition_expr ()->accept_vis (*this); - expr.get_if_block ()->accept_vis (*this); - expr.get_else_block ()->accept_vis (*this); -} - -void EarlyNameResolver::visit (AST::IfLetExpr &expr) { expr.get_value_expr ()->accept_vis (*this); @@ -539,14 +259,6 @@ EarlyNameResolver::visit (AST::IfLetExpr &expr) } void -EarlyNameResolver::visit (AST::IfLetExprConseqElse &expr) -{ - expr.get_value_expr ()->accept_vis (*this); - expr.get_if_block ()->accept_vis (*this); - expr.get_else_block ()->accept_vis (*this); -} - -void EarlyNameResolver::visit (AST::MatchExpr &expr) { expr.get_scrutinee_expr ()->accept_vis (*this); @@ -568,39 +280,10 @@ EarlyNameResolver::visit (AST::MatchExpr &expr) } void -EarlyNameResolver::visit (AST::AwaitExpr &expr) -{ - expr.get_awaited_expr ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::AsyncBlockExpr &expr) -{ - expr.get_block_expr ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::TypeParam ¶m) -{ - for (auto &bound : param.get_type_param_bounds ()) - bound->accept_vis (*this); - - if (param.has_type ()) - param.get_type ()->accept_vis (*this); -} - -void EarlyNameResolver::visit (AST::LifetimeWhereClauseItem &) {} void -EarlyNameResolver::visit (AST::TypeBoundWhereClauseItem &item) -{ - for (auto &bound : item.get_type_param_bounds ()) - bound->accept_vis (*this); -} - -void EarlyNameResolver::visit (AST::Module &module) { if (module.get_kind () == AST::Module::UNLOADED) @@ -656,141 +339,14 @@ EarlyNameResolver::visit (AST::UseDeclaration &) {} void -EarlyNameResolver::visit (AST::Function &function) -{ - if (function.has_generics ()) - for (auto &generic : function.get_generic_params ()) - generic->accept_vis (*this); - - for (auto &p : function.get_function_params ()) - p->accept_vis (*this); - - if (function.has_return_type ()) - function.get_return_type ()->accept_vis (*this); - - function.get_definition ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::TypeAlias &type_alias) -{ - type_alias.get_type_aliased ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::StructStruct &struct_item) -{ - for (auto &field : struct_item.get_fields ()) - field.get_field_type ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::TupleStruct &tuple_struct) -{ - for (auto &field : tuple_struct.get_fields ()) - field.get_field_type ()->accept_vis (*this); -} - -void EarlyNameResolver::visit (AST::EnumItem &) {} void -EarlyNameResolver::visit (AST::EnumItemTuple &item) -{ - for (auto &field : item.get_tuple_fields ()) - field.get_field_type ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::EnumItemStruct &item) -{ - for (auto &field : item.get_struct_fields ()) - field.get_field_type ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::EnumItemDiscriminant &item) -{ - item.get_expr ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::Enum &enum_item) -{ - for (auto &generic : enum_item.get_generic_params ()) - generic->accept_vis (*this); - - for (auto &variant : enum_item.get_variants ()) - variant->accept_vis (*this); -} - -void EarlyNameResolver::visit (AST::Union &) {} void -EarlyNameResolver::visit (AST::ConstantItem &const_item) -{ - const_item.get_type ()->accept_vis (*this); - if (const_item.has_expr ()) - const_item.get_expr ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::StaticItem &static_item) -{ - static_item.get_type ()->accept_vis (*this); - static_item.get_expr ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::TraitItemFunc &item) -{ - auto &decl = item.get_trait_function_decl (); - - if (decl.has_return_type ()) - decl.get_return_type ()->accept_vis (*this); - - for (auto &generic : decl.get_generic_params ()) - generic->accept_vis (*this); - - for (auto &p : decl.get_function_params ()) - p->accept_vis (*this); - - if (item.has_definition ()) - item.get_definition ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::TraitItemMethod &item) -{ - // FIXME: Can we factor this with the above function? - auto &decl = item.get_trait_method_decl (); - - if (decl.has_return_type ()) - decl.get_return_type ()->accept_vis (*this); - - for (auto &generic : decl.get_generic_params ()) - generic->accept_vis (*this); - - for (auto &p : decl.get_function_params ()) - p->accept_vis (*this); - - if (item.has_definition ()) - item.get_definition ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::TraitItemConst &item) -{ - item.get_type ()->accept_vis (*this); - - if (item.has_expr ()) - item.get_expr ()->accept_vis (*this); -} - -void EarlyNameResolver::visit (AST::TraitItemType &) {} @@ -841,26 +397,6 @@ EarlyNameResolver::visit (AST::ExternalTypeItem &item) } void -EarlyNameResolver::visit (AST::ExternalStaticItem &item) -{ - item.get_type ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::ExternalFunctionItem &item) -{ - for (auto &generic : item.get_generic_params ()) - generic->accept_vis (*this); - - for (auto ¶m : item.get_function_params ()) - if (!param.is_variadic ()) - param.get_type ()->accept_vis (*this); - - if (item.has_return_type ()) - item.get_return_type ()->accept_vis (*this); -} - -void EarlyNameResolver::visit (AST::ExternBlock &block) { scoped (block.get_node_id (), [&block, this] () { @@ -870,10 +406,6 @@ EarlyNameResolver::visit (AST::ExternBlock &block) } void -EarlyNameResolver::visit (AST::MacroMatchFragment &) -{} - -void EarlyNameResolver::visit (AST::MacroMatchRepetition &) {} @@ -992,10 +524,6 @@ EarlyNameResolver::visit (AST::MetaItemSeq &) {} void -EarlyNameResolver::visit (AST::MetaWord &) -{} - -void EarlyNameResolver::visit (AST::MetaNameValueStr &) {} @@ -1008,25 +536,6 @@ EarlyNameResolver::visit (AST::MetaListNameValueStr &) {} void -EarlyNameResolver::visit (AST::LiteralPattern &) -{} - -void -EarlyNameResolver::visit (AST::IdentifierPattern &pattern) -{ - if (pattern.has_pattern_to_bind ()) - pattern.get_pattern_to_bind ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::WildcardPattern &) -{} - -void -EarlyNameResolver::visit (AST::RestPattern &) -{} - -void EarlyNameResolver::visit (AST::RangePatternBoundLiteral &) {} @@ -1039,31 +548,6 @@ EarlyNameResolver::visit (AST::RangePatternBoundQualPath &) {} void -EarlyNameResolver::visit (AST::RangePattern &pattern) -{ - pattern.get_lower_bound ()->accept_vis (*this); - pattern.get_upper_bound ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::ReferencePattern &pattern) -{ - pattern.get_referenced_pattern ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::StructPatternFieldTuplePat &field) -{ - field.get_index_pattern ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::StructPatternFieldIdentPat &field) -{ - field.get_ident_pattern ()->accept_vis (*this); -} - -void EarlyNameResolver::visit (AST::StructPatternFieldIdent &) {} @@ -1072,22 +556,6 @@ EarlyNameResolver::visit (AST::StructPattern &) {} void -EarlyNameResolver::visit (AST::TupleStructItemsNoRange &tuple_items) -{ - for (auto &pattern : tuple_items.get_patterns ()) - pattern->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::TupleStructItemsRange &tuple_items) -{ - for (auto &pattern : tuple_items.get_lower_patterns ()) - pattern->accept_vis (*this); - for (auto &pattern : tuple_items.get_upper_patterns ()) - pattern->accept_vis (*this); -} - -void EarlyNameResolver::visit (AST::TupleStructPattern &pattern) { if (!pattern.has_items ()) @@ -1104,70 +572,6 @@ EarlyNameResolver::visit (AST::TupleStructPattern &pattern) } void -EarlyNameResolver::visit (AST::TuplePatternItemsMultiple &tuple_items) -{ - for (auto &pattern : tuple_items.get_patterns ()) - pattern->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::TuplePatternItemsRanged &tuple_items) -{ - for (auto &pattern : tuple_items.get_lower_patterns ()) - pattern->accept_vis (*this); - for (auto &pattern : tuple_items.get_upper_patterns ()) - pattern->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::TuplePattern &pattern) -{ - pattern.get_items ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::GroupedPattern &pattern) -{ - pattern.get_pattern_in_parens ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::SlicePattern &pattern) -{ - for (auto &item : pattern.get_items ()) - item->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::AltPattern &pattern) -{ - for (auto &alt : pattern.get_alts ()) - alt->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::EmptyStmt &) -{} - -void -EarlyNameResolver::visit (AST::LetStmt &stmt) -{ - if (stmt.has_type ()) - stmt.get_type ()->accept_vis (*this); - - if (stmt.has_init_expr ()) - stmt.get_init_expr ()->accept_vis (*this); - - stmt.get_pattern ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::ExprStmt &stmt) -{ - stmt.get_expr ()->accept_vis (*this); -} - -void EarlyNameResolver::visit (AST::TraitBound &) {} @@ -1196,10 +600,6 @@ EarlyNameResolver::visit (AST::TupleType &) {} void -EarlyNameResolver::visit (AST::NeverType &) -{} - -void EarlyNameResolver::visit (AST::RawPointerType &) {} @@ -1219,38 +619,5 @@ void EarlyNameResolver::visit (AST::InferredType &) {} -void -EarlyNameResolver::visit (AST::BareFunctionType &type) -{ - for (auto ¶m : type.get_function_params ()) - param.get_type ()->accept_vis (*this); - - if (type.has_return_type ()) - type.get_return_type ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::VariadicParam ¶m) -{ - if (param.has_pattern ()) - param.get_pattern ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::FunctionParam ¶m) -{ - param.get_pattern ()->accept_vis (*this); - param.get_type ()->accept_vis (*this); -} - -void -EarlyNameResolver::visit (AST::SelfParam ¶m) -{ - if (param.has_type ()) - param.get_type ()->accept_vis (*this); - if (param.has_lifetime ()) - param.get_lifetime ().accept_vis (*this); -} - } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/resolve/rust-early-name-resolver.h b/gcc/rust/resolve/rust-early-name-resolver.h index cebc6e4..bf62ec1 100644 --- a/gcc/rust/resolve/rust-early-name-resolver.h +++ b/gcc/rust/resolve/rust-early-name-resolver.h @@ -27,7 +27,7 @@ namespace Rust { namespace Resolver { -class EarlyNameResolver : public AST::ASTVisitor +class EarlyNameResolver : public AST::DefaultASTVisitor { public: EarlyNameResolver (); @@ -35,6 +35,7 @@ public: void go (AST::Crate &crate); private: + using AST::DefaultASTVisitor::visit; /** * Execute a lambda within a scope. This is equivalent to calling * `enter_scope` before your code and `exit_scope` after. This ensures @@ -126,18 +127,14 @@ private: */ void resolve_qualified_path_type (AST::QualifiedPathType &path); - virtual void visit (AST::Token &tok); + virtual void visit (AST::Crate &crate); virtual void visit (AST::DelimTokenTree &delim_tok_tree); virtual void visit (AST::AttrInputMetaItemContainer &input); virtual void visit (AST::IdentifierExpr &ident_expr); - virtual void visit (AST::Lifetime &lifetime); virtual void visit (AST::LifetimeParam &lifetime_param); virtual void visit (AST::ConstGenericParam &const_param); virtual void visit (AST::PathInExpression &path); - virtual void visit (AST::TypePathSegment &segment); virtual void visit (AST::TypePathSegmentGeneric &segment); - virtual void visit (AST::TypePathSegmentFunction &segment); - virtual void visit (AST::TypePath &path); virtual void visit (AST::QualifiedPathInExpression &path); virtual void visit (AST::QualifiedPathInType &path); virtual void visit (AST::LiteralExpr &expr); @@ -145,124 +142,45 @@ private: virtual void visit (AST::AttrInputMacro &attr_input); virtual void visit (AST::MetaItemLitExpr &meta_item); virtual void visit (AST::MetaItemPathLit &meta_item); - virtual void visit (AST::BorrowExpr &expr); - virtual void visit (AST::DereferenceExpr &expr); - virtual void visit (AST::ErrorPropagationExpr &expr); - virtual void visit (AST::NegationExpr &expr); - virtual void visit (AST::ArithmeticOrLogicalExpr &expr); - virtual void visit (AST::ComparisonExpr &expr); - virtual void visit (AST::LazyBooleanExpr &expr); - virtual void visit (AST::TypeCastExpr &expr); - virtual void visit (AST::AssignmentExpr &expr); - virtual void visit (AST::CompoundAssignmentExpr &expr); - virtual void visit (AST::GroupedExpr &expr); - virtual void visit (AST::ArrayElemsValues &elems); - virtual void visit (AST::ArrayElemsCopied &elems); - virtual void visit (AST::ArrayExpr &expr); - virtual void visit (AST::ArrayIndexExpr &expr); - virtual void visit (AST::TupleExpr &expr); - virtual void visit (AST::TupleIndexExpr &expr); virtual void visit (AST::StructExprStruct &expr); virtual void visit (AST::StructExprFieldIdentifier &field); - virtual void visit (AST::StructExprFieldIdentifierValue &field); - virtual void visit (AST::StructExprFieldIndexValue &field); - virtual void visit (AST::StructExprStructFields &expr); virtual void visit (AST::StructExprStructBase &expr); - virtual void visit (AST::CallExpr &expr); - virtual void visit (AST::MethodCallExpr &expr); - virtual void visit (AST::FieldAccessExpr &expr); - virtual void visit (AST::ClosureExprInner &expr); virtual void visit (AST::BlockExpr &expr); - virtual void visit (AST::ClosureExprInnerTyped &expr); virtual void visit (AST::ContinueExpr &expr); - virtual void visit (AST::BreakExpr &expr); - virtual void visit (AST::RangeFromToExpr &expr); - virtual void visit (AST::RangeFromExpr &expr); - virtual void visit (AST::RangeToExpr &expr); virtual void visit (AST::RangeFullExpr &expr); - virtual void visit (AST::RangeFromToInclExpr &expr); - virtual void visit (AST::RangeToInclExpr &expr); - virtual void visit (AST::ReturnExpr &expr); - virtual void visit (AST::UnsafeBlockExpr &expr); - virtual void visit (AST::LoopExpr &expr); - virtual void visit (AST::WhileLoopExpr &expr); - virtual void visit (AST::WhileLetLoopExpr &expr); virtual void visit (AST::ForLoopExpr &expr); - virtual void visit (AST::IfExpr &expr); - virtual void visit (AST::IfExprConseqElse &expr); virtual void visit (AST::IfLetExpr &expr); - virtual void visit (AST::IfLetExprConseqElse &expr); virtual void visit (AST::MatchExpr &expr); - virtual void visit (AST::AwaitExpr &expr); - virtual void visit (AST::AsyncBlockExpr &expr); - virtual void visit (AST::TypeParam ¶m); virtual void visit (AST::LifetimeWhereClauseItem &item); - virtual void visit (AST::TypeBoundWhereClauseItem &item); virtual void visit (AST::Module &module); virtual void visit (AST::ExternCrate &crate); virtual void visit (AST::UseTreeGlob &use_tree); virtual void visit (AST::UseTreeList &use_tree); virtual void visit (AST::UseTreeRebind &use_tree); virtual void visit (AST::UseDeclaration &use_decl); - virtual void visit (AST::Function &function); - virtual void visit (AST::TypeAlias &type_alias); - virtual void visit (AST::StructStruct &struct_item); - virtual void visit (AST::TupleStruct &tuple_struct); virtual void visit (AST::EnumItem &item); - virtual void visit (AST::EnumItemTuple &item); - virtual void visit (AST::EnumItemStruct &item); - virtual void visit (AST::EnumItemDiscriminant &item); - virtual void visit (AST::Enum &enum_item); virtual void visit (AST::Union &union_item); - virtual void visit (AST::ConstantItem &const_item); - virtual void visit (AST::StaticItem &static_item); - virtual void visit (AST::TraitItemFunc &item); - virtual void visit (AST::TraitItemMethod &item); - virtual void visit (AST::TraitItemConst &item); virtual void visit (AST::TraitItemType &item); virtual void visit (AST::Trait &trait); virtual void visit (AST::InherentImpl &impl); virtual void visit (AST::TraitImpl &impl); virtual void visit (AST::ExternalTypeItem &item); - virtual void visit (AST::ExternalStaticItem &item); - virtual void visit (AST::ExternalFunctionItem &item); virtual void visit (AST::ExternBlock &block); - virtual void visit (AST::MacroMatchFragment &match); virtual void visit (AST::MacroMatchRepetition &match); virtual void visit (AST::MacroMatcher &matcher); virtual void visit (AST::MacroRulesDefinition &rules_def); virtual void visit (AST::MacroInvocation ¯o_invoc); virtual void visit (AST::MetaItemPath &meta_item); virtual void visit (AST::MetaItemSeq &meta_item); - virtual void visit (AST::MetaWord &meta_item); virtual void visit (AST::MetaNameValueStr &meta_item); virtual void visit (AST::MetaListPaths &meta_item); virtual void visit (AST::MetaListNameValueStr &meta_item); - virtual void visit (AST::LiteralPattern &pattern); - virtual void visit (AST::IdentifierPattern &pattern); - virtual void visit (AST::WildcardPattern &pattern); - virtual void visit (AST::RestPattern &pattern); virtual void visit (AST::RangePatternBoundLiteral &bound); virtual void visit (AST::RangePatternBoundPath &bound); virtual void visit (AST::RangePatternBoundQualPath &bound); - virtual void visit (AST::RangePattern &pattern); - virtual void visit (AST::ReferencePattern &pattern); - virtual void visit (AST::StructPatternFieldTuplePat &field); - virtual void visit (AST::StructPatternFieldIdentPat &field); virtual void visit (AST::StructPatternFieldIdent &field); virtual void visit (AST::StructPattern &pattern); - virtual void visit (AST::TupleStructItemsNoRange &tuple_items); - virtual void visit (AST::TupleStructItemsRange &tuple_items); virtual void visit (AST::TupleStructPattern &pattern); - virtual void visit (AST::TuplePatternItemsMultiple &tuple_items); - virtual void visit (AST::TuplePatternItemsRanged &tuple_items); - virtual void visit (AST::TuplePattern &pattern); - virtual void visit (AST::GroupedPattern &pattern); - virtual void visit (AST::SlicePattern &pattern); - virtual void visit (AST::AltPattern &pattern); - virtual void visit (AST::EmptyStmt &stmt); - virtual void visit (AST::LetStmt &stmt); - virtual void visit (AST::ExprStmt &stmt); virtual void visit (AST::TraitBound &bound); virtual void visit (AST::ImplTraitType &type); virtual void visit (AST::TraitObjectType &type); @@ -270,17 +188,11 @@ private: virtual void visit (AST::ImplTraitTypeOneBound &type); virtual void visit (AST::TraitObjectTypeOneBound &type); virtual void visit (AST::TupleType &type); - virtual void visit (AST::NeverType &type); virtual void visit (AST::RawPointerType &type); virtual void visit (AST::ReferenceType &type); virtual void visit (AST::ArrayType &type); virtual void visit (AST::SliceType &type); virtual void visit (AST::InferredType &type); - virtual void visit (AST::BareFunctionType &type); - - virtual void visit (AST::VariadicParam &type); - virtual void visit (AST::FunctionParam &type); - virtual void visit (AST::SelfParam &type); }; } // namespace Resolver -- cgit v1.1 From a3f4152a312c873b0d81c0715946b15a04193700 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Thu, 30 Nov 2023 10:43:36 +0100 Subject: gccrs: Add multiple regression test in name resolution Local variables and functions or global variables have different resolution when binded to a variable. This was not covered before, even though it was handled by the new name resolution. This commit highlight this behavior from the new name resolution mechanism. gcc/testsuite/ChangeLog: * rust/compile/name_resolution11.rs: New test. * rust/compile/name_resolution12.rs: New test. * rust/compile/name_resolution13.rs: New test. Signed-off-by: Pierre-Emmanuel Patry --- gcc/testsuite/rust/compile/name_resolution11.rs | 7 +++++++ gcc/testsuite/rust/compile/name_resolution12.rs | 10 ++++++++++ gcc/testsuite/rust/compile/name_resolution13.rs | 9 +++++++++ 3 files changed, 26 insertions(+) create mode 100644 gcc/testsuite/rust/compile/name_resolution11.rs create mode 100644 gcc/testsuite/rust/compile/name_resolution12.rs create mode 100644 gcc/testsuite/rust/compile/name_resolution13.rs diff --git a/gcc/testsuite/rust/compile/name_resolution11.rs b/gcc/testsuite/rust/compile/name_resolution11.rs new file mode 100644 index 0000000..a464d2a --- /dev/null +++ b/gcc/testsuite/rust/compile/name_resolution11.rs @@ -0,0 +1,7 @@ +// { dg-additional-options "-frust-name-resolution-2.0 -frust-compile-until=lowering" } +fn foo() { + let b = 10; + fn bar() { + let a = foo; + } +} diff --git a/gcc/testsuite/rust/compile/name_resolution12.rs b/gcc/testsuite/rust/compile/name_resolution12.rs new file mode 100644 index 0000000..9cce31c --- /dev/null +++ b/gcc/testsuite/rust/compile/name_resolution12.rs @@ -0,0 +1,10 @@ +// { dg-additional-options "-frust-name-resolution-2.0 -frust-compile-until=lowering" } + +const TOTO: i32 = 10; + +fn foo() { + let b = 10; + fn bar() { + let e = TOTO; + } +} diff --git a/gcc/testsuite/rust/compile/name_resolution13.rs b/gcc/testsuite/rust/compile/name_resolution13.rs new file mode 100644 index 0000000..52a152b --- /dev/null +++ b/gcc/testsuite/rust/compile/name_resolution13.rs @@ -0,0 +1,9 @@ +// { dg-additional-options "-frust-name-resolution-2.0 -frust-compile-until=lowering" } + +fn foo() { + let b = 10; + fn bar() { + let c = b; + // { dg-error "cannot find value .b. in this scope .E0425." "" { target *-*-* } .-1 } + } +} -- cgit v1.1 From f5e04e40490e57bff2da0568ab9e67a33e644898 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Thu, 30 Nov 2023 13:27:01 +0100 Subject: gccrs: Add execution test for name resolution 2.0 We already have some compile tests but it lacked an execution test to ensure everything compiles correctly to the correct value. gcc/testsuite/ChangeLog: * rust/execute/torture/name_resolution.rs: New test. Signed-off-by: Pierre-Emmanuel Patry --- .../rust/execute/torture/name_resolution.rs | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 gcc/testsuite/rust/execute/torture/name_resolution.rs diff --git a/gcc/testsuite/rust/execute/torture/name_resolution.rs b/gcc/testsuite/rust/execute/torture/name_resolution.rs new file mode 100644 index 0000000..7492183 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/name_resolution.rs @@ -0,0 +1,24 @@ +// { dg-additional-options "-frust-name-resolution-2.0" } +// { dg-output "Value is 10\r*\n" } + +const BAZ: i32 = 10; + +extern "C" { + fn printf(s: *const i8, ...); +} + +fn foo() { + fn bar() { + let e = BAZ; + unsafe { + printf("Value is %i\n" as *const str as *const i8, e); + } + } + + bar(); +} + +fn main() -> i32 { + foo(); + 0 +} -- cgit v1.1 From 7a989394795a740dd4bcabbba251428cc9df08f1 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Wed, 22 Nov 2023 15:15:29 +0100 Subject: gccrs: Make function bodies truly optional Missing body on a function should be rejected at a later stage in the compiler, not during parsing. gcc/rust/ChangeLog: * ast/rust-ast-collector.cc (TokenCollector::visit): Adapt defintion getter. * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise. * expand/rust-cfg-strip.cc (CfgStrip::visit): Likewise. * expand/rust-expand-visitor.cc (ExpandVisitor::visit): Likewise. * hir/rust-ast-lower-implitem.h: Likewise. * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): Likewise. * resolve/rust-ast-resolve-item.cc (ResolveItem::visit): Likewise. * resolve/rust-ast-resolve-stmt.h: Likewise. * resolve/rust-default-resolver.cc (DefaultResolver::visit): Likewise. * util/rust-attributes.cc (AttributeChecker::visit): Likewise. * parse/rust-parse-impl.h: Allow empty function body during parsing. * ast/rust-ast.cc (Function::Function): Constructor now take an optional for the body. (Function::operator=): Adapt to new optional member. (Function::as_string): Likewise. * ast/rust-item.h (class Function): Make body optional and do not rely on nullptr anymore. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/ast/rust-ast-collector.cc | 7 +- gcc/rust/ast/rust-ast-visitor.cc | 3 +- gcc/rust/ast/rust-ast.cc | 24 +++---- gcc/rust/ast/rust-item.h | 13 ++-- gcc/rust/expand/rust-cfg-strip.cc | 16 +++-- gcc/rust/expand/rust-expand-visitor.cc | 8 ++- gcc/rust/hir/rust-ast-lower-implitem.h | 2 +- gcc/rust/hir/rust-ast-lower-item.cc | 2 +- gcc/rust/parse/rust-parse-impl.h | 105 +++++++++++++----------------- gcc/rust/resolve/rust-ast-resolve-item.cc | 2 +- gcc/rust/resolve/rust-ast-resolve-stmt.h | 2 +- gcc/rust/resolve/rust-default-resolver.cc | 3 +- gcc/rust/util/rust-attributes.cc | 3 +- 13 files changed, 92 insertions(+), 98 deletions(-) diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index 647724b..d5a98f1 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -1730,11 +1730,10 @@ TokenCollector::visit (Function &function) if (function.has_where_clause ()) visit (function.get_where_clause ()); - auto &block = function.get_definition (); - if (!block) - push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION)); + if (function.has_body ()) + visit (*function.get_definition ()); else - visit (block); + push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION)); newline (); } diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index 4ec5c7c..230a152b 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -777,7 +777,8 @@ DefaultASTVisitor::visit (AST::Function &function) if (function.has_return_type ()) visit (function.get_return_type ()); visit (function.get_where_clause ()); - visit (function.get_definition ()); + if (function.has_body ()) + visit (*function.get_definition ()); } void diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index 607f079..b909603 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -18,6 +18,7 @@ along with GCC; see the file COPYING3. If not see . */ #include "rust-ast.h" +#include "optional.h" #include "rust-system.h" #include "rust-ast-full.h" #include "rust-diagnostics.h" @@ -1100,8 +1101,10 @@ Function::Function (Function const &other) return_type = other.return_type->clone_type (); // guard to prevent null dereference (only required if error state) - if (other.function_body != nullptr) - function_body = other.function_body->clone_block_expr (); + if (other.has_body ()) + function_body = other.function_body.value ()->clone_block_expr (); + else + function_body = tl::nullopt; generic_params.reserve (other.generic_params.size ()); for (const auto &e : other.generic_params) @@ -1131,10 +1134,10 @@ Function::operator= (Function const &other) return_type = nullptr; // guard to prevent null dereference (only required if error state) - if (other.function_body != nullptr) - function_body = other.function_body->clone_block_expr (); + if (other.has_body ()) + function_body = other.function_body.value ()->clone_block_expr (); else - function_body = nullptr; + function_body = tl::nullopt; generic_params.reserve (other.generic_params.size ()); for (const auto &e : other.generic_params) @@ -1221,15 +1224,8 @@ Function::as_string () const str += "\n"; - // DEBUG: null pointer check - if (function_body == nullptr) - { - rust_debug ( - "something really terrible has gone wrong - null pointer function " - "body in function."); - return "NULL_POINTER_MARK"; - } - str += function_body->as_string () + "\n"; + if (has_body ()) + str += function_body.value ()->as_string () + "\n"; return str; } diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 9a83f3d..a995273 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -1299,7 +1299,7 @@ class Function : public VisItem, std::vector> function_params; std::unique_ptr return_type; WhereClause where_clause; - std::unique_ptr function_body; + tl::optional> function_body; location_t locus; bool is_default; @@ -1323,14 +1323,16 @@ public: return function_params.size () > 0 && function_params[0]->is_self (); } + bool has_body () const { return function_body.has_value (); } + // Mega-constructor with all possible fields Function (Identifier function_name, FunctionQualifiers qualifiers, std::vector> generic_params, std::vector> function_params, std::unique_ptr return_type, WhereClause where_clause, - std::unique_ptr function_body, Visibility vis, - std::vector outer_attrs, location_t locus, - bool is_default = false) + tl::optional> function_body, + Visibility vis, std::vector outer_attrs, + location_t locus, bool is_default = false) : VisItem (std::move (vis), std::move (outer_attrs)), qualifiers (std::move (qualifiers)), function_name (std::move (function_name)), @@ -1390,9 +1392,8 @@ public: } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_definition () + tl::optional> &get_definition () { - rust_assert (function_body != nullptr); return function_body; } diff --git a/gcc/rust/expand/rust-cfg-strip.cc b/gcc/rust/expand/rust-cfg-strip.cc index fd11565..0895201 100644 --- a/gcc/rust/expand/rust-cfg-strip.cc +++ b/gcc/rust/expand/rust-cfg-strip.cc @@ -2031,13 +2031,17 @@ CfgStrip::visit (AST::Function &function) /* body should always exist - if error state, should have returned * before now */ // can't strip block itself, but can strip sub-expressions - auto &block_expr = function.get_definition (); - block_expr->accept_vis (*this); - if (block_expr->is_marked_for_strip ()) - rust_error_at (block_expr->get_locus (), - "cannot strip block expression in this position - outer " - "attributes not allowed"); + if (function.has_body ()) + { + auto &block_expr = function.get_definition ().value (); + block_expr->accept_vis (*this); + if (block_expr->is_marked_for_strip ()) + rust_error_at (block_expr->get_locus (), + "cannot strip block expression in this position - outer " + "attributes not allowed"); + } } + void CfgStrip::visit (AST::TypeAlias &type_alias) { diff --git a/gcc/rust/expand/rust-expand-visitor.cc b/gcc/rust/expand/rust-expand-visitor.cc index 1745af0..ad473c2 100644 --- a/gcc/rust/expand/rust-expand-visitor.cc +++ b/gcc/rust/expand/rust-expand-visitor.cc @@ -1001,8 +1001,9 @@ ExpandVisitor::visit (AST::UseDeclaration &use_decl) void ExpandVisitor::visit (AST::Function &function) { - visit_inner_using_attrs (function, - function.get_definition ()->get_inner_attrs ()); + if (function.has_body ()) + visit_inner_using_attrs ( + function, function.get_definition ().value ()->get_inner_attrs ()); for (auto ¶m : function.get_generic_params ()) visit (param); @@ -1014,7 +1015,8 @@ ExpandVisitor::visit (AST::Function &function) if (function.has_where_clause ()) expand_where_clause (function.get_where_clause ()); - visit (function.get_definition ()); + if (function.has_body ()) + visit (*function.get_definition ()); } void diff --git a/gcc/rust/hir/rust-ast-lower-implitem.h b/gcc/rust/hir/rust-ast-lower-implitem.h index 096a30e..6f904dd 100644 --- a/gcc/rust/hir/rust-ast-lower-implitem.h +++ b/gcc/rust/hir/rust-ast-lower-implitem.h @@ -168,7 +168,7 @@ public: bool terminated = false; std::unique_ptr function_body = std::unique_ptr ( - ASTLoweringBlock::translate (function.get_definition ().get (), + ASTLoweringBlock::translate (function.get_definition ()->get (), &terminated)); auto crate_num = mappings->get_current_crate (); diff --git a/gcc/rust/hir/rust-ast-lower-item.cc b/gcc/rust/hir/rust-ast-lower-item.cc index 8d6ab7c..2895872 100644 --- a/gcc/rust/hir/rust-ast-lower-item.cc +++ b/gcc/rust/hir/rust-ast-lower-item.cc @@ -446,7 +446,7 @@ ASTLoweringItem::visit (AST::Function &function) bool terminated = false; std::unique_ptr function_body = std::unique_ptr ( - ASTLoweringBlock::translate (function.get_definition ().get (), + ASTLoweringBlock::translate (function.get_definition ()->get (), &terminated)); auto crate_num = mappings->get_current_crate (); diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index acceec3..52766af 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -23,6 +23,7 @@ * This is also the reason why there are no include guards. */ #include "rust-common.h" +#include "rust-expr.h" #include "rust-item.h" #include "rust-common.h" #include "rust-token.h" @@ -2976,14 +2977,21 @@ Parser::parse_function (AST::Visibility vis, // parse where clause - if exists AST::WhereClause where_clause = parse_where_clause (); - // parse block expression - std::unique_ptr block_expr = parse_block_expr (); + tl::optional> body = tl::nullopt; + if (lexer.peek_token ()->get_id () == SEMICOLON) + lexer.skip_token (); + else + { + std::unique_ptr block_expr = parse_block_expr (); + if (block_expr != nullptr) + body = std::move (block_expr); + } return std::unique_ptr ( new AST::Function (std::move (function_name), std::move (qualifiers), std::move (generic_params), std::move (function_params), std::move (return_type), std::move (where_clause), - std::move (block_expr), std::move (vis), + std::move (body), std::move (vis), std::move (outer_attrs), locus)); } @@ -5710,49 +5718,33 @@ Parser::parse_inherent_impl_function_or_method ( // parse where clause (optional) AST::WhereClause where_clause = parse_where_clause (); - // parse function definition (in block) - semicolon not allowed + tl::optional> body = tl::nullopt; if (lexer.peek_token ()->get_id () == SEMICOLON) + lexer.skip_token (); + else { - Error error (lexer.peek_token ()->get_locus (), - "%s declaration in inherent impl not allowed - must have " - "a definition", - is_method ? "method" : "function"); - add_error (std::move (error)); + auto result = parse_block_expr (); - lexer.skip_token (); - return nullptr; - } - std::unique_ptr body = parse_block_expr (); - if (body == nullptr) - { - Error error (lexer.peek_token ()->get_locus (), - "could not parse definition in inherent impl %s definition", - is_method ? "method" : "function"); - add_error (std::move (error)); + if (result == nullptr) + { + Error error ( + lexer.peek_token ()->get_locus (), + "could not parse definition in inherent impl %s definition", + is_method ? "method" : "function"); + add_error (std::move (error)); - skip_after_end_block (); - return nullptr; + skip_after_end_block (); + return nullptr; + } + body = std::move (result); } - // do actual if instead of ternary for return value optimisation - if (is_method) - { - return std::unique_ptr ( - new AST::Function (std::move (ident), std::move (qualifiers), - std::move (generic_params), - std::move (function_params), std::move (return_type), - std::move (where_clause), std::move (body), - std::move (vis), std::move (outer_attrs), locus)); - } - else - { - return std::unique_ptr ( - new AST::Function (std::move (ident), std::move (qualifiers), - std::move (generic_params), - std::move (function_params), std::move (return_type), - std::move (where_clause), std::move (body), - std::move (vis), std::move (outer_attrs), locus)); - } + return std::unique_ptr ( + new AST::Function (std::move (ident), std::move (qualifiers), + std::move (generic_params), std::move (function_params), + std::move (return_type), std::move (where_clause), + std::move (body), std::move (vis), + std::move (outer_attrs), locus)); } // Parses a single trait impl item (item inside a trait impl block). @@ -5960,27 +5952,24 @@ Parser::parse_trait_impl_function_or_method ( "successfully parsed where clause in function or method trait impl item"); // parse function definition (in block) - semicolon not allowed - if (lexer.peek_token ()->get_id () == SEMICOLON) - { - Error error ( - lexer.peek_token ()->get_locus (), - "%s declaration in trait impl not allowed - must have a definition", - is_method ? "method" : "function"); - add_error (std::move (error)); + tl::optional> body = tl::nullopt; - lexer.skip_token (); - return nullptr; - } - std::unique_ptr body = parse_block_expr (); - if (body == nullptr) + if (lexer.peek_token ()->get_id () == SEMICOLON) + lexer.skip_token (); + else { - Error error (lexer.peek_token ()->get_locus (), - "could not parse definition in trait impl %s definition", - is_method ? "method" : "function"); - add_error (std::move (error)); + auto result = parse_block_expr (); + if (result == nullptr) + { + Error error (lexer.peek_token ()->get_locus (), + "could not parse definition in trait impl %s definition", + is_method ? "method" : "function"); + add_error (std::move (error)); - skip_after_end_block (); - return nullptr; + skip_after_end_block (); + return nullptr; + } + body = std::move (result); } return std::unique_ptr ( diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc index eaee5bc..60eca5b 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.cc +++ b/gcc/rust/resolve/rust-ast-resolve-item.cc @@ -616,7 +616,7 @@ ResolveItem::visit (AST::Function &function) } // resolve the function body - ResolveExpr::go (function.get_definition ().get (), path, cpath); + ResolveExpr::go (function.get_definition ()->get (), path, cpath); resolver->get_name_scope ().pop (); resolver->get_type_scope ().pop (); diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h index 293c98f..f9aa93b 100644 --- a/gcc/rust/resolve/rust-ast-resolve-stmt.h +++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h @@ -378,7 +378,7 @@ public: } // resolve the function body - ResolveExpr::go (function.get_definition ().get (), path, cpath); + ResolveExpr::go (function.get_definition ()->get (), path, cpath); resolver->get_name_scope ().pop (); resolver->get_type_scope ().pop (); diff --git a/gcc/rust/resolve/rust-default-resolver.cc b/gcc/rust/resolve/rust-default-resolver.cc index 1ab174b..c1ed3ce 100644 --- a/gcc/rust/resolve/rust-default-resolver.cc +++ b/gcc/rust/resolve/rust-default-resolver.cc @@ -77,7 +77,8 @@ DefaultResolver::visit (AST::Function &function) } } - function.get_definition ()->accept_vis (*this); + if (function.has_body ()) + function.get_definition ().value ()->accept_vis (*this); }; ctx.scoped (Rib::Kind::Function, function.get_node_id (), def_fn); diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc index a1e2308..3c296b5 100644 --- a/gcc/rust/util/rust-attributes.cc +++ b/gcc/rust/util/rust-attributes.cc @@ -667,7 +667,8 @@ AttributeChecker::visit (AST::Function &fun) else if (result.name == "no_mangle") check_no_mangle_function (attribute, fun); } - fun.get_definition ()->accept_vis (*this); + if (fun.has_body ()) + fun.get_definition ().value ()->accept_vis (*this); } void -- cgit v1.1 From 04fd5a043b08fdc4d4e60499b8fd83d02007a737 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Wed, 22 Nov 2023 16:37:17 +0100 Subject: gccrs: Add validation for functions without body Add checks in the ast validation pass to error out with functions (either free or associated) without a definition. gcc/rust/ChangeLog: * checks/errors/rust-ast-validation.cc (ASTValidation::visit): Add a validation check and emit an error depending on the context. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/checks/errors/rust-ast-validation.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc index 2743eb0..6fb142c 100644 --- a/gcc/rust/checks/errors/rust-ast-validation.cc +++ b/gcc/rust/checks/errors/rust-ast-validation.cc @@ -109,6 +109,16 @@ ASTValidation::visit (AST::Function &function) function.get_self_param ()->get_locus (), "% parameter is only allowed in associated functions"); + if (!function.has_body ()) + { + if (context.back () == Context::INHERENT_IMPL + || context.back () == Context::TRAIT_IMPL) + rust_error_at (function.get_locus (), + "associated function in % without body"); + else if (context.back () != Context::TRAIT) + rust_error_at (function.get_locus (), "free function without a body"); + } + if (function.is_variadic ()) rust_error_at ( function.get_function_params ().back ()->get_locus (), -- cgit v1.1 From a7991de39ff3ef42cd48bb460a02134af73d7b9d Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Thu, 23 Nov 2023 14:08:50 +0100 Subject: gccrs: Add a regression test for function body check Function body check emit an error message when a required function body is missing. gcc/testsuite/ChangeLog: * rust/compile/functions_without_body.rs: New test. Signed-off-by: Pierre-Emmanuel Patry --- .../rust/compile/functions_without_body.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 gcc/testsuite/rust/compile/functions_without_body.rs diff --git a/gcc/testsuite/rust/compile/functions_without_body.rs b/gcc/testsuite/rust/compile/functions_without_body.rs new file mode 100644 index 0000000..36ddea5 --- /dev/null +++ b/gcc/testsuite/rust/compile/functions_without_body.rs @@ -0,0 +1,21 @@ +struct MyStruct; + +trait X {} + +fn test_a(); +// { dg-error "free function without a body" "" { target *-*-* } .-1 } + +impl MyStruct { + fn test_b() + // { dg-error "associated function in .impl. without body" "" { target *-*-* } .-1 } + where + T: Copy; + + fn test_c(); + // { dg-error "associated function in .impl. without body" "" { target *-*-* } .-1 } +} + +impl X for MyStruct { + fn test_d(); + // { dg-error "associated function in .impl. without body" "" { target *-*-* } .-1 } +} -- cgit v1.1 From f48f9a9ac6f20ffe2775437e3b21ed0208a9cee2 Mon Sep 17 00:00:00 2001 From: Nobel Singh Date: Tue, 5 Dec 2023 18:12:29 +0545 Subject: gccrs: Generate error for const trait functions Fixes issue #2040 Add check to assure that a function cant be declared const inside trait impl blocks. gcc/rust/ChangeLog: * checks/errors/rust-ast-validation.cc (ASTValidation::visit): Add check for const funtion. gcc/testsuite/ChangeLog: * rust/compile/issue-2040.rs: New test. Signed-off-by: Nobel Singh --- gcc/rust/checks/errors/rust-ast-validation.cc | 4 ++++ gcc/testsuite/rust/compile/issue-2040.rs | 12 ++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 gcc/testsuite/rust/compile/issue-2040.rs diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc index 6fb142c..cd197fc 100644 --- a/gcc/rust/checks/errors/rust-ast-validation.cc +++ b/gcc/rust/checks/errors/rust-ast-validation.cc @@ -103,6 +103,10 @@ ASTValidation::visit (AST::Function &function) rust_error_at (function.get_locus (), "functions cannot be both % and %"); + if (qualifiers.is_const () && context.back () == Context::TRAIT_IMPL) + rust_error_at (function.get_locus (), ErrorCode::E0379, + "functions in traits cannot be declared const"); + if (valid_context.find (context.back ()) == valid_context.end () && function.has_self_param ()) rust_error_at ( diff --git a/gcc/testsuite/rust/compile/issue-2040.rs b/gcc/testsuite/rust/compile/issue-2040.rs new file mode 100644 index 0000000..fbac168 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-2040.rs @@ -0,0 +1,12 @@ +trait Foo { + fn f() -> u32; +} + +impl Foo for u32 { + const fn f() -> u32 { + // { dg-error "functions in traits cannot be declared const" "" { target *-*-* } .-1 } + 22 + } +} + +fn main() {} -- cgit v1.1 From d7b2d6704f3350917b16f454163927e4c823802b Mon Sep 17 00:00:00 2001 From: Kushal Pal Date: Sat, 9 Dec 2023 12:04:01 +0530 Subject: gccrs: Renamed `WIN64` to `WIN_64` Fixes issue #2768 gcc/rust/ChangeLog: * backend/rust-compile-base.cc (HIRCompileBase::setup_abi_options): Renamed `WIN64` to `WIN_64` * util/rust-abi.cc (get_abi_from_string): Likewise (get_string_from_abi): Likewise * util/rust-abi.h (enum ABI): Likewise Signed-off-by: Kushal Pal --- gcc/rust/backend/rust-compile-base.cc | 2 +- gcc/rust/util/rust-abi.cc | 4 ++-- gcc/rust/util/rust-abi.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc index fcab75b..984492f 100644 --- a/gcc/rust/backend/rust-compile-base.cc +++ b/gcc/rust/backend/rust-compile-base.cc @@ -463,7 +463,7 @@ HIRCompileBase::setup_abi_options (tree fndecl, ABI abi) break; - case Rust::ABI::WIN64: + case Rust::ABI::WIN_64: abi_tree = get_identifier ("ms_abi"); break; diff --git a/gcc/rust/util/rust-abi.cc b/gcc/rust/util/rust-abi.cc index 05739e1..d17402e 100644 --- a/gcc/rust/util/rust-abi.cc +++ b/gcc/rust/util/rust-abi.cc @@ -40,7 +40,7 @@ get_abi_from_string (const std::string &abi) else if (abi.compare ("sysv64") == 0) return Rust::ABI::SYSV64; else if (abi.compare ("win64") == 0) - return Rust::ABI::WIN64; + return Rust::ABI::WIN_64; return Rust::ABI::UNKNOWN; } @@ -64,7 +64,7 @@ get_string_from_abi (Rust::ABI abi) return "fastcall"; case Rust::ABI::SYSV64: return "sysv64"; - case Rust::ABI::WIN64: + case Rust::ABI::WIN_64: return "win64"; case Rust::ABI::UNKNOWN: diff --git a/gcc/rust/util/rust-abi.h b/gcc/rust/util/rust-abi.h index d794cc3..a0180ed 100644 --- a/gcc/rust/util/rust-abi.h +++ b/gcc/rust/util/rust-abi.h @@ -30,7 +30,7 @@ enum ABI CDECL, STDCALL, FASTCALL, - WIN64, + WIN_64, SYSV64 }; -- cgit v1.1 From bdbc24c36cad3dc26324c4d5ea38f8bd0f02c9a8 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Sat, 9 Dec 2023 01:22:02 -0500 Subject: gccrs: Allow enabling lang_items and no_core features gcc/rust/ChangeLog: * checks/errors/rust-feature.cc (Feature::name_hash_map): Add entries for Name::LANG_ITEMS and Name::NO_CORE. * checks/errors/rust-feature.h (Feature::Name::LANG_ITEMS): New. (Feature::Name::NO_CORE): New. gcc/testsuite/ChangeLog: * rust/compile/sized-stub.rs: New test. Signed-off-by: Owen Avery --- gcc/rust/checks/errors/rust-feature.cc | 2 ++ gcc/rust/checks/errors/rust-feature.h | 2 ++ gcc/testsuite/rust/compile/sized-stub.rs | 6 ++++++ 3 files changed, 10 insertions(+) create mode 100644 gcc/testsuite/rust/compile/sized-stub.rs diff --git a/gcc/rust/checks/errors/rust-feature.cc b/gcc/rust/checks/errors/rust-feature.cc index 88649f1..c12710a 100644 --- a/gcc/rust/checks/errors/rust-feature.cc +++ b/gcc/rust/checks/errors/rust-feature.cc @@ -56,6 +56,8 @@ const std::map Feature::name_hash_map = { // later Rust versions {"optin_builtin_traits", Feature::Name::AUTO_TRAITS}, {"extern_types", Feature::Name::EXTERN_TYPES}, + {"lang_items", Feature::Name::LANG_ITEMS}, + {"no_core", Feature::Name::NO_CORE}, }; // namespace Rust tl::optional diff --git a/gcc/rust/checks/errors/rust-feature.h b/gcc/rust/checks/errors/rust-feature.h index 4ff059c..e6bc236 100644 --- a/gcc/rust/checks/errors/rust-feature.h +++ b/gcc/rust/checks/errors/rust-feature.h @@ -43,6 +43,8 @@ public: DECL_MACRO, AUTO_TRAITS, EXTERN_TYPES, + LANG_ITEMS, + NO_CORE, }; const std::string &as_string () { return m_name_str; } diff --git a/gcc/testsuite/rust/compile/sized-stub.rs b/gcc/testsuite/rust/compile/sized-stub.rs new file mode 100644 index 0000000..4e89b1f --- /dev/null +++ b/gcc/testsuite/rust/compile/sized-stub.rs @@ -0,0 +1,6 @@ +#![feature(lang_items)] +#![feature(no_core)] +#![no_core] + +#[lang = "sized"] +trait Sized {} -- cgit v1.1 From b3b5115533c44f6f9206a702586ac9b3fe6750cb Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Mon, 27 Nov 2023 17:00:56 +0100 Subject: gccrs: Make default resolver inherit from default visitor The default resolver put some scope in place but mostly has traversal functions similar to the default ast visitor, making it inherit from the default visitor allows us to avoid code duplication. gcc/rust/ChangeLog: * resolve/rust-default-resolver.cc (DefaultResolver::visit): Remove duplicated functions. * resolve/rust-default-resolver.h (class DefaultResolver): Make the default resolver inherit from the default visitor. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/resolve/rust-default-resolver.cc | 240 +----------------------------- gcc/rust/resolve/rust-default-resolver.h | 44 +----- 2 files changed, 5 insertions(+), 279 deletions(-) diff --git a/gcc/rust/resolve/rust-default-resolver.cc b/gcc/rust/resolve/rust-default-resolver.cc index c1ed3ce..ab4d5e8 100644 --- a/gcc/rust/resolve/rust-default-resolver.cc +++ b/gcc/rust/resolve/rust-default-resolver.cc @@ -18,6 +18,7 @@ #include "rust-default-resolver.h" #include "rust-ast-full.h" +#include "rust-ast-visitor.h" #include "rust-item.h" namespace Rust { @@ -148,27 +149,12 @@ DefaultResolver::visit (AST::StructStruct &type) // we also can't visit `StructField`s by default, so there's nothing to do - // correct? or should we do something like - for (auto &field : type.get_fields ()) - field.get_field_type ()->accept_vis (*this); + AST::DefaultASTVisitor::visit (type); // FIXME: ??? } void -DefaultResolver::visit (AST::TupleStruct &type) -{ - for (auto &field : type.get_fields ()) - field.get_field_type ()->accept_vis (*this); -} - -void -DefaultResolver::visit (AST::Union &type) -{ - for (auto &field : type.get_variants ()) - field.get_field_type ()->accept_vis (*this); -} - -void DefaultResolver::visit (AST::Enum &type) { // FIXME: Do we need to scope anything by default? @@ -183,118 +169,6 @@ DefaultResolver::visit (AST::Enum &type) } void -DefaultResolver::visit (AST::BorrowExpr &expr) -{ - expr.get_borrowed_expr ()->accept_vis (*this); -} - -void -DefaultResolver::visit (AST::DereferenceExpr &expr) -{ - expr.get_dereferenced_expr ()->accept_vis (*this); -} - -void -DefaultResolver::visit (AST::ErrorPropagationExpr &expr) -{ - expr.get_propagating_expr ()->accept_vis (*this); -} - -void -DefaultResolver::visit (AST::NegationExpr &expr) -{ - expr.get_negated_expr ()->accept_vis (*this); -} - -void -DefaultResolver::visit (AST::ArithmeticOrLogicalExpr &expr) -{ - expr.get_left_expr ()->accept_vis (*this); - expr.get_right_expr ()->accept_vis (*this); -} - -void -DefaultResolver::visit (AST::ComparisonExpr &expr) -{ - expr.get_left_expr ()->accept_vis (*this); - expr.get_right_expr ()->accept_vis (*this); -} - -void -DefaultResolver::visit (AST::LazyBooleanExpr &expr) -{ - expr.get_left_expr ()->accept_vis (*this); - expr.get_right_expr ()->accept_vis (*this); -} - -void -DefaultResolver::visit (AST::TypeCastExpr &expr) -{ - expr.get_type_to_cast_to ()->accept_vis (*this); - expr.get_casted_expr ()->accept_vis (*this); -} - -void -DefaultResolver::visit (AST::AssignmentExpr &expr) -{ - expr.get_left_expr ()->accept_vis (*this); - expr.get_right_expr ()->accept_vis (*this); -} - -void -DefaultResolver::visit (AST::CompoundAssignmentExpr &expr) -{ - expr.get_left_expr ()->accept_vis (*this); - expr.get_right_expr ()->accept_vis (*this); -} - -void -DefaultResolver::visit (AST::GroupedExpr &expr) -{ - expr.get_expr_in_parens ()->accept_vis (*this); -} - -void -DefaultResolver::visit (AST::ArrayElemsValues &array) -{ - for (auto &value : array.get_values ()) - value->accept_vis (*this); -} - -void -DefaultResolver::visit (AST::ArrayElemsCopied &array) -{ - array.get_elem_to_copy ()->accept_vis (*this); - array.get_num_copies ()->accept_vis (*this); -} - -void -DefaultResolver::visit (AST::ArrayExpr &expr) -{ - expr.get_array_elems ()->accept_vis (*this); -} - -void -DefaultResolver::visit (AST::ArrayIndexExpr &expr) -{ - expr.get_array_expr ()->accept_vis (*this); - expr.get_index_expr ()->accept_vis (*this); -} - -void -DefaultResolver::visit (AST::TupleExpr &expr) -{ - for (auto &element : expr.get_tuple_elems ()) - element->accept_vis (*this); -} - -void -DefaultResolver::visit (AST::TupleIndexExpr &expr) -{ - expr.get_tuple_expr ()->accept_vis (*this); -} - -void DefaultResolver::visit (AST::StructExprFieldIdentifierValue &) {} @@ -303,28 +177,6 @@ DefaultResolver::visit (AST::StructExprFieldIndexValue &) {} void -DefaultResolver::visit (AST::CallExpr &expr) -{ - expr.get_function_expr ()->accept_vis (*this); - for (auto ¶m : expr.get_params ()) - param->accept_vis (*this); -} - -void -DefaultResolver::visit (AST::MethodCallExpr &expr) -{ - expr.get_receiver_expr ()->accept_vis (*this); - for (auto ¶m : expr.get_params ()) - param->accept_vis (*this); -} - -void -DefaultResolver::visit (AST::FieldAccessExpr &expr) -{ - expr.get_receiver_expr ()->accept_vis (*this); -} - -void DefaultResolver::visit (AST::ClosureExprInner &) {} @@ -337,13 +189,6 @@ DefaultResolver::visit (AST::ContinueExpr &expr) {} void -DefaultResolver::visit (AST::BreakExpr &expr) -{ - if (expr.has_break_expr ()) - expr.get_break_expr ()->accept_vis (*this); -} - -void DefaultResolver::visit (AST::RangeFromToExpr &expr) {} @@ -356,10 +201,6 @@ DefaultResolver::visit (AST::RangeToExpr &expr) {} void -DefaultResolver::visit (AST::RangeFullExpr &expr) -{} - -void DefaultResolver::visit (AST::RangeFromToInclExpr &expr) {} @@ -416,28 +257,6 @@ DefaultResolver::visit (AST::AsyncBlockExpr &expr) {} void -DefaultResolver::visit (AST::LetStmt &let_stmt) -{ - let_stmt.get_pattern ()->accept_vis (*this); - - if (let_stmt.has_type ()) - let_stmt.get_type ()->accept_vis (*this); - - if (let_stmt.has_init_expr ()) - let_stmt.get_init_expr ()->accept_vis (*this); -} - -void -DefaultResolver::visit (AST::ExprStmt &stmt) -{ - stmt.get_expr ()->accept_vis (*this); -} - -void -DefaultResolver::visit (AST::Token &) -{} - -void DefaultResolver::visit (AST::DelimTokenTree &) {} @@ -450,10 +269,6 @@ DefaultResolver::visit (AST::IdentifierExpr &expr) {} void -DefaultResolver::visit (AST::Lifetime &) -{} - -void DefaultResolver::visit (AST::LifetimeParam &) {} @@ -466,10 +281,6 @@ DefaultResolver::visit (AST::PathInExpression &) {} void -DefaultResolver::visit (AST::TypePathSegment &) -{} - -void DefaultResolver::visit (AST::TypePathSegmentGeneric &) {} @@ -514,10 +325,6 @@ DefaultResolver::visit (AST::StructExprStruct &) {} void -DefaultResolver::visit (AST::StructExprFieldIdentifier &) -{} - -void DefaultResolver::visit (AST::StructExprStructFields &) {} @@ -624,10 +431,6 @@ DefaultResolver::visit (AST::ExternalFunctionItem &) {} void -DefaultResolver::visit (AST::MacroMatchFragment &) -{} - -void DefaultResolver::visit (AST::MacroMatchRepetition &) {} @@ -652,14 +455,6 @@ DefaultResolver::visit (AST::MetaItemSeq &) {} void -DefaultResolver::visit (AST::MetaWord &) -{} - -void -DefaultResolver::visit (AST::MetaNameValueStr &) -{} - -void DefaultResolver::visit (AST::MetaListPaths &) {} @@ -668,29 +463,6 @@ DefaultResolver::visit (AST::MetaListNameValueStr &) {} void -DefaultResolver::visit (AST::LiteralPattern &) -{} - -void -DefaultResolver::visit (AST::IdentifierPattern &pattern) -{ - if (pattern.has_pattern_to_bind ()) - pattern.get_pattern_to_bind ()->accept_vis (*this); -} - -void -DefaultResolver::visit (AST::WildcardPattern &) -{} - -void -DefaultResolver::visit (AST::RestPattern &) -{} - -void -DefaultResolver::visit (AST::RangePatternBoundLiteral &) -{} - -void DefaultResolver::visit (AST::RangePatternBoundPath &) {} @@ -791,10 +563,6 @@ DefaultResolver::visit (AST::TupleType &) {} void -DefaultResolver::visit (AST::NeverType &) -{} - -void DefaultResolver::visit (AST::RawPointerType &) {} @@ -811,10 +579,6 @@ DefaultResolver::visit (AST::SliceType &) {} void -DefaultResolver::visit (AST::InferredType &) -{} - -void DefaultResolver::visit (AST::BareFunctionType &) {} diff --git a/gcc/rust/resolve/rust-default-resolver.h b/gcc/rust/resolve/rust-default-resolver.h index 49255d3..20dbff8 100644 --- a/gcc/rust/resolve/rust-default-resolver.h +++ b/gcc/rust/resolve/rust-default-resolver.h @@ -32,9 +32,11 @@ namespace Resolver2_0 { * visiting each node's subnodes - a block's statements, a function call's * arguments... */ -class DefaultResolver : public AST::ASTVisitor +class DefaultResolver : public AST::DefaultASTVisitor { public: + using AST::DefaultASTVisitor::visit; + virtual ~DefaultResolver () {} // First, our lexical scope expressions - these visit their sub nodes, always @@ -51,41 +53,17 @@ public: // type dec nodes, which visit their fields or variants by default void visit (AST::StructStruct &); - void visit (AST::TupleStruct &); - void visit (AST::Union &); void visit (AST::Enum &); // Visitors that visit their expression node(s) - void visit (AST::BorrowExpr &); - void visit (AST::DereferenceExpr &); - void visit (AST::ErrorPropagationExpr &); - void visit (AST::NegationExpr &); - void visit (AST::ArithmeticOrLogicalExpr &); - void visit (AST::ComparisonExpr &); - void visit (AST::LazyBooleanExpr &); - void visit (AST::TypeCastExpr &); - void visit (AST::AssignmentExpr &); - void visit (AST::CompoundAssignmentExpr &); - void visit (AST::GroupedExpr &); - void visit (AST::ArrayElemsValues &); - void visit (AST::ArrayElemsCopied &); - void visit (AST::ArrayExpr &); - void visit (AST::ArrayIndexExpr &); - void visit (AST::TupleExpr &); - void visit (AST::TupleIndexExpr &); void visit (AST::StructExprFieldIdentifierValue &); void visit (AST::StructExprFieldIndexValue &); - void visit (AST::CallExpr &); - void visit (AST::MethodCallExpr &); - void visit (AST::FieldAccessExpr &); void visit (AST::ClosureExprInner &); void visit (AST::ClosureExprInnerTyped &); void visit (AST::ContinueExpr &); - void visit (AST::BreakExpr &); void visit (AST::RangeFromToExpr &); void visit (AST::RangeFromExpr &); void visit (AST::RangeToExpr &); - void visit (AST::RangeFullExpr &); void visit (AST::RangeFromToInclExpr &); void visit (AST::RangeToInclExpr &); void visit (AST::ReturnExpr &); @@ -100,19 +78,14 @@ public: void visit (AST::MatchExpr &); void visit (AST::AwaitExpr &); void visit (AST::AsyncBlockExpr &); - void visit (AST::LetStmt &); - void visit (AST::ExprStmt &); // Leaf visitors, which do nothing by default - void visit (AST::Token &); void visit (AST::DelimTokenTree &); void visit (AST::AttrInputMetaItemContainer &); void visit (AST::IdentifierExpr &); - void visit (AST::Lifetime &); void visit (AST::LifetimeParam &); void visit (AST::ConstGenericParam &); void visit (AST::PathInExpression &); - void visit (AST::TypePathSegment &); void visit (AST::TypePathSegmentGeneric &); void visit (AST::TypePathSegmentFunction &); void visit (AST::TypePath &); @@ -124,7 +97,6 @@ public: void visit (AST::MetaItemLitExpr &); void visit (AST::MetaItemPathLit &); void visit (AST::StructExprStruct &); - void visit (AST::StructExprFieldIdentifier &); void visit (AST::StructExprStructFields &); void visit (AST::StructExprStructBase &); void visit (AST::TypeParam &); @@ -149,22 +121,14 @@ public: void visit (AST::ExternalTypeItem &); void visit (AST::ExternalStaticItem &); void visit (AST::ExternalFunctionItem &); - void visit (AST::MacroMatchFragment &); void visit (AST::MacroMatchRepetition &); void visit (AST::MacroMatcher &); void visit (AST::MacroRulesDefinition &); void visit (AST::MacroInvocation &); void visit (AST::MetaItemPath &); void visit (AST::MetaItemSeq &); - void visit (AST::MetaWord &); - void visit (AST::MetaNameValueStr &); void visit (AST::MetaListPaths &); void visit (AST::MetaListNameValueStr &); - void visit (AST::LiteralPattern &); - void visit (AST::IdentifierPattern &); - void visit (AST::WildcardPattern &); - void visit (AST::RestPattern &); - void visit (AST::RangePatternBoundLiteral &); void visit (AST::RangePatternBoundPath &); void visit (AST::RangePatternBoundQualPath &); void visit (AST::RangePattern &); @@ -190,12 +154,10 @@ public: void visit (AST::ImplTraitTypeOneBound &); void visit (AST::TraitObjectTypeOneBound &); void visit (AST::TupleType &); - void visit (AST::NeverType &); void visit (AST::RawPointerType &); void visit (AST::ReferenceType &); void visit (AST::ArrayType &); void visit (AST::SliceType &); - void visit (AST::InferredType &); void visit (AST::BareFunctionType &); void visit (AST::FunctionParam &); void visit (AST::VariadicParam &); -- cgit v1.1 From 65fb288e0dacee46ba0d981e00e151064e2d4162 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Mon, 27 Nov 2023 14:12:20 +0100 Subject: gccrs: Make expand visitor inherit from default visitor Many visit functions in the expand visitor simply visit their components like the default visitor. Making the expand visitor inherit from the default visitor allows us to keep all visitor in sync without having to change every visitor. gcc/rust/ChangeLog: * expand/rust-expand-visitor.cc (ExpandVisitor::go): Add call to visit on the crate. (ExpandVisitor::visit): Remove some visit functions in favor of their default visitor counterpart. * expand/rust-expand-visitor.h (class ExpandVisitor): Inherit from default visitor and remove now useless function prototypes. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/expand/rust-expand-visitor.cc | 492 +-------------------------------- gcc/rust/expand/rust-expand-visitor.h | 82 +----- 2 files changed, 9 insertions(+), 565 deletions(-) diff --git a/gcc/rust/expand/rust-expand-visitor.cc b/gcc/rust/expand/rust-expand-visitor.cc index ad473c2..a60c472 100644 --- a/gcc/rust/expand/rust-expand-visitor.cc +++ b/gcc/rust/expand/rust-expand-visitor.cc @@ -39,7 +39,7 @@ is_builtin (AST::Attribute &attr) void ExpandVisitor::go (AST::Crate &crate) { - expand_inner_items (crate.items); + visit (crate); } static std::unique_ptr @@ -474,8 +474,10 @@ ExpandVisitor::expand_trait_method_decl (AST::TraitMethodDecl &decl) } void -ExpandVisitor::visit (AST::Token &) -{} +ExpandVisitor::visit (AST::Crate &crate) +{ + expand_inner_items (crate.items); +} void ExpandVisitor::visit (AST::DelimTokenTree &) @@ -490,10 +492,6 @@ ExpandVisitor::visit (AST::IdentifierExpr &ident_expr) {} void -ExpandVisitor::visit (AST::Lifetime &) -{} - -void ExpandVisitor::visit (AST::LifetimeParam &) {} @@ -517,10 +515,6 @@ ExpandVisitor::visit (AST::PathInExpression &path) } void -ExpandVisitor::visit (AST::TypePathSegment &) -{} - -void ExpandVisitor::visit (AST::TypePathSegmentGeneric &segment) {} @@ -537,13 +531,6 @@ ExpandVisitor::visit (AST::TypePathSegmentFunction &segment) } void -ExpandVisitor::visit (AST::TypePath &path) -{ - for (auto &segment : path.get_segments ()) - visit (segment); -} - -void ExpandVisitor::visit (AST::QualifiedPathInExpression &path) { expand_qualified_path_type (path.get_qualified_path_type ()); @@ -586,30 +573,12 @@ ExpandVisitor::visit (AST::MetaItemPathLit &) {} void -ExpandVisitor::visit (AST::BorrowExpr &expr) -{ - visit (expr.get_borrowed_expr ()); -} - -void -ExpandVisitor::visit (AST::DereferenceExpr &expr) -{ - visit (expr.get_dereferenced_expr ()); -} - -void ExpandVisitor::visit (AST::ErrorPropagationExpr &expr) { visit (expr.get_propagating_expr ()); } void -ExpandVisitor::visit (AST::NegationExpr &expr) -{ - visit (expr.get_negated_expr ()); -} - -void ExpandVisitor::visit (AST::ArithmeticOrLogicalExpr &expr) { maybe_expand_expr (expr.get_left_expr ()); @@ -631,14 +600,6 @@ ExpandVisitor::visit (AST::LazyBooleanExpr &expr) } void -ExpandVisitor::visit (AST::TypeCastExpr &expr) -{ - visit (expr.get_casted_expr ()); - - visit (expr.get_type_to_cast_to ()); -} - -void ExpandVisitor::visit (AST::AssignmentExpr &expr) { maybe_expand_expr (expr.get_left_expr ()); @@ -659,84 +620,10 @@ ExpandVisitor::visit (AST::GroupedExpr &expr) } void -ExpandVisitor::visit (AST::ArrayElemsValues &elems) -{ - for (auto &elem : elems.get_values ()) - visit (elem); -} - -void -ExpandVisitor::visit (AST::ArrayElemsCopied &elems) -{ - visit (elems.get_elem_to_copy ()); - visit (elems.get_num_copies ()); -} - -void -ExpandVisitor::visit (AST::ArrayExpr &expr) -{ - visit (expr.get_array_elems ()); -} - -void -ExpandVisitor::visit (AST::ArrayIndexExpr &expr) -{ - visit (expr.get_array_expr ()); - visit (expr.get_index_expr ()); -} - -void -ExpandVisitor::visit (AST::TupleExpr &expr) -{ - for (auto &element : expr.get_tuple_elems ()) - visit (element); -} - -void -ExpandVisitor::visit (AST::TupleIndexExpr &expr) -{ - visit (expr.get_tuple_expr ()); - - // We can't have macro invocations for tuple indexes, right? Need a test! -} - -void ExpandVisitor::visit (AST::StructExprStruct &expr) {} void -ExpandVisitor::visit (AST::StructExprFieldIdentifier &) -{} - -void -ExpandVisitor::visit (AST::StructExprFieldIdentifierValue &field) -{ - visit (field.get_value ()); -} - -void -ExpandVisitor::visit (AST::StructExprFieldIndexValue &field) -{ - visit (field.get_value ()); -} - -void -ExpandVisitor::visit (AST::StructExprStructFields &expr) -{ - for (auto &field : expr.get_fields ()) - visit (field); - - if (expr.has_struct_base ()) - visit (expr.get_struct_base ().get_base_struct ()); -} - -void -ExpandVisitor::visit (AST::StructExprStructBase &expr) -{ - visit (expr.get_struct_base ().get_base_struct ()); -} - -void ExpandVisitor::visit (AST::CallExpr &expr) { visit (expr.get_function_expr ()); @@ -755,12 +642,6 @@ ExpandVisitor::visit (AST::MethodCallExpr &expr) } void -ExpandVisitor::visit (AST::FieldAccessExpr &expr) -{ - visit (expr.get_receiver_expr ()); -} - -void ExpandVisitor::visit (AST::ClosureExprInner &expr) { expand_closure_params (expr.get_params ()); @@ -793,93 +674,6 @@ ExpandVisitor::visit (AST::ContinueExpr &expr) {} void -ExpandVisitor::visit (AST::BreakExpr &expr) -{ - if (expr.has_break_expr ()) - visit (expr.get_break_expr ()); -} - -void -ExpandVisitor::visit (AST::RangeFromToExpr &expr) -{ - visit (expr.get_from_expr ()); - visit (expr.get_to_expr ()); -} - -void -ExpandVisitor::visit (AST::RangeFromExpr &expr) -{ - visit (expr.get_from_expr ()); -} - -void -ExpandVisitor::visit (AST::RangeToExpr &expr) -{ - visit (expr.get_to_expr ()); -} - -void -ExpandVisitor::visit (AST::RangeFullExpr &) -{} - -void -ExpandVisitor::visit (AST::RangeFromToInclExpr &expr) -{ - visit (expr.get_from_expr ()); - visit (expr.get_to_expr ()); -} - -void -ExpandVisitor::visit (AST::RangeToInclExpr &expr) -{ - visit (expr.get_to_expr ()); -} - -void -ExpandVisitor::visit (AST::ReturnExpr &expr) -{ - if (expr.has_returned_expr ()) - visit (expr.get_returned_expr ()); -} - -void -ExpandVisitor::visit (AST::UnsafeBlockExpr &expr) -{ - visit (expr.get_block_expr ()); -} - -void -ExpandVisitor::visit (AST::LoopExpr &expr) -{ - visit (expr.get_loop_block ()); -} - -void -ExpandVisitor::visit (AST::WhileLoopExpr &expr) -{ - visit (expr.get_predicate_expr ()); - visit (expr.get_loop_block ()); -} - -void -ExpandVisitor::visit (AST::WhileLetLoopExpr &expr) -{ - for (auto &pattern : expr.get_patterns ()) - visit (pattern); - - visit (expr.get_scrutinee_expr ()); - visit (expr.get_loop_block ()); -} - -void -ExpandVisitor::visit (AST::ForLoopExpr &expr) -{ - visit (expr.get_pattern ()); - visit (expr.get_iterator_expr ()); - visit (expr.get_loop_block ()); -} - -void ExpandVisitor::visit (AST::IfExpr &expr) { maybe_expand_expr (expr.get_condition_expr ()); @@ -933,18 +727,6 @@ ExpandVisitor::visit (AST::MatchExpr &expr) } void -ExpandVisitor::visit (AST::AwaitExpr &expr) -{ - visit (expr.get_awaited_expr ()); -} - -void -ExpandVisitor::visit (AST::AsyncBlockExpr &expr) -{ - visit (expr.get_block_expr ()); -} - -void ExpandVisitor::visit (AST::TypeParam ¶m) { for (auto &bound : param.get_type_param_bounds ()) @@ -968,17 +750,6 @@ ExpandVisitor::visit (AST::TypeBoundWhereClauseItem &item) } void -ExpandVisitor::visit (AST::Module &module) -{ - if (module.get_kind () == AST::Module::ModuleKind::LOADED) - { - visit_inner_attrs (module); - for (auto &item : module.get_items ()) - visit (item); - } -} - -void ExpandVisitor::visit (AST::ExternCrate &crate) {} @@ -1020,12 +791,6 @@ ExpandVisitor::visit (AST::Function &function) } void -ExpandVisitor::visit (AST::TypeAlias &type_alias) -{ - visit (type_alias.get_type_aliased ()); -} - -void ExpandVisitor::visit (AST::StructStruct &struct_item) { for (auto &generic : struct_item.get_generic_params ()) @@ -1072,16 +837,6 @@ ExpandVisitor::visit (AST::EnumItemDiscriminant &item) } void -ExpandVisitor::visit (AST::Enum &enum_item) -{ - for (auto &generic : enum_item.get_generic_params ()) - visit (generic); - - for (auto &variant : enum_item.get_variants ()) - variant->accept_vis (*this); -} - -void ExpandVisitor::visit (AST::Union &union_item) { for (auto &generic : union_item.get_generic_params ()) @@ -1135,13 +890,6 @@ ExpandVisitor::visit (AST::TraitItemConst &const_item) } void -ExpandVisitor::visit (AST::TraitItemType &item) -{ - for (auto &type : item.get_type_param_bounds ()) - visit (type); -} - -void ExpandVisitor::visit (AST::Trait &trait) { for (auto &generic : trait.get_generic_params ()) @@ -1256,11 +1004,6 @@ ExpandVisitor::visit (AST::ExternBlock &block) block.get_extern_items (), extractor); } -// I don't think it would be possible to strip macros without expansion -void -ExpandVisitor::visit (AST::MacroMatchFragment &) -{} - void ExpandVisitor::visit (AST::MacroMatchRepetition &) {} @@ -1282,14 +1025,6 @@ ExpandVisitor::visit (AST::MetaItemSeq &) {} void -ExpandVisitor::visit (AST::MetaWord &) -{} - -void -ExpandVisitor::visit (AST::MetaNameValueStr &) -{} - -void ExpandVisitor::visit (AST::MetaListPaths &) {} @@ -1298,152 +1033,16 @@ ExpandVisitor::visit (AST::MetaListNameValueStr &) {} void -ExpandVisitor::visit (AST::LiteralPattern &) -{} - -void -ExpandVisitor::visit (AST::IdentifierPattern &pattern) -{ - if (pattern.has_pattern_to_bind ()) - visit (pattern.get_pattern_to_bind ()); -} - -void -ExpandVisitor::visit (AST::WildcardPattern &) -{} - -void -ExpandVisitor::visit (AST::RestPattern &) -{} - -void -ExpandVisitor::visit (AST::RangePatternBoundLiteral &) -{} - -void -ExpandVisitor::visit (AST::RangePatternBoundPath &bound) -{ - visit (bound.get_path ()); -} - -void -ExpandVisitor::visit (AST::RangePatternBoundQualPath &bound) -{ - visit (bound.get_qualified_path ()); -} - -void -ExpandVisitor::visit (AST::RangePattern &pattern) -{ - visit (pattern.get_lower_bound ()); - visit (pattern.get_upper_bound ()); -} - -void -ExpandVisitor::visit (AST::ReferencePattern &pattern) -{ - visit (pattern.get_referenced_pattern ()); -} - -void -ExpandVisitor::visit (AST::StructPatternFieldTuplePat &field) -{ - visit (field.get_index_pattern ()); -} - -void -ExpandVisitor::visit (AST::StructPatternFieldIdentPat &field) -{ - visit (field.get_ident_pattern ()); -} - -void ExpandVisitor::visit (AST::StructPatternFieldIdent &field) {} void -ExpandVisitor::visit (AST::StructPattern &pattern) -{ - visit (pattern.get_path ()); - - for (auto &inner : - pattern.get_struct_pattern_elems ().get_struct_pattern_fields ()) - visit (inner); -} - -void -ExpandVisitor::visit (AST::TupleStructItemsNoRange &tuple_items) -{ - for (auto &pattern : tuple_items.get_patterns ()) - visit (pattern); -} - -void -ExpandVisitor::visit (AST::TupleStructItemsRange &tuple_items) -{ - for (auto &lower_pattern : tuple_items.get_lower_patterns ()) - visit (lower_pattern); - for (auto &upper_pattern : tuple_items.get_upper_patterns ()) - visit (upper_pattern); -} - -void -ExpandVisitor::visit (AST::TupleStructPattern &pattern) -{ - visit (pattern.get_path ()); - - if (pattern.has_items ()) - visit (pattern.get_items ()); -} - -void -ExpandVisitor::visit (AST::TuplePatternItemsMultiple &tuple_items) -{ - for (auto &pattern : tuple_items.get_patterns ()) - visit (pattern); -} - -void -ExpandVisitor::visit (AST::TuplePatternItemsRanged &tuple_items) -{ - for (auto &pattern : tuple_items.get_lower_patterns ()) - visit (pattern); - for (auto &pattern : tuple_items.get_upper_patterns ()) - visit (pattern); -} - -void -ExpandVisitor::visit (AST::TuplePattern &pattern) -{ - if (pattern.has_tuple_pattern_items ()) - visit (pattern.get_items ()); -} - -void ExpandVisitor::visit (AST::GroupedPattern &pattern) { visit (pattern.get_pattern_in_parens ()); } void -ExpandVisitor::visit (AST::SlicePattern &pattern) -{ - for (auto &item : pattern.get_items ()) - visit (item); -} - -void -ExpandVisitor::visit (AST::AltPattern &pattern) -{ - for (auto &alt : pattern.get_alts ()) - visit (alt); -} - -void -ExpandVisitor::visit (AST::EmptyStmt &) -{} - -void ExpandVisitor::visit (AST::LetStmt &stmt) { visit (stmt.get_pattern ()); @@ -1462,83 +1061,6 @@ ExpandVisitor::visit (AST::ExprStmt &stmt) } void -ExpandVisitor::visit (AST::TraitBound &bound) -{ - visit (bound.get_type_path ()); -} - -void -ExpandVisitor::visit (AST::ImplTraitType &type) -{ - for (auto &bound : type.get_type_param_bounds ()) - visit (bound); -} - -void -ExpandVisitor::visit (AST::TraitObjectType &type) -{ - for (auto &bound : type.get_type_param_bounds ()) - visit (bound); -} - -void -ExpandVisitor::visit (AST::ParenthesisedType &type) -{ - visit (type.get_type_in_parens ()); -} - -void -ExpandVisitor::visit (AST::ImplTraitTypeOneBound &type) -{ - visit (type.get_trait_bound ()); -} - -void -ExpandVisitor::visit (AST::TraitObjectTypeOneBound &type) -{ - visit (type.get_trait_bound ()); -} - -void -ExpandVisitor::visit (AST::TupleType &type) -{ - for (auto &elem : type.get_elems ()) - visit (elem); -} - -void -ExpandVisitor::visit (AST::NeverType &) -{} - -void -ExpandVisitor::visit (AST::RawPointerType &type) -{ - visit (type.get_type_pointed_to ()); -} - -void -ExpandVisitor::visit (AST::ReferenceType &type) -{ - visit (type.get_type_referenced ()); -} - -void -ExpandVisitor::visit (AST::ArrayType &type) -{ - visit (type.get_elem_type ()); -} - -void -ExpandVisitor::visit (AST::SliceType &type) -{ - visit (type.get_elem_type ()); -} - -void -ExpandVisitor::visit (AST::InferredType &) -{} - -void ExpandVisitor::visit (AST::BareFunctionType &type) { for (auto ¶m : type.get_function_params ()) @@ -1551,10 +1073,6 @@ ExpandVisitor::visit (AST::BareFunctionType &type) } void -ExpandVisitor::visit (AST::VariadicParam ¶m) -{} - -void ExpandVisitor::visit (AST::FunctionParam ¶m) { maybe_expand_type (param.get_type ()); diff --git a/gcc/rust/expand/rust-expand-visitor.h b/gcc/rust/expand/rust-expand-visitor.h index 74f2673..bae9b0f 100644 --- a/gcc/rust/expand/rust-expand-visitor.h +++ b/gcc/rust/expand/rust-expand-visitor.h @@ -37,7 +37,7 @@ is_derive (AST::Attribute &attr); bool is_builtin (AST::Attribute &attr); -class ExpandVisitor : public AST::ASTVisitor +class ExpandVisitor : public AST::DefaultASTVisitor { public: ExpandVisitor (MacroExpander &expander) : expander (expander) {} @@ -45,6 +45,8 @@ public: /* Expand all of the macro invocations currently contained in a crate */ void go (AST::Crate &crate); + using AST::DefaultASTVisitor::visit; + /* Maybe expand a macro invocation in lieu of an expression */ void maybe_expand_expr (std::unique_ptr &expr); @@ -186,21 +188,18 @@ public: maybe_expand_type (type); } - void visit (AST::Token &) override; + void visit (AST::Crate &crate) override; void visit (AST::DelimTokenTree &) override; void visit (AST::AttrInputMetaItemContainer &) override; void visit (AST::IdentifierExpr &ident_expr) override; - void visit (AST::Lifetime &) override; void visit (AST::LifetimeParam &) override; void visit (AST::ConstGenericParam &) override; void visit (AST::MacroInvocation ¯o_invoc) override; void visit (AST::PathInExpression &path) override; - void visit (AST::TypePathSegment &) override; void visit (AST::TypePathSegmentGeneric &segment) override; void visit (AST::TypePathSegmentFunction &segment) override; - void visit (AST::TypePath &path) override; void visit (AST::QualifiedPathInExpression &path) override; void visit (AST::QualifiedPathInType &path) override; @@ -209,84 +208,49 @@ public: void visit (AST::AttrInputMacro &) override; void visit (AST::MetaItemLitExpr &) override; void visit (AST::MetaItemPathLit &) override; - void visit (AST::BorrowExpr &expr) override; - void visit (AST::DereferenceExpr &expr) override; void visit (AST::ErrorPropagationExpr &expr) override; - void visit (AST::NegationExpr &expr) override; void visit (AST::ArithmeticOrLogicalExpr &expr) override; void visit (AST::ComparisonExpr &expr) override; void visit (AST::LazyBooleanExpr &expr) override; - void visit (AST::TypeCastExpr &expr) override; void visit (AST::AssignmentExpr &expr) override; void visit (AST::CompoundAssignmentExpr &expr) override; void visit (AST::GroupedExpr &expr) override; - void visit (AST::ArrayElemsValues &elems) override; - void visit (AST::ArrayElemsCopied &elems) override; - void visit (AST::ArrayExpr &expr) override; - void visit (AST::ArrayIndexExpr &expr) override; - void visit (AST::TupleExpr &expr) override; - void visit (AST::TupleIndexExpr &expr) override; void visit (AST::StructExprStruct &expr) override; - void visit (AST::StructExprFieldIdentifier &) override; - void visit (AST::StructExprFieldIdentifierValue &field) override; - void visit (AST::StructExprFieldIndexValue &field) override; - void visit (AST::StructExprStructFields &expr) override; - void visit (AST::StructExprStructBase &expr) override; void visit (AST::CallExpr &expr) override; void visit (AST::MethodCallExpr &expr) override; - void visit (AST::FieldAccessExpr &expr) override; void visit (AST::ClosureExprInner &expr) override; void visit (AST::BlockExpr &expr) override; void visit (AST::ClosureExprInnerTyped &expr) override; void visit (AST::ContinueExpr &expr) override; - void visit (AST::BreakExpr &expr) override; - void visit (AST::RangeFromToExpr &expr) override; - void visit (AST::RangeFromExpr &expr) override; - void visit (AST::RangeToExpr &expr) override; - void visit (AST::RangeFullExpr &) override; - void visit (AST::RangeFromToInclExpr &expr) override; - void visit (AST::RangeToInclExpr &expr) override; - void visit (AST::ReturnExpr &expr) override; - void visit (AST::UnsafeBlockExpr &expr) override; - void visit (AST::LoopExpr &expr) override; - void visit (AST::WhileLoopExpr &expr) override; - void visit (AST::WhileLetLoopExpr &expr) override; - void visit (AST::ForLoopExpr &expr) override; void visit (AST::IfExpr &expr) override; void visit (AST::IfExprConseqElse &expr) override; void visit (AST::IfLetExpr &expr) override; void visit (AST::IfLetExprConseqElse &expr) override; void visit (AST::MatchExpr &expr) override; - void visit (AST::AwaitExpr &expr) override; - void visit (AST::AsyncBlockExpr &expr) override; void visit (AST::TypeParam ¶m) override; void visit (AST::LifetimeWhereClauseItem &) override; void visit (AST::TypeBoundWhereClauseItem &item) override; - void visit (AST::Module &module) override; void visit (AST::ExternCrate &crate) override; void visit (AST::UseTreeGlob &) override; void visit (AST::UseTreeList &) override; void visit (AST::UseTreeRebind &) override; void visit (AST::UseDeclaration &use_decl) override; void visit (AST::Function &function) override; - void visit (AST::TypeAlias &type_alias) override; void visit (AST::StructStruct &struct_item) override; void visit (AST::TupleStruct &tuple_struct) override; void visit (AST::EnumItem &item) override; void visit (AST::EnumItemTuple &item) override; void visit (AST::EnumItemStruct &item) override; void visit (AST::EnumItemDiscriminant &item) override; - void visit (AST::Enum &enum_item) override; void visit (AST::Union &union_item) override; void visit (AST::ConstantItem &const_item) override; void visit (AST::StaticItem &static_item) override; void visit (AST::TraitItemFunc &item) override; void visit (AST::TraitItemMethod &item) override; void visit (AST::TraitItemConst &item) override; - void visit (AST::TraitItemType &item) override; void visit (AST::Trait &trait) override; void visit (AST::InherentImpl &impl) override; void visit (AST::TraitImpl &impl) override; @@ -296,58 +260,20 @@ public: void visit (AST::ExternBlock &block) override; // I don't think it would be possible to strip macros without expansion - void visit (AST::MacroMatchFragment &) override; void visit (AST::MacroMatchRepetition &) override; void visit (AST::MacroMatcher &) override; void visit (AST::MacroRulesDefinition &rules_def) override; void visit (AST::MetaItemPath &) override; void visit (AST::MetaItemSeq &) override; - void visit (AST::MetaWord &) override; - void visit (AST::MetaNameValueStr &) override; void visit (AST::MetaListPaths &) override; void visit (AST::MetaListNameValueStr &) override; - void visit (AST::LiteralPattern &) override; - void visit (AST::IdentifierPattern &pattern) override; - void visit (AST::WildcardPattern &) override; - void visit (AST::RestPattern &) override; - void visit (AST::RangePatternBoundLiteral &) override; - void visit (AST::RangePatternBoundPath &bound) override; - void visit (AST::RangePatternBoundQualPath &bound) override; - void visit (AST::RangePattern &pattern) override; - void visit (AST::ReferencePattern &pattern) override; - void visit (AST::StructPatternFieldTuplePat &field) override; - void visit (AST::StructPatternFieldIdentPat &field) override; void visit (AST::StructPatternFieldIdent &field) override; - void visit (AST::StructPattern &pattern) override; - void visit (AST::TupleStructItemsNoRange &tuple_items) override; - void visit (AST::TupleStructItemsRange &tuple_items) override; - void visit (AST::TupleStructPattern &pattern) override; - void visit (AST::TuplePatternItemsMultiple &tuple_items) override; - void visit (AST::TuplePatternItemsRanged &tuple_items) override; - void visit (AST::TuplePattern &pattern) override; void visit (AST::GroupedPattern &pattern) override; - void visit (AST::SlicePattern &pattern) override; - void visit (AST::AltPattern &pattern) override; - void visit (AST::EmptyStmt &) override; void visit (AST::LetStmt &stmt) override; void visit (AST::ExprStmt &stmt) override; - void visit (AST::TraitBound &bound) override; - void visit (AST::ImplTraitType &type) override; - void visit (AST::TraitObjectType &type) override; - void visit (AST::ParenthesisedType &type) override; - void visit (AST::ImplTraitTypeOneBound &type) override; - void visit (AST::TraitObjectTypeOneBound &type) override; - void visit (AST::TupleType &type) override; - void visit (AST::NeverType &) override; - void visit (AST::RawPointerType &type) override; - void visit (AST::ReferenceType &type) override; - void visit (AST::ArrayType &type) override; - void visit (AST::SliceType &type) override; - void visit (AST::InferredType &) override; void visit (AST::BareFunctionType &type) override; - void visit (AST::VariadicParam &type) override; void visit (AST::FunctionParam &type) override; void visit (AST::SelfParam &type) override; -- cgit v1.1 From 5ee51aa3e5a76f55889e47ca874e1010a3a878d7 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Thu, 23 Nov 2023 20:22:29 +0100 Subject: gccrs: Change cfg stripper to use default visitor Cfg visitor used it's own visit patterns, this made the code longer than required. gcc/rust/ChangeLog: * expand/rust-cfg-strip.cc (CfgStrip::visit): Change calls from visitor to default visitor. (CfgStrip::go): Add call to visit crate. * expand/rust-cfg-strip.h (class CfgStrip): Update prototypes and remove empty ones. * ast/rust-ast-visitor.cc: add WhereClause condition check. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/ast/rust-ast-visitor.cc | 30 +- gcc/rust/expand/rust-cfg-strip.cc | 722 +++++++++++--------------------------- gcc/rust/expand/rust-cfg-strip.h | 52 +-- 3 files changed, 228 insertions(+), 576 deletions(-) diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index 230a152b..5865703 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -776,7 +776,8 @@ DefaultASTVisitor::visit (AST::Function &function) visit (param); if (function.has_return_type ()) visit (function.get_return_type ()); - visit (function.get_where_clause ()); + if (function.has_where_clause ()) + visit (function.get_where_clause ()); if (function.has_body ()) visit (*function.get_definition ()); } @@ -788,7 +789,8 @@ DefaultASTVisitor::visit (AST::TypeAlias &type_alias) visit (type_alias.get_visibility ()); for (auto &generic : type_alias.get_generic_params ()) visit (generic); - visit (type_alias.get_where_clause ()); + if (type_alias.has_where_clause ()) + visit (type_alias.get_where_clause ()); visit (type_alias.get_type_aliased ()); } @@ -807,7 +809,8 @@ DefaultASTVisitor::visit (AST::StructStruct &struct_item) visit (struct_item.get_visibility ()); for (auto &generic : struct_item.get_generic_params ()) visit (generic); - visit (struct_item.get_where_clause ()); + if (struct_item.has_where_clause ()) + visit (struct_item.get_where_clause ()); for (auto &field : struct_item.get_fields ()) visit (field); } @@ -827,7 +830,8 @@ DefaultASTVisitor::visit (AST::TupleStruct &tuple_struct) visit (tuple_struct.get_visibility ()); for (auto &generic : tuple_struct.get_generic_params ()) visit (generic); - visit (tuple_struct.get_where_clause ()); + if (tuple_struct.has_where_clause ()) + visit (tuple_struct.get_where_clause ()); for (auto &field : tuple_struct.get_fields ()) visit (field); } @@ -869,7 +873,8 @@ DefaultASTVisitor::visit (AST::Enum &enum_item) visit (enum_item.get_visibility ()); for (auto &generic : enum_item.get_generic_params ()) visit (generic); - visit (enum_item.get_where_clause ()); + if (enum_item.has_where_clause ()) + visit (enum_item.get_where_clause ()); for (auto &item : enum_item.get_variants ()) visit (item); } @@ -881,7 +886,8 @@ DefaultASTVisitor::visit (AST::Union &union_item) visit (union_item.get_visibility ()); for (auto &generic : union_item.get_generic_params ()) visit (generic); - visit (union_item.get_where_clause ()); + if (union_item.has_where_clause ()) + visit (union_item.get_where_clause ()); for (auto &variant : union_item.get_variants ()) visit (variant); } @@ -978,7 +984,8 @@ DefaultASTVisitor::visit (AST::Trait &trait) for (auto &generic : trait.get_generic_params ()) visit (generic); - visit (trait.get_where_clause ()); + if (trait.has_where_clause ()) + visit (trait.get_where_clause ()); for (auto &bound : trait.get_type_param_bounds ()) visit (bound); @@ -995,7 +1002,8 @@ DefaultASTVisitor::visit (AST::InherentImpl &impl) for (auto &generic : impl.get_generic_params ()) visit (generic); - visit (impl.get_where_clause ()); + if (impl.has_where_clause ()) + visit (impl.get_where_clause ()); visit (impl.get_type ()); visit_inner_attrs (impl); for (auto &item : impl.get_impl_items ()) @@ -1010,7 +1018,8 @@ DefaultASTVisitor::visit (AST::TraitImpl &impl) for (auto &generic : impl.get_generic_params ()) visit (generic); - visit (impl.get_where_clause ()); + if (impl.has_where_clause ()) + visit (impl.get_where_clause ()); visit (impl.get_type ()); visit_inner_attrs (impl); for (auto &item : impl.get_impl_items ()) @@ -1048,7 +1057,8 @@ DefaultASTVisitor::visit (AST::ExternalFunctionItem &item) for (auto &generic : item.get_generic_params ()) visit (generic); - visit (item.get_where_clause ()); + if (item.has_where_clause ()) + visit (item.get_where_clause ()); for (auto ¶m : item.get_function_params ()) visit (param); diff --git a/gcc/rust/expand/rust-cfg-strip.cc b/gcc/rust/expand/rust-cfg-strip.cc index 0895201..22f3127 100644 --- a/gcc/rust/expand/rust-cfg-strip.cc +++ b/gcc/rust/expand/rust-cfg-strip.cc @@ -18,6 +18,7 @@ #include "rust-cfg-strip.h" #include "rust-ast-full.h" +#include "rust-ast-visitor.h" #include "rust-session-manager.h" #include "rust-attribute-values.h" @@ -135,6 +136,12 @@ expand_cfg_attrs (AST::AttrVec &attrs) void CfgStrip::go (AST::Crate &crate) { + visit (crate); +} + +void +CfgStrip::visit (AST::Crate &crate) +{ // expand crate cfg_attr attributes expand_cfg_attrs (crate.inner_attrs); @@ -147,17 +154,15 @@ CfgStrip::go (AST::Crate &crate) auto &items = crate.items; + AST::DefaultASTVisitor::visit (crate); for (auto it = items.begin (); it != items.end ();) { auto &item = *it; - item->accept_vis (*this); - if (item->is_marked_for_strip ()) it = items.erase (it); else it++; } - // expand module attributes? } @@ -421,24 +426,10 @@ CfgStrip::maybe_strip_trait_method_decl (AST::TraitMethodDecl &decl) } void -CfgStrip::visit (AST::Token &) -{ - // shouldn't require? -} -void -CfgStrip::visit (AST::DelimTokenTree &) -{ - // shouldn't require? -} -void -CfgStrip::visit (AST::AttrInputMetaItemContainer &) -{ - // shouldn't require? -} -void CfgStrip::visit (AST::IdentifierExpr &ident_expr) { // strip test based on outer attrs + AST::DefaultASTVisitor::visit (ident_expr); expand_cfg_attrs (ident_expr.get_outer_attrs ()); if (fails_cfg_with_expand (ident_expr.get_outer_attrs ())) { @@ -446,21 +437,6 @@ CfgStrip::visit (AST::IdentifierExpr &ident_expr) return; } } -void -CfgStrip::visit (AST::Lifetime &) -{ - // shouldn't require? -} -void -CfgStrip::visit (AST::LifetimeParam &) -{ - // supposedly does not require - cfg does nothing -} -void -CfgStrip::visit (AST::ConstGenericParam &) -{ - // likewise -} void CfgStrip::visit (AST::MacroInvocation ¯o_invoc) @@ -497,11 +473,7 @@ CfgStrip::visit (AST::PathInExpression &path) maybe_strip_generic_args (segment.get_generic_args ()); } } -void -CfgStrip::visit (AST::TypePathSegment &) -{ - // shouldn't require -} + void CfgStrip::visit (AST::TypePathSegmentGeneric &segment) { @@ -515,11 +487,11 @@ CfgStrip::visit (AST::TypePathSegmentGeneric &segment) void CfgStrip::visit (AST::TypePathSegmentFunction &segment) { + AST::DefaultASTVisitor::visit (segment); auto &type_path_function = segment.get_type_path_function (); for (auto &type : type_path_function.get_params ()) { - type->accept_vis (*this); if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); @@ -528,24 +500,19 @@ CfgStrip::visit (AST::TypePathSegmentFunction &segment) if (type_path_function.has_return_type ()) { auto &return_type = type_path_function.get_return_type (); - return_type->accept_vis (*this); if (return_type->is_marked_for_strip ()) rust_error_at (return_type->get_locus (), "cannot strip type in this position"); } } -void -CfgStrip::visit (AST::TypePath &path) -{ - // this shouldn't strip any segments, but can strip inside them - for (auto &segment : path.get_segments ()) - segment->accept_vis (*this); -} + void CfgStrip::visit (AST::QualifiedPathInExpression &path) { // initial strip test based on outer attrs + AST::DefaultASTVisitor::visit (path); + expand_cfg_attrs (path.get_outer_attrs ()); if (fails_cfg_with_expand (path.get_outer_attrs ())) { @@ -561,14 +528,14 @@ CfgStrip::visit (AST::QualifiedPathInExpression &path) maybe_strip_generic_args (segment.get_generic_args ()); } } + void CfgStrip::visit (AST::QualifiedPathInType &path) { maybe_strip_qualified_path_type (path.get_qualified_path_type ()); // this shouldn't strip any segments, but can strip inside them - for (auto &segment : path.get_segments ()) - segment->accept_vis (*this); + AST::DefaultASTVisitor::visit (path); } void @@ -582,29 +549,11 @@ CfgStrip::visit (AST::LiteralExpr &expr) return; } } -void -CfgStrip::visit (AST::AttrInputLiteral &) -{ - // shouldn't require? -} -void -CfgStrip::visit (AST::AttrInputMacro &) -{ - // shouldn't require? -} -void -CfgStrip::visit (AST::MetaItemLitExpr &) -{ - // shouldn't require? -} -void -CfgStrip::visit (AST::MetaItemPathLit &) -{ - // shouldn't require? -} + void CfgStrip::visit (AST::BorrowExpr &expr) { + AST::DefaultASTVisitor::visit (expr); // initial strip test based on outer attrs expand_cfg_attrs (expr.get_outer_attrs ()); if (fails_cfg_with_expand (expr.get_outer_attrs ())) @@ -617,7 +566,6 @@ CfgStrip::visit (AST::BorrowExpr &expr) * allowed to have external attributes in this position so can't be * stripped. */ auto &borrowed_expr = expr.get_borrowed_expr (); - borrowed_expr->accept_vis (*this); if (borrowed_expr->is_marked_for_strip ()) rust_error_at (borrowed_expr->get_locus (), "cannot strip expression in this position - outer " @@ -647,6 +595,8 @@ CfgStrip::visit (AST::DereferenceExpr &expr) void CfgStrip::visit (AST::ErrorPropagationExpr &expr) { + AST::DefaultASTVisitor::visit (expr); + // initial strip test based on outer attrs expand_cfg_attrs (expr.get_outer_attrs ()); if (fails_cfg_with_expand (expr.get_outer_attrs ())) @@ -659,7 +609,6 @@ CfgStrip::visit (AST::ErrorPropagationExpr &expr) * allowed to have external attributes in this position so can't be * stripped. */ auto &propagating_expr = expr.get_propagating_expr (); - propagating_expr->accept_vis (*this); if (propagating_expr->is_marked_for_strip ()) rust_error_at (propagating_expr->get_locus (), "cannot strip expression in this position - outer " @@ -668,6 +617,7 @@ CfgStrip::visit (AST::ErrorPropagationExpr &expr) void CfgStrip::visit (AST::NegationExpr &expr) { + AST::DefaultASTVisitor::visit (expr); // initial strip test based on outer attrs expand_cfg_attrs (expr.get_outer_attrs ()); if (fails_cfg_with_expand (expr.get_outer_attrs ())) @@ -680,7 +630,6 @@ CfgStrip::visit (AST::NegationExpr &expr) * allowed to have external attributes in this position so can't be * stripped. */ auto &negated_expr = expr.get_negated_expr (); - negated_expr->accept_vis (*this); if (negated_expr->is_marked_for_strip ()) rust_error_at (negated_expr->get_locus (), "cannot strip expression in this position - outer " @@ -689,19 +638,10 @@ CfgStrip::visit (AST::NegationExpr &expr) void CfgStrip::visit (AST::ArithmeticOrLogicalExpr &expr) { + AST::DefaultASTVisitor::visit (expr); /* outer attributes never allowed before these. while cannot strip * two direct descendant expressions, can strip ones below that */ - /* should have no possibility for outer attrs as would be parsed - * with outer expr */ - auto &l_expr = expr.get_left_expr (); - l_expr->accept_vis (*this); - - /* should syntactically not have outer attributes, though this may - * not have worked in practice */ - auto &r_expr = expr.get_right_expr (); - r_expr->accept_vis (*this); - // ensure that they are not marked for strip if (expr.get_left_expr ()->is_marked_for_strip ()) rust_error_at (expr.get_left_expr ()->get_locus (), @@ -713,21 +653,13 @@ CfgStrip::visit (AST::ArithmeticOrLogicalExpr &expr) "cannot strip expression in this position - outer " "attributes not allowed"); } + void CfgStrip::visit (AST::ComparisonExpr &expr) { /* outer attributes never allowed before these. while cannot strip * two direct descendant expressions, can strip ones below that */ - - /* should have no possibility for outer attrs as would be parsed - * with outer expr */ - auto &l_expr = expr.get_left_expr (); - l_expr->accept_vis (*this); - - /* should syntactically not have outer attributes, though this may - * not have worked in practice */ - auto &r_expr = expr.get_right_expr (); - r_expr->accept_vis (*this); + AST::DefaultASTVisitor::visit (expr); // ensure that they are not marked for strip if (expr.get_left_expr ()->is_marked_for_strip ()) @@ -740,21 +672,13 @@ CfgStrip::visit (AST::ComparisonExpr &expr) "cannot strip expression in this position - outer " "attributes not allowed"); } + void CfgStrip::visit (AST::LazyBooleanExpr &expr) { /* outer attributes never allowed before these. while cannot strip * two direct descendant expressions, can strip ones below that */ - - /* should have no possibility for outer attrs as would be parsed - * with outer expr */ - auto &l_expr = expr.get_left_expr (); - l_expr->accept_vis (*this); - - /* should syntactically not have outer attributes, though this may - * not have worked in practice */ - auto &r_expr = expr.get_right_expr (); - r_expr->accept_vis (*this); + AST::DefaultASTVisitor::visit (expr); // ensure that they are not marked for strip if (expr.get_left_expr ()->is_marked_for_strip ()) @@ -767,17 +691,15 @@ CfgStrip::visit (AST::LazyBooleanExpr &expr) "cannot strip expression in this position - outer " "attributes not allowed"); } + void CfgStrip::visit (AST::TypeCastExpr &expr) { /* outer attributes never allowed before these. while cannot strip * direct descendant expression, can strip ones below that */ + AST::DefaultASTVisitor::visit (expr); auto &casted_expr = expr.get_casted_expr (); - /* should have no possibility for outer attrs as would be parsed - * with outer expr */ - casted_expr->accept_vis (*this); - // ensure that they are not marked for strip if (casted_expr->is_marked_for_strip ()) rust_error_at (casted_expr->get_locus (), @@ -786,7 +708,6 @@ CfgStrip::visit (AST::TypeCastExpr &expr) // TODO: strip sub-types of type auto &type = expr.get_type_to_cast_to (); - type->accept_vis (*this); if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); } @@ -799,16 +720,7 @@ CfgStrip::visit (AST::AssignmentExpr &expr) expr.mark_for_strip (); return; } - - /* should have no possibility for outer attrs as would be parsed - * with outer expr */ - auto &l_expr = expr.get_left_expr (); - l_expr->accept_vis (*this); - - /* should syntactically not have outer attributes, though this may - * not have worked in practice */ - auto &r_expr = expr.get_right_expr (); - r_expr->accept_vis (*this); + AST::DefaultASTVisitor::visit (expr); // ensure that they are not marked for strip if (expr.get_left_expr ()->is_marked_for_strip ()) @@ -826,16 +738,7 @@ CfgStrip::visit (AST::CompoundAssignmentExpr &expr) { /* outer attributes never allowed before these. while cannot strip * two direct descendant expressions, can strip ones below that */ - - /* should have no possibility for outer attrs as would be parsed - * with outer expr */ - auto &l_expr = expr.get_left_expr (); - l_expr->accept_vis (*this); - - /* should syntactically not have outer attributes, though this may - * not have worked in practice */ - auto &r_expr = expr.get_right_expr (); - r_expr->accept_vis (*this); + AST::DefaultASTVisitor::visit (expr); // ensure that they are not marked for strip if (expr.get_left_expr ()->is_marked_for_strip ()) @@ -871,8 +774,9 @@ CfgStrip::visit (AST::GroupedExpr &expr) /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be * stripped. */ + AST::DefaultASTVisitor::visit (expr); + auto &inner_expr = expr.get_expr_in_parens (); - inner_expr->accept_vis (*this); if (inner_expr->is_marked_for_strip ()) rust_error_at (inner_expr->get_locus (), "cannot strip expression in this position - outer " @@ -892,10 +796,10 @@ CfgStrip::visit (AST::ArrayElemsCopied &elems) * expressions" according to spec. on the other hand, it would not * make conceptual sense to be able to remove either expression. As * such, not implementing. TODO clear up the ambiguity here */ + AST::DefaultASTVisitor::visit (elems); // only intend stripping for internal sub-expressions auto &copied_expr = elems.get_elem_to_copy (); - copied_expr->accept_vis (*this); if (copied_expr->is_marked_for_strip ()) rust_error_at (copied_expr->get_locus (), "cannot strip expression in this position - outer " @@ -930,8 +834,9 @@ CfgStrip::visit (AST::ArrayExpr &expr) /* assuming you can't strip away the ArrayElems type, but can strip * internal expressions and whatever */ - expr.get_array_elems ()->accept_vis (*this); + AST::DefaultASTVisitor::visit (expr); } + void CfgStrip::visit (AST::ArrayIndexExpr &expr) { @@ -949,15 +854,15 @@ CfgStrip::visit (AST::ArrayIndexExpr &expr) /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be * stripped. */ - auto &array_expr = expr.get_array_expr (); - array_expr->accept_vis (*this); + AST::DefaultASTVisitor::visit (expr); + + const auto &array_expr = expr.get_array_expr (); if (array_expr->is_marked_for_strip ()) rust_error_at (array_expr->get_locus (), "cannot strip expression in this position - outer " "attributes not allowed"); - auto &index_expr = expr.get_index_expr (); - index_expr->accept_vis (*this); + const auto &index_expr = expr.get_index_expr (); if (index_expr->is_marked_for_strip ()) rust_error_at (index_expr->get_locus (), "cannot strip expression in this position - outer " @@ -1001,16 +906,17 @@ CfgStrip::visit (AST::TupleIndexExpr &expr) return; } + AST::DefaultASTVisitor::visit (expr); /* wouldn't strip this directly (as outer attrs should be * associated with this level), but any sub-expressions would be * stripped. Thus, no need to erase when strip check called. */ auto &tuple_expr = expr.get_tuple_expr (); - tuple_expr->accept_vis (*this); if (tuple_expr->is_marked_for_strip ()) rust_error_at (tuple_expr->get_locus (), "cannot strip expression in this position - outer " "attributes not allowed"); } + void CfgStrip::visit (AST::StructExprStruct &expr) { @@ -1038,18 +944,15 @@ CfgStrip::visit (AST::StructExprStruct &expr) rust_error_at (struct_name.get_locus (), "cannot strip path in this position"); } -void -CfgStrip::visit (AST::StructExprFieldIdentifier &) -{ - // as no attrs (at moment, at least), no stripping possible -} + void CfgStrip::visit (AST::StructExprFieldIdentifierValue &field) { /* as no attrs possible (at moment, at least), only sub-expression * stripping is possible */ + AST::DefaultASTVisitor::visit (field); + auto &value = field.get_value (); - value->accept_vis (*this); if (value->is_marked_for_strip ()) rust_error_at (value->get_locus (), "cannot strip expression in this position - outer " @@ -1060,8 +963,9 @@ CfgStrip::visit (AST::StructExprFieldIndexValue &field) { /* as no attrs possible (at moment, at least), only sub-expression * stripping is possible */ + AST::DefaultASTVisitor::visit (field); + auto &value = field.get_value (); - value->accept_vis (*this); if (value->is_marked_for_strip ()) rust_error_at (value->get_locus (), "cannot strip expression in this position - outer " @@ -1098,11 +1002,7 @@ CfgStrip::visit (AST::StructExprStructFields &expr) * stripped at top level of struct fields, but I wouldn't think * that they would be, so operating under the assumption that only * sub-expressions can be stripped. */ - for (auto &field : expr.get_fields ()) - { - field->accept_vis (*this); - // shouldn't strip in this - } + AST::DefaultASTVisitor::visit (expr); /* struct base presumably can't be stripped, as the '..' is before * the expression. as such, can only strip sub-expressions. */ @@ -1116,6 +1016,7 @@ CfgStrip::visit (AST::StructExprStructFields &expr) "attributes not allowed"); } } + void CfgStrip::visit (AST::StructExprStructBase &expr) { @@ -1167,8 +1068,9 @@ CfgStrip::visit (AST::CallExpr &expr) /* should not be outer attrs on "function" expression - outer attrs * should be associated with call expr as a whole. only sub-expr * expansion is possible. */ + AST::DefaultASTVisitor::visit (expr); + auto &function = expr.get_function_expr (); - function->accept_vis (*this); if (function->is_marked_for_strip ()) rust_error_at (function->get_locus (), "cannot strip expression in this position - outer " @@ -1194,8 +1096,9 @@ CfgStrip::visit (AST::MethodCallExpr &expr) /* should not be outer attrs on "receiver" expression - outer attrs * should be associated with call expr as a whole. only sub-expr * expansion is possible. */ + AST::DefaultASTVisitor::visit (expr); + auto &receiver = expr.get_receiver_expr (); - receiver->accept_vis (*this); if (receiver->is_marked_for_strip ()) rust_error_at (receiver->get_locus (), "cannot strip expression in this position - outer " @@ -1223,8 +1126,9 @@ CfgStrip::visit (AST::FieldAccessExpr &expr) /* should not be outer attrs on "receiver" expression - outer attrs * should be associated with field expr as a whole. only sub-expr * expansion is possible. */ + AST::DefaultASTVisitor::visit (expr); + auto &receiver = expr.get_receiver_expr (); - receiver->accept_vis (*this); if (receiver->is_marked_for_strip ()) rust_error_at (receiver->get_locus (), "cannot strip expression in this position - outer " @@ -1245,9 +1149,10 @@ CfgStrip::visit (AST::ClosureExprInner &expr) * allowed by spec */ maybe_strip_closure_params (expr.get_params ()); + AST::DefaultASTVisitor::visit (expr); + // can't strip expression itself, but can strip sub-expressions auto &definition_expr = expr.get_definition_expr (); - definition_expr->accept_vis (*this); if (definition_expr->is_marked_for_strip ()) rust_error_at (definition_expr->get_locus (), "cannot strip expression in this position - outer " @@ -1276,13 +1181,13 @@ CfgStrip::visit (AST::BlockExpr &expr) maybe_strip_pointer_allow_strip (expr.get_statements ()); + AST::DefaultASTVisitor::visit (expr); + // strip tail expression if exists - can actually fully remove it if (expr.has_tail_expr ()) { auto &tail_expr = expr.get_tail_expr (); - tail_expr->accept_vis (*this); - if (tail_expr->is_marked_for_strip ()) expr.strip_tail_expr (); } @@ -1303,9 +1208,10 @@ CfgStrip::visit (AST::ClosureExprInnerTyped &expr) * allowed by spec */ maybe_strip_closure_params (expr.get_params ()); + AST::DefaultASTVisitor::visit (expr); + // can't strip return type, but can strip sub-types auto &type = expr.get_return_type (); - type->accept_vis (*this); if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); @@ -1339,6 +1245,7 @@ CfgStrip::visit (AST::BreakExpr &expr) expr.mark_for_strip (); return; } + AST::DefaultASTVisitor::visit (expr); /* spec does not say that you can have outer attributes on * expression, so assuming you can't. stripping for sub-expressions @@ -1347,8 +1254,6 @@ CfgStrip::visit (AST::BreakExpr &expr) { auto &break_expr = expr.get_break_expr (); - break_expr->accept_vis (*this); - if (break_expr->is_marked_for_strip ()) rust_error_at (break_expr->get_locus (), "cannot strip expression in this position - outer " @@ -1360,13 +1265,7 @@ CfgStrip::visit (AST::RangeFromToExpr &expr) { /* outer attributes never allowed before these. while cannot strip * two direct descendant expressions, can strip ones below that */ - - /* should have no possibility for outer attrs as would be parsed - * with outer expr */ - expr.get_from_expr ()->accept_vis (*this); - /* should syntactically not have outer attributes, though this may - * not have worked in practice */ - expr.get_to_expr ()->accept_vis (*this); + AST::DefaultASTVisitor::visit (expr); // ensure that they are not marked for strip if (expr.get_from_expr ()->is_marked_for_strip ()) @@ -1385,12 +1284,10 @@ CfgStrip::visit (AST::RangeFromExpr &expr) /* outer attributes never allowed before these. while cannot strip * direct descendant expression, can strip ones below that */ + AST::DefaultASTVisitor::visit (expr); /* should have no possibility for outer attrs as would be parsed * with outer expr */ auto &from_expr = expr.get_from_expr (); - - from_expr->accept_vis (*this); - if (from_expr->is_marked_for_strip ()) rust_error_at (from_expr->get_locus (), "cannot strip expression in this position - outer " @@ -1402,34 +1299,23 @@ CfgStrip::visit (AST::RangeToExpr &expr) /* outer attributes never allowed before these. while cannot strip * direct descendant expression, can strip ones below that */ + AST::DefaultASTVisitor::visit (expr); /* should syntactically not have outer attributes, though this may * not have worked in practice */ auto &to_expr = expr.get_to_expr (); - - to_expr->accept_vis (*this); - if (to_expr->is_marked_for_strip ()) rust_error_at (to_expr->get_locus (), "cannot strip expression in this position - outer " "attributes not allowed"); } -void -CfgStrip::visit (AST::RangeFullExpr &) -{ - // outer attributes never allowed before these, so no stripping -} + void CfgStrip::visit (AST::RangeFromToInclExpr &expr) { /* outer attributes never allowed before these. while cannot strip * two direct descendant expressions, can strip ones below that */ - /* should have no possibility for outer attrs as would be parsed - * with outer expr */ - expr.get_from_expr ()->accept_vis (*this); - /* should syntactically not have outer attributes, though this may - * not have worked in practice */ - expr.get_to_expr ()->accept_vis (*this); + AST::DefaultASTVisitor::visit (expr); // ensure that they are not marked for strip if (expr.get_from_expr ()->is_marked_for_strip ()) @@ -1448,12 +1334,10 @@ CfgStrip::visit (AST::RangeToInclExpr &expr) /* outer attributes never allowed before these. while cannot strip * direct descendant expression, can strip ones below that */ + AST::DefaultASTVisitor::visit (expr); /* should syntactically not have outer attributes, though this may * not have worked in practice */ auto &to_expr = expr.get_to_expr (); - - to_expr->accept_vis (*this); - if (to_expr->is_marked_for_strip ()) rust_error_at (to_expr->get_locus (), "cannot strip expression in this position - outer " @@ -1470,15 +1354,14 @@ CfgStrip::visit (AST::ReturnExpr &expr) return; } + AST::DefaultASTVisitor::visit (expr); + /* spec does not say that you can have outer attributes on * expression, so assuming you can't. stripping for sub-expressions * is the only thing that can be done */ if (expr.has_returned_expr ()) { auto &returned_expr = expr.get_returned_expr (); - - returned_expr->accept_vis (*this); - if (returned_expr->is_marked_for_strip ()) rust_error_at (returned_expr->get_locus (), "cannot strip expression in this position - outer " @@ -1501,9 +1384,10 @@ CfgStrip::visit (AST::UnsafeBlockExpr &expr) return; } + AST::DefaultASTVisitor::visit (expr); + // can't strip block itself, but can strip sub-expressions auto &block_expr = expr.get_block_expr (); - block_expr->accept_vis (*this); if (block_expr->is_marked_for_strip ()) rust_error_at (block_expr->get_locus (), "cannot strip block expression in this position - outer " @@ -1520,9 +1404,10 @@ CfgStrip::visit (AST::LoopExpr &expr) return; } + AST::DefaultASTVisitor::visit (expr); + // can't strip block itself, but can strip sub-expressions auto &loop_block = expr.get_loop_block (); - loop_block->accept_vis (*this); if (loop_block->is_marked_for_strip ()) rust_error_at (loop_block->get_locus (), "cannot strip block expression in this position - outer " @@ -1539,9 +1424,9 @@ CfgStrip::visit (AST::WhileLoopExpr &expr) return; } + AST::DefaultASTVisitor::visit (expr); // can't strip predicate expr itself, but can strip sub-expressions auto &predicate_expr = expr.get_predicate_expr (); - predicate_expr->accept_vis (*this); if (predicate_expr->is_marked_for_strip ()) rust_error_at (predicate_expr->get_locus (), "cannot strip expression in this position - outer " @@ -1549,7 +1434,6 @@ CfgStrip::visit (AST::WhileLoopExpr &expr) // can't strip block itself, but can strip sub-expressions auto &loop_block = expr.get_loop_block (); - loop_block->accept_vis (*this); if (loop_block->is_marked_for_strip ()) rust_error_at (loop_block->get_locus (), "cannot strip block expression in this position - outer " @@ -1566,17 +1450,15 @@ CfgStrip::visit (AST::WhileLetLoopExpr &expr) return; } + AST::DefaultASTVisitor::visit (expr); + for (auto &pattern : expr.get_patterns ()) - { - pattern->accept_vis (*this); - if (pattern->is_marked_for_strip ()) - rust_error_at (pattern->get_locus (), - "cannot strip pattern in this position"); - } + if (pattern->is_marked_for_strip ()) + rust_error_at (pattern->get_locus (), + "cannot strip pattern in this position"); // can't strip scrutinee expr itself, but can strip sub-expressions auto &scrutinee_expr = expr.get_scrutinee_expr (); - scrutinee_expr->accept_vis (*this); if (scrutinee_expr->is_marked_for_strip ()) rust_error_at (scrutinee_expr->get_locus (), "cannot strip expression in this position - outer " @@ -1584,7 +1466,6 @@ CfgStrip::visit (AST::WhileLetLoopExpr &expr) // can't strip block itself, but can strip sub-expressions auto &loop_block = expr.get_loop_block (); - loop_block->accept_vis (*this); if (loop_block->is_marked_for_strip ()) rust_error_at (loop_block->get_locus (), "cannot strip block expression in this position - outer " @@ -1601,16 +1482,15 @@ CfgStrip::visit (AST::ForLoopExpr &expr) return; } + AST::DefaultASTVisitor::visit (expr); // strip sub-patterns of pattern auto &pattern = expr.get_pattern (); - pattern->accept_vis (*this); if (pattern->is_marked_for_strip ()) rust_error_at (pattern->get_locus (), "cannot strip pattern in this position"); // can't strip scrutinee expr itself, but can strip sub-expressions auto &iterator_expr = expr.get_iterator_expr (); - iterator_expr->accept_vis (*this); if (iterator_expr->is_marked_for_strip ()) rust_error_at (iterator_expr->get_locus (), "cannot strip expression in this position - outer " @@ -1618,7 +1498,6 @@ CfgStrip::visit (AST::ForLoopExpr &expr) // can't strip block itself, but can strip sub-expressions auto &loop_block = expr.get_loop_block (); - loop_block->accept_vis (*this); if (loop_block->is_marked_for_strip ()) rust_error_at (loop_block->get_locus (), "cannot strip block expression in this position - outer " @@ -1638,9 +1517,10 @@ CfgStrip::visit (AST::IfExpr &expr) return; } + AST::DefaultASTVisitor::visit (expr); + // can't strip condition expr itself, but can strip sub-expressions auto &condition_expr = expr.get_condition_expr (); - condition_expr->accept_vis (*this); if (condition_expr->is_marked_for_strip ()) rust_error_at (condition_expr->get_locus (), "cannot strip expression in this position - outer " @@ -1648,12 +1528,12 @@ CfgStrip::visit (AST::IfExpr &expr) // can't strip if block itself, but can strip sub-expressions auto &if_block = expr.get_if_block (); - if_block->accept_vis (*this); if (if_block->is_marked_for_strip ()) rust_error_at (if_block->get_locus (), "cannot strip block expression in this position - outer " "attributes not allowed"); } + void CfgStrip::visit (AST::IfExprConseqElse &expr) { @@ -1665,9 +1545,10 @@ CfgStrip::visit (AST::IfExprConseqElse &expr) return; } + AST::DefaultASTVisitor::visit (expr); + // can't strip condition expr itself, but can strip sub-expressions auto &condition_expr = expr.get_condition_expr (); - condition_expr->accept_vis (*this); if (condition_expr->is_marked_for_strip ()) rust_error_at (condition_expr->get_locus (), "cannot strip expression in this position - outer " @@ -1675,7 +1556,6 @@ CfgStrip::visit (AST::IfExprConseqElse &expr) // can't strip if block itself, but can strip sub-expressions auto &if_block = expr.get_if_block (); - if_block->accept_vis (*this); if (if_block->is_marked_for_strip ()) rust_error_at (if_block->get_locus (), "cannot strip block expression in this position - outer " @@ -1683,12 +1563,12 @@ CfgStrip::visit (AST::IfExprConseqElse &expr) // can't strip else block itself, but can strip sub-expressions auto &else_block = expr.get_else_block (); - else_block->accept_vis (*this); if (else_block->is_marked_for_strip ()) rust_error_at (else_block->get_locus (), "cannot strip block expression in this position - outer " "attributes not allowed"); } + void CfgStrip::visit (AST::IfLetExpr &expr) { @@ -1700,17 +1580,15 @@ CfgStrip::visit (AST::IfLetExpr &expr) return; } + AST::DefaultASTVisitor::visit (expr); + for (auto &pattern : expr.get_patterns ()) - { - pattern->accept_vis (*this); - if (pattern->is_marked_for_strip ()) - rust_error_at (pattern->get_locus (), - "cannot strip pattern in this position"); - } + if (pattern->is_marked_for_strip ()) + rust_error_at (pattern->get_locus (), + "cannot strip pattern in this position"); // can't strip value expr itself, but can strip sub-expressions auto &value_expr = expr.get_value_expr (); - value_expr->accept_vis (*this); if (value_expr->is_marked_for_strip ()) rust_error_at (value_expr->get_locus (), "cannot strip expression in this position - outer " @@ -1718,7 +1596,6 @@ CfgStrip::visit (AST::IfLetExpr &expr) // can't strip if block itself, but can strip sub-expressions auto &if_block = expr.get_if_block (); - if_block->accept_vis (*this); if (if_block->is_marked_for_strip ()) rust_error_at (if_block->get_locus (), "cannot strip block expression in this position - outer " @@ -1735,17 +1612,15 @@ CfgStrip::visit (AST::IfLetExprConseqElse &expr) return; } + AST::DefaultASTVisitor::visit (expr); + for (auto &pattern : expr.get_patterns ()) - { - pattern->accept_vis (*this); - if (pattern->is_marked_for_strip ()) - rust_error_at (pattern->get_locus (), - "cannot strip pattern in this position"); - } + if (pattern->is_marked_for_strip ()) + rust_error_at (pattern->get_locus (), + "cannot strip pattern in this position"); // can't strip value expr itself, but can strip sub-expressions auto &value_expr = expr.get_value_expr (); - value_expr->accept_vis (*this); if (value_expr->is_marked_for_strip ()) rust_error_at (value_expr->get_locus (), "cannot strip expression in this position - outer " @@ -1753,7 +1628,6 @@ CfgStrip::visit (AST::IfLetExprConseqElse &expr) // can't strip if block itself, but can strip sub-expressions auto &if_block = expr.get_if_block (); - if_block->accept_vis (*this); if (if_block->is_marked_for_strip ()) rust_error_at (if_block->get_locus (), "cannot strip block expression in this position - outer " @@ -1761,7 +1635,6 @@ CfgStrip::visit (AST::IfLetExprConseqElse &expr) // can't strip else block itself, but can strip sub-expressions auto &else_block = expr.get_else_block (); - else_block->accept_vis (*this); if (else_block->is_marked_for_strip ()) rust_error_at (else_block->get_locus (), "cannot strip block expression in this position - outer " @@ -1786,9 +1659,10 @@ CfgStrip::visit (AST::MatchExpr &expr) return; } + AST::DefaultASTVisitor::visit (expr); + // can't strip scrutinee expr itself, but can strip sub-expressions auto &scrutinee_expr = expr.get_scrutinee_expr (); - scrutinee_expr->accept_vis (*this); if (scrutinee_expr->is_marked_for_strip ()) rust_error_at (scrutinee_expr->get_locus (), "cannot strip expression in this position - outer " @@ -1811,12 +1685,9 @@ CfgStrip::visit (AST::MatchExpr &expr) } for (auto &pattern : match_arm.get_patterns ()) - { - pattern->accept_vis (*this); - if (pattern->is_marked_for_strip ()) - rust_error_at (pattern->get_locus (), - "cannot strip pattern in this position"); - } + if (pattern->is_marked_for_strip ()) + rust_error_at (pattern->get_locus (), + "cannot strip pattern in this position"); /* assuming that guard expression cannot be stripped as * strictly speaking you would have to strip the whole guard to @@ -1825,7 +1696,6 @@ CfgStrip::visit (AST::MatchExpr &expr) if (match_arm.has_match_arm_guard ()) { auto &guard_expr = match_arm.get_guard_expr (); - guard_expr->accept_vis (*this); if (guard_expr->is_marked_for_strip ()) rust_error_at (guard_expr->get_locus (), "cannot strip expression in this position - outer " @@ -1834,7 +1704,6 @@ CfgStrip::visit (AST::MatchExpr &expr) // strip sub-expressions from match cases auto &case_expr = match_case.get_expr (); - case_expr->accept_vis (*this); if (case_expr->is_marked_for_strip ()) rust_error_at (case_expr->get_locus (), "cannot strip expression in this position - outer " @@ -1844,6 +1713,7 @@ CfgStrip::visit (AST::MatchExpr &expr) ++it; } } + void CfgStrip::visit (AST::AwaitExpr &expr) { @@ -1864,6 +1734,7 @@ CfgStrip::visit (AST::AwaitExpr &expr) "cannot strip expression in this position - outer " "attributes not allowed"); } + void CfgStrip::visit (AST::AsyncBlockExpr &expr) { @@ -1875,9 +1746,10 @@ CfgStrip::visit (AST::AsyncBlockExpr &expr) return; } + AST::DefaultASTVisitor::visit (expr); + // can't strip block itself, but can strip sub-expressions auto &block_expr = expr.get_block_expr (); - block_expr->accept_vis (*this); if (block_expr->is_marked_for_strip ()) rust_error_at (block_expr->get_locus (), "cannot strip block expression in this position - outer " @@ -1889,43 +1761,24 @@ CfgStrip::visit (AST::TypeParam ¶m) { // outer attributes don't actually do anything, so ignore them - if (param.has_type_param_bounds ()) - { - // don't strip directly, only components of bounds - for (auto &bound : param.get_type_param_bounds ()) - bound->accept_vis (*this); - } + AST::DefaultASTVisitor::visit (param); - if (param.has_type ()) - { - auto &type = param.get_type (); - type->accept_vis (*this); - - if (type->is_marked_for_strip ()) - rust_error_at (type->get_locus (), - "cannot strip type in this position"); - } -} -void -CfgStrip::visit (AST::LifetimeWhereClauseItem &) -{ - // shouldn't require + if (param.has_type () && param.get_type ()->is_marked_for_strip ()) + rust_error_at (param.get_type ()->get_locus (), + "cannot strip type in this position"); } + void CfgStrip::visit (AST::TypeBoundWhereClauseItem &item) { // for lifetimes shouldn't require + AST::DefaultASTVisitor::visit (item); auto &type = item.get_type (); - type->accept_vis (*this); - if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); - - // don't strip directly, only components of bounds - for (auto &bound : item.get_type_param_bounds ()) - bound->accept_vis (*this); } + void CfgStrip::visit (AST::Module &module) { @@ -1952,6 +1805,7 @@ CfgStrip::visit (AST::Module &module) // strip items if required maybe_strip_pointer_allow_strip (module.get_items ()); } + void CfgStrip::visit (AST::ExternCrate &extern_crate) { @@ -1970,21 +1824,7 @@ CfgStrip::visit (AST::ExternCrate &extern_crate) extern_crate.get_locus ()); } } -void -CfgStrip::visit (AST::UseTreeGlob &) -{ - // shouldn't require? -} -void -CfgStrip::visit (AST::UseTreeList &) -{ - // shouldn't require? -} -void -CfgStrip::visit (AST::UseTreeRebind &) -{ - // shouldn't require? -} + void CfgStrip::visit (AST::UseDeclaration &use_decl) { @@ -1996,6 +1836,7 @@ CfgStrip::visit (AST::UseDeclaration &use_decl) return; } } + void CfgStrip::visit (AST::Function &function) { @@ -2007,9 +1848,7 @@ CfgStrip::visit (AST::Function &function) return; } - // just expand sub-stuff - can't actually strip generic params themselves - for (auto ¶m : function.get_generic_params ()) - param->accept_vis (*this); + AST::DefaultASTVisitor::visit (function); /* strip function parameters if required - this is specifically * allowed by spec */ @@ -2018,25 +1857,19 @@ CfgStrip::visit (AST::Function &function) if (function.has_return_type ()) { auto &return_type = function.get_return_type (); - return_type->accept_vis (*this); - if (return_type->is_marked_for_strip ()) rust_error_at (return_type->get_locus (), "cannot strip type in this position"); } - if (function.has_where_clause ()) - maybe_strip_where_clause (function.get_where_clause ()); - /* body should always exist - if error state, should have returned * before now */ // can't strip block itself, but can strip sub-expressions if (function.has_body ()) { - auto &block_expr = function.get_definition ().value (); - block_expr->accept_vis (*this); - if (block_expr->is_marked_for_strip ()) - rust_error_at (block_expr->get_locus (), + auto &block_expr = function.get_definition (); + if (block_expr.value ()->is_marked_for_strip ()) + rust_error_at (block_expr.value ()->get_locus (), "cannot strip block expression in this position - outer " "attributes not allowed"); } @@ -2053,18 +1886,13 @@ CfgStrip::visit (AST::TypeAlias &type_alias) return; } - // just expand sub-stuff - can't actually strip generic params themselves - for (auto ¶m : type_alias.get_generic_params ()) - param->accept_vis (*this); - - if (type_alias.has_where_clause ()) - maybe_strip_where_clause (type_alias.get_where_clause ()); + AST::DefaultASTVisitor::visit (type_alias); auto &type = type_alias.get_type_aliased (); - type->accept_vis (*this); if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); } + void CfgStrip::visit (AST::StructStruct &struct_item) { @@ -2076,12 +1904,7 @@ CfgStrip::visit (AST::StructStruct &struct_item) return; } - // just expand sub-stuff - can't actually strip generic params themselves - for (auto ¶m : struct_item.get_generic_params ()) - param->accept_vis (*this); - - if (struct_item.has_where_clause ()) - maybe_strip_where_clause (struct_item.get_where_clause ()); + AST::DefaultASTVisitor::visit (struct_item); } void CfgStrip::visit (AST::TupleStruct &tuple_struct) @@ -2094,16 +1917,11 @@ CfgStrip::visit (AST::TupleStruct &tuple_struct) return; } - // just expand sub-stuff - can't actually strip generic params themselves - for (auto ¶m : tuple_struct.get_generic_params ()) - param->accept_vis (*this); + AST::DefaultASTVisitor::visit (tuple_struct); /* strip struct fields if required - this is presumably * allowed by spec */ maybe_strip_tuple_fields (tuple_struct.get_fields ()); - - if (tuple_struct.has_where_clause ()) - maybe_strip_where_clause (tuple_struct.get_where_clause ()); } void CfgStrip::visit (AST::EnumItem &item) @@ -2116,6 +1934,7 @@ CfgStrip::visit (AST::EnumItem &item) return; } } + void CfgStrip::visit (AST::EnumItemTuple &item) { @@ -2131,6 +1950,7 @@ CfgStrip::visit (AST::EnumItemTuple &item) * allowed by spec */ maybe_strip_tuple_fields (item.get_tuple_fields ()); } + void CfgStrip::visit (AST::EnumItemStruct &item) { @@ -2146,6 +1966,7 @@ CfgStrip::visit (AST::EnumItemStruct &item) * allowed by spec */ maybe_strip_struct_fields (item.get_struct_fields ()); } + void CfgStrip::visit (AST::EnumItemDiscriminant &item) { @@ -2157,11 +1978,11 @@ CfgStrip::visit (AST::EnumItemDiscriminant &item) return; } + AST::DefaultASTVisitor::visit (item); /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be * stripped. */ auto &expr = item.get_expr (); - expr->accept_vis (*this); if (expr->is_marked_for_strip ()) rust_error_at (expr->get_locus (), "cannot strip expression in this position - outer " @@ -2178,12 +1999,7 @@ CfgStrip::visit (AST::Enum &enum_item) return; } - // just expand sub-stuff - can't actually strip generic params themselves - for (auto ¶m : enum_item.get_generic_params ()) - param->accept_vis (*this); - - if (enum_item.has_where_clause ()) - maybe_strip_where_clause (enum_item.get_where_clause ()); + AST::DefaultASTVisitor::visit (enum_item); /* strip enum fields if required - this is presumably * allowed by spec */ @@ -2200,12 +2016,7 @@ CfgStrip::visit (AST::Union &union_item) return; } - // just expand sub-stuff - can't actually strip generic params themselves - for (auto ¶m : union_item.get_generic_params ()) - param->accept_vis (*this); - - if (union_item.has_where_clause ()) - maybe_strip_where_clause (union_item.get_where_clause ()); + AST::DefaultASTVisitor::visit (union_item); /* strip union fields if required - this is presumably * allowed by spec */ @@ -2222,10 +2033,10 @@ CfgStrip::visit (AST::ConstantItem &const_item) return; } + AST::DefaultASTVisitor::visit (const_item); + // strip any sub-types auto &type = const_item.get_type (); - type->accept_vis (*this); - if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); @@ -2235,7 +2046,6 @@ CfgStrip::visit (AST::ConstantItem &const_item) if (const_item.has_expr ()) { auto &expr = const_item.get_expr (); - expr->accept_vis (*this); if (expr->is_marked_for_strip ()) rust_error_at (expr->get_locus (), "cannot strip expression in this position - outer " @@ -2253,9 +2063,10 @@ CfgStrip::visit (AST::StaticItem &static_item) return; } + AST::DefaultASTVisitor::visit (static_item); + // strip any sub-types auto &type = static_item.get_type (); - type->accept_vis (*this); if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); @@ -2264,7 +2075,6 @@ CfgStrip::visit (AST::StaticItem &static_item) * allowed to have external attributes in this position so can't be * stripped. */ auto &expr = static_item.get_expr (); - expr->accept_vis (*this); if (expr->is_marked_for_strip ()) rust_error_at (expr->get_locus (), "cannot strip expression in this position - outer " @@ -2283,19 +2093,21 @@ CfgStrip::visit (AST::TraitItemFunc &item) maybe_strip_trait_function_decl (item.get_trait_function_decl ()); + AST::DefaultASTVisitor::visit (item); + if (item.has_definition ()) { /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be * stripped. */ auto &block = item.get_definition (); - block->accept_vis (*this); if (block->is_marked_for_strip ()) rust_error_at (block->get_locus (), "cannot strip block expression in this " "position - outer attributes not allowed"); } } + void CfgStrip::visit (AST::TraitItemMethod &item) { @@ -2309,19 +2121,21 @@ CfgStrip::visit (AST::TraitItemMethod &item) maybe_strip_trait_method_decl (item.get_trait_method_decl ()); + AST::DefaultASTVisitor::visit (item); + if (item.has_definition ()) { /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be * stripped. */ auto &block = item.get_definition (); - block->accept_vis (*this); if (block->is_marked_for_strip ()) rust_error_at (block->get_locus (), "cannot strip block expression in this " "position - outer attributes not allowed"); } } + void CfgStrip::visit (AST::TraitItemConst &item) { @@ -2333,9 +2147,10 @@ CfgStrip::visit (AST::TraitItemConst &item) return; } + AST::DefaultASTVisitor::visit (item); + // strip any sub-types auto &type = item.get_type (); - type->accept_vis (*this); if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); @@ -2346,13 +2161,13 @@ CfgStrip::visit (AST::TraitItemConst &item) if (item.has_expression ()) { auto &expr = item.get_expr (); - expr->accept_vis (*this); if (expr->is_marked_for_strip ()) rust_error_at (expr->get_locus (), "cannot strip expression in this position - outer " "attributes not allowed"); } } + void CfgStrip::visit (AST::TraitItemType &item) { @@ -2364,13 +2179,9 @@ CfgStrip::visit (AST::TraitItemType &item) return; } - if (item.has_type_param_bounds ()) - { - // don't strip directly, only components of bounds - for (auto &bound : item.get_type_param_bounds ()) - bound->accept_vis (*this); - } + AST::DefaultASTVisitor::visit (item); } + void CfgStrip::visit (AST::Trait &trait) { @@ -2390,22 +2201,11 @@ CfgStrip::visit (AST::Trait &trait) return; } - // just expand sub-stuff - can't actually strip generic params themselves - for (auto ¶m : trait.get_generic_params ()) - param->accept_vis (*this); - - if (trait.has_type_param_bounds ()) - { - // don't strip directly, only components of bounds - for (auto &bound : trait.get_type_param_bounds ()) - bound->accept_vis (*this); - } - - if (trait.has_where_clause ()) - maybe_strip_where_clause (trait.get_where_clause ()); + AST::DefaultASTVisitor::visit (trait); maybe_strip_pointer_allow_strip (trait.get_trait_items ()); } + void CfgStrip::visit (AST::InherentImpl &impl) { @@ -2425,21 +2225,16 @@ CfgStrip::visit (AST::InherentImpl &impl) return; } - // just expand sub-stuff - can't actually strip generic params themselves - for (auto ¶m : impl.get_generic_params ()) - param->accept_vis (*this); + AST::DefaultASTVisitor::visit (impl); auto &type = impl.get_type (); - type->accept_vis (*this); if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); - if (impl.has_where_clause ()) - maybe_strip_where_clause (impl.get_where_clause ()); - maybe_strip_pointer_allow_strip (impl.get_impl_items ()); } + void CfgStrip::visit (AST::TraitImpl &impl) { @@ -2459,13 +2254,9 @@ CfgStrip::visit (AST::TraitImpl &impl) return; } - // just expand sub-stuff - can't actually strip generic params themselves - for (auto ¶m : impl.get_generic_params ()) - param->accept_vis (*this); + AST::DefaultASTVisitor::visit (impl); auto &type = impl.get_type (); - type->accept_vis (*this); - if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); @@ -2475,9 +2266,6 @@ CfgStrip::visit (AST::TraitImpl &impl) rust_error_at (trait_path.get_locus (), "cannot strip typepath in this position"); - if (impl.has_where_clause ()) - maybe_strip_where_clause (impl.get_where_clause ()); - maybe_strip_pointer_allow_strip (impl.get_impl_items ()); } @@ -2505,9 +2293,9 @@ CfgStrip::visit (AST::ExternalStaticItem &item) return; } - auto &type = item.get_type (); - type->accept_vis (*this); + AST::DefaultASTVisitor::visit (item); + auto &type = item.get_type (); if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); } @@ -2523,9 +2311,7 @@ CfgStrip::visit (AST::ExternalFunctionItem &item) return; } - // just expand sub-stuff - can't actually strip generic params themselves - for (auto ¶m : item.get_generic_params ()) - param->accept_vis (*this); + AST::DefaultASTVisitor::visit (item); /* strip function parameters if required - this is specifically * allowed by spec */ @@ -2545,8 +2331,6 @@ CfgStrip::visit (AST::ExternalFunctionItem &item) if (!param.is_variadic ()) { auto &type = param.get_type (); - param.get_type ()->accept_vis (*this); - if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); @@ -2565,15 +2349,11 @@ CfgStrip::visit (AST::ExternalFunctionItem &item) if (item.has_return_type ()) { auto &return_type = item.get_return_type (); - return_type->accept_vis (*this); if (return_type->is_marked_for_strip ()) rust_error_at (return_type->get_locus (), "cannot strip type in this position"); } - - if (item.has_where_clause ()) - maybe_strip_where_clause (item.get_where_clause ()); } void @@ -2598,16 +2378,6 @@ CfgStrip::visit (AST::ExternBlock &block) maybe_strip_pointer_allow_strip (block.get_extern_items ()); } -// I don't think it would be possible to strip macros without expansion -void -CfgStrip::visit (AST::MacroMatchFragment &) -{} -void -CfgStrip::visit (AST::MacroMatchRepetition &) -{} -void -CfgStrip::visit (AST::MacroMatcher &) -{} void CfgStrip::visit (AST::MacroRulesDefinition &rules_def) { @@ -2621,57 +2391,20 @@ CfgStrip::visit (AST::MacroRulesDefinition &rules_def) } void -CfgStrip::visit (AST::MetaItemPath &) -{} -void -CfgStrip::visit (AST::MetaItemSeq &) -{} -void -CfgStrip::visit (AST::MetaWord &) -{} -void -CfgStrip::visit (AST::MetaNameValueStr &) -{} -void -CfgStrip::visit (AST::MetaListPaths &) -{} -void -CfgStrip::visit (AST::MetaListNameValueStr &) -{} - -void -CfgStrip::visit (AST::LiteralPattern &) -{ - // not possible -} -void CfgStrip::visit (AST::IdentifierPattern &pattern) { // can only strip sub-patterns of the inner pattern to bind if (!pattern.has_pattern_to_bind ()) return; + AST::DefaultASTVisitor::visit (pattern); + auto &sub_pattern = pattern.get_pattern_to_bind (); - sub_pattern->accept_vis (*this); if (sub_pattern->is_marked_for_strip ()) rust_error_at (sub_pattern->get_locus (), "cannot strip pattern in this position"); } -void -CfgStrip::visit (AST::WildcardPattern &) -{ - // not possible -} -void -CfgStrip::visit (AST::RestPattern &) -{ - // not possible -} -void -CfgStrip::visit (AST::RangePatternBoundLiteral &) -{ - // not possible -} + void CfgStrip::visit (AST::RangePatternBoundPath &bound) { @@ -2681,6 +2414,7 @@ CfgStrip::visit (AST::RangePatternBoundPath &bound) if (path.is_marked_for_strip ()) rust_error_at (path.get_locus (), "cannot strip path in this position"); } + void CfgStrip::visit (AST::RangePatternBoundQualPath &bound) { @@ -2690,18 +2424,13 @@ CfgStrip::visit (AST::RangePatternBoundQualPath &bound) if (path.is_marked_for_strip ()) rust_error_at (path.get_locus (), "cannot strip path in this position"); } -void -CfgStrip::visit (AST::RangePattern &pattern) -{ - // should have no capability to strip lower or upper bounds, only expand - pattern.get_lower_bound ()->accept_vis (*this); - pattern.get_upper_bound ()->accept_vis (*this); -} + void CfgStrip::visit (AST::ReferencePattern &pattern) { + AST::DefaultASTVisitor::visit (pattern); + auto &sub_pattern = pattern.get_referenced_pattern (); - sub_pattern->accept_vis (*this); if (sub_pattern->is_marked_for_strip ()) rust_error_at (sub_pattern->get_locus (), "cannot strip pattern in this position"); @@ -2717,13 +2446,15 @@ CfgStrip::visit (AST::StructPatternFieldTuplePat &field) return; } + AST::DefaultASTVisitor::visit (field); + // strip sub-patterns (can't strip top-level pattern) auto &sub_pattern = field.get_index_pattern (); - sub_pattern->accept_vis (*this); if (sub_pattern->is_marked_for_strip ()) rust_error_at (sub_pattern->get_locus (), "cannot strip pattern in this position"); } + void CfgStrip::visit (AST::StructPatternFieldIdentPat &field) { @@ -2735,9 +2466,9 @@ CfgStrip::visit (AST::StructPatternFieldIdentPat &field) return; } + AST::DefaultASTVisitor::visit (field); // strip sub-patterns (can't strip top-level pattern) auto &sub_pattern = field.get_ident_pattern (); - sub_pattern->accept_vis (*this); if (sub_pattern->is_marked_for_strip ()) rust_error_at (sub_pattern->get_locus (), "cannot strip pattern in this position"); @@ -2753,6 +2484,7 @@ CfgStrip::visit (AST::StructPatternFieldIdent &field) return; } } + void CfgStrip::visit (AST::StructPattern &pattern) { @@ -2780,14 +2512,14 @@ CfgStrip::visit (AST::StructPattern &pattern) elems.strip_etc (); } } + void CfgStrip::visit (AST::TupleStructItemsNoRange &tuple_items) { + AST::DefaultASTVisitor::visit (tuple_items); // can't strip individual patterns, only sub-patterns for (auto &pattern : tuple_items.get_patterns ()) { - pattern->accept_vis (*this); - if (pattern->is_marked_for_strip ()) rust_error_at (pattern->get_locus (), "cannot strip pattern in this position"); @@ -2797,11 +2529,10 @@ CfgStrip::visit (AST::TupleStructItemsNoRange &tuple_items) void CfgStrip::visit (AST::TupleStructItemsRange &tuple_items) { + AST::DefaultASTVisitor::visit (tuple_items); // can't strip individual patterns, only sub-patterns for (auto &lower_pattern : tuple_items.get_lower_patterns ()) { - lower_pattern->accept_vis (*this); - if (lower_pattern->is_marked_for_strip ()) rust_error_at (lower_pattern->get_locus (), "cannot strip pattern in this position"); @@ -2809,14 +2540,13 @@ CfgStrip::visit (AST::TupleStructItemsRange &tuple_items) } for (auto &upper_pattern : tuple_items.get_upper_patterns ()) { - upper_pattern->accept_vis (*this); - if (upper_pattern->is_marked_for_strip ()) rust_error_at (upper_pattern->get_locus (), "cannot strip pattern in this position"); // TODO: quit stripping now? or keep going? } } + void CfgStrip::visit (AST::TupleStructPattern &pattern) { @@ -2826,31 +2556,32 @@ CfgStrip::visit (AST::TupleStructPattern &pattern) if (path.is_marked_for_strip ()) rust_error_at (path.get_locus (), "cannot strip path in this position"); - if (pattern.has_items ()) - pattern.get_items ()->accept_vis (*this); + AST::DefaultASTVisitor::visit (pattern); } + void CfgStrip::visit (AST::TuplePatternItemsMultiple &tuple_items) { + AST::DefaultASTVisitor::visit (tuple_items); + // can't strip individual patterns, only sub-patterns for (auto &pattern : tuple_items.get_patterns ()) { - pattern->accept_vis (*this); - if (pattern->is_marked_for_strip ()) rust_error_at (pattern->get_locus (), "cannot strip pattern in this position"); // TODO: quit stripping now? or keep going? } } + void CfgStrip::visit (AST::TuplePatternItemsRanged &tuple_items) { + AST::DefaultASTVisitor::visit (tuple_items); + // can't strip individual patterns, only sub-patterns for (auto &lower_pattern : tuple_items.get_lower_patterns ()) { - lower_pattern->accept_vis (*this); - if (lower_pattern->is_marked_for_strip ()) rust_error_at (lower_pattern->get_locus (), "cannot strip pattern in this position"); @@ -2858,54 +2589,46 @@ CfgStrip::visit (AST::TuplePatternItemsRanged &tuple_items) } for (auto &upper_pattern : tuple_items.get_upper_patterns ()) { - upper_pattern->accept_vis (*this); - if (upper_pattern->is_marked_for_strip ()) rust_error_at (upper_pattern->get_locus (), "cannot strip pattern in this position"); // TODO: quit stripping now? or keep going? } } -void -CfgStrip::visit (AST::TuplePattern &pattern) -{ - if (pattern.has_tuple_pattern_items ()) - pattern.get_items ()->accept_vis (*this); -} + void CfgStrip::visit (AST::GroupedPattern &pattern) { + AST::DefaultASTVisitor::visit (pattern); // can't strip inner pattern, only sub-patterns auto &pattern_in_parens = pattern.get_pattern_in_parens (); - pattern_in_parens->accept_vis (*this); - if (pattern_in_parens->is_marked_for_strip ()) rust_error_at (pattern_in_parens->get_locus (), "cannot strip pattern in this position"); } + void CfgStrip::visit (AST::SlicePattern &pattern) { + AST::DefaultASTVisitor::visit (pattern); // can't strip individual patterns, only sub-patterns for (auto &item : pattern.get_items ()) { - item->accept_vis (*this); - if (item->is_marked_for_strip ()) rust_error_at (item->get_locus (), "cannot strip pattern in this position"); // TODO: quit stripping now? or keep going? } } + void CfgStrip::visit (AST::AltPattern &pattern) { + AST::DefaultASTVisitor::visit (pattern); // can't strip individual patterns, only sub-patterns for (auto &alt : pattern.get_alts ()) { - alt->accept_vis (*this); - if (alt->is_marked_for_strip ()) rust_error_at (alt->get_locus (), "cannot strip pattern in this position"); @@ -2914,11 +2637,6 @@ CfgStrip::visit (AST::AltPattern &pattern) } void -CfgStrip::visit (AST::EmptyStmt &) -{ - // assuming no outer attributes, so nothing can happen -} -void CfgStrip::visit (AST::LetStmt &stmt) { // initial strip test based on outer attrs @@ -2929,9 +2647,9 @@ CfgStrip::visit (AST::LetStmt &stmt) return; } + AST::DefaultASTVisitor::visit (stmt); // can't strip pattern, but call for sub-patterns auto &pattern = stmt.get_pattern (); - pattern->accept_vis (*this); if (pattern->is_marked_for_strip ()) rust_error_at (pattern->get_locus (), "cannot strip pattern in this position"); @@ -2940,7 +2658,6 @@ CfgStrip::visit (AST::LetStmt &stmt) if (stmt.has_type ()) { auto &type = stmt.get_type (); - type->accept_vis (*this); if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), @@ -2953,7 +2670,6 @@ CfgStrip::visit (AST::LetStmt &stmt) if (stmt.has_init_expr ()) { auto &init_expr = stmt.get_init_expr (); - init_expr->accept_vis (*this); if (init_expr->is_marked_for_strip ()) rust_error_at (init_expr->get_locus (), @@ -2961,6 +2677,7 @@ CfgStrip::visit (AST::LetStmt &stmt) "attributes not allowed"); } } + void CfgStrip::visit (AST::ExprStmt &stmt) { @@ -2970,9 +2687,9 @@ CfgStrip::visit (AST::ExprStmt &stmt) if (stmt.is_marked_for_strip ()) return; + AST::DefaultASTVisitor::visit (stmt); // strip if expr is to be stripped auto &expr = stmt.get_expr (); - expr->accept_vis (*this); if (expr->is_marked_for_strip ()) { stmt.mark_for_strip (); @@ -2992,93 +2709,66 @@ CfgStrip::visit (AST::TraitBound &bound) rust_error_at (path.get_locus (), "cannot strip type path in this position"); } -void -CfgStrip::visit (AST::ImplTraitType &type) -{ - // don't strip directly, only components of bounds - for (auto &bound : type.get_type_param_bounds ()) - bound->accept_vis (*this); -} -void -CfgStrip::visit (AST::TraitObjectType &type) -{ - // don't strip directly, only components of bounds - for (auto &bound : type.get_type_param_bounds ()) - bound->accept_vis (*this); -} + void CfgStrip::visit (AST::ParenthesisedType &type) { + AST::DefaultASTVisitor::visit (type); // expand but don't strip inner type auto &inner_type = type.get_type_in_parens (); - inner_type->accept_vis (*this); if (inner_type->is_marked_for_strip ()) rust_error_at (inner_type->get_locus (), "cannot strip type in this position"); } -void -CfgStrip::visit (AST::ImplTraitTypeOneBound &type) -{ - // no stripping possible - visit (type.get_trait_bound ()); -} -void -CfgStrip::visit (AST::TraitObjectTypeOneBound &type) -{ - // no stripping possible - visit (type.get_trait_bound ()); -} + void CfgStrip::visit (AST::TupleType &type) { + AST::DefaultASTVisitor::visit (type); // TODO: assuming that types can't be stripped as types don't have outer // attributes for (auto &elem_type : type.get_elems ()) { - elem_type->accept_vis (*this); if (elem_type->is_marked_for_strip ()) rust_error_at (elem_type->get_locus (), "cannot strip type in this position"); } } -void -CfgStrip::visit (AST::NeverType &) -{ - // no stripping possible -} + void CfgStrip::visit (AST::RawPointerType &type) { + AST::DefaultASTVisitor::visit (type); // expand but don't strip type pointed to auto &pointed_type = type.get_type_pointed_to (); - pointed_type->accept_vis (*this); if (pointed_type->is_marked_for_strip ()) rust_error_at (pointed_type->get_locus (), "cannot strip type in this position"); } + void CfgStrip::visit (AST::ReferenceType &type) { + AST::DefaultASTVisitor::visit (type); // expand but don't strip type referenced auto &referenced_type = type.get_type_referenced (); - referenced_type->accept_vis (*this); if (referenced_type->is_marked_for_strip ()) rust_error_at (referenced_type->get_locus (), "cannot strip type in this position"); } + void CfgStrip::visit (AST::ArrayType &type) { + AST::DefaultASTVisitor::visit (type); // expand but don't strip type referenced auto &base_type = type.get_elem_type (); - base_type->accept_vis (*this); if (base_type->is_marked_for_strip ()) rust_error_at (base_type->get_locus (), "cannot strip type in this position"); // same for expression auto &size_expr = type.get_size_expr (); - size_expr->accept_vis (*this); if (size_expr->is_marked_for_strip ()) rust_error_at (size_expr->get_locus (), "cannot strip expression in this position"); @@ -3086,22 +2776,19 @@ CfgStrip::visit (AST::ArrayType &type) void CfgStrip::visit (AST::SliceType &type) { + AST::DefaultASTVisitor::visit (type); // expand but don't strip elem type auto &elem_type = type.get_elem_type (); - elem_type->accept_vis (*this); if (elem_type->is_marked_for_strip ()) rust_error_at (elem_type->get_locus (), "cannot strip type in this position"); } -void -CfgStrip::visit (AST::InferredType &) -{ - // none possible -} + void CfgStrip::visit (AST::BareFunctionType &type) { // seem to be no generics + AST::DefaultASTVisitor::visit (type); // presumably function params can be stripped auto ¶ms = type.get_function_params (); @@ -3118,8 +2805,6 @@ CfgStrip::visit (AST::BareFunctionType &type) } auto &type = param.get_type (); - type->accept_vis (*this); - if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); @@ -3137,7 +2822,6 @@ CfgStrip::visit (AST::BareFunctionType &type) // In that case, we need to handle AST::TypeNoBounds on top of just // AST::Types auto &return_type = type.get_return_type (); - return_type->accept_vis (*this); if (return_type->is_marked_for_strip ()) rust_error_at (return_type->get_locus (), "cannot strip type in this position"); @@ -3147,21 +2831,13 @@ CfgStrip::visit (AST::BareFunctionType &type) } void -CfgStrip::visit (AST::VariadicParam &type) -{} - -void -CfgStrip::visit (AST::FunctionParam &type) -{} - -void CfgStrip::visit (AST::SelfParam ¶m) { + AST::DefaultASTVisitor::visit (param); + if (param.has_type ()) { auto &type = param.get_type (); - type->accept_vis (*this); - if (type->is_marked_for_strip ()) rust_error_at (type->get_locus (), "cannot strip type in this position"); diff --git a/gcc/rust/expand/rust-cfg-strip.h b/gcc/rust/expand/rust-cfg-strip.h index 32dbee6..6b968b3 100644 --- a/gcc/rust/expand/rust-cfg-strip.h +++ b/gcc/rust/expand/rust-cfg-strip.h @@ -22,10 +22,12 @@ namespace Rust { // Visitor used to maybe_strip attributes. -class CfgStrip : public AST::ASTVisitor +class CfgStrip : public AST::DefaultASTVisitor { private: public: + using DefaultASTVisitor::visit; + CfgStrip () {} /* Run the AttrVisitor on an entire crate */ @@ -63,29 +65,18 @@ public: } } - void visit (AST::Token &) override; - void visit (AST::DelimTokenTree &) override; - void visit (AST::AttrInputMetaItemContainer &) override; + void visit (AST::Crate &crate) override; void visit (AST::IdentifierExpr &ident_expr) override; - void visit (AST::Lifetime &) override; - void visit (AST::LifetimeParam &) override; - void visit (AST::ConstGenericParam &) override; void visit (AST::MacroInvocation ¯o_invoc) override; void visit (AST::PathInExpression &path) override; - void visit (AST::TypePathSegment &) override; void visit (AST::TypePathSegmentGeneric &segment) override; void visit (AST::TypePathSegmentFunction &segment) override; - void visit (AST::TypePath &path) override; void visit (AST::QualifiedPathInExpression &path) override; void visit (AST::QualifiedPathInType &path) override; void visit (AST::LiteralExpr &expr) override; - void visit (AST::AttrInputLiteral &) override; - void visit (AST::AttrInputMacro &) override; - void visit (AST::MetaItemLitExpr &) override; - void visit (AST::MetaItemPathLit &) override; void visit (AST::BorrowExpr &expr) override; void visit (AST::DereferenceExpr &expr) override; void visit (AST::ErrorPropagationExpr &expr) override; @@ -104,7 +95,6 @@ public: void visit (AST::TupleExpr &expr) override; void visit (AST::TupleIndexExpr &expr) override; void visit (AST::StructExprStruct &expr) override; - void visit (AST::StructExprFieldIdentifier &) override; void visit (AST::StructExprFieldIdentifierValue &field) override; void visit (AST::StructExprFieldIndexValue &field) override; @@ -123,7 +113,6 @@ public: void visit (AST::RangeFromToExpr &expr) override; void visit (AST::RangeFromExpr &expr) override; void visit (AST::RangeToExpr &expr) override; - void visit (AST::RangeFullExpr &) override; void visit (AST::RangeFromToInclExpr &expr) override; void visit (AST::RangeToInclExpr &expr) override; void visit (AST::ReturnExpr &expr) override; @@ -140,13 +129,9 @@ public: void visit (AST::AwaitExpr &expr) override; void visit (AST::AsyncBlockExpr &expr) override; void visit (AST::TypeParam ¶m) override; - void visit (AST::LifetimeWhereClauseItem &) override; void visit (AST::TypeBoundWhereClauseItem &item) override; void visit (AST::Module &module) override; void visit (AST::ExternCrate &crate) override; - void visit (AST::UseTreeGlob &) override; - void visit (AST::UseTreeList &) override; - void visit (AST::UseTreeRebind &) override; void visit (AST::UseDeclaration &use_decl) override; void visit (AST::Function &function) override; void visit (AST::TypeAlias &type_alias) override; @@ -173,24 +158,10 @@ public: void visit (AST::ExternBlock &block) override; // I don't think it would be possible to strip macros without expansion - void visit (AST::MacroMatchFragment &) override; - void visit (AST::MacroMatchRepetition &) override; - void visit (AST::MacroMatcher &) override; void visit (AST::MacroRulesDefinition &rules_def) override; - void visit (AST::MetaItemPath &) override; - void visit (AST::MetaItemSeq &) override; - void visit (AST::MetaWord &) override; - void visit (AST::MetaNameValueStr &) override; - void visit (AST::MetaListPaths &) override; - void visit (AST::MetaListNameValueStr &) override; - void visit (AST::LiteralPattern &) override; void visit (AST::IdentifierPattern &pattern) override; - void visit (AST::WildcardPattern &) override; - void visit (AST::RestPattern &) override; - void visit (AST::RangePatternBoundLiteral &) override; void visit (AST::RangePatternBoundPath &bound) override; void visit (AST::RangePatternBoundQualPath &bound) override; - void visit (AST::RangePattern &pattern) override; void visit (AST::ReferencePattern &pattern) override; void visit (AST::StructPatternFieldTuplePat &field) override; void visit (AST::StructPatternFieldIdentPat &field) override; @@ -201,31 +172,26 @@ public: void visit (AST::TupleStructPattern &pattern) override; void visit (AST::TuplePatternItemsMultiple &tuple_items) override; void visit (AST::TuplePatternItemsRanged &tuple_items) override; - void visit (AST::TuplePattern &pattern) override; void visit (AST::GroupedPattern &pattern) override; void visit (AST::SlicePattern &pattern) override; void visit (AST::AltPattern &pattern) override; - void visit (AST::EmptyStmt &) override; void visit (AST::LetStmt &stmt) override; void visit (AST::ExprStmt &stmt) override; void visit (AST::TraitBound &bound) override; - void visit (AST::ImplTraitType &type) override; - void visit (AST::TraitObjectType &type) override; void visit (AST::ParenthesisedType &type) override; - void visit (AST::ImplTraitTypeOneBound &type) override; - void visit (AST::TraitObjectTypeOneBound &type) override; void visit (AST::TupleType &type) override; - void visit (AST::NeverType &) override; void visit (AST::RawPointerType &type) override; void visit (AST::ReferenceType &type) override; void visit (AST::ArrayType &type) override; void visit (AST::SliceType &type) override; - void visit (AST::InferredType &) override; void visit (AST::BareFunctionType &type) override; - void visit (AST::VariadicParam &type) override; - void visit (AST::FunctionParam &type) override; void visit (AST::SelfParam &type) override; + + template void visit (T &item) + { + DefaultASTVisitor::visit (item); + } }; } // namespace Rust -- cgit v1.1 From 5bcfcfe98550cdc72ba76bf0872b2b4e5129caa5 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 3 Nov 2022 15:02:37 +0100 Subject: gccrs: refactor builtins initialization and attributes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit performs builtin initialization in a more "GCC-y" way, similarly to what the D frontend is doing. This way, we no longer have to worry about invalid attributes or types when initializing them by hand. Also add attributes support through LANG_HOOKS_COMMON_ATTRIBUTE_TABLE lang hook. Most of these changes are based on D frontend. gcc/rust/ChangeLog: * Make-lang.in (GRS_OBJS): Add rust-attribs.o. * backend/rust-builtins.cc (builtin_const, builtin_noreturn) (builtin_novops): Remove. (BuiltinsContext::lookup_simple_builtin): Adjust. (BuiltinsContext::setup_overflow_fns): Remove. (BuiltinsContext::define_function_type): Set builtin type to errormark so the builtin is considered unavailable. (BuiltinsContext::setup_math_fns): Remove. (BuiltinsContext::setup_atomic_fns): Remove. (build_c_type_nodes): Refactor based on D frontend. (BuiltinsContext::define_builtin_types): Likewise. (DEF_PRIMITIVE_TYPE): New. (DEF_FUNCTION_TYPE_0): New. (DEF_FUNCTION_TYPE_1): New. (DEF_FUNCTION_TYPE_2): New. (DEF_FUNCTION_TYPE_3): New. (DEF_FUNCTION_TYPE_4): New. (DEF_FUNCTION_TYPE_5): New. (DEF_FUNCTION_TYPE_6): New. (DEF_FUNCTION_TYPE_7): New. (DEF_FUNCTION_TYPE_8): New. (DEF_FUNCTION_TYPE_9): New. (DEF_FUNCTION_TYPE_10): New. (DEF_FUNCTION_TYPE_11): New. (DEF_FUNCTION_TYPE_VAR_0): New. (DEF_FUNCTION_TYPE_VAR_1): New. (DEF_FUNCTION_TYPE_VAR_2): New. (DEF_FUNCTION_TYPE_VAR_3): New. (DEF_FUNCTION_TYPE_VAR_4): New. (DEF_FUNCTION_TYPE_VAR_5): New. (DEF_FUNCTION_TYPE_VAR_6): New. (DEF_FUNCTION_TYPE_VAR_7): New. (DEF_FUNCTION_TYPE_VAR_11): New. (DEF_POINTER_TYPE): New. (BuiltinsContext::setup): Adjust. (BuiltinsContext::define_builtin_attributes): New. (DEF_ATTR_NULL_TREE): New. (DEF_ATTR_INT): New. (DEF_ATTR_STRING): New. (DEF_ATTR_IDENT): New. (DEF_ATTR_TREE_LIST): New. (handle_flags): Remove. (BuiltinsContext::define_builtins): New. (DEF_BUILTIN): New. (BuiltinsContext::define_builtin): Remove. (BuiltinsContext::register_rust_mappings): New. Add all missing builtins. (BuiltinsContext::lookup_gcc_builtin): Adjust. * backend/rust-builtins.h (DEF_PRIMITIVE_TYPE): New. (DEF_FUNCTION_TYPE_0): New. (DEF_FUNCTION_TYPE_1): New. (DEF_FUNCTION_TYPE_2): New. (DEF_FUNCTION_TYPE_3): New. (DEF_FUNCTION_TYPE_4): New. (DEF_FUNCTION_TYPE_5): New. (DEF_FUNCTION_TYPE_6): New. (DEF_FUNCTION_TYPE_7): New. (DEF_FUNCTION_TYPE_8): New. (DEF_FUNCTION_TYPE_9): New. (DEF_FUNCTION_TYPE_10): New. (DEF_FUNCTION_TYPE_11): New. (DEF_FUNCTION_TYPE_VAR_0): New. (DEF_FUNCTION_TYPE_VAR_1): New. (DEF_FUNCTION_TYPE_VAR_2): New. (DEF_FUNCTION_TYPE_VAR_3): New. (DEF_FUNCTION_TYPE_VAR_4): New. (DEF_FUNCTION_TYPE_VAR_5): New. (DEF_FUNCTION_TYPE_VAR_6): New. (DEF_FUNCTION_TYPE_VAR_7): New. (DEF_FUNCTION_TYPE_VAR_11): New. (DEF_POINTER_TYPE): New. (DEF_ATTR_NULL_TREE): New. (DEF_ATTR_INT): New. (DEF_ATTR_STRING): New. (DEF_ATTR_IDENT): New. (DEF_ATTR_TREE_LIST): New. * backend/rust-compile-intrinsic.cc (Intrinsics::compile): Add comment. (op_with_overflow_inner): Adjust. (copy_handler_inner): Adjust. (prefetch_data_handler): Adjust. (build_atomic_builtin_name): Adjust. (atomic_load_handler_inner): Adjust. (uninit_handler): Adjust. (move_val_init_handler): Adjust. (expect_handler_inner): Adjust. * rust-gcc.cc (fetch_overflow_builtins): Adjust. * rust-lang.cc (rust_localize_identifier): Adjust. (LANG_HOOKS_COMMON_ATTRIBUTE_TABLE): New. * rust-attribs.cc: New file. gcc/testsuite/ChangeLog: * rust/compile/torture/intrinsics-4.rs: Adjust. * rust/compile/torture/intrinsics-math.rs: Adjust. * rust/execute/torture/atomic_load.rs: Adjust. * rust/execute/torture/atomic_store.rs: Adjust. * rust/compile/torture/intrinsics-1.rs: Removed. * rust/compile/torture/builtin_abort.rs: New test. * rust/execute/torture/builtin_abort.rs: New test. Signed-off-by: Marc Poulhiès Co-authored-by: Arthur Cohen --- gcc/rust/Make-lang.in | 1 + gcc/rust/backend/rust-builtins.cc | 524 +++++++++++---------- gcc/rust/backend/rust-builtins.h | 118 ++++- gcc/rust/backend/rust-compile-intrinsic.cc | 68 ++- gcc/rust/rust-attribs.cc | 370 +++++++++++++++ gcc/rust/rust-gcc.cc | 8 +- gcc/rust/rust-lang.cc | 6 + .../rust/compile/torture/builtin_abort.rs | 18 + gcc/testsuite/rust/compile/torture/intrinsics-1.rs | 22 - gcc/testsuite/rust/compile/torture/intrinsics-4.rs | 2 +- .../rust/compile/torture/intrinsics-math.rs | 80 ++-- gcc/testsuite/rust/execute/torture/atomic_load.rs | 4 +- gcc/testsuite/rust/execute/torture/atomic_store.rs | 4 +- .../rust/execute/torture/builtin_abort.rs | 14 + 14 files changed, 899 insertions(+), 340 deletions(-) create mode 100644 gcc/rust/rust-attribs.cc create mode 100644 gcc/testsuite/rust/compile/torture/builtin_abort.rs delete mode 100644 gcc/testsuite/rust/compile/torture/intrinsics-1.rs create mode 100644 gcc/testsuite/rust/execute/torture/builtin_abort.rs diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 47cc877..b138ba2 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -64,6 +64,7 @@ gccrs$(exeext): $(GCCRS_D_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBDEPS) # The compiler proper, not driver GRS_OBJS = \ rust/rust-lang.o \ + rust/rust-attribs.o \ rust/rust-object-export.o \ rust/rust-linemap.o \ rust/rust-diagnostics.o \ diff --git a/gcc/rust/backend/rust-builtins.cc b/gcc/rust/backend/rust-builtins.cc index cd06379..1a87f86 100644 --- a/gcc/rust/backend/rust-builtins.cc +++ b/gcc/rust/backend/rust-builtins.cc @@ -14,15 +14,16 @@ // along with GCC; see the file COPYING3. If not see // . +#include "rust-diagnostics.h" +#include "rust-system.h" #include "rust-builtins.h" +#include "target.h" +#include "stringpool.h" + namespace Rust { namespace Compile { -static const int builtin_const = 1 << 0; -static const int builtin_noreturn = 1 << 1; -static const int builtin_novops = 1 << 2; - BuiltinsContext & BuiltinsContext::get () { @@ -33,280 +34,317 @@ BuiltinsContext::get () bool BuiltinsContext::lookup_simple_builtin (const std::string &name, tree *builtin) { + auto *to_search = &name; + auto it = rust_intrinsic_to_gcc_builtin.find (name); - if (it == rust_intrinsic_to_gcc_builtin.end ()) - return false; + if (it != rust_intrinsic_to_gcc_builtin.end ()) + to_search = &it->second; - return lookup_gcc_builtin (it->second, builtin); + return lookup_gcc_builtin (*to_search, builtin); } BuiltinsContext::BuiltinsContext () { setup (); } +/** + * Define a function type according to `builtin-types.def` + * + * *Heavily* inspired by the D frontend's `def_fn_type` function + */ void -BuiltinsContext::setup_overflow_fns () +BuiltinsContext::define_function_type (Type def_idx, Type ret_idx, + bool is_variadic, size_t n, ...) { - tree overflow_type - = build_varargs_function_type_list (boolean_type_node, NULL_TREE); - - define_builtin ("add_overflow", BUILT_IN_ADD_OVERFLOW, - "__builtin_add_overflow", "add_overflow", overflow_type, 0); - define_builtin ("sub_overflow", BUILT_IN_SUB_OVERFLOW, - "__builtin_sub_overflow", "sub_overflow", overflow_type, 0); - define_builtin ("mul_overflow", BUILT_IN_MUL_OVERFLOW, - "__builtin_mul_overflow", "mul_overflow", overflow_type, 0); + va_list list; + va_start (list, n); + + auto args = std::vector (); + + for (size_t i = 0; i < n; i++) + { + // The argument is an enum Type, but it's promoted to int when passed + // though '...'. + auto arg_idx = va_arg (list, int); + auto arg_type = builtin_types[arg_idx]; + + args.emplace_back (arg_type); + } + + auto return_type = builtin_types[ret_idx]; + if (return_type == error_mark_node) + { + // Mark the builtin as not available. + builtin_types[def_idx] = error_mark_node; + va_end (list); + return; + } + + auto fn_type = NULL_TREE; + if (is_variadic) + fn_type = build_varargs_function_type_array (return_type, n, args.data ()); + else + fn_type = build_function_type_array (return_type, n, args.data ()); + + builtin_types[def_idx] = fn_type; + va_end (list); } -void -BuiltinsContext::setup_math_fns () +// Taken directly from the D frontend +static void +build_c_type_nodes (void) { - tree fn_type_f32_to_f32 - = build_function_type_list (float_type_node, float_type_node, NULL_TREE); - tree fn_type_f64_to_f64 - = build_function_type_list (double_type_node, double_type_node, NULL_TREE); - tree fn_type_f32_f32_to_f32 - = build_function_type_list (float_type_node, float_type_node, - float_type_node, NULL_TREE); - tree fn_type_f64_f64_to_f64 - = build_function_type_list (double_type_node, double_type_node, - double_type_node, NULL_TREE); - tree fn_type_f32_i32_to_f32 - = build_function_type_list (float_type_node, float_type_node, - integer_type_node, NULL_TREE); - tree fn_type_f64_i32_to_f64 - = build_function_type_list (double_type_node, double_type_node, - integer_type_node, NULL_TREE); - - define_builtin ("sqrtf32", BUILT_IN_SQRTF, "__builtin_sqrtf", "sqrtf", - fn_type_f32_to_f32, builtin_const); - define_builtin ("sqrtf64", BUILT_IN_SQRT, "__builtin_sqrt", "sqrt", - fn_type_f64_to_f64, builtin_const); - - define_builtin ("powif32", BUILT_IN_POWIF, "__builtin_powif", "powif", - fn_type_f32_i32_to_f32, builtin_const); - define_builtin ("powif64", BUILT_IN_POWI, "__builtin_powi", "powi", - fn_type_f64_i32_to_f64, builtin_const); - - define_builtin ("sinf32", BUILT_IN_SINF, "__builtin_sinf", "sinf", - fn_type_f32_to_f32, builtin_const); - define_builtin ("sinf64", BUILT_IN_SIN, "__builtin_sin", "sin", - fn_type_f64_to_f64, builtin_const); - - define_builtin ("cosf32", BUILT_IN_COSF, "__builtin_cosf", "cosf", - fn_type_f32_to_f32, builtin_const); - define_builtin ("cosf64", BUILT_IN_COS, "__builtin_cos", "cos", - fn_type_f64_to_f64, builtin_const); - - define_builtin ("powf32", BUILT_IN_POWF, "__builtin_powf", "powf", - fn_type_f32_f32_to_f32, builtin_const); - define_builtin ("powf64", BUILT_IN_POW, "__builtin_pow", "pow", - fn_type_f64_f64_to_f64, builtin_const); - - define_builtin ("expf32", BUILT_IN_EXPF, "__builtin_expf", "expf", - fn_type_f32_to_f32, builtin_const); - define_builtin ("expf64", BUILT_IN_EXP, "__builtin_exp", "exp", - fn_type_f64_to_f64, builtin_const); - - define_builtin ("exp2f32", BUILT_IN_EXP2F, "__builtin_exp2f", "exp2f", - fn_type_f32_to_f32, builtin_const); - define_builtin ("exp2f64", BUILT_IN_EXP2, "__builtin_exp2", "exp2", - fn_type_f64_to_f64, builtin_const); - - define_builtin ("logf32", BUILT_IN_LOGF, "__builtin_logf", "logf", - fn_type_f32_to_f32, builtin_const); - define_builtin ("logf64", BUILT_IN_LOG, "__builtin_log", "log", - fn_type_f64_to_f64, builtin_const); - - define_builtin ("log10f32", BUILT_IN_LOG10F, "__builtin_log10f", "log10f", - fn_type_f32_to_f32, builtin_const); - define_builtin ("log10f64", BUILT_IN_LOG10, "__builtin_log10", "log10", - fn_type_f64_to_f64, builtin_const); - - define_builtin ("log2f32", BUILT_IN_LOG2F, "__builtin_log2f", "log2f", - fn_type_f32_to_f32, builtin_const); - define_builtin ("log2f64", BUILT_IN_LOG2, "__builtin_log2", "log2", - fn_type_f64_to_f64, builtin_const); - - define_builtin ("fmaf32", BUILT_IN_FMAF, "__builtin_fmaf", "fmaf", - fn_type_f32_f32_to_f32, builtin_const); - define_builtin ("fmaf64", BUILT_IN_FMA, "__builtin_fma", "fma", - fn_type_f64_f64_to_f64, builtin_const); - - define_builtin ("fabsf32", BUILT_IN_FABSF, "__builtin_fabsf", "fabsf", - fn_type_f32_to_f32, builtin_const); - define_builtin ("fabsf64", BUILT_IN_FABS, "__builtin_fabs", "fabs", - fn_type_f64_to_f64, builtin_const); - - define_builtin ("minnumf32", BUILT_IN_FMINF, "__builtin_fminf", "fminf", - fn_type_f32_f32_to_f32, builtin_const); - define_builtin ("minnumf64", BUILT_IN_FMIN, "__builtin_fmin", "fmin", - fn_type_f64_f64_to_f64, builtin_const); - - define_builtin ("maxnumf32", BUILT_IN_FMAXF, "__builtin_fmaxf", "fmaxf", - fn_type_f32_f32_to_f32, builtin_const); - define_builtin ("maxnumf64", BUILT_IN_FMAX, "__builtin_fmax", "fmax", - fn_type_f64_f64_to_f64, builtin_const); - - define_builtin ("copysignf32", BUILT_IN_COPYSIGNF, "__builtin_copysignf", - "copysignf", fn_type_f32_f32_to_f32, builtin_const); - define_builtin ("copysignf64", BUILT_IN_COPYSIGN, "__builtin_copysign", - "copysign", fn_type_f64_f64_to_f64, builtin_const); - - define_builtin ("floorf32", BUILT_IN_FLOORF, "__builtin_floorf", "floorf", - fn_type_f32_to_f32, builtin_const); - define_builtin ("floorf64", BUILT_IN_FLOOR, "__builtin_floor", "floor", - fn_type_f64_to_f64, builtin_const); - - define_builtin ("ceilf32", BUILT_IN_CEILF, "__builtin_ceilf", "ceilf", - fn_type_f32_to_f32, builtin_const); - define_builtin ("ceilf64", BUILT_IN_CEIL, "__builtin_ceil", "ceil", - fn_type_f64_to_f64, builtin_const); - - define_builtin ("truncf32", BUILT_IN_TRUNCF, "__builtin_truncf", "truncf", - fn_type_f32_to_f32, builtin_const); - define_builtin ("truncf64", BUILT_IN_TRUNC, "__builtin_trunc", "trunc", - fn_type_f64_to_f64, builtin_const); - - define_builtin ("rintf32", BUILT_IN_RINTF, "__builtin_rintf", "rintf", - fn_type_f32_to_f32, builtin_const); - define_builtin ("rintf64", BUILT_IN_RINT, "__builtin_rint", "rint", - fn_type_f64_to_f64, builtin_const); - - define_builtin ("nearbyintf32", BUILT_IN_NEARBYINTF, "__builtin_nearbyintf", - "nearbyintf", fn_type_f32_to_f32, builtin_const); - define_builtin ("nearbyintf64", BUILT_IN_NEARBYINT, "__builtin_nearbyint", - "nearbyint", fn_type_f64_to_f64, builtin_const); - - define_builtin ("roundf32", BUILT_IN_ROUNDF, "__builtin_roundf", "roundf", - fn_type_f32_to_f32, builtin_const); - define_builtin ("roundf64", BUILT_IN_ROUND, "__builtin_round", "round", - fn_type_f64_to_f64, builtin_const); + string_type_node = build_pointer_type (char_type_node); + const_string_type_node = build_pointer_type ( + build_qualified_type (char_type_node, TYPE_QUAL_CONST)); + + if (strcmp (UINTMAX_TYPE, "unsigned int") == 0) + { + intmax_type_node = integer_type_node; + uintmax_type_node = unsigned_type_node; + } + else if (strcmp (UINTMAX_TYPE, "long unsigned int") == 0) + { + intmax_type_node = long_integer_type_node; + uintmax_type_node = long_unsigned_type_node; + } + else if (strcmp (UINTMAX_TYPE, "long long unsigned int") == 0) + { + intmax_type_node = long_long_integer_type_node; + uintmax_type_node = long_long_unsigned_type_node; + } + else + gcc_unreachable (); + + signed_size_type_node = signed_type_for (size_type_node); + wint_type_node = unsigned_type_node; + pid_type_node = integer_type_node; } +/** + * Define all builtin types in the `builtin_types` array + */ void -BuiltinsContext::setup_atomic_fns () +BuiltinsContext::define_builtin_types () { - auto atomic_store_type - = build_varargs_function_type_list (void_type_node, NULL_TREE); - auto atomic_load_type = [] (tree ret_type_node) { - return build_function_type_list (ret_type_node, - ptr_type_node, // const_ptr_type_node? - integer_type_node, NULL_TREE); + // This is taken directly from the D frontend's handling of builtins + auto va_list_ref_type_node = build_reference_type (va_list_type_node); + auto va_list_arg_type_node = va_list_type_node; + + build_c_type_nodes (); + + auto builtin_type_for_size = [] (int size, bool unsignedp) { + tree type = lang_hooks.types.type_for_size (size, unsignedp); + return type ? type : error_mark_node; }; - // FIXME: These should be the definition for the generic version of the - // atomic_store builtins, but I cannot get them to work properly. Revisit - // later. define_builtin ("atomic_store", BUILT_IN_ATOMIC_STORE, - // "__atomic_store", NULL, - // atomic_store_type, 0); - // define_builtin ("atomic_store_n", BUILT_IN_ATOMIC_STORE_N, - // "__atomic_store_n", - // NULL, atomic_store_type, 0); - - define_builtin ("atomic_store_1", BUILT_IN_ATOMIC_STORE_1, "__atomic_store_1", - NULL, atomic_store_type, 0); - define_builtin ("atomic_store_2", BUILT_IN_ATOMIC_STORE_2, "__atomic_store_2", - NULL, atomic_store_type, 0); - define_builtin ("atomic_store_4", BUILT_IN_ATOMIC_STORE_4, "__atomic_store_4", - NULL, atomic_store_type, 0); - define_builtin ("atomic_store_8", BUILT_IN_ATOMIC_STORE_8, "__atomic_store_8", - NULL, atomic_store_type, 0); - define_builtin ("atomic_store_16", BUILT_IN_ATOMIC_STORE_16, - "__atomic_store_16", NULL, atomic_store_type, 0); - - define_builtin ("atomic_load_1", BUILT_IN_ATOMIC_LOAD_1, "__atomic_load_1", - NULL, atomic_load_type (integer_type_node), 0); - define_builtin ("atomic_load_2", BUILT_IN_ATOMIC_LOAD_2, "__atomic_load_2", - NULL, atomic_load_type (integer_type_node), 0); - define_builtin ("atomic_load_4", BUILT_IN_ATOMIC_LOAD_4, "__atomic_load_4", - NULL, atomic_load_type (integer_type_node), 0); - define_builtin ("atomic_load_8", BUILT_IN_ATOMIC_LOAD_8, "__atomic_load_8", - NULL, atomic_load_type (integer_type_node), 0); +#define DEF_PRIMITIVE_TYPE(ENUM, VALUE) builtin_types[ENUM] = VALUE; +#define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \ + define_function_type (ENUM, RETURN, 0, 0); +#define DEF_FUNCTION_TYPE_1(ENUM, RETURN, A1) \ + define_function_type (ENUM, RETURN, 0, 1, A1); +#define DEF_FUNCTION_TYPE_2(ENUM, RETURN, A1, A2) \ + define_function_type (ENUM, RETURN, 0, 2, A1, A2); +#define DEF_FUNCTION_TYPE_3(ENUM, RETURN, A1, A2, A3) \ + define_function_type (ENUM, RETURN, 0, 3, A1, A2, A3); +#define DEF_FUNCTION_TYPE_4(ENUM, RETURN, A1, A2, A3, A4) \ + define_function_type (ENUM, RETURN, 0, 4, A1, A2, A3, A4); +#define DEF_FUNCTION_TYPE_5(ENUM, RETURN, A1, A2, A3, A4, A5) \ + define_function_type (ENUM, RETURN, 0, 5, A1, A2, A3, A4, A5); +#define DEF_FUNCTION_TYPE_6(ENUM, RETURN, A1, A2, A3, A4, A5, A6) \ + define_function_type (ENUM, RETURN, 0, 6, A1, A2, A3, A4, A5, A6); +#define DEF_FUNCTION_TYPE_7(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7) \ + define_function_type (ENUM, RETURN, 0, 7, A1, A2, A3, A4, A5, A6, A7); +#define DEF_FUNCTION_TYPE_8(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8) \ + define_function_type (ENUM, RETURN, 0, 8, A1, A2, A3, A4, A5, A6, A7, A8); +#define DEF_FUNCTION_TYPE_9(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, A9) \ + define_function_type (ENUM, RETURN, 0, 9, A1, A2, A3, A4, A5, A6, A7, A8, A9); +#define DEF_FUNCTION_TYPE_10(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, A9, \ + A10) \ + define_function_type (ENUM, RETURN, 0, 10, A1, A2, A3, A4, A5, A6, A7, A8, \ + A9, A10); +#define DEF_FUNCTION_TYPE_11(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, A9, \ + A10, A11) \ + define_function_type (ENUM, RETURN, 0, 11, A1, A2, A3, A4, A5, A6, A7, A8, \ + A9, A10, A11); +#define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \ + define_function_type (ENUM, RETURN, 1, 0); +#define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, A1) \ + define_function_type (ENUM, RETURN, 1, 1, A1); +#define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, A1, A2) \ + define_function_type (ENUM, RETURN, 1, 2, A1, A2); +#define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, A1, A2, A3) \ + define_function_type (ENUM, RETURN, 1, 3, A1, A2, A3); +#define DEF_FUNCTION_TYPE_VAR_4(ENUM, RETURN, A1, A2, A3, A4) \ + define_function_type (ENUM, RETURN, 1, 4, A1, A2, A3, A4); +#define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, A1, A2, A3, A4, A5) \ + define_function_type (ENUM, RETURN, 1, 5, A1, A2, A3, A4, A5); +#define DEF_FUNCTION_TYPE_VAR_6(ENUM, RETURN, A1, A2, A3, A4, A5, A6) \ + define_function_type (ENUM, RETURN, 1, 6, A1, A2, A3, A4, A5, A6); +#define DEF_FUNCTION_TYPE_VAR_7(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7) \ + define_function_type (ENUM, RETURN, 1, 7, A1, A2, A3, A4, A5, A6, A7); +#define DEF_FUNCTION_TYPE_VAR_11(ENUM, RETURN, A1, A2, A3, A4, A5, A6, A7, A8, \ + A9, A10, A11) \ + define_function_type (ENUM, RETURN, 1, 11, A1, A2, A3, A4, A5, A6, A7, A8, \ + A9, A10, A11); +#define DEF_POINTER_TYPE(ENUM, TYPE) \ + builtin_types[ENUM] = build_pointer_type (builtin_types[TYPE]); + +#include "builtin-types.def" + +#undef DEF_PRIMITIVE_TYPE +#undef DEF_FUNCTION_TYPE_1 +#undef DEF_FUNCTION_TYPE_2 +#undef DEF_FUNCTION_TYPE_3 +#undef DEF_FUNCTION_TYPE_4 +#undef DEF_FUNCTION_TYPE_5 +#undef DEF_FUNCTION_TYPE_6 +#undef DEF_FUNCTION_TYPE_7 +#undef DEF_FUNCTION_TYPE_8 +#undef DEF_FUNCTION_TYPE_9 +#undef DEF_FUNCTION_TYPE_10 +#undef DEF_FUNCTION_TYPE_11 +#undef DEF_FUNCTION_TYPE_VAR_0 +#undef DEF_FUNCTION_TYPE_VAR_1 +#undef DEF_FUNCTION_TYPE_VAR_2 +#undef DEF_FUNCTION_TYPE_VAR_3 +#undef DEF_FUNCTION_TYPE_VAR_4 +#undef DEF_FUNCTION_TYPE_VAR_5 +#undef DEF_FUNCTION_TYPE_VAR_6 +#undef DEF_FUNCTION_TYPE_VAR_7 +#undef DEF_FUNCTION_TYPE_VAR_11 +#undef DEF_POINTER_TYPE + + builtin_types[Type::BT_LAST] = NULL_TREE; } +/** + * Define all builtin attributes in the `builtin_types` array + */ void -BuiltinsContext::setup () +BuiltinsContext::define_builtin_attributes () + { - setup_math_fns (); - setup_overflow_fns (); - setup_atomic_fns (); - - define_builtin ("unreachable", BUILT_IN_UNREACHABLE, "__builtin_unreachable", - NULL, build_function_type (void_type_node, void_list_node), - builtin_const | builtin_noreturn); - - define_builtin ("abort", BUILT_IN_ABORT, "__builtin_abort", "abort", - build_function_type (void_type_node, void_list_node), - builtin_const | builtin_noreturn); - - define_builtin ("breakpoint", BUILT_IN_TRAP, "__builtin_trap", "breakpoint", - build_function_type (void_type_node, void_list_node), - builtin_const | builtin_noreturn); - - define_builtin ("expect", BUILT_IN_EXPECT, "__builtin_expect", "expect", - build_function_type_list (long_integer_type_node, - long_integer_type_node, - long_integer_type_node, NULL_TREE), - builtin_const); - - define_builtin ("memcpy", BUILT_IN_MEMCPY, "__builtin_memcpy", "memcpy", - build_function_type_list (build_pointer_type (void_type_node), - build_pointer_type (void_type_node), - build_pointer_type (void_type_node), - size_type_node, NULL_TREE), - 0); - - define_builtin ("memset", BUILT_IN_MEMSET, "__builtin_memset", "memset", - build_function_type_list (void_type_node, ptr_type_node, - integer_type_node, size_type_node, - NULL_TREE), - 0); - - define_builtin ("prefetch", BUILT_IN_PREFETCH, "__builtin_prefetch", - "prefetch", - build_varargs_function_type_list ( - build_pointer_type (const_ptr_type_node), NULL_TREE), - builtin_const); + auto *built_in_attributes = builtin_attributes; + +#define DEF_ATTR_NULL_TREE(ENUM) built_in_attributes[(int) ENUM] = NULL_TREE; +#define DEF_ATTR_INT(ENUM, VALUE) \ + built_in_attributes[ENUM] = build_int_cst (NULL_TREE, VALUE); +#define DEF_ATTR_STRING(ENUM, VALUE) \ + built_in_attributes[ENUM] = build_string (strlen (VALUE), VALUE); +#define DEF_ATTR_IDENT(ENUM, STRING) \ + built_in_attributes[ENUM] = get_identifier (STRING); +#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) \ + built_in_attributes[ENUM] \ + = tree_cons (built_in_attributes[PURPOSE], built_in_attributes[VALUE], \ + built_in_attributes[CHAIN]); +#include "builtin-attrs.def" +#undef DEF_ATTR_NULL_TREE +#undef DEF_ATTR_INT +#undef DEF_ATTR_STRING +#undef DEF_ATTR_IDENT +#undef DEF_ATTR_TREE_LIST } -static void -handle_flags (tree decl, int flags) +/** + * Define all builtin functions during the first initialization of the + * `BuiltinsContext`. + */ +void +BuiltinsContext::define_builtins () { - if (flags & builtin_const) - TREE_READONLY (decl) = 1; - if (flags & builtin_noreturn) - TREE_READONLY (decl) = 1; - if (flags & builtin_novops) - DECL_IS_NOVOPS (decl) = 1; + auto *built_in_attributes = builtin_attributes; + auto build_builtin = [this] (built_in_function fn_code, const char *fn_name, + built_in_class fn_class, tree fn_type, bool both, + bool fallback, tree attributes, bool implicit) { + if (fn_type == error_mark_node) + return; + + static auto to_skip = strlen ("__builtin_"); + + auto libname = fn_name + to_skip; + auto decl = add_builtin_function (fn_name, fn_type, fn_code, fn_class, + fallback ? libname : NULL, attributes); + + set_builtin_decl (fn_code, decl, implicit); + + builtin_functions.insert ({std::string (fn_name), decl}); + }; + +#define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, FALLBACK_P, \ + NONANSI_P, ATTRS, IMPLICIT, COND) \ + if (NAME && COND) \ + build_builtin (ENUM, NAME, CLASS, builtin_types[TYPE], BOTH_P, FALLBACK_P, \ + built_in_attributes[ATTRS], IMPLICIT); +#include "builtins.def" +#undef DEF_BUILTIN } +/** + * Register direct mappings between Rust functions and GCC builtins + */ void -BuiltinsContext::define_builtin (const std::string rust_name, - built_in_function bcode, const char *name, - const char *libname, tree fntype, int flags) +BuiltinsContext::register_rust_mappings () { - tree decl = add_builtin_function (name, fntype, bcode, BUILT_IN_NORMAL, - libname, NULL_TREE); - handle_flags (decl, flags); - set_builtin_decl (bcode, decl, true); - - this->builtin_functions_[name] = decl; - if (libname != NULL) - { - decl = add_builtin_function (libname, fntype, bcode, BUILT_IN_NORMAL, - NULL, NULL_TREE); - handle_flags (decl, flags); + rust_intrinsic_to_gcc_builtin = { + {"sinf32", "__builtin_sinf"}, + {"sqrtf32", "__builtin_sqrtf"}, + {"sqrtf64", "__builtin_sqrt"}, + {"unreachable", "__builtin_unreachable"}, + {"abort", "__builtin_abort"}, + {"sinf64", "__builtin_sin"}, + {"cosf32", "__builtin_cosf"}, + {"cosf64", "__builtin_cos"}, + {"powf32", "__builtin_powf"}, + {"powf64", "__builtin_pow"}, + {"expf32", "__builtin_expf"}, + {"expf64", "__builtin_exp"}, + {"exp2f32", "__builtin_exp2f"}, + {"exp2f64", "__builtin_exp2"}, + {"logf32", "__builtin_logf"}, + {"logf64", "__builtin_log"}, + {"log10f32", "__builtin_log10f"}, + {"log10f64", "__builtin_log10"}, + {"log2f32", "__builtin_log2f"}, + {"log2f64", "__builtin_log2"}, + {"fmaf32", "__builtin_fmaf"}, + {"fmaf64", "__builtin_fma"}, + {"fabsf32", "__builtin_fabsf"}, + {"fabsf64", "__builtin_fabs"}, + {"minnumf32", "__builtin_fminf"}, + {"minnumf64", "__builtin_fmin"}, + {"maxnumf32", "__builtin_fmaxf"}, + {"maxnumf64", "__builtin_fmax"}, + {"copysignf32", "__builtin_copysignf"}, + {"copysignf64", "__builtin_copysign"}, + {"floorf32", "__builtin_floorf"}, + {"floorf64", "__builtin_floor"}, + {"ceilf32", "__builtin_ceilf"}, + {"ceilf64", "__builtin_ceil"}, + {"truncf32", "__builtin_truncf"}, + {"truncf64", "__builtin_trunc"}, + {"rintf32", "__builtin_rintf"}, + {"rintf64", "__builtin_rint"}, + {"nearbyintf32", "__builtin_nearbyintf"}, + {"nearbyintf64", "__builtin_nearbyint"}, + {"roundf32", "__builtin_roundf"}, + {"roundf64", "__builtin_round"}, + }; +} - this->builtin_functions_[libname] = decl; - } +void +BuiltinsContext::setup () +{ + define_builtin_types (); + define_builtin_attributes (); + define_builtins (); - rust_intrinsic_to_gcc_builtin[rust_name] = name; + register_rust_mappings (); } bool BuiltinsContext::lookup_gcc_builtin (const std::string &name, tree *builtin) { - auto it = builtin_functions_.find (name); - if (it == builtin_functions_.end ()) + auto it = builtin_functions.find (name); + if (it == builtin_functions.end ()) return false; *builtin = it->second; diff --git a/gcc/rust/backend/rust-builtins.h b/gcc/rust/backend/rust-builtins.h index c282510..5052eda 100644 --- a/gcc/rust/backend/rust-builtins.h +++ b/gcc/rust/backend/rust-builtins.h @@ -21,6 +21,7 @@ #include "rust-tree.h" #include "langhooks.h" #include "tree.h" +#include "selftest.h" namespace Rust { namespace Compile { @@ -75,6 +76,7 @@ namespace Compile { // _ => return None, // }; // Some(cx.get_intrinsic(&llvm_name)) + class BuiltinsContext { public: @@ -83,6 +85,110 @@ public: bool lookup_simple_builtin (const std::string &name, tree *builtin); private: + enum Type + { +#define DEF_PRIMITIVE_TYPE(NAME, V) NAME, +#define DEF_FUNCTION_TYPE_0(NAME, R) NAME, +#define DEF_FUNCTION_TYPE_1(NAME, R, A1) NAME, +#define DEF_FUNCTION_TYPE_2(NAME, R, A1, A2) NAME, +#define DEF_FUNCTION_TYPE_3(NAME, R, A1, A2, A3) NAME, +#define DEF_FUNCTION_TYPE_4(NAME, R, A1, A2, A3, A4) NAME, +#define DEF_FUNCTION_TYPE_5(NAME, R, A1, A2, A3, A4, A5) NAME, +#define DEF_FUNCTION_TYPE_6(NAME, R, A1, A2, A3, A4, A5, A6) NAME, +#define DEF_FUNCTION_TYPE_7(NAME, R, A1, A2, A3, A4, A5, A6, A7) NAME, +#define DEF_FUNCTION_TYPE_8(NAME, R, A1, A2, A3, A4, A5, A6, A7, A8) NAME, +#define DEF_FUNCTION_TYPE_9(NAME, R, A1, A2, A3, A4, A5, A6, A7, A8, A9) NAME, +#define DEF_FUNCTION_TYPE_10(NAME, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) \ + NAME, +#define DEF_FUNCTION_TYPE_11(NAME, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, \ + A11) \ + NAME, +#define DEF_FUNCTION_TYPE_VAR_0(NAME, R) NAME, +#define DEF_FUNCTION_TYPE_VAR_1(NAME, R, A1) NAME, +#define DEF_FUNCTION_TYPE_VAR_2(NAME, R, A1, A2) NAME, +#define DEF_FUNCTION_TYPE_VAR_3(NAME, R, A1, A2, A3) NAME, +#define DEF_FUNCTION_TYPE_VAR_4(NAME, R, A1, A2, A3, A4) NAME, +#define DEF_FUNCTION_TYPE_VAR_5(NAME, R, A1, A2, A3, A4, A5) NAME, +#define DEF_FUNCTION_TYPE_VAR_6(NAME, R, A1, A2, A3, A4, A5, A6) NAME, +#define DEF_FUNCTION_TYPE_VAR_7(NAME, R, A1, A2, A3, A4, A5, A6, A7) NAME, +#define DEF_FUNCTION_TYPE_VAR_11(NAME, R, A1, A2, A3, A4, A5, A6, A7, A8, A9, \ + A10, A11) \ + NAME, +#define DEF_POINTER_TYPE(NAME, TYPE) NAME, + +#include "builtin-types.def" + +#undef DEF_PRIMITIVE_TYPE +#undef DEF_FUNCTION_TYPE_0 +#undef DEF_FUNCTION_TYPE_1 +#undef DEF_FUNCTION_TYPE_2 +#undef DEF_FUNCTION_TYPE_3 +#undef DEF_FUNCTION_TYPE_4 +#undef DEF_FUNCTION_TYPE_5 +#undef DEF_FUNCTION_TYPE_6 +#undef DEF_FUNCTION_TYPE_7 +#undef DEF_FUNCTION_TYPE_8 +#undef DEF_FUNCTION_TYPE_9 +#undef DEF_FUNCTION_TYPE_10 +#undef DEF_FUNCTION_TYPE_11 +#undef DEF_FUNCTION_TYPE_VAR_0 +#undef DEF_FUNCTION_TYPE_VAR_1 +#undef DEF_FUNCTION_TYPE_VAR_2 +#undef DEF_FUNCTION_TYPE_VAR_3 +#undef DEF_FUNCTION_TYPE_VAR_4 +#undef DEF_FUNCTION_TYPE_VAR_5 +#undef DEF_FUNCTION_TYPE_VAR_6 +#undef DEF_FUNCTION_TYPE_VAR_7 +#undef DEF_FUNCTION_TYPE_VAR_11 +#undef DEF_POINTER_TYPE + + BT_LAST, + }; + + enum Attr + { +#define DEF_ATTR_NULL_TREE(ENUM) ENUM, +#define DEF_ATTR_INT(ENUM, VALUE) ENUM, +#define DEF_ATTR_STRING(ENUM, VALUE) ENUM, +#define DEF_ATTR_IDENT(ENUM, STRING) ENUM, +#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) ENUM, + +#include "builtin-attrs.def" + +#undef DEF_ATTR_NULL_TREE +#undef DEF_ATTR_INT +#undef DEF_ATTR_STRING +#undef DEF_ATTR_IDENT +#undef DEF_ATTR_TREE_LIST + + ATTR_LAST, + }; + + /** + * All builtin types, as defined in `builtin-types.def` + * + * This array is filled by the `define_builtin_types` method, during the first + * initialization of the `BuiltinsContext` + */ + tree builtin_types[Type::BT_LAST + 1]; + + /** + * Similarly, this array contains all builtin attributes, as defined in + * `builtin-attr.def` + * + * This array is filled by the `define_builtin_attributes` method, during the + * first initialization of the `BuiltinsContext` + */ + tree builtin_attributes[Attr::ATTR_LAST + 1]; + + void define_function_type (Type def, Type ret, bool is_variadic, size_t n, + ...); + void define_builtin_types (); + void define_builtin_attributes (); + void define_builtins (); + + void register_rust_mappings (); + BuiltinsContext (); void setup_overflow_fns (); @@ -91,20 +197,10 @@ private: void setup (); - // Define a builtin function. BCODE is the builtin function code - // defined by builtins.def. NAME is the name of the builtin function. - // LIBNAME is the name of the corresponding library function, and is - // NULL if there isn't one. FNTYPE is the type of the function. - // CONST_P is true if the function has the const attribute. - // NORETURN_P is true if the function has the noreturn attribute. - void define_builtin (const std::string rust_name, built_in_function bcode, - const char *name, const char *libname, tree fntype, - int flags); - bool lookup_gcc_builtin (const std::string &name, tree *builtin); // A mapping of the GCC built-ins exposed to GCC Rust. - std::map builtin_functions_; + std::map builtin_functions; std::map rust_intrinsic_to_gcc_builtin; }; diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc index feaf74d..49ee4c0 100644 --- a/gcc/rust/backend/rust-compile-intrinsic.cc +++ b/gcc/rust/backend/rust-compile-intrinsic.cc @@ -29,6 +29,8 @@ #include "print-tree.h" #include "fold-const.h" #include "langhooks.h" +#include "rust-gcc.h" +#include "rust-constexpr.h" #include "print-tree.h" @@ -243,6 +245,14 @@ static const std::mapget_identifier (), &builtin)) return builtin; @@ -653,17 +664,17 @@ op_with_overflow_inner (Context *ctx, TyTy::FnType *fntype, tree_code op) switch (op) { case PLUS_EXPR: - BuiltinsContext::get ().lookup_simple_builtin ("add_overflow", + BuiltinsContext::get ().lookup_simple_builtin ("__builtin_add_overflow", &overflow_builtin); break; case MINUS_EXPR: - BuiltinsContext::get ().lookup_simple_builtin ("sub_overflow", + BuiltinsContext::get ().lookup_simple_builtin ("__builtin_sub_overflow", &overflow_builtin); break; case MULT_EXPR: - BuiltinsContext::get ().lookup_simple_builtin ("mul_overflow", + BuiltinsContext::get ().lookup_simple_builtin ("__builtin_mul_overflow", &overflow_builtin); break; @@ -749,8 +760,8 @@ copy_handler_inner (Context *ctx, TyTy::FnType *fntype, bool overlaps) = build2 (MULT_EXPR, size_type_node, TYPE_SIZE_UNIT (param_type), count); tree memcpy_raw = nullptr; - BuiltinsContext::get ().lookup_simple_builtin (overlaps ? "memmove" - : "memcpy", + BuiltinsContext::get ().lookup_simple_builtin (overlaps ? "__builtin_memmove" + : "__builtin_memcpy", &memcpy_raw); rust_assert (memcpy_raw); auto memcpy = build_fold_addr_expr_loc (UNKNOWN_LOCATION, memcpy_raw); @@ -797,18 +808,34 @@ prefetch_data_handler (Context *ctx, TyTy::FnType *fntype, Prefetch kind) enter_intrinsic_block (ctx, fndecl); auto addr = Backend::var_expression (args[0], UNDEF_LOCATION); - auto locality = Backend::var_expression (args[1], UNDEF_LOCATION); + + // The core library technically allows you to pass any i32 value as a + // locality, but LLVM will then complain if the value cannot be constant + // evaluated. For now, we ignore the locality argument and instead always + // pass `3` (the most restrictive value). This allows us to still have + // prefetch behavior, just not as granular as expected. In future Rust + // versions, we hope that prefetch intrinsics will be split up according to + // locality, similarly to atomic intrinsics. + // The solution is to try and perform constant folding for the locality + // argument, or instead of creating a new function definition, modify the call + // site directly This has the bad side-effect of creating warnings about + // `unused name - locality`, which we hack away here: + // TODO: Take care of handling locality properly + Backend::var_expression (args[1], UNDEF_LOCATION); + auto rw_flag = make_unsigned_long_tree (kind == Prefetch::Write ? 1 : 0); auto prefetch_raw = NULL_TREE; - auto ok - = BuiltinsContext::get ().lookup_simple_builtin ("prefetch", &prefetch_raw); + auto ok = BuiltinsContext::get ().lookup_simple_builtin ("__builtin_prefetch", + &prefetch_raw); rust_assert (ok); auto prefetch = build_fold_addr_expr_loc (UNKNOWN_LOCATION, prefetch_raw); - auto prefetch_call - = Backend::call_expression (prefetch, {addr, rw_flag, locality}, nullptr, - UNDEF_LOCATION); + auto prefetch_call = Backend::call_expression (prefetch, + {addr, rw_flag, + // locality arg + make_unsigned_long_tree (3)}, + nullptr, UNDEF_LOCATION); TREE_READONLY (prefetch_call) = 0; TREE_SIDE_EFFECTS (prefetch_call) = 1; @@ -833,7 +860,7 @@ build_atomic_builtin_name (const std::string &prefix, location_t locus, // TODO: Can we maybe get the generic version (atomic_store_n) to work... This // would be so much better - std::string result = prefix; + std::string result = "__" + prefix; // + "n"; auto type_name = operand_type->get_name (); if (type_name == "usize" || type_name == "isize") @@ -843,6 +870,13 @@ build_atomic_builtin_name (const std::string &prefix, location_t locus, return ""; } + if (type_name.at (0) == 'i') + { + rust_sorry_at (locus, "atomics are not yet supported for signed " + "integer types (i8, i16, i32, i64, i128)"); + return ""; + } + auto type_size_str = allowed_types.find (type_name); if (!check_for_basic_integer_type ("atomic", locus, operand_type)) @@ -970,6 +1004,7 @@ atomic_load_handler_inner (Context *ctx, TyTy::FnType *fntype, int ordering) TREE_SIDE_EFFECTS (load_call) = 1; ctx->add_statement (return_statement); + finalize_intrinsic_block (ctx, fndecl); return fndecl; @@ -1060,7 +1095,8 @@ uninit_handler (Context *ctx, TyTy::FnType *fntype) // BUILTIN size_of FN BODY BEGIN tree memset_builtin = error_mark_node; - BuiltinsContext::get ().lookup_simple_builtin ("memset", &memset_builtin); + BuiltinsContext::get ().lookup_simple_builtin ("__builtin_memset", + &memset_builtin); rust_assert (memset_builtin != error_mark_node); // call memset with 0x01 and size of the thing see @@ -1123,7 +1159,8 @@ move_val_init_handler (Context *ctx, TyTy::FnType *fntype) tree size = TYPE_SIZE_UNIT (template_parameter_type); tree memcpy_builtin = error_mark_node; - BuiltinsContext::get ().lookup_simple_builtin ("memcpy", &memcpy_builtin); + BuiltinsContext::get ().lookup_simple_builtin ("__builtin_memcpy", + &memcpy_builtin); rust_assert (memcpy_builtin != error_mark_node); src = build_fold_addr_expr_loc (BUILTINS_LOCATION, src); @@ -1157,7 +1194,8 @@ expect_handler_inner (Context *ctx, TyTy::FnType *fntype, bool likely) compile_fn_params (ctx, fntype, fndecl, ¶m_vars); tree expr = Backend::var_expression (param_vars[0], UNDEF_LOCATION); tree expect_fn_raw = nullptr; - BuiltinsContext::get ().lookup_simple_builtin ("expect", &expect_fn_raw); + BuiltinsContext::get ().lookup_simple_builtin ("__builtin_expect", + &expect_fn_raw); rust_assert (expect_fn_raw); auto expect_fn = build_fold_addr_expr_loc (BUILTINS_LOCATION, expect_fn_raw); diff --git a/gcc/rust/rust-attribs.cc b/gcc/rust/rust-attribs.cc new file mode 100644 index 0000000..134dcf9 --- /dev/null +++ b/gcc/rust/rust-attribs.cc @@ -0,0 +1,370 @@ +/* rust-attribs.c -- Rust attributes handling. + Copyright (C) 2015-2023 Free Software Foundation, Inc. + +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 +. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" + +#include "tree.h" +#include "diagnostic.h" +#include "tm.h" +#include "cgraph.h" +#include "toplev.h" +#include "target.h" +#include "common/common-target.h" +#include "stringpool.h" +#include "attribs.h" +#include "varasm.h" +#include "fold-const.h" +#include "opts.h" + +/* Heavily based on the D frontend Only a subset of the attributes found in the + * D frontend have been pulled, the goal being to have the builtin function + * correctly setup. It's possible we may need to add extra attributes in the + * future. + */ + +extern const attribute_spec grs_langhook_common_attribute_table[]; + +/* Internal attribute handlers for built-in functions. */ +static tree +handle_noreturn_attribute (tree *, tree, tree, int, bool *); +static tree +handle_leaf_attribute (tree *, tree, tree, int, bool *); +static tree +handle_const_attribute (tree *, tree, tree, int, bool *); +static tree +handle_malloc_attribute (tree *, tree, tree, int, bool *); +static tree +handle_pure_attribute (tree *, tree, tree, int, bool *); +static tree +handle_novops_attribute (tree *, tree, tree, int, bool *); +static tree +handle_nonnull_attribute (tree *, tree, tree, int, bool *); +static tree +handle_nothrow_attribute (tree *, tree, tree, int, bool *); +static tree +handle_type_generic_attribute (tree *, tree, tree, int, bool *); +static tree +handle_transaction_pure_attribute (tree *, tree, tree, int, bool *); +static tree +handle_returns_twice_attribute (tree *, tree, tree, int, bool *); +static tree +handle_fnspec_attribute (tree *, tree, tree, int, bool *); +static tree +handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *); + +/* Helper to define attribute exclusions. */ +#define ATTR_EXCL(name, function, type, variable) \ + { \ + name, function, type, variable \ + } + +static const struct attribute_spec::exclusions attr_noreturn_exclusions[] = { + // ATTR_EXCL ("alloc_size", true, true, true), + ATTR_EXCL ("const", true, true, true), + // ATTR_EXCL ("malloc", true, true, true), + ATTR_EXCL ("pure", true, true, true), + ATTR_EXCL ("returns_twice", true, true, true), + ATTR_EXCL (NULL, false, false, false), +}; + +static const struct attribute_spec::exclusions attr_returns_twice_exclusions[] + = { + ATTR_EXCL ("noreturn", true, true, true), + ATTR_EXCL (NULL, false, false, false), +}; + +static const struct attribute_spec::exclusions attr_const_pure_exclusions[] = { + // ATTR_EXCL ("alloc_size", true, true, true), + ATTR_EXCL ("const", true, true, true), + ATTR_EXCL ("noreturn", true, true, true), + ATTR_EXCL ("pure", true, true, true), ATTR_EXCL (NULL, false, false, false)}; + +/* Helper to define an attribute. */ +#define ATTR_SPEC(name, min_len, max_len, decl_req, type_req, fn_type_req, \ + affects_type_identity, handler, exclude) \ + { \ + name, min_len, max_len, decl_req, type_req, fn_type_req, \ + affects_type_identity, handler, exclude \ + } + +/* Table of machine-independent attributes. + For internal use (marking of built-ins) only. */ +const attribute_spec grs_langhook_common_attribute_table[] = { + ATTR_SPEC ("noreturn", 0, 0, true, false, false, false, + handle_noreturn_attribute, attr_noreturn_exclusions), + ATTR_SPEC ("leaf", 0, 0, true, false, false, false, handle_leaf_attribute, + NULL), + ATTR_SPEC ("const", 0, 0, true, false, false, false, handle_const_attribute, + attr_const_pure_exclusions), + ATTR_SPEC ("malloc", 0, 0, true, false, false, false, handle_malloc_attribute, + NULL), + ATTR_SPEC ("returns_twice", 0, 0, true, false, false, false, + handle_returns_twice_attribute, attr_returns_twice_exclusions), + ATTR_SPEC ("pure", 0, 0, true, false, false, false, handle_pure_attribute, + attr_const_pure_exclusions), + ATTR_SPEC ("nonnull", 0, -1, false, true, true, false, + handle_nonnull_attribute, NULL), + ATTR_SPEC ("nothrow", 0, 0, true, false, false, false, + handle_nothrow_attribute, NULL), + ATTR_SPEC ("transaction_pure", 0, 0, false, true, true, false, + handle_transaction_pure_attribute, NULL), + ATTR_SPEC ("no vops", 0, 0, true, false, false, false, + handle_novops_attribute, NULL), + ATTR_SPEC ("type generic", 0, 0, false, true, true, false, + handle_type_generic_attribute, NULL), + ATTR_SPEC ("fn spec", 1, 1, false, true, true, false, handle_fnspec_attribute, + NULL), + ATTR_SPEC ("omp declare simd", 0, -1, true, false, false, false, + handle_omp_declare_simd_attribute, NULL), + ATTR_SPEC (NULL, 0, 0, false, false, false, false, NULL, NULL), +}; + +/* Built-in attribute handlers. + These functions take the arguments: + (tree *node, tree name, tree args, int flags, bool *no_add_attrs) */ + +/* Handle a "noreturn" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_noreturn_attribute (tree *node, tree, tree, int, bool *) +{ + tree type = TREE_TYPE (*node); + + if (TREE_CODE (*node) == FUNCTION_DECL) + TREE_THIS_VOLATILE (*node) = 1; + else if (TREE_CODE (type) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) + TREE_TYPE (*node) = build_pointer_type ( + build_type_variant (TREE_TYPE (type), TYPE_READONLY (TREE_TYPE (type)), + 1)); + else + gcc_unreachable (); + + return NULL_TREE; +} + +/* Handle a "leaf" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_leaf_attribute (tree *node, tree name, tree, int, bool *no_add_attrs) +{ + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + if (!TREE_PUBLIC (*node)) + { + warning (OPT_Wattributes, "%qE attribute has no effect", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "const" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_const_attribute (tree *node, tree, tree, int, bool *) +{ + tree type = TREE_TYPE (*node); + + if (TREE_CODE (*node) == FUNCTION_DECL) + TREE_READONLY (*node) = 1; + else if (TREE_CODE (type) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) + TREE_TYPE (*node) = build_pointer_type ( + build_type_variant (TREE_TYPE (type), 1, + TREE_THIS_VOLATILE (TREE_TYPE (type)))); + else + gcc_unreachable (); + + return NULL_TREE; +} + +/* Handle a "malloc" attribute; arguments as in + struct attribute_spec.handler. */ + +tree +handle_malloc_attribute (tree *node, tree, tree, int, bool *) +{ + gcc_assert (TREE_CODE (*node) == FUNCTION_DECL + && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (*node)))); + DECL_IS_MALLOC (*node) = 1; + return NULL_TREE; +} + +/* Handle a "pure" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_pure_attribute (tree *node, tree, tree, int, bool *) +{ + gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); + DECL_PURE_P (*node) = 1; + return NULL_TREE; +} + +/* Handle a "no vops" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_novops_attribute (tree *node, tree, tree, int, bool *) +{ + gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); + DECL_IS_NOVOPS (*node) = 1; + return NULL_TREE; +} + +/* Helper for nonnull attribute handling; fetch the operand number + from the attribute argument list. */ + +static bool +get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp) +{ + /* Verify the arg number is a constant. */ + if (!tree_fits_uhwi_p (arg_num_expr)) + return false; + + *valp = TREE_INT_CST_LOW (arg_num_expr); + return true; +} + +/* Handle the "nonnull" attribute. */ + +static tree +handle_nonnull_attribute (tree *node, tree, tree args, int, bool *) +{ + tree type = *node; + + /* If no arguments are specified, all pointer arguments should be + non-null. Verify a full prototype is given so that the arguments + will have the correct types when we actually check them later. + Avoid diagnosing type-generic built-ins since those have no + prototype. */ + if (!args) + { + gcc_assert (prototype_p (type) || !TYPE_ATTRIBUTES (type) + || lookup_attribute ("type generic", TYPE_ATTRIBUTES (type))); + + return NULL_TREE; + } + + /* Argument list specified. Verify that each argument number references + a pointer argument. */ + for (; args; args = TREE_CHAIN (args)) + { + tree argument; + unsigned HOST_WIDE_INT arg_num = 0, ck_num; + + if (!get_nonnull_operand (TREE_VALUE (args), &arg_num)) + gcc_unreachable (); + + argument = TYPE_ARG_TYPES (type); + if (argument) + { + for (ck_num = 1;; ck_num++) + { + if (!argument || ck_num == arg_num) + break; + argument = TREE_CHAIN (argument); + } + + gcc_assert (argument + && TREE_CODE (TREE_VALUE (argument)) == POINTER_TYPE); + } + } + + return NULL_TREE; +} + +/* Handle a "nothrow" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_nothrow_attribute (tree *node, tree, tree, int, bool *) +{ + gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); + TREE_NOTHROW (*node) = 1; + return NULL_TREE; +} + +/* Handle a "type generic" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_type_generic_attribute (tree *node, tree, tree, int, bool *) +{ + /* Ensure we have a function type. */ + gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE); + + /* Ensure we have a variadic function. */ + gcc_assert (!prototype_p (*node) || stdarg_p (*node)); + + return NULL_TREE; +} + +/* Handle a "transaction_pure" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_transaction_pure_attribute (tree *node, tree, tree, int, bool *) +{ + /* Ensure we have a function type. */ + gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE); + + return NULL_TREE; +} + +/* Handle a "returns_twice" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_returns_twice_attribute (tree *node, tree, tree, int, bool *) +{ + gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); + + DECL_IS_RETURNS_TWICE (*node) = 1; + + return NULL_TREE; +} + +/* Handle a "fn spec" attribute; arguments as in + struct attribute_spec.handler. */ + +tree +handle_fnspec_attribute (tree *, tree, tree args, int, bool *) +{ + gcc_assert (args && TREE_CODE (TREE_VALUE (args)) == STRING_CST + && !TREE_CHAIN (args)); + return NULL_TREE; +} + +/* Handle an "omp declare simd" attribute; arguments as in + struct attribute_spec.handler. */ + +tree +handle_omp_declare_simd_attribute (tree *node, tree, tree, int, bool *) +{ + gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); + return NULL_TREE; +} diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index 580bda7..f17e19a 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -1131,20 +1131,20 @@ fetch_overflow_builtins (ArithmeticOrLogicalOperator op) switch (op) { case ArithmeticOrLogicalOperator::ADD: - builtin_ctx.lookup_simple_builtin ("add_overflow", &builtin); + builtin_ctx.lookup_simple_builtin ("__builtin_add_overflow", &builtin); break; case ArithmeticOrLogicalOperator::SUBTRACT: - builtin_ctx.lookup_simple_builtin ("sub_overflow", &builtin); + builtin_ctx.lookup_simple_builtin ("__builtin_sub_overflow", &builtin); break; case ArithmeticOrLogicalOperator::MULTIPLY: - builtin_ctx.lookup_simple_builtin ("mul_overflow", &builtin); + builtin_ctx.lookup_simple_builtin ("__builtin_mul_overflow", &builtin); break; default: rust_unreachable (); break; }; - builtin_ctx.lookup_simple_builtin ("abort", &abort); + builtin_ctx.lookup_simple_builtin ("__builtin_abort", &abort); rust_assert (abort); rust_assert (builtin); diff --git a/gcc/rust/rust-lang.cc b/gcc/rust/rust-lang.cc index f9bec3f..8b76ba2 100644 --- a/gcc/rust/rust-lang.cc +++ b/gcc/rust/rust-lang.cc @@ -380,6 +380,8 @@ rust_localize_identifier (const char *ident) return identifier_to_locale (ident); } +extern const attribute_spec grs_langhook_common_attribute_table[]; + /* The language hooks data structure. This is the main interface between the GCC * front-end and the GCC middle-end/back-end. A list of language hooks could be * found in /langhooks.h @@ -400,6 +402,8 @@ rust_localize_identifier (const char *ident) #undef LANG_HOOKS_GIMPLIFY_EXPR #undef LANG_HOOKS_EH_PERSONALITY +#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE + #define LANG_HOOKS_NAME "GNU Rust" #define LANG_HOOKS_INIT grs_langhook_init #define LANG_HOOKS_OPTION_LANG_MASK grs_langhook_option_lang_mask @@ -420,6 +424,8 @@ rust_localize_identifier (const char *ident) #define LANG_HOOKS_GIMPLIFY_EXPR grs_langhook_gimplify_expr #define LANG_HOOKS_EH_PERSONALITY grs_langhook_eh_personality +#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE grs_langhook_common_attribute_table + #if CHECKING_P #undef LANG_HOOKS_RUN_LANG_SELFTESTS diff --git a/gcc/testsuite/rust/compile/torture/builtin_abort.rs b/gcc/testsuite/rust/compile/torture/builtin_abort.rs new file mode 100644 index 0000000..3112cdc --- /dev/null +++ b/gcc/testsuite/rust/compile/torture/builtin_abort.rs @@ -0,0 +1,18 @@ +// { dg-options "-fdump-tree-original" } + +// { dg-final { scan-assembler-not "__builtin_abort\[^\"\]" } } +// { dg-final { scan-tree-dump "__builtin_abort" "original" } } + +#![feature(rustc_attrs)] +#![feature(intrinsics)] + +mod intrinsics { + extern "rust-intrinsic" { + pub fn abort() -> !; + } +} + +pub fn main () -> i32 { + abort(); + 0 +} diff --git a/gcc/testsuite/rust/compile/torture/intrinsics-1.rs b/gcc/testsuite/rust/compile/torture/intrinsics-1.rs deleted file mode 100644 index 6704c02..0000000 --- a/gcc/testsuite/rust/compile/torture/intrinsics-1.rs +++ /dev/null @@ -1,22 +0,0 @@ -// { dg-additional-options -fdump-tree-original } - -#![feature(intrinsics)] - -extern "rust-intrinsic" { - pub fn sqrtf32(x: f32) -> f32; - pub fn sinf32(x: f32) -> f32; -} - -fn main() { - unsafe fn foo() { - let mut f32; - - f32 = sqrtf32(5f32); - // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_sqrtf \(5\.0e\+0\);$} 1 original } } - - f32 = sinf32(39f32); - // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_sinf \(3\.9e\+1\);$} 1 original } } - } - - unsafe { foo() }; -} diff --git a/gcc/testsuite/rust/compile/torture/intrinsics-4.rs b/gcc/testsuite/rust/compile/torture/intrinsics-4.rs index 1f6c0d6..3d26e99 100644 --- a/gcc/testsuite/rust/compile/torture/intrinsics-4.rs +++ b/gcc/testsuite/rust/compile/torture/intrinsics-4.rs @@ -67,7 +67,7 @@ extern "rust-intrinsic" { } fn main() { - let mut dst = 15; + let mut dst = 15u32; let new_value = 14; unsafe { diff --git a/gcc/testsuite/rust/compile/torture/intrinsics-math.rs b/gcc/testsuite/rust/compile/torture/intrinsics-math.rs index fb329ba..42acdde 100644 --- a/gcc/testsuite/rust/compile/torture/intrinsics-math.rs +++ b/gcc/testsuite/rust/compile/torture/intrinsics-math.rs @@ -69,104 +69,104 @@ fn main() { let mut f64; f32 = sqrtf32(1f32); - // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_sqrtf \(1\.0e\+0\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_sqrt. \(.*.*1\.0e\+0\);$} 1 original } } f64 = sqrtf64(2f64); - // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_sqrt \(2\.0e\+0\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_sqrt.? \(.*2\.0e\+0\);$} 1 original } } f32 = sinf32(39f32); - // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_sinf \(3\.9e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_sin. \(.*3\.9e\+1\);$} 1 original } } f64 = sinf64(40f64); - // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_sin \(4\.0e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_sin.? \(.*4\.0e\+1\);$} 1 original } } f32 = cosf32(5f32); - // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_cosf \(5\.0e\+0\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_cos. \(.*5\.0e\+0\);$} 1 original } } f64 = cosf64(6f64); - // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_cos \(6\.0e\+0\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_cos.? \(.*6\.0e\+0\);$} 1 original } } f32 = powf32(7f32, 8f32); - // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_powf \(7\.0e\+0, 8\.0e\+0\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_pow. \(.*7\.0e\+0, .*8\.0e\+0\);$} 1 original } } f64 = powf64(9f64, 10f64); - // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_pow \(9\.0e\+0, 1\.0e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_pow.? \(.*9\.0e\+0, .*1\.0e\+1\);$} 1 original } } f32 = expf32(11f32); - // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_expf \(1\.1e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_exp. \(.*1\.1e\+1\);$} 1 original } } f64 = expf64(12f64); - // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_exp \(1\.2e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_exp.? \(.*1\.2e\+1\);$} 1 original } } f32 = exp2f32(13f32); - // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_expf \(1\.1e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_exp. \(.*1\.1e\+1\);$} 1 original } } f64 = exp2f64(14f64); - // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_exp \(1\.2e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_exp.? \(.*1\.2e\+1\);$} 1 original } } f32 = logf32(15f32); - // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_logf \(1\.5e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_log. \(.*1\.5e\+1\);$} 1 original } } f64 = logf64(16f64); - // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_log \(1\.6e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_log.? \(.*1\.6e\+1\);$} 1 original } } f32 = log10f32(17f32); - // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_log10f \(1\.7e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_log10. \(.*1\.7e\+1\);$} 1 original } } f64 = log10f64(18f64); - // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_log10 \(1\.8e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_log10.? \(.*1\.8e\+1\);$} 1 original } } f32 = log2f32(19f32); - // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_log2f \(1\.9e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_log2. \(.*1\.9e\+1\);$} 1 original } } f64 = log2f64(20f64); - // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_log2 \(2\.0e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_log2.? \(.*2\.0e\+1\);$} 1 original } } f32 = fmaf32(21f32, 22f32, 23f32); - // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_fmaf \(2\.1e\+1, 2\.2e\+1, 2\.3e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_fma. \(.*2\.1e\+1, .*2\.2e\+1, .*2\.3e\+1\);$} 1 original } } f64 = fmaf64(24f64, 25f64, 26f64); - // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_fma \(2\.4e\+1, 2\.5e\+1, 2\.6e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_fma.? \(.*2\.4e\+1, .*2\.5e\+1, .*2\.6e\+1\);$} 1 original } } f32 = fabsf32(27f32); - // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_fabsf \(2\.7e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_fabs. \(.*2\.7e\+1\);$} 1 original } } f64 = fabsf64(28f64); - // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_fabs \(2\.8e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_fabs.? \(.*2\.8e\+1\);$} 1 original } } f32 = minnumf32(29f32, 30f32); - // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_fminf \(2\.9e\+1, 3\.0e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_fmin. \(.*2\.9e\+1, .*3\.0e\+1\);$} 1 original } } f64 = minnumf64(31f64, 32f64); - // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_fmin \(3\.1e\+1, 3\.2e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_fmin.? \(.*3\.1e\+1, .*3\.2e\+1\);$} 1 original } } f32 = maxnumf32(33f32, 34f32); - // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_fmaxf \(3\.3e\+1, 3\.4e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_fmax. \(.*3\.3e\+1, .*3\.4e\+1\);$} 1 original } } f64 = maxnumf64(35f64, 36f64); - // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_fmax \(3\.5e\+1, 3\.6e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_fmax.? \(.*3\.5e\+1, .*3\.6e\+1\);$} 1 original } } f32 = copysignf32(37f32, 38f32); - // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_copysignf \(3\.7e\+1, 3\.8e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_copysign. \(.*3\.7e\+1, .*3\.8e\+1\);$} 1 original } } f64 = copysignf64(39f64, 40f64); - // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_copysign \(3\.9e\+1, 4\.0e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_copysign.? \(.*3\.9e\+1, .*4\.0e\+1\);$} 1 original } } f32 = floorf32(41f32); - // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_floorf \(4\.1e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_floor. \(.*4\.1e\+1\);$} 1 original } } f64 = floorf64(42f64); - // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_floor \(4\.2e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_floor.? \(.*4\.2e\+1\);$} 1 original } } f32 = ceilf32(43f32); - // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_ceilf \(4\.3e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_ceil. \(.*4\.3e\+1\);$} 1 original } } f64 = ceilf64(44f64); - // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_ceil \(4\.4e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_ceil.? \(.*4\.4e\+1\);$} 1 original } } f32 = truncf32(45f32); - // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_truncf \(4\.5e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_trunc. \(.*4\.5e\+1\);$} 1 original } } f64 = truncf64(46f64); - // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_trunc \(4\.6e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_trunc.? \(.*4\.6e\+1\);$} 1 original } } f32 = rintf32(47f32); - // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_rintf \(4\.7e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_rint. \(.*4\.7e\+1\);$} 1 original } } f64 = rintf64(48f64); - // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_rint \(4\.8e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_rint.? \(.*4\.8e\+1\);$} 1 original } } f32 = nearbyintf32(49f32); - // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_nearbyintf \(4\.9e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_nearbyint. \(.*4\.9e\+1\);$} 1 original } } f64 = nearbyintf64(50f64); - // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_nearbyint \(5\.0e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_nearbyint.? \(.*5\.0e\+1\);$} 1 original } } f32 = roundf32(51f32); - // { dg-final { scan-tree-dump-times {(?n)f32 = __builtin_roundf \(5\.1e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f32 .* __builtin_round. \(.*5\.1e\+1\);$} 1 original } } f64 = roundf64(52f64); - // { dg-final { scan-tree-dump-times {(?n)f64 = __builtin_round \(5\.2e\+1\);$} 1 original } } + // { dg-final { scan-tree-dump-times {(?n)f64 .* __builtin_round.? \(.*5\.2e\+1\);$} 1 original } } } unsafe { foo() }; diff --git a/gcc/testsuite/rust/execute/torture/atomic_load.rs b/gcc/testsuite/rust/execute/torture/atomic_load.rs index b66c464..11da848 100644 --- a/gcc/testsuite/rust/execute/torture/atomic_load.rs +++ b/gcc/testsuite/rust/execute/torture/atomic_load.rs @@ -66,14 +66,14 @@ extern "rust-intrinsic" { pub fn atomic_load_unordered(src: *const T) -> T; } -fn main() -> i32 { +fn main() -> u32 { let one; let two; let three; let four; unsafe { - let mut src = 1; + let mut src = 1u32; one = atomic_load_seqcst(&src); src = 2; diff --git a/gcc/testsuite/rust/execute/torture/atomic_store.rs b/gcc/testsuite/rust/execute/torture/atomic_store.rs index dcbb2a9..1b46678 100644 --- a/gcc/testsuite/rust/execute/torture/atomic_store.rs +++ b/gcc/testsuite/rust/execute/torture/atomic_store.rs @@ -66,8 +66,8 @@ extern "rust-intrinsic" { pub fn atomic_store_unordered(dst: *mut T, val: T); } -fn main() -> i32 { - let mut dst = 15; +fn main() -> u32 { + let mut dst = 15u32; let one; let two; let three; diff --git a/gcc/testsuite/rust/execute/torture/builtin_abort.rs b/gcc/testsuite/rust/execute/torture/builtin_abort.rs new file mode 100644 index 0000000..9f2d8c2 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/builtin_abort.rs @@ -0,0 +1,14 @@ +// { dg-shouldfail "abort should stop the program" } +#![feature(rustc_attrs)] +#![feature(intrinsics)] + +mod intrinsics { + extern "rust-intrinsic" { + pub fn abort() -> !; + } +} + +pub fn main () -> i32 { + abort(); + 0 +} -- cgit v1.1 From cc9465332ebcabebb04b95549989d74a8f1c0ce6 Mon Sep 17 00:00:00 2001 From: Jakub Dupak Date: Sun, 3 Dec 2023 11:07:04 +0100 Subject: gccrs: HIR: add missing getters gcc/rust/ChangeLog: * hir/tree/rust-hir-item.h: Ad lifetime getter. * hir/tree/rust-hir-path.h: Make getter const ref. * hir/tree/rust-hir.h: Const ref and new getter. Signed-off-by: Jakub Dupak --- gcc/rust/hir/tree/rust-hir-item.h | 2 ++ gcc/rust/hir/tree/rust-hir-path.h | 4 ++++ gcc/rust/hir/tree/rust-hir.h | 7 ++++++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index f72d8c8..7445078 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -443,6 +443,8 @@ public: // Returns whether the self-param has a valid lifetime. bool has_lifetime () const { return !lifetime.is_error (); } + const Lifetime &get_lifetime () const { return lifetime; } + // Returns whether the self-param is in an error state. bool is_error () const { return self_kind == ImplicitSelfKind::NONE; } diff --git a/gcc/rust/hir/tree/rust-hir-path.h b/gcc/rust/hir/tree/rust-hir-path.h index 9fe126a..0566e2e 100644 --- a/gcc/rust/hir/tree/rust-hir-path.h +++ b/gcc/rust/hir/tree/rust-hir-path.h @@ -218,6 +218,10 @@ public: std::string as_string () const; std::vector &get_lifetime_args () { return lifetime_args; } + const std::vector &get_lifetime_args () const + { + return lifetime_args; + } std::vector > &get_type_args () { return type_args; } diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h index 0f2d522..f66f53f 100644 --- a/gcc/rust/hir/tree/rust-hir.h +++ b/gcc/rust/hir/tree/rust-hir.h @@ -572,7 +572,10 @@ public: void accept_vis (HIRFullVisitor &vis) override; - std::string get_name () const { return lifetime_name; } + WARN_UNUSED_RESULT const std::string &get_name () const + { + return lifetime_name; + } AST::Lifetime::LifetimeType get_lifetime_type () const { @@ -662,6 +665,8 @@ public: // Returns whether the lifetime param has any lifetime bounds. bool has_lifetime_bounds () const { return !lifetime_bounds.empty (); } + std::vector &get_lifetime_bounds () { return lifetime_bounds; } + // Returns whether the lifetime param has an outer attribute. bool has_outer_attribute () const { return !outer_attr.is_empty (); } -- cgit v1.1 From ed198edc9bfc17b4c2356068623aa31bda4e1ee7 Mon Sep 17 00:00:00 2001 From: Jakub Dupak Date: Sun, 3 Dec 2023 11:13:04 +0100 Subject: gccrs: TyTy: Fix missed nodiscard gcc/rust/ChangeLog: * typecheck/rust-tyty.h: Fix nodiscard to warn unused. Signed-off-by: Jakub Dupak --- gcc/rust/typecheck/rust-tyty.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 8bfa83d..da4b901 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -177,7 +177,7 @@ public: virtual BaseType *clone () const = 0; // Check if TyTy::BaseType is of a specific type. - template [[nodiscard]] bool is () const + template WARN_UNUSED_RESULT bool is () const { static_assert (std::is_base_of::value, "Can only safely cast to TyTy types."); -- cgit v1.1 From 35d5f82eaeaa849997039586109b0b302a88148a Mon Sep 17 00:00:00 2001 From: Jakub Dupak Date: Mon, 11 Dec 2023 21:52:48 +0100 Subject: gccrs: BIR: Fix missed nodiscard gcc/rust/ChangeLog: * checks/errors/borrowck/rust-bir-builder-internal.h: Replace nodiscard. * checks/errors/borrowck/rust-bir-place.h: Replace nodiscard. Signed-off-by: Jakub Dupak --- gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h | 4 ++-- gcc/rust/checks/errors/borrowck/rust-bir-place.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h index f33eb07..cd61151 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h @@ -261,12 +261,12 @@ protected: // CFG helpers protected: // HIR resolution helpers template - [[nodiscard]] TyTy::BaseType *lookup_type (T &hir_node) const + WARN_UNUSED_RESULT TyTy::BaseType *lookup_type (T &hir_node) const { return lookup_type (hir_node.get_mappings ().get_hirid ()); } - [[nodiscard]] TyTy::BaseType *lookup_type (HirId hirid) const + WARN_UNUSED_RESULT TyTy::BaseType *lookup_type (HirId hirid) const { TyTy::BaseType *type = nullptr; bool ok = ctx.tyctx.lookup_type (hirid, &type); diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-place.h b/gcc/rust/checks/errors/borrowck/rust-bir-place.h index 66b131d..8c2df47 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-place.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-place.h @@ -148,9 +148,9 @@ public: 0); } - [[nodiscard]] PlaceId lookup_or_add_path (Place::Kind kind, - TyTy::BaseType *tyty, - PlaceId parent, size_t id = 0) + WARN_UNUSED_RESULT PlaceId lookup_or_add_path (Place::Kind kind, + TyTy::BaseType *tyty, + PlaceId parent, size_t id = 0) { PlaceId current = 0; if (parent < places.size ()) -- cgit v1.1 From 7eaef4f5b19a6e5298ce63218a0af791f54f8102 Mon Sep 17 00:00:00 2001 From: Jakub Dupak Date: Sun, 3 Dec 2023 11:15:06 +0100 Subject: gccrs: TyTy: refactor to new API gcc/rust/ChangeLog: * typecheck/rust-hir-type-check-type.cc (TypeCheckType::resolve_root_path): Refactor. Signed-off-by: Jakub Dupak --- gcc/rust/typecheck/rust-hir-type-check-type.cc | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc index 62a1776..9519201 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc @@ -442,14 +442,9 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset, root_tyty = lookup; // this enforces the proper get_segments checks to take place - bool is_adt = root_tyty->get_kind () == TyTy::TypeKind::ADT; - if (is_adt) - { - const TyTy::ADTType &adt - = *static_cast (root_tyty); - if (adt.is_enum ()) - return root_tyty; - } + auto *maybe_adt = root_tyty->try_as (); + if (maybe_adt && maybe_adt->is_enum ()) + return root_tyty; } return root_tyty; -- cgit v1.1 From 44c58e2972826bd795431a3dada784b65c4d6487 Mon Sep 17 00:00:00 2001 From: Jakub Dupak Date: Sun, 3 Dec 2023 11:16:59 +0100 Subject: gccrs: TyTy: Common interface for fucntion-like types gcc/rust/ChangeLog: * typecheck/rust-tyty.h (class ClosureType): Inherit interface. (class FnPtr): Inherit interface. (class FnType): Inherit interface. (class CallableTypeInterface): New interface. (BaseType::is): Detect interface members API. Signed-off-by: Jakub Dupak --- gcc/rust/typecheck/rust-tyty.h | 116 ++++++++++++++++++++++++++++++++++------- 1 file changed, 98 insertions(+), 18 deletions(-) diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index da4b901..6ce760d 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -38,6 +38,10 @@ class AssociatedImplTrait; } // namespace Resolver namespace TyTy { +class ClosureType; +class FnPtr; +class FnType; +class CallableTypeInterface; // https://rustc-dev-guide.rust-lang.org/type-inference.html#inference-variables // https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variants @@ -242,6 +246,22 @@ protected: Analysis::Mappings *mappings; }; +/** Unified interface for all function-like types. */ +class CallableTypeInterface : public BaseType +{ +public: + explicit CallableTypeInterface (HirId ref, HirId ty_ref, TypeKind kind, + RustIdent ident, + std::set refs = std::set ()) + : BaseType (ref, ty_ref, kind, ident, refs) + {} + + WARN_UNUSED_RESULT virtual size_t get_num_params () const = 0; + WARN_UNUSED_RESULT virtual BaseType * + get_param_type_at (size_t index) const = 0; + WARN_UNUSED_RESULT virtual BaseType *get_return_type () const = 0; +}; + class InferType : public BaseType { public: @@ -736,7 +756,7 @@ private: ReprOptions repr; }; -class FnType : public BaseType, public SubstitutionRef +class FnType : public CallableTypeInterface, public SubstitutionRef { public: static constexpr auto KIND = TypeKind::FNDEF; @@ -751,7 +771,7 @@ public: std::vector> params, BaseType *type, std::vector subst_refs, std::set refs = std::set ()) - : BaseType (ref, ref, TypeKind::FNDEF, ident, refs), + : CallableTypeInterface (ref, ref, TypeKind::FNDEF, ident, refs), SubstitutionRef (std::move (subst_refs), SubstitutionArgumentMappings::error ()), params (std::move (params)), type (type), flags (flags), @@ -766,7 +786,7 @@ public: std::vector> params, BaseType *type, std::vector subst_refs, std::set refs = std::set ()) - : BaseType (ref, ty_ref, TypeKind::FNDEF, ident, refs), + : CallableTypeInterface (ref, ty_ref, TypeKind::FNDEF, ident, refs), SubstitutionRef (std::move (subst_refs), SubstitutionArgumentMappings::error ()), params (params), type (type), flags (flags), identifier (identifier), @@ -832,8 +852,6 @@ public: return params.at (idx); } - BaseType *get_return_type () const { return type; } - BaseType *clone () const final override; FnType * @@ -842,6 +860,21 @@ public: ABI get_abi () const { return abi; } uint8_t get_flags () const { return flags; } + WARN_UNUSED_RESULT size_t get_num_params () const override + { + return params.size (); + } + + WARN_UNUSED_RESULT BaseType *get_param_type_at (size_t index) const override + { + return param_at (index).second; + } + + WARN_UNUSED_RESULT BaseType *get_return_type () const override + { + return type; + } + private: std::vector> params; BaseType *type; @@ -851,33 +884,50 @@ private: ABI abi; }; -class FnPtr : public BaseType +class FnPtr : public CallableTypeInterface { public: static constexpr auto KIND = TypeKind::FNPTR; FnPtr (HirId ref, location_t locus, std::vector params, TyVar result_type, std::set refs = std::set ()) - : BaseType (ref, ref, TypeKind::FNPTR, - {Resolver::CanonicalPath::create_empty (), locus}, refs), + : CallableTypeInterface (ref, ref, TypeKind::FNPTR, + {Resolver::CanonicalPath::create_empty (), locus}, + refs), params (std::move (params)), result_type (result_type) {} FnPtr (HirId ref, HirId ty_ref, location_t locus, std::vector params, TyVar result_type, std::set refs = std::set ()) - : BaseType (ref, ty_ref, TypeKind::FNPTR, - {Resolver::CanonicalPath::create_empty (), locus}, refs), + : CallableTypeInterface (ref, ty_ref, TypeKind::FNPTR, + {Resolver::CanonicalPath::create_empty (), locus}, + refs), params (params), result_type (result_type) {} std::string get_name () const override final { return as_string (); } - BaseType *get_return_type () const { return result_type.get_tyty (); } + WARN_UNUSED_RESULT size_t get_num_params () const override + { + return params.size (); + } + + WARN_UNUSED_RESULT BaseType *get_param_type_at (size_t index) const override + { + return params.at (index).get_tyty (); + } + + WARN_UNUSED_RESULT BaseType *get_return_type () const override + { + return result_type.get_tyty (); + } + const TyVar &get_var_return_type () const { return result_type; } size_t num_params () const { return params.size (); } - BaseType *param_at (size_t idx) const { return params.at (idx).get_tyty (); } + // DEPRECATED: Use get_param_type_at + BaseType *param_at (size_t idx) const { return get_param_type_at (idx); } void accept_vis (TyVisitor &vis) override; void accept_vis (TyConstVisitor &vis) const override; @@ -898,19 +948,19 @@ private: TyVar result_type; }; -class ClosureType : public BaseType, public SubstitutionRef +class ClosureType : public CallableTypeInterface, public SubstitutionRef { public: static constexpr auto KIND = TypeKind::CLOSURE; - ClosureType (HirId ref, DefId id, RustIdent ident, - TyTy::TupleType *parameters, TyVar result_type, + ClosureType (HirId ref, DefId id, RustIdent ident, TupleType *parameters, + TyVar result_type, std::vector subst_refs, std::set captures, std::set refs = std::set (), std::vector specified_bounds = std::vector ()) - : BaseType (ref, ref, TypeKind::CLOSURE, ident, refs), + : CallableTypeInterface (ref, ref, TypeKind::CLOSURE, ident, refs), SubstitutionRef (std::move (subst_refs), SubstitutionArgumentMappings::error ()), parameters (parameters), result_type (std::move (result_type)), id (id), @@ -922,13 +972,13 @@ public: } ClosureType (HirId ref, HirId ty_ref, RustIdent ident, DefId id, - TyTy::TupleType *parameters, TyVar result_type, + TupleType *parameters, TyVar result_type, std::vector subst_refs, std::set captures, std::set refs = std::set (), std::vector specified_bounds = std::vector ()) - : BaseType (ref, ty_ref, TypeKind::CLOSURE, ident, refs), + : CallableTypeInterface (ref, ty_ref, TypeKind::CLOSURE, ident, refs), SubstitutionRef (std::move (subst_refs), SubstitutionArgumentMappings::error ()), parameters (parameters), result_type (std::move (result_type)), id (id), @@ -942,6 +992,21 @@ public: void accept_vis (TyVisitor &vis) override; void accept_vis (TyConstVisitor &vis) const override; + WARN_UNUSED_RESULT size_t get_num_params () const override + { + return parameters->num_fields (); + } + + WARN_UNUSED_RESULT BaseType *get_param_type_at (size_t index) const override + { + return parameters->get_field (index); + } + + WARN_UNUSED_RESULT BaseType *get_return_type () const override + { + return result_type.get_tyty (); + } + std::string as_string () const override; std::string get_name () const override final { return as_string (); } @@ -1495,6 +1560,21 @@ private: DefId item; }; +template <> +WARN_UNUSED_RESULT inline bool +BaseType::is () const +{ + auto kind = this->get_kind (); + return kind == FNPTR || kind == FNDEF || kind == CLOSURE; +} + +template <> +WARN_UNUSED_RESULT inline bool +BaseType::is () const +{ + return this->is (); +} + } // namespace TyTy } // namespace Rust -- cgit v1.1 From 75e6d0cf415c939b020cef2e2693b652848ae45d Mon Sep 17 00:00:00 2001 From: Jakub Dupak Date: Mon, 11 Dec 2023 23:11:34 +0100 Subject: gccrs: TyTy: SubstitutionRef cast specialization Allows skipping parent check when casting. gcc/rust/ChangeLog: * typecheck/rust-tyty.h (BaseType::is): Cast API. (SubstitutionRef>): Cast API. (BaseType::as): Cast API. (BaseType::try_as): Cast API. Signed-off-by: Jakub Dupak --- gcc/rust/typecheck/rust-tyty.h | 78 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 6ce760d..2ed407e 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -1575,6 +1575,84 @@ BaseType::is () const return this->is (); } +template <> +WARN_UNUSED_RESULT inline bool +BaseType::is () const +{ + auto kind = this->get_kind (); + return kind == FNPTR || kind == FNDEF || kind == CLOSURE || kind == ADT + || kind == PROJECTION; +} + +template <> +WARN_UNUSED_RESULT inline bool +BaseType::is () const +{ + return this->is (); +} + +template <> +WARN_UNUSED_RESULT inline SubstitutionRef * +BaseType::as () +{ + auto kind = this->get_kind (); + switch (kind) + { + case FNDEF: + return static_cast (this); + case CLOSURE: + return static_cast (this); + case ADT: + return static_cast (this); + case PROJECTION: + return static_cast (this); + default: + rust_unreachable (); + } +} + +template <> +WARN_UNUSED_RESULT inline const SubstitutionRef * +BaseType::as () const +{ + auto kind = this->get_kind (); + switch (kind) + { + case FNDEF: + return static_cast (this); + case CLOSURE: + return static_cast (this); + case ADT: + return static_cast (this); + case PROJECTION: + return static_cast (this); + default: + rust_unreachable (); + } +} + +template <> +WARN_UNUSED_RESULT inline SubstitutionRef * +BaseType::try_as () +{ + if (this->is ()) + { + return this->as (); + } + return nullptr; +} + +template <> +WARN_UNUSED_RESULT inline const SubstitutionRef * +BaseType::try_as () const +{ + if (this->is ()) + { + return this->as (); + } + return nullptr; +} + } // namespace TyTy } // namespace Rust -- cgit v1.1 From c54326a8677f6c978523502d5041537d0acf6867 Mon Sep 17 00:00:00 2001 From: Jakub Dupak Date: Mon, 11 Dec 2023 22:09:07 +0100 Subject: gccrs: BIR: Cleanup gcc/rust/ChangeLog: * checks/errors/borrowck/rust-bir-place.h: Cleanup. * checks/errors/borrowck/rust-borrow-checker.h: Cleanup. Signed-off-by: Jakub Dupak --- gcc/rust/checks/errors/borrowck/rust-bir-place.h | 2 +- gcc/rust/checks/errors/borrowck/rust-borrow-checker.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-place.h b/gcc/rust/checks/errors/borrowck/rust-bir-place.h index 8c2df47..523c2f6 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-place.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-place.h @@ -211,7 +211,7 @@ public: auto lookup = lookup_variable (id); if (lookup != INVALID_PLACE) return lookup; - places.push_back ( + add_place ( {Place::VARIABLE, id, {}, is_type_copy (tyty), false, NO_LIFETIME, tyty}); return places.size () - 1; }; diff --git a/gcc/rust/checks/errors/borrowck/rust-borrow-checker.h b/gcc/rust/checks/errors/borrowck/rust-borrow-checker.h index 549af35..e1a3f19 100644 --- a/gcc/rust/checks/errors/borrowck/rust-borrow-checker.h +++ b/gcc/rust/checks/errors/borrowck/rust-borrow-checker.h @@ -30,7 +30,8 @@ class BorrowChecker public: explicit BorrowChecker (bool enable_dump_bir) - : enable_dump_bir (enable_dump_bir){}; + : enable_dump_bir (enable_dump_bir) + {} /** Perform borrow-checking using polonius on an entire crate */ void go (HIR::Crate &crate); -- cgit v1.1 From 7b80033eaea03a46e0e73965819ff363ad553b5d Mon Sep 17 00:00:00 2001 From: Raiki Tamura Date: Tue, 26 Dec 2023 13:08:42 +0900 Subject: gccrs: split rust-mangle.cc into two files gcc/rust/ChangeLog: * Make-lang.in: Add .o files * backend/rust-mangle.cc (struct V0Path): moved to splitted files (v0_path): Likewise. (legacy_mangle_name): Likewise. (legacy_mangle_canonical_path): Likewise. (legacy_hash): Likewise. (v0_tuple_prefix): Likewise. (v0_numeric_prefix): Likewise. (v0_simple_type_prefix): Likewise. (v0_complex_type_prefix): Likewise. (v0_integer_62): Likewise. (v0_opt_integer_62): Likewise. (v0_disambiguator): Likewise. (v0_type_prefix): Likewise. (v0_generic_args): Likewise. (v0_identifier): Likewise. (v0_type_path): Likewise. (v0_function_path): Likewise. (v0_scope_path): Likewise. (v0_crate_path): Likewise. (v0_inherent_or_trait_impl_path): Likewise. (v0_closure): Likewise. (legacy_mangle_item): Likewise. (v0_mangle_item): Likewise. * backend/rust-mangle.h (legacy_mangle_item): Likewise. (v0_mangle_item): Likewise. * backend/rust-mangle-legacy.cc: New file. * backend/rust-mangle-v0.cc: New file. Signed-off-by: Raiki Tamura --- gcc/rust/Make-lang.in | 2 + gcc/rust/backend/rust-mangle-legacy.cc | 164 +++++++++ gcc/rust/backend/rust-mangle-v0.cc | 508 ++++++++++++++++++++++++++ gcc/rust/backend/rust-mangle.cc | 648 +-------------------------------- gcc/rust/backend/rust-mangle.h | 8 + 5 files changed, 700 insertions(+), 630 deletions(-) create mode 100644 gcc/rust/backend/rust-mangle-legacy.cc create mode 100644 gcc/rust/backend/rust-mangle-v0.cc diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index b138ba2..bdaef41 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -85,6 +85,8 @@ GRS_OBJS = \ rust/rust-session-manager.o \ rust/rust-compile.o \ rust/rust-mangle.o \ + rust/rust-mangle-v0.o \ + rust/rust-mangle-legacy.o \ rust/rust-compile-resolve-path.o \ rust/rust-macro-expand.o \ rust/rust-cfg-strip.o \ diff --git a/gcc/rust/backend/rust-mangle-legacy.cc b/gcc/rust/backend/rust-mangle-legacy.cc new file mode 100644 index 0000000..fd0ba1b --- /dev/null +++ b/gcc/rust/backend/rust-mangle-legacy.cc @@ -0,0 +1,164 @@ +// Copyright (C) 2020-2023 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 +// . + +#include "rust-mangle.h" +#include "fnv-hash.h" +#include "rust-unicode.h" +#include "rust-diagnostics.h" +#include "rust-system.h" +#include + +namespace Rust { +namespace Compile { + +const std::string kLegacySymbolPrefix = "_ZN"; +static const std::string kLegacySymbolDelim = "E"; +static const std::string kLegacyGenericDelim = "$C$"; +static const std::string kLegacySubstBegin = "$LT$"; +static const std::string kLegacySubstEnd = "$GT$"; +static const std::string kLegacySpace = "$u20$"; +static const std::string kLegacyRef = "$RF$"; +static const std::string kLegacyPtr = "$BP$"; +static const std::string kLegacyLeftSqParen = "$u5b$"; // [ +static const std::string kLegacyRightSqParen = "$u5d$"; // ] +static const std::string kLegacyLeftBrace = "$u7b$"; // { +static const std::string kLegacyRightBrace = "$u7d$"; // } +static const std::string kQualPathBegin = "_" + kLegacySubstBegin; +static const std::string kLegacyComma = "$C$"; + +static std::string +legacy_mangle_name (const std::string &name) +{ + // example + // <&T as core::fmt::Debug>::fmt: + // _ZN42_$LT$$RF$T$u20$as$u20$core..fmt..Debug$GT$3fmt17h6dac924c0051eef7E + // replace all white space with $ and & with RF + // + // ::fooA: + // _ZN43_$LT$example..Bar$u20$as$u20$example..A$GT$4fooA17hfc615fa76c7db7a0E: + // + // core::ptr::const_ptr::::cast: + // _ZN4core3ptr9const_ptr33_$LT$impl$u20$$BP$const$u20$T$GT$4cast17hb79f4617226f1d55E: + // + // core::ptr::const_ptr::::as_ptr: + // _ZN4core3ptr9const_ptr43_$LT$impl$u20$$BP$const$u20$$u5b$T$u5d$$GT$6as_ptr17he16e0dcd9473b04fE: + // + // example::Foo::new: + // _ZN7example12Foo$LT$T$GT$3new17h9a2aacb7fd783515E: + // + // >::call + // _ZN74_$LT$example..Identity$u20$as$u20$example..FnLike$LT$$RF$T$C$$RF$T$GT$$GT$4call17ha9ee58935895acb3E + + tl::optional utf8_name = Utf8String::make_utf8_string (name); + rust_assert (utf8_name.has_value ()); + std::vector chars = utf8_name.value ().get_chars (); + std::string buffer; + for (size_t i = 0; i < chars.size (); i++) + { + std::string m; + Codepoint c = chars.at (i); + + if (c == ' ') + m = kLegacySpace; + else if (c == '&') + m = kLegacyRef; + else if (i == 0 && c == '<') + m = kQualPathBegin; + else if (c == '<') + m = kLegacySubstBegin; + else if (c == '>') + m = kLegacySubstEnd; + else if (c == '*') + m = kLegacyPtr; + else if (c == '[') + m = kLegacyLeftSqParen; + else if (c == ']') + m = kLegacyRightSqParen; + else if (c == '{') + m = kLegacyLeftBrace; + else if (c == '}') + m = kLegacyRightBrace; + else if (c == ',') + m = kLegacyComma; + else if (c == ':') + { + rust_assert (i + 1 < chars.size ()); + rust_assert (chars.at (i + 1) == ':'); + i++; + m = ".."; + } + else if (c.is_ascii ()) + // ASCII + m.push_back (c.value); + else + { + // Non-ASCII + std::stringstream escaped; + escaped << std::hex << "$u" << c.value << "$"; + m += escaped.str (); + } + buffer += m; + } + + return std::to_string (buffer.size ()) + buffer; +} + +static std::string +legacy_mangle_canonical_path (const Resolver::CanonicalPath &path) +{ + std::string buffer; + for (size_t i = 0; i < path.size (); i++) + { + auto &seg = path.get_seg_at (i); + buffer += legacy_mangle_name (seg.second); + } + return buffer; +} + +// rustc uses a sip128 hash for legacy mangling, but an fnv 128 was quicker to +// implement for now +static std::string +legacy_hash (const std::string &fingerprint) +{ + Hash::FNV128 hasher; + hasher.write ((const unsigned char *) fingerprint.c_str (), + fingerprint.size ()); + + uint64_t hi, lo; + hasher.sum (&hi, &lo); + + char hex[16 + 1]; + memset (hex, 0, sizeof hex); + snprintf (hex, sizeof hex, "%08" PRIx64 "%08" PRIx64, lo, hi); + + return "h" + std::string (hex, sizeof (hex) - 1); +} + +std::string +legacy_mangle_item (const TyTy::BaseType *ty, + const Resolver::CanonicalPath &path) +{ + const std::string hash = legacy_hash (ty->mangle_string ()); + const std::string hash_sig = legacy_mangle_name (hash); + + return kLegacySymbolPrefix + legacy_mangle_canonical_path (path) + hash_sig + + kLegacySymbolDelim; +} + +} // namespace Compile +} // namespace Rust diff --git a/gcc/rust/backend/rust-mangle-v0.cc b/gcc/rust/backend/rust-mangle-v0.cc new file mode 100644 index 0000000..634ccb0 --- /dev/null +++ b/gcc/rust/backend/rust-mangle-v0.cc @@ -0,0 +1,508 @@ +// Copyright (C) 2020-2023 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 +// . + +#include "rust-mangle.h" +#include "optional.h" +#include "rust-base62.h" +#include "rust-diagnostics.h" +#include "rust-system.h" +#include "rust-tyty.h" +#include "rust-unicode.h" +#include "rust-punycode.h" +#include "rust-compile-type.h" +#include + +namespace Rust { +namespace Compile { + +struct V0Path +{ + std::string prefix = ""; + // Used for "N" + std::string ns = ""; + std::string path = ""; + // Used for "N" and "C" + std::string ident = ""; + std::string disambiguator = ""; + // Used for "M" and "X" + std::string impl_path = ""; + std::string impl_type = ""; + std::string trait_type = ""; + // Used for generic types + std::string generic_postfix = ""; + std::string generic_prefix = ""; + + std::string as_string () const + { + if (prefix == "N") + return generic_prefix + prefix + ns + path + disambiguator + ident + + generic_postfix; + else if (prefix == "M") + return prefix + impl_path + impl_type; + else if (prefix == "X") + return prefix + impl_type + trait_type; + else if (prefix == "C") + return prefix + disambiguator + ident; + else + rust_unreachable (); + } +}; + +static std::string +v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, + const Resolver::CanonicalPath &path); + +static std::string +v0_tuple_prefix (const TyTy::BaseType *ty) +{ + if (ty->is_unit ()) + return "u"; + + // FIXME: ARTHUR: Add rest of algorithm + return ""; +} + +static std::string +v0_numeric_prefix (const TyTy::BaseType *ty) +{ + static const std::map num_prefixes = { + {"i8", "a"}, {"u8", "h"}, {"i16", "s"}, {"u16", "t"}, + {"i32", "l"}, {"u32", "m"}, {"i64", "x"}, {"u64", "y"}, + {"isize", "i"}, {"usize", "j"}, {"f32", "f"}, {"f64", "d"}, + }; + + auto ty_kind = ty->get_kind (); + auto ty_str = ty->as_string (); + auto numeric_iter = num_prefixes.end (); + + // Special numeric types + if (ty_kind == TyTy::TypeKind::ISIZE) + return "i"; + else if (ty_kind == TyTy::TypeKind::USIZE) + return "j"; + + numeric_iter = num_prefixes.find (ty_str); + if (numeric_iter != num_prefixes.end ()) + return numeric_iter->second; + + rust_unreachable (); +} + +static std::string +v0_simple_type_prefix (const TyTy::BaseType *ty) +{ + switch (ty->get_kind ()) + { + case TyTy::TypeKind::BOOL: + return "b"; + case TyTy::TypeKind::CHAR: + return "c"; + case TyTy::TypeKind::STR: + return "e"; + case TyTy::TypeKind::NEVER: + return "z"; + + // Placeholder types + case TyTy::TypeKind::ERROR: // Fallthrough + case TyTy::TypeKind::INFER: // Fallthrough + case TyTy::TypeKind::PLACEHOLDER: // Fallthrough + case TyTy::TypeKind::PARAM: + // FIXME: TyTy::TypeKind::BOUND is also a valid variant in rustc + return "p"; + + case TyTy::TypeKind::TUPLE: + return v0_tuple_prefix (ty); + + case TyTy::TypeKind::UINT: // Fallthrough + case TyTy::TypeKind::INT: // Fallthrough + case TyTy::TypeKind::FLOAT: // Fallthrough + case TyTy::TypeKind::ISIZE: // Fallthrough + case TyTy::TypeKind::USIZE: + return v0_numeric_prefix (ty); + + default: + return ""; + } + + rust_unreachable (); +} + +static std::string +v0_complex_type_prefix (Context *ctx, const TyTy::BaseType *ty) +{ + // FIXME: ref, slice, dyn, etc. + // TODO: generics + switch (ty->get_kind ()) + { + case TyTy::TypeKind::ADT: { + const TyTy::ADTType *adt = static_cast (ty); + return v0_path (ctx, ty, adt->get_ident ().path); + } + break; + default: + return ""; + } +} + +// Returns an underscore-terminated base62 integer. +// This corresponds to the `` grammar in the v0 mangling RFC: +// - 0 is encoded as "_" +// - any other value is encoded as itself minus one in base 62, followed by +// "_" +static std::string +v0_integer_62 (uint64_t x) +{ + std::stringstream s; + if (x > 0) + s << base62_integer (x - 1); + + s << "_"; + return s.str (); +} + +// Returns a tag-prefixed base62 integer when the +// integer is greater than 0: +// - 0 is encoded as "" (nothing) +// - any other value is encoded as + v0_integer_62(itself), that is +// + base62(itself - 1) + '_' +static std::string +v0_opt_integer_62 (std::string tag, uint64_t x) +{ + if (x > 0) + { + return tag + v0_integer_62 (x); + } + return ""; +} + +static std::string +v0_disambiguator (uint64_t dis) +{ + return v0_opt_integer_62 ("s", dis); +} + +static std::string +v0_type_prefix (Context *ctx, const TyTy::BaseType *ty) +{ + std::string ty_prefix; + + ty_prefix = v0_simple_type_prefix (ty); + if (!ty_prefix.empty ()) + return ty_prefix; + + ty_prefix = v0_complex_type_prefix (ctx, ty); + if (!ty_prefix.empty ()) + return ty_prefix; + + rust_unreachable (); +} + +static std::string +v0_generic_args (Context *ctx, const TyTy::BaseType *ty) +{ + std::stringstream ss; + const TyTy::FnType *fnty = static_cast (ty); + TyTy::SubstitutionArgumentMappings &subst_ref + = const_cast (fnty)->get_substitution_arguments (); + for (TyTy::SubstitutionArg &map : subst_ref.get_mappings ()) + { + ss << v0_type_prefix (ctx, map.get_tyty ()); + } + return ss.str (); +} + +// Returns an mangled identifier. This corresponds to the +// `` grammar in the v0 mangling RFC. +static std::string +v0_identifier (const std::string &identifier) +{ + std::stringstream mangled; + // The grammar for unicode identifier is contained in + // , right under the one. If the + // identifier contains unicode values, then an extra "u" needs to be added to + // the mangling string and `punycode` must be used to encode the characters. + + if (!is_ascii_only (identifier)) + mangled << "u"; + + tl::optional uident_opt + = Utf8String::make_utf8_string (identifier); + rust_assert (uident_opt.has_value ()); + tl::optional punycode_opt + = encode_punycode (uident_opt.value ()); + rust_assert (punycode_opt.has_value ()); + + std::string punycode = punycode_opt.value (); + + // remove a tailing hyphen + if (punycode.back () == '-') + punycode.pop_back (); + + // replace a hyphen in punycode with a underscore + std::replace (punycode.begin (), punycode.end (), '-', '_'); + + mangled << std::to_string (punycode.size ()); + + // Add extra '_' + if (punycode[0] == '_' || ('0' <= punycode[0] && punycode[0] <= '9')) + mangled << "_"; + + mangled << punycode; + return mangled.str (); +} + +static V0Path +v0_type_path (V0Path path, std::string ident) +{ + V0Path v0path; + v0path.prefix = "N"; + v0path.ns = "t"; + v0path.path = path.as_string (); + v0path.ident = ident; + // TODO: Need ? + return v0path; +} + +static V0Path +v0_function_path (V0Path path, Rust::Compile::Context *ctx, + const TyTy::BaseType *ty, HIR::Function *fn, + std::string ident) +{ + V0Path v0path; + v0path.prefix = "N"; + v0path.ns = "v"; + v0path.path = path.as_string (); + v0path.ident = ident; + if (!fn->get_generic_params ().empty ()) + { + v0path.generic_prefix = "I"; + v0path.generic_postfix = v0_generic_args (ctx, ty) + "E"; + } + return v0path; +} + +static V0Path +v0_scope_path (V0Path path, std::string ident, std::string ns) +{ + V0Path v0path; + v0path.prefix = "N"; + v0path.ns = ns; + v0path.path = path.as_string (); + v0path.ident = ident; + return v0path; +} + +static V0Path +v0_crate_path (CrateNum crate_num, std::string ident) +{ + V0Path v0path; + v0path.prefix = "C"; + v0path.disambiguator = v0_disambiguator (crate_num); + v0path.ident = ident; + return v0path; +} + +static V0Path +v0_inherent_or_trait_impl_path (Rust::Compile::Context *ctx, + HIR::ImplBlock *impl_block) +{ + V0Path v0path; + bool ok; + + // lookup impl type + TyTy::BaseType *impl_ty = nullptr; + ok = ctx->get_tyctx ()->lookup_type ( + impl_block->get_type ()->get_mappings ().get_hirid (), &impl_ty); + rust_assert (ok); + + // FIXME: dummy value for now + v0path.impl_path = "C5crate"; + v0path.impl_type = v0_type_prefix (ctx, impl_ty); + + if (impl_block->has_trait_ref ()) + { + // trait impl: X + v0path.prefix = "X"; + + TyTy::BaseType *trait_ty = nullptr; + ok = ctx->get_tyctx ()->lookup_type ( + impl_block->get_trait_ref ()->get_mappings ().get_hirid (), &trait_ty); + rust_assert (ok); + + v0path.trait_type = v0_type_prefix (ctx, trait_ty); + } + else + // inherent impl: M + v0path.prefix = "M"; + + return v0path; +} + +static V0Path +v0_closure (V0Path path, HirId closure) +{ + V0Path v0path; + v0path.prefix = "N"; + v0path.ns = "C"; + v0path.disambiguator = v0_disambiguator (closure); + v0path.path = path.as_string (); + v0path.ident = "0"; + return v0path; +} + +static std::string +v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, + const Resolver::CanonicalPath &cpath) +{ + auto mappings = Analysis::Mappings::get (); + + V0Path v0path = {}; + + cpath.iterate_segs ([&] (const Resolver::CanonicalPath &seg) { + HirId hir_id; + bool ok = mappings->lookup_node_to_hir (seg.get_node_id (), &hir_id); + if (!ok) + { + // FIXME: generic arg in canonical path? (e.g. in crate::S) + rust_unreachable (); + } + + HirId parent_impl_id = UNKNOWN_HIRID; + HIR::ImplItem *impl_item + = mappings->lookup_hir_implitem (hir_id, &parent_impl_id); + HIR::TraitItem *trait_item = mappings->lookup_hir_trait_item (hir_id); + HIR::Item *item = mappings->lookup_hir_item (hir_id); + HIR::Expr *expr = mappings->lookup_hir_expr (hir_id); + + if (impl_item != nullptr) + { + switch (impl_item->get_impl_item_type ()) + { + case HIR::ImplItem::FUNCTION: { + HIR::Function *fn = static_cast (impl_item); + v0path = v0_function_path (v0path, ctx, ty, fn, + v0_identifier (seg.get ())); + } + break; + case HIR::ImplItem::CONSTANT: + v0path = v0_scope_path (v0path, v0_identifier (seg.get ()), "v"); + break; + default: + rust_internal_error_at (UNDEF_LOCATION, "Attempt to mangle '%s'", + cpath.get ().c_str ()); + break; + } + } + else if (trait_item != nullptr) + { + switch (trait_item->get_item_kind ()) + { + case HIR::TraitItem::FUNC: { + HIR::Function *fn = static_cast (impl_item); + v0path = v0_function_path (v0path, ctx, ty, fn, + v0_identifier (seg.get ())); + } + break; + case HIR::TraitItem::CONST: + v0path = v0_scope_path (v0path, v0_identifier (seg.get ()), "v"); + break; + default: + rust_internal_error_at (UNDEF_LOCATION, "Attempt to mangle '%s'", + cpath.get ().c_str ()); + break; + } + } + else if (item != nullptr) + switch (item->get_item_kind ()) + { + case HIR::Item::ItemKind::Function: { + HIR::Function *fn = static_cast (item); + v0path = v0_function_path (v0path, ctx, ty, fn, + v0_identifier (seg.get ())); + } + break; + case HIR::Item::ItemKind::Module: + v0path = v0_scope_path (v0path, v0_identifier (seg.get ()), "t"); + break; + case HIR::Item::ItemKind::Trait: // FIXME: correct? + case HIR::Item::ItemKind::Static: + case HIR::Item::ItemKind::Constant: + v0path = v0_scope_path (v0path, v0_identifier (seg.get ()), "v"); + break; + case HIR::Item::ItemKind::Struct: + case HIR::Item::ItemKind::Enum: + case HIR::Item::ItemKind::Union: + v0path = v0_type_path (v0path, v0_identifier (seg.get ())); + break; + case HIR::Item::ItemKind::Impl: + // Trait impl or inherent impl. + { + HIR::ImplBlock *impl_block = static_cast (item); + v0path = v0_inherent_or_trait_impl_path (ctx, impl_block); + } + break; + case HIR::Item::ItemKind::ExternBlock: + case HIR::Item::ItemKind::ExternCrate: + case HIR::Item::ItemKind::UseDeclaration: + case HIR::Item::ItemKind::TypeAlias: + case HIR::Item::ItemKind::EnumItem: // FIXME: correct? + rust_internal_error_at (UNDEF_LOCATION, "Attempt to mangle '%s'", + cpath.get ().c_str ()); + break; + } + else if (expr != nullptr) + { + rust_assert (expr->get_expression_type () + == HIR::Expr::ExprType::Closure); + // Use HIR ID as disambiguator. + v0path = v0_closure (v0path, hir_id); + } + else + // Not HIR item, impl item, trait impl item, nor expr. Assume a crate. + v0path + = v0_crate_path (cpath.get_crate_num (), v0_identifier (seg.get ())); + + return true; + }); + + return v0path.as_string (); +} + +std::string +v0_mangle_item (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, + const Resolver::CanonicalPath &path) +{ + rust_debug ("Start mangling: %s", path.get ().c_str ()); + + // TODO: get Instanciating CrateNum + // auto mappings = Analysis::Mappings::get (); + // std::string crate_name; + // bool ok = mappings->get_crate_name (path.get_crate_num (), crate_name); + // rust_assert (ok); + + std::stringstream mangled; + mangled << "_R"; + mangled << v0_path (ctx, ty, path); + + rust_debug ("=> %s", mangled.str ().c_str ()); + + return mangled.str (); +} + +} // namespace Compile +} // namespace Rust diff --git a/gcc/rust/backend/rust-mangle.cc b/gcc/rust/backend/rust-mangle.cc index e1c9e94..53ed6b5 100644 --- a/gcc/rust/backend/rust-mangle.cc +++ b/gcc/rust/backend/rust-mangle.cc @@ -1,640 +1,28 @@ -#include "rust-mangle.h" -#include "fnv-hash.h" -#include "optional.h" -#include "rust-base62.h" -#include "rust-unicode.h" -#include "rust-diagnostics.h" -#include "rust-hir-full-decls.h" -#include "rust-hir-item.h" -#include "rust-hir-type-bounds.h" -#include "rust-system.h" -#include "rust-tyty-subst.h" -#include "rust-tyty.h" -#include "rust-unicode.h" -#include "rust-punycode.h" -#include "rust-hir.h" -#include "rust-compile-type.h" -#include - -// FIXME: Rename those to legacy_* -static const std::string kMangledSymbolPrefix = "_ZN"; -static const std::string kMangledSymbolDelim = "E"; -static const std::string kMangledGenericDelim = "$C$"; -static const std::string kMangledSubstBegin = "$LT$"; -static const std::string kMangledSubstEnd = "$GT$"; -static const std::string kMangledSpace = "$u20$"; -static const std::string kMangledRef = "$RF$"; -static const std::string kMangledPtr = "$BP$"; -static const std::string kMangledLeftSqParen = "$u5b$"; // [ -static const std::string kMangledRightSqParen = "$u5d$"; // ] -static const std::string kMangledLeftBrace = "$u7b$"; // { -static const std::string kMangledRightBrace = "$u7d$"; // } -static const std::string kQualPathBegin = "_" + kMangledSubstBegin; -static const std::string kMangledComma = "$C$"; - -namespace Rust { -namespace Compile { - -Mangler::MangleVersion Mangler::version = MangleVersion::LEGACY; - -struct V0Path -{ - std::string prefix = ""; - // Used for "N" - std::string ns = ""; - std::string path = ""; - // Used for "N" and "C" - std::string ident = ""; - std::string disambiguator = ""; - // Used for "M" and "X" - std::string impl_path = ""; - std::string impl_type = ""; - std::string trait_type = ""; - // Used for generic types - std::string generic_postfix = ""; - std::string generic_prefix = ""; - - std::string as_string () const - { - if (prefix == "N") - return generic_prefix + prefix + ns + path + disambiguator + ident - + generic_postfix; - else if (prefix == "M") - return prefix + impl_path + impl_type; - else if (prefix == "X") - return prefix + impl_type + trait_type; - else if (prefix == "C") - return prefix + disambiguator + ident; - else - rust_unreachable (); - } -}; - -static std::string -v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, - const Resolver::CanonicalPath &path); - -static std::string -legacy_mangle_name (const std::string &name) -{ - // example - // <&T as core::fmt::Debug>::fmt: - // _ZN42_$LT$$RF$T$u20$as$u20$core..fmt..Debug$GT$3fmt17h6dac924c0051eef7E - // replace all white space with $ and & with RF - // - // ::fooA: - // _ZN43_$LT$example..Bar$u20$as$u20$example..A$GT$4fooA17hfc615fa76c7db7a0E: - // - // core::ptr::const_ptr::::cast: - // _ZN4core3ptr9const_ptr33_$LT$impl$u20$$BP$const$u20$T$GT$4cast17hb79f4617226f1d55E: - // - // core::ptr::const_ptr::::as_ptr: - // _ZN4core3ptr9const_ptr43_$LT$impl$u20$$BP$const$u20$$u5b$T$u5d$$GT$6as_ptr17he16e0dcd9473b04fE: - // - // example::Foo::new: - // _ZN7example12Foo$LT$T$GT$3new17h9a2aacb7fd783515E: - // - // >::call - // _ZN74_$LT$example..Identity$u20$as$u20$example..FnLike$LT$$RF$T$C$$RF$T$GT$$GT$4call17ha9ee58935895acb3E - - tl::optional utf8_name = Utf8String::make_utf8_string (name); - rust_assert (utf8_name.has_value ()); - std::vector chars = utf8_name.value ().get_chars (); - std::string buffer; - for (size_t i = 0; i < chars.size (); i++) - { - std::string m; - Codepoint c = chars.at (i); - - if (c == ' ') - m = kMangledSpace; - else if (c == '&') - m = kMangledRef; - else if (i == 0 && c == '<') - m = kQualPathBegin; - else if (c == '<') - m = kMangledSubstBegin; - else if (c == '>') - m = kMangledSubstEnd; - else if (c == '*') - m = kMangledPtr; - else if (c == '[') - m = kMangledLeftSqParen; - else if (c == ']') - m = kMangledRightSqParen; - else if (c == '{') - m = kMangledLeftBrace; - else if (c == '}') - m = kMangledRightBrace; - else if (c == ',') - m = kMangledComma; - else if (c == ':') - { - rust_assert (i + 1 < chars.size ()); - rust_assert (chars.at (i + 1) == ':'); - i++; - m = ".."; - } - else if (c.is_ascii ()) - // ASCII - m.push_back (c.value); - else - { - // Non-ASCII - std::stringstream escaped; - escaped << std::hex << "$u" << c.value << "$"; - m += escaped.str (); - } - buffer += m; - } - - return std::to_string (buffer.size ()) + buffer; -} - -static std::string -legacy_mangle_canonical_path (const Resolver::CanonicalPath &path) -{ - std::string buffer; - for (size_t i = 0; i < path.size (); i++) - { - auto &seg = path.get_seg_at (i); - buffer += legacy_mangle_name (seg.second); - } - return buffer; -} - -// rustc uses a sip128 hash for legacy mangling, but an fnv 128 was quicker to -// implement for now -static std::string -legacy_hash (const std::string &fingerprint) -{ - Hash::FNV128 hasher; - hasher.write ((const unsigned char *) fingerprint.c_str (), - fingerprint.size ()); - - uint64_t hi, lo; - hasher.sum (&hi, &lo); - - char hex[16 + 1]; - memset (hex, 0, sizeof hex); - snprintf (hex, sizeof hex, "%08" PRIx64 "%08" PRIx64, lo, hi); - - return "h" + std::string (hex, sizeof (hex) - 1); -} - -static std::string -v0_tuple_prefix (const TyTy::BaseType *ty) -{ - if (ty->is_unit ()) - return "u"; - - // FIXME: ARTHUR: Add rest of algorithm - return ""; -} - -static std::string -v0_numeric_prefix (const TyTy::BaseType *ty) -{ - static const std::map num_prefixes = { - {"i8", "a"}, {"u8", "h"}, {"i16", "s"}, {"u16", "t"}, - {"i32", "l"}, {"u32", "m"}, {"i64", "x"}, {"u64", "y"}, - {"isize", "i"}, {"usize", "j"}, {"f32", "f"}, {"f64", "d"}, - }; - - auto ty_kind = ty->get_kind (); - auto ty_str = ty->as_string (); - auto numeric_iter = num_prefixes.end (); - - // Special numeric types - if (ty_kind == TyTy::TypeKind::ISIZE) - return "i"; - else if (ty_kind == TyTy::TypeKind::USIZE) - return "j"; - - numeric_iter = num_prefixes.find (ty_str); - if (numeric_iter != num_prefixes.end ()) - return numeric_iter->second; - - rust_unreachable (); -} - -static std::string -v0_simple_type_prefix (const TyTy::BaseType *ty) -{ - switch (ty->get_kind ()) - { - case TyTy::TypeKind::BOOL: - return "b"; - case TyTy::TypeKind::CHAR: - return "c"; - case TyTy::TypeKind::STR: - return "e"; - case TyTy::TypeKind::NEVER: - return "z"; - - // Placeholder types - case TyTy::TypeKind::ERROR: // Fallthrough - case TyTy::TypeKind::INFER: // Fallthrough - case TyTy::TypeKind::PLACEHOLDER: // Fallthrough - case TyTy::TypeKind::PARAM: - // FIXME: TyTy::TypeKind::BOUND is also a valid variant in rustc - return "p"; - - case TyTy::TypeKind::TUPLE: - return v0_tuple_prefix (ty); - - case TyTy::TypeKind::UINT: // Fallthrough - case TyTy::TypeKind::INT: // Fallthrough - case TyTy::TypeKind::FLOAT: // Fallthrough - case TyTy::TypeKind::ISIZE: // Fallthrough - case TyTy::TypeKind::USIZE: // Fallthrough - return v0_numeric_prefix (ty); - - default: - return ""; - } - - rust_unreachable (); -} - -static std::string -v0_complex_type_prefix (Context *ctx, const TyTy::BaseType *ty) -{ - // FIXME: ref, slice, dyn, etc. - // TODO: generics - switch (ty->get_kind ()) - { - case TyTy::TypeKind::ADT: { - const TyTy::ADTType *adt = static_cast (ty); - return v0_path (ctx, ty, adt->get_ident ().path); - } - break; - default: - return ""; - } -} - -// Returns an underscore-terminated base62 integer. -// This corresponds to the `` grammar in the v0 mangling RFC: -// - 0 is encoded as "_" -// - any other value is encoded as itself minus one in base 62, followed by -// "_" -static std::string -v0_integer_62 (uint64_t x) -{ - std::stringstream s; - if (x > 0) - s << base62_integer (x - 1); - - s << "_"; - return s.str (); -} - -// Returns a tag-prefixed base62 integer when the -// integer is greater than 0: -// - 0 is encoded as "" (nothing) -// - any other value is encoded as + v0_integer_62(itself), that is -// + base62(itself - 1) + '_' -static std::string -v0_opt_integer_62 (std::string tag, uint64_t x) -{ - if (x > 0) - { - return tag + v0_integer_62 (x); - } - return ""; -} - -static std::string -v0_disambiguator (uint64_t dis) -{ - return v0_opt_integer_62 ("s", dis); -} - -static std::string -v0_type_prefix (Context *ctx, const TyTy::BaseType *ty) -{ - std::string ty_prefix; - - ty_prefix = v0_simple_type_prefix (ty); - if (!ty_prefix.empty ()) - return ty_prefix; - - ty_prefix = v0_complex_type_prefix (ctx, ty); - if (!ty_prefix.empty ()) - return ty_prefix; - - rust_unreachable (); -} - -static std::string -v0_generic_args (Context *ctx, const TyTy::BaseType *ty) -{ - std::stringstream ss; - const TyTy::FnType *fnty = static_cast (ty); - TyTy::SubstitutionArgumentMappings &subst_ref - = const_cast (fnty)->get_substitution_arguments (); - for (TyTy::SubstitutionArg &map : subst_ref.get_mappings ()) - { - ss << v0_type_prefix (ctx, map.get_tyty ()); - } - return ss.str (); -} - -// Returns an mangled identifier. This corresponds to the -// `` grammar in the v0 mangling RFC. -static std::string -v0_identifier (const std::string &identifier) -{ - std::stringstream mangled; - // The grammar for unicode identifier is contained in - // , right under the one. If the - // identifier contains unicode values, then an extra "u" needs to be added to - // the mangling string and `punycode` must be used to encode the characters. - - if (!is_ascii_only (identifier)) - mangled << "u"; - - tl::optional uident_opt - = Utf8String::make_utf8_string (identifier); - rust_assert (uident_opt.has_value ()); - tl::optional punycode_opt - = encode_punycode (uident_opt.value ()); - rust_assert (punycode_opt.has_value ()); - - std::string punycode = punycode_opt.value (); - - // remove a tailing hyphen - if (punycode.back () == '-') - punycode.pop_back (); +// Copyright (C) 2020-2023 Free Software Foundation, Inc. - // replace a hyphen in punycode with a underscore - std::replace (punycode.begin (), punycode.end (), '-', '_'); +// This file is part of GCC. - mangled << std::to_string (punycode.size ()); +// 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. - // Add extra '_' - if (punycode[0] == '_' || ('0' <= punycode[0] && punycode[0] <= '9')) - mangled << "_"; - - mangled << punycode; - return mangled.str (); -} - -static V0Path -v0_type_path (V0Path path, std::string ident) -{ - V0Path v0path; - v0path.prefix = "N"; - v0path.ns = "t"; - v0path.path = path.as_string (); - v0path.ident = ident; - // TODO: Need ? - return v0path; -} - -static V0Path -v0_function_path (V0Path path, Rust::Compile::Context *ctx, - const TyTy::BaseType *ty, HIR::Function *fn, - std::string ident) -{ - V0Path v0path; - v0path.prefix = "N"; - v0path.ns = "v"; - v0path.path = path.as_string (); - v0path.ident = ident; - if (!fn->get_generic_params ().empty ()) - { - v0path.generic_prefix = "I"; - v0path.generic_postfix = v0_generic_args (ctx, ty) + "E"; - } - return v0path; -} - -static V0Path -v0_scope_path (V0Path path, std::string ident, std::string ns) -{ - V0Path v0path; - v0path.prefix = "N"; - v0path.ns = ns; - v0path.path = path.as_string (); - v0path.ident = ident; - return v0path; -} - -static V0Path -v0_crate_path (CrateNum crate_num, std::string ident) -{ - V0Path v0path; - v0path.prefix = "C"; - v0path.disambiguator = v0_disambiguator (crate_num); - v0path.ident = ident; - return v0path; -} - -static V0Path -v0_inherent_or_trait_impl_path (Rust::Compile::Context *ctx, - HIR::ImplBlock *impl_block) -{ - V0Path v0path; - bool ok; +// 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. - // lookup impl type - TyTy::BaseType *impl_ty = nullptr; - ok = ctx->get_tyctx ()->lookup_type ( - impl_block->get_type ()->get_mappings ().get_hirid (), &impl_ty); - rust_assert (ok); +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . - // FIXME: dummy value for now - v0path.impl_path = "C5crate"; - v0path.impl_type = v0_type_prefix (ctx, impl_ty); - - if (impl_block->has_trait_ref ()) - { - // trait impl: X - v0path.prefix = "X"; - - TyTy::BaseType *trait_ty = nullptr; - ok = ctx->get_tyctx ()->lookup_type ( - impl_block->get_trait_ref ()->get_mappings ().get_hirid (), &trait_ty); - rust_assert (ok); - - v0path.trait_type = v0_type_prefix (ctx, trait_ty); - } - else - // inherent impl: M - v0path.prefix = "M"; - - return v0path; -} - -static V0Path -v0_closure (V0Path path, HirId closure) -{ - V0Path v0path; - v0path.prefix = "N"; - v0path.ns = "C"; - v0path.disambiguator = v0_disambiguator (closure); - v0path.path = path.as_string (); - v0path.ident = "0"; - return v0path; -} - -static std::string -v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, - const Resolver::CanonicalPath &cpath) -{ - auto mappings = Analysis::Mappings::get (); - - V0Path v0path = {}; - - cpath.iterate_segs ([&] (const Resolver::CanonicalPath &seg) { - HirId hir_id; - bool ok = mappings->lookup_node_to_hir (seg.get_node_id (), &hir_id); - if (!ok) - { - // FIXME: generic arg in canonical path? (e.g. in crate::S) - rust_unreachable (); - } - - HirId parent_impl_id = UNKNOWN_HIRID; - HIR::ImplItem *impl_item - = mappings->lookup_hir_implitem (hir_id, &parent_impl_id); - HIR::TraitItem *trait_item = mappings->lookup_hir_trait_item (hir_id); - HIR::Item *item = mappings->lookup_hir_item (hir_id); - HIR::Expr *expr = mappings->lookup_hir_expr (hir_id); - - if (impl_item != nullptr) - { - switch (impl_item->get_impl_item_type ()) - { - case HIR::ImplItem::FUNCTION: { - HIR::Function *fn = static_cast (impl_item); - v0path = v0_function_path (v0path, ctx, ty, fn, - v0_identifier (seg.get ())); - } - break; - case HIR::ImplItem::CONSTANT: - v0path = v0_scope_path (v0path, v0_identifier (seg.get ()), "v"); - break; - default: - rust_internal_error_at (UNDEF_LOCATION, "Attempt to mangle '%s'", - cpath.get ().c_str ()); - break; - } - } - else if (trait_item != nullptr) - { - switch (trait_item->get_item_kind ()) - { - case HIR::TraitItem::FUNC: { - HIR::Function *fn = static_cast (impl_item); - v0path = v0_function_path (v0path, ctx, ty, fn, - v0_identifier (seg.get ())); - } - break; - case HIR::TraitItem::CONST: - v0path = v0_scope_path (v0path, v0_identifier (seg.get ()), "v"); - break; - default: - rust_internal_error_at (UNDEF_LOCATION, "Attempt to mangle '%s'", - cpath.get ().c_str ()); - break; - } - } - else if (item != nullptr) - switch (item->get_item_kind ()) - { - case HIR::Item::ItemKind::Function: { - HIR::Function *fn = static_cast (item); - v0path = v0_function_path (v0path, ctx, ty, fn, - v0_identifier (seg.get ())); - } - break; - case HIR::Item::ItemKind::Module: - v0path = v0_scope_path (v0path, v0_identifier (seg.get ()), "t"); - break; - case HIR::Item::ItemKind::Trait: // FIXME: correct? - case HIR::Item::ItemKind::Static: - case HIR::Item::ItemKind::Constant: - v0path = v0_scope_path (v0path, v0_identifier (seg.get ()), "v"); - break; - case HIR::Item::ItemKind::Struct: - case HIR::Item::ItemKind::Enum: - case HIR::Item::ItemKind::Union: - v0path = v0_type_path (v0path, v0_identifier (seg.get ())); - break; - case HIR::Item::ItemKind::Impl: - // Trait impl or inherent impl. - { - HIR::ImplBlock *impl_block = static_cast (item); - v0path = v0_inherent_or_trait_impl_path (ctx, impl_block); - } - break; - case HIR::Item::ItemKind::ExternBlock: - case HIR::Item::ItemKind::ExternCrate: - case HIR::Item::ItemKind::UseDeclaration: - case HIR::Item::ItemKind::TypeAlias: - case HIR::Item::ItemKind::EnumItem: // FIXME: correct? - rust_internal_error_at (UNDEF_LOCATION, "Attempt to mangle '%s'", - cpath.get ().c_str ()); - break; - } - else if (expr != nullptr) - { - rust_assert (expr->get_expression_type () - == HIR::Expr::ExprType::Closure); - // Use HIR ID as disambiguator. - v0path = v0_closure (v0path, hir_id); - } - else - { - // Not HIR item, impl item, trait impl item, nor expr. Assume a crate. - - // std::string crate_name; - // bool ok = mappings->get_crate_name (path.get_crate_num (), - // crate_name); rust_assert (ok); rust_assert (crate_name == seg.get()); - - v0path - = v0_crate_path (cpath.get_crate_num (), v0_identifier (seg.get ())); - } - - return true; - }); - - return v0path.as_string (); -} - -static std::string -legacy_mangle_item (const TyTy::BaseType *ty, - const Resolver::CanonicalPath &path) -{ - const std::string hash = legacy_hash (ty->mangle_string ()); - const std::string hash_sig = legacy_mangle_name (hash); - - return kMangledSymbolPrefix + legacy_mangle_canonical_path (path) + hash_sig - + kMangledSymbolDelim; -} - -static std::string -v0_mangle_item (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, - const Resolver::CanonicalPath &path) -{ - rust_debug ("Start mangling: %s", path.get ().c_str ()); - - // auto mappings = Analysis::Mappings::get (); - // std::string crate_name; - // bool ok = mappings->get_crate_name (path.get_crate_num (), crate_name); - // rust_assert (ok); - - std::stringstream mangled; - mangled << "_R"; - mangled << v0_path (ctx, ty, path); +#include "rust-mangle.h" +#include "rust-system.h" - rust_debug ("=> %s", mangled.str ().c_str ()); +namespace Rust { +namespace Compile { - return mangled.str (); -} +Mangler::MangleVersion Mangler::version = MangleVersion::LEGACY; std::string Mangler::mangle_item (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, diff --git a/gcc/rust/backend/rust-mangle.h b/gcc/rust/backend/rust-mangle.h index 09329bb..2a84b6b 100644 --- a/gcc/rust/backend/rust-mangle.h +++ b/gcc/rust/backend/rust-mangle.h @@ -49,6 +49,14 @@ private: static enum MangleVersion version; }; +std::string +legacy_mangle_item (const TyTy::BaseType *ty, + const Resolver::CanonicalPath &path); + +std::string +v0_mangle_item (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, + const Resolver::CanonicalPath &path); + } // namespace Compile } // namespace Rust #endif // RUST_MANGLE_H -- cgit v1.1 From bffceda8b9a80f4a4cea28b4e42e13ffb07264c7 Mon Sep 17 00:00:00 2001 From: Kushal Pal Date: Sat, 16 Dec 2023 00:41:09 +0530 Subject: gccrs: Handle `async` qualifier inside trait Fixes #2778 gcc/rust/ChangeLog: * parse/rust-parse-impl.h (Parser::parse_trait_impl_item): Handled `async` items Signed-off-by: Kushal Pal --- gcc/rust/parse/rust-parse-impl.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 52766af..378b9ad 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -5784,6 +5784,8 @@ Parser::parse_trait_impl_item () // function or method return parse_trait_impl_function_or_method (visibility, std::move (outer_attrs)); + case ASYNC: + return parse_async_item (visibility, std::move (outer_attrs)); case CONST: // lookahead to resolve production - could be function/method or const // item -- cgit v1.1 From 81fcf1087ccaa83088aaed8b8be9777e66d2465d Mon Sep 17 00:00:00 2001 From: Kushal Pal Date: Sat, 16 Dec 2023 20:07:23 +0530 Subject: gccrs: Generate error for `async` trait fucntions Fixes #2767 gcc/rust/ChangeLog: * checks/errors/rust-ast-validation.cc (ASTValidation::visit): Added check for `async` function inside trait. gcc/testsuite/ChangeLog: * rust/compile/issue-2767.rs: New test. Signed-off-by: Kushal Pal --- gcc/rust/checks/errors/rust-ast-validation.cc | 5 +++++ gcc/testsuite/rust/compile/issue-2767.rs | 13 +++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 gcc/testsuite/rust/compile/issue-2767.rs diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc index cd197fc..b50e9cd 100644 --- a/gcc/rust/checks/errors/rust-ast-validation.cc +++ b/gcc/rust/checks/errors/rust-ast-validation.cc @@ -107,6 +107,11 @@ ASTValidation::visit (AST::Function &function) rust_error_at (function.get_locus (), ErrorCode::E0379, "functions in traits cannot be declared const"); + // may change soon + if (qualifiers.is_async () && context.back () == Context::TRAIT_IMPL) + rust_error_at (function.get_locus (), ErrorCode::E0706, + "functions in traits cannot be declared %"); + if (valid_context.find (context.back ()) == valid_context.end () && function.has_self_param ()) rust_error_at ( diff --git a/gcc/testsuite/rust/compile/issue-2767.rs b/gcc/testsuite/rust/compile/issue-2767.rs new file mode 100644 index 0000000..9e7e0f9 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-2767.rs @@ -0,0 +1,13 @@ +// { dg-additional-options "-frust-edition=2018" } +trait Foo { + fn f() -> u32; +} + +impl Foo for u32 { + async fn f() -> u32 { + // { dg-error "functions in traits cannot be declared .async." "" { target *-*-* } .-1 } + 22 + } +} + +fn main() {} -- cgit v1.1 From c936a63cb7540d0248df645c56d6237553b06991 Mon Sep 17 00:00:00 2001 From: Jakub Dupak Date: Sun, 3 Dec 2023 12:23:17 +0100 Subject: gccrs: ast: Fix lifetime type parsing There was a mismatch whether lifetime 'static is parsed as "static" or "'static". gcc/rust/ChangeLog: * parse/rust-parse-impl.h (Parser::lifetime_from_token): Fix matched pattern. Signed-off-by: Jakub Dupak --- gcc/rust/parse/rust-parse-impl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 378b9ad..90bc2e2 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -4158,11 +4158,11 @@ Parser::lifetime_from_token (const_TokenPtr tok) location_t locus = tok->get_locus (); std::string lifetime_ident = tok->get_str (); - if (lifetime_ident == "'static") + if (lifetime_ident == "static") { return AST::Lifetime (AST::Lifetime::STATIC, "", locus); } - else if (lifetime_ident == "'_") + else if (lifetime_ident == "_") { return AST::Lifetime (AST::Lifetime::WILDCARD, "", locus); } -- cgit v1.1 From 50f305926810ca9ac9efacd6daeebad01f0cd68b Mon Sep 17 00:00:00 2001 From: Jakub Dupak Date: Sun, 3 Dec 2023 12:25:23 +0100 Subject: gccrs: ast: Unify explicitly and implicitly elided lifettimes gcc/rust/ChangeLog: * ast/rust-ast.h: Elided lifetime static constructor * ast/rust-type.h: Default lifetime to elided. * parse/rust-parse-impl.h (Parser::parse_lifetime_param): Use elided lifetime. (Parser::parse_lifetime): Use elided lifetime/ (Parser::lifetime_from_token): Use elided lifetime. (Parser::parse_self_param): Use elided lifetime. (Parser::parse_reference_type_inner): Use elided lifetime. Signed-off-by: Jakub Dupak --- gcc/rust/ast/rust-ast.h | 2 ++ gcc/rust/ast/rust-type.h | 2 +- gcc/rust/parse/rust-parse-impl.h | 10 ++++------ 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index b193c67..a450854 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -1512,6 +1512,8 @@ public: // Creates an "error" lifetime. static Lifetime error () { return Lifetime (NAMED, ""); } + static Lifetime elided () { return Lifetime (WILDCARD, ""); } + // Returns true if the lifetime is in an error state. bool is_error () const { diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h index 1637367..91a9d2f 100644 --- a/gcc/rust/ast/rust-type.h +++ b/gcc/rust/ast/rust-type.h @@ -547,7 +547,7 @@ public: // Constructor ReferenceType (bool is_mut, std::unique_ptr type_no_bounds, - location_t locus, Lifetime lifetime = Lifetime::error ()) + location_t locus, Lifetime lifetime = Lifetime::elided ()) : lifetime (std::move (lifetime)), has_mut (is_mut), type (std::move (type_no_bounds)), locus (locus) {} diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 90bc2e2..0e2cfce 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -3470,8 +3470,6 @@ Parser::parse_lifetime_param () return AST::LifetimeParam::create_error (); } lexer.skip_token (); - /* TODO: does this always create a named lifetime? or can a different type - * be made? */ AST::Lifetime lifetime (AST::Lifetime::NAMED, lifetime_tok->get_str (), lifetime_tok->get_locus ()); @@ -4141,10 +4139,9 @@ AST::Lifetime Parser::parse_lifetime () { const_TokenPtr lifetime_tok = lexer.peek_token (); - // create error lifetime if doesn't exist if (lifetime_tok->get_id () != LIFETIME) { - return AST::Lifetime::error (); + return AST::Lifetime::elided (); } lexer.skip_token (); @@ -4164,6 +4161,7 @@ Parser::lifetime_from_token (const_TokenPtr tok) } else if (lifetime_ident == "_") { + // Explicitly and implicitly elided lifetimes follow the same rules. return AST::Lifetime (AST::Lifetime::WILDCARD, "", locus); } else @@ -7177,7 +7175,7 @@ tl::expected, ParseSelfError> Parser::parse_self_param () { bool has_reference = false; - AST::Lifetime lifetime = AST::Lifetime::error (); + AST::Lifetime lifetime = AST::Lifetime::elided (); location_t locus = lexer.peek_token ()->get_locus (); @@ -9837,7 +9835,7 @@ std::unique_ptr Parser::parse_reference_type_inner (location_t locus) { // parse optional lifetime - AST::Lifetime lifetime = AST::Lifetime::error (); + AST::Lifetime lifetime = AST::Lifetime::elided (); if (lexer.peek_token ()->get_id () == LIFETIME) { lifetime = parse_lifetime (); -- cgit v1.1 From 6def638e66df549ad3885c2888a7fce9b0552670 Mon Sep 17 00:00:00 2001 From: Jakub Dupak Date: Sun, 3 Dec 2023 12:28:07 +0100 Subject: gccrs: ast: Full lifetime elision handling gcc/rust/ChangeLog: * parse/rust-parse-impl.h (Parser::parse_generic_param): Lifetime elision control. (Parser::parse_lifetime_where_clause_item): Lifetime elision control. (Parser::parse_type_param_bound): Lifetime elision control. (Parser::parse_lifetime_bounds): Lifetime elision control. (Parser::parse_lifetime): Lifetime elision control. (Parser::parse_path_generic_args): Lifetime elision control. (Parser::parse_self_param): Lifetime elision control. (Parser::parse_break_expr): Lifetime elision control. (Parser::parse_continue_expr): Lifetime elision control. (Parser::parse_reference_type_inner): Lifetime elision control. * parse/rust-parse.h: Lifetime elision control. Signed-off-by: Jakub Dupak --- gcc/rust/parse/rust-parse-impl.h | 25 +++++++++++++------------ gcc/rust/parse/rust-parse.h | 2 +- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 0e2cfce..dfa2762 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -3099,7 +3099,7 @@ Parser::parse_generic_param (EndTokenPred is_end_token) switch (token->get_id ()) { case LIFETIME: { - auto lifetime = parse_lifetime (); + auto lifetime = parse_lifetime (false); if (lifetime.is_error ()) { rust_error_at ( @@ -3808,7 +3808,7 @@ template std::unique_ptr Parser::parse_lifetime_where_clause_item () { - AST::Lifetime lifetime = parse_lifetime (); + AST::Lifetime lifetime = parse_lifetime (false); if (lifetime.is_error ()) { // TODO: error here? @@ -4001,7 +4001,7 @@ Parser::parse_type_param_bound () { case LIFETIME: return std::unique_ptr ( - new AST::Lifetime (parse_lifetime ())); + new AST::Lifetime (parse_lifetime (false))); case LEFT_PAREN: case QUESTION_MARK: case FOR: @@ -4075,7 +4075,7 @@ Parser::parse_lifetime_bounds () while (true) { - AST::Lifetime lifetime = parse_lifetime (); + AST::Lifetime lifetime = parse_lifetime (false); // quick exit for parsing failure if (lifetime.is_error ()) @@ -4105,7 +4105,7 @@ Parser::parse_lifetime_bounds (EndTokenPred is_end_token) while (!is_end_token (lexer.peek_token ()->get_id ())) { - AST::Lifetime lifetime = parse_lifetime (); + AST::Lifetime lifetime = parse_lifetime (false); if (lifetime.is_error ()) { @@ -4136,12 +4136,13 @@ Parser::parse_lifetime_bounds (EndTokenPred is_end_token) * existing. */ template AST::Lifetime -Parser::parse_lifetime () +Parser::parse_lifetime (bool allow_elided) { const_TokenPtr lifetime_tok = lexer.peek_token (); if (lifetime_tok->get_id () != LIFETIME) { - return AST::Lifetime::elided (); + return (allow_elided) ? AST::Lifetime::elided () + : AST::Lifetime::error (); } lexer.skip_token (); @@ -6606,7 +6607,7 @@ Parser::parse_path_generic_args () location_t locus = t->get_locus (); while (!is_right_angle_tok (t->get_id ())) { - AST::Lifetime lifetime = parse_lifetime (); + AST::Lifetime lifetime = parse_lifetime (false); if (lifetime.is_error ()) { // not necessarily an error @@ -7227,7 +7228,7 @@ Parser::parse_self_param () // now test whether it has a lifetime if (lexer.peek_token ()->get_id () == LIFETIME) { - lifetime = parse_lifetime (); + lifetime = parse_lifetime (true); // something went wrong somehow if (lifetime.is_error ()) @@ -7763,7 +7764,7 @@ Parser::parse_break_expr (AST::AttrVec outer_attrs, AST::Lifetime label = AST::Lifetime::error (); if (lexer.peek_token ()->get_id () == LIFETIME) { - label = parse_lifetime (); + label = parse_lifetime (false); } // parse break return expression if it exists @@ -7794,7 +7795,7 @@ Parser::parse_continue_expr (AST::AttrVec outer_attrs, AST::Lifetime label = AST::Lifetime::error (); if (lexer.peek_token ()->get_id () == LIFETIME) { - label = parse_lifetime (); + label = parse_lifetime (false); } return std::unique_ptr ( @@ -9838,7 +9839,7 @@ Parser::parse_reference_type_inner (location_t locus) AST::Lifetime lifetime = AST::Lifetime::elided (); if (lexer.peek_token ()->get_id () == LIFETIME) { - lifetime = parse_lifetime (); + lifetime = parse_lifetime (true); if (lifetime.is_error ()) { Error error (lexer.peek_token ()->get_locus (), diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 4291e41..3fc8620 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -303,7 +303,7 @@ private: std::vector parse_lifetime_bounds (); template std::vector parse_lifetime_bounds (EndTokenPred is_end_token); - AST::Lifetime parse_lifetime (); + AST::Lifetime parse_lifetime (bool allow_elided); AST::Lifetime lifetime_from_token (const_TokenPtr tok); std::unique_ptr parse_external_type_item (AST::Visibility vis, AST::AttrVec outer_attrs); -- cgit v1.1 From bc1a47f72de0b40a7f26372f8407c0492e10403e Mon Sep 17 00:00:00 2001 From: Jakub Dupak Date: Sun, 3 Dec 2023 12:30:08 +0100 Subject: gccrs: ast: Infer static lifetime for const and static items (probably incomplete propagation) gcc/rust/ChangeLog: * hir/rust-ast-lower-base.cc (ASTLoweringBase::lower_lifetime): Propagate static requirement. * hir/rust-ast-lower-base.h: Propagate static requirement. * hir/rust-ast-lower-implitem.h: Propagate static requirement. * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): Propagate static requirement. * hir/rust-ast-lower-type.cc (ASTLoweringType::translate): Propagate static requirement. (ASTLoweringType::visit): Propagate static requirement. * hir/rust-ast-lower-type.h: Propagate static requirement. Signed-off-by: Jakub Dupak --- gcc/rust/hir/rust-ast-lower-base.cc | 14 +++++++++++--- gcc/rust/hir/rust-ast-lower-base.h | 3 ++- gcc/rust/hir/rust-ast-lower-implitem.h | 3 ++- gcc/rust/hir/rust-ast-lower-item.cc | 5 +++-- gcc/rust/hir/rust-ast-lower-type.cc | 28 ++++++++++++++++++---------- gcc/rust/hir/rust-ast-lower-type.h | 12 ++++++++++-- 6 files changed, 46 insertions(+), 19 deletions(-) diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc index f843855..748cec7 100644 --- a/gcc/rust/hir/rust-ast-lower-base.cc +++ b/gcc/rust/hir/rust-ast-lower-base.cc @@ -530,16 +530,24 @@ ASTLoweringBase::visit (AST::SelfParam ¶m) {} HIR::Lifetime -ASTLoweringBase::lower_lifetime (AST::Lifetime &lifetime) +ASTLoweringBase::lower_lifetime (AST::Lifetime &lifetime, + bool default_to_static_lifetime) { + auto lifetime_type = lifetime.get_lifetime_type (); + if (lifetime_type == AST::Lifetime::WILDCARD && default_to_static_lifetime) + { + // If compiling in a static context. + lifetime_type = AST::Lifetime::STATIC; + } + auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, lifetime.get_node_id (), mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); mappings->insert_node_to_hir (mapping.get_nodeid (), mapping.get_hirid ()); - return HIR::Lifetime (mapping, lifetime.get_lifetime_type (), - lifetime.get_lifetime_name (), lifetime.get_locus ()); + return HIR::Lifetime (mapping, lifetime_type, lifetime.get_lifetime_name (), + lifetime.get_locus ()); } HIR::LoopLabel diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h index d52afd3..8da1175 100644 --- a/gcc/rust/hir/rust-ast-lower-base.h +++ b/gcc/rust/hir/rust-ast-lower-base.h @@ -264,7 +264,8 @@ protected: Analysis::Mappings *mappings; Analysis::BuiltinAttributeMappings *attr_mappings; - HIR::Lifetime lower_lifetime (AST::Lifetime &lifetime); + HIR::Lifetime lower_lifetime (AST::Lifetime &lifetime, + bool default_to_static_lifetime = false); HIR::LoopLabel lower_loop_label (AST::LoopLabel &loop_label); diff --git a/gcc/rust/hir/rust-ast-lower-implitem.h b/gcc/rust/hir/rust-ast-lower-implitem.h index 6f904dd..81dae14 100644 --- a/gcc/rust/hir/rust-ast-lower-implitem.h +++ b/gcc/rust/hir/rust-ast-lower-implitem.h @@ -88,7 +88,8 @@ public: { HIR::Visibility vis = translate_visibility (constant.get_visibility ()); - HIR::Type *type = ASTLoweringType::translate (constant.get_type ().get ()); + HIR::Type *type + = ASTLoweringType::translate (constant.get_type ().get (), true); HIR::Expr *expr = ASTLoweringExpr::translate (constant.get_expr ().get ()); auto crate_num = mappings->get_current_crate (); diff --git a/gcc/rust/hir/rust-ast-lower-item.cc b/gcc/rust/hir/rust-ast-lower-item.cc index 2895872..7ef556f 100644 --- a/gcc/rust/hir/rust-ast-lower-item.cc +++ b/gcc/rust/hir/rust-ast-lower-item.cc @@ -351,7 +351,7 @@ ASTLoweringItem::visit (AST::StaticItem &var) { HIR::Visibility vis = translate_visibility (var.get_visibility ()); - HIR::Type *type = ASTLoweringType::translate (var.get_type ().get ()); + HIR::Type *type = ASTLoweringType::translate (var.get_type ().get (), true); HIR::Expr *expr = ASTLoweringExpr::translate (var.get_expr ().get ()); auto crate_num = mappings->get_current_crate (); @@ -372,7 +372,8 @@ ASTLoweringItem::visit (AST::ConstantItem &constant) { HIR::Visibility vis = translate_visibility (constant.get_visibility ()); - HIR::Type *type = ASTLoweringType::translate (constant.get_type ().get ()); + HIR::Type *type + = ASTLoweringType::translate (constant.get_type ().get (), true); HIR::Expr *expr = ASTLoweringExpr::translate (constant.get_expr ().get ()); auto crate_num = mappings->get_current_crate (); diff --git a/gcc/rust/hir/rust-ast-lower-type.cc b/gcc/rust/hir/rust-ast-lower-type.cc index 5388f21..5cea71f 100644 --- a/gcc/rust/hir/rust-ast-lower-type.cc +++ b/gcc/rust/hir/rust-ast-lower-type.cc @@ -180,9 +180,9 @@ ASTLowerQualifiedPathInType::visit (AST::QualifiedPathInType &path) } HIR::Type * -ASTLoweringType::translate (AST::Type *type) +ASTLoweringType::translate (AST::Type *type, bool default_to_static_lifetime) { - ASTLoweringType resolver; + ASTLoweringType resolver (default_to_static_lifetime); type->accept_vis (resolver); rust_assert (resolver.translated != nullptr); @@ -222,7 +222,8 @@ ASTLoweringType::visit (AST::BareFunctionType &fntype) } HIR::Type *param_type - = ASTLoweringType::translate (param.get_type ().get ()); + = ASTLoweringType::translate (param.get_type ().get (), + default_to_static_lifetime); HIR::MaybeNamedParam p (param.get_name (), kind, std::unique_ptr (param_type), @@ -234,7 +235,8 @@ ASTLoweringType::visit (AST::BareFunctionType &fntype) if (fntype.has_return_type ()) { return_type - = ASTLoweringType::translate (fntype.get_return_type ().get ()); + = ASTLoweringType::translate (fntype.get_return_type ().get (), + default_to_static_lifetime); } auto crate_num = mappings->get_current_crate (); @@ -254,7 +256,8 @@ ASTLoweringType::visit (AST::TupleType &tuple) std::vector> elems; for (auto &e : tuple.get_elems ()) { - HIR::Type *t = ASTLoweringType::translate (e.get ()); + HIR::Type *t + = ASTLoweringType::translate (e.get (), default_to_static_lifetime); elems.push_back (std::unique_ptr (t)); } @@ -283,7 +286,8 @@ void ASTLoweringType::visit (AST::ArrayType &type) { HIR::Type *translated_type - = ASTLoweringType::translate (type.get_elem_type ().get ()); + = ASTLoweringType::translate (type.get_elem_type ().get (), + default_to_static_lifetime); HIR::Expr *array_size = ASTLoweringExpr::translate (type.get_size_expr ().get ()); @@ -301,10 +305,12 @@ ASTLoweringType::visit (AST::ArrayType &type) void ASTLoweringType::visit (AST::ReferenceType &type) { - HIR::Lifetime lifetime = lower_lifetime (type.get_lifetime ()); + HIR::Lifetime lifetime + = lower_lifetime (type.get_lifetime (), default_to_static_lifetime); HIR::Type *base_type - = ASTLoweringType::translate (type.get_base_type ().get ()); + = ASTLoweringType::translate (type.get_base_type ().get (), + default_to_static_lifetime); auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, type.get_node_id (), @@ -322,7 +328,8 @@ void ASTLoweringType::visit (AST::RawPointerType &type) { HIR::Type *base_type - = ASTLoweringType::translate (type.get_type_pointed_to ().get ()); + = ASTLoweringType::translate (type.get_type_pointed_to ().get (), + default_to_static_lifetime); auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, type.get_node_id (), @@ -343,7 +350,8 @@ void ASTLoweringType::visit (AST::SliceType &type) { HIR::Type *base_type - = ASTLoweringType::translate (type.get_elem_type ().get ()); + = ASTLoweringType::translate (type.get_elem_type ().get (), + default_to_static_lifetime); auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, type.get_node_id (), diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h index 8194a9a..ed90c17 100644 --- a/gcc/rust/hir/rust-ast-lower-type.h +++ b/gcc/rust/hir/rust-ast-lower-type.h @@ -63,7 +63,8 @@ class ASTLoweringType : public ASTLoweringBase using Rust::HIR::ASTLoweringBase::visit; public: - static HIR::Type *translate (AST::Type *type); + static HIR::Type *translate (AST::Type *type, + bool default_to_static_lifetime = false); void visit (AST::BareFunctionType &fntype) override; void visit (AST::TupleType &tuple) override; @@ -79,7 +80,14 @@ public: void visit (AST::TraitObjectType &type) override; private: - ASTLoweringType () : ASTLoweringBase (), translated (nullptr) {} + ASTLoweringType (bool default_to_static_lifetime) + : ASTLoweringBase (), + default_to_static_lifetime (default_to_static_lifetime), + translated (nullptr) + {} + + /** Used when compiling const and static items. */ + bool default_to_static_lifetime; HIR::Type *translated; }; -- cgit v1.1 From d8e8ad5493848a3b8f5883817770da2aba5d3edd Mon Sep 17 00:00:00 2001 From: Jakub Dupak Date: Sun, 3 Dec 2023 12:32:55 +0100 Subject: gccrs: ast: Lower 'for' lifetimes gcc/rust/ChangeLog: * hir/rust-ast-lower-type.cc (ASTLoweringType::visit): For lifetimes. Signed-off-by: Jakub Dupak --- gcc/rust/hir/rust-ast-lower-type.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gcc/rust/hir/rust-ast-lower-type.cc b/gcc/rust/hir/rust-ast-lower-type.cc index 5cea71f..a0178eb 100644 --- a/gcc/rust/hir/rust-ast-lower-type.cc +++ b/gcc/rust/hir/rust-ast-lower-type.cc @@ -199,6 +199,13 @@ ASTLoweringType::visit (AST::BareFunctionType &fntype) { bool is_variadic = false; std::vector lifetime_params; + for (auto &lifetime_param : fntype.get_for_lifetimes ()) + { + auto generic_param = ASTLowerGenericParam::translate (&lifetime_param); + lifetime_params.push_back ( + *static_cast (generic_param)); + } + HIR::FunctionQualifiers qualifiers = lower_qualifiers (fntype.get_function_qualifiers ()); -- cgit v1.1 From 14025f735967c1909f2e722210f8c4e694b9ee51 Mon Sep 17 00:00:00 2001 From: Jakub Dupak Date: Thu, 14 Dec 2023 12:54:11 +0100 Subject: gccrs: TyTy: Refactor FnType deprecated API gcc/rust/ChangeLog: * backend/rust-compile-expr.cc (CompileExpr::visit): Use new API. * typecheck/rust-tyty-call.cc (TypeCheckCallExpr::visit): Use new API. * typecheck/rust-tyty-cmp.h: Remove old API. * typecheck/rust-tyty.cc (FnPtr::is_equal): Use new API. * typecheck/rust-tyty.h: Remove old API. * typecheck/rust-unify.cc (UnifyRules::expect_fnptr): Use new API. Signed-off-by: Jakub Dupak --- gcc/rust/backend/rust-compile-expr.cc | 2 +- gcc/rust/typecheck/rust-tyty-call.cc | 2 +- gcc/rust/typecheck/rust-tyty-cmp.h | 6 +++--- gcc/rust/typecheck/rust-tyty.cc | 2 +- gcc/rust/typecheck/rust-tyty.h | 3 --- gcc/rust/typecheck/rust-unify.cc | 6 +++--- 6 files changed, 9 insertions(+), 12 deletions(-) diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index e0917f6..596b848 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -1198,7 +1198,7 @@ CompileExpr::visit (HIR::CallExpr &expr) if (base->get_kind () == TyTy::TypeKind::FNPTR) { const TyTy::FnPtr *fn = static_cast (base); - *result = fn->param_at (index); + *result = fn->get_param_type_at (index); return true; } diff --git a/gcc/rust/typecheck/rust-tyty-call.cc b/gcc/rust/typecheck/rust-tyty-call.cc index 31afe04..a28780b 100644 --- a/gcc/rust/typecheck/rust-tyty-call.cc +++ b/gcc/rust/typecheck/rust-tyty-call.cc @@ -271,7 +271,7 @@ TypeCheckCallExpr::visit (FnPtr &type) for (auto &argument : call.get_arguments ()) { location_t arg_locus = argument->get_locus (); - BaseType *fnparam = type.param_at (i); + BaseType *fnparam = type.get_param_type_at (i); auto argument_expr_tyty = Resolver::TypeCheckExpr::Resolve (argument.get ()); if (argument_expr_tyty->get_kind () == TyTy::TypeKind::ERROR) diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h index 6d4bc16..98ff1dc 100644 --- a/gcc/rust/typecheck/rust-tyty-cmp.h +++ b/gcc/rust/typecheck/rust-tyty-cmp.h @@ -800,8 +800,8 @@ public: for (size_t i = 0; i < base->num_params (); i++) { - auto this_param = base->param_at (i); - auto other_param = type.param_at (i); + auto this_param = base->get_param_type_at (i); + auto other_param = type.get_param_type_at (i); if (!this_param->can_eq (other_param, emit_error_flag)) { BaseCmp::visit (type); @@ -830,7 +830,7 @@ public: for (size_t i = 0; i < base->num_params (); i++) { - auto this_param = base->param_at (i); + auto this_param = base->get_param_type_at (i); auto other_param = type.param_at (i).second; if (!this_param->can_eq (other_param, emit_error_flag)) { diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index e9b42eb..f1789f0 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -2123,7 +2123,7 @@ FnPtr::is_equal (const BaseType &other) const for (size_t i = 0; i < num_params (); i++) { - if (!param_at (i)->is_equal (*other2.param_at (i))) + if (!get_param_type_at (i)->is_equal (*other2.get_param_type_at (i))) return false; } return true; diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 2ed407e..b04048f 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -926,9 +926,6 @@ public: size_t num_params () const { return params.size (); } - // DEPRECATED: Use get_param_type_at - BaseType *param_at (size_t idx) const { return get_param_type_at (idx); } - void accept_vis (TyVisitor &vis) override; void accept_vis (TyConstVisitor &vis) const override; diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc index 3027f09..8b43380 100644 --- a/gcc/rust/typecheck/rust-unify.cc +++ b/gcc/rust/typecheck/rust-unify.cc @@ -1009,8 +1009,8 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) for (size_t i = 0; i < ltype->num_params (); i++) { - auto a = ltype->param_at (i); - auto b = type.param_at (i); + auto a = ltype->get_param_type_at (i); + auto b = type.get_param_type_at (i); auto unified_param = UnifyRules::Resolve (TyTy::TyWithLocation (a), @@ -1058,7 +1058,7 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype) for (size_t i = 0; i < ltype->num_params (); i++) { - auto this_param = ltype->param_at (i); + auto this_param = ltype->get_param_type_at (i); auto other_param = type.param_at (i).second; auto unified_param -- cgit v1.1 From 8b7d6adbbb886039f8c6e14a581dcbc9c63ce380 Mon Sep 17 00:00:00 2001 From: Nirmal Patel Date: Wed, 27 Dec 2023 17:49:58 -0500 Subject: gccrs: Handle newlines during string parsing while lexing If newline strings are encountered while lexing, the lexer now handles newline characters by incrementing current line number. This provides correct line number when displaying errors. If the lexer encounters end of file before string end, then it will use the start of the string as the location to an report error. gcc/rust/ChangeLog: * lex/rust-lex.cc (Lexer::parse_byte_string): Handle newline while parsing byte strings (Lexer::parse_string): Handle newline while parsing strings Signed-off-by: Nirmal Patel --- gcc/rust/lex/rust-lex.cc | 40 +++++++++++++++++------- gcc/testsuite/rust/compile/issue-2187.rs | 11 +++++++ gcc/testsuite/rust/execute/torture/issue-2187.rs | 23 ++++++++++++++ 3 files changed, 63 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/rust/compile/issue-2187.rs create mode 100644 gcc/testsuite/rust/execute/torture/issue-2187.rs diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc index 5bff2d9..6fc336d 100644 --- a/gcc/rust/lex/rust-lex.cc +++ b/gcc/rust/lex/rust-lex.cc @@ -1766,13 +1766,15 @@ Lexer::parse_byte_string (location_t loc) std::string str; str.reserve (16); // some sensible default - int length = 1; current_char = peek_input (); + const location_t string_begin_locus = get_current_location (); + while (current_char != '"' && !current_char.is_eof ()) { if (current_char == '\\') { + int length = 1; auto escape_length_pair = parse_escape ('"'); char output_char = std::get<0> (escape_length_pair); @@ -1784,18 +1786,25 @@ Lexer::parse_byte_string (location_t loc) if (output_char != 0 || !std::get<2> (escape_length_pair)) str += output_char; + current_column += length; + continue; } - length++; + current_column++; + if (current_char.value == '\n') + { + current_line++; + current_column = 1; + // tell line_table that new line starts + start_line (current_line, max_column_hint); + } str += current_char; skip_input (); current_char = peek_input (); } - current_column += length; - if (current_char == '"') { current_column++; @@ -1805,7 +1814,7 @@ Lexer::parse_byte_string (location_t loc) } else if (current_char.is_eof ()) { - rust_error_at (get_current_location (), "unended byte string literal"); + rust_error_at (string_begin_locus, "unended byte string literal"); return Token::make (END_OF_FILE, get_current_location ()); } else @@ -1996,14 +2005,17 @@ Lexer::parse_string (location_t loc) std::string str; str.reserve (16); // some sensible default - int length = 1; current_char = peek_input (); + const location_t string_begin_locus = get_current_location (); + // FIXME: This fails if the input ends. How do we check for EOF? while (current_char.value != '"' && !current_char.is_eof ()) { if (current_char.value == '\\') { + int length = 1; + // parse escape auto utf8_escape_pair = parse_utf8_escape (); current_char = std::get<0> (utf8_escape_pair); @@ -2016,21 +2028,28 @@ Lexer::parse_string (location_t loc) if (current_char != Codepoint (0) || !std::get<2> (utf8_escape_pair)) str += current_char.as_string (); + current_column += length; + // FIXME: should remove this but can't. // `parse_utf8_escape` does not update `current_char` correctly. current_char = peek_input (); continue; } - length++; + current_column++; + if (current_char.value == '\n') + { + current_line++; + current_column = 1; + // tell line_table that new line starts + start_line (current_line, max_column_hint); + } str += current_char; skip_input (); current_char = peek_input (); } - current_column += length; - if (current_char.value == '"') { current_column++; @@ -2040,7 +2059,7 @@ Lexer::parse_string (location_t loc) } else if (current_char.is_eof ()) { - rust_error_at (get_current_location (), "unended string literal"); + rust_error_at (string_begin_locus, "unended string literal"); return Token::make (END_OF_FILE, get_current_location ()); } else @@ -2049,7 +2068,6 @@ Lexer::parse_string (location_t loc) } str.shrink_to_fit (); - loc += length - 1; return Token::make_string (loc, std::move (str)); } diff --git a/gcc/testsuite/rust/compile/issue-2187.rs b/gcc/testsuite/rust/compile/issue-2187.rs new file mode 100644 index 0000000..deef417 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-2187.rs @@ -0,0 +1,11 @@ +const A: &'static u8 = b" +"; +const B: &'static str = b" +"; +const C: &'static u8 = " +"; +const D: &'static str = " +"; +ERROR_TIME +// { dg-error "unrecognised token" "" { target *-*-* } .-1 } +// { dg-error "failed to parse item in crate" "" { target *-*-* } .-2 } diff --git a/gcc/testsuite/rust/execute/torture/issue-2187.rs b/gcc/testsuite/rust/execute/torture/issue-2187.rs new file mode 100644 index 0000000..b531257 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/issue-2187.rs @@ -0,0 +1,23 @@ +/* { dg-output "L1\n\L2\nL3\nL4" } */ +extern "C" { + fn printf(s: *const i8, ...); +} + +fn main() -> i32 { + let A = b"L1 +L2\0"; + let B = "L3 +L4\0"; + + unsafe { + let a = "%s\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c, A); + printf(c, B); + } + + 0 +} + -- cgit v1.1 From f46fdb6399d91d56f095088c8cf0f1fd6d971e25 Mon Sep 17 00:00:00 2001 From: Kushal Pal Date: Wed, 3 Jan 2024 16:02:07 +0530 Subject: gccrs: Handle `async` functions in traits Fixes #2785 gcc/rust/ChangeLog: * checks/errors/rust-ast-validation.cc (ASTValidation::visit): Added check for `async` functions inside trait. * parse/rust-parse-impl.h (Parser::parse_trait_item): Added switch-case for ASYNC token. gcc/testsuite/ChangeLog: * rust/compile/issue-2785.rs: New test. Signed-off-by: Kushal Pal --- gcc/rust/checks/errors/rust-ast-validation.cc | 13 ++++++++++--- gcc/rust/parse/rust-parse-impl.h | 1 + gcc/testsuite/rust/compile/issue-2785.rs | 9 +++++++++ 3 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/rust/compile/issue-2785.rs diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc index b50e9cd..0ed5d06 100644 --- a/gcc/rust/checks/errors/rust-ast-validation.cc +++ b/gcc/rust/checks/errors/rust-ast-validation.cc @@ -141,9 +141,16 @@ ASTValidation::visit (AST::TraitFunctionDecl &decl) { const auto &qualifiers = decl.get_qualifiers (); - if (context.back () == Context::TRAIT && qualifiers.is_const ()) - rust_error_at (decl.get_identifier ().get_locus (), ErrorCode::E0379, - "functions in traits cannot be declared const"); + if (context.back () == Context::TRAIT) + { + // may change soon + if (qualifiers.is_async ()) + rust_error_at (decl.get_identifier ().get_locus (), ErrorCode::E0706, + "functions in traits cannot be declared %"); + if (qualifiers.is_const ()) + rust_error_at (decl.get_identifier ().get_locus (), ErrorCode::E0379, + "functions in traits cannot be declared const"); + } } void diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index dfa2762..3055a39 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -5096,6 +5096,7 @@ Parser::parse_trait_item () // else, fallthrough to function // TODO: find out how to disable gcc "implicit fallthrough" error gcc_fallthrough (); + case ASYNC: case UNSAFE: case EXTERN_KW: case FN_KW: { diff --git a/gcc/testsuite/rust/compile/issue-2785.rs b/gcc/testsuite/rust/compile/issue-2785.rs new file mode 100644 index 0000000..08f6346 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-2785.rs @@ -0,0 +1,9 @@ +// { dg-additional-options "-frust-edition=2018" } +trait Foo { + async fn foo(){} + // { dg-error "functions in traits cannot be declared .async." "" { target *-*-* } .-1 } + async fn bar(); + // { dg-error "functions in traits cannot be declared .async." "" { target *-*-* } .-1 } +} + +fn main() {} -- cgit v1.1 From f7c8a712be233f492b21bb1a4c4a3aa5f07b184b Mon Sep 17 00:00:00 2001 From: Kushal Pal Date: Tue, 16 Jan 2024 19:06:35 +0530 Subject: gccrs: Fix inconsistent formatting gcc/rust/ChangeLog: * checks/errors/rust-ast-validation.cc (ASTValidation::visit): Enclose const in single quotes. gcc/testsuite/ChangeLog: * rust/compile/const_trait_fn.rs: Enclose const in single quotes. Signed-off-by: Kushal Pal --- gcc/rust/checks/errors/rust-ast-validation.cc | 2 +- gcc/testsuite/rust/compile/const_trait_fn.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc index 0ed5d06..ccb071f 100644 --- a/gcc/rust/checks/errors/rust-ast-validation.cc +++ b/gcc/rust/checks/errors/rust-ast-validation.cc @@ -149,7 +149,7 @@ ASTValidation::visit (AST::TraitFunctionDecl &decl) "functions in traits cannot be declared %"); if (qualifiers.is_const ()) rust_error_at (decl.get_identifier ().get_locus (), ErrorCode::E0379, - "functions in traits cannot be declared const"); + "functions in traits cannot be declared %"); } } diff --git a/gcc/testsuite/rust/compile/const_trait_fn.rs b/gcc/testsuite/rust/compile/const_trait_fn.rs index cff2f5f..41bba3b 100644 --- a/gcc/testsuite/rust/compile/const_trait_fn.rs +++ b/gcc/testsuite/rust/compile/const_trait_fn.rs @@ -1,4 +1,4 @@ trait Osterkz { const fn x(); - // { dg-error "functions in traits cannot be declared const .E0379." "" { target *-*-* } .-1 } + // { dg-error "functions in traits cannot be declared .const." "" { target *-*-* } .-1 } } -- cgit v1.1 From 7a0c487d2c54b3cf3a83563add89a87220a109c2 Mon Sep 17 00:00:00 2001 From: Kushal Pal Date: Sat, 6 Jan 2024 11:29:14 +0530 Subject: gccrs: Handle `async` keyword for regular implementations Fixes #2788 gcc/rust/ChangeLog: * parse/rust-parse-impl.h (Parser::parse_inherent_impl_item): Added switch-case for ASYNC token. gcc/testsuite/ChangeLog: * rust/compile/issue-2788.rs: New test. Signed-off-by: Kushal Pal --- gcc/rust/parse/rust-parse-impl.h | 1 + gcc/testsuite/rust/compile/issue-2788.rs | 10 ++++++++++ 2 files changed, 11 insertions(+) create mode 100644 gcc/testsuite/rust/compile/issue-2788.rs diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 3055a39..c14c75c 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -5600,6 +5600,7 @@ Parser::parse_inherent_impl_item () return nullptr; } } + case ASYNC: case EXTERN_KW: case UNSAFE: case FN_KW: diff --git a/gcc/testsuite/rust/compile/issue-2788.rs b/gcc/testsuite/rust/compile/issue-2788.rs new file mode 100644 index 0000000..b3828fc --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-2788.rs @@ -0,0 +1,10 @@ +// { dg-additional-options "-frust-compile-until=lowering" } +struct Foo { + arg_1: u32, + arg_2: i32, +} + +impl Foo { + async fn asynchronous_function_1(&self) {} + async fn asynchronous_function_2() {} +} -- cgit v1.1 From 88a27c3bc0f1ecf91699b0dbc38bd00dc87a47a4 Mon Sep 17 00:00:00 2001 From: Robert Goss Date: Tue, 16 Jan 2024 22:50:51 +0000 Subject: gccrs: Add improved error when a field is redefined in a struct constructor Fixes #2381 If a struct type is initialized with one of it's fields repeated it will currently issue an error at the use site. However we would like to give the rust error code and (like rustc) show both the specifications for the field to help the user diagnose the issue. We move the check after the index for the field has been established so we can look up if the field has already been defined and get it's location. We update the visit method to return if it has handled an error otherwise we then output a second fatal error as not all the field in the specification have been processed. gcc/rust/ChangeLog: * typecheck/rust-hir-type-check-struct-field.h: Allow visit to return a bool * typecheck/rust-hir-type-check-struct.cc: Improve check of repeat fields gcc/testsuite/ChangeLog: * rust/compile/repeated_constructor_fields.rs: Added case with constructor field repeated Signed-off-by: Robert Goss --- .../typecheck/rust-hir-type-check-struct-field.h | 6 +- gcc/rust/typecheck/rust-hir-type-check-struct.cc | 90 +++++++++++++++------- .../rust/compile/repeated_constructor_fields.rs | 10 +++ 3 files changed, 74 insertions(+), 32 deletions(-) create mode 100644 gcc/testsuite/rust/compile/repeated_constructor_fields.rs diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h index 923c707..31d2896 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h +++ b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h @@ -35,9 +35,9 @@ public: protected: void resolve (HIR::StructExprStructFields &struct_expr); - void visit (HIR::StructExprFieldIdentifierValue &field); - void visit (HIR::StructExprFieldIndexValue &field); - void visit (HIR::StructExprFieldIdentifier &field); + bool visit (HIR::StructExprFieldIdentifierValue &field); + bool visit (HIR::StructExprFieldIndexValue &field); + bool visit (HIR::StructExprFieldIdentifier &field); private: TypeCheckStructExpr (HIR::Expr *e); diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct.cc b/gcc/rust/typecheck/rust-hir-type-check-struct.cc index f2dd8b6..56aa3d8 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-struct.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-struct.cc @@ -102,19 +102,26 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr) switch (field->get_kind ()) { case HIR::StructExprField::StructExprFieldKind::IDENTIFIER: - visit (static_cast (*field.get ())); + ok = visit ( + static_cast (*field.get ())); break; case HIR::StructExprField::StructExprFieldKind::IDENTIFIER_VALUE: - visit ( + ok = visit ( static_cast (*field.get ())); break; case HIR::StructExprField::StructExprFieldKind::INDEX_VALUE: - visit (static_cast (*field.get ())); + ok = visit ( + static_cast (*field.get ())); break; } + if (!ok) + { + return; + } + if (resolved_field_value_expr == nullptr) { rust_fatal_error (field->get_locus (), @@ -238,16 +245,9 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr) resolved = struct_def; } -void +bool TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field) { - auto it = fields_assigned.find (field.field_name.as_string ()); - if (it != fields_assigned.end ()) - { - rust_fatal_error (field.get_locus (), "used more than once"); - return; - } - size_t field_index; TyTy::StructFieldType *field_type; bool ok = variant->lookup_field (field.field_name.as_string (), &field_type, @@ -255,7 +255,20 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field) if (!ok) { rust_error_at (field.get_locus (), "unknown field"); - return; + return true; + } + + auto it = adtFieldIndexToField.find (field_index); + if (it != adtFieldIndexToField.end ()) + { + rich_location repeat_location (line_table, field.get_locus ()); + auto prev_field_locus = it->second->get_locus (); + repeat_location.add_range (prev_field_locus); + + rust_error_at (repeat_location, ErrorCode::E0062, + "field %<%s%> specified more than once", + field.field_name.as_string ().c_str ()); + return false; } TyTy::BaseType *value = TypeCheckExpr::Resolve (field.get_value ().get ()); @@ -273,18 +286,14 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field) fields_assigned.insert (field.field_name.as_string ()); adtFieldIndexToField[field_index] = &field; } + + return true; } -void +bool TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field) { std::string field_name (std::to_string (field.get_tuple_index ())); - auto it = fields_assigned.find (field_name); - if (it != fields_assigned.end ()) - { - rust_fatal_error (field.get_locus (), "used more than once"); - return; - } size_t field_index; TyTy::StructFieldType *field_type; @@ -292,7 +301,20 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field) if (!ok) { rust_error_at (field.get_locus (), "unknown field"); - return; + return true; + } + + auto it = adtFieldIndexToField.find (field_index); + if (it != adtFieldIndexToField.end ()) + { + rich_location repeat_location (line_table, field.get_locus ()); + auto prev_field_locus = it->second->get_locus (); + repeat_location.add_range (prev_field_locus); + + rust_error_at (repeat_location, ErrorCode::E0062, + "field %<%s%> specified more than once", + field_name.c_str ()); + return false; } TyTy::BaseType *value = TypeCheckExpr::Resolve (field.get_value ().get ()); @@ -310,18 +332,13 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field) fields_assigned.insert (field_name); adtFieldIndexToField[field_index] = &field; } + + return true; } -void +bool TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field) { - auto it = fields_assigned.find (field.get_field_name ().as_string ()); - if (it != fields_assigned.end ()) - { - rust_fatal_error (field.get_locus (), "used more than once"); - return; - } - size_t field_index; TyTy::StructFieldType *field_type; bool ok = variant->lookup_field (field.get_field_name ().as_string (), @@ -329,7 +346,20 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field) if (!ok) { rust_error_at (field.get_locus (), "unknown field"); - return; + return true; + } + + auto it = adtFieldIndexToField.find (field_index); + if (it != adtFieldIndexToField.end ()) + { + rich_location repeat_location (line_table, field.get_locus ()); + auto prev_field_locus = it->second->get_locus (); + repeat_location.add_range (prev_field_locus); + + rust_error_at (repeat_location, ErrorCode::E0062, + "field %<%s%> specified more than once", + field.get_field_name ().as_string ().c_str ()); + return false; } // we can make the field look like a path expr to take advantage of existing @@ -358,6 +388,8 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field) fields_assigned.insert (field.get_field_name ().as_string ()); adtFieldIndexToField[field_index] = &field; } + + return true; } } // namespace Resolver diff --git a/gcc/testsuite/rust/compile/repeated_constructor_fields.rs b/gcc/testsuite/rust/compile/repeated_constructor_fields.rs new file mode 100644 index 0000000..729001b --- /dev/null +++ b/gcc/testsuite/rust/compile/repeated_constructor_fields.rs @@ -0,0 +1,10 @@ +struct Foo { + x: i32, +} + +fn main() { + let x = Foo { + x: 0, + x: 0, // { dg-error "field 'x' specified more than once" } + }; +} -- cgit v1.1 From 1460044f87ef6801d5c17cf94a9a87282bff9464 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Wed, 20 Dec 2023 02:30:20 -0500 Subject: gccrs: Unify storage of associated items in SingleASTNode gcc/rust/ChangeLog: * ast/rust-ast-fragment.cc (Fragment::assert_single_fragment): Update. * ast/rust-ast.h (class TraitImplItem): Move definition before that of TraitItem. (class TraitItem): Inherit from TraitImplItem instead of AssociatedItem. (class SingleASTNode): Unify handling of associated items. (SingleASTNode::take_assoc_item): Move from... (SingleASTNode::take_impl_item): ...here, but leave stub calling take_assoc_item behind. (SingleASTNode::take_trait_item): Cast associated item to TraitItem. (SingleASTNode::take_trait_impl_item): Cast associated item to TraitImplItem. * ast/rust-ast.cc (SingleASTNode::SingleASTNode): Unify handling of associated items. (SingleASTNode::operator=): Likewise. (SingleASTNode::accept_vis): Likewise. (SingleASTNode::is_error): Likewise. (SingleASTNode::as_string): Likewise. * ast/rust-item.h (class Function): Remove direct inheritence from AssociatedItem. (class ConstantItem): Likewise. * ast/rust-macro.h (class MacroInvocation): Remove direct inheritence from AssociatedItem and TraitImplItem. --- gcc/rust/ast/rust-ast-fragment.cc | 4 +-- gcc/rust/ast/rust-ast.cc | 52 +++++++------------------------- gcc/rust/ast/rust-ast.h | 63 ++++++++++++++++++--------------------- gcc/rust/ast/rust-item.h | 8 ++--- gcc/rust/ast/rust-macro.h | 2 -- 5 files changed, 42 insertions(+), 87 deletions(-) diff --git a/gcc/rust/ast/rust-ast-fragment.cc b/gcc/rust/ast/rust-ast-fragment.cc index e757451..d8bf4aa 100644 --- a/gcc/rust/ast/rust-ast-fragment.cc +++ b/gcc/rust/ast/rust-ast-fragment.cc @@ -153,14 +153,12 @@ void Fragment::assert_single_fragment (SingleASTNode::NodeType expected) const { static const std::map str_map = { - {SingleASTNode::NodeType::IMPL, "impl"}, + {SingleASTNode::NodeType::ASSOC_ITEM, "associated item"}, {SingleASTNode::NodeType::ITEM, "item"}, {SingleASTNode::NodeType::TYPE, "type"}, {SingleASTNode::NodeType::EXPRESSION, "expr"}, {SingleASTNode::NodeType::STMT, "stmt"}, {SingleASTNode::NodeType::EXTERN, "extern"}, - {SingleASTNode::NodeType::TRAIT, "trait"}, - {SingleASTNode::NodeType::TRAIT_IMPL, "trait impl"}, }; auto actual = nodes[0].get_kind (); diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index b909603..360a9ce 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -60,16 +60,8 @@ SingleASTNode::SingleASTNode (SingleASTNode const &other) external_item = other.external_item->clone_external_item (); break; - case TRAIT: - trait_item = other.trait_item->clone_trait_item (); - break; - - case IMPL: - impl_item = other.impl_item->clone_associated_item (); - break; - - case TRAIT_IMPL: - trait_impl_item = other.trait_impl_item->clone_trait_impl_item (); + case ASSOC_ITEM: + assoc_item = other.assoc_item->clone_associated_item (); break; case TYPE: @@ -100,16 +92,8 @@ SingleASTNode::operator= (SingleASTNode const &other) external_item = other.external_item->clone_external_item (); break; - case TRAIT: - trait_item = other.trait_item->clone_trait_item (); - break; - - case IMPL: - impl_item = other.impl_item->clone_associated_item (); - break; - - case TRAIT_IMPL: - trait_impl_item = other.trait_impl_item->clone_trait_impl_item (); + case ASSOC_ITEM: + assoc_item = other.assoc_item->clone_associated_item (); break; case TYPE: @@ -140,16 +124,8 @@ SingleASTNode::accept_vis (ASTVisitor &vis) external_item->accept_vis (vis); break; - case TRAIT: - trait_item->accept_vis (vis); - break; - - case IMPL: - impl_item->accept_vis (vis); - break; - - case TRAIT_IMPL: - trait_impl_item->accept_vis (vis); + case ASSOC_ITEM: + assoc_item->accept_vis (vis); break; case TYPE: @@ -171,12 +147,8 @@ SingleASTNode::is_error () return stmt == nullptr; case EXTERN: return external_item == nullptr; - case TRAIT: - return trait_item == nullptr; - case IMPL: - return impl_item == nullptr; - case TRAIT_IMPL: - return trait_impl_item == nullptr; + case ASSOC_ITEM: + return assoc_item == nullptr; case TYPE: return type == nullptr; } @@ -198,12 +170,8 @@ SingleASTNode::as_string () const return "Stmt: " + stmt->as_string (); case EXTERN: return "External Item: " + external_item->as_string (); - case TRAIT: - return "Trait Item: " + trait_item->as_string (); - case IMPL: - return "Impl Item: " + impl_item->as_string (); - case TRAIT_IMPL: - return "Trait Impl Item: " + trait_impl_item->as_string (); + case ASSOC_ITEM: + return "Associated Item: " + assoc_item->as_string (); case TYPE: return "Type: " + type->as_string (); } diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index a450854..256a527 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -1657,8 +1657,22 @@ public: virtual location_t get_locus () const = 0; }; +// Abstract base class for items used in a trait impl +class TraitImplItem : public AssociatedItem +{ +protected: + virtual TraitImplItem *clone_associated_item_impl () const override = 0; + +public: + // Unique pointer custom clone function + std::unique_ptr clone_trait_impl_item () const + { + return std::unique_ptr (clone_associated_item_impl ()); + } +}; + // Item used in trait declarations - abstract base class -class TraitItem : virtual public AssociatedItem +class TraitItem : public TraitImplItem { protected: TraitItem (location_t locus) @@ -1689,20 +1703,6 @@ public: location_t get_locus () const override { return locus; } }; -// Abstract base class for items used in a trait impl -class TraitImplItem : virtual public AssociatedItem -{ -protected: - virtual TraitImplItem *clone_associated_item_impl () const override = 0; - -public: - // Unique pointer custom clone function - std::unique_ptr clone_trait_impl_item () const - { - return std::unique_ptr (clone_associated_item_impl ()); - } -}; - // Abstract base class for an item used inside an extern block class ExternalItem : public Visitable { @@ -1831,9 +1831,7 @@ public: ITEM, STMT, EXTERN, - TRAIT, - IMPL, - TRAIT_IMPL, + ASSOC_ITEM, TYPE, }; @@ -1845,9 +1843,7 @@ private: std::unique_ptr item; std::unique_ptr stmt; std::unique_ptr external_item; - std::unique_ptr trait_item; - std::unique_ptr impl_item; - std::unique_ptr trait_impl_item; + std::unique_ptr assoc_item; std::unique_ptr type; public: @@ -1867,16 +1863,8 @@ public: : kind (EXTERN), external_item (std::move (item)) {} - SingleASTNode (std::unique_ptr item) - : kind (TRAIT), trait_item (std::move (item)) - {} - SingleASTNode (std::unique_ptr item) - : kind (IMPL), impl_item (std::move (item)) - {} - - SingleASTNode (std::unique_ptr trait_impl_item) - : kind (TRAIT_IMPL), trait_impl_item (std::move (trait_impl_item)) + : kind (ASSOC_ITEM), assoc_item (std::move (item)) {} SingleASTNode (std::unique_ptr type) @@ -1936,7 +1924,8 @@ public: std::unique_ptr take_trait_item () { rust_assert (!is_error ()); - return std::move (trait_item); + return std::unique_ptr ( + static_cast (assoc_item.release ())); } std::unique_ptr take_external_item () @@ -1945,16 +1934,22 @@ public: return std::move (external_item); } - std::unique_ptr take_impl_item () + std::unique_ptr take_assoc_item () { rust_assert (!is_error ()); - return std::move (impl_item); + return std::move (assoc_item); + } + + std::unique_ptr take_impl_item () + { + return take_assoc_item (); } std::unique_ptr take_trait_impl_item () { rust_assert (!is_error ()); - return std::move (trait_impl_item); + return std::unique_ptr ( + static_cast (assoc_item.release ())); } std::unique_ptr take_type () diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index a995273..5b9eb64 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -1289,9 +1289,7 @@ protected: class LetStmt; // Rust function declaration AST node -class Function : public VisItem, - virtual public AssociatedItem, - public TraitImplItem +class Function : public VisItem, public TraitImplItem { FunctionQualifiers qualifiers; Identifier function_name; @@ -2314,9 +2312,7 @@ protected: /* "Constant item" AST node - used for constant, compile-time expressions * within module scope (like constexpr) */ -class ConstantItem : public VisItem, - virtual public AssociatedItem, - public TraitImplItem +class ConstantItem : public VisItem, public TraitImplItem { // either has an identifier or "_" - maybe handle in identifier? // bool identifier_is_underscore; diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h index 41c21cf..bcf5b0b 100644 --- a/gcc/rust/ast/rust-macro.h +++ b/gcc/rust/ast/rust-macro.h @@ -598,8 +598,6 @@ class MacroInvocation : public TypeNoBounds, public Pattern, public Item, public TraitItem, - public TraitImplItem, - virtual public AssociatedItem, public ExternalItem, public ExprWithoutBlock { -- cgit v1.1 From adb62fe2b46c3e60b8fcf4a40845ed919ca636e2 Mon Sep 17 00:00:00 2001 From: Kushal Pal Date: Sat, 30 Dec 2023 09:40:19 +0530 Subject: gccrs: Added newline to get more readable lexdump Fixes #2783 gcc/rust/ChangeLog: * lex/rust-lex.cc (Lexer::dump_and_skip): Changed " " to '\n' Signed-off-by: Kushal Pal --- gcc/rust/lex/rust-lex.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc index 6fc336d..bf6bf4c 100644 --- a/gcc/rust/lex/rust-lex.cc +++ b/gcc/rust/lex/rust-lex.cc @@ -240,7 +240,7 @@ Lexer::dump_and_skip (int n) + std::string (tok->get_type_hint_str ())) : "") << " "; - out << Linemap::location_to_string (loc) << " "; + out << Linemap::location_to_string (loc) << '\n'; } token_queue.skip (0); -- cgit v1.1 From aed23b571148656ef00c4b3ebc69db2232030849 Mon Sep 17 00:00:00 2001 From: Jakub Dupak Date: Tue, 9 Jan 2024 15:43:01 +0100 Subject: gccrs: Test: fix missing lifetime in a test This test did not compile with rustc. gcc/testsuite/ChangeLog: * rust/compile/torture/utf8_identifiers.rs: add mising lifetime Signed-off-by: Jakub Dupak --- gcc/testsuite/rust/compile/torture/utf8_identifiers.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/testsuite/rust/compile/torture/utf8_identifiers.rs b/gcc/testsuite/rust/compile/torture/utf8_identifiers.rs index eeee01c..696fcc0 100644 --- a/gcc/testsuite/rust/compile/torture/utf8_identifiers.rs +++ b/gcc/testsuite/rust/compile/torture/utf8_identifiers.rs @@ -1,7 +1,7 @@ #[lang = "sized"] pub trait Sized {} -pub fn f() { +pub fn f<'かに>() { let crab = (); let Κάβουρας = 0.001; -- cgit v1.1 From 37d4cf484618460e7db3d5a69c094510ae9396ce Mon Sep 17 00:00:00 2001 From: Jakub Dupak Date: Tue, 9 Jan 2024 15:45:12 +0100 Subject: gccrs: AST: Fix for lifetime parsing gcc/rust/ChangeLog: * parse/rust-parse-impl.h (Parser::parse_where_clause): fix parsing (Parser::parse_where_clause_item): fix parsing (Parser::parse_type_bound_where_clause_item): fix parsing (Parser::parse_trait_bound): fix parsing * parse/rust-parse.h: fix parsing Signed-off-by: Jakub Dupak --- gcc/rust/parse/rust-parse-impl.h | 37 +++++++++++++++++++++++-------------- gcc/rust/parse/rust-parse.h | 6 ++++-- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index c14c75c..7ea7276 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -3756,6 +3756,10 @@ Parser::parse_where_clause () * so won't be here */ std::vector> where_clause_items; + std::vector for_lifetimes; + if (lexer.peek_token ()->get_id () == FOR) + for_lifetimes = parse_for_lifetimes (); + /* HACK: where clauses end with a right curly or semicolon or equals in all * uses currently */ const_TokenPtr t = lexer.peek_token (); @@ -3763,7 +3767,7 @@ Parser::parse_where_clause () && t->get_id () != EQUAL) { std::unique_ptr where_clause_item - = parse_where_clause_item (); + = parse_where_clause_item (for_lifetimes); if (where_clause_item == nullptr) { @@ -3791,7 +3795,8 @@ Parser::parse_where_clause () * commas. */ template std::unique_ptr -Parser::parse_where_clause_item () +Parser::parse_where_clause_item ( + const std::vector &outer_for_lifetimes) { // shitty cheat way of determining lifetime or type bound - test for // lifetime @@ -3800,7 +3805,7 @@ Parser::parse_where_clause_item () if (t->get_id () == LIFETIME) return parse_lifetime_where_clause_item (); else - return parse_type_bound_where_clause_item (); + return parse_type_bound_where_clause_item (outer_for_lifetimes); } // Parses a lifetime where clause item. @@ -3834,12 +3839,10 @@ Parser::parse_lifetime_where_clause_item () // Parses a type bound where clause item. template std::unique_ptr -Parser::parse_type_bound_where_clause_item () +Parser::parse_type_bound_where_clause_item ( + const std::vector &outer_for_lifetimes) { - // parse for lifetimes, if it exists - std::vector for_lifetimes; - if (lexer.peek_token ()->get_id () == FOR) - for_lifetimes = parse_for_lifetimes (); + std::vector for_lifetimes = outer_for_lifetimes; std::unique_ptr type = parse_type (); if (type == nullptr) @@ -3853,6 +3856,13 @@ Parser::parse_type_bound_where_clause_item () return nullptr; } + if (lexer.peek_token ()->get_id () == FOR) + { + auto for_lifetimes_inner = parse_for_lifetimes (); + for_lifetimes.insert (for_lifetimes.end (), for_lifetimes_inner.begin (), + for_lifetimes_inner.end ()); + } + // parse type param bounds if they exist std::vector> type_param_bounds = parse_type_param_bounds (); @@ -4029,6 +4039,11 @@ Parser::parse_trait_bound () location_t locus = lexer.peek_token ()->get_locus (); + /* parse optional `for lifetimes`. */ + std::vector for_lifetimes; + if (lexer.peek_token ()->get_id () == FOR) + for_lifetimes = parse_for_lifetimes (); + // handle trait bound being in parentheses if (lexer.peek_token ()->get_id () == LEFT_PAREN) { @@ -4043,12 +4058,6 @@ Parser::parse_trait_bound () lexer.skip_token (); } - /* parse for lifetimes, if it exists (although empty for lifetimes is ok to - * handle this) */ - std::vector for_lifetimes; - if (lexer.peek_token ()->get_id () == FOR) - for_lifetimes = parse_for_lifetimes (); - // handle TypePath AST::TypePath type_path = parse_type_path (); diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 3fc8620..02f9021 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -288,11 +288,13 @@ private: std::unique_ptr parse_function_param (); std::unique_ptr parse_function_return_type (); AST::WhereClause parse_where_clause (); - std::unique_ptr parse_where_clause_item (); + std::unique_ptr parse_where_clause_item ( + const std::vector &global_for_lifetimes); std::unique_ptr parse_lifetime_where_clause_item (); std::unique_ptr - parse_type_bound_where_clause_item (); + parse_type_bound_where_clause_item ( + const std::vector &global_for_lifetimes); std::vector parse_for_lifetimes (); template std::vector> -- cgit v1.1 From 4b13ec24b1abcaa735583a55b8fa564446aa57eb Mon Sep 17 00:00:00 2001 From: Jakub Dupak Date: Tue, 9 Jan 2024 15:46:41 +0100 Subject: gccrs: AST: Fix for lifetime lowering gcc/rust/ChangeLog: * hir/rust-ast-lower-type.cc (ASTLoweringTypeBounds::visit): fix for lifetimes (ASTLowerWhereClauseItem::visit): fix for lifetimes Signed-off-by: Jakub Dupak --- gcc/rust/hir/rust-ast-lower-type.cc | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/gcc/rust/hir/rust-ast-lower-type.cc b/gcc/rust/hir/rust-ast-lower-type.cc index a0178eb..504ca05 100644 --- a/gcc/rust/hir/rust-ast-lower-type.cc +++ b/gcc/rust/hir/rust-ast-lower-type.cc @@ -529,8 +529,13 @@ ASTLoweringTypeBounds::translate (AST::TypeParamBound *type) void ASTLoweringTypeBounds::visit (AST::TraitBound &bound) { - // FIXME - std::vector lifetimes; + std::vector for_lifetimes; + for (auto &lifetime_param : bound.get_for_lifetimes ()) + { + auto generic_param = ASTLowerGenericParam::translate (&lifetime_param); + for_lifetimes.push_back ( + *static_cast (generic_param)); + } AST::TypePath &ast_trait_path = bound.get_type_path (); HIR::TypePath *trait_path = ASTLowerTypePath::translate (ast_trait_path); @@ -543,8 +548,9 @@ ASTLoweringTypeBounds::visit (AST::TraitBound &bound) BoundPolarity polarity = bound.has_opening_question_mark () ? BoundPolarity::AntiBound : BoundPolarity::RegularBound; - translated = new HIR::TraitBound (mapping, *trait_path, bound.get_locus (), - bound.is_in_parens (), polarity); + translated + = new HIR::TraitBound (mapping, *trait_path, bound.get_locus (), + bound.is_in_parens (), polarity, for_lifetimes); } void @@ -596,6 +602,13 @@ ASTLowerWhereClauseItem::visit (AST::TypeBoundWhereClauseItem &item) // FIXME std::vector for_lifetimes; + for (auto &lifetime_param : item.get_for_lifetimes ()) + { + auto generic_param = ASTLowerGenericParam::translate (&lifetime_param); + for_lifetimes.push_back ( + *static_cast (generic_param)); + } + std::unique_ptr bound_type = std::unique_ptr ( ASTLoweringType::translate (item.get_type ().get ())); -- cgit v1.1 From b49afa9ba4ad94fc71a246bceca2fcc277cb0ada Mon Sep 17 00:00:00 2001 From: Jakub Dupak Date: Thu, 18 Jan 2024 14:37:58 +0100 Subject: gccrs: Test: check implemented for lifetime handling gcc/testsuite/ChangeLog: * rust/compile/for_lifetimes.rs: New test. Signed-off-by: Jakub Dupak --- gcc/testsuite/rust/compile/for_lifetimes.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 gcc/testsuite/rust/compile/for_lifetimes.rs diff --git a/gcc/testsuite/rust/compile/for_lifetimes.rs b/gcc/testsuite/rust/compile/for_lifetimes.rs new file mode 100644 index 0000000..2646962 --- /dev/null +++ b/gcc/testsuite/rust/compile/for_lifetimes.rs @@ -0,0 +1,19 @@ +// { dg-additional-options "-frust-compile-until=typecheck" } + +fn function_pointer_as_argument(f: for<'a> fn(&'a i32) -> &'a i32) -> i32 { + 0 +} + +fn function_pointer_as_return() -> for<'a> fn(&'a i32) -> &'a i32 { +} + +// https://doc.rust-lang.org/reference/trait-bounds.html + +trait Fn {} +fn call_on_ref_zero(f: F) where for<'a> F: Fn(&'a i32) {} + +fn call_on_ref_zero2(f: F) where F: for<'a> Fn(&'a i32) {} + +trait Trait<'a, T: 'a> {} + +impl<'a, T> Trait<'a, T> for &'a T {} \ No newline at end of file -- cgit v1.1 From c3ce1d6d8728969997a556e3f8bc59b726aff49a Mon Sep 17 00:00:00 2001 From: Robert Goss Date: Sun, 14 Jan 2024 17:34:22 +0000 Subject: gccrs: Add improved error when no fields in initializer If a struct type with a variant that has fields is initialized with some fields the expression HIR StructExprStructFields is checked that all the fields are assigned. However, if no fields are initialized the HIR StructExprStruct is generated. This doesn't check if the struct is a unit during typechekc and only fails at the compile stage with a ICE. Add a check at the typecheck stage that makes sure the struct does not have a variant with fields and give an error message based on the rustc one. We have also updated the message given in the case where one field was present to list the missing fields and match more closely the new message. gcc/rust/ChangeLog: * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit) Add additional check * typecheck/rust-hir-type-check-struct-field.h: A helper method to make error added * typecheck/rust-hir-type-check-struct.cc (TypeCheckStructExpr::resolve) Update message gcc/testsuite/ChangeLog: * rust/compile/missing_constructor_fields.rs: Added case with no initializers Signed-off-by: Robert Goss --- gcc/rust/typecheck/rust-hir-type-check-expr.cc | 18 ++++++++ .../typecheck/rust-hir-type-check-struct-field.h | 9 ++++ gcc/rust/typecheck/rust-hir-type-check-struct.cc | 48 ++++++++++++++++++++-- .../rust/compile/missing_constructor_fields.rs | 6 ++- 4 files changed, 76 insertions(+), 5 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc index 030e5f1..43d183f 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc @@ -1017,6 +1017,24 @@ TypeCheckExpr::visit (HIR::StructExprStruct &struct_expr) return; } + TyTy::ADTType *adt = static_cast (struct_path_ty); + for (auto variant : adt->get_variants ()) + { + if (!variant->get_fields ().empty ()) + { + std::vector field_names; + for (auto &field : variant->get_fields ()) + field_names.push_back (field->get_name ()); + Error missing_fields_error + = TypeCheckStructExpr::make_missing_field_error ( + struct_expr.get_locus (), field_names, + struct_path_ty->get_name ()); + // We might want to return or handle these in the future emit for now. + missing_fields_error.emit (); + return; + } + } + infered = struct_path_ty; } diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h index 31d2896..792eebf 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h +++ b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h @@ -25,6 +25,9 @@ #include "rust-tyty.h" namespace Rust { + +struct Error; + namespace Resolver { class TypeCheckStructExpr : public TypeCheckBase @@ -32,6 +35,12 @@ class TypeCheckStructExpr : public TypeCheckBase public: static TyTy::BaseType *Resolve (HIR::StructExprStructFields *expr); + // Helper for making any errors + static Error + make_missing_field_error (location_t locus, + const std::vector &missing_field_names, + const std::string &struct_name); + protected: void resolve (HIR::StructExprStructFields &struct_expr); diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct.cc b/gcc/rust/typecheck/rust-hir-type-check-struct.cc index 56aa3d8..d2977ac 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-struct.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-struct.cc @@ -142,7 +142,16 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr) } // check the arguments are all assigned and fix up the ordering - if (fields_assigned.size () != variant->num_fields ()) + std::vector missing_field_names; + for (auto &field : variant->get_fields ()) + { + auto it = fields_assigned.find (field->get_name ()); + if (it == fields_assigned.end ()) + { + missing_field_names.push_back (field->get_name ()); + } + } + if (!missing_field_names.empty ()) { if (struct_def->is_union ()) { @@ -156,8 +165,12 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr) } else if (!struct_expr.has_struct_base ()) { - rust_error_at (struct_expr.get_locus (), ErrorCode::E0063, - "constructor is missing fields"); + Error missing_fields_error + = make_missing_field_error (struct_expr.get_locus (), + missing_field_names, + struct_path_ty->get_name ()); + // We might want to return or handle these in the future emit for now. + missing_fields_error.emit (); return; } else @@ -392,5 +405,34 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field) return true; } +Error +TypeCheckStructExpr::make_missing_field_error ( + location_t locus, const std::vector &missing_field_names, + const std::string &struct_name) +{ + // Message plurality depends on size + if (missing_field_names.size () == 1) + { + return Error (locus, ErrorCode::E0063, + "missing field %s in initializer of %qs", + missing_field_names[0].c_str (), struct_name.c_str ()); + } + // Make comma separated string for display + std::stringstream display_field_names; + bool first = true; + for (auto &name : missing_field_names) + { + if (!first) + { + display_field_names << ", "; + } + first = false; + display_field_names << name; + } + return Error (locus, ErrorCode::E0063, + "missing fields %s in initializer of %qs", + display_field_names.str ().c_str (), struct_name.c_str ()); +} + } // namespace Resolver } // namespace Rust diff --git a/gcc/testsuite/rust/compile/missing_constructor_fields.rs b/gcc/testsuite/rust/compile/missing_constructor_fields.rs index 9d49210..6e3965b 100644 --- a/gcc/testsuite/rust/compile/missing_constructor_fields.rs +++ b/gcc/testsuite/rust/compile/missing_constructor_fields.rs @@ -6,5 +6,7 @@ struct Foo { } fn main() { - let x = Foo { x: 0 , y:1 }; // { dg-error "constructor is missing fields" } -} \ No newline at end of file + let z = Foo { x: 0 , y:1 }; // { dg-error "missing field z in initializer of 'Foo'" } + let xz = Foo { y:1 }; // { dg-error "missing fields x, z in initializer of 'Foo'" } + let xyz = Foo { }; // { dg-error "missing fields x, y, z in initializer of 'Foo'" } +} -- cgit v1.1 From 1740fbe1dd6005faaae1459af4e0bc31cd993ed2 Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Wed, 20 Dec 2023 03:04:36 -0500 Subject: gccrs: Remove TraitImplItem gcc/rust/ChangeLog: * ast/rust-ast-full-decls.h (class TraitImplItem): Remove forward declaration. (class AssociatedItem): Add forward declaration. * ast/rust-ast.h (class TraitImplItem): Remove. (class TraitItem): Inherit from AssociatedItem. (SingleASTNode::take_trait_impl_item): Return std::unique_ptr instead of std::unique_ptr. * ast/rust-item.h (class Function): Inherit from AssociatedItem instead of TraitImplItem. (class TypeAlias): Likewise. (class ConstantItem): Likewise. (class TraitImpl): Store items as AssociatedItem. * expand/rust-derive-clone.cc (DeriveClone::clone_fn): Return std::unique_ptr. (DeriveClone::clone_impl): Take std::unique_ptr. * expand/rust-derive-clone.h (DeriveClone::clone_fn): Return std::unique_ptr. (DeriveClone::clone_impl): Take std::unique_ptr. * expand/rust-expand-visitor.cc (ExpandVisitor::visit): Handle changes to SingleASTNode::take_trait_impl_item. * parse/rust-parse-impl.h (Parser::parse_impl): Parse TraitImpl as containing AssociatedItem. (Parser::parse_trait_impl_item): Return std::unique_ptr. (Parser::parse_trait_impl_function_or_method): Likewise. * parse/rust-parse.h (Parser::parse_trait_impl_item): Return std::unique_ptr. (Parser::parse_trait_impl_function_or_method): Likewise. Signed-off-by: Owen Avery --- gcc/rust/ast/rust-ast-full-decls.h | 2 +- gcc/rust/ast/rust-ast.h | 22 +++------------------- gcc/rust/ast/rust-item.h | 18 +++++++++--------- gcc/rust/expand/rust-derive-clone.cc | 8 ++++---- gcc/rust/expand/rust-derive-clone.h | 4 ++-- gcc/rust/expand/rust-expand-visitor.cc | 2 +- gcc/rust/parse/rust-parse-impl.h | 8 ++++---- gcc/rust/parse/rust-parse.h | 4 ++-- 8 files changed, 26 insertions(+), 42 deletions(-) diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h index 5bfaaa8..0f95149 100644 --- a/gcc/rust/ast/rust-ast-full-decls.h +++ b/gcc/rust/ast/rust-ast-full-decls.h @@ -52,7 +52,7 @@ class GenericParam; class LifetimeParam; class ConstGenericParam; class TraitItem; -class TraitImplItem; +class AssociatedItem; struct Crate; class PathExpr; diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 256a527..e96ac34 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -1657,22 +1657,8 @@ public: virtual location_t get_locus () const = 0; }; -// Abstract base class for items used in a trait impl -class TraitImplItem : public AssociatedItem -{ -protected: - virtual TraitImplItem *clone_associated_item_impl () const override = 0; - -public: - // Unique pointer custom clone function - std::unique_ptr clone_trait_impl_item () const - { - return std::unique_ptr (clone_associated_item_impl ()); - } -}; - // Item used in trait declarations - abstract base class -class TraitItem : public TraitImplItem +class TraitItem : public AssociatedItem { protected: TraitItem (location_t locus) @@ -1945,11 +1931,9 @@ public: return take_assoc_item (); } - std::unique_ptr take_trait_impl_item () + std::unique_ptr take_trait_impl_item () { - rust_assert (!is_error ()); - return std::unique_ptr ( - static_cast (assoc_item.release ())); + return take_assoc_item (); } std::unique_ptr take_type () diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 5b9eb64..1553f29 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -1289,7 +1289,7 @@ protected: class LetStmt; // Rust function declaration AST node -class Function : public VisItem, public TraitImplItem +class Function : public VisItem, public AssociatedItem { FunctionQualifiers qualifiers; Identifier function_name; @@ -1436,7 +1436,7 @@ protected: }; // Rust type alias (i.e. typedef) AST node -class TypeAlias : public VisItem, public TraitImplItem +class TypeAlias : public VisItem, public AssociatedItem { Identifier new_type_name; @@ -2312,7 +2312,7 @@ protected: /* "Constant item" AST node - used for constant, compile-time expressions * within module scope (like constexpr) */ -class ConstantItem : public VisItem, public TraitImplItem +class ConstantItem : public VisItem, public AssociatedItem { // either has an identifier or "_" - maybe handle in identifier? // bool identifier_is_underscore; @@ -3484,7 +3484,7 @@ class TraitImpl : public Impl TypePath trait_path; // bool has_impl_items; - std::vector> impl_items; + std::vector> impl_items; public: std::string as_string () const override; @@ -3494,7 +3494,7 @@ public: // Mega-constructor TraitImpl (TypePath trait_path, bool is_unsafe, bool has_exclam, - std::vector> impl_items, + std::vector> impl_items, std::vector> generic_params, std::unique_ptr trait_type, WhereClause where_clause, Visibility vis, std::vector inner_attrs, @@ -3513,7 +3513,7 @@ public: { impl_items.reserve (other.impl_items.size ()); for (const auto &e : other.impl_items) - impl_items.push_back (e->clone_trait_impl_item ()); + impl_items.push_back (e->clone_associated_item ()); } // Overloaded assignment operator with vector clone @@ -3526,7 +3526,7 @@ public: impl_items.reserve (other.impl_items.size ()); for (const auto &e : other.impl_items) - impl_items.push_back (e->clone_trait_impl_item ()); + impl_items.push_back (e->clone_associated_item ()); return *this; } @@ -3541,11 +3541,11 @@ public: bool is_exclam () const { return has_exclam; } // TODO: think of better way to do this - const std::vector> &get_impl_items () const + const std::vector> &get_impl_items () const { return impl_items; } - std::vector> &get_impl_items () + std::vector> &get_impl_items () { return impl_items; } diff --git a/gcc/rust/expand/rust-derive-clone.cc b/gcc/rust/expand/rust-derive-clone.cc index cc198ee..01226e4 100644 --- a/gcc/rust/expand/rust-derive-clone.cc +++ b/gcc/rust/expand/rust-derive-clone.cc @@ -43,7 +43,7 @@ DeriveClone::clone_call (std::unique_ptr &&to_clone) * fn clone(&self) -> Self { } * */ -std::unique_ptr +std::unique_ptr DeriveClone::clone_fn (std::unique_ptr &&clone_expr) { auto block = std::unique_ptr ( @@ -57,7 +57,7 @@ DeriveClone::clone_fn (std::unique_ptr &&clone_expr) std::vector> params; params.push_back (std::move (self)); - return std::unique_ptr ( + return std::unique_ptr ( new Function ({"clone"}, builder.fn_qualifiers (), /* generics */ {}, /* function params */ std::move (params), std::move (big_self_type), WhereClause::create_empty (), @@ -73,7 +73,7 @@ DeriveClone::clone_fn (std::unique_ptr &&clone_expr) * */ std::unique_ptr -DeriveClone::clone_impl (std::unique_ptr &&clone_fn, +DeriveClone::clone_impl (std::unique_ptr &&clone_fn, std::string name) { // should that be `$crate::core::clone::Clone` instead? @@ -81,7 +81,7 @@ DeriveClone::clone_impl (std::unique_ptr &&clone_fn, segments.emplace_back (builder.type_path_segment ("Clone")); auto clone = TypePath (std::move (segments), loc); - auto trait_items = std::vector> (); + auto trait_items = std::vector> (); trait_items.emplace_back (std::move (clone_fn)); return std::unique_ptr ( diff --git a/gcc/rust/expand/rust-derive-clone.h b/gcc/rust/expand/rust-derive-clone.h index dcb88f9..1009247 100644 --- a/gcc/rust/expand/rust-derive-clone.h +++ b/gcc/rust/expand/rust-derive-clone.h @@ -49,7 +49,7 @@ private: * fn clone(&self) -> Self { } * */ - std::unique_ptr clone_fn (std::unique_ptr &&clone_expr); + std::unique_ptr clone_fn (std::unique_ptr &&clone_expr); /** * Create the Clone trait implementation for a type @@ -59,7 +59,7 @@ private: * } * */ - std::unique_ptr clone_impl (std::unique_ptr &&clone_fn, + std::unique_ptr clone_impl (std::unique_ptr &&clone_fn, std::string name); virtual void visit_struct (StructStruct &item); diff --git a/gcc/rust/expand/rust-expand-visitor.cc b/gcc/rust/expand/rust-expand-visitor.cc index a60c472..dad2417 100644 --- a/gcc/rust/expand/rust-expand-visitor.cc +++ b/gcc/rust/expand/rust-expand-visitor.cc @@ -957,7 +957,7 @@ ExpandVisitor::visit (AST::TraitImpl &impl) if (impl.has_where_clause ()) expand_where_clause (impl.get_where_clause ()); - std::function (AST::SingleASTNode)> + std::function (AST::SingleASTNode)> extractor = [] (AST::SingleASTNode node) { return node.take_trait_impl_item (); }; diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 7ea7276..c622ed7 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -5492,12 +5492,12 @@ Parser::parse_impl (AST::Visibility vis, AST::AttrVec inner_attrs = parse_inner_attributes (); // parse trait impl items - std::vector> impl_items; + std::vector> impl_items; const_TokenPtr t = lexer.peek_token (); while (t->get_id () != RIGHT_CURLY) { - std::unique_ptr impl_item + std::unique_ptr impl_item = parse_trait_impl_item (); if (impl_item == nullptr) @@ -5759,7 +5759,7 @@ Parser::parse_inherent_impl_function_or_method ( // Parses a single trait impl item (item inside a trait impl block). template -std::unique_ptr +std::unique_ptr Parser::parse_trait_impl_item () { // parse outer attributes (if they exist) @@ -5836,7 +5836,7 @@ Parser::parse_trait_impl_item () * smaller ones and prevents duplication of logic. Strictly, this parses a * function or method item inside a trait impl item block. */ template -std::unique_ptr +std::unique_ptr Parser::parse_trait_impl_function_or_method ( AST::Visibility vis, AST::AttrVec outer_attrs) { diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 02f9021..3439754 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -171,7 +171,7 @@ public: std::unique_ptr parse_external_item (); std::unique_ptr parse_trait_item (); std::unique_ptr parse_inherent_impl_item (); - std::unique_ptr parse_trait_impl_item (); + std::unique_ptr parse_trait_impl_item (); AST::PathInExpression parse_path_in_expression (); std::vector> parse_lifetime_params (); AST::Visibility parse_visibility (); @@ -353,7 +353,7 @@ private: std::unique_ptr parse_inherent_impl_function_or_method (AST::Visibility vis, AST::AttrVec outer_attrs); - std::unique_ptr + std::unique_ptr parse_trait_impl_function_or_method (AST::Visibility vis, AST::AttrVec outer_attrs); std::unique_ptr -- cgit v1.1 From 2a9881565c7b48d04cf891666a66a1a2e560bce8 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Mon, 22 Jan 2024 14:04:11 +0100 Subject: gccrs: Fix output line ending patterns. gcc/testsuite/ChangeLog: * rust/execute/torture/builtin_macros1.rs: Fix output pattern. * rust/execute/torture/coercion3.rs: Likewise. * rust/execute/torture/issue-2080.rs: Likewise. * rust/execute/torture/issue-2179.rs: Likewise. * rust/execute/torture/issue-2180.rs: Likewise. * rust/execute/torture/iter1.rs: Likewise. --- gcc/testsuite/rust/execute/torture/builtin_macros1.rs | 2 +- gcc/testsuite/rust/execute/torture/coercion3.rs | 2 +- gcc/testsuite/rust/execute/torture/issue-2080.rs | 2 +- gcc/testsuite/rust/execute/torture/issue-2179.rs | 2 +- gcc/testsuite/rust/execute/torture/issue-2180.rs | 2 +- gcc/testsuite/rust/execute/torture/iter1.rs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/gcc/testsuite/rust/execute/torture/builtin_macros1.rs b/gcc/testsuite/rust/execute/torture/builtin_macros1.rs index f5dcbd6..04d0058 100644 --- a/gcc/testsuite/rust/execute/torture/builtin_macros1.rs +++ b/gcc/testsuite/rust/execute/torture/builtin_macros1.rs @@ -1,4 +1,4 @@ -// { dg-output "rust/execute/torture/builtin_macros1.rs\r*" } +// { dg-output "rust/execute/torture/builtin_macros1.rs\r*\n" } #![feature(rustc_attrs)] #[rustc_builtin_macro] diff --git a/gcc/testsuite/rust/execute/torture/coercion3.rs b/gcc/testsuite/rust/execute/torture/coercion3.rs index e88338a..0686056 100644 --- a/gcc/testsuite/rust/execute/torture/coercion3.rs +++ b/gcc/testsuite/rust/execute/torture/coercion3.rs @@ -1,4 +1,4 @@ -// { dg-output "123\n" } +// { dg-output "123\r*\n" } #[lang = "sized"] pub trait Sized {} diff --git a/gcc/testsuite/rust/execute/torture/issue-2080.rs b/gcc/testsuite/rust/execute/torture/issue-2080.rs index dbdbf41..5fdf911 100644 --- a/gcc/testsuite/rust/execute/torture/issue-2080.rs +++ b/gcc/testsuite/rust/execute/torture/issue-2080.rs @@ -1,4 +1,4 @@ -// { dg-output "hello world: gccrs\n" } +// { dg-output "hello world: gccrs\r*\n" } // { dg-additional-options "-w" } static TEST_1: &str = "gccrs"; static TEST_2: i32 = 123; diff --git a/gcc/testsuite/rust/execute/torture/issue-2179.rs b/gcc/testsuite/rust/execute/torture/issue-2179.rs index 86ed11f..8a5ec1b 100644 --- a/gcc/testsuite/rust/execute/torture/issue-2179.rs +++ b/gcc/testsuite/rust/execute/torture/issue-2179.rs @@ -1,4 +1,4 @@ -// { dg-output "123\n" } +// { dg-output "123\r*\n" } #[lang = "sized"] pub trait Sized {} diff --git a/gcc/testsuite/rust/execute/torture/issue-2180.rs b/gcc/testsuite/rust/execute/torture/issue-2180.rs index beed696..6bd7172 100644 --- a/gcc/testsuite/rust/execute/torture/issue-2180.rs +++ b/gcc/testsuite/rust/execute/torture/issue-2180.rs @@ -1,4 +1,4 @@ -// { dg-output "123\n" } +// { dg-output "123\r*\n" } #[lang = "sized"] pub trait Sized {} diff --git a/gcc/testsuite/rust/execute/torture/iter1.rs b/gcc/testsuite/rust/execute/torture/iter1.rs index 08f0645..c3b6c7b 100644 --- a/gcc/testsuite/rust/execute/torture/iter1.rs +++ b/gcc/testsuite/rust/execute/torture/iter1.rs @@ -1,4 +1,4 @@ -// { dg-output "1\n2\n" } +// { dg-output "1\r*\n2\r*\n" } #![feature(intrinsics)] pub use option::Option::{self, None, Some}; -- cgit v1.1