aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorSimplyTheOther <simplytheother@gmail.com>2020-12-07 19:51:24 +0800
committerSimplyTheOther <simplytheother@gmail.com>2020-12-08 21:10:36 +0800
commitc7080f178a637cad04e196a404d5d44bb33189af (patch)
treea023eeee3f2c3ab85190e4967cfe0599b466843e /gcc
parentdb39766514144dbbad34d9db3977c3a72d1216c3 (diff)
downloadgcc-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.cc2
-rw-r--r--gcc/rust/ast/rust-item.h20
-rw-r--r--gcc/rust/ast/rust-pattern.h25
-rw-r--r--gcc/rust/ast/rust-stmt.h7
-rw-r--r--gcc/rust/ast/rust-type.h108
-rw-r--r--gcc/rust/backend/rust-compile.cc10
-rw-r--r--gcc/rust/expand/rust-macro-expand.cc167
-rw-r--r--gcc/rust/parse/rust-parse-impl.h79
-rw-r--r--gcc/rust/parse/rust-parse.h2
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 ();