diff options
Diffstat (limited to 'gcc/rust/ast')
-rw-r--r-- | gcc/rust/ast/rust-ast-builder-type.cc | 164 | ||||
-rw-r--r-- | gcc/rust/ast/rust-ast-builder-type.h | 57 | ||||
-rw-r--r-- | gcc/rust/ast/rust-ast-builder.cc | 201 | ||||
-rw-r--r-- | gcc/rust/ast/rust-ast-builder.h | 17 | ||||
-rw-r--r-- | gcc/rust/ast/rust-ast-collector.cc | 14 | ||||
-rw-r--r-- | gcc/rust/ast/rust-ast-collector.h | 2 | ||||
-rw-r--r-- | gcc/rust/ast/rust-ast-full-decls.h | 4 | ||||
-rw-r--r-- | gcc/rust/ast/rust-ast-visitor.cc | 52 | ||||
-rw-r--r-- | gcc/rust/ast/rust-ast-visitor.h | 6 | ||||
-rw-r--r-- | gcc/rust/ast/rust-ast.cc | 4 | ||||
-rw-r--r-- | gcc/rust/ast/rust-ast.h | 27 | ||||
-rw-r--r-- | gcc/rust/ast/rust-expr.h | 196 | ||||
-rw-r--r-- | gcc/rust/ast/rust-item.h | 2 | ||||
-rw-r--r-- | gcc/rust/ast/rust-path.cc | 28 | ||||
-rw-r--r-- | gcc/rust/ast/rust-path.h | 274 | ||||
-rw-r--r-- | gcc/rust/ast/rust-pattern.h | 2 | ||||
-rw-r--r-- | gcc/rust/ast/rust-type.h | 10 |
17 files changed, 942 insertions, 118 deletions
diff --git a/gcc/rust/ast/rust-ast-builder-type.cc b/gcc/rust/ast/rust-ast-builder-type.cc new file mode 100644 index 0000000..e76d0de --- /dev/null +++ b/gcc/rust/ast/rust-ast-builder-type.cc @@ -0,0 +1,164 @@ +// Copyright (C) 2020-2024 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 +// <http://www.gnu.org/licenses/>. + +#include "rust-ast-builder-type.h" +#include "rust-ast-builder.h" +#include "rust-ast-full.h" +#include "rust-common.h" +#include "rust-make-unique.h" + +namespace Rust { +namespace AST { + +ASTTypeBuilder::ASTTypeBuilder () : translated (nullptr) {} + +Type * +ASTTypeBuilder::build (Type &type) +{ + ASTTypeBuilder builder; + type.accept_vis (builder); + rust_assert (builder.translated != nullptr); + return builder.translated; +} + +void +ASTTypeBuilder::visit (BareFunctionType &fntype) +{ + /* TODO */ +} + +void +ASTTypeBuilder::visit (TupleType &tuple) +{ + std::vector<std::unique_ptr<Type> > elems; + for (auto &elem : tuple.get_elems ()) + { + Type *t = ASTTypeBuilder::build (*elem.get ()); + std::unique_ptr<Type> ty (t); + elems.push_back (std::move (ty)); + } + translated = new TupleType (std::move (elems), tuple.get_locus ()); +} + +void +ASTTypeBuilder::visit (TypePath &path) +{ + std::vector<std::unique_ptr<TypePathSegment> > segments; + for (auto &seg : path.get_segments ()) + { + switch (seg->get_type ()) + { + case TypePathSegment::REG: { + const TypePathSegment &segment + = (const TypePathSegment &) (*seg.get ()); + TypePathSegment *s + = new TypePathSegment (segment.get_ident_segment (), + segment.get_separating_scope_resolution (), + segment.get_locus ()); + std::unique_ptr<TypePathSegment> sg (s); + segments.push_back (std::move (sg)); + } + break; + + case TypePathSegment::GENERIC: { + TypePathSegmentGeneric &generic + = (TypePathSegmentGeneric &) (*seg.get ()); + + GenericArgs args + = Builder::new_generic_args (generic.get_generic_args ()); + TypePathSegmentGeneric *s + = new TypePathSegmentGeneric (generic.get_ident_segment (), false, + std::move (args), + generic.get_locus ()); + std::unique_ptr<TypePathSegment> sg (s); + segments.push_back (std::move (sg)); + } + break; + + case TypePathSegment::FUNCTION: { + rust_unreachable (); + // TODO + // const TypePathSegmentFunction &fn + // = (const TypePathSegmentFunction &) (*seg.get ()); + } + break; + } + } + + translated = new TypePath (std::move (segments), path.get_locus (), + path.has_opening_scope_resolution_op ()); +} + +void +ASTTypeBuilder::visit (QualifiedPathInType &path) +{ + /* TODO */ +} + +void +ASTTypeBuilder::visit (ArrayType &type) +{ + /* TODO */ +} + +void +ASTTypeBuilder::visit (ReferenceType &type) +{ + /* TODO */ +} + +void +ASTTypeBuilder::visit (RawPointerType &type) +{ + /* TODO */ +} + +void +ASTTypeBuilder::visit (SliceType &type) +{ + Type *t = ASTTypeBuilder::build (type.get_elem_type ()); + std::unique_ptr<Type> ty (t); + translated = new SliceType (std::move (ty), type.get_locus ()); +} + +void +ASTTypeBuilder::visit (InferredType &type) +{ + translated = new InferredType (type.get_locus ()); +} + +void +ASTTypeBuilder::visit (NeverType &type) +{ + translated = new NeverType (type.get_locus ()); +} + +void +ASTTypeBuilder::visit (TraitObjectTypeOneBound &type) +{ + /* TODO */ +} + +void +ASTTypeBuilder::visit (TraitObjectType &type) +{ + /* TODO */ +} + +} // namespace AST +} // namespace Rust diff --git a/gcc/rust/ast/rust-ast-builder-type.h b/gcc/rust/ast/rust-ast-builder-type.h new file mode 100644 index 0000000..b67ae3b --- /dev/null +++ b/gcc/rust/ast/rust-ast-builder-type.h @@ -0,0 +1,57 @@ +// Copyright (C) 2020-2024 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 +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_BUILDER_TYPE +#define RUST_AST_BUILDER_TYPE + +#include "rust-ast-visitor.h" + +namespace Rust { +namespace AST { + +class ASTTypeBuilder : public DefaultASTVisitor +{ +protected: + using DefaultASTVisitor::visit; + +public: + static Type *build (Type &type); + + void visit (BareFunctionType &fntype) override; + void visit (TupleType &tuple) override; + void visit (TypePath &path) override; + void visit (QualifiedPathInType &path) override; + void visit (ArrayType &type) override; + void visit (ReferenceType &type) override; + void visit (RawPointerType &type) override; + void visit (SliceType &type) override; + void visit (InferredType &type) override; + void visit (NeverType &type) override; + void visit (TraitObjectTypeOneBound &type) override; + void visit (TraitObjectType &type) override; + +private: + ASTTypeBuilder (); + + Type *translated; +}; + +} // namespace AST +} // namespace Rust + +#endif // RUST_AST_BUILDER_TYPE diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc index 4679aa7..529c686 100644 --- a/gcc/rust/ast/rust-ast-builder.cc +++ b/gcc/rust/ast/rust-ast-builder.cc @@ -17,8 +17,7 @@ // <http://www.gnu.org/licenses/>. #include "rust-ast-builder.h" -#include "rust-ast-full-decls.h" -#include "rust-ast-full.h" +#include "rust-ast-builder-type.h" #include "rust-common.h" #include "rust-expr.h" #include "rust-token.h" @@ -83,6 +82,13 @@ Builder::type_path_segment (std::string seg) const new TypePathSegment (seg, false, loc)); } +std::unique_ptr<TypePathSegment> +Builder::generic_type_path_segment (std::string seg, GenericArgs args) const +{ + return std::unique_ptr<TypePathSegment> ( + new TypePathSegmentGeneric (PathIdentSegment (seg, loc), false, args, loc)); +} + std::unique_ptr<Type> Builder::single_type_path (std::string type) const { @@ -92,6 +98,15 @@ Builder::single_type_path (std::string type) const return std::unique_ptr<Type> (new TypePath (std::move (segments), loc)); } +std::unique_ptr<Type> +Builder::single_generic_type_path (std::string type, GenericArgs args) const +{ + auto segments = std::vector<std::unique_ptr<TypePathSegment>> (); + segments.emplace_back (generic_type_path_segment (type, args)); + + return std::unique_ptr<Type> (new TypePath (std::move (segments), loc)); +} + PathInExpression Builder::path_in_expression (std::vector<std::string> &&segments) const { @@ -174,5 +189,187 @@ Builder::wildcard () const return std::unique_ptr<Pattern> (new WildcardPattern (loc)); } +std::unique_ptr<Type> +Builder::new_type (Type &type) +{ + Type *t = ASTTypeBuilder::build (type); + return std::unique_ptr<Type> (t); +} + +std::unique_ptr<GenericParam> +Builder::new_lifetime_param (LifetimeParam ¶m) +{ + Lifetime l = new_lifetime (param.get_lifetime ()); + std::vector<Lifetime> lifetime_bounds; + for (auto b : param.get_lifetime_bounds ()) + { + Lifetime bl = new_lifetime (b); + lifetime_bounds.push_back (bl); + } + + auto p = new LifetimeParam (l, std::move (lifetime_bounds), + param.get_outer_attrs (), param.get_locus ()); + return std::unique_ptr<GenericParam> (p); +} + +std::unique_ptr<GenericParam> +Builder::new_type_param (TypeParam ¶m) +{ + location_t locus = param.get_locus (); + AST::AttrVec outer_attrs = param.get_outer_attrs (); + Identifier type_representation = param.get_type_representation (); + std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds; + std::unique_ptr<Type> type = nullptr; + + if (param.has_type ()) + type = new_type (param.get_type ()); + + for (const auto &b : param.get_type_param_bounds ()) + { + switch (b->get_bound_type ()) + { + case TypeParamBound::TypeParamBoundType::TRAIT: { + const TraitBound &tb = (const TraitBound &) *b.get (); + const TypePath &path = tb.get_type_path (); + + std::vector<LifetimeParam> for_lifetimes; + for (const auto &lifetime : tb.get_for_lifetimes ()) + { + std::vector<Lifetime> lifetime_bounds; + for (const auto &b : lifetime.get_lifetime_bounds ()) + { + Lifetime bl = new_lifetime (b); + lifetime_bounds.push_back (std::move (bl)); + } + + Lifetime nl = new_lifetime (lifetime.get_lifetime ()); + LifetimeParam p (std::move (nl), std::move (lifetime_bounds), + {}, lifetime.get_locus ()); + for_lifetimes.push_back (std::move (p)); + } + + std::vector<std::unique_ptr<TypePathSegment>> segments; + for (auto &seg : path.get_segments ()) + { + switch (seg->get_type ()) + { + case TypePathSegment::REG: { + const TypePathSegment &segment + = (const TypePathSegment &) (*seg.get ()); + TypePathSegment *s = new TypePathSegment ( + segment.get_ident_segment (), + segment.get_separating_scope_resolution (), + segment.get_locus ()); + std::unique_ptr<TypePathSegment> sg (s); + segments.push_back (std::move (sg)); + } + break; + + case TypePathSegment::GENERIC: { + TypePathSegmentGeneric &generic + = (TypePathSegmentGeneric &) (*seg.get ()); + + GenericArgs args + = new_generic_args (generic.get_generic_args ()); + TypePathSegmentGeneric *s = new TypePathSegmentGeneric ( + generic.get_ident_segment (), false, std::move (args), + generic.get_locus ()); + std::unique_ptr<TypePathSegment> sg (s); + segments.push_back (std::move (sg)); + } + break; + + case TypePathSegment::FUNCTION: { + rust_unreachable (); + // TODO + // const TypePathSegmentFunction &fn + // = (const TypePathSegmentFunction &) (*seg.get ()); + } + break; + } + } + + TypePath p (std::move (segments), path.get_locus (), + path.has_opening_scope_resolution_op ()); + + TraitBound *b = new TraitBound (std::move (p), tb.get_locus (), + tb.is_in_parens (), + tb.has_opening_question_mark (), + std::move (for_lifetimes)); + std::unique_ptr<TypeParamBound> bound (b); + type_param_bounds.push_back (std::move (bound)); + } + break; + + case TypeParamBound::TypeParamBoundType::LIFETIME: { + const Lifetime &l = (const Lifetime &) *b.get (); + + auto bl = new Lifetime (l.get_lifetime_type (), + l.get_lifetime_name (), l.get_locus ()); + std::unique_ptr<TypeParamBound> bound (bl); + type_param_bounds.push_back (std::move (bound)); + } + break; + } + } + + auto type_param + = new TypeParam (type_representation, locus, std::move (type_param_bounds), + std::move (type), std::move (outer_attrs)); + + return std::unique_ptr<GenericParam> (type_param); +} + +Lifetime +Builder::new_lifetime (const Lifetime &lifetime) +{ + return Lifetime (lifetime.get_lifetime_type (), lifetime.get_lifetime_name (), + lifetime.get_locus ()); +} + +GenericArgs +Builder::new_generic_args (GenericArgs &args) +{ + std::vector<Lifetime> lifetime_args; + std::vector<GenericArg> generic_args; + std::vector<GenericArgsBinding> binding_args; + location_t locus = args.get_locus (); + + for (const auto &lifetime : args.get_lifetime_args ()) + { + Lifetime l = new_lifetime (lifetime); + lifetime_args.push_back (std::move (l)); + } + + for (auto &binding : args.get_binding_args ()) + { + Type &t = *binding.get_type_ptr ().get (); + std::unique_ptr<Type> ty = new_type (t); + GenericArgsBinding b (binding.get_identifier (), std::move (ty), + binding.get_locus ()); + binding_args.push_back (std::move (b)); + } + + for (auto &arg : args.get_generic_args ()) + { + switch (arg.get_kind ()) + { + case GenericArg::Kind::Type: { + std::unique_ptr<Type> ty = new_type (arg.get_type ()); + GenericArg arg = GenericArg::create_type (std::move (ty)); + } + break; + + default: + // FIXME + rust_unreachable (); + break; + } + } + + return GenericArgs (std::move (lifetime_args), std::move (generic_args), + std::move (binding_args), locus); +} + } // namespace AST } // namespace Rust diff --git a/gcc/rust/ast/rust-ast-builder.h b/gcc/rust/ast/rust-ast-builder.h index aed71e7..bad79d0 100644 --- a/gcc/rust/ast/rust-ast-builder.h +++ b/gcc/rust/ast/rust-ast-builder.h @@ -82,10 +82,16 @@ public: /* And similarly for type path segments */ std::unique_ptr<TypePathSegment> type_path_segment (std::string seg) const; + std::unique_ptr<TypePathSegment> + generic_type_path_segment (std::string seg, GenericArgs args) const; + /* Create a Type from a single string - the most basic kind of type in our AST */ std::unique_ptr<Type> single_type_path (std::string type) const; + std::unique_ptr<Type> single_generic_type_path (std::string type, + GenericArgs args) const; + /** * Create a path in expression from multiple segments (`Clone::clone`). You * do not need to separate the segments using `::`, you can simply provide a @@ -116,6 +122,17 @@ public: /* Create a wildcard pattern (`_`) */ std::unique_ptr<Pattern> wildcard () const; + static std::unique_ptr<Type> new_type (Type &type); + + static std::unique_ptr<GenericParam> + new_lifetime_param (LifetimeParam ¶m); + + static std::unique_ptr<GenericParam> new_type_param (TypeParam ¶m); + + static Lifetime new_lifetime (const Lifetime &lifetime); + + static GenericArgs new_generic_args (GenericArgs &args); + private: /** * Location of the generated AST nodes diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index 6980fef..2022668 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -21,6 +21,7 @@ #include "rust-expr.h" #include "rust-item.h" #include "rust-keyword-values.h" +#include "rust-system.h" #include "rust-token.h" namespace Rust { @@ -561,6 +562,19 @@ TokenCollector::visit (PathInExpression &path) } void +TokenCollector::visit (RegularPath &path) +{ + // FIXME: We probably want to have a proper implementation here, and call this + // function from things like the PathInExpression visitor +} + +void +TokenCollector::visit (LangItemPath &path) +{ + // TODO: Implement proper token collection for lang item paths +} + +void TokenCollector::visit (TypePathSegment &segment) { // Syntax: diff --git a/gcc/rust/ast/rust-ast-collector.h b/gcc/rust/ast/rust-ast-collector.h index b2dc41b..32a5bd3 100644 --- a/gcc/rust/ast/rust-ast-collector.h +++ b/gcc/rust/ast/rust-ast-collector.h @@ -234,6 +234,8 @@ public: void visit (PathExprSegment &segment); void visit (PathIdentSegment &segment); void visit (PathInExpression &path); + void visit (RegularPath &path); + void visit (LangItemPath &path); void visit (TypePathSegment &segment); void visit (TypePathSegmentGeneric &segment); void visit (TypePathSegmentFunction &segment); diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h index d2ba876..80d217e 100644 --- a/gcc/rust/ast/rust-ast-full-decls.h +++ b/gcc/rust/ast/rust-ast-full-decls.h @@ -61,7 +61,7 @@ class PathIdentSegment; struct GenericArgsBinding; struct GenericArgs; class PathExprSegment; -class PathPattern; +class Path; class PathInExpression; class TypePathSegment; class TypePathSegmentGeneric; @@ -148,7 +148,7 @@ class AsyncBlockExpr; enum class InlineAsmOption; struct AnonConst; struct InlineAsmRegOrRegClass; -struct InlineAsmOperand; +class InlineAsmOperand; struct InlineAsmPlaceHolder; struct InlineAsmTemplatePiece; struct TupleClobber; diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index 866357b..8f53e52 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -86,6 +86,17 @@ DefaultASTVisitor::visit (AST::ConstGenericParam &const_param) } void +DefaultASTVisitor::visit (AST::RegularPath &path) +{ + for (auto &segment : path.get_segments ()) + visit (segment); +} + +void +DefaultASTVisitor::visit (AST::LangItemPath &path) +{} + +void DefaultASTVisitor::visit (AST::PathInExpression &path) { visit_outer_attrs (path); @@ -664,7 +675,46 @@ DefaultASTVisitor::visit (AST::AsyncBlockExpr &expr) void DefaultASTVisitor::visit (AST::InlineAsm &expr) -{} +{ + visit_outer_attrs (expr); + using RegisterType = AST::InlineAsmOperand::RegisterType; + for (auto &operand : expr.get_operands ()) + { + switch (operand.get_register_type ()) + { + case RegisterType::In: { + visit (operand.get_in ().expr); + break; + } + case RegisterType::Out: { + visit (operand.get_out ().expr); + break; + } + case RegisterType::InOut: { + visit (operand.get_in_out ().expr); + break; + } + case RegisterType::SplitInOut: { + auto split = operand.get_split_in_out (); + visit (split.in_expr); + visit (split.out_expr); + break; + } + case RegisterType::Const: { + visit (operand.get_const ().anon_const.expr); + break; + } + case RegisterType::Sym: { + visit (operand.get_sym ().expr); + break; + } + case RegisterType::Label: { + visit (operand.get_label ().expr); + break; + } + } + } +} void DefaultASTVisitor::visit (AST::TypeParam ¶m) diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h index 2f56d89..50b9301 100644 --- a/gcc/rust/ast/rust-ast-visitor.h +++ b/gcc/rust/ast/rust-ast-visitor.h @@ -24,6 +24,7 @@ #include "rust-ast-full-decls.h" #include "rust-ast.h" #include "rust-item.h" +#include "rust-path.h" #include "rust-system.h" namespace Rust { @@ -58,6 +59,8 @@ public: // virtual void visit(TraitImplItem& trait_impl_item) = 0; // rust-path.h + virtual void visit (RegularPath &path) = 0; + virtual void visit (LangItemPath &path) = 0; virtual void visit (PathInExpression &path) = 0; virtual void visit (TypePathSegment &segment) = 0; virtual void visit (TypePathSegmentGeneric &segment) = 0; @@ -241,7 +244,6 @@ class DefaultASTVisitor : public ASTVisitor public: virtual void visit (AST::Crate &crate); -protected: virtual void visit (AST::Token &tok) override; virtual void visit (AST::DelimTokenTree &delim_tok_tree) override; virtual void visit (AST::AttrInputMetaItemContainer &input) override; @@ -249,6 +251,8 @@ protected: virtual void visit (AST::Lifetime &lifetime) override; virtual void visit (AST::LifetimeParam &lifetime_param) override; virtual void visit (AST::ConstGenericParam &const_param) override; + virtual void visit (AST::RegularPath &path) override; + virtual void visit (AST::LangItemPath &path) override; virtual void visit (AST::PathInExpression &path) override; virtual void visit (AST::TypePathSegment &segment) override; virtual void visit (AST::TypePathSegmentGeneric &segment) override; diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index bf7d31d..1d52352 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -311,7 +311,8 @@ Attribute::get_traits_to_derive () // Copy constructor must deep copy attr_input as unique pointer Attribute::Attribute (Attribute const &other) - : path (other.path), locus (other.locus) + : path (other.path), locus (other.locus), + inner_attribute (other.inner_attribute) { // guard to protect from null pointer dereference if (other.attr_input != nullptr) @@ -324,6 +325,7 @@ Attribute::operator= (Attribute const &other) { path = other.path; locus = other.locus; + inner_attribute = other.inner_attribute; // guard to protect from null pointer dereference if (other.attr_input != nullptr) attr_input = other.attr_input->clone_attr_input (); diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 4f40eff..42ad011 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -1477,6 +1477,12 @@ protected: class TypeParamBound : public Visitable { public: + enum TypeParamBoundType + { + TRAIT, + LIFETIME + }; + virtual ~TypeParamBound () {} // Unique pointer custom clone function @@ -1491,6 +1497,8 @@ public: virtual location_t get_locus () const = 0; + virtual TypeParamBoundType get_bound_type () const = 0; + protected: // Clone function implementation as pure virtual method virtual TypeParamBound *clone_type_param_bound_impl () const = 0; @@ -1546,12 +1554,17 @@ public: void accept_vis (ASTVisitor &vis) override; - LifetimeType get_lifetime_type () { return lifetime_type; } + LifetimeType get_lifetime_type () const { return lifetime_type; } location_t get_locus () const override final { return locus; } std::string get_lifetime_name () const { return lifetime_name; } + TypeParamBoundType get_bound_type () const override + { + return TypeParamBound::TypeParamBoundType::LIFETIME; + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -1587,7 +1600,7 @@ public: virtual Kind get_kind () const = 0; - NodeId get_node_id () { return node_id; } + NodeId get_node_id () const { return node_id; } protected: GenericParam () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {} @@ -1619,6 +1632,11 @@ public: std::vector<Lifetime> &get_lifetime_bounds () { return lifetime_bounds; } + const std::vector<Lifetime> &get_lifetime_bounds () const + { + return lifetime_bounds; + } + // Returns whether the lifetime param has an outer attribute. bool has_outer_attribute () const { return !outer_attrs.empty (); } @@ -2048,11 +2066,6 @@ public: } }; -// Base path expression AST node - abstract -class PathExpr : public ExprWithoutBlock -{ -}; - } // namespace AST } // namespace Rust diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 9477bf0..438d3d3 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -4768,9 +4768,10 @@ struct InlineAsmRegOrRegClass location_t locus; }; -struct InlineAsmOperand +class InlineAsmOperand { - enum RegisterType +public: + enum class RegisterType { In, Out, @@ -4781,8 +4782,24 @@ struct InlineAsmOperand Label, }; - struct In + class Register + { + public: + Register () {} + virtual ~Register () = default; + + std::unique_ptr<Register> clone () const + { + return std::unique_ptr<Register> (clone_impl ()); + } + + protected: + virtual Register *clone_impl () const = 0; + }; + + class In : public Register { + public: tl::optional<InlineAsmRegOrRegClass> reg; std::unique_ptr<Expr> expr; @@ -4807,10 +4824,14 @@ struct InlineAsmOperand return *this; } + + private: + In *clone_impl () const { return new In (*this); } }; - struct Out + class Out : public Register { + public: tl::optional<InlineAsmRegOrRegClass> reg; bool late; std::unique_ptr<Expr> expr; // can be null @@ -4836,10 +4857,14 @@ struct InlineAsmOperand expr = other.expr->clone_expr (); return *this; } + + private: + Out *clone_impl () const { return new Out (*this); } }; - struct InOut + class InOut : public Register { + public: tl::optional<InlineAsmRegOrRegClass> reg; bool late; std::unique_ptr<Expr> expr; // this can't be null @@ -4866,10 +4891,14 @@ struct InlineAsmOperand return *this; } + + private: + InOut *clone_impl () const { return new InOut (*this); } }; - struct SplitInOut + class SplitInOut : public Register { + public: tl::optional<InlineAsmRegOrRegClass> reg; bool late; std::unique_ptr<Expr> in_expr; @@ -4901,15 +4930,23 @@ struct InlineAsmOperand return *this; } + + private: + SplitInOut *clone_impl () const { return new SplitInOut (*this); } }; - struct Const + class Const : public Register { + public: AnonConst anon_const; + + private: + Const *clone_impl () const { return new Const (*this); } }; - struct Sym + class Sym : public Register { + public: std::unique_ptr<Expr> expr; Sym (std::unique_ptr<Expr> expr) : expr (std::move (expr)) @@ -4926,10 +4963,14 @@ struct InlineAsmOperand expr = std::unique_ptr<Expr> (other.expr->clone_expr ()); return *this; } + + private: + Sym *clone_impl () const { return new Sym (*this); } }; - struct Label + class Label : public Register { + public: std::string label_name; std::unique_ptr<Expr> expr; @@ -4950,76 +4991,127 @@ struct InlineAsmOperand expr = std::unique_ptr<Expr> (other.expr->clone_expr ()); return *this; } - }; - RegisterType register_type; - - tl::optional<struct In> in; - tl::optional<struct Out> out; - tl::optional<struct InOut> in_out; - tl::optional<struct SplitInOut> split_in_out; - tl::optional<struct Const> cnst; - tl::optional<struct Sym> sym; - tl::optional<struct Label> label; + private: + Label *clone_impl () const { return new Label (*this); } + }; - InlineAsmOperand () {} InlineAsmOperand (const InlineAsmOperand &other) - : in (other.in), out (other.out), in_out (other.in_out), - split_in_out (other.split_in_out), cnst (other.cnst), sym (other.sym) + : register_type (other.register_type), locus (other.locus), + reg (other.reg->clone ()) {} - void set_in (const tl::optional<struct In> ®) - { - this->register_type = In; + InlineAsmOperand (const In ®, location_t locus) + : register_type (RegisterType::In), locus (locus), reg (new In (reg)) + {} + InlineAsmOperand (const Out ®, location_t locus) + : register_type (RegisterType::Out), locus (locus), reg (new Out (reg)) + {} + InlineAsmOperand (const InOut ®, location_t locus) + : register_type (RegisterType::InOut), locus (locus), reg (new InOut (reg)) + {} + InlineAsmOperand (const SplitInOut ®, location_t locus) + : register_type (RegisterType::SplitInOut), locus (locus), + reg (new SplitInOut (reg)) + {} + InlineAsmOperand (const Const ®, location_t locus) + : register_type (RegisterType::Const), locus (locus), reg (new Const (reg)) + {} + InlineAsmOperand (const Sym ®, location_t locus) + : register_type (RegisterType::Sym), locus (locus), reg (new Sym (reg)) + {} + InlineAsmOperand (const Label ®, location_t locus) + : register_type (RegisterType::Label), locus (locus), reg (new Label (reg)) + {} - if (reg.has_value ()) - this->in = reg.value (); - } + location_t get_locus () const { return locus; } + RegisterType get_register_type () const { return register_type; } - void set_out (const tl::optional<struct Out> ®) + // Potentially fail immediately if you don't use get_register_type() to + // inspect the RegisterType first before calling the following functions Check + // first + In &get_in () + { + rust_assert (register_type == RegisterType::In); + return static_cast<In &> (*reg); + } + const In &get_in () const { - this->register_type = Out; + rust_assert (register_type == RegisterType::In); + return static_cast<const In &> (*reg); + } - if (reg.has_value ()) - this->out = reg.value (); + Out &get_out () + { + rust_assert (register_type == RegisterType::Out); + return static_cast<Out &> (*reg); + } + const Out &get_out () const + { + rust_assert (register_type == RegisterType::Out); + return static_cast<const Out &> (*reg); } - void set_in_out (const tl::optional<struct InOut> ®) + InOut &get_in_out () + { + rust_assert (register_type == RegisterType::InOut); + return static_cast<InOut &> (*reg); + } + const InOut &get_in_out () const { - this->register_type = InOut; - if (reg.has_value ()) - this->in_out = reg.value (); + rust_assert (register_type == RegisterType::InOut); + return static_cast<const InOut &> (*reg); } - void set_split_in_out (const tl::optional<struct SplitInOut> ®) + SplitInOut &get_split_in_out () { - this->register_type = SplitInOut; - if (reg.has_value ()) - this->split_in_out = reg.value (); + rust_assert (register_type == RegisterType::SplitInOut); + return static_cast<SplitInOut &> (*reg); + } + const SplitInOut &get_split_in_out () const + { + rust_assert (register_type == RegisterType::SplitInOut); + return static_cast<const SplitInOut &> (*reg); } - void set_cnst (const tl::optional<struct Const> ®) + Const &get_const () + { + rust_assert (register_type == RegisterType::Const); + return static_cast<Const &> (*reg); + } + const Const &get_const () const { - this->register_type = Const; - if (reg.has_value ()) - this->cnst = reg.value (); + rust_assert (register_type == RegisterType::Const); + return static_cast<Const &> (*reg); } - void set_sym (const tl::optional<struct Sym> ®) + Sym &get_sym () + { + rust_assert (register_type == RegisterType::Sym); + return static_cast<Sym &> (*reg); + } + const Sym &get_sym () const { - this->register_type = Sym; - if (reg.has_value ()) - this->sym = reg.value (); + rust_assert (register_type == RegisterType::Sym); + return static_cast<const Sym &> (*reg); } - void set_label (const tl::optional<struct Label> ®) + Label &get_label () { - this->register_type = Label; - if (reg.has_value ()) - this->label = reg.value (); + rust_assert (register_type == RegisterType::Label); + return static_cast<Label &> (*reg); } + const Label &get_label () const + { + rust_assert (register_type == RegisterType::Label); + return static_cast<const Label &> (*reg); + } + +private: + RegisterType register_type; location_t locus; + std::unique_ptr<Register> reg; }; struct InlineAsmPlaceHolder diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index bd9113f..2ae7c44 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -1213,7 +1213,7 @@ public: std::string as_string () const override; - NewBindType get_new_bind_type () { return bind_type; } + NewBindType get_new_bind_type () const { return bind_type; } void accept_vis (ASTVisitor &vis) override; diff --git a/gcc/rust/ast/rust-path.cc b/gcc/rust/ast/rust-path.cc index 3aaf263..06c98cd 100644 --- a/gcc/rust/ast/rust-path.cc +++ b/gcc/rust/ast/rust-path.cc @@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ +#include "rust-path.h" #include "rust-system.h" #include "rust-ast-full.h" #include "rust-diagnostics.h" @@ -135,7 +136,7 @@ PathExprSegment::as_string () const } std::string -PathPattern::as_string () const +RegularPath::as_string () const { std::string str; @@ -148,8 +149,15 @@ PathPattern::as_string () const return str; } +std::string +LangItemPath::as_string () const +{ + // FIXME: Handle #[lang] paths + rust_unreachable (); +} + SimplePath -PathPattern::convert_to_simple_path (bool with_opening_scope_resolution) const +RegularPath::convert_to_simple_path (bool with_opening_scope_resolution) const { if (!has_segments ()) return SimplePath::create_empty (); @@ -184,6 +192,18 @@ PathPattern::convert_to_simple_path (bool with_opening_scope_resolution) const } void +RegularPath::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + +void +LangItemPath::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + +void PathInExpression::accept_vis (ASTVisitor &vis) { vis.visit (*this); @@ -197,7 +217,7 @@ PathInExpression::as_string () const if (has_opening_scope_resolution) str = "::"; - return str + PathPattern::as_string (); + return str + path->as_string (); } std::string @@ -297,7 +317,7 @@ TypePathFunction::as_string () const std::string QualifiedPathInExpression::as_string () const { - return path_type.as_string () + "::" + PathPattern::as_string (); + return path_type.as_string () + "::" + path->as_string (); } std::string diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index b20f31c..98fde5a 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -22,6 +22,9 @@ * for virtually all AST-related functionality. */ #include "rust-ast.h" +#include "rust-hir-map.h" +#include "rust-mapping-common.h" +#include "rust-system.h" #include "system.h" namespace Rust { @@ -476,15 +479,23 @@ public: std::string as_string () const; - // TODO: is this better? Or is a "vis_pattern" better? std::vector<GenericArg> &get_generic_args () { return generic_args; } - // TODO: is this better? Or is a "vis_pattern" better? std::vector<GenericArgsBinding> &get_binding_args () { return binding_args; } + const std::vector<GenericArgsBinding> &get_binding_args () const + { + return binding_args; + } + std::vector<Lifetime> &get_lifetime_args () { return lifetime_args; }; - location_t get_locus () { return locus; } + const std::vector<Lifetime> &get_lifetime_args () const + { + return lifetime_args; + }; + + location_t get_locus () const { return locus; } }; /* A segment of a path in expression, including an identifier aspect and maybe @@ -565,51 +576,114 @@ public: // AST node representing a pattern that involves a "path" - abstract base // class -class PathPattern : public Pattern +class Path : public Pattern { - std::vector<PathExprSegment> segments; +public: + enum class Kind + { + LangItem, + Regular, + }; + + virtual Kind get_path_kind () const = 0; + + Pattern::Kind get_pattern_kind () override final + { + return Pattern::Kind::Path; + } + + location_t get_locus () const override final { return locus; } + NodeId get_node_id () const override final { return node_id; } + + std::unique_ptr<Path> clone_path () + { + return std::unique_ptr<Path> (clone_path_impl ()); + } + + Pattern *clone_pattern_impl () const override final + { + return clone_path_impl (); + } protected: - PathPattern (std::vector<PathExprSegment> segments) - : segments (std::move (segments)) + location_t locus; + NodeId node_id; + + Path (location_t locus, NodeId node_id) : locus (locus), node_id (node_id) {} + + virtual Path *clone_path_impl () const = 0; +}; + +class RegularPath : public Path +{ + std::vector<PathExprSegment> segments; + +public: + explicit RegularPath (std::vector<PathExprSegment> &&segments, + location_t locus, NodeId node_id) + : Path (locus, node_id), segments (std::move (segments)) {} + std::string as_string () const override; + // Returns whether path has segments. bool has_segments () const { return !segments.empty (); } + std::vector<PathExprSegment> &get_segments () { return segments; } + + const std::vector<PathExprSegment> &get_segments () const { return segments; } + + /* Returns whether the path is a single segment (excluding qualified path + * initial as segment). */ + bool is_single_segment () const { return segments.size () == 1; } + /* Converts path segments to their equivalent SimplePath segments if * possible, and creates a SimplePath from them. */ SimplePath convert_to_simple_path (bool with_opening_scope_resolution) const; - // Removes all segments of the path. - void remove_all_segments () + Path::Kind get_path_kind () const override { return Path::Kind::Regular; } + + void accept_vis (ASTVisitor &vis) override; + + Path *clone_path_impl () const override { - segments.clear (); - segments.shrink_to_fit (); + return new RegularPath (std::vector<PathExprSegment> (segments), locus, + node_id); } +}; -public: - /* Returns whether the path is a single segment (excluding qualified path - * initial as segment). */ - bool is_single_segment () const { return segments.size () == 1; } +class LangItemPath : public Path +{ + NodeId lang_item; + // TODO: Add LangItemKind or w/ever here as well - std::string as_string () const override; + // TODO: This constructor is wrong + explicit LangItemPath (NodeId lang_item, location_t locus) + : Path (locus, lang_item), lang_item (lang_item) + {} - // TODO: this seems kinda dodgy - std::vector<PathExprSegment> &get_segments () { return segments; } - const std::vector<PathExprSegment> &get_segments () const { return segments; } + Path::Kind get_path_kind () const override { return Path::Kind::LangItem; } - Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; } + void accept_vis (ASTVisitor &vis) override; + + Path *clone_path_impl () const override + { + return new LangItemPath (lang_item, locus); + } + + std::string as_string () const override; }; /* AST node representing a path-in-expression pattern (path that allows * generic arguments) */ -class PathInExpression : public PathPattern, public PathExpr +class PathInExpression : public Pattern, public ExprWithoutBlock { std::vector<Attribute> outer_attrs; bool has_opening_scope_resolution; location_t locus; NodeId _node_id; + std::unique_ptr<Path> path; + bool marked_for_strip; public: std::string as_string () const override; @@ -618,12 +692,34 @@ public: PathInExpression (std::vector<PathExprSegment> path_segments, std::vector<Attribute> outer_attrs, location_t locus, bool has_opening_scope_resolution = false) - : PathPattern (std::move (path_segments)), - outer_attrs (std::move (outer_attrs)), + : outer_attrs (std::move (outer_attrs)), has_opening_scope_resolution (has_opening_scope_resolution), - locus (locus), _node_id (Analysis::Mappings::get ().get_next_node_id ()) + locus (locus), _node_id (Analysis::Mappings::get ().get_next_node_id ()), + path (Rust::make_unique<RegularPath> (std::move (path_segments), locus, + _node_id)), + marked_for_strip (false) {} + PathInExpression (const PathInExpression &other) + : outer_attrs (other.outer_attrs), + has_opening_scope_resolution (other.has_opening_scope_resolution), + locus (other.locus), _node_id (other._node_id), + path (other.path->clone_path ()), + marked_for_strip (other.marked_for_strip) + {} + + PathInExpression &operator= (const PathInExpression &other) + { + outer_attrs = other.outer_attrs; + has_opening_scope_resolution = other.has_opening_scope_resolution; + locus = other.locus; + _node_id = other._node_id; + path = other.path->clone_path (); + marked_for_strip = other.marked_for_strip; + + return *this; + } + // Creates an error state path in expression. static PathInExpression create_error () { @@ -631,28 +727,34 @@ public: } // Returns whether path in expression is in an error state. - bool is_error () const { return !has_segments (); } + bool is_error () const + { + // FIXME: Cleanup + if (path->get_path_kind () == Path::Kind::Regular) + return !static_cast<RegularPath &> (*path).has_segments (); + + return false; + } /* Converts PathInExpression to SimplePath if possible (i.e. no generic * arguments). Otherwise returns an empty SimplePath. */ SimplePath as_simple_path () const { - /* delegate to parent class as can't access segments. however, - * QualifiedPathInExpression conversion to simple path wouldn't make - * sense, so the method in the parent class should be protected, not - * public. Have to pass in opening scope resolution as parent class has no - * access to it. - */ - return convert_to_simple_path (has_opening_scope_resolution); + // FIXME: Cleanup + if (path->get_path_kind () == Path::Kind::Regular) + return static_cast<RegularPath &> (*path).convert_to_simple_path ( + has_opening_scope_resolution); + else + // FIXME: lang item to simple path? + rust_unreachable (); } location_t get_locus () const override final { return locus; } void accept_vis (ASTVisitor &vis) override; - // Invalid if path is empty (error state), so base stripping on that. - void mark_for_strip () override { remove_all_segments (); } - bool is_marked_for_strip () const override { return is_error (); } + void mark_for_strip () override { marked_for_strip = true; } + bool is_marked_for_strip () const override { return marked_for_strip; } bool opening_scope_resolution () const { @@ -671,13 +773,61 @@ public: NodeId get_pattern_node_id () const { return get_node_id (); } - PathExprSegment &get_final_segment () { return get_segments ().back (); } + PathExprSegment &get_final_segment () + { + if (path->get_path_kind () == Path::Kind::Regular) + return static_cast<RegularPath &> (*path).get_segments ().back (); + + // lang item segment? + rust_unreachable (); + } + const PathExprSegment &get_final_segment () const { - return get_segments ().back (); + if (path->get_path_kind () == Path::Kind::Regular) + return static_cast<RegularPath &> (*path).get_segments ().back (); + + // lang item segment? + rust_unreachable (); + } + + const std::vector<PathExprSegment> &get_segments () const + { + if (path->get_path_kind () == Path::Kind::Regular) + return static_cast<RegularPath &> (*path).get_segments (); + + rust_unreachable (); + } + + std::vector<PathExprSegment> &get_segments () + { + if (path->get_path_kind () == Path::Kind::Regular) + return static_cast<RegularPath &> (*path).get_segments (); + + rust_unreachable (); + } + + bool is_single_segment () const + { + if (path->get_path_kind () == Path::Kind::Regular) + return static_cast<RegularPath &> (*path).get_segments ().size () == 1; + + return false; } + Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; } + protected: + PathInExpression (std::vector<Attribute> &&outer_attrs, + bool has_opening_scope_resolution, location_t locus, + NodeId node_id, std::unique_ptr<Path> &&path, + bool marked_for_strip) + : outer_attrs (std::move (outer_attrs)), + has_opening_scope_resolution (has_opening_scope_resolution), + locus (locus), _node_id (node_id), path (std::move (path)), + marked_for_strip (marked_for_strip) + {} + /* Use covariance to implement clone function as returning this object * rather than base */ PathInExpression *clone_pattern_impl () const final override @@ -1226,12 +1376,12 @@ public: /* AST node representing a qualified path-in-expression pattern (path that * allows specifying trait functions) */ -class QualifiedPathInExpression : public PathPattern, public PathExpr +class QualifiedPathInExpression : public Pattern, public ExprWithoutBlock { std::vector<Attribute> outer_attrs; QualifiedPathType path_type; - location_t locus; - NodeId _node_id; + + std::unique_ptr<Path> path; public: std::string as_string () const override; @@ -1240,10 +1390,16 @@ public: std::vector<PathExprSegment> path_segments, std::vector<Attribute> outer_attrs, location_t locus) - : PathPattern (std::move (path_segments)), - outer_attrs (std::move (outer_attrs)), - path_type (std::move (qual_path_type)), locus (locus), - _node_id (Analysis::Mappings::get ().get_next_node_id ()) + : outer_attrs (std::move (outer_attrs)), + path_type (std::move (qual_path_type)), + path (Rust::make_unique<RegularPath> ( + std::move (path_segments), locus, + Analysis::Mappings::get ().get_next_node_id ())) + {} + + QualifiedPathInExpression (const QualifiedPathInExpression &other) + : outer_attrs (other.outer_attrs), path_type (other.path_type), + path (other.path->clone_path ()) {} /* TODO: maybe make a shortcut constructor that has QualifiedPathType @@ -1259,7 +1415,9 @@ public: {}, UNDEF_LOCATION); } - location_t get_locus () const override final { return locus; } + Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; } + + location_t get_locus () const override final { return path->get_locus (); } void accept_vis (ASTVisitor &vis) override; @@ -1285,7 +1443,31 @@ public: outer_attrs = std::move (new_attrs); } - NodeId get_node_id () const override { return _node_id; } + NodeId get_node_id () const override { return path->get_node_id (); } + + const std::vector<PathExprSegment> &get_segments () const + { + if (path->get_path_kind () == Path::Kind::Regular) + return static_cast<RegularPath &> (*path).get_segments (); + + rust_unreachable (); + } + + std::vector<PathExprSegment> &get_segments () + { + if (path->get_path_kind () == Path::Kind::Regular) + return static_cast<RegularPath &> (*path).get_segments (); + + rust_unreachable (); + } + + bool is_single_segment () const + { + if (path->get_path_kind () == Path::Kind::Regular) + return static_cast<RegularPath &> (*path).get_segments ().size () == 1; + + return false; + } protected: /* Use covariance to implement clone function as returning this object diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h index 383a5ee..69dbd98 100644 --- a/gcc/rust/ast/rust-pattern.h +++ b/gcc/rust/ast/rust-pattern.h @@ -1657,7 +1657,7 @@ protected: }; // Moved definition to rust-path.h -class PathPattern; +class Path; // Forward decls for paths (defined in rust-path.h) class PathInExpression; diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h index cf830f6..20e0232 100644 --- a/gcc/rust/ast/rust-type.h +++ b/gcc/rust/ast/rust-type.h @@ -48,6 +48,11 @@ public: std::vector<LifetimeParam> &get_for_lifetimes () { return for_lifetimes; } + const std::vector<LifetimeParam> &get_for_lifetimes () const + { + return for_lifetimes; + } + TraitBound (TypePath type_path, location_t locus, bool in_parens = false, bool opening_question_mark = false, std::vector<LifetimeParam> for_lifetimes @@ -81,6 +86,11 @@ public: bool is_in_parens () const { return in_parens; } bool has_opening_question_mark () const { return opening_question_mark; } + TypeParamBoundType get_bound_type () const override + { + return TypeParamBound::TypeParamBoundType::TRAIT; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ |