diff options
author | SimplyTheOther <simplytheother@gmail.com> | 2020-12-07 19:51:24 +0800 |
---|---|---|
committer | SimplyTheOther <simplytheother@gmail.com> | 2020-12-08 21:10:36 +0800 |
commit | c7080f178a637cad04e196a404d5d44bb33189af (patch) | |
tree | a023eeee3f2c3ab85190e4967cfe0599b466843e /gcc | |
parent | db39766514144dbbad34d9db3977c3a72d1216c3 (diff) | |
download | gcc-c7080f178a637cad04e196a404d5d44bb33189af.zip gcc-c7080f178a637cad04e196a404d5d44bb33189af.tar.gz gcc-c7080f178a637cad04e196a404d5d44bb33189af.tar.bz2 |
Added more cfg stripping code
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/analysis/rust-type-resolution.cc | 2 | ||||
-rw-r--r-- | gcc/rust/ast/rust-item.h | 20 | ||||
-rw-r--r-- | gcc/rust/ast/rust-pattern.h | 25 | ||||
-rw-r--r-- | gcc/rust/ast/rust-stmt.h | 7 | ||||
-rw-r--r-- | gcc/rust/ast/rust-type.h | 108 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile.cc | 10 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.cc | 167 | ||||
-rw-r--r-- | gcc/rust/parse/rust-parse-impl.h | 79 | ||||
-rw-r--r-- | gcc/rust/parse/rust-parse.h | 2 |
9 files changed, 336 insertions, 84 deletions
diff --git a/gcc/rust/analysis/rust-type-resolution.cc b/gcc/rust/analysis/rust-type-resolution.cc index 439543e..2c720c6 100644 --- a/gcc/rust/analysis/rust-type-resolution.cc +++ b/gcc/rust/analysis/rust-type-resolution.cc @@ -1038,7 +1038,7 @@ TypeResolution::visit (AST::LetStmt &stmt) if (stmt.has_type () && stmt.has_init_expr ()) { - if (!typesAreCompatible (stmt.type.get (), inferedType, + if (!typesAreCompatible (stmt.get_type ().get (), inferedType, stmt.get_init_expr ()->get_locus_slow ())) { return; diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index c47a6f5..455511c 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -90,8 +90,12 @@ public: TypeParam (TypeParam const &other) : outer_attr (other.outer_attr), type_representation (other.type_representation), - type (other.type->clone_type ()), locus (other.locus) + locus (other.locus) { + // guard to prevent null pointer dereference + if (other.type != nullptr) + type = other.type->clone_type (); + type_param_bounds.reserve (other.type_param_bounds.size ()); for (const auto &e : other.type_param_bounds) type_param_bounds.push_back (e->clone_type_param_bound ()); @@ -101,11 +105,15 @@ public: TypeParam &operator= (TypeParam const &other) { type_representation = other.type_representation; - // type_param_bounds = other.type_param_bounds; - type = other.type->clone_type (); outer_attr = other.outer_attr; locus = other.locus; + // guard to prevent null pointer dereference + if (other.type != nullptr) + type = other.type->clone_type (); + else + type = nullptr; + type_param_bounds.reserve (other.type_param_bounds.size ()); for (const auto &e : other.type_param_bounds) type_param_bounds.push_back (e->clone_type_param_bound ()); @@ -453,7 +461,7 @@ public: if (!this->extern_abi.empty ()) { // having extern is required; not having it is an implementation error - gcc_assert (has_extern); + rust_assert (has_extern); } } @@ -1101,7 +1109,7 @@ public: { // compiler implementation error if there is a path with a // non-path-prefixed use tree glob - gcc_assert (!has_path ()); + rust_assert (!has_path ()); } // TODO: do path-prefixed paths also have to have a path? If so, have an // assert for that too. @@ -1153,7 +1161,7 @@ public: { // compiler implementation error if there is a path with a // non-path-prefixed use tree glob - gcc_assert (!has_path ()); + rust_assert (!has_path ()); } // TODO: do path-prefixed paths also have to have a path? If so, have an // assert for that too. diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h index 5dd0429..5ae68ab 100644 --- a/gcc/rust/ast/rust-pattern.h +++ b/gcc/rust/ast/rust-pattern.h @@ -223,6 +223,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: this mutable getter seems kinda dodgy + PathInExpression &get_path () { return path; } + const PathInExpression &get_path () const { return path; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -251,6 +255,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: this mutable getter seems kinda dodgy + QualifiedPathInExpression &get_qualified_path () { return path; } + const QualifiedPathInExpression &get_qualified_path () const { return path; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -310,6 +318,17 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? or is a "vis_bound" better? + std::unique_ptr<RangePatternBound>& get_lower_bound () { + rust_assert (lower != nullptr); + return lower; + } + + std::unique_ptr<RangePatternBound>& get_upper_bound () { + rust_assert (upper != nullptr); + return upper; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -735,6 +754,9 @@ public: StructPatternElements &get_struct_pattern_elems () { return elems; } const StructPatternElements &get_struct_pattern_elems () const { return elems; } + PathInExpression &get_path () { return path; } + const PathInExpression &get_path () const { return path; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -940,6 +962,9 @@ public: return items; } + PathInExpression &get_path () { return path; } + const PathInExpression &get_path () const { return path; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/ast/rust-stmt.h b/gcc/rust/ast/rust-stmt.h index 167828c..88be256 100644 --- a/gcc/rust/ast/rust-stmt.h +++ b/gcc/rust/ast/rust-stmt.h @@ -41,7 +41,6 @@ class LetStmt : public Stmt // bool has_outer_attrs; std::vector<Attribute> outer_attrs; -public: std::unique_ptr<Pattern> variables_pattern; // bool has_type; @@ -52,6 +51,7 @@ public: Location locus; +public: Type *inferedType; // Returns whether let statement has outer attributes. @@ -140,6 +140,11 @@ public: return variables_pattern; } + std::unique_ptr<Type> &get_type () { + rust_assert (has_type ()); + return type; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h index d5953a5..ea9a89c 100644 --- a/gcc/rust/ast/rust-type.h +++ b/gcc/rust/ast/rust-type.h @@ -43,6 +43,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: this mutable getter seems kinda dodgy + TypePath &get_type_path () { return type_path; } + const TypePath &get_type_path () const { return type_path; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -109,6 +113,10 @@ public: Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; + + // TODO: mutable getter seems kinda dodgy + std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds () { return type_param_bounds; } + const std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds () const { return type_param_bounds; } }; // An opaque value of another type that implements a set of traits @@ -168,6 +176,10 @@ public: Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; + + // TODO: mutable getter seems kinda dodgy + std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds () { return type_param_bounds; } + const std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds () const { return type_param_bounds; } }; // A type with parentheses around it, used to avoid ambiguity. @@ -226,6 +238,12 @@ public: Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; + + // TODO: would a "vis_type" be better? + std::unique_ptr<Type> &get_type_in_parens () { + rust_assert (type_in_parens != nullptr); + return type_in_parens; + } }; // Impl trait with a single bound? Poor reference material here. @@ -253,6 +271,12 @@ public: Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; + + // TODO: would a "vis_type" be better? + TraitBound &get_trait_bound () { + // TODO: check to ensure invariants are met? + return trait_bound; + } }; /* A trait object with a single trait bound. The "trait bound" is really just @@ -292,6 +316,12 @@ public: Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; + + // TODO: would a "vis_type" be better? + TraitBound &get_trait_bound () { + // TODO: check to ensure invariants are met? + return trait_bound; + } }; class TypePath; // definition moved to "rust-path.h" @@ -342,6 +372,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: mutable getter seems kinda dodgy + std::vector<std::unique_ptr<Type> > &get_elems () { return elems; } + const std::vector<std::unique_ptr<Type> > &get_elems () const { return elems; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -429,6 +463,12 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: would a "vis_type" be better? + std::unique_ptr<TypeNoBounds> &get_type_pointed_to () { + rust_assert (type != nullptr); + return type; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -490,6 +530,12 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: would a "vis_type" be better? + std::unique_ptr<TypeNoBounds> &get_type_referenced () { + rust_assert (type != nullptr); + return type; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -539,6 +585,18 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: would a "vis_type" be better? + std::unique_ptr<Type> &get_elem_type () { + rust_assert (elem_type != nullptr); + return elem_type; + } + + // TODO: would a "vis_expr" be better? + std::unique_ptr<Expr> &get_size_expr () { + rust_assert (size != nullptr); + return size; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -586,6 +644,12 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: would a "vis_type" be better? + std::unique_ptr<Type> &get_elem_type () { + rust_assert (elem_type != nullptr); + return elem_type; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -635,6 +699,8 @@ public: }; private: + std::vector<Attribute> outer_attrs; + std::unique_ptr<Type> param_type; ParamKind param_kind; @@ -644,14 +710,14 @@ private: public: MaybeNamedParam (Identifier name, ParamKind param_kind, - std::unique_ptr<Type> param_type, Location locus) - : param_type (std::move (param_type)), param_kind (param_kind), + std::unique_ptr<Type> param_type, std::vector<Attribute> outer_attrs, Location locus) + : outer_attrs (std::move (outer_attrs)), param_type (std::move (param_type)), param_kind (param_kind), name (std::move (name)), locus (locus) {} // Copy constructor with clone MaybeNamedParam (MaybeNamedParam const &other) - : param_kind (other.param_kind), name (other.name), locus (other.locus) + : outer_attrs (other.outer_attrs), param_kind (other.param_kind), name (other.name), locus (other.locus) { // guard to prevent null dereference if (other.param_type != nullptr) @@ -663,6 +729,7 @@ public: // Overloaded assignment operator with clone MaybeNamedParam &operator= (MaybeNamedParam const &other) { + outer_attrs = other.outer_attrs; name = other.name; param_kind = other.param_kind; locus = other.locus; @@ -688,10 +755,20 @@ public: // Creates an error state param. static MaybeNamedParam create_error () { - return MaybeNamedParam ("", UNNAMED, nullptr, Location ()); + return MaybeNamedParam ("", UNNAMED, nullptr, {}, Location ()); } Location get_locus () const { return locus; } + + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } + + // TODO: would a "vis_type" be better? + std::unique_ptr<Type> &get_type () { + rust_assert (param_type != nullptr); + return param_type; + } }; /* A function pointer type - can be created via coercion from function items and @@ -705,6 +782,7 @@ class BareFunctionType : public TypeNoBounds FunctionQualifiers function_qualifiers; std::vector<MaybeNamedParam> params; bool is_variadic; + std::vector<Attribute> variadic_attrs; // bool has_return_type; // BareFunctionReturnType return_type; @@ -721,19 +799,22 @@ public: BareFunctionType (std::vector<LifetimeParam> lifetime_params, FunctionQualifiers qualifiers, - std::vector<MaybeNamedParam> named_params, bool is_variadic, + std::vector<MaybeNamedParam> named_params, bool is_variadic, std::vector<Attribute> variadic_attrs, std::unique_ptr<TypeNoBounds> type, Location locus) : for_lifetimes (std::move (lifetime_params)), function_qualifiers (std::move (qualifiers)), params (std::move (named_params)), is_variadic (is_variadic), - return_type (std::move (type)), locus (locus) - {} + variadic_attrs (std::move (variadic_attrs)), return_type (std::move (type)), locus (locus) + { + if (!variadic_attrs.empty()) + is_variadic = true; + } // Copy constructor with clone BareFunctionType (BareFunctionType const &other) : for_lifetimes (other.for_lifetimes), function_qualifiers (other.function_qualifiers), params (other.params), - is_variadic (other.is_variadic), locus (other.locus) + is_variadic (other.is_variadic), variadic_attrs (other.variadic_attrs), locus (other.locus) { // guard to prevent null dereference if (other.return_type != nullptr) @@ -747,6 +828,7 @@ public: function_qualifiers = other.function_qualifiers; params = other.params; is_variadic = other.is_variadic; + variadic_attrs = other.variadic_attrs; locus = other.locus; // guard to prevent null dereference @@ -769,6 +851,16 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: this mutable getter seems kinda dodgy + std::vector<MaybeNamedParam> &get_function_params () { return params; } + const std::vector<MaybeNamedParam> &get_function_params () const { return params; } + + // TODO: would a "vis_type" be better? + std::unique_ptr<TypeNoBounds> &get_return_type () { + rust_assert (has_return_type ()); + return return_type; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index d684c7d..3691f9e 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -88,21 +88,21 @@ bool Compilation::compileVarDecl (Bfunction *fndecl, AST::LetStmt *stmt, std::vector<Bvariable *> &vars) { - AST::Type *type = stmt->has_type () ? stmt->type.get () : stmt->inferedType; + AST::Type *type = stmt->has_type () ? stmt->get_type ().get () : stmt->inferedType; translatedType = NULL; type->accept_vis (*this); if (translatedType == NULL) { - rust_error_at (stmt->locus, "failed to compile type for var decl"); + rust_error_at (stmt->get_locus (), "failed to compile type for var decl"); return false; } - stmt->variables_pattern->accept_vis (*this); + stmt->get_pattern ()->accept_vis (*this); for (auto &pattern : patternBuffer) { auto var = backend->local_variable (fndecl, pattern.get_ident (), translatedType, NULL /*decl_var*/, - false /*address_taken*/, stmt->locus); + false /*address_taken*/, stmt->get_locus ()); vars.push_back (var); scope.InsertVar (pattern.get_ident (), var); } @@ -1298,7 +1298,7 @@ Compilation::visit (AST::LetStmt &stmt) if (!stmt.has_init_expr ()) return; - stmt.variables_pattern->accept_vis (*this); + stmt.get_pattern ()->accept_vis (*this); for (auto &pattern : patternBuffer) { Bvariable *var = NULL; diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 2fe84cb..95fb962 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -2349,6 +2349,7 @@ namespace Rust { } } + // I don't think it would be possible to strip macros without expansion void visit(AST::MacroMatchFragment& match) override {} void visit(AST::MacroMatchRepetition& match) override {} void visit(AST::MacroMatcher& matcher) override {} @@ -2401,13 +2402,23 @@ namespace Rust { // not possible } void visit(AST::RangePatternBoundPath& bound) override { - // TODO: maybe possible if path is possible + // can expand path, but not strip it directly + auto& path = bound.get_path(); + visit(path); + if (path.is_marked_for_strip()) + rust_error_at(path.get_locus(), "cannot strip path in this position"); } void visit(AST::RangePatternBoundQualPath& bound) override { - // TODO: maybe possible if path is possible + // can expand path, but not strip it directly + auto& path = bound.get_qualified_path(); + visit(path); + if (path.is_marked_for_strip()) + rust_error_at(path.get_locus(), "cannot strip path in this position"); } void visit(AST::RangePattern& pattern) override { - // TODO: possible if any bounds are possible + // 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 visit(AST::ReferencePattern& pattern) override { auto& sub_pattern = pattern.get_referenced_pattern(); @@ -2452,6 +2463,12 @@ namespace Rust { } } void visit(AST::StructPattern& pattern) override { + // expand (but don't strip) path + auto& path = pattern.get_path(); + visit(path); + if (path.is_marked_for_strip()) + rust_error_at(path.get_locus(), "cannot strip path in this position"); + // TODO: apparently struct pattern fields can have outer attrs. so can they be stripped? if (!pattern.has_struct_pattern_elems()) return; @@ -2506,7 +2523,11 @@ namespace Rust { } } void visit(AST::TupleStructPattern& pattern) override { - // TODO: stripping of path? + // expand (but don't strip) path + auto& path = pattern.get_path(); + visit(path); + 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); @@ -2578,6 +2599,14 @@ namespace Rust { pattern->accept_vis(*this); if (pattern->is_marked_for_strip()) rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position"); + + // similar for type + 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_slow(), "cannot strip type in this position"); + } /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be @@ -2621,25 +2650,123 @@ namespace Rust { } } - // stripping shouldn't be required or possible for types - 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::TraitBound& bound) override { + // nothing in for lifetimes to strip + + // expand but don't strip type path + auto& path = bound.get_type_path(); + visit(path); + if (path.is_marked_for_strip()) + rust_error_at(path.get_locus(), "cannot strip type path in this position"); + } + void visit(AST::ImplTraitType& type) override { + // don't strip directly, only components of bounds + for (auto& bound : type.get_type_param_bounds()) + bound->accept_vis(*this); + } + void visit(AST::TraitObjectType& type) override { + // don't strip directly, only components of bounds + for (auto& bound : type.get_type_param_bounds()) + bound->accept_vis(*this); + } + void visit(AST::ParenthesisedType& type) override { + // 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_slow(), "cannot strip type in this position"); + } + void visit(AST::ImplTraitTypeOneBound& type) override { + // no stripping possible + visit(type.get_trait_bound()); + } + void visit(AST::TraitObjectTypeOneBound& type) override { + // no stripping possible + visit(type.get_trait_bound()); + } + void visit(AST::TupleType& type) override { + // 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_slow(), "cannot strip type in this position"); + } + } + void visit(AST::NeverType& type) override { + // no stripping possible + } + void visit(AST::RawPointerType& type) override { + // 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_slow(), "cannot strip type in this position"); + } + void visit(AST::ReferenceType& type) override { + // 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_slow(), "cannot strip type in this position"); + } void visit(AST::ArrayType& type) override { - // TODO: array type contains a "constant expression" - could this have strippable sub-exprs? + // 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_slow(), "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_slow(), "cannot strip expression in this position"); + } + void visit(AST::SliceType& type) override { + // 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_slow(), "cannot strip type in this position"); + } + void visit(AST::InferredType& type) override { + // none possible } - void visit(AST::SliceType& type) override {} - void visit(AST::InferredType& type) override {} void visit(AST::BareFunctionType& type) override { - // TODO: bare function type contains "maybe-named params" that have outer attributes - could this be strippable? - // apparently "attribute rules are same as on regular function params", so looks like a yes + // seem to be no generics + + // presumably function params can be stripped + auto& params = type.get_function_params(); + for (int i = 0; i < params.size();) { + auto& param = params[i]; + + auto& param_attrs = param.get_outer_attrs(); + expander.expand_cfg_attrs(param_attrs); + if (expander.fails_cfg(param_attrs)) { + params.erase(params.begin() + i); + continue; + } + + auto& type = param.get_type(); + type->accept_vis(*this); + if (type->is_marked_for_strip()) + rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); + + // increment if nothing else happens + i++; + } + + /* TODO: assuming that variadic nature cannot be stripped. If this + * is not true, then have code here to do so. */ + + if (type.has_return_type()) { + 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_slow(), "cannot strip type in this position"); + } + + // no where clause, apparently } }; diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 88252ac..3315da3 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -9205,7 +9205,7 @@ Parser<ManagedTokenSource>::parse_for_prefixed_type () // Parses a maybe named param used in bare function types. template <typename ManagedTokenSource> AST::MaybeNamedParam -Parser<ManagedTokenSource>::parse_maybe_named_param () +Parser<ManagedTokenSource>::parse_maybe_named_param (std::vector<AST::Attribute> outer_attrs) { /* Basically guess that param is named if first token is identifier or * underscore and second token is semicolon. This should probably have no @@ -9242,7 +9242,7 @@ Parser<ManagedTokenSource>::parse_maybe_named_param () } return AST::MaybeNamedParam (std::move (name), kind, std::move (type), - current->get_locus ()); + std::move (outer_attrs), current->get_locus ()); } /* Parses a bare function type (with the given for lifetimes for convenience - @@ -9258,63 +9258,58 @@ Parser<ManagedTokenSource>::parse_bare_function_type ( AST::FunctionQualifiers qualifiers = parse_function_qualifiers (); if (!skip_token (FN_TOK)) - { return nullptr; - } if (!skip_token (LEFT_PAREN)) - { return nullptr; - } // parse function params, if they exist std::vector<AST::MaybeNamedParam> params; bool is_variadic = false; - const_TokenPtr t = lexer.peek_token (); - while (t->get_id () != RIGHT_PAREN) - { - // handle ellipsis (only if next character is right paren) - if (t->get_id () == ELLIPSIS) - { - if (lexer.peek_token (1)->get_id () == RIGHT_PAREN) - { - lexer.skip_token (); - is_variadic = true; - break; - } - else - { - rust_error_at (t->get_locus (), - "ellipsis (for variadic) can only go at end of " - "bare function type"); - return nullptr; - } - } + std::vector<AST::Attribute> variadic_attrs; - // parse required param - AST::MaybeNamedParam param = parse_maybe_named_param (); - if (param.is_error ()) - { - rust_error_at ( - t->get_locus (), - "failed to parse maybe named param in bare function type"); - return nullptr; - } - params.push_back (std::move (param)); + const_TokenPtr t = lexer.peek_token (); + while (t->get_id () != RIGHT_PAREN) + { + std::vector<AST::Attribute> temp_attrs = parse_outer_attributes (); - if (lexer.peek_token ()->get_id () != COMMA) - { - break; - } + if (lexer.peek_token ()->get_id () == ELLIPSIS) + { lexer.skip_token (); + is_variadic = true; + variadic_attrs = std::move (temp_attrs); t = lexer.peek_token (); + + if (t->get_id() != RIGHT_PAREN) + { + rust_error_at (t->get_locus (), + "expected right parentheses after variadic in maybe named function " + "parameters, found %qs", + t->get_token_description ()); + return nullptr; + } + + break; } - if (!skip_token (RIGHT_PAREN)) + AST::MaybeNamedParam param = parse_maybe_named_param (std::move (temp_attrs)); + if (param.is_error ()) { + rust_error_at (lexer.peek_token ()->get_locus (), "failed to parse maybe named param in bare function type"); return nullptr; } + params.push_back (std::move (param)); + + if (lexer.peek_token ()->get_id () != COMMA) + break; + + lexer.skip_token (); + t = lexer.peek_token (); + } + + if (!skip_token (RIGHT_PAREN)) + return nullptr; // bare function return type, if exists std::unique_ptr<AST::TypeNoBounds> return_type = nullptr; @@ -9335,7 +9330,7 @@ Parser<ManagedTokenSource>::parse_bare_function_type ( return std::unique_ptr<AST::BareFunctionType> (new AST::BareFunctionType ( std::move (for_lifetimes), std::move (qualifiers), std::move (params), - is_variadic, std::move (return_type), best_try_locus)); + is_variadic, std::move (variadic_attrs), std::move (return_type), best_try_locus)); } // Parses a reference type (mutable or immutable, with given lifetime). diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index a6de87b..7218ebc 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -545,7 +545,7 @@ private: std::unique_ptr<AST::Type> parse_paren_prefixed_type (); std::unique_ptr<AST::TypeNoBounds> parse_paren_prefixed_type_no_bounds (); std::unique_ptr<AST::Type> parse_for_prefixed_type (); - AST::MaybeNamedParam parse_maybe_named_param (); + AST::MaybeNamedParam parse_maybe_named_param (std::vector<AST::Attribute> outer_attrs); // Statement-related std::unique_ptr<AST::Stmt> parse_stmt (); |