aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rust')
-rw-r--r--gcc/rust/ChangeLog995
-rw-r--r--gcc/rust/Make-lang.in1
-rw-r--r--gcc/rust/ast/rust-ast-builder.cc11
-rw-r--r--gcc/rust/ast/rust-ast-collector.cc57
-rw-r--r--gcc/rust/ast/rust-ast-collector.h1
-rw-r--r--gcc/rust/ast/rust-ast-visitor.cc46
-rw-r--r--gcc/rust/ast/rust-ast-visitor.h4
-rw-r--r--gcc/rust/ast/rust-ast.cc29
-rw-r--r--gcc/rust/ast/rust-ast.h40
-rw-r--r--gcc/rust/ast/rust-desugar-for-loops.cc4
-rw-r--r--gcc/rust/ast/rust-expr.h165
-rw-r--r--gcc/rust/ast/rust-item.h23
-rw-r--r--gcc/rust/ast/rust-path.cc2
-rw-r--r--gcc/rust/ast/rust-path.h28
-rw-r--r--gcc/rust/ast/rust-stmt.h29
-rw-r--r--gcc/rust/ast/rust-type.h10
-rw-r--r--gcc/rust/backend/rust-compile-asm.cc54
-rw-r--r--gcc/rust/backend/rust-compile-asm.h14
-rw-r--r--gcc/rust/backend/rust-compile-base.cc36
-rw-r--r--gcc/rust/backend/rust-compile-base.h14
-rw-r--r--gcc/rust/backend/rust-compile-block.h2
-rw-r--r--gcc/rust/backend/rust-compile-context.h5
-rw-r--r--gcc/rust/backend/rust-compile-expr.cc25
-rw-r--r--gcc/rust/backend/rust-compile-expr.h1
-rw-r--r--gcc/rust/backend/rust-compile-extern.h6
-rw-r--r--gcc/rust/backend/rust-compile-implitem.cc2
-rw-r--r--gcc/rust/backend/rust-compile-implitem.h6
-rw-r--r--gcc/rust/backend/rust-compile-intrinsic.cc2
-rw-r--r--gcc/rust/backend/rust-compile-item.cc6
-rw-r--r--gcc/rust/backend/rust-compile-item.h4
-rw-r--r--gcc/rust/backend/rust-compile-resolve-path.cc36
-rw-r--r--gcc/rust/backend/rust-compile-type.cc31
-rw-r--r--gcc/rust/backend/rust-compile-type.h2
-rw-r--r--gcc/rust/backend/rust-compile.cc2
-rw-r--r--gcc/rust/backend/rust-constexpr.cc6
-rw-r--r--gcc/rust/checks/errors/borrowck/ffi-polonius/.cargo/config.toml5
-rw-r--r--gcc/rust/checks/errors/borrowck/ffi-polonius/Cargo.lock10
-rw-r--r--gcc/rust/checks/errors/borrowck/ffi-polonius/Cargo.toml10
-rw-r--r--gcc/rust/checks/errors/borrowck/ffi-polonius/vendor/log/Cargo.toml2
-rw-r--r--gcc/rust/checks/errors/borrowck/ffi-polonius/vendor/log/src/lib.rs138
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc4
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h1
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h1
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h1
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-place.h12
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir.h40
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.cc2
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-function-collector.h1
-rw-r--r--gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc4
-rw-r--r--gcc/rust/checks/errors/privacy/rust-privacy-reporter.h1
-rw-r--r--gcc/rust/checks/errors/rust-ast-validation.cc2
-rw-r--r--gcc/rust/checks/errors/rust-const-checker.cc7
-rw-r--r--gcc/rust/checks/errors/rust-const-checker.h1
-rw-r--r--gcc/rust/checks/errors/rust-feature-gate.cc7
-rw-r--r--gcc/rust/checks/errors/rust-feature.cc4
-rw-r--r--gcc/rust/checks/errors/rust-feature.h1
-rw-r--r--gcc/rust/checks/errors/rust-hir-pattern-analysis.cc4
-rw-r--r--gcc/rust/checks/errors/rust-hir-pattern-analysis.h1
-rw-r--r--gcc/rust/checks/errors/rust-unsafe-checker.cc16
-rw-r--r--gcc/rust/checks/errors/rust-unsafe-checker.h1
-rw-r--r--gcc/rust/expand/rust-derive-clone.cc13
-rw-r--r--gcc/rust/expand/rust-derive-debug.cc3
-rw-r--r--gcc/rust/expand/rust-derive-default.cc3
-rw-r--r--gcc/rust/expand/rust-derive-eq.cc3
-rw-r--r--gcc/rust/expand/rust-derive.h1
-rw-r--r--gcc/rust/expand/rust-expand-visitor.cc3
-rw-r--r--gcc/rust/expand/rust-macro-builtins-asm.cc237
-rw-r--r--gcc/rust/expand/rust-macro-builtins-asm.h32
-rw-r--r--gcc/rust/expand/rust-macro-builtins-format-args.cc7
-rw-r--r--gcc/rust/expand/rust-macro-builtins-log-debug.cc2
-rw-r--r--gcc/rust/expand/rust-macro-builtins.cc13
-rw-r--r--gcc/rust/expand/rust-macro-builtins.h4
-rw-r--r--gcc/rust/expand/rust-macro-expand.cc21
-rw-r--r--gcc/rust/expand/rust-token-tree-desugar.cc72
-rw-r--r--gcc/rust/expand/rust-token-tree-desugar.h55
-rw-r--r--gcc/rust/hir/rust-ast-lower-base.cc16
-rw-r--r--gcc/rust/hir/rust-ast-lower-base.h1
-rw-r--r--gcc/rust/hir/rust-ast-lower-block.h4
-rw-r--r--gcc/rust/hir/rust-ast-lower-expr.cc65
-rw-r--r--gcc/rust/hir/rust-ast-lower-expr.h1
-rw-r--r--gcc/rust/hir/rust-ast-lower-implitem.cc29
-rw-r--r--gcc/rust/hir/rust-ast-lower-item.cc5
-rw-r--r--gcc/rust/hir/rust-ast-lower-stmt.cc14
-rw-r--r--gcc/rust/hir/rust-ast-lower-type.cc2
-rw-r--r--gcc/rust/hir/rust-ast-lower.cc11
-rw-r--r--gcc/rust/hir/rust-hir-dump.cc22
-rw-r--r--gcc/rust/hir/rust-hir-dump.h1
-rw-r--r--gcc/rust/hir/tree/rust-hir-bound.h12
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr-abstract.h1
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr.cc24
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr.h125
-rw-r--r--gcc/rust/hir/tree/rust-hir-full-decls.h1
-rw-r--r--gcc/rust/hir/tree/rust-hir-generic-param.h3
-rw-r--r--gcc/rust/hir/tree/rust-hir-item.cc28
-rw-r--r--gcc/rust/hir/tree/rust-hir-item.h63
-rw-r--r--gcc/rust/hir/tree/rust-hir-stmt.cc12
-rw-r--r--gcc/rust/hir/tree/rust-hir-stmt.h16
-rw-r--r--gcc/rust/hir/tree/rust-hir-type.cc5
-rw-r--r--gcc/rust/hir/tree/rust-hir-type.h9
-rw-r--r--gcc/rust/hir/tree/rust-hir-visitor.h3
-rw-r--r--gcc/rust/hir/tree/rust-hir.cc117
-rw-r--r--gcc/rust/parse/rust-parse-impl.h231
-rw-r--r--gcc/rust/parse/rust-parse.h47
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-base.cc4
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-base.h6
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-expr.cc25
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-expr.h1
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-implitem.h19
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-item.cc2
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-path.cc10
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-stmt.cc2
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-stmt.h27
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-toplevel.h32
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-type.cc5
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-type.h4
-rw-r--r--gcc/rust/resolve/rust-default-resolver.cc8
-rw-r--r--gcc/rust/resolve/rust-default-resolver.h2
-rw-r--r--gcc/rust/resolve/rust-early-name-resolver-2.0.cc33
-rw-r--r--gcc/rust/resolve/rust-early-name-resolver-2.0.h16
-rw-r--r--gcc/rust/resolve/rust-forever-stack.h43
-rw-r--r--gcc/rust/resolve/rust-forever-stack.hxx147
-rw-r--r--gcc/rust/resolve/rust-late-name-resolver-2.0.cc211
-rw-r--r--gcc/rust/resolve/rust-late-name-resolver-2.0.h12
-rw-r--r--gcc/rust/resolve/rust-name-resolution-context.cc59
-rw-r--r--gcc/rust/resolve/rust-name-resolution-context.h152
-rw-r--r--gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc17
-rw-r--r--gcc/rust/rust-gcc.cc261
-rw-r--r--gcc/rust/rust-session-manager.cc2
-rw-r--r--gcc/rust/typecheck/rust-hir-dot-operator.cc7
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-reference.h7
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-resolve.cc41
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-base.cc114
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-base.h8
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.cc169
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h1
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-implitem.cc205
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-item.cc57
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-path.cc6
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-pattern.cc21
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-struct-field.h3
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-struct.cc54
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.cc51
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.h11
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.cc35
-rw-r--r--gcc/rust/typecheck/rust-substitution-mapper.cc27
-rw-r--r--gcc/rust/typecheck/rust-substitution-mapper.h2
-rw-r--r--gcc/rust/typecheck/rust-type-util.cc37
-rw-r--r--gcc/rust/typecheck/rust-typecheck-context.cc11
-rw-r--r--gcc/rust/typecheck/rust-tyty-bounds.cc59
-rw-r--r--gcc/rust/typecheck/rust-tyty-subst.cc8
-rw-r--r--gcc/rust/typecheck/rust-tyty-subst.h8
-rw-r--r--gcc/rust/typecheck/rust-tyty-variance-analysis.cc2
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc85
-rw-r--r--gcc/rust/typecheck/rust-tyty.h27
-rw-r--r--gcc/rust/util/expected.h4
-rw-r--r--gcc/rust/util/rust-attribute-values.h27
-rw-r--r--gcc/rust/util/rust-attributes.cc22
-rw-r--r--gcc/rust/util/rust-attributes.h7
-rw-r--r--gcc/rust/util/rust-lang-item.cc1
-rw-r--r--gcc/rust/util/rust-lang-item.h2
-rw-r--r--gcc/rust/util/rust-stacked-contexts.h9
161 files changed, 4223 insertions, 1317 deletions
diff --git a/gcc/rust/ChangeLog b/gcc/rust/ChangeLog
index b85622b..2a5219d 100644
--- a/gcc/rust/ChangeLog
+++ b/gcc/rust/ChangeLog
@@ -1,3 +1,998 @@
+2025-06-26 Martin Jambor <mjambor@suse.cz>
+
+ * checks/errors/borrowck/rust-borrow-checker-diagnostics.cc
+ (BorrowCheckerDiagnostics::get_loan): Type cast loan to uint32_t.
+
+2025-04-28 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * checks/errors/borrowck/rust-bir-place.h
+ (IndexVec::size_type): Add.
+ (IndexVec::MAX_INDEX): Add.
+ (IndexVec::size): Change the return type to the type of the
+ internal value used by the index type.
+ (PlaceDB::lookup_or_add_variable): Use the return value from the
+ PlaceDB::add_place call.
+ * checks/errors/borrowck/rust-bir.h
+ (struct BasicBlockId): Move this definition before the
+ definition of the struct Function.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Visit visibility.
+
+2025-04-28 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-ast-visitor.cc
+ (DefaultASTVisitor::visit): Visit the loop labels of
+ WhileLetLoopExpr instances before visiting their scrutinee
+ expressions.
+ * resolve/rust-early-name-resolver-2.0.cc
+ (Early::resolve_glob_import): Pass the glob import's path
+ directly to NameResolutionContext::resolve_path.
+ * resolve/rust-toplevel-name-resolver-2.0.cc
+ (TopLevel::visit): Remove unnecessary call to
+ Identifier::as_string.
+ (flatten_glob): Improve handling of cases where a glob use tree
+ has no path.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * expand/rust-derive-clone.cc (DeriveClone::clone_enum_struct): Clone
+ path to avoid using the same nodeid.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit_function_params):
+ Add specialized function to visit function parameters.
+ (DefaultASTVisitor::visit): Remove parameter visit and call specialized
+ function instead.
+ * ast/rust-ast-visitor.h: Add function prototye.
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Remove
+ function.
+ (Late::visit_function_params): Override specialized visit function.
+ * resolve/rust-late-name-resolver-2.0.h: Add overriden function
+ prototype.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * resolve/rust-name-resolution-context.h: Use BindingLayer instead.
+ * resolve/rust-name-resolution-context.cc (BindingLayer::BindingLayer):
+ Add new constructor for binding layer.
+ (BindingLayer::bind_test): Add a function to test a binding constraint.
+ (BindingLayer::push): Push a new binding group.
+ (BindingLayer::and_binded): Add function to test and-binding
+ constraint.
+ (BindingLayer::or_binded): Add function to test or-binding constraints.
+ (BindingLayer::insert_ident): Insert a new identifier in the current
+ binding group.
+ (BindingLayer::merge): Merge current binding group with it's parent.
+ (BindingLayer::get_source): Get the source of the current binding
+ group.
+ * resolve/rust-late-name-resolver-2.0.cc: Use stacked context for
+ binding group.
+ * util/rust-stacked-contexts.h: Add mutable peek function.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Add binding
+ creation in visitor.
+ * resolve/rust-late-name-resolver-2.0.h: Add function prototypes.
+ * resolve/rust-name-resolution-context.h: Add binding context.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * resolve/rust-name-resolution-context.h (struct Binding): Add Binding
+ struct to differentiate Or and Product bindings in patterns.
+ (enum class): Add Binding kind.
+ (class BindingContext): Add binding context with Binding stack.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast.h: Add hash function.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast.h: Add equality operator.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * resolve/rust-default-resolver.cc (DefaultResolver::visit): Add visit
+ function for TypeParam.
+ * resolve/rust-default-resolver.h: Add function prototype.
+ * resolve/rust-forever-stack.h: Add function to check for forward
+ declaration ban.
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Check forward
+ declarations.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast-collector.cc (TokenCollector::visit): Remove error kind
+ and change function call.
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Change call name.
+ * ast/rust-path.cc (ConstGenericParam::as_string): Likewise.
+ * ast/rust-path.h: Remove error kind.
+ * hir/rust-ast-lower-type.cc (ASTLowerGenericParam::visit): Change call
+ name.
+ * parse/rust-parse-impl.h (Parser::parse_generic_param): Use optional
+ on parsing failure.
+ (Parser::parse_generic_arg): Likewise.
+ (Parser::parse_path_generic_args): Likewise.
+ * parse/rust-parse.h: Likewise.
+ * resolve/rust-ast-resolve-type.h: Change call name.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Change error
+ message.
+
+2025-04-28 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-early-name-resolver-2.0.cc
+ (Early::build_import_mapping): Avoid outputting an "unresolved
+ import" error if other errors are outputted during resolution.
+ * resolve/rust-early-name-resolver-2.0.h
+ (Early::resolve_path_in_all_ns): Collect path resolution errors
+ while avoiding duplicate errors for resolutions in each
+ namespace.
+ * resolve/rust-forever-stack.h
+ (ForeverStack::resolve_path): Add parameter for collecting
+ errors.
+ (ForeverStack::find_starting_point): Likewise.
+ (ForeverStack::resolve_segments): Likewise.
+ * resolve/rust-forever-stack.hxx
+ (check_leading_kw_at_start): Likewise.
+ (ForeverStack::find_starting_point): Likewise.
+ (ForeverStack::resolve_segments): Likewise.
+ (ForeverStack::resolve_path): Likewise.
+ * resolve/rust-name-resolution-context.h
+ (NameResolutionContext::resolve_path): Add optional parameter
+ for collecting errors.
+
+2025-04-28 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-expr.cc (CompileExpr::array_copied_expr): prealloc the vector
+
+2025-04-28 Philip Herron <herron.philip@googlemail.com>
+
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): add guard
+ * expand/rust-expand-visitor.cc (ExpandVisitor::visit): add guard
+
+2025-04-28 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-ast-resolve-path.cc
+ (ResolvePath::resolve_path): Adjust error messages.
+ * resolve/rust-ast-resolve-type.cc
+ (ResolveRelativeTypePath::go): Likewise.
+ * resolve/rust-forever-stack.hxx
+ (check_leading_kw_at_start): Likewise.
+
+2025-04-28 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): fix bad assertion
+
+2025-04-28 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-forever-stack.hxx
+ (ForeverStack::resolve_path): Pass instance of Node to lambda by
+ reference instead of by value.
+
+2025-04-28 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-struct-field.h: keep reference to parent expression
+ * typecheck/rust-hir-type-check-struct.cc (TypeCheckStructExpr::TypeCheckStructExpr):
+ update ctor
+ (TypeCheckStructExpr::resolve): remove bad rust_fatal_errors
+ (TypeCheckStructExpr::visit): cleanup errors
+
+2025-04-28 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-late-name-resolver-2.0.cc
+ (Late::visit): Handle StructPatternFieldIdent.
+ * resolve/rust-late-name-resolver-2.0.h
+ (Late::visit): Likewise.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast-collector.cc (TokenCollector::visit): Dump llvm inline
+ asm tokens.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast-collector.cc (TokenCollector::visit): Remove unreachable
+ code.
+ * ast/rust-expr.h (struct LlvmOperand): Add LlvmOperand struct to
+ represent input and outputs.
+ (class LlvmInlineAsm): Add input, output and clobber operands.
+ (struct TupleTemplateStr): Add locus getter.
+ * backend/rust-compile-block.h: Add visit for LlvmInlineAsm.
+ * backend/rust-compile-expr.cc (CompileExpr::visit): Add llvm inline
+ asm stmt compilation.
+ * backend/rust-compile-expr.h: Add function prototype.
+ * backend/rust-compile-asm.h (class CompileLlvmAsm): Add llvm asm hir
+ not to gimple.
+ * backend/rust-compile-asm.cc (CompileLlvmAsm::CompileLlvmAsm): Add
+ constructor.
+ (CompileLlvmAsm::construct_operands): Add function to construct operand
+ tree.
+ (CompileLlvmAsm::construct_clobbers): Add function to construct clobber
+ tree.
+ (CompileLlvmAsm::tree_codegen_asm): Generate the whole tree for a given
+ llvm inline assembly node.
+ * checks/errors/borrowck/rust-bir-builder-expr-stmt.cc (ExprStmtBuilder::visit):
+ Add visit function.
+ * checks/errors/borrowck/rust-bir-builder-expr-stmt.h: Add function
+ prototype.
+ * checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h: Add visit
+ function.
+ * checks/errors/borrowck/rust-bir-builder-struct.h: Likewise.
+ * checks/errors/borrowck/rust-function-collector.h: Likewise.
+ * checks/errors/privacy/rust-privacy-reporter.cc (PrivacyReporter::visit):
+ Likewise.
+ * checks/errors/privacy/rust-privacy-reporter.h: Add visit function
+ prototype.
+ * checks/errors/rust-const-checker.cc (ConstChecker::visit): Add visit
+ function.
+ * checks/errors/rust-const-checker.h: Add visit function prototype.
+ * checks/errors/rust-hir-pattern-analysis.cc (PatternChecker::visit):
+ Add visit function.
+ * checks/errors/rust-hir-pattern-analysis.h: Add visit function
+ prototype.
+ * checks/errors/rust-unsafe-checker.cc (UnsafeChecker::visit): Add
+ visit function.
+ * checks/errors/rust-unsafe-checker.h: Add function prototype.
+ * expand/rust-macro-builtins-asm.cc (parse_llvm_templates): Parse
+ templates.
+ (parse_llvm_arguments): Add function to parse non template tokens.
+ (parse_llvm_operands): Add function to parse operands, either input or
+ output.
+ (parse_llvm_outputs): Add function to parse and collect llvm asm
+ outputs.
+ (parse_llvm_inputs): Likewise with inputs.
+ (parse_llvm_clobbers): Add function to parse llvm asm clobbers.
+ (parse_llvm_options): Add function to parse llvm asm options.
+ (parse_llvm_asm): Add function to parse llvm asm.
+ * expand/rust-macro-builtins-asm.h (class LlvmAsmContext): Add context
+ for llvm asm parser.
+ (parse_llvm_outputs): Add function prototype.
+ (parse_llvm_inputs): Likewise.
+ (parse_llvm_clobbers): Likewise.
+ (parse_llvm_options): Likewise.
+ * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Lower AST llvm
+ asm node to HIR.
+ * hir/rust-ast-lower-expr.h: Add function prototype.
+ * hir/rust-hir-dump.cc (Dump::visit): Add visit function.
+ * hir/rust-hir-dump.h: Add function prototype.
+ * hir/tree/rust-hir-expr-abstract.h: Add HIR llvm asm node kind.
+ * hir/tree/rust-hir-expr.h (struct LlvmOperand): Add LlvmOperand type
+ to represent input and outputs.
+ (class LlvmInlineAsm): Add LlvmInlineAsm hir node.
+ * hir/tree/rust-hir-full-decls.h (class LlvmInlineAsm): Add
+ LlvmInlineAsm hir node forward declaration.
+ * hir/tree/rust-hir-visitor.h: Add visit functions for LlvmInlineAsm
+ hir node.
+ * hir/tree/rust-hir.cc (LlvmInlineAsm::accept_vis): Add hir node
+ visitor related functions.
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit):
+ Type check input and output operands.
+ * typecheck/rust-hir-type-check-expr.h: Add function prototype.
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Visit input and
+ output operand expressions.
+ * resolve/rust-ast-resolve-expr.cc (ResolveExpr::visit): Resolve input
+ and output expressions.
+ * resolve/rust-ast-resolve-expr.h: Add function prototypes.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast-collector.cc (TokenCollector::visit): Make visitor
+ unreachable.
+ * ast/rust-ast-collector.h: Add visit for LlvmInlineAsmNode.
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Add visit
+ function for the default ast visitor.
+ * ast/rust-ast-visitor.h: Add function prototype.
+ * ast/rust-ast.cc (LlvmInlineAsm::accept_vis): Add accept_vis to
+ LlvmInlineAsm node.
+ * ast/rust-ast.h: Add LlvmInlineAsm node kind.
+ * ast/rust-expr.h (class LlvmInlineAsm): Add LlvmInlineAsm node.
+ * expand/rust-derive.h: Add visit function for LlvmInlineAsm node.
+ * expand/rust-macro-builtins-asm.cc (MacroBuiltin::llvm_asm_handler):
+ Add handler for llvm inline assembly nodes.
+ (parse_llvm_asm): Add function to parse llvm assembly nodes.
+ * expand/rust-macro-builtins-asm.h (parse_llvm_asm): Add function
+ prototypes.
+ * expand/rust-macro-builtins.cc (inline_llvm_asm_maker): Add macro
+ transcriber.
+ * expand/rust-macro-builtins.h: Add transcriber function prototype.
+ * hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Add visit
+ function for LlvmInlineAsm node.
+ * hir/rust-ast-lower-base.h: Add visit function prototype.
+ * resolve/rust-ast-resolve-base.cc (ResolverBase::visit): Add visit
+ function for LlvmInlineAsm node.
+ * resolve/rust-ast-resolve-base.h: Add visit function prototype.
+
+2025-04-28 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * expand/rust-macro-builtins-asm.cc (parse_asm_arg): Emit error
+ message.
+
+2025-04-28 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-item.cc (TypeCheckItem::visit): add diagnostic
+ * typecheck/rust-tyty.cc (BaseType::contains_infer): new helper to grab first infer var
+ * typecheck/rust-tyty.h: prototype
+
+2025-04-28 Philip Herron <herron.philip@googlemail.com>
+
+ * rust-gcc.cc (arithmetic_or_logical_expression): Ensure this is an integer
+
+2025-04-28 Philip Herron <herron.philip@googlemail.com>
+
+ * hir/rust-hir-dump.cc (Dump::visit): add guard for optional label
+
+2025-04-28 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * typecheck/rust-tyty.h: Remove extra redundant comment.
+ * typecheck/rust-hir-type-check-base.cc: Update comment on repr
+ handling.
+
+2025-04-28 Zhi Heng <yapzhhg@gmail.com>
+
+ * typecheck/rust-hir-type-check-base.cc: Set enum representing
+ type properly if repr is an integer type.
+ * typecheck/rust-hir-type-check-item.cc: Update comments.
+
+2025-04-28 Zhi Heng <yapzhhg@gmail.com>
+
+ * typecheck/rust-tyty.h: Add new `ReprKind` enum to
+ `ReprOptions`.
+ * typecheck/rust-hir-type-check-base.cc: Handle setting of
+ `repr_kind`.
+ * typecheck/rust-hir-type-check-item.cc: New check for
+ zero-variant enums.
+
+2025-04-28 Philip Herron <herron.philip@googlemail.com>
+
+ * checks/errors/rust-unsafe-checker.cc (UnsafeChecker::visit): add null check
+ * hir/tree/rust-hir-item.h: add has_type helper
+ * typecheck/rust-hir-trait-resolve.cc (TraitItemReference::resolve_item):
+ add missing type checking
+
+2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * util/rust-lang-item.h: Add new manually_drop lang item.
+ * util/rust-lang-item.cc: Likewise.
+
+2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * util/rust-attribute-values.h: Add RUSTFMT value.
+ * util/rust-attributes.cc: Define the attribute.
+ * util/rust-attributes.h (enum CompilerPass): Add EXTERNAL variant.
+ * expand/rust-macro-builtins.cc: Fix formatting.
+
+2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * resolve/rust-early-name-resolver-2.0.cc (Early::visit_attributes): Remove assertion.
+
+2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * util/rust-attribute-values.h: Add missing attributes.
+ * util/rust-attributes.cc: Likewise.
+ * util/rust-attributes.h (enum CompilerPass): Mention adding something for const
+ functions.
+
+2025-04-14 beamandala <mandalapubhavesh@gmail.com>
+
+ * expand/rust-macro-builtins.cc (MacroBuiltin::builtin_transcribers):
+ Add entry for track_caller.
+ * util/rust-attribute-values.h: add `TRACK_CALLER` attribute.
+ * util/rust-attributes.cc: add `track_caller` attribute definition.
+
+2025-04-14 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * checks/errors/rust-const-checker.cc
+ (ConstChecker::visit): Visit the enum items of enums.
+ * resolve/rust-ast-resolve-item.cc
+ (ResolveItem::visit): Resolve enum discriminants during nr1.0.
+
+2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-macro-builtins-format-args.cc (format_args_parse_arguments): Improve safety,
+ allow extra commas after end of argument list.
+
+2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-macro-expand.cc (MacroExpander::expand_decl_macro): Call into
+ TokenTreeDesugar.
+ * expand/rust-token-tree-desugar.cc: New file.
+ * expand/rust-token-tree-desugar.h: New file.
+ * Make-lang.in: Compile them.
+
+2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-macro-expand.cc (MacroExpander::match_n_matches): Do not
+ insert fragments and substack fragments if the matcher failed.
+
+2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * rust-session-manager.cc (Session::compile_crate): Call the visitor later in the pipeline.
+
+2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast.h (DelimTokenTree::get_locus): New function.
+
+2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-expr.h (class RangeExpr): Add empty outer attributes and allow getting them
+ and setting them.
+
+2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit): Return if module
+ is unloaded.
+
+2025-04-14 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * typecheck/rust-hir-type-check-expr.cc (is_default_fn): New.
+ (emit_ambiguous_resolution_error): New.
+ (handle_multiple_candidates): Properly handle multiple candidates in
+ the case of specialization.
+ (TypeCheckExpr::visit): Call `handle_multiple_candidates`.
+
+2025-04-14 Andrew Pinski <quic_apinski@quicinc.com>
+
+ PR rust/119342
+ * rust-gcc.cc (block): Add comment on why chaining
+ the variables of the scope toether.
+
+2025-04-14 Andrew Pinski <quic_apinski@quicinc.com>
+
+ PR rust/119341
+ * rust-gcc.cc (function_type): Use range fors.
+ (function_type_variadic): Likewise.
+ (fill_in_fields): Likewise.
+ (statement_list): Likewise.
+ (block): Likewise.
+ (block_add_statements): Likewise.
+ (function_set_parameters): Likewise.
+ (write_global_definitions): Likewise.
+
+2025-04-14 Andrew Pinski <quic_apinski@quicinc.com>
+
+ * rust-gcc.cc (Bvariable::get_tree): Use error_operand_p.
+ (pointer_type): Likewise.
+ (reference_type): Likewise.
+ (immutable_type): Likewise.
+ (function_type): Likewise.
+ (function_type_variadic): Likewise.
+ Cleanup the check for receiver.type first.
+ (function_ptr_type): Use error_operand_p.
+ (fill_in_fields): Likewise.
+ (fill_in_array): Likewise.
+ (named_type): Likewise.
+ (type_size): Likewise.
+ (type_alignment): Likewise.
+ (type_field_alignment): Likewise.
+ (type_field_offset): Likewise.
+ (zero_expression): Likewise.
+ (float_constant_expression): Likewise.
+ (convert_expression): Likewise.
+ (struct_field_expression): Likewise.
+ (compound_expression): Likewise.
+ (conditional_expression): Likewise.
+ (negation_expression): Likewise.
+ (arithmetic_or_logical_expression): Likewise.
+ (arithmetic_or_logical_expression_checked): Likewise.
+ (comparison_expression): Likewise.
+ (lazy_boolean_expression): Likewise.
+ (constructor_expression): Likewise.
+ (array_constructor_expression): Likewise.
+ (array_index_expression): Likewise.
+ (call_expression): Likewise.
+ (init_statement): Likewise.
+ (assignment_statement): Likewise.
+ (return_statement): Likewise.
+ (exception_handler_statement): Likewise.
+ (if_statement): Likewise.
+ (compound_statement): Likewise.
+ Tighten up the code, removing t variable.
+ (statement_list): Use error_operand_p.
+ (block): Likewise.
+ (block_add_statements): Likewise.
+ (convert_tree): Likewise.
+ (global_variable): Likewise.
+ (global_variable_set_init): Likewise.
+ (local_variable): Likewise.
+ (parameter_variable): Likewise.
+ (static_chain_variable): Likewise.
+ (temporary_variable): Likewise.
+ (function): Likewise. Tighten up the code.
+ (function_defer_statement): Use error_operand_p.
+ (function_set_parameters): Use error_operand_p.
+ (write_global_definitions): Use error_operand_p.
+ Tighten up the code around the loop.
+
+2025-04-14 Andrew Pinski <quic_apinski@quicinc.com>
+
+ * rust-gcc.cc (is_floating_point): Use FLOAT_TYPE_P
+ instead of manually checking the type.
+
+2025-04-08 Matty Kuhn <matty.kuhn.1@gmail.com>
+
+ * ast/rust-ast.h: (AST::Attribute): add empty_input function
+ * checks/errors/rust-feature-gate.cc: (FeatureGate::visit): check for empty feature gate
+
+2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast-collector.cc (TokenCollector::visit): Update label
+ getter call.
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise.
+ * ast/rust-ast.cc (BreakExpr::as_string): Likewise.
+ * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise.
+ * resolve/rust-ast-resolve-expr.cc (ResolveExpr::visit): Likewise.
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Likewise.
+ * ast/rust-expr.h: Add optional getter and rename label getter to
+ get_label_unchecked.
+
+2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast-collector.cc (TokenCollector::visit):
+ Call unchecked getter.
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit):
+ Likewise.
+ * ast/rust-ast.cc (ContinueExpr::as_string): Likewise.
+ * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise.
+ * resolve/rust-ast-resolve-expr.cc (ResolveExpr::visit): Likewise.
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Likewise.
+ * ast/rust-expr.h: Add new getter for the optional and rename getter
+ to get_label_unchecked.
+
+2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * parse/rust-parse-impl.h (Parser::parse_loop_label): Change function
+ return type to expected.
+ (Parser::parse_labelled_loop_expr): Adapt call location to new return
+ type.
+ * parse/rust-parse.h (enum class): Update function prototype.
+
+2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Add call
+ to label resolution if there is one label.
+ (Late::resolve_label): Look for labels and emit an error message on
+ failure.
+ * resolve/rust-late-name-resolver-2.0.h: Add function prototypes.
+
+2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * resolve/rust-ast-resolve-expr.cc (ResolveExpr::visit):
+ Change error message to match rustc.
+
+2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast-builder.cc (Builder::self_ref_param): Remove error state
+ and use optional.
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Check label
+ before visiting.
+ * ast/rust-ast.cc (ContinueExpr::as_string): Retrieve label value.
+ (Lifetime::as_string): Retrieve lifetime value.
+ (ReferenceType::as_string): Likewise.
+ (SelfParam::as_string): Likewise.
+ * ast/rust-ast.h: Remove lifetime and LifetimeParam error state.
+ * ast/rust-desugar-for-loops.cc (DesugarForLoops::DesugarCtx::make_break_arm):
+ Use optional instead of error state.
+ * ast/rust-expr.h (class ContinueExpr): Make label optional.
+ * ast/rust-item.h (class SelfParam): Make lifetime optional.
+ * ast/rust-type.h (class ReferenceType): Likewise.
+ * backend/rust-compile-base.cc: Use optional for self param instead
+ of error state.
+ * backend/rust-compile-base.h: Update function prototype.
+ * expand/rust-derive-clone.cc (DeriveClone::clone_fn): Use optional.
+ * hir/rust-ast-lower-base.cc (ASTLoweringBase::lower_self): Lower
+ lifetime only if it exists.
+ * hir/rust-ast-lower-block.h: Lower loop label only if it exists.
+ * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise.
+ * hir/rust-ast-lower-implitem.cc (ASTLowerImplItem::visit): Remove
+ references to error state.
+ (ASTLowerTraitItem::visit): Lower self param only if it exists.
+ * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): Use nullopt
+ for default value instead of SelfParam error state.
+ * hir/rust-ast-lower.cc (ASTLoweringExprWithBlock::visit): Lower label
+ only if it exists.
+ * hir/rust-hir-dump.cc (Dump::do_traitfunctiondecl): Print self only if
+ it exists.
+ (Dump::visit): Liewise.
+ * hir/tree/rust-hir-bound.h: Remove error state.
+ * hir/tree/rust-hir-expr.cc (ContinueExpr::ContinueExpr): Use optional
+ in constructor for loop label.
+ (BreakExpr::BreakExpr): Likewise.
+ * hir/tree/rust-hir-expr.h (class ContinueExpr): Remove error state
+ implementation.
+ (class BreakExpr): Likewise.
+ * hir/tree/rust-hir-generic-param.h: Likewise.
+ * hir/tree/rust-hir-item.cc (SelfParam::SelfParam): Make lifetime
+ optional.
+ (Function::Function): Make self param optional.
+ * hir/tree/rust-hir-item.h (class Function): Likewise.
+ * hir/tree/rust-hir-type.cc (ReferenceType::ReferenceType): Make
+ lifetime optional.
+ * hir/tree/rust-hir-type.h (class ReferenceType): Likewise.
+ * hir/tree/rust-hir.cc (ContinueExpr::as_string): Use new getter.
+ (BreakExpr::as_string): Likewise.
+ (Lifetime::as_string): Likewise.
+ (ReferenceType::as_string): Likewise.
+ (TraitFunctionDecl::as_string): Likewise.
+ (SelfParam::as_string): Remove error state checking.
+ * parse/rust-parse-impl.h (Parser::parse_generic_param): Adapt to
+ optional.
+ (Parser::parse_lifetime_params): Likewise.
+ (Parser::parse_lifetime_params_objs): Likewise.
+ (Parser::parse_lifetime_param): Likewise.
+ (Parser::parse_lifetime_where_clause_item): Likewise.
+ (Parser::parse_type_param_bound): Likewise.
+ (Parser::parse_lifetime_bounds): Likewise.
+ (Parser::parse_path_generic_args): Likewise.
+ (Parser::parse_self_param): Likewise.
+ (Parser::parse_break_expr): Likewise.
+ (Parser::parse_continue_expr): Likewise.
+ (Parser::parse_reference_type_inner): Likewise.
+ * parse/rust-parse.h (class ParseLifetimeParamError): Add new class for
+ lifetime param parsing errors.
+ (class ParseLifetimeError): Add new class for lifetime parsing errors.
+ (enum ParseSelfError): Add new class for self param parsing errors.
+ * typecheck/rust-hir-type-check-implitem.cc (TypeCheckImplItem::visit):
+ Use unchecked getter in checked context. And make anonymous region.
+ * typecheck/rust-hir-type-check.cc (TraitItemReference::get_type_from_fn):
+ Likewise.
+
+2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Add
+ check for loop label before visiting it.
+
+2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-expr.h: Remove error getter and constructor.
+
+2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast-builder.cc (Builder::block): Call with a nullopt instead
+ of an error loop label.
+ (WhileLetLoopExpr::as_string): Use getter function and adapt to
+ newtype.
+ * ast/rust-ast.cc (WhileLoopExpr::as_string): Likewise.
+ (LoopExpr::as_string): Likewise.
+ (BreakExpr::as_string): Likewise.
+ (ForLoopExpr::as_string): Likewise.
+ * ast/rust-expr.h (class BlockExpr): Make loop label optional.
+ (class BreakExpr): Likewise.
+ * expand/rust-derive-clone.cc (DeriveClone::clone_fn): Use nullopt.
+ * expand/rust-derive-debug.cc (DeriveDebug::stub_debug_fn): Likewise.
+ * expand/rust-derive-default.cc (DeriveDefault::default_fn): Likewise.
+ * expand/rust-derive-eq.cc: Likewise.
+ * parse/rust-parse-impl.h (Parser::parse_block_expr): Use optional
+ for arguments.
+ (Parser::parse_loop_expr): Likewise.
+ (Parser::parse_while_loop_expr): Likewise.
+ (Parser::parse_while_let_loop_expr): Likewise.
+ (Parser::parse_for_loop_expr): Likewise.
+ (Parser::parse_labelled_loop_expr): Likewise.
+ (Parser::parse_loop_label): Return an optional.
+ * parse/rust-parse.h: Update function prototype and use nullopt for
+ default values.
+
+2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Change default
+ visit order.
+
+2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Visit loop label
+ only if it exists.
+
+2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * hir/rust-ast-lower.cc (ASTLoweringBlock::visit): Lower label only if
+ it exists.
+ * hir/tree/rust-hir-expr.cc (BlockExpr::BlockExpr): Make loop label
+ optional.
+ (BaseLoopExpr::BaseLoopExpr): Likewise.
+ (LoopExpr::LoopExpr): Likewise.
+ (WhileLoopExpr::WhileLoopExpr): Likewise.
+ * hir/tree/rust-hir-expr.h: Use optional for lifetime and labels.
+ * hir/tree/rust-hir.cc (WhileLoopExpr::as_string): Use getter.
+ (WhileLetLoopExpr::as_string): Likewise.
+ (LoopExpr::as_string): Likewise.
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Resolve labels.
+ * resolve/rust-late-name-resolver-2.0.h: Add visit function prototype
+ for loop labels.
+
+2025-04-08 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * util/expected.h: Use gcc_unreachable within gcc context.
+
+2025-04-08 Sri Ganesh Thota <sriganeshthota12345@gmail.com>
+
+ * resolve/rust-ast-resolve-base.h (redefined_error): created a function for
+ rust_error_at for redefined at multiple times.
+ * resolve/rust-ast-resolve-implitem.h: changed rust_error_at to redefined_error.
+ * resolve/rust-ast-resolve-stmt.cc (ResolveStmt::visit): changed rust_error_at to
+ redefined_error.
+ * resolve/rust-ast-resolve-stmt.h: changed rust_error_at to redefined_error.
+ * resolve/rust-ast-resolve-toplevel.h: changed rust_error_at to redefined_error.
+
+2025-04-08 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-ast-visitor.cc
+ (DefaultASTVisitor::visit): Remove explicit visitation of a
+ function's self parameter, as if it exists it'll be visited as
+ one of the function parameters.
+
+2025-04-08 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-typecheck-context.cc (TypeCheckContext::lookup_lifetime): emit error
+
+2025-04-08 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast.cc (Function::Function): Rename is_default -> has_default.
+ (Function::operator=): Likewise.
+ * ast/rust-item.h (class Function): Add `is_default` method.
+ * hir/rust-ast-lower-implitem.cc (ASTLowerImplItem::visit): Lower default qualifier.
+ * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): Likewise.
+ * hir/tree/rust-hir-item.cc (Function::Function): Add `is_default` member.
+ (Function::operator=): Likewise.
+ * hir/tree/rust-hir-item.h (enum class Defaultness): New enum.
+ (class Function): Use it.
+
+2025-04-08 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * checks/errors/rust-feature.cc (Feature::create): Handle `#![feature(min_specialization)]`.
+ * checks/errors/rust-feature.h: Likewise.
+
+2025-04-08 Philip Herron <herron.philip@googlemail.com>
+
+ * resolve/rust-ast-resolve-type.cc (ResolveRelativeTypePath::go): fix error msg
+ * typecheck/rust-substitution-mapper.cc (SubstMapper::Resolve): add validation
+ (SubstMapper::valid_type): new check
+ (SubstMapper::visit): check if can resolve
+ * typecheck/rust-substitution-mapper.h: new prototype
+
+2025-04-08 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-base.cc (HIRCompileBase::address_expression): allow optional type
+ * backend/rust-compile-base.h: update prototype
+ * backend/rust-compile-expr.cc (CompileExpr::visit): update borrow expr
+ * backend/rust-compile-extern.h: remove unused debug
+ * backend/rust-compile-resolve-path.cc (HIRCompileBase::query_compile): update usage
+ * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): lower raw ref
+ * hir/tree/rust-hir-expr.cc (BorrowExpr::BorrowExpr): add flag for raw ref
+ * hir/tree/rust-hir-expr.h (class BorrowExpr): add new raw ref field
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): add handle for raw ref
+
+2025-04-08 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit): emit error
+
+2025-04-08 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-trait-resolve.cc (TraitResolver::resolve_trait): new argument
+ * typecheck/rust-hir-type-check-base.cc (TypeCheckBase::TypeCheckBase): new helper
+ * typecheck/rust-hir-type-check-base.h: new helper prototype
+ * typecheck/rust-hir-type-check-implitem.cc (TypeCheckTopLevelExternItem::visit):
+ remove comment out code
+ * typecheck/rust-hir-type-check-path.cc (TypeCheckExpr::resolve_root_path): check for null
+ * typecheck/rust-hir-type-check-type.cc (TypeCheckType::resolve_root_path): likewise
+ (TypeResolveGenericParam::Resolve): new args
+ (TypeResolveGenericParam::ApplyAnyTraitBounds): new helper
+ (TypeResolveGenericParam::apply_trait_bounds): new field
+ (TypeResolveGenericParam::visit): update
+ * typecheck/rust-hir-type-check-type.h: new args
+ * typecheck/rust-hir-type-check.cc (TraitItemReference::get_type_from_fn): reuse helper
+ * typecheck/rust-type-util.cc (query_type): check for recursive query
+ * typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::SubstitutionParamMapping):
+ remove const
+ (SubstitutionParamMapping::get_generic_param): likewise
+ * typecheck/rust-tyty-subst.h: likewise
+ * typecheck/rust-tyty-variance-analysis.cc (GenericTyVisitorCtx::process_type): likewise
+
+2025-04-08 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-base.cc: new flag is_root_item
+ * backend/rust-compile-base.h: update prototype
+ * backend/rust-compile-implitem.cc (CompileTraitItem::visit): update call
+ * backend/rust-compile-implitem.h: remove old debug internal error
+ * backend/rust-compile-item.cc (CompileItem::visit): update call
+ * backend/rust-compile-item.h: remove old debug
+ * backend/rust-compile-resolve-path.cc (HIRCompileBase::query_compile): update calls
+ * backend/rust-compile.cc: likewise
+ * typecheck/rust-hir-trait-resolve.cc (TraitResolver::resolve_path_to_trait):
+ remove assertion and error
+
+2025-04-08 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-base.cc: remove assertion
+
+2025-04-08 Philip Herron <herron.philip@googlemail.com>
+
+ * rust-gcc.cc (arithmetic_or_logical_expression): unwrap const decls
+
+2025-04-08 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-forever-stack.h
+ (ForeverStack::ForeverStack): Initialize extern_prelude.
+ (ForeverStack::resolve_path): Add parameter
+ has_opening_scope_resolution.
+ (ForeverStack::extern_prelude): Add field.
+ * resolve/rust-forever-stack.hxx: Include rust-edition.h.
+ (ForeverStacl::resolve_path): Handle global paths (paths with an
+ opening scope resolution operator).
+ * resolve/rust-late-name-resolver-2.0.cc
+ (Late::visit): Handle global paths.
+ * resolve/rust-name-resolution-context.h
+ (NameResolutionContext::resolve_path): Handle global paths.
+
+2025-04-08 Ryutaro Okada <1015ryu88@gmail.com>
+
+ * backend/rust-compile-resolve-path.cc: Evaluate the enum's discriminant in a const context
+
+2025-03-31 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-type.cc (TypeCheckType::resolve_root_path):
+ catch nullptr root_tyty
+
+2025-03-31 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-base.cc (TypeCheckBase::parse_repr_options):
+ check for null and empty and add missing delete call
+
+2025-03-31 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-tyty-subst.h: check for min range
+
+2025-03-31 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-base.cc (TypeCheckBase::parse_repr_options): check for input
+
+2025-03-31 Philip Herron <herron.philip@googlemail.com>
+
+ * hir/rust-hir-dump.cc (Dump::visit): check has type
+ * hir/tree/rust-hir-type.cc (BareFunctionType::BareFunctionType): likewise
+
+2025-03-31 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-constexpr.cc (eval_store_expression): turn this back on
+
+2025-03-31 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * expand/rust-macro-builtins-log-debug.cc:
+ Add newline to end of file.
+
+2025-03-31 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-forever-stack.h
+ (ForeverStack::get_prelude): Rename to...
+ (ForeverStack::get_lang_prelude): ...here.
+ (ForeverStack::prelude): Rename to...
+ (ForeverStack::lang_prelude): ...here.
+ (ForeverStack::ForeverStack): Handle renames.
+ * resolve/rust-forever-stack.hxx
+ (ForeverStack::push_inner): Likewise.
+ (ForeverStack::resolve_segments): Likewise.
+ (ForeverStack::resolve_path): Likewise.
+ (ForeverStack::get_prelude): Rename to...
+ (ForeverStack::get_lang_prelude): ...here and handle renames.
+ * resolve/rust-late-name-resolver-2.0.cc
+ (Late::visit): Handle renames.
+
+2025-03-31 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-context.h: only push named types
+ * backend/rust-compile-type.cc (TyTyResolveCompile::visit): run the type hasher
+
+2025-03-31 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-resolve-path.cc (HIRCompileBase::query_compile): check for Expr trait
+ * hir/rust-hir-dump.cc (Dump::visit): expr is optional
+
+2025-03-31 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * resolve/rust-forever-stack.hxx: Add a new specialized function
+ to retrieve the last "real" segment depending on the namespace.
+ * resolve/rust-forever-stack.h: Add new function prototype.
+ * resolve/rust-early-name-resolver-2.0.cc (Early::finalize_rebind_import):
+ Set declared name according to the selected segment, if there is a self
+ suffix in the use declaration then select the previous segment.
+
+2025-03-31 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-base.cc (HIRCompileBase::unit_expression): pass ctx
+ * backend/rust-compile-base.h: cant be static
+ * backend/rust-compile-intrinsic.cc (try_handler_inner): pass ctx
+ * backend/rust-compile-type.cc
+ (TyTyResolveCompile::get_unit_type): update to grab the first locus
+ (TyTyResolveCompile::visit): pass ctx
+ * backend/rust-compile-type.h: likewise
+
+2025-03-31 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-dot-operator.cc:
+
+2025-03-31 Philip Herron <herron.philip@googlemail.com>
+
+ * resolve/rust-ast-resolve-path.cc (ResolvePath::resolve_path): check for super mid path
+
+2025-03-31 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-base.cc (HIRCompileBase::address_expression): new helper constexpr
+ * backend/rust-compile-base.h: prototype
+ * backend/rust-compile-type.cc (TyTyResolveCompile::visit): call constexpr helper
+
+2025-03-31 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-item.cc (TypeCheckItem::resolve_impl_block_substitutions):
+ Track the polarity
+ * typecheck/rust-tyty-bounds.cc (TypeBoundPredicate::validate_type_implements_this):
+ new validator
+ * typecheck/rust-tyty.h: new prototypes
+
+2025-03-31 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-expr.cc (CompileExpr::array_value_expr): add value chk for array expr
+
+2025-03-31 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-trait-reference.h: add default infer arg
+ * typecheck/rust-hir-trait-resolve.cc: dont add new infer vars
+ * typecheck/rust-hir-type-check-path.cc (TypeCheckExpr::resolve_segments): dont infer
+
+2025-03-31 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * checks/errors/rust-ast-validation.cc
+ (ASTValidation::visit): Allow constant items lacking expressions
+ if and only if they're associated with a trait definition, not a
+ trait implementation.
+
+2025-03-31 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * hir/rust-ast-lower-base.cc
+ (ASTLoweringBase::lower_literal): Lower raw string literals into
+ normal string literals.
+
+2025-03-31 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * checks/errors/borrowck/ffi-polonius/Cargo.lock: Regenerate.
+ * checks/errors/borrowck/ffi-polonius/Cargo.toml: Update to use source patching instead of
+ vendoring, lower edition to 2018.
+ * checks/errors/borrowck/ffi-polonius/vendor/log/Cargo.toml: Change edition to 2018.
+ * checks/errors/borrowck/ffi-polonius/vendor/log/src/lib.rs: Remove uses of unstable
+ feature.
+ * checks/errors/borrowck/ffi-polonius/.cargo/config.toml: Removed.
+
+2025-03-31 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * hir/tree/rust-hir-stmt.h (class LetStmt): Add optional diverging else expression.
+ * hir/tree/rust-hir-stmt.cc: Likewise.
+ * hir/rust-ast-lower-stmt.cc (ASTLoweringStmt::visit): Add handling for lowering
+ diverging else.
+
+2025-03-31 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * resolve/rust-ast-resolve-stmt.h: Add handling for diverging else.
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Likewise.
+
+2025-03-31 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast-collector.cc (TokenCollector::visit): Add handling for diverging else
+ expression.
+
+2025-03-31 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * parse/rust-parse-impl.h (Parser::parse_let_stmt): Add new parsing in case of `else` token.
+
+2025-03-31 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-stmt.h (class LetStmt): Add optional expression for diverging else.
+ * ast/rust-ast-builder.cc (Builder::let): Use new API.
+
2025-03-26 Iain Sandoe <iain@sandoe.co.uk>
* metadata/rust-export-metadata.cc
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 4028b47..835e113 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -115,6 +115,7 @@ GRS_OBJS = \
rust/rust-macro-builtins-format-args.o \
rust/rust-macro-builtins-location.o \
rust/rust-macro-builtins-include.o \
+ rust/rust-token-tree-desugar.o \
rust/rust-fmt.o \
rust/rust-hir.o \
rust/rust-hir-map.o \
diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc
index 86290e1..08c52b1 100644
--- a/gcc/rust/ast/rust-ast-builder.cc
+++ b/gcc/rust/ast/rust-ast-builder.cc
@@ -17,6 +17,7 @@
// <http://www.gnu.org/licenses/>.
#include "rust-ast-builder.h"
+#include "optional.h"
#include "rust-ast-builder-type.h"
#include "rust-ast.h"
#include "rust-common.h"
@@ -136,7 +137,7 @@ Builder::tuple (std::vector<std::unique_ptr<Expr>> &&values) const
std::unique_ptr<Param>
Builder::self_ref_param (bool mutability) const
{
- return std::make_unique<SelfParam> (Lifetime::error (), mutability, loc);
+ return std::make_unique<SelfParam> (tl::nullopt, mutability, loc);
}
std::unique_ptr<Param>
@@ -334,9 +335,9 @@ std::unique_ptr<BlockExpr>
Builder::block (std::vector<std::unique_ptr<Stmt>> &&stmts,
std::unique_ptr<Expr> &&tail_expr) const
{
- return std::unique_ptr<BlockExpr> (
- new BlockExpr (std::move (stmts), std::move (tail_expr), {}, {},
- LoopLabel::error (), loc, loc));
+ return std::unique_ptr<BlockExpr> (new BlockExpr (std::move (stmts),
+ std::move (tail_expr), {},
+ {}, tl::nullopt, loc, loc));
}
std::unique_ptr<Expr>
@@ -352,7 +353,7 @@ Builder::let (std::unique_ptr<Pattern> &&pattern, std::unique_ptr<Type> &&type,
{
return std::unique_ptr<Stmt> (new LetStmt (std::move (pattern),
std::move (init), std::move (type),
- {}, loc));
+ tl::nullopt, {}, loc));
}
std::unique_ptr<Expr>
diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc
index 073fa72..c850e96 100644
--- a/gcc/rust/ast/rust-ast-collector.cc
+++ b/gcc/rust/ast/rust-ast-collector.cc
@@ -22,6 +22,7 @@
#include "rust-expr.h"
#include "rust-item.h"
#include "rust-keyword-values.h"
+#include "rust-location.h"
#include "rust-path.h"
#include "rust-system.h"
#include "rust-token.h"
@@ -490,7 +491,7 @@ TokenCollector::visit (ConstGenericParam &param)
if (param.has_default_value ())
{
push (Rust::Token::make (EQUAL, UNDEF_LOCATION));
- visit (param.get_default_value ());
+ visit (param.get_default_value_unchecked ());
}
}
@@ -638,8 +639,6 @@ TokenCollector::visit (GenericArg &arg)
push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (path)));
}
break;
- case GenericArg::Kind::Error:
- rust_unreachable ();
}
}
@@ -1278,7 +1277,7 @@ TokenCollector::visit (ContinueExpr &expr)
{
push (Rust::Token::make (CONTINUE, expr.get_locus ()));
if (expr.has_label ())
- visit (expr.get_label ());
+ visit (expr.get_label_unchecked ());
}
void
@@ -1286,7 +1285,7 @@ TokenCollector::visit (BreakExpr &expr)
{
push (Rust::Token::make (BREAK, expr.get_locus ()));
if (expr.has_label ())
- visit (expr.get_label ());
+ visit (expr.get_label_unchecked ());
if (expr.has_break_expr ())
visit (expr.get_break_expr ());
}
@@ -1521,6 +1520,47 @@ void
TokenCollector::visit (InlineAsm &expr)
{}
+void
+TokenCollector::visit (LlvmInlineAsm &expr)
+{
+ push (Rust::Token::make_identifier (expr.get_locus (), "llvm_asm"));
+ push (Rust::Token::make (EXCLAM, expr.get_locus ()));
+ push (Rust::Token::make (LEFT_PAREN, expr.get_locus ()));
+ for (auto &template_str : expr.get_templates ())
+ push (Rust::Token::make_string (template_str.get_locus (),
+ std::move (template_str.symbol)));
+
+ push (Rust::Token::make (COLON, expr.get_locus ()));
+ for (auto output : expr.get_outputs ())
+ {
+ push (Rust::Token::make_string (expr.get_locus (),
+ std::move (output.constraint)));
+ visit (output.expr);
+ push (Rust::Token::make (COMMA, expr.get_locus ()));
+ }
+
+ push (Rust::Token::make (COLON, expr.get_locus ()));
+ for (auto input : expr.get_inputs ())
+ {
+ push (Rust::Token::make_string (expr.get_locus (),
+ std::move (input.constraint)));
+ visit (input.expr);
+ push (Rust::Token::make (COMMA, expr.get_locus ()));
+ }
+
+ push (Rust::Token::make (COLON, expr.get_locus ()));
+ for (auto &clobber : expr.get_clobbers ())
+ {
+ push (Rust::Token::make_string (expr.get_locus (),
+ std::move (clobber.symbol)));
+ push (Rust::Token::make (COMMA, expr.get_locus ()));
+ }
+ push (Rust::Token::make (COLON, expr.get_locus ()));
+ // Dump options
+
+ push (Rust::Token::make (RIGHT_PAREN, expr.get_locus ()));
+}
+
// rust-item.h
void
@@ -2587,6 +2627,13 @@ TokenCollector::visit (LetStmt &stmt)
push (Rust::Token::make (EQUAL, UNDEF_LOCATION));
visit (stmt.get_init_expr ());
}
+
+ if (stmt.has_else_expr ())
+ {
+ push (Rust::Token::make (ELSE, UNDEF_LOCATION));
+ visit (stmt.get_else_expr ());
+ }
+
push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION));
}
diff --git a/gcc/rust/ast/rust-ast-collector.h b/gcc/rust/ast/rust-ast-collector.h
index b014c23..f45e3cc 100644
--- a/gcc/rust/ast/rust-ast-collector.h
+++ b/gcc/rust/ast/rust-ast-collector.h
@@ -303,6 +303,7 @@ public:
void visit (AwaitExpr &expr);
void visit (AsyncBlockExpr &expr);
void visit (InlineAsm &expr);
+ void visit (LlvmInlineAsm &expr);
// rust-item.h
void visit (TypeParam &param);
void visit (LifetimeWhereClauseItem &item);
diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc
index ba5f87b..b6833f6 100644
--- a/gcc/rust/ast/rust-ast-visitor.cc
+++ b/gcc/rust/ast/rust-ast-visitor.cc
@@ -82,7 +82,7 @@ DefaultASTVisitor::visit (AST::ConstGenericParam &const_param)
if (const_param.has_type ())
visit (const_param.get_type ());
if (const_param.has_default_value ())
- visit (const_param.get_default_value ());
+ visit (const_param.get_default_value_unchecked ());
}
void
@@ -108,7 +108,8 @@ DefaultASTVisitor::visit (GenericArgsBinding &binding)
void
DefaultASTVisitor::visit (AST::TypePathSegmentGeneric &segment)
{
- visit (segment.get_generic_args ());
+ if (segment.has_generic_args ())
+ visit (segment.get_generic_args ());
}
void
@@ -477,7 +478,8 @@ void
DefaultASTVisitor::visit (AST::ContinueExpr &expr)
{
visit_outer_attrs (expr);
- visit (expr.get_label ());
+ if (expr.has_label ())
+ visit (expr.get_label_unchecked ());
}
void
@@ -485,7 +487,7 @@ DefaultASTVisitor::visit (AST::BreakExpr &expr)
{
visit_outer_attrs (expr);
if (expr.has_label ())
- visit (expr.get_label ());
+ visit (expr.get_label_unchecked ());
if (expr.has_break_expr ())
visit (expr.get_break_expr ());
@@ -559,7 +561,8 @@ void
DefaultASTVisitor::visit (AST::LoopExpr &expr)
{
visit_outer_attrs (expr);
- visit (expr.get_loop_label ());
+ if (expr.has_loop_label ())
+ visit (expr.get_loop_label ());
visit (expr.get_loop_block ());
}
@@ -567,8 +570,9 @@ void
DefaultASTVisitor::visit (AST::WhileLoopExpr &expr)
{
visit_outer_attrs (expr);
+ if (expr.has_loop_label ())
+ visit (expr.get_loop_label ());
visit (expr.get_predicate_expr ());
- visit (expr.get_loop_label ());
visit (expr.get_loop_block ());
}
@@ -578,8 +582,8 @@ DefaultASTVisitor::visit (AST::WhileLetLoopExpr &expr)
visit_outer_attrs (expr);
for (auto &pattern : expr.get_patterns ())
visit (pattern);
- visit (expr.get_scrutinee_expr ());
visit (expr.get_loop_label ());
+ visit (expr.get_scrutinee_expr ());
visit (expr.get_loop_block ());
}
@@ -589,7 +593,8 @@ DefaultASTVisitor::visit (AST::ForLoopExpr &expr)
visit_outer_attrs (expr);
visit (expr.get_pattern ());
visit (expr.get_iterator_expr ());
- visit (expr.get_loop_label ());
+ if (expr.has_loop_label ())
+ visit (expr.get_loop_label ());
visit (expr.get_loop_block ());
}
@@ -710,6 +715,16 @@ DefaultASTVisitor::visit (AST::InlineAsm &expr)
}
void
+DefaultASTVisitor::visit (AST::LlvmInlineAsm &expr)
+{
+ for (auto &output : expr.get_outputs ())
+ visit (output.expr);
+
+ for (auto &input : expr.get_inputs ())
+ visit (input.expr);
+}
+
+void
DefaultASTVisitor::visit (AST::TypeParam &param)
{
visit_outer_attrs (param);
@@ -813,10 +828,18 @@ DefaultASTVisitor::visit (AST::UseTreeRebind &use_tree)
void
DefaultASTVisitor::visit (AST::UseDeclaration &use_decl)
{
+ visit (use_decl.get_visibility ());
visit (use_decl.get_tree ());
}
void
+DefaultASTVisitor::visit_function_params (AST::Function &function)
+{
+ for (auto &param : function.get_function_params ())
+ visit (param);
+}
+
+void
DefaultASTVisitor::visit (AST::Function &function)
{
visit_outer_attrs (function);
@@ -824,10 +847,9 @@ DefaultASTVisitor::visit (AST::Function &function)
visit (function.get_qualifiers ());
for (auto &generic : function.get_generic_params ())
visit (generic);
- if (function.has_self_param ())
- visit (function.get_self_param ());
- for (auto &param : function.get_function_params ())
- visit (param);
+
+ visit_function_params (function);
+
if (function.has_return_type ())
visit (function.get_return_type ());
if (function.has_where_clause ())
diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h
index 51661df..b1fc504 100644
--- a/gcc/rust/ast/rust-ast-visitor.h
+++ b/gcc/rust/ast/rust-ast-visitor.h
@@ -131,6 +131,7 @@ public:
virtual void visit (AwaitExpr &expr) = 0;
virtual void visit (AsyncBlockExpr &expr) = 0;
virtual void visit (InlineAsm &expr) = 0;
+ virtual void visit (LlvmInlineAsm &expr) = 0;
// rust-item.h
virtual void visit (TypeParam &param) = 0;
@@ -241,6 +242,8 @@ public:
class DefaultASTVisitor : public ASTVisitor
{
public:
+ virtual void visit_function_params (AST::Function &function);
+
virtual void visit (AST::Crate &crate);
virtual void visit (AST::Token &tok) override;
@@ -314,6 +317,7 @@ public:
virtual void visit (AST::AwaitExpr &expr) override;
virtual void visit (AST::AsyncBlockExpr &expr) override;
virtual void visit (InlineAsm &expr) override;
+ virtual void visit (LlvmInlineAsm &expr) override;
virtual void visit (AST::TypeParam &param) override;
virtual void visit (AST::LifetimeWhereClauseItem &item) override;
diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc
index ab82303..4e82be4 100644
--- a/gcc/rust/ast/rust-ast.cc
+++ b/gcc/rust/ast/rust-ast.cc
@@ -1068,7 +1068,7 @@ Function::Function (Function const &other)
: VisItem (other), ExternalItem (other.get_node_id ()),
qualifiers (other.qualifiers), function_name (other.function_name),
where_clause (other.where_clause), locus (other.locus),
- is_default (other.is_default),
+ has_default (other.has_default),
is_external_function (other.is_external_function)
{
// guard to prevent null dereference (always required)
@@ -1100,7 +1100,7 @@ Function::operator= (Function const &other)
// visibility = other.visibility->clone_visibility();
// outer_attrs = other.outer_attrs;
locus = other.locus;
- is_default = other.is_default;
+ has_default = other.has_default;
is_external_function = other.is_external_function;
// guard to prevent null dereference (always required)
@@ -1631,7 +1631,7 @@ ContinueExpr::as_string () const
std::string str ("continue ");
if (has_label ())
- str += label.as_string ();
+ str += get_label_unchecked ().as_string ();
return str;
}
@@ -2095,7 +2095,7 @@ WhileLoopExpr::as_string () const
if (!has_loop_label ())
str += "none";
else
- str += loop_label.as_string ();
+ str += get_loop_label ().as_string ();
str += "\n Conditional expr: " + condition->as_string ();
@@ -2115,7 +2115,7 @@ WhileLetLoopExpr::as_string () const
if (!has_loop_label ())
str += "none";
else
- str += loop_label.as_string ();
+ str += get_loop_label ().as_string ();
str += "\n Match arm patterns: ";
if (match_arm_patterns.empty ())
@@ -2146,7 +2146,7 @@ LoopExpr::as_string () const
if (!has_loop_label ())
str += "none";
else
- str += loop_label.as_string ();
+ str += get_loop_label ().as_string ();
str += "\n Loop block: " + loop_block->as_string ();
@@ -2183,7 +2183,7 @@ BreakExpr::as_string () const
std::string str ("break ");
if (has_label ())
- str += label.as_string () + " ";
+ str += get_label_unchecked ().as_string () + " ";
if (has_break_expr ())
str += break_expr->as_string ();
@@ -2485,9 +2485,6 @@ MacroMatchRepetition::as_string () const
std::string
Lifetime::as_string () const
{
- if (is_error ())
- return "error lifetime";
-
switch (lifetime_type)
{
case NAMED:
@@ -2545,7 +2542,7 @@ ForLoopExpr::as_string () const
if (!has_loop_label ())
str += "none";
else
- str += loop_label.as_string ();
+ str += get_loop_label ().as_string ();
str += "\n Pattern: " + pattern->as_string ();
@@ -2612,7 +2609,7 @@ ReferenceType::as_string () const
std::string str ("&");
if (has_lifetime ())
- str += lifetime.as_string () + " ";
+ str += get_lifetime ().as_string () + " ";
if (has_mut)
str += "mut ";
@@ -3070,7 +3067,7 @@ SelfParam::as_string () const
else if (has_lifetime ())
{
// ref and lifetime
- std::string str = "&" + lifetime.as_string () + " ";
+ std::string str = "&" + get_lifetime ().as_string () + " ";
if (is_mut)
str += "mut ";
@@ -4654,6 +4651,12 @@ InlineAsm::accept_vis (ASTVisitor &vis)
}
void
+LlvmInlineAsm::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
TypeParam::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 4d7d23d..aa6ad50 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -57,6 +57,11 @@ public:
bool empty () const { return ident.empty (); }
+ bool operator== (const Identifier &other) const
+ {
+ return ident == other.ident;
+ }
+
private:
std::string ident;
location_t loc;
@@ -657,6 +662,9 @@ public:
// Returns whether the attribute is considered an "empty" attribute.
bool is_empty () const { return attr_input == nullptr && path.is_empty (); }
+ // Returns whether the attribute has no input
+ bool empty_input () const { return !attr_input; }
+
location_t get_locus () const { return locus; }
AttrInput &get_attr_input () const { return *attr_input; }
@@ -1015,6 +1023,7 @@ public:
}
DelimType get_delim_type () const { return delim_type; }
+ location_t get_locus () const { return locus; }
};
/* Forward decl - definition moved to rust-expr.h as it requires LiteralExpr
@@ -1260,6 +1269,7 @@ public:
Await,
AsyncBlock,
InlineAsm,
+ LlvmInlineAsm,
Identifier,
FormatArgs,
MacroInvocation,
@@ -1587,17 +1597,9 @@ public:
lifetime_name (std::move (name)), locus (locus)
{}
- // Creates an "error" lifetime.
- static Lifetime error () { return Lifetime (NAMED, ""); }
-
static Lifetime elided () { return Lifetime (WILDCARD, ""); }
// Returns true if the lifetime is in an error state.
- bool is_error () const
- {
- return lifetime_type == NAMED && lifetime_name.empty ();
- }
-
std::string as_string () const override;
void accept_vis (ASTVisitor &vis) override;
@@ -1688,15 +1690,6 @@ public:
// Returns whether the lifetime param has an outer attribute.
bool has_outer_attribute () const { return !outer_attrs.empty (); }
- // Creates an error state lifetime param.
- static LifetimeParam create_error ()
- {
- return LifetimeParam (Lifetime::error (), {}, {}, UNDEF_LOCATION);
- }
-
- // Returns whether the lifetime param is in an error state.
- bool is_error () const { return lifetime.is_error (); }
-
// Constructor
LifetimeParam (Lifetime lifetime, std::vector<Lifetime> lifetime_bounds,
AST::AttrVec outer_attrs, location_t locus)
@@ -2109,6 +2102,19 @@ template <> struct less<Rust::Identifier>
return lhs.as_string () < rhs.as_string ();
}
};
+
+template <> struct hash<Rust::Identifier>
+{
+ std::size_t operator() (const Rust::Identifier &k) const
+ {
+ using std::hash;
+ using std::size_t;
+ using std::string;
+
+ return hash<string> () (k.as_string ()) ^ (hash<int> () (k.get_locus ()));
+ }
+};
+
} // namespace std
#endif
diff --git a/gcc/rust/ast/rust-desugar-for-loops.cc b/gcc/rust/ast/rust-desugar-for-loops.cc
index 5e5cbbc..ffc3470 100644
--- a/gcc/rust/ast/rust-desugar-for-loops.cc
+++ b/gcc/rust/ast/rust-desugar-for-loops.cc
@@ -59,8 +59,8 @@ DesugarForLoops::DesugarCtx::make_break_arm ()
auto arm = make_match_arm (std::unique_ptr<Pattern> (new PathInExpression (
builder.path_in_expression (LangItem::Kind::OPTION_NONE))));
- auto break_expr = std::unique_ptr<Expr> (
- new BreakExpr (Lifetime::error (), nullptr, {}, loc));
+ auto break_expr
+ = std::unique_ptr<Expr> (new BreakExpr (tl::nullopt, nullptr, {}, loc));
return MatchCase (std::move (arm), std::move (break_expr));
}
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h
index cff09fe..fdb6360 100644
--- a/gcc/rust/ast/rust-expr.h
+++ b/gcc/rust/ast/rust-expr.h
@@ -31,11 +31,6 @@ public:
{}
// Returns whether the LoopLabel is in an error state.
- bool is_error () const { return label.is_error (); }
-
- // Creates an error state LoopLabel.
- static LoopLabel error () { return LoopLabel (Lifetime::error ()); }
-
location_t get_locus () const { return locus; }
Lifetime &get_lifetime () { return label; }
@@ -2590,7 +2585,7 @@ class BlockExpr : public ExprWithBlock
std::vector<Attribute> inner_attrs;
std::vector<std::unique_ptr<Stmt> > statements;
std::unique_ptr<Expr> expr;
- LoopLabel label;
+ tl::optional<LoopLabel> label;
location_t start_locus;
location_t end_locus;
bool marked_for_strip = false;
@@ -2607,8 +2602,9 @@ public:
BlockExpr (std::vector<std::unique_ptr<Stmt> > block_statements,
std::unique_ptr<Expr> block_expr,
std::vector<Attribute> inner_attribs,
- std::vector<Attribute> outer_attribs, LoopLabel label,
- location_t start_locus, location_t end_locus)
+ std::vector<Attribute> outer_attribs,
+ tl::optional<LoopLabel> label, location_t start_locus,
+ location_t end_locus)
: outer_attrs (std::move (outer_attribs)),
inner_attrs (std::move (inner_attribs)),
statements (std::move (block_statements)), expr (std::move (block_expr)),
@@ -2727,8 +2723,8 @@ public:
outer_attrs = std::move (new_attrs);
}
- bool has_label () { return !label.is_error (); }
- LoopLabel &get_label () { return label; }
+ bool has_label () { return label.has_value (); }
+ LoopLabel &get_label () { return label.value (); }
Expr::Kind get_expr_kind () const override { return Expr::Kind::Block; }
@@ -2848,7 +2844,7 @@ protected:
class ContinueExpr : public ExprWithoutBlock
{
std::vector<Attribute> outer_attrs;
- Lifetime label;
+ tl::optional<Lifetime> label;
location_t locus;
// TODO: find another way to store this to save memory?
@@ -2858,11 +2854,11 @@ public:
std::string as_string () const override;
// Returns true if the continue expr has a label.
- bool has_label () const { return !label.is_error (); }
+ bool has_label () const { return label.has_value (); }
// Constructor for a ContinueExpr with a label.
- ContinueExpr (Lifetime label, std::vector<Attribute> outer_attribs,
- location_t locus)
+ ContinueExpr (tl::optional<Lifetime> label,
+ std::vector<Attribute> outer_attribs, location_t locus)
: outer_attrs (std::move (outer_attribs)), label (std::move (label)),
locus (locus)
{}
@@ -2883,7 +2879,11 @@ public:
outer_attrs = std::move (new_attrs);
}
- Lifetime &get_label () { return label; }
+ Lifetime &get_label_unchecked () { return label.value (); }
+ const Lifetime &get_label_unchecked () const { return label.value (); }
+
+ tl::optional<Lifetime> &get_label () { return label; }
+ const tl::optional<Lifetime> &get_label () const { return label; }
Expr::Kind get_expr_kind () const override { return Expr::Kind::Continue; }
@@ -2901,7 +2901,7 @@ protected:
class BreakExpr : public ExprWithoutBlock
{
std::vector<Attribute> outer_attrs;
- LoopLabel label;
+ tl::optional<LoopLabel> label;
std::unique_ptr<Expr> break_expr;
location_t locus;
@@ -2912,14 +2912,15 @@ public:
std::string as_string () const override;
// Returns whether the break expression has a label or not.
- bool has_label () const { return !label.is_error (); }
+ bool has_label () const { return label.has_value (); }
/* Returns whether the break expression has an expression used in the break or
* not. */
bool has_break_expr () const { return break_expr != nullptr; }
// Constructor for a break expression
- BreakExpr (LoopLabel break_label, std::unique_ptr<Expr> expr_in_break,
+ BreakExpr (tl::optional<LoopLabel> break_label,
+ std::unique_ptr<Expr> expr_in_break,
std::vector<Attribute> outer_attribs, location_t locus)
: outer_attrs (std::move (outer_attribs)), label (std::move (break_label)),
break_expr (std::move (expr_in_break)), locus (locus)
@@ -2981,7 +2982,11 @@ public:
outer_attrs = std::move (new_attrs);
}
- LoopLabel &get_label () { return label; }
+ LoopLabel &get_label_unchecked () { return label.value (); }
+ const LoopLabel &get_label_unchecked () const { return label.value (); }
+
+ tl::optional<LoopLabel> &get_label () { return label; }
+ const tl::optional<LoopLabel> &get_label () const { return label; }
Expr::Kind get_expr_kind () const override { return Expr::Kind::Break; }
@@ -2999,6 +3004,10 @@ class RangeExpr : public ExprWithoutBlock
{
location_t locus;
+ // Some visitors still check for attributes on RangeExprs, and they will need
+ // to be supported in the future - so keep that for now
+ std::vector<Attribute> empty_attributes = {};
+
protected:
// outer attributes not allowed before range expressions
RangeExpr (location_t locus) : locus (locus) {}
@@ -3008,15 +3017,11 @@ public:
std::vector<Attribute> &get_outer_attrs () override final
{
- // RangeExpr cannot have any outer attributes
- rust_assert (false);
+ return empty_attributes;
}
// should never be called - error if called
- void set_outer_attrs (std::vector<Attribute> /* new_attrs */) override
- {
- rust_assert (false);
- }
+ void set_outer_attrs (std::vector<Attribute> /* new_attrs */) override {}
Expr::Kind get_expr_kind () const override { return Expr::Kind::Range; }
};
@@ -3657,7 +3662,7 @@ class BaseLoopExpr : public ExprWithBlock
protected:
// protected to allow subclasses better use of them
std::vector<Attribute> outer_attrs;
- LoopLabel loop_label;
+ tl::optional<LoopLabel> loop_label;
std::unique_ptr<BlockExpr> loop_block;
private:
@@ -3666,7 +3671,7 @@ private:
protected:
// Constructor for BaseLoopExpr
BaseLoopExpr (std::unique_ptr<BlockExpr> loop_block, location_t locus,
- LoopLabel loop_label = LoopLabel::error (),
+ tl::optional<LoopLabel> loop_label = tl::nullopt,
std::vector<Attribute> outer_attribs
= std::vector<Attribute> ())
: outer_attrs (std::move (outer_attribs)),
@@ -3706,9 +3711,10 @@ protected:
BaseLoopExpr &operator= (BaseLoopExpr &&other) = default;
public:
- bool has_loop_label () const { return !loop_label.is_error (); }
+ bool has_loop_label () const { return loop_label.has_value (); }
- LoopLabel &get_loop_label () { return loop_label; }
+ LoopLabel &get_loop_label () { return loop_label.value (); }
+ const LoopLabel &get_loop_label () const { return loop_label.value (); }
location_t get_locus () const override final { return locus; }
@@ -3752,7 +3758,7 @@ public:
// Constructor for LoopExpr
LoopExpr (std::unique_ptr<BlockExpr> loop_block, location_t locus,
- LoopLabel loop_label = LoopLabel::error (),
+ tl::optional<LoopLabel> loop_label = tl::nullopt,
std::vector<Attribute> outer_attribs = std::vector<Attribute> ())
: BaseLoopExpr (std::move (loop_block), locus, std::move (loop_label),
std::move (outer_attribs))
@@ -3785,7 +3791,7 @@ public:
// Constructor for while loop with loop label
WhileLoopExpr (std::unique_ptr<Expr> loop_condition,
std::unique_ptr<BlockExpr> loop_block, location_t locus,
- LoopLabel loop_label = LoopLabel::error (),
+ tl::optional<LoopLabel> loop_label = tl::nullopt,
std::vector<Attribute> outer_attribs
= std::vector<Attribute> ())
: BaseLoopExpr (std::move (loop_block), locus, std::move (loop_label),
@@ -3851,7 +3857,7 @@ public:
WhileLetLoopExpr (std::vector<std::unique_ptr<Pattern> > match_arm_patterns,
std::unique_ptr<Expr> scrutinee,
std::unique_ptr<BlockExpr> loop_block, location_t locus,
- LoopLabel loop_label = LoopLabel::error (),
+ tl::optional<LoopLabel> loop_label = tl::nullopt,
std::vector<Attribute> outer_attribs
= std::vector<Attribute> ())
: BaseLoopExpr (std::move (loop_block), locus, std::move (loop_label),
@@ -3938,7 +3944,7 @@ public:
ForLoopExpr (std::unique_ptr<Pattern> loop_pattern,
std::unique_ptr<Expr> iterator_expr,
std::unique_ptr<BlockExpr> loop_body, location_t locus,
- LoopLabel loop_label = LoopLabel::error (),
+ tl::optional<LoopLabel> loop_label = tl::nullopt,
std::vector<Attribute> outer_attribs = std::vector<Attribute> ())
: BaseLoopExpr (std::move (loop_body), locus, std::move (loop_label),
std::move (outer_attribs)),
@@ -4879,6 +4885,27 @@ struct InlineAsmRegOrRegClass
location_t locus;
};
+struct LlvmOperand
+{
+ std::string constraint;
+ std::unique_ptr<Expr> expr;
+
+ LlvmOperand (std::string constraint, std::unique_ptr<Expr> &&expr)
+ : constraint (constraint), expr (std::move (expr))
+ {}
+
+ LlvmOperand (const LlvmOperand &other)
+ : constraint (other.constraint), expr (other.expr->clone_expr ())
+ {}
+ LlvmOperand &operator= (const LlvmOperand &other)
+ {
+ constraint = other.constraint;
+ expr = other.expr->clone_expr ();
+
+ return *this;
+ }
+};
+
class InlineAsmOperand
{
public:
@@ -5252,6 +5279,7 @@ struct TupleTemplateStr
location_t loc;
std::string symbol;
+ location_t get_locus () { return loc; }
TupleTemplateStr (location_t loc, const std::string &symbol)
: loc (loc), symbol (symbol)
{}
@@ -5324,6 +5352,77 @@ public:
Expr::Kind get_expr_kind () const override { return Expr::Kind::InlineAsm; }
};
+class LlvmInlineAsm : public ExprWithoutBlock
+{
+ // llvm_asm!("" : : "r"(&mut dummy) : "memory" : "volatile");
+ // Asm, Outputs, Inputs, Clobbers, Options,
+
+public:
+ enum class Dialect
+ {
+ Att,
+ Intel,
+ };
+
+private:
+ location_t locus;
+ std::vector<Attribute> outer_attrs;
+ std::vector<LlvmOperand> inputs;
+ std::vector<LlvmOperand> outputs;
+ std::vector<TupleTemplateStr> templates;
+ std::vector<TupleClobber> clobbers;
+ bool volatility;
+ bool align_stack;
+ Dialect dialect;
+
+public:
+ LlvmInlineAsm (location_t locus) : locus (locus) {}
+
+ Dialect get_dialect () { return dialect; }
+
+ location_t get_locus () const override { return locus; }
+
+ void mark_for_strip () override {}
+
+ bool is_marked_for_strip () const override { return false; }
+
+ std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
+
+ void accept_vis (ASTVisitor &vis) override;
+
+ std::string as_string () const override { return "InlineAsm AST Node"; }
+
+ void set_outer_attrs (std::vector<Attribute> v) override { outer_attrs = v; }
+
+ LlvmInlineAsm *clone_expr_without_block_impl () const override
+ {
+ return new LlvmInlineAsm (*this);
+ }
+
+ std::vector<TupleTemplateStr> &get_templates () { return templates; }
+
+ Expr::Kind get_expr_kind () const override
+ {
+ return Expr::Kind::LlvmInlineAsm;
+ }
+
+ void set_align_stack (bool align_stack) { this->align_stack = align_stack; }
+ bool is_stack_aligned () { return align_stack; }
+
+ void set_volatile (bool volatility) { this->volatility = volatility; }
+ bool is_volatile () { return volatility; }
+
+ void set_dialect (Dialect dialect) { this->dialect = dialect; }
+
+ void set_inputs (std::vector<LlvmOperand> operands) { inputs = operands; }
+ void set_outputs (std::vector<LlvmOperand> operands) { outputs = operands; }
+
+ std::vector<LlvmOperand> &get_inputs () { return inputs; }
+ std::vector<LlvmOperand> &get_outputs () { return outputs; }
+
+ std::vector<TupleClobber> &get_clobbers () { return clobbers; }
+};
+
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 8eb0cc5..062f85d 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -434,13 +434,14 @@ class SelfParam : public Param
bool has_ref;
bool is_mut;
// bool has_lifetime; // only possible if also ref
- Lifetime lifetime;
+ tl::optional<Lifetime> lifetime;
// bool has_type; // only possible if not ref
std::unique_ptr<Type> type;
// Unrestricted constructor used for error state
- SelfParam (Lifetime lifetime, bool has_ref, bool is_mut, Type *type)
+ SelfParam (tl::optional<Lifetime> lifetime, bool has_ref, bool is_mut,
+ Type *type)
: Param ({}, UNDEF_LOCATION), has_ref (has_ref), is_mut (is_mut),
lifetime (std::move (lifetime)), type (type)
{}
@@ -453,7 +454,7 @@ public:
bool has_type () const { return type != nullptr; }
// Returns whether the self-param has a valid lifetime.
- bool has_lifetime () const { return !lifetime.is_error (); }
+ bool has_lifetime () const { return lifetime.has_value (); }
// Returns whether the self-param is in an error state.
bool is_error () const
@@ -472,11 +473,11 @@ public:
// Type-based self parameter (not ref, no lifetime)
SelfParam (std::unique_ptr<Type> type, bool is_mut, location_t locus)
: Param ({}, locus), has_ref (false), is_mut (is_mut),
- lifetime (Lifetime::error ()), type (std::move (type))
+ lifetime (tl::nullopt), type (std::move (type))
{}
// Lifetime-based self parameter (is ref, no type)
- SelfParam (Lifetime lifetime, bool is_mut, location_t locus)
+ SelfParam (tl::optional<Lifetime> lifetime, bool is_mut, location_t locus)
: Param ({}, locus), has_ref (true), is_mut (is_mut),
lifetime (std::move (lifetime))
{}
@@ -522,8 +523,8 @@ public:
bool get_has_ref () const { return has_ref; };
bool get_is_mut () const { return is_mut; }
- Lifetime get_lifetime () const { return lifetime; }
- Lifetime &get_lifetime () { return lifetime; }
+ Lifetime get_lifetime () const { return lifetime.value (); }
+ Lifetime &get_lifetime () { return lifetime.value (); }
NodeId get_node_id () const { return node_id; }
@@ -1330,7 +1331,7 @@ class Function : public VisItem, public AssociatedItem, public ExternalItem
WhereClause where_clause;
tl::optional<std::unique_ptr<BlockExpr>> function_body;
location_t locus;
- bool is_default;
+ bool has_default;
bool is_external_function;
public:
@@ -1355,6 +1356,8 @@ public:
bool has_body () const { return function_body.has_value (); }
+ bool is_default () const { return has_default; }
+
// Mega-constructor with all possible fields
Function (Identifier function_name, FunctionQualifiers qualifiers,
std::vector<std::unique_ptr<GenericParam>> generic_params,
@@ -1362,7 +1365,7 @@ public:
std::unique_ptr<Type> return_type, WhereClause where_clause,
tl::optional<std::unique_ptr<BlockExpr>> function_body,
Visibility vis, std::vector<Attribute> outer_attrs,
- location_t locus, bool is_default = false,
+ location_t locus, bool has_default = false,
bool is_external_function = false)
: VisItem (std::move (vis), std::move (outer_attrs)),
ExternalItem (Stmt::node_id), qualifiers (std::move (qualifiers)),
@@ -1372,7 +1375,7 @@ public:
return_type (std::move (return_type)),
where_clause (std::move (where_clause)),
function_body (std::move (function_body)), locus (locus),
- is_default (is_default), is_external_function (is_external_function)
+ has_default (has_default), is_external_function (is_external_function)
{}
// TODO: add constructor with less fields
diff --git a/gcc/rust/ast/rust-path.cc b/gcc/rust/ast/rust-path.cc
index 69627be..8e43ddf 100644
--- a/gcc/rust/ast/rust-path.cc
+++ b/gcc/rust/ast/rust-path.cc
@@ -119,7 +119,7 @@ ConstGenericParam::as_string () const
str += "const " + name.as_string () + ": " + type->as_string ();
if (has_default_value ())
- str += " = " + get_default_value ().as_string ();
+ str += " = " + get_default_value_unchecked ().as_string ();
return str;
}
diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h
index 805be8e..a4ba93b 100644
--- a/gcc/rust/ast/rust-path.h
+++ b/gcc/rust/ast/rust-path.h
@@ -167,17 +167,11 @@ public:
*/
enum class Kind
{
- Error,
Const, // A const value
Type, // A type argument (not discernable during parsing)
Either, // Either a type or a const value, cleared up during resolving
};
- static GenericArg create_error ()
- {
- return GenericArg (nullptr, nullptr, {""}, Kind::Error, UNDEF_LOCATION);
- }
-
static GenericArg create_const (std::unique_ptr<Expr> expression)
{
auto locus = expression->get_locus ();
@@ -222,8 +216,6 @@ public:
GenericArg (GenericArg &&other) = default;
GenericArg &operator= (GenericArg &&other) = default;
- bool is_error () const { return kind == Kind::Error; }
-
Kind get_kind () const { return kind; }
location_t get_locus () const { return locus; }
@@ -239,8 +231,6 @@ public:
break;
case Kind::Either:
break;
- case Kind::Error:
- rust_unreachable ();
}
}
@@ -283,8 +273,6 @@ public:
{
switch (get_kind ())
{
- case Kind::Error:
- rust_unreachable ();
case Kind::Either:
return "Ambiguous: " + path.as_string ();
case Kind::Const:
@@ -355,15 +343,15 @@ class ConstGenericParam : public GenericParam
/**
* Default value for the const generic parameter
*/
- GenericArg default_value;
+ tl::optional<GenericArg> default_value;
AST::AttrVec outer_attrs;
location_t locus;
public:
ConstGenericParam (Identifier name, std::unique_ptr<AST::Type> type,
- GenericArg default_value, AST::AttrVec outer_attrs,
- location_t locus)
+ tl::optional<GenericArg> default_value,
+ AST::AttrVec outer_attrs, location_t locus)
: name (name), type (std::move (type)),
default_value (std::move (default_value)), outer_attrs (outer_attrs),
locus (locus)
@@ -376,7 +364,7 @@ public:
{}
bool has_type () const { return type != nullptr; }
- bool has_default_value () const { return !default_value.is_error (); }
+ bool has_default_value () const { return default_value.has_value (); }
const Identifier &get_name () const { return name; }
@@ -389,18 +377,18 @@ public:
return *type;
}
- GenericArg &get_default_value ()
+ GenericArg &get_default_value_unchecked ()
{
rust_assert (has_default_value ());
- return default_value;
+ return default_value.value ();
}
- const GenericArg &get_default_value () const
+ const GenericArg &get_default_value_unchecked () const
{
rust_assert (has_default_value ());
- return default_value;
+ return default_value.value ();
}
std::string as_string () const override;
diff --git a/gcc/rust/ast/rust-stmt.h b/gcc/rust/ast/rust-stmt.h
index 6cbecaf..f843a79 100644
--- a/gcc/rust/ast/rust-stmt.h
+++ b/gcc/rust/ast/rust-stmt.h
@@ -19,6 +19,7 @@
#ifndef RUST_AST_STATEMENT_H
#define RUST_AST_STATEMENT_H
+#include "optional.h"
#include "rust-ast.h"
#include "rust-path.h"
#include "rust-expr.h"
@@ -72,6 +73,8 @@ class LetStmt : public Stmt
// bool has_init_expr;
std::unique_ptr<Expr> init_expr;
+ tl::optional<std::unique_ptr<Expr>> else_expr;
+
location_t locus;
public:
@@ -85,15 +88,18 @@ public:
// Returns whether let statement has an initialisation expression.
bool has_init_expr () const { return init_expr != nullptr; }
+ bool has_else_expr () const { return else_expr.has_value (); }
std::string as_string () const override;
LetStmt (std::unique_ptr<Pattern> variables_pattern,
std::unique_ptr<Expr> init_expr, std::unique_ptr<Type> type,
+ tl::optional<std::unique_ptr<Expr>> else_expr,
std::vector<Attribute> outer_attrs, location_t locus)
: outer_attrs (std::move (outer_attrs)),
variables_pattern (std::move (variables_pattern)),
- type (std::move (type)), init_expr (std::move (init_expr)), locus (locus)
+ type (std::move (type)), init_expr (std::move (init_expr)),
+ else_expr (std::move (else_expr)), locus (locus)
{}
// Copy constructor with clone
@@ -107,6 +113,9 @@ public:
// guard to prevent null dereference (always required)
if (other.init_expr != nullptr)
init_expr = other.init_expr->clone_expr ();
+ if (other.else_expr.has_value ())
+ else_expr = other.else_expr.value ()->clone_expr ();
+
if (other.type != nullptr)
type = other.type->clone_type ();
}
@@ -128,6 +137,12 @@ public:
init_expr = other.init_expr->clone_expr ();
else
init_expr = nullptr;
+
+ if (other.else_expr != nullptr)
+ else_expr = other.else_expr.value ()->clone_expr ();
+ else
+ else_expr = tl::nullopt;
+
if (other.type != nullptr)
type = other.type->clone_type ();
else
@@ -162,12 +177,24 @@ public:
return *init_expr;
}
+ Expr &get_else_expr ()
+ {
+ rust_assert (has_else_expr ());
+ return *else_expr.value ();
+ }
+
std::unique_ptr<Expr> &get_init_expr_ptr ()
{
rust_assert (has_init_expr ());
return init_expr;
}
+ std::unique_ptr<Expr> &get_else_expr_ptr ()
+ {
+ rust_assert (has_else_expr ());
+ return else_expr.value ();
+ }
+
Pattern &get_pattern ()
{
rust_assert (variables_pattern != nullptr);
diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h
index 20e0232..1bb521d 100644
--- a/gcc/rust/ast/rust-type.h
+++ b/gcc/rust/ast/rust-type.h
@@ -542,7 +542,7 @@ protected:
class ReferenceType : public TypeNoBounds
{
// bool has_lifetime; // TODO: handle in lifetime or something?
- Lifetime lifetime;
+ tl::optional<Lifetime> lifetime;
bool has_mut;
std::unique_ptr<TypeNoBounds> type;
@@ -553,11 +553,12 @@ public:
bool is_mut () const { return has_mut; }
// Returns whether the reference has a lifetime.
- bool has_lifetime () const { return !lifetime.is_error (); }
+ bool has_lifetime () const { return lifetime.has_value (); }
// Constructor
ReferenceType (bool is_mut, std::unique_ptr<TypeNoBounds> type_no_bounds,
- location_t locus, Lifetime lifetime = Lifetime::elided ())
+ location_t locus,
+ tl::optional<Lifetime> lifetime = Lifetime::elided ())
: lifetime (std::move (lifetime)), has_mut (is_mut),
type (std::move (type_no_bounds)), locus (locus)
{}
@@ -598,7 +599,8 @@ public:
bool get_has_mut () const { return has_mut; }
- Lifetime &get_lifetime () { return lifetime; }
+ Lifetime &get_lifetime () { return lifetime.value (); }
+ const Lifetime &get_lifetime () const { return lifetime.value (); }
TypeNoBounds &get_base_type () { return *type; }
diff --git a/gcc/rust/backend/rust-compile-asm.cc b/gcc/rust/backend/rust-compile-asm.cc
index 22498bc..7351cf0 100644
--- a/gcc/rust/backend/rust-compile-asm.cc
+++ b/gcc/rust/backend/rust-compile-asm.cc
@@ -1,5 +1,7 @@
#include "rust-compile-asm.h"
#include "rust-compile-expr.h"
+#include "rust-system.h"
+
namespace Rust {
namespace Compile {
@@ -141,5 +143,57 @@ CompileAsm::asm_construct_label_tree (HIR::InlineAsm &expr)
return NULL_TREE;
}
+CompileLlvmAsm::CompileLlvmAsm (Context *ctx) : HIRCompileBase (ctx) {}
+
+tree
+CompileLlvmAsm::construct_operands (std::vector<HIR::LlvmOperand> operands)
+{
+ tree head = NULL_TREE;
+ for (auto &operand : operands)
+ {
+ tree t = CompileExpr::Compile (*operand.expr, this->ctx);
+ auto name = build_string (operand.constraint.size () + 1,
+ operand.constraint.c_str ());
+ head = chainon (head,
+ build_tree_list (build_tree_list (NULL_TREE, name), t));
+ }
+ return head;
+}
+
+tree
+CompileLlvmAsm::construct_clobbers (std::vector<AST::TupleClobber> clobbers)
+{
+ tree head = NULL_TREE;
+ for (auto &clobber : clobbers)
+ {
+ auto name
+ = build_string (clobber.symbol.size () + 1, clobber.symbol.c_str ());
+ head = chainon (head, build_tree_list (NULL_TREE, name));
+ }
+ return head;
+}
+
+tree
+CompileLlvmAsm::tree_codegen_asm (HIR::LlvmInlineAsm &expr)
+{
+ tree ret = make_node (ASM_EXPR);
+ TREE_TYPE (ret) = void_type_node;
+ SET_EXPR_LOCATION (ret, expr.get_locus ());
+ ASM_VOLATILE_P (ret) = expr.options.is_volatile;
+
+ std::stringstream ss;
+ for (const auto &template_str : expr.templates)
+ {
+ ss << template_str.symbol << "\n";
+ }
+
+ ASM_STRING (ret) = Backend::string_constant_expression (ss.str ());
+ ASM_INPUTS (ret) = construct_operands (expr.inputs);
+ ASM_OUTPUTS (ret) = construct_operands (expr.outputs);
+ ASM_CLOBBERS (ret) = construct_clobbers (expr.get_clobbers ());
+
+ return ret;
+}
+
} // namespace Compile
} // namespace Rust
diff --git a/gcc/rust/backend/rust-compile-asm.h b/gcc/rust/backend/rust-compile-asm.h
index 4abd24e..22be94a 100644
--- a/gcc/rust/backend/rust-compile-asm.h
+++ b/gcc/rust/backend/rust-compile-asm.h
@@ -56,6 +56,20 @@ public:
tree tree_codegen_asm (HIR::InlineAsm &);
};
+
+class CompileLlvmAsm : private HIRCompileBase
+{
+private:
+ tree construct_operands (std::vector<HIR::LlvmOperand> operands);
+
+ tree construct_clobbers (std::vector<AST::TupleClobber>);
+
+public:
+ CompileLlvmAsm (Context *ctx);
+
+ tree tree_codegen_asm (HIR::LlvmInlineAsm &);
+};
+
} // namespace Compile
} // namespace Rust
#endif // RUST_COMPILE_ASM
diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc
index bcc7fc4..12b9561 100644
--- a/gcc/rust/backend/rust-compile-base.cc
+++ b/gcc/rust/backend/rust-compile-base.cc
@@ -549,7 +549,7 @@ HIRCompileBase::mark_addressable (tree exp, location_t locus)
}
tree
-HIRCompileBase::address_expression (tree expr, location_t location)
+HIRCompileBase::address_expression (tree expr, location_t location, tree ptrty)
{
if (expr == error_mark_node)
return error_mark_node;
@@ -557,7 +557,22 @@ HIRCompileBase::address_expression (tree expr, location_t location)
if (!mark_addressable (expr, location))
return error_mark_node;
- return build_fold_addr_expr_loc (location, expr);
+ if (ptrty == NULL || ptrty == error_mark_node)
+ ptrty = build_pointer_type (TREE_TYPE (expr));
+
+ return build_fold_addr_expr_with_type_loc (location, expr, ptrty);
+}
+
+tree
+HIRCompileBase::compile_constant_expr (
+ Context *ctx, HirId coercion_id, TyTy::BaseType *resolved_type,
+ TyTy::BaseType *expected_type, const Resolver::CanonicalPath &canonical_path,
+ HIR::Expr &const_value_expr, location_t locus, location_t expr_locus)
+{
+ HIRCompileBase c (ctx);
+ return c.compile_constant_item (coercion_id, resolved_type, expected_type,
+ canonical_path, const_value_expr, locus,
+ expr_locus);
}
tree
@@ -651,7 +666,8 @@ get_abi (const AST::AttrVec &outer_attrs,
tree
HIRCompileBase::compile_function (
- const std::string &fn_name, HIR::SelfParam &self_param,
+ bool is_root_item, const std::string &fn_name,
+ tl::optional<HIR::SelfParam> &self_param,
std::vector<HIR::FunctionParam> &function_params,
const HIR::FunctionQualifiers &qualifiers, HIR::Visibility &visibility,
AST::AttrVec &outer_attrs, location_t locus, HIR::BlockExpr *function_body,
@@ -662,7 +678,7 @@ HIRCompileBase::compile_function (
= canonical_path.get () + fntype->subst_as_string ();
// we don't mangle the main fn since we haven't implemented the main shim
- bool is_main_fn = fn_name.compare ("main") == 0;
+ bool is_main_fn = fn_name.compare ("main") == 0 && is_root_item;
if (is_main_fn)
{
rust_assert (!main_identifier_node);
@@ -698,24 +714,24 @@ HIRCompileBase::compile_function (
// setup the params
TyTy::BaseType *tyret = fntype->get_return_type ();
std::vector<Bvariable *> param_vars;
- if (!self_param.is_error ())
+ if (self_param)
{
rust_assert (fntype->is_method ());
TyTy::BaseType *self_tyty_lookup = fntype->get_self_type ();
tree self_type = TyTyResolveCompile::compile (ctx, self_tyty_lookup);
Bvariable *compiled_self_param
- = CompileSelfParam::compile (ctx, fndecl, self_param, self_type,
- self_param.get_locus ());
+ = CompileSelfParam::compile (ctx, fndecl, self_param.value (),
+ self_type, self_param->get_locus ());
param_vars.push_back (compiled_self_param);
- ctx->insert_var_decl (self_param.get_mappings ().get_hirid (),
+ ctx->insert_var_decl (self_param->get_mappings ().get_hirid (),
compiled_self_param);
}
// offset from + 1 for the TyTy::FnType being used when this is a method to
// skip over Self on the FnType
- bool is_method = !self_param.is_error ();
+ bool is_method = self_param.has_value ();
size_t i = is_method ? 1 : 0;
for (auto &referenced_param : function_params)
{
@@ -1011,7 +1027,7 @@ HIRCompileBase::resolve_method_address (TyTy::FnType *fntype,
tree
HIRCompileBase::unit_expression (location_t locus)
{
- tree unit_type = TyTyResolveCompile::get_unit_type ();
+ tree unit_type = TyTyResolveCompile::get_unit_type (ctx);
return Backend::constructor_expression (unit_type, false, {}, -1, locus);
}
diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h
index 9328a7f..6814abc 100644
--- a/gcc/rust/backend/rust-compile-base.h
+++ b/gcc/rust/backend/rust-compile-base.h
@@ -29,7 +29,14 @@ class HIRCompileBase
public:
virtual ~HIRCompileBase () {}
- static tree address_expression (tree expr, location_t locus);
+ static tree address_expression (tree expr, location_t locus,
+ tree ptrty = NULL_TREE);
+
+ static tree compile_constant_expr (
+ Context *ctx, HirId coercion_id, TyTy::BaseType *resolved_type,
+ TyTy::BaseType *expected_type,
+ const Resolver::CanonicalPath &canonical_path, HIR::Expr &const_value_expr,
+ location_t locus, location_t expr_locus);
protected:
HIRCompileBase (Context *ctx) : ctx (ctx) {}
@@ -96,7 +103,8 @@ protected:
HIR::Expr &const_value_expr, location_t locus,
location_t expr_locus);
- tree compile_function (const std::string &fn_name, HIR::SelfParam &self_param,
+ tree compile_function (bool is_root_item, const std::string &fn_name,
+ tl::optional<HIR::SelfParam> &self_param,
std::vector<HIR::FunctionParam> &function_params,
const HIR::FunctionQualifiers &qualifiers,
HIR::Visibility &visibility, AST::AttrVec &outer_attrs,
@@ -104,7 +112,7 @@ protected:
const Resolver::CanonicalPath &canonical_path,
TyTy::FnType *fntype);
- static tree unit_expression (location_t locus);
+ tree unit_expression (location_t locus);
void setup_fndecl (tree fndecl, bool is_main_entry_point, bool is_generic_fn,
HIR::Visibility &visibility,
diff --git a/gcc/rust/backend/rust-compile-block.h b/gcc/rust/backend/rust-compile-block.h
index 37e3980..3f38d08 100644
--- a/gcc/rust/backend/rust-compile-block.h
+++ b/gcc/rust/backend/rust-compile-block.h
@@ -100,6 +100,7 @@ public:
void visit (HIR::AwaitExpr &) override {}
void visit (HIR::AsyncBlockExpr &) override {}
void visit (HIR::InlineAsm &) override {}
+ void visit (HIR::LlvmInlineAsm &) override {}
private:
CompileConditionalBlocks (Context *ctx, Bvariable *result)
@@ -182,6 +183,7 @@ public:
void visit (HIR::AwaitExpr &) override {}
void visit (HIR::AsyncBlockExpr &) override {}
void visit (HIR::InlineAsm &) override {}
+ void visit (HIR::LlvmInlineAsm &) override {}
private:
CompileExprWithBlock (Context *ctx, Bvariable *result)
diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h
index a446388..ce81a1d 100644
--- a/gcc/rust/backend/rust-compile-context.h
+++ b/gcc/rust/backend/rust-compile-context.h
@@ -72,7 +72,10 @@ public:
return it->second;
compiled_type_map.insert ({h, type});
- push_type (type);
+
+ if (TYPE_NAME (type) != NULL)
+ push_type (type);
+
return type;
}
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index 21f4ca1..dd3420f 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -368,6 +368,13 @@ CompileExpr::visit (HIR::InlineAsm &expr)
}
void
+CompileExpr::visit (HIR::LlvmInlineAsm &expr)
+{
+ CompileLlvmAsm asm_codegen (ctx);
+ ctx->add_statement (asm_codegen.tree_codegen_asm (expr));
+}
+
+void
CompileExpr::visit (HIR::IfExprConseqElse &expr)
{
TyTy::BaseType *if_type = nullptr;
@@ -905,7 +912,8 @@ CompileExpr::visit (HIR::BorrowExpr &expr)
&tyty))
return;
- translated = address_expression (main_expr, expr.get_locus ());
+ tree expected_type = TyTyResolveCompile::compile (ctx, tyty);
+ translated = address_expression (main_expr, expr.get_locus (), expected_type);
}
void
@@ -1902,6 +1910,14 @@ CompileExpr::array_value_expr (location_t expr_locus,
for (auto &elem : elems.get_values ())
{
tree translated_expr = CompileExpr::Compile (*elem, ctx);
+ if (translated_expr == error_mark_node)
+ {
+ rich_location r (line_table, expr_locus);
+ r.add_fixit_replace (elem->get_locus (), "not a value");
+ rust_error_at (r, ErrorCode::E0423, "expected value");
+ return error_mark_node;
+ }
+
constructor.push_back (translated_expr);
indexes.push_back (i++);
}
@@ -1956,8 +1972,12 @@ CompileExpr::array_copied_expr (location_t expr_locus,
if (ctx->const_context_p ())
{
size_t idx = 0;
+
std::vector<unsigned long> indexes;
std::vector<tree> constructor;
+
+ indexes.reserve (len);
+ constructor.reserve (len);
for (unsigned HOST_WIDE_INT i = 0; i < len; i++)
{
constructor.push_back (translated_expr);
@@ -2003,6 +2023,9 @@ HIRCompileBase::resolve_adjustements (
tree e = expression;
for (auto &adjustment : adjustments)
{
+ if (e == error_mark_node)
+ return error_mark_node;
+
switch (adjustment.get_type ())
{
case Resolver::Adjustment::AdjustmentType::ERROR:
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h
index dc78dee..65ed4b3 100644
--- a/gcc/rust/backend/rust-compile-expr.h
+++ b/gcc/rust/backend/rust-compile-expr.h
@@ -69,6 +69,7 @@ public:
void visit (HIR::RangeFromToInclExpr &expr) override;
void visit (HIR::ClosureExpr &expr) override;
void visit (HIR::InlineAsm &expr) override;
+ void visit (HIR::LlvmInlineAsm &expr) override;
// TODO
void visit (HIR::ErrorPropagationExpr &) override {}
diff --git a/gcc/rust/backend/rust-compile-extern.h b/gcc/rust/backend/rust-compile-extern.h
index bacd1c0..d6aa589 100644
--- a/gcc/rust/backend/rust-compile-extern.h
+++ b/gcc/rust/backend/rust-compile-extern.h
@@ -34,16 +34,10 @@ class CompileExternItem : public HIRCompileBase,
public:
static tree compile (HIR::ExternalItem *item, Context *ctx,
TyTy::BaseType *concrete = nullptr,
- bool is_query_mode = false,
location_t ref_locus = UNDEF_LOCATION)
{
CompileExternItem compiler (ctx, concrete, ref_locus);
item->accept_vis (compiler);
-
- if (is_query_mode && compiler.reference == error_mark_node)
- rust_internal_error_at (ref_locus, "failed to compile extern item: %s",
- item->as_string ().c_str ());
-
return compiler.reference;
}
diff --git a/gcc/rust/backend/rust-compile-implitem.cc b/gcc/rust/backend/rust-compile-implitem.cc
index 71b3e8d..1230c85 100644
--- a/gcc/rust/backend/rust-compile-implitem.cc
+++ b/gcc/rust/backend/rust-compile-implitem.cc
@@ -117,7 +117,7 @@ CompileTraitItem::visit (HIR::TraitItemFunc &func)
auto vis = HIR::Visibility (HIR::Visibility::VisType::PUBLIC);
HIR::TraitFunctionDecl &function = func.get_decl ();
tree fndecl
- = compile_function (function.get_function_name ().as_string (),
+ = compile_function (false, function.get_function_name ().as_string (),
function.get_self (), function.get_function_params (),
function.get_qualifiers (), vis,
func.get_outer_attrs (), func.get_locus (),
diff --git a/gcc/rust/backend/rust-compile-implitem.h b/gcc/rust/backend/rust-compile-implitem.h
index d2ef989..2d18dbf 100644
--- a/gcc/rust/backend/rust-compile-implitem.h
+++ b/gcc/rust/backend/rust-compile-implitem.h
@@ -30,16 +30,10 @@ class CompileInherentImplItem : public CompileItem
public:
static tree Compile (HIR::ImplItem *item, Context *ctx,
TyTy::BaseType *concrete = nullptr,
- bool is_query_mode = false,
location_t ref_locus = UNDEF_LOCATION)
{
CompileInherentImplItem compiler (ctx, concrete, ref_locus);
item->accept_vis (compiler);
-
- if (is_query_mode && compiler.reference == error_mark_node)
- rust_internal_error_at (ref_locus, "failed to compile impl item: %s",
- item->as_string ().c_str ());
-
return compiler.reference;
}
diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc
index fb0c661..4888e23 100644
--- a/gcc/rust/backend/rust-compile-intrinsic.cc
+++ b/gcc/rust/backend/rust-compile-intrinsic.cc
@@ -1322,7 +1322,7 @@ try_handler_inner (Context *ctx, TyTy::FnType *fntype, bool is_new_api)
if (is_new_api)
{
- auto ret_type = TyTyResolveCompile::get_unit_type ();
+ auto ret_type = TyTyResolveCompile::get_unit_type (ctx);
auto ret_expr = Backend::constructor_expression (ret_type, false, {}, -1,
UNDEF_LOCATION);
normal_return_stmt
diff --git a/gcc/rust/backend/rust-compile-item.cc b/gcc/rust/backend/rust-compile-item.cc
index 7ce9848..9666990 100644
--- a/gcc/rust/backend/rust-compile-item.cc
+++ b/gcc/rust/backend/rust-compile-item.cc
@@ -252,8 +252,12 @@ CompileItem::visit (HIR::Function &function)
if (function.get_qualifiers ().is_const ())
ctx->push_const_context ();
+ auto lookup_root_item = ctx->get_mappings ().lookup_hir_item (
+ function.get_mappings ().get_hirid ());
+ bool is_root_item = lookup_root_item.has_value ();
tree fndecl
- = compile_function (function.get_function_name ().as_string (),
+ = compile_function (is_root_item,
+ function.get_function_name ().as_string (),
function.get_self_param (),
function.get_function_params (),
function.get_qualifiers (), function.get_visibility (),
diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h
index eccb040..d9d946d 100644
--- a/gcc/rust/backend/rust-compile-item.h
+++ b/gcc/rust/backend/rust-compile-item.h
@@ -35,10 +35,6 @@ public:
{
CompileItem compiler (ctx, concrete, ref_locus);
item->accept_vis (compiler);
-
- if (compiler.reference == error_mark_node)
- rust_debug ("failed to compile item: %s", item->as_string ().c_str ());
-
return compiler.reference;
}
diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc
index 2b6880c..81d2dbb 100644
--- a/gcc/rust/backend/rust-compile-resolve-path.cc
+++ b/gcc/rust/backend/rust-compile-resolve-path.cc
@@ -105,7 +105,9 @@ ResolvePathRef::attempt_constructor_expression_lookup (
// make the ctor for the union
HIR::Expr &discrim_expr = variant->get_discriminant ();
+ ctx->push_const_context ();
tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx);
+ ctx->pop_const_context ();
tree folded_discrim_expr = fold_expr (discrim_expr_node);
tree qualifier = folded_discrim_expr;
@@ -259,10 +261,10 @@ HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup,
HIR::ExternalItem *resolved_extern_item = hir_extern_item->first;
if (!lookup->has_substitutions_defined ())
return CompileExternItem::compile (resolved_extern_item, ctx, nullptr,
- true, expr_locus);
+ expr_locus);
else
return CompileExternItem::compile (resolved_extern_item, ctx, lookup,
- true, expr_locus);
+ expr_locus);
}
else
{
@@ -284,10 +286,10 @@ HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup,
{
if (!lookup->has_substitutions_defined ())
return CompileInherentImplItem::Compile (resolved_item->first, ctx,
- nullptr, true, expr_locus);
+ nullptr, expr_locus);
else
return CompileInherentImplItem::Compile (resolved_item->first, ctx,
- lookup, true, expr_locus);
+ lookup, expr_locus);
}
else if (auto trait_item
= ctx->get_mappings ().lookup_hir_trait_item (ref))
@@ -301,6 +303,27 @@ HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup,
trait->get_mappings ().get_defid (), &trait_ref);
rust_assert (ok);
+ if (trait_item.value ()->get_item_kind ()
+ == HIR::TraitItem::TraitItemKind::CONST)
+ {
+ auto &c
+ = *static_cast<HIR::TraitItemConst *> (trait_item.value ());
+ if (!c.has_expr ())
+ {
+ rich_location r (line_table, expr_locus);
+ r.add_range (trait->get_locus ());
+ r.add_range (c.get_locus ());
+ rust_error_at (r, "no default expression on trait constant");
+ return error_mark_node;
+ }
+
+ return CompileExpr::Compile (c.get_expr (), ctx);
+ }
+
+ if (trait_item.value ()->get_item_kind ()
+ != HIR::TraitItem::TraitItemKind::FUNC)
+ return error_mark_node;
+
// the type resolver can only resolve type bounds to their trait
// item so its up to us to figure out if this path should resolve
// to an trait-impl-block-item or if it can be defaulted to the
@@ -349,11 +372,10 @@ HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup,
if (!lookup->has_substitutions_defined ())
return CompileInherentImplItem::Compile (impl_item, ctx,
- nullptr, true,
- expr_locus);
+ nullptr, expr_locus);
else
return CompileInherentImplItem::Compile (impl_item, ctx, lookup,
- true, expr_locus);
+ expr_locus);
}
}
}
diff --git a/gcc/rust/backend/rust-compile-type.cc b/gcc/rust/backend/rust-compile-type.cc
index d8af1d1..83e5756 100644
--- a/gcc/rust/backend/rust-compile-type.cc
+++ b/gcc/rust/backend/rust-compile-type.cc
@@ -81,13 +81,22 @@ TyTyResolveCompile::get_implicit_enumeral_node_type (TyTy::BaseType *repr)
}
tree
-TyTyResolveCompile::get_unit_type ()
+TyTyResolveCompile::get_unit_type (Context *ctx)
{
static tree unit_type;
if (unit_type == nullptr)
{
+ auto cn = ctx->get_mappings ().get_current_crate ();
+ auto &c = ctx->get_mappings ().get_ast_crate (cn);
+ location_t locus = BUILTINS_LOCATION;
+ if (c.items.size () > 0)
+ {
+ auto &item = c.items[0];
+ locus = item->get_locus ();
+ }
+
auto unit_type_node = Backend::struct_type ({});
- unit_type = Backend::named_type ("()", unit_type_node, BUILTINS_LOCATION);
+ unit_type = Backend::named_type ("()", unit_type_node, locus);
}
return unit_type;
}
@@ -421,7 +430,7 @@ TyTyResolveCompile::visit (const TyTy::TupleType &type)
{
if (type.num_fields () == 0)
{
- translated = get_unit_type ();
+ translated = get_unit_type (ctx);
return;
}
@@ -456,12 +465,24 @@ TyTyResolveCompile::visit (const TyTy::ArrayType &type)
= TyTyResolveCompile::compile (ctx, type.get_element_type ());
ctx->push_const_context ();
- tree capacity_expr = CompileExpr::Compile (type.get_capacity_expr (), ctx);
+
+ HIR::Expr &hir_capacity_expr = type.get_capacity_expr ();
+ TyTy::BaseType *capacity_expr_ty = nullptr;
+ bool ok = ctx->get_tyctx ()->lookup_type (
+ hir_capacity_expr.get_mappings ().get_hirid (), &capacity_expr_ty);
+ rust_assert (ok);
+ tree capacity_expr = HIRCompileBase::compile_constant_expr (
+ ctx, hir_capacity_expr.get_mappings ().get_hirid (), capacity_expr_ty,
+ capacity_expr_ty, Resolver::CanonicalPath::create_empty (),
+ hir_capacity_expr, type.get_locus (), hir_capacity_expr.get_locus ());
+
ctx->pop_const_context ();
tree folded_capacity_expr = fold_expr (capacity_expr);
translated = Backend::array_type (element_type, folded_capacity_expr);
+ if (translated != error_mark_node)
+ translated = ctx->insert_compiled_type (translated);
}
void
@@ -714,7 +735,7 @@ TyTyResolveCompile::visit (const TyTy::StrType &type)
void
TyTyResolveCompile::visit (const TyTy::NeverType &)
{
- translated = get_unit_type ();
+ translated = get_unit_type (ctx);
}
void
diff --git a/gcc/rust/backend/rust-compile-type.h b/gcc/rust/backend/rust-compile-type.h
index bc611cf..7ebc4a6 100644
--- a/gcc/rust/backend/rust-compile-type.h
+++ b/gcc/rust/backend/rust-compile-type.h
@@ -30,7 +30,7 @@ public:
static tree compile (Context *ctx, const TyTy::BaseType *ty,
bool trait_object_mode = false);
- static tree get_unit_type ();
+ static tree get_unit_type (Context *ctx);
void visit (const TyTy::InferType &) override;
void visit (const TyTy::ADTType &) override;
diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc
index 7b00066..dbd8515 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -338,7 +338,7 @@ HIRCompileBase::compute_address_for_trait_item (
}
return CompileInherentImplItem::Compile (associated_function, ctx,
- lookup_fntype, true, locus);
+ lookup_fntype, locus);
}
// we can only compile trait-items with a body
diff --git a/gcc/rust/backend/rust-constexpr.cc b/gcc/rust/backend/rust-constexpr.cc
index 2f2bbbd..dc2d6b1 100644
--- a/gcc/rust/backend/rust-constexpr.cc
+++ b/gcc/rust/backend/rust-constexpr.cc
@@ -2697,10 +2697,8 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval,
}
if (TREE_CODE (probe) == ARRAY_REF)
{
- // TODO
- rust_unreachable ();
- // elt = eval_and_check_array_index (ctx, probe, false,
- // non_constant_p, overflow_p);
+ elt = eval_and_check_array_index (ctx, probe, false,
+ non_constant_p, overflow_p);
if (*non_constant_p)
return t;
}
diff --git a/gcc/rust/checks/errors/borrowck/ffi-polonius/.cargo/config.toml b/gcc/rust/checks/errors/borrowck/ffi-polonius/.cargo/config.toml
deleted file mode 100644
index 0236928..0000000
--- a/gcc/rust/checks/errors/borrowck/ffi-polonius/.cargo/config.toml
+++ /dev/null
@@ -1,5 +0,0 @@
-[source.crates-io]
-replace-with = "vendored-sources"
-
-[source.vendored-sources]
-directory = "vendor"
diff --git a/gcc/rust/checks/errors/borrowck/ffi-polonius/Cargo.lock b/gcc/rust/checks/errors/borrowck/ffi-polonius/Cargo.lock
index f7cbd41..1b223b6 100644
--- a/gcc/rust/checks/errors/borrowck/ffi-polonius/Cargo.lock
+++ b/gcc/rust/checks/errors/borrowck/ffi-polonius/Cargo.lock
@@ -1,12 +1,8 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
-version = 3
-
[[package]]
name = "datafrog"
version = "2.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0afaad2b26fa326569eb264b1363e8ae3357618c43982b3f285f0774ce76b69"
[[package]]
name = "ffi-polonius"
@@ -18,14 +14,10 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "polonius-engine"
version = "0.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4e8e505342045d397d0b6674dcb82d6faf5cf40484d30eeb88fc82ef14e903f"
dependencies = [
"datafrog",
"log",
@@ -35,5 +27,3 @@ dependencies = [
[[package]]
name = "rustc-hash"
version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
diff --git a/gcc/rust/checks/errors/borrowck/ffi-polonius/Cargo.toml b/gcc/rust/checks/errors/borrowck/ffi-polonius/Cargo.toml
index 71315c3..3bc8e3f 100644
--- a/gcc/rust/checks/errors/borrowck/ffi-polonius/Cargo.toml
+++ b/gcc/rust/checks/errors/borrowck/ffi-polonius/Cargo.toml
@@ -1,11 +1,17 @@
[package]
name = "ffi-polonius"
version = "0.1.0"
-edition = "2021"
+edition = "2018"
license = "GPL-3"
[lib]
crate-type = ["staticlib"]
[dependencies]
-polonius-engine = "0.13.0" \ No newline at end of file
+polonius-engine = "0.13.0"
+
+[patch.crates-io]
+log = { path = "vendor/log" }
+datafrog = { path = "vendor/datafrog" }
+polonius-engine = { path = "vendor/polonius-engine" }
+rustc-hash = { path = "vendor/rustc-hash" }
diff --git a/gcc/rust/checks/errors/borrowck/ffi-polonius/vendor/log/Cargo.toml b/gcc/rust/checks/errors/borrowck/ffi-polonius/vendor/log/Cargo.toml
index 313a005..a199e31 100644
--- a/gcc/rust/checks/errors/borrowck/ffi-polonius/vendor/log/Cargo.toml
+++ b/gcc/rust/checks/errors/borrowck/ffi-polonius/vendor/log/Cargo.toml
@@ -10,7 +10,7 @@
# See Cargo.toml.orig for the original contents.
[package]
-edition = "2021"
+edition = "2018"
rust-version = "1.60.0"
name = "log"
version = "0.4.22"
diff --git a/gcc/rust/checks/errors/borrowck/ffi-polonius/vendor/log/src/lib.rs b/gcc/rust/checks/errors/borrowck/ffi-polonius/vendor/log/src/lib.rs
index 6b43a9a..603bbac 100644
--- a/gcc/rust/checks/errors/borrowck/ffi-polonius/vendor/log/src/lib.rs
+++ b/gcc/rust/checks/errors/borrowck/ffi-polonius/vendor/log/src/lib.rs
@@ -397,20 +397,13 @@ mod serde;
#[cfg(feature = "kv")]
pub mod kv;
-#[cfg(target_has_atomic = "ptr")]
-use std::sync::atomic::{AtomicUsize, Ordering};
-
-#[cfg(not(target_has_atomic = "ptr"))]
use std::cell::Cell;
-#[cfg(not(target_has_atomic = "ptr"))]
use std::sync::atomic::Ordering;
-#[cfg(not(target_has_atomic = "ptr"))]
struct AtomicUsize {
v: Cell<usize>,
}
-#[cfg(not(target_has_atomic = "ptr"))]
impl AtomicUsize {
const fn new(v: usize) -> AtomicUsize {
AtomicUsize { v: Cell::new(v) }
@@ -423,26 +416,10 @@ impl AtomicUsize {
fn store(&self, val: usize, _order: Ordering) {
self.v.set(val)
}
-
- #[cfg(target_has_atomic = "ptr")]
- fn compare_exchange(
- &self,
- current: usize,
- new: usize,
- _success: Ordering,
- _failure: Ordering,
- ) -> Result<usize, usize> {
- let prev = self.v.get();
- if current == prev {
- self.v.set(new);
- }
- Ok(prev)
- }
}
// Any platform without atomics is unlikely to have multiple cores, so
// writing via Cell will not be a race condition.
-#[cfg(not(target_has_atomic = "ptr"))]
unsafe impl Sync for AtomicUsize {}
// The LOGGER static holds a pointer to the global logger. It is protected by
@@ -1258,17 +1235,6 @@ where
}
}
-/// Sets the global maximum log level.
-///
-/// Generally, this should only be called by the active logging implementation.
-///
-/// Note that `Trace` is the maximum level, because it provides the maximum amount of detail in the emitted logs.
-#[inline]
-#[cfg(target_has_atomic = "ptr")]
-pub fn set_max_level(level: LevelFilter) {
- MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::Relaxed);
-}
-
/// A thread-unsafe version of [`set_max_level`].
///
/// This function is available on all platforms, even those that do not have
@@ -1320,110 +1286,6 @@ pub fn max_level() -> LevelFilter {
unsafe { mem::transmute(MAX_LOG_LEVEL_FILTER.load(Ordering::Relaxed)) }
}
-/// Sets the global logger to a `Box<Log>`.
-///
-/// This is a simple convenience wrapper over `set_logger`, which takes a
-/// `Box<Log>` rather than a `&'static Log`. See the documentation for
-/// [`set_logger`] for more details.
-///
-/// Requires the `std` feature.
-///
-/// # Errors
-///
-/// An error is returned if a logger has already been set.
-///
-/// [`set_logger`]: fn.set_logger.html
-#[cfg(all(feature = "std", target_has_atomic = "ptr"))]
-pub fn set_boxed_logger(logger: Box<dyn Log>) -> Result<(), SetLoggerError> {
- set_logger_inner(|| Box::leak(logger))
-}
-
-/// Sets the global logger to a `&'static Log`.
-///
-/// This function may only be called once in the lifetime of a program. Any log
-/// events that occur before the call to `set_logger` completes will be ignored.
-///
-/// This function does not typically need to be called manually. Logger
-/// implementations should provide an initialization method that installs the
-/// logger internally.
-///
-/// # Availability
-///
-/// This method is available even when the `std` feature is disabled. However,
-/// it is currently unavailable on `thumbv6` targets, which lack support for
-/// some atomic operations which are used by this function. Even on those
-/// targets, [`set_logger_racy`] will be available.
-///
-/// # Errors
-///
-/// An error is returned if a logger has already been set.
-///
-/// # Examples
-///
-/// ```
-/// use log::{error, info, warn, Record, Level, Metadata, LevelFilter};
-///
-/// static MY_LOGGER: MyLogger = MyLogger;
-///
-/// struct MyLogger;
-///
-/// impl log::Log for MyLogger {
-/// fn enabled(&self, metadata: &Metadata) -> bool {
-/// metadata.level() <= Level::Info
-/// }
-///
-/// fn log(&self, record: &Record) {
-/// if self.enabled(record.metadata()) {
-/// println!("{} - {}", record.level(), record.args());
-/// }
-/// }
-/// fn flush(&self) {}
-/// }
-///
-/// # fn main(){
-/// log::set_logger(&MY_LOGGER).unwrap();
-/// log::set_max_level(LevelFilter::Info);
-///
-/// info!("hello log");
-/// warn!("warning");
-/// error!("oops");
-/// # }
-/// ```
-///
-/// [`set_logger_racy`]: fn.set_logger_racy.html
-#[cfg(target_has_atomic = "ptr")]
-pub fn set_logger(logger: &'static dyn Log) -> Result<(), SetLoggerError> {
- set_logger_inner(|| logger)
-}
-
-#[cfg(target_has_atomic = "ptr")]
-fn set_logger_inner<F>(make_logger: F) -> Result<(), SetLoggerError>
-where
- F: FnOnce() -> &'static dyn Log,
-{
- match STATE.compare_exchange(
- UNINITIALIZED,
- INITIALIZING,
- Ordering::Acquire,
- Ordering::Relaxed,
- ) {
- Ok(UNINITIALIZED) => {
- unsafe {
- LOGGER = make_logger();
- }
- STATE.store(INITIALIZED, Ordering::Release);
- Ok(())
- }
- Err(INITIALIZING) => {
- while STATE.load(Ordering::Relaxed) == INITIALIZING {
- std::hint::spin_loop();
- }
- Err(SetLoggerError(()))
- }
- _ => Err(SetLoggerError(())),
- }
-}
-
/// A thread-unsafe version of [`set_logger`].
///
/// This function is available on all platforms, even those that do not have
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
index d6acc6a..6b8b2e9 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
@@ -325,6 +325,10 @@ ExprStmtBuilder::visit (HIR::InlineAsm &expr)
{}
void
+ExprStmtBuilder::visit (HIR::LlvmInlineAsm &expr)
+{}
+
+void
ExprStmtBuilder::visit (HIR::MethodCallExpr &expr)
{}
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h
index daedb68..5cab3c4 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h
@@ -100,6 +100,7 @@ protected: // Expr
void visit (HIR::IfExpr &expr) override;
void visit (HIR::IfExprConseqElse &expr) override;
void visit (HIR::InlineAsm &expr) override;
+ void visit (HIR::LlvmInlineAsm &expr) override;
void visit (HIR::MatchExpr &expr) override;
void visit (HIR::AwaitExpr &expr) override;
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h
index 3bc622c..b7a1555 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h
@@ -207,6 +207,7 @@ public:
}
void visit (HIR::InlineAsm &expr) override {}
+ void visit (HIR::LlvmInlineAsm &expr) override {}
protected: // Illegal at this position.
void visit (HIR::StructExprFieldIdentifier &field) override
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h
index 94fcecd..84311cc 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h
@@ -153,6 +153,7 @@ protected:
void visit (HIR::AwaitExpr &expr) override { rust_unreachable (); }
void visit (HIR::AsyncBlockExpr &expr) override { rust_unreachable (); }
void visit (HIR::InlineAsm &expr) override { rust_unreachable (); }
+ void visit (HIR::LlvmInlineAsm &expr) override { rust_unreachable (); }
void visit (HIR::TypeParam &param) override { rust_unreachable (); }
void visit (HIR::ConstGenericParam &param) override { rust_unreachable (); }
void visit (HIR::LifetimeWhereClauseItem &item) override
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-place.h b/gcc/rust/checks/errors/borrowck/rust-bir-place.h
index 67ca90b..dd9e672 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-place.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-place.h
@@ -204,6 +204,9 @@ template <typename I, typename T> class IndexVec
{
std::vector<T> internal_vector;
+ typedef decltype (std::declval<I> ().value) size_type;
+ static constexpr auto MAX_INDEX = std::numeric_limits<size_type>::max ();
+
public:
IndexVec () = default;
IndexVec (size_t size) { internal_vector.reserve (size); }
@@ -219,7 +222,11 @@ public:
internal_vector.emplace_back (std::forward<Args> (args)...);
}
- size_t size () const { return internal_vector.size (); }
+ size_type size () const
+ {
+ rust_assert (internal_vector.size () < MAX_INDEX);
+ return static_cast<size_type> (internal_vector.size ());
+ }
std::vector<T> &get_vector () { return internal_vector; }
};
@@ -418,8 +425,7 @@ public:
if (lookup != INVALID_PLACE)
return lookup;
- add_place ({Place::VARIABLE, id, {}, is_type_copy (tyty), tyty});
- return {places.size () - 1};
+ return add_place ({Place::VARIABLE, id, {}, is_type_copy (tyty), tyty});
};
template <typename FN> void for_each_path_from_root (PlaceId var, FN fn) const
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir.h b/gcc/rust/checks/errors/borrowck/rust-bir.h
index e90e508..8a5f7be 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir.h
@@ -35,6 +35,26 @@ using BasicBlocks = IndexVec<BasicBlockId, BasicBlock>;
class Statement;
class AbstractExpr;
+/** Unique identifier for a basic block in the BIR. */
+struct BasicBlockId
+{
+ uint32_t value;
+ // some overloads for comparision
+ bool operator== (const BasicBlockId &rhs) const { return value == rhs.value; }
+ bool operator!= (const BasicBlockId &rhs) const
+ {
+ return !(operator== (rhs));
+ }
+ bool operator< (const BasicBlockId &rhs) const { return value < rhs.value; }
+ bool operator> (const BasicBlockId &rhs) const { return value > rhs.value; }
+ bool operator<= (const BasicBlockId &rhs) const { return !(operator> (rhs)); }
+ bool operator>= (const BasicBlockId &rhs) const { return !(operator< (rhs)); }
+};
+
+static constexpr BasicBlockId INVALID_BB
+ = {std::numeric_limits<uint32_t>::max ()};
+static constexpr BasicBlockId ENTRY_BASIC_BLOCK = {0};
+
/**
* Top-level entity of the Borrow-checker IR (BIR).
* It represents a single function (method, closure, etc.), which is the
@@ -132,26 +152,6 @@ public:
WARN_UNUSED_RESULT location_t get_location () const { return location; }
};
-/** Unique identifier for a basic block in the BIR. */
-struct BasicBlockId
-{
- uint32_t value;
- // some overloads for comparision
- bool operator== (const BasicBlockId &rhs) const { return value == rhs.value; }
- bool operator!= (const BasicBlockId &rhs) const
- {
- return !(operator== (rhs));
- }
- bool operator< (const BasicBlockId &rhs) const { return value < rhs.value; }
- bool operator> (const BasicBlockId &rhs) const { return value > rhs.value; }
- bool operator<= (const BasicBlockId &rhs) const { return !(operator> (rhs)); }
- bool operator>= (const BasicBlockId &rhs) const { return !(operator< (rhs)); }
-};
-
-static constexpr BasicBlockId INVALID_BB
- = {std::numeric_limits<uint32_t>::max ()};
-static constexpr BasicBlockId ENTRY_BASIC_BLOCK = {0};
-
struct BasicBlock
{
// BIR "instructions".
diff --git a/gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.cc b/gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.cc
index 6c67706..adf1448 100644
--- a/gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.cc
@@ -142,7 +142,7 @@ BorrowCheckerDiagnostics::get_statement (Polonius::Point point)
const BIR::Loan &
BorrowCheckerDiagnostics::get_loan (Polonius::Loan loan)
{
- return bir_function.place_db.get_loans ()[{loan}];
+ return bir_function.place_db.get_loans ()[{(uint32_t) loan}];
}
const HIR::LifetimeParam *
diff --git a/gcc/rust/checks/errors/borrowck/rust-function-collector.h b/gcc/rust/checks/errors/borrowck/rust-function-collector.h
index cdb20e8..7cf0952 100644
--- a/gcc/rust/checks/errors/borrowck/rust-function-collector.h
+++ b/gcc/rust/checks/errors/borrowck/rust-function-collector.h
@@ -123,6 +123,7 @@ public:
void visit (HIR::AwaitExpr &expr) override {}
void visit (HIR::AsyncBlockExpr &expr) override {}
void visit (HIR::InlineAsm &expr) override {}
+ void visit (HIR::LlvmInlineAsm &expr) override {}
void visit (HIR::TypeParam &param) override {}
void visit (HIR::ConstGenericParam &param) override {}
void visit (HIR::LifetimeWhereClauseItem &item) override {}
diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
index a537c42..2a10053 100644
--- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
+++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
@@ -306,6 +306,10 @@ PrivacyReporter::visit (HIR::InlineAsm &)
{}
void
+PrivacyReporter::visit (HIR::LlvmInlineAsm &)
+{}
+
+void
PrivacyReporter::visit (HIR::TypePath &path)
{
check_for_privacy_violation (path.get_mappings ().get_nodeid (),
diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
index 5111a3e..7df2cf4 100644
--- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
+++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
@@ -125,6 +125,7 @@ types
virtual void visit (HIR::AwaitExpr &expr);
virtual void visit (HIR::AsyncBlockExpr &expr);
virtual void visit (HIR::InlineAsm &expr);
+ virtual void visit (HIR::LlvmInlineAsm &expr);
virtual void visit (HIR::EnumItemTuple &);
virtual void visit (HIR::EnumItemStruct &);
diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc b/gcc/rust/checks/errors/rust-ast-validation.cc
index 59b2805..0f4bdeb 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.cc
+++ b/gcc/rust/checks/errors/rust-ast-validation.cc
@@ -56,7 +56,7 @@ ASTValidation::visit (AST::LoopLabel &label)
void
ASTValidation::visit (AST::ConstantItem &const_item)
{
- if (!const_item.has_expr () && ctx.peek () != Kind::TRAIT_IMPL)
+ if (!const_item.has_expr () && ctx.peek () != Kind::TRAIT)
{
rust_error_at (const_item.get_locus (),
"associated constant in %<impl%> without body");
diff --git a/gcc/rust/checks/errors/rust-const-checker.cc b/gcc/rust/checks/errors/rust-const-checker.cc
index 4904322..3716ea5 100644
--- a/gcc/rust/checks/errors/rust-const-checker.cc
+++ b/gcc/rust/checks/errors/rust-const-checker.cc
@@ -537,6 +537,10 @@ ConstChecker::visit (InlineAsm &)
{}
void
+ConstChecker::visit (LlvmInlineAsm &)
+{}
+
+void
ConstChecker::visit (TypeParam &)
{}
@@ -646,6 +650,9 @@ ConstChecker::visit (Enum &enum_item)
{
check_default_const_generics (enum_item.get_generic_params (),
ConstGenericCtx::Enum);
+
+ for (auto &item : enum_item.get_variants ())
+ item->accept_vis (*this);
}
void
diff --git a/gcc/rust/checks/errors/rust-const-checker.h b/gcc/rust/checks/errors/rust-const-checker.h
index 00f57988..b954330 100644
--- a/gcc/rust/checks/errors/rust-const-checker.h
+++ b/gcc/rust/checks/errors/rust-const-checker.h
@@ -132,6 +132,7 @@ private:
virtual void visit (AwaitExpr &expr) override;
virtual void visit (AsyncBlockExpr &expr) override;
virtual void visit (InlineAsm &expr) override;
+ virtual void visit (LlvmInlineAsm &expr) override;
virtual void visit (TypeParam &param) override;
virtual void visit (ConstGenericParam &param) override;
diff --git a/gcc/rust/checks/errors/rust-feature-gate.cc b/gcc/rust/checks/errors/rust-feature-gate.cc
index f3daa61..44007f9 100644
--- a/gcc/rust/checks/errors/rust-feature-gate.cc
+++ b/gcc/rust/checks/errors/rust-feature-gate.cc
@@ -40,6 +40,13 @@ FeatureGate::visit (AST::Crate &crate)
{
if (attr.get_path ().as_string () == "feature")
{
+ // check for empty feature, such as `#![feature], this is an error
+ if (attr.empty_input ())
+ {
+ rust_error_at (attr.get_locus (), ErrorCode::E0556,
+ "malformed %<feature%> attribute input");
+ continue;
+ }
const auto &attr_input = attr.get_attr_input ();
auto type = attr_input.get_attr_input_type ();
if (type == AST::AttrInput::AttrInputType::TOKEN_TREE)
diff --git a/gcc/rust/checks/errors/rust-feature.cc b/gcc/rust/checks/errors/rust-feature.cc
index 25af46c..441a1b2 100644
--- a/gcc/rust/checks/errors/rust-feature.cc
+++ b/gcc/rust/checks/errors/rust-feature.cc
@@ -55,6 +55,9 @@ Feature::create (Feature::Name f)
"1.11.0", 37854);
case Feature::Name::PRELUDE_IMPORT:
return Feature (f, Feature::State::ACTIVE, "prelude_import", "1.0.0");
+ case Feature::Name::MIN_SPECIALIZATION:
+ return Feature (f, Feature::State::ACTIVE, "min_specialization",
+ "1.0.0" /* FIXME: What version here? */, 31844);
case Feature::Name::AUTO_TRAITS:
return Feature (f, Feature::State::ACTIVE, "optin_builtin_traits",
"1.0.0", 13231);
@@ -80,6 +83,7 @@ const std::map<std::string, Feature::Name> Feature::name_hash_map = {
{"raw_ref_op", Feature::Name::RAW_REF_OP},
{"exclusive_range_pattern", Feature::Name::EXCLUSIVE_RANGE_PATTERN},
{"prelude_import", Feature::Name::PRELUDE_IMPORT},
+ {"min_specialization", Feature::Name::MIN_SPECIALIZATION},
}; // namespace Rust
tl::optional<Feature::Name>
diff --git a/gcc/rust/checks/errors/rust-feature.h b/gcc/rust/checks/errors/rust-feature.h
index 9edae6d..e7cb0af 100644
--- a/gcc/rust/checks/errors/rust-feature.h
+++ b/gcc/rust/checks/errors/rust-feature.h
@@ -51,6 +51,7 @@ public:
RAW_REF_OP,
EXCLUSIVE_RANGE_PATTERN,
PRELUDE_IMPORT,
+ MIN_SPECIALIZATION,
};
const std::string &as_string () { return m_name_str; }
diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
index 257f4cd..648bc07 100644
--- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
+++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
@@ -423,6 +423,10 @@ PatternChecker::visit (InlineAsm &expr)
{}
void
+PatternChecker::visit (LlvmInlineAsm &expr)
+{}
+
+void
PatternChecker::visit (TypeParam &)
{}
diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h
index 2171340..6d60ced 100644
--- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h
+++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h
@@ -106,6 +106,7 @@ private:
virtual void visit (AwaitExpr &expr) override;
virtual void visit (AsyncBlockExpr &expr) override;
virtual void visit (InlineAsm &expr) override;
+ virtual void visit (LlvmInlineAsm &expr) override;
virtual void visit (TypeParam &param) override;
virtual void visit (ConstGenericParam &param) override;
virtual void visit (LifetimeWhereClauseItem &item) override;
diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.cc b/gcc/rust/checks/errors/rust-unsafe-checker.cc
index 8aa59ee..46eef11 100644
--- a/gcc/rust/checks/errors/rust-unsafe-checker.cc
+++ b/gcc/rust/checks/errors/rust-unsafe-checker.cc
@@ -481,9 +481,14 @@ UnsafeChecker::visit (MethodCallExpr &expr)
TyTy::BaseType *method_type;
context.lookup_type (expr.get_method_name ().get_mappings ().get_hirid (),
&method_type);
+ if (!method_type || !method_type->is<TyTy::FnType> ())
+ return;
auto &fn = static_cast<TyTy::FnType &> (*method_type);
+ // FIXME
+ // should probably use the defid lookup instead
+ // tl::optional<HIR::Item *> lookup_defid (DefId id);
auto method = mappings.lookup_hir_implitem (fn.get_ref ());
if (!unsafe_context.is_in_context () && method)
check_unsafe_call (static_cast<Function *> (method->first),
@@ -666,6 +671,17 @@ UnsafeChecker::visit (InlineAsm &expr)
}
void
+UnsafeChecker::visit (LlvmInlineAsm &expr)
+{
+ if (unsafe_context.is_in_context ())
+ return;
+
+ rust_error_at (
+ expr.get_locus (), ErrorCode::E0133,
+ "use of inline assembly is unsafe and requires unsafe function or block");
+}
+
+void
UnsafeChecker::visit (TypeParam &)
{}
diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.h b/gcc/rust/checks/errors/rust-unsafe-checker.h
index 63098fe..9a8fb7c 100644
--- a/gcc/rust/checks/errors/rust-unsafe-checker.h
+++ b/gcc/rust/checks/errors/rust-unsafe-checker.h
@@ -114,6 +114,7 @@ private:
virtual void visit (AwaitExpr &expr) override;
virtual void visit (AsyncBlockExpr &expr) override;
virtual void visit (InlineAsm &expr) override;
+ virtual void visit (LlvmInlineAsm &expr) override;
virtual void visit (TypeParam &param) override;
virtual void visit (ConstGenericParam &param) override;
virtual void visit (LifetimeWhereClauseItem &item) override;
diff --git a/gcc/rust/expand/rust-derive-clone.cc b/gcc/rust/expand/rust-derive-clone.cc
index 074ea01..321fa00 100644
--- a/gcc/rust/expand/rust-derive-clone.cc
+++ b/gcc/rust/expand/rust-derive-clone.cc
@@ -61,11 +61,10 @@ std::unique_ptr<AssociatedItem>
DeriveClone::clone_fn (std::unique_ptr<Expr> &&clone_expr)
{
auto block = std::unique_ptr<BlockExpr> (
- new BlockExpr ({}, std::move (clone_expr), {}, {}, AST::LoopLabel::error (),
- loc, loc));
+ new BlockExpr ({}, std::move (clone_expr), {}, {}, tl::nullopt, loc, loc));
auto big_self_type = builder.single_type_path ("Self");
- std::unique_ptr<SelfParam> self (new SelfParam (Lifetime::error (),
+ std::unique_ptr<SelfParam> self (new SelfParam (tl::nullopt,
/* is_mut */ false, loc));
std::vector<std::unique_ptr<Param>> params;
@@ -294,8 +293,14 @@ DeriveClone::clone_enum_struct (PathInExpression variant_path,
new ReferencePattern (std::unique_ptr<Pattern> (new StructPattern (
variant_path, loc, pattern_elts)),
false, false, loc));
+
+ PathInExpression new_path (variant_path.get_segments (),
+ variant_path.get_outer_attrs (),
+ variant_path.get_locus (),
+ variant_path.opening_scope_resolution ());
+
auto expr = std::unique_ptr<Expr> (
- new StructExprStructFields (variant_path, std::move (cloned_fields), loc));
+ new StructExprStructFields (new_path, std::move (cloned_fields), loc));
return builder.match_case (std::move (pattern), std::move (expr));
}
diff --git a/gcc/rust/expand/rust-derive-debug.cc b/gcc/rust/expand/rust-derive-debug.cc
index 7ad3908..a0bf9d8 100644
--- a/gcc/rust/expand/rust-derive-debug.cc
+++ b/gcc/rust/expand/rust-derive-debug.cc
@@ -50,8 +50,7 @@ DeriveDebug::stub_debug_fn ()
// we can't use builder.block() here as it returns a unique_ptr<Expr> and
// Function's constructor expects a unique_ptr<BlockExpr>
auto block = std::unique_ptr<BlockExpr> (
- new BlockExpr ({}, std::move (stub_return), {}, {},
- AST::LoopLabel::error (), loc, loc));
+ new BlockExpr ({}, std::move (stub_return), {}, {}, tl::nullopt, loc, loc));
auto self = builder.self_ref_param ();
diff --git a/gcc/rust/expand/rust-derive-default.cc b/gcc/rust/expand/rust-derive-default.cc
index c54f8c3..2e8b456 100644
--- a/gcc/rust/expand/rust-derive-default.cc
+++ b/gcc/rust/expand/rust-derive-default.cc
@@ -58,8 +58,7 @@ DeriveDefault::default_fn (std::unique_ptr<Expr> &&return_expr)
= std::unique_ptr<Type> (new TypePath (builder.type_path ("Self")));
auto block = std::unique_ptr<BlockExpr> (
- new BlockExpr ({}, std::move (return_expr), {}, {},
- AST::LoopLabel::error (), loc, loc));
+ new BlockExpr ({}, std::move (return_expr), {}, {}, tl::nullopt, loc, loc));
return builder.function ("default", {}, std::move (self_ty),
std::move (block));
diff --git a/gcc/rust/expand/rust-derive-eq.cc b/gcc/rust/expand/rust-derive-eq.cc
index dc173de..5e7a894 100644
--- a/gcc/rust/expand/rust-derive-eq.cc
+++ b/gcc/rust/expand/rust-derive-eq.cc
@@ -49,8 +49,7 @@ DeriveEq::assert_receiver_is_total_eq_fn (
stmts.emplace_back (assert_type_is_eq (std::move (type)));
auto block = std::unique_ptr<BlockExpr> (
- new BlockExpr (std::move (stmts), nullptr, {}, {}, AST::LoopLabel::error (),
- loc, loc));
+ new BlockExpr (std::move (stmts), nullptr, {}, {}, tl::nullopt, loc, loc));
auto self = builder.self_ref_param ();
diff --git a/gcc/rust/expand/rust-derive.h b/gcc/rust/expand/rust-derive.h
index d8cc0a4..5fca49c 100644
--- a/gcc/rust/expand/rust-derive.h
+++ b/gcc/rust/expand/rust-derive.h
@@ -171,6 +171,7 @@ private:
virtual void visit (AwaitExpr &expr) override final{};
virtual void visit (AsyncBlockExpr &expr) override final{};
virtual void visit (InlineAsm &expr) override final{};
+ virtual void visit (LlvmInlineAsm &expr) override final{};
virtual void visit (TypeParam &param) override final{};
virtual void visit (LifetimeWhereClauseItem &item) override final{};
virtual void visit (TypeBoundWhereClauseItem &item) override final{};
diff --git a/gcc/rust/expand/rust-expand-visitor.cc b/gcc/rust/expand/rust-expand-visitor.cc
index d4db313..42df5e1 100644
--- a/gcc/rust/expand/rust-expand-visitor.cc
+++ b/gcc/rust/expand/rust-expand-visitor.cc
@@ -489,7 +489,8 @@ ExpandVisitor::visit (AST::PathInExpression &path)
void
ExpandVisitor::visit (AST::TypePathSegmentGeneric &segment)
{
- expand_generic_args (segment.get_generic_args ());
+ if (segment.has_generic_args ())
+ expand_generic_args (segment.get_generic_args ());
}
void
diff --git a/gcc/rust/expand/rust-macro-builtins-asm.cc b/gcc/rust/expand/rust-macro-builtins-asm.cc
index 4d02604..e255729 100644
--- a/gcc/rust/expand/rust-macro-builtins-asm.cc
+++ b/gcc/rust/expand/rust-macro-builtins-asm.cc
@@ -22,6 +22,7 @@
#include "rust-ast.h"
#include "rust-fmt.h"
#include "rust-stmt.h"
+#include "rust-parse.h"
namespace Rust {
std::map<AST::InlineAsmOption, std::string> InlineAsmOptionMap{
@@ -660,6 +661,15 @@ MacroBuiltin::asm_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
return parse_asm (invoc_locus, invoc, semicolon, is_global_asm);
}
+tl::optional<AST::Fragment>
+MacroBuiltin::llvm_asm_handler (location_t invoc_locus,
+ AST::MacroInvocData &invoc,
+ AST::InvocKind semicolon,
+ AST::AsmKind is_global_asm)
+{
+ return parse_llvm_asm (invoc_locus, invoc, semicolon, is_global_asm);
+}
+
tl::expected<InlineAsmContext, InlineAsmParseError>
parse_asm_arg (InlineAsmContext inline_asm_ctx)
{
@@ -671,6 +681,14 @@ parse_asm_arg (InlineAsmContext inline_asm_ctx)
{
token = parser.peek_current_token ();
+ if (token->get_id () == COLON || token->get_id () == SCOPE_RESOLUTION)
+ {
+ rust_error_at (
+ token->get_locus (),
+ "the legacy LLVM-style %<asm!%> syntax is no longer supported");
+ return tl::unexpected<InlineAsmParseError> (COMMITTED);
+ }
+
// We accept a comma token here.
if (token->get_id () != COMMA
&& inline_asm_ctx.consumed_comma_without_formatted_string)
@@ -962,4 +980,223 @@ validate (InlineAsmContext inline_asm_ctx)
{
return tl::expected<InlineAsmContext, InlineAsmParseError> (inline_asm_ctx);
}
+
+tl::optional<LlvmAsmContext>
+parse_llvm_templates (LlvmAsmContext ctx)
+{
+ auto &parser = ctx.parser;
+
+ auto token = parser.peek_current_token ();
+
+ if (token->get_id () == ctx.last_token_id
+ || token->get_id () != STRING_LITERAL)
+ {
+ return tl::nullopt;
+ }
+
+ ctx.llvm_asm.get_templates ().emplace_back (token->get_locus (),
+ strip_double_quotes (
+ token->as_string ()));
+ ctx.parser.skip_token ();
+
+ token = parser.peek_current_token ();
+ if (token->get_id () != ctx.last_token_id && token->get_id () != COLON
+ && token->get_id () != SCOPE_RESOLUTION)
+ {
+ // We do not handle multiple template string, we provide minimal support
+ // for the black_box intrinsics.
+ rust_unreachable ();
+ }
+
+ return ctx;
+}
+
+tl::optional<LlvmAsmContext>
+parse_llvm_arguments (LlvmAsmContext ctx)
+{
+ auto &parser = ctx.parser;
+ enum State
+ {
+ Templates = 0,
+ Output,
+ Input,
+ Clobbers,
+ Options
+ } current_state
+ = State::Templates;
+
+ while (parser.peek_current_token ()->get_id () != ctx.last_token_id
+ && parser.peek_current_token ()->get_id () != END_OF_FILE)
+ {
+ if (parser.peek_current_token ()->get_id () == SCOPE_RESOLUTION)
+ {
+ parser.skip_token (SCOPE_RESOLUTION);
+ current_state = static_cast<State> (current_state + 2);
+ }
+ else
+ {
+ parser.skip_token (COLON);
+ current_state = static_cast<State> (current_state + 1);
+ }
+
+ switch (current_state)
+ {
+ case State::Output:
+ parse_llvm_outputs (ctx);
+ break;
+ case State::Input:
+ parse_llvm_inputs (ctx);
+ break;
+ case State::Clobbers:
+ parse_llvm_clobbers (ctx);
+ break;
+ case State::Options:
+ parse_llvm_options (ctx);
+ break;
+ case State::Templates:
+ default:
+ rust_unreachable ();
+ }
+ }
+
+ return ctx;
+}
+
+void
+parse_llvm_operands (LlvmAsmContext &ctx, std::vector<AST::LlvmOperand> &result)
+{
+ auto &parser = ctx.parser;
+ auto token = parser.peek_current_token ();
+ while (token->get_id () != COLON && token->get_id () != SCOPE_RESOLUTION
+ && token->get_id () != ctx.last_token_id)
+ {
+ std::string constraint;
+ if (token->get_id () == STRING_LITERAL)
+ {
+ constraint = strip_double_quotes (token->as_string ());
+ }
+ parser.skip_token (STRING_LITERAL);
+ parser.skip_token (LEFT_PAREN);
+
+ token = parser.peek_current_token ();
+
+ ParseRestrictions restrictions;
+ restrictions.expr_can_be_null = true;
+ auto expr = parser.parse_expr ();
+
+ parser.skip_token (RIGHT_PAREN);
+
+ result.emplace_back (constraint, std::move (expr));
+
+ if (parser.peek_current_token ()->get_id () == COMMA)
+ parser.skip_token (COMMA);
+
+ token = parser.peek_current_token ();
+ }
+}
+
+void
+parse_llvm_outputs (LlvmAsmContext &ctx)
+{
+ parse_llvm_operands (ctx, ctx.llvm_asm.get_outputs ());
+}
+
+void
+parse_llvm_inputs (LlvmAsmContext &ctx)
+{
+ parse_llvm_operands (ctx, ctx.llvm_asm.get_inputs ());
+}
+
+void
+parse_llvm_clobbers (LlvmAsmContext &ctx)
+{
+ auto &parser = ctx.parser;
+ auto token = parser.peek_current_token ();
+ while (token->get_id () != COLON && token->get_id () != ctx.last_token_id)
+ {
+ if (token->get_id () == STRING_LITERAL)
+ {
+ ctx.llvm_asm.get_clobbers ().push_back (
+ {strip_double_quotes (token->as_string ()), token->get_locus ()});
+ }
+ parser.skip_token (STRING_LITERAL);
+ token = parser.peek_current_token ();
+ }
+}
+
+void
+parse_llvm_options (LlvmAsmContext &ctx)
+{
+ auto &parser = ctx.parser;
+ auto token = parser.peek_current_token ();
+
+ while (token->get_id () != ctx.last_token_id)
+ {
+ if (token->get_id () == STRING_LITERAL)
+ {
+ auto token_str = strip_double_quotes (token->as_string ());
+
+ if (token_str == "volatile")
+ ctx.llvm_asm.set_volatile (true);
+ else if (token_str == "alignstack")
+ ctx.llvm_asm.set_align_stack (true);
+ else if (token_str == "intel")
+ ctx.llvm_asm.set_dialect (AST::LlvmInlineAsm::Dialect::Intel);
+ else
+ rust_error_at (token->get_locus (),
+ "Unknown llvm assembly option %qs",
+ token_str.c_str ());
+ }
+ parser.skip_token (STRING_LITERAL);
+
+ token = parser.peek_current_token ();
+
+ if (token->get_id () == ctx.last_token_id)
+ continue;
+ parser.skip_token (COMMA);
+ }
+
+ parser.skip_token ();
+}
+
+tl::optional<AST::Fragment>
+parse_llvm_asm (location_t invoc_locus, AST::MacroInvocData &invoc,
+ AST::InvocKind semicolon, AST::AsmKind is_global_asm)
+{
+ MacroInvocLexer lex (invoc.get_delim_tok_tree ().to_token_stream ());
+ Parser<MacroInvocLexer> parser (lex);
+ auto last_token_id = macro_end_token (invoc.get_delim_tok_tree (), parser);
+
+ AST::LlvmInlineAsm llvm_asm{invoc_locus};
+
+ auto asm_ctx = LlvmAsmContext (llvm_asm, parser, last_token_id);
+
+ auto resulting_context
+ = parse_llvm_templates (asm_ctx).and_then (parse_llvm_arguments);
+
+ if (resulting_context)
+ {
+ auto node = (*resulting_context).llvm_asm.clone_expr_without_block ();
+
+ std::vector<AST::SingleASTNode> single_vec = {};
+
+ // If the macro invocation has a semicolon (`asm!("...");`), then we
+ // need to make it a statement. This way, it will be expanded
+ // properly.
+ if (semicolon == AST::InvocKind::Semicoloned)
+ single_vec.emplace_back (AST::SingleASTNode (
+ std::make_unique<AST::ExprStmt> (std::move (node), invoc_locus,
+ semicolon
+ == AST::InvocKind::Semicoloned)));
+ else
+ single_vec.emplace_back (AST::SingleASTNode (std::move (node)));
+
+ AST::Fragment fragment_ast
+ = AST::Fragment (single_vec,
+ std::vector<std::unique_ptr<AST::Token>> ());
+ return fragment_ast;
+ }
+ return tl::nullopt;
+}
+
} // namespace Rust
diff --git a/gcc/rust/expand/rust-macro-builtins-asm.h b/gcc/rust/expand/rust-macro-builtins-asm.h
index 8081dae..bd64a7f 100644
--- a/gcc/rust/expand/rust-macro-builtins-asm.h
+++ b/gcc/rust/expand/rust-macro-builtins-asm.h
@@ -172,4 +172,36 @@ tl::optional<std::string>
parse_label (Parser<MacroInvocLexer> &parser, TokenId last_token_id,
InlineAsmContext &inline_asm_ctx);
+// LLVM ASM bits
+
+class LlvmAsmContext
+{
+public:
+ AST::LlvmInlineAsm &llvm_asm;
+ Parser<MacroInvocLexer> &parser;
+ int last_token_id;
+
+public:
+ LlvmAsmContext (AST::LlvmInlineAsm &llvm_asm, Parser<MacroInvocLexer> &parser,
+ int last_token_id)
+ : llvm_asm (llvm_asm), parser (parser), last_token_id (last_token_id)
+ {}
+};
+
+void
+parse_llvm_outputs (LlvmAsmContext &ctx);
+
+void
+parse_llvm_inputs (LlvmAsmContext &ctx);
+
+void
+parse_llvm_clobbers (LlvmAsmContext &ctx);
+
+void
+parse_llvm_options (LlvmAsmContext &ctx);
+
+WARN_UNUSED_RESULT tl::optional<AST::Fragment>
+parse_llvm_asm (location_t invoc_locus, AST::MacroInvocData &invoc,
+ AST::InvocKind semicolon, AST::AsmKind is_global_asm);
+
} // namespace Rust
diff --git a/gcc/rust/expand/rust-macro-builtins-format-args.cc b/gcc/rust/expand/rust-macro-builtins-format-args.cc
index 8eb32d5..3e1249d 100644
--- a/gcc/rust/expand/rust-macro-builtins-format-args.cc
+++ b/gcc/rust/expand/rust-macro-builtins-format-args.cc
@@ -55,6 +55,8 @@ format_args_parse_arguments (AST::MacroInvocData &invoc)
if (parser.peek_current_token ()->get_id () == STRING_LITERAL)
format_expr = parser.parse_literal_expr ();
+ rust_assert (format_expr);
+
// TODO(Arthur): Clean this up - if we haven't parsed a string literal but a
// macro invocation, what do we do here? return a tl::unexpected?
auto format_str = static_cast<AST::LiteralExpr &> (*format_expr)
@@ -81,6 +83,11 @@ format_args_parse_arguments (AST::MacroInvocData &invoc)
{
parser.skip_token (COMMA);
+ // Check in case of an extraneous comma in the args list, which is
+ // allowed - format_args!("fmt", arg, arg2,)
+ if (parser.peek_current_token ()->get_id () == last_token_id)
+ break;
+
if (parser.peek_current_token ()->get_id () == IDENTIFIER
&& parser.peek (1)->get_id () == EQUAL)
{
diff --git a/gcc/rust/expand/rust-macro-builtins-log-debug.cc b/gcc/rust/expand/rust-macro-builtins-log-debug.cc
index 49670d2..3d7b54f 100644
--- a/gcc/rust/expand/rust-macro-builtins-log-debug.cc
+++ b/gcc/rust/expand/rust-macro-builtins-log-debug.cc
@@ -30,4 +30,4 @@ MacroBuiltin::assert_handler (location_t invoc_locus,
return AST::Fragment::create_error ();
}
-} // namespace Rust \ No newline at end of file
+} // namespace Rust
diff --git a/gcc/rust/expand/rust-macro-builtins.cc b/gcc/rust/expand/rust-macro-builtins.cc
index 39c4c46..b58ed71 100644
--- a/gcc/rust/expand/rust-macro-builtins.cc
+++ b/gcc/rust/expand/rust-macro-builtins.cc
@@ -83,7 +83,6 @@ const BiMap<std::string, BuiltinMacro> MacroBuiltin::builtins = {{
{"Ord", BuiltinMacro::Ord},
{"PartialOrd", BuiltinMacro::PartialOrd},
{"Hash", BuiltinMacro::Hash},
-
}};
AST::MacroTranscriberFunc
@@ -104,6 +103,15 @@ inline_asm_maker (AST::AsmKind global_asm)
};
}
+AST::MacroTranscriberFunc
+inline_llvm_asm_maker (AST::AsmKind global_asm)
+{
+ return [global_asm] (location_t loc, AST::MacroInvocData &invoc,
+ AST::InvocKind semicolon) {
+ return MacroBuiltin::llvm_asm_handler (loc, invoc, semicolon, global_asm);
+ };
+}
+
std::unordered_map<std::string, AST::MacroTranscriberFunc>
MacroBuiltin::builtin_transcribers = {
{"assert", MacroBuiltin::assert_handler},
@@ -122,7 +130,7 @@ std::unordered_map<std::string, AST::MacroTranscriberFunc>
{"format_args_nl", format_args_maker (AST::FormatArgs::Newline::Yes)},
{"asm", inline_asm_maker (AST::AsmKind::Inline)},
// FIXME: Is that okay?
- {"llvm_asm", inline_asm_maker (AST::AsmKind::Inline)},
+ {"llvm_asm", inline_llvm_asm_maker (AST::AsmKind::Inline)},
{"global_asm", inline_asm_maker (AST::AsmKind::Global)},
{"option_env", MacroBuiltin::option_env_handler},
/* Unimplemented macro builtins */
@@ -137,6 +145,7 @@ std::unordered_map<std::string, AST::MacroTranscriberFunc>
{"cfg_accessible", MacroBuiltin::sorry},
{"rustc_const_stable", MacroBuiltin::sorry},
{"rustc_const_unstable", MacroBuiltin::sorry},
+ {"track_caller", MacroBuiltin::sorry},
/* Derive builtins do not need a real transcriber, but still need one. It
should however never be called since builtin derive macros get expanded
differently, and benefit from knowing on what kind of items they are
diff --git a/gcc/rust/expand/rust-macro-builtins.h b/gcc/rust/expand/rust-macro-builtins.h
index ff06ebf..541e956 100644
--- a/gcc/rust/expand/rust-macro-builtins.h
+++ b/gcc/rust/expand/rust-macro-builtins.h
@@ -181,6 +181,10 @@ public:
AST::AsmKind is_global_asm);
static tl::optional<AST::Fragment>
+ llvm_asm_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
+ AST::InvocKind semicolon, AST::AsmKind is_global_asm);
+
+ static tl::optional<AST::Fragment>
format_args_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
AST::InvocKind semicolon, AST::FormatArgs::Newline nl);
diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc
index cd17a3f..673b8fb 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -28,6 +28,7 @@
#include "rust-cfg-strip.h"
#include "rust-early-name-resolver.h"
#include "rust-proc-macro.h"
+#include "rust-token-tree-desugar.h"
namespace Rust {
@@ -78,7 +79,10 @@ MacroExpander::expand_decl_macro (location_t invoc_locus,
* trees.
*/
- AST::DelimTokenTree &invoc_token_tree = invoc.get_delim_tok_tree ();
+ AST::DelimTokenTree &invoc_token_tree_sugar = invoc.get_delim_tok_tree ();
+
+ // We must first desugar doc comments into proper attributes
+ auto invoc_token_tree = AST::TokenTreeDesugar ().go (invoc_token_tree_sugar);
// find matching arm
AST::MacroRule *matched_rule = nullptr;
@@ -621,9 +625,10 @@ MacroExpander::match_n_matches (Parser<MacroInvocLexer> &parser,
// matched fragment get the offset in the token stream
size_t offs_end = source.get_offs ();
- sub_stack.insert_metavar (
- MatchedFragment (fragment->get_ident ().as_string (),
- offs_begin, offs_end));
+ if (valid_current_match)
+ sub_stack.insert_metavar (
+ MatchedFragment (fragment->get_ident ().as_string (),
+ offs_begin, offs_end));
}
break;
@@ -650,15 +655,15 @@ MacroExpander::match_n_matches (Parser<MacroInvocLexer> &parser,
}
auto old_stack = sub_stack.pop ();
- // nest metavars into repetitions
- for (auto &ent : old_stack)
- sub_stack.append_fragment (ent.first, std::move (ent.second));
-
// If we've encountered an error once, stop trying to match more
// repetitions
if (!valid_current_match)
break;
+ // nest metavars into repetitions
+ for (auto &ent : old_stack)
+ sub_stack.append_fragment (ent.first, std::move (ent.second));
+
match_amount++;
// Break early if we notice there's too many expressions already
diff --git a/gcc/rust/expand/rust-token-tree-desugar.cc b/gcc/rust/expand/rust-token-tree-desugar.cc
new file mode 100644
index 0000000..3b47180
--- /dev/null
+++ b/gcc/rust/expand/rust-token-tree-desugar.cc
@@ -0,0 +1,72 @@
+// Copyright (C) 2025 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-token-tree-desugar.h"
+#include "rust-ast.h"
+#include "rust-token.h"
+
+namespace Rust {
+namespace AST {
+
+DelimTokenTree
+TokenTreeDesugar::go (DelimTokenTree &tts)
+{
+ tts.accept_vis (*this);
+
+ return DelimTokenTree (tts.get_delim_type (), std::move (desugared),
+ tts.get_locus ());
+}
+
+void
+TokenTreeDesugar::append (TokenPtr &&new_token)
+{
+ desugared.emplace_back (std::make_unique<Token> (std::move (new_token)));
+}
+
+void
+TokenTreeDesugar::append (std::unique_ptr<TokenTree> &&new_token)
+{
+ desugared.emplace_back (std::move (new_token));
+}
+
+void
+TokenTreeDesugar::visit (Token &tts)
+{
+ if (tts.get_id () == TokenId::OUTER_DOC_COMMENT
+ || tts.get_id () == TokenId::INNER_DOC_COMMENT)
+ {
+ append (Rust::Token::make (TokenId::HASH, tts.get_locus ()));
+
+ if (tts.get_id () == TokenId::INNER_DOC_COMMENT)
+ append (Rust::Token::make (EXCLAM, tts.get_locus ()));
+
+ append (Rust::Token::make (TokenId::LEFT_SQUARE, tts.get_locus ()));
+ append (Rust::Token::make_identifier (tts.get_locus (), "doc"));
+ append (Rust::Token::make (TokenId::EQUAL, tts.get_locus ()));
+ append (Rust::Token::make_string (tts.get_locus (),
+ std::string (tts.get_str ())));
+ append (Rust::Token::make (TokenId::RIGHT_SQUARE, tts.get_locus ()));
+ }
+ else
+ {
+ append (tts.clone_token ());
+ }
+}
+
+}; // namespace AST
+}; // namespace Rust
diff --git a/gcc/rust/expand/rust-token-tree-desugar.h b/gcc/rust/expand/rust-token-tree-desugar.h
new file mode 100644
index 0000000..ccba53b
--- /dev/null
+++ b/gcc/rust/expand/rust-token-tree-desugar.h
@@ -0,0 +1,55 @@
+// Copyright (C) 2025 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_TOKEN_TREE_DESUGAR_H
+#define RUST_TOKEN_TREE_DESUGAR_H
+
+#include "rust-ast-visitor.h"
+#include "rust-system.h"
+#include "rust-ast.h"
+
+namespace Rust {
+namespace AST {
+
+/**
+ * Desugar a given token-tree before parsing it for a macro invocation. At the
+ * moment, the sole purpose of this desugar is to transform doc-comments into
+ * their attribute form (/// comment -> #[doc = "comment"])
+ */
+class TokenTreeDesugar : public DefaultASTVisitor
+{
+public:
+ TokenTreeDesugar () : desugared (std::vector<std::unique_ptr<TokenTree>> ())
+ {}
+
+ DelimTokenTree go (DelimTokenTree &tts);
+
+private:
+ std::vector<std::unique_ptr<TokenTree>> desugared;
+ void append (TokenPtr &&new_token);
+ void append (std::unique_ptr<TokenTree> &&new_token);
+
+ using DefaultASTVisitor::visit;
+
+ virtual void visit (Token &tts) override;
+};
+
+}; // namespace AST
+}; // namespace Rust
+
+#endif //! RUST_TOKEN_TREE_DESUGAR_H
diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc
index c1fef3d..2d9a445 100644
--- a/gcc/rust/hir/rust-ast-lower-base.cc
+++ b/gcc/rust/hir/rust-ast-lower-base.cc
@@ -267,6 +267,10 @@ void
ASTLoweringBase::visit (AST::InlineAsm &)
{}
+void
+ASTLoweringBase::visit (AST::LlvmInlineAsm &)
+{}
+
// void ASTLoweringBase::visit(MatchCasematch_case) {}
// void ASTLoweringBase:: (AST::MatchCaseBlockExpr &) {}
// void ASTLoweringBase:: (AST::MatchCaseExpr &) {}
@@ -690,8 +694,12 @@ ASTLoweringBase::lower_self (AST::Param &param)
self.get_is_mut (), self.get_locus ());
}
- AST::Lifetime l = self.get_lifetime ();
- return HIR::SelfParam (mapping, lower_lifetime (l), self.get_is_mut (),
+ tl::optional<HIR::Lifetime> lifetime = tl::nullopt;
+
+ if (self.has_lifetime ())
+ lifetime = lower_lifetime (self.get_lifetime ());
+
+ return HIR::SelfParam (mapping, lifetime, self.get_is_mut (),
self.get_locus ());
}
@@ -933,8 +941,8 @@ ASTLoweringBase::lower_literal (const AST::Literal &literal)
case AST::Literal::LitType::BYTE_STRING:
type = HIR::Literal::LitType::BYTE_STRING;
break;
- case AST::Literal::LitType::RAW_STRING: // TODO: Lower raw string literals.
- rust_unreachable ();
+ case AST::Literal::LitType::RAW_STRING:
+ type = HIR::Literal::LitType::STRING;
break;
case AST::Literal::LitType::INT:
type = HIR::Literal::LitType::INT;
diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h
index b3bb174..3116181 100644
--- a/gcc/rust/hir/rust-ast-lower-base.h
+++ b/gcc/rust/hir/rust-ast-lower-base.h
@@ -152,6 +152,7 @@ public:
virtual void visit (AST::IfLetExpr &expr) override;
virtual void visit (AST::IfLetExprConseqElse &expr) override;
virtual void visit (AST::InlineAsm &expr) override;
+ virtual void visit (AST::LlvmInlineAsm &expr) override;
// virtual void visit(MatchCase& match_case) override;
// virtual void visit (AST::MatchCaseBlockExpr &match_case) override;
// virtual void visit (AST::MatchCaseExpr &match_case) override;
diff --git a/gcc/rust/hir/rust-ast-lower-block.h b/gcc/rust/hir/rust-ast-lower-block.h
index a39c010..93cd443 100644
--- a/gcc/rust/hir/rust-ast-lower-block.h
+++ b/gcc/rust/hir/rust-ast-lower-block.h
@@ -195,7 +195,9 @@ public:
HIR::BlockExpr *loop_block
= ASTLoweringBlock::translate (expr.get_loop_block (), &terminated);
- HIR::LoopLabel loop_label = lower_loop_label (expr.get_loop_label ());
+ tl::optional<HIR::LoopLabel> loop_label = tl::nullopt;
+ if (expr.has_loop_label ())
+ loop_label = lower_loop_label (expr.get_loop_label ());
auto crate_num = mappings.get_current_crate ();
Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
diff --git a/gcc/rust/hir/rust-ast-lower-expr.cc b/gcc/rust/hir/rust-ast-lower-expr.cc
index 9f363c0..07d0c835 100644
--- a/gcc/rust/hir/rust-ast-lower-expr.cc
+++ b/gcc/rust/hir/rust-ast-lower-expr.cc
@@ -597,8 +597,10 @@ ASTLoweringExpr::visit (AST::ForLoopExpr &expr)
void
ASTLoweringExpr::visit (AST::BreakExpr &expr)
{
- HIR::Lifetime break_label
- = lower_lifetime (expr.get_label ().get_lifetime ());
+ tl::optional<HIR::Lifetime> break_label = tl::nullopt;
+ if (expr.has_label ())
+ break_label = lower_lifetime (expr.get_label_unchecked ().get_lifetime ());
+
HIR::Expr *break_expr
= expr.has_break_expr ()
? ASTLoweringExpr::translate (expr.get_break_expr ())
@@ -618,7 +620,9 @@ ASTLoweringExpr::visit (AST::BreakExpr &expr)
void
ASTLoweringExpr::visit (AST::ContinueExpr &expr)
{
- HIR::Lifetime break_label = lower_lifetime (expr.get_label ());
+ tl::optional<HIR::Lifetime> break_label;
+ if (expr.has_label ())
+ break_label = lower_lifetime (expr.get_label_unchecked ());
auto crate_num = mappings.get_current_crate ();
Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
@@ -633,9 +637,6 @@ ASTLoweringExpr::visit (AST::ContinueExpr &expr)
void
ASTLoweringExpr::visit (AST::BorrowExpr &expr)
{
- if (expr.is_raw_borrow ())
- rust_unreachable ();
-
HIR::Expr *borrow_lvalue
= ASTLoweringExpr::translate (expr.get_borrowed_expr ());
@@ -646,8 +647,8 @@ ASTLoweringExpr::visit (AST::BorrowExpr &expr)
auto *borrow_expr
= new HIR::BorrowExpr (mapping, std::unique_ptr<HIR::Expr> (borrow_lvalue),
- expr.get_mutability (), expr.get_outer_attrs (),
- expr.get_locus ());
+ expr.get_mutability (), expr.is_raw_borrow (),
+ expr.get_outer_attrs (), expr.get_locus ());
if (expr.get_is_double_borrow ())
{
@@ -659,8 +660,8 @@ ASTLoweringExpr::visit (AST::BorrowExpr &expr)
borrow_expr
= new HIR::BorrowExpr (mapping,
std::unique_ptr<HIR::Expr> (borrow_expr),
- expr.get_mutability (), expr.get_outer_attrs (),
- expr.get_locus ());
+ expr.get_mutability (), expr.is_raw_borrow (),
+ expr.get_outer_attrs (), expr.get_locus ());
}
translated = borrow_expr;
@@ -954,6 +955,50 @@ ASTLoweringExpr::visit (AST::InlineAsm &expr)
hir_operands, expr.get_clobber_abi (),
expr.get_options (), mapping);
}
+
+void
+ASTLoweringExpr::visit (AST::LlvmInlineAsm &expr)
+{
+ auto crate_num = mappings.get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings.get_next_hir_id (crate_num),
+ mappings.get_next_localdef_id (crate_num));
+
+ std::vector<LlvmOperand> inputs;
+ std::vector<LlvmOperand> outputs;
+
+ for (auto i : expr.get_inputs ())
+ {
+ std::unique_ptr<Expr> inner_expr
+ = std::unique_ptr<Expr> (translate (*i.expr.get ()));
+ inputs.emplace_back (i.constraint, std::move (inner_expr));
+ }
+
+ for (auto o : expr.get_outputs ())
+ {
+ std::unique_ptr<Expr> inner_expr
+ = std::unique_ptr<Expr> (translate (*o.expr.get ()));
+ outputs.emplace_back (o.constraint, std::move (inner_expr));
+ }
+
+ HIR::LlvmInlineAsm::Options options{expr.is_volatile (),
+ expr.is_stack_aligned (),
+ expr.get_dialect ()};
+
+ // We're not really supporting llvm_asm, only the bare minimum
+ // we're quite conservative here as the current code support more usecase.
+ rust_assert (outputs.size () == 0);
+ rust_assert (inputs.size () <= 1);
+ rust_assert (expr.get_clobbers ().size () <= 1);
+ rust_assert (expr.get_templates ().size () == 1);
+ rust_assert (expr.get_templates ()[0].symbol == "");
+
+ translated
+ = new HIR::LlvmInlineAsm (expr.get_locus (), inputs, outputs,
+ expr.get_templates (), expr.get_clobbers (),
+ options, expr.get_outer_attrs (), mapping);
+}
+
void
ASTLoweringExpr::visit (AST::FormatArgs &fmt)
{
diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h
index af60e01..adedeb3 100644
--- a/gcc/rust/hir/rust-ast-lower-expr.h
+++ b/gcc/rust/hir/rust-ast-lower-expr.h
@@ -122,6 +122,7 @@ public:
void visit (AST::ClosureExprInner &expr) override;
void visit (AST::ClosureExprInnerTyped &expr) override;
void visit (AST::InlineAsm &expr) override;
+ void visit (AST::LlvmInlineAsm &expr) override;
// Extra visitor for FormatArgs nodes
void visit (AST::FormatArgs &fmt) override;
diff --git a/gcc/rust/hir/rust-ast-lower-implitem.cc b/gcc/rust/hir/rust-ast-lower-implitem.cc
index 5380d25..d815a71 100644
--- a/gcc/rust/hir/rust-ast-lower-implitem.cc
+++ b/gcc/rust/hir/rust-ast-lower-implitem.cc
@@ -22,6 +22,7 @@
#include "rust-ast-lower-expr.h"
#include "rust-ast-lower-pattern.h"
#include "rust-ast-lower-block.h"
+#include "rust-hir-item.h"
#include "rust-item.h"
namespace Rust {
@@ -131,7 +132,7 @@ ASTLowerImplItem::visit (AST::Function &function)
Identifier function_name = function.get_function_name ();
location_t locus = function.get_locus ();
- HIR::SelfParam self_param = HIR::SelfParam::error ();
+ tl::optional<HIR::SelfParam> self_param = tl::nullopt;
if (function.has_self_param ())
self_param = lower_self (function.get_self_param ());
@@ -140,6 +141,9 @@ ASTLowerImplItem::visit (AST::Function &function)
ASTLoweringType::translate (function.get_return_type ()))
: nullptr;
+ Defaultness defaultness
+ = function.is_default () ? Defaultness::Default : Defaultness::Final;
+
std::vector<HIR::FunctionParam> function_params;
for (auto &p : function.get_function_params ())
{
@@ -183,15 +187,15 @@ ASTLowerImplItem::visit (AST::Function &function)
std::move (function_params), std::move (return_type),
std::move (where_clause), std::move (function_body),
std::move (vis), function.get_outer_attrs (),
- std::move (self_param), locus);
+ std::move (self_param), defaultness, locus);
- if (!fn->get_self_param ().is_error ())
+ if (fn->is_method ())
{
// insert mappings for self
- mappings.insert_hir_self_param (&fn->get_self_param ());
+ mappings.insert_hir_self_param (&fn->get_self_param_unchecked ());
mappings.insert_location (
- fn->get_self_param ().get_mappings ().get_hirid (),
- fn->get_self_param ().get_locus ());
+ fn->get_self_param_unchecked ().get_mappings ().get_hirid (),
+ fn->get_self_param_unchecked ().get_locus ());
}
// add the mappings for the function params at the end
@@ -245,9 +249,9 @@ ASTLowerTraitItem::visit (AST::Function &func)
// set self parameter to error if this is a method
// else lower to hir
- HIR::SelfParam self_param = func.has_self_param ()
- ? lower_self (func.get_self_param ())
- : HIR::SelfParam::error ();
+ tl::optional<HIR::SelfParam> self_param = tl::nullopt;
+ if (func.has_self_param ())
+ self_param = lower_self (func.get_self_param ());
std::vector<HIR::FunctionParam> function_params;
for (auto &p : func.get_function_params ())
@@ -299,9 +303,10 @@ ASTLowerTraitItem::visit (AST::Function &func)
if (func.has_self_param ())
{
// insert mappings for self
- mappings.insert_hir_self_param (&self_param);
- mappings.insert_location (self_param.get_mappings ().get_hirid (),
- self_param.get_locus ());
+ // TODO: Is this correct ? Looks fishy
+ mappings.insert_hir_self_param (&*self_param);
+ mappings.insert_location (self_param->get_mappings ().get_hirid (),
+ self_param->get_locus ());
}
// add the mappings for the function params at the end
diff --git a/gcc/rust/hir/rust-ast-lower-item.cc b/gcc/rust/hir/rust-ast-lower-item.cc
index 5dbcad5..f4396b5 100644
--- a/gcc/rust/hir/rust-ast-lower-item.cc
+++ b/gcc/rust/hir/rust-ast-lower-item.cc
@@ -451,13 +451,16 @@ ASTLoweringItem::visit (AST::Function &function)
mappings.insert_location (function_body->get_mappings ().get_hirid (),
function.get_locus ());
+ Defaultness defaultness
+ = function.is_default () ? Defaultness::Default : Defaultness::Final;
+
auto fn
= new HIR::Function (mapping, std::move (function_name),
std::move (qualifiers), std::move (generic_params),
std::move (function_params), std::move (return_type),
std::move (where_clause), std::move (function_body),
std::move (vis), function.get_outer_attrs (),
- HIR::SelfParam::error (), locus);
+ tl::nullopt, defaultness, locus);
// add the mappings for the function params at the end
for (auto &param : fn->get_function_params ())
diff --git a/gcc/rust/hir/rust-ast-lower-stmt.cc b/gcc/rust/hir/rust-ast-lower-stmt.cc
index fd2cdfb..dbb1723 100644
--- a/gcc/rust/hir/rust-ast-lower-stmt.cc
+++ b/gcc/rust/hir/rust-ast-lower-stmt.cc
@@ -76,20 +76,26 @@ ASTLoweringStmt::visit (AST::LetStmt &stmt)
type
= std::unique_ptr<Type> (ASTLoweringType::translate (stmt.get_type ()));
- tl::optional<std::unique_ptr<HIR::Expr>> init_expression = tl::nullopt;
+ tl::optional<std::unique_ptr<HIR::Expr>> init_expr = tl::nullopt;
+ tl::optional<std::unique_ptr<HIR::Expr>> else_expr = tl::nullopt;
if (stmt.has_init_expr ())
- init_expression = std::unique_ptr<HIR::Expr> (
+ init_expr = std::unique_ptr<HIR::Expr> (
ASTLoweringExpr::translate (stmt.get_init_expr ()));
+ if (stmt.has_else_expr ())
+ else_expr = std::unique_ptr<HIR::Expr> (
+ ASTLoweringExpr::translate (stmt.get_else_expr ()));
+
auto crate_num = mappings.get_current_crate ();
Analysis::NodeMapping mapping (crate_num, stmt.get_node_id (),
mappings.get_next_hir_id (crate_num),
UNKNOWN_LOCAL_DEFID);
translated
= new HIR::LetStmt (mapping, std::unique_ptr<HIR::Pattern> (variables),
- std::move (init_expression), std::move (type),
- stmt.get_outer_attrs (), stmt.get_locus ());
+ std::move (init_expr), std::move (else_expr),
+ std::move (type), stmt.get_outer_attrs (),
+ stmt.get_locus ());
}
void
diff --git a/gcc/rust/hir/rust-ast-lower-type.cc b/gcc/rust/hir/rust-ast-lower-type.cc
index d3e528d..a678f18 100644
--- a/gcc/rust/hir/rust-ast-lower-type.cc
+++ b/gcc/rust/hir/rust-ast-lower-type.cc
@@ -557,7 +557,7 @@ ASTLowerGenericParam::visit (AST::ConstGenericParam &param)
HIR::Expr *default_expr = nullptr;
if (param.has_default_value ())
default_expr = ASTLoweringExpr::translate (
- param.get_default_value ().get_expression ());
+ param.get_default_value_unchecked ().get_expression ());
translated = new HIR::ConstGenericParam (param.get_name ().as_string (),
std::unique_ptr<Type> (type),
diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc
index ebdf981..76bd135 100644
--- a/gcc/rust/hir/rust-ast-lower.cc
+++ b/gcc/rust/hir/rust-ast-lower.cc
@@ -97,7 +97,11 @@ ASTLowering::go ()
void
ASTLoweringBlock::visit (AST::BlockExpr &expr)
{
- auto label = lower_loop_label (expr.get_label ());
+ tl::optional<HIR::LoopLabel> label;
+ if (expr.has_label ())
+ label = lower_loop_label (expr.get_label ());
+ else
+ label = tl::nullopt;
std::vector<std::unique_ptr<HIR::Stmt>> block_stmts;
bool block_did_terminate = false;
@@ -398,7 +402,10 @@ ASTLoweringExprWithBlock::visit (AST::WhileLoopExpr &expr)
HIR::BlockExpr *loop_block
= ASTLoweringBlock::translate (expr.get_loop_block (), &terminated);
- HIR::LoopLabel loop_label = lower_loop_label (expr.get_loop_label ());
+ tl::optional<HIR::LoopLabel> loop_label;
+ if (expr.has_loop_label ())
+ loop_label = lower_loop_label (expr.get_loop_label ());
+
HIR::Expr *loop_condition
= ASTLoweringExpr::translate (expr.get_predicate_expr (), &terminated);
diff --git a/gcc/rust/hir/rust-hir-dump.cc b/gcc/rust/hir/rust-hir-dump.cc
index d495841..cb32f68 100644
--- a/gcc/rust/hir/rust-hir-dump.cc
+++ b/gcc/rust/hir/rust-hir-dump.cc
@@ -546,7 +546,8 @@ Dump::do_traitfunctiondecl (TraitFunctionDecl &e)
else
put_field ("where_clause", "none");
- put_field ("self", e.get_self ().as_string ());
+ if (e.is_method ())
+ put_field ("self", e.get_self_unchecked ().as_string ());
end ("TraitFunctionDecl");
}
@@ -1283,7 +1284,9 @@ Dump::visit (BlockExpr &e)
do_expr (e);
do_inner_attrs (e);
put_field ("tail_reachable", std::to_string (e.is_tail_reachable ()));
- put_field ("label", e.get_label ().as_string ());
+
+ if (e.has_label ())
+ put_field ("label", e.get_label ().as_string ());
visit_collection ("statements", e.get_statements ());
@@ -1507,6 +1510,10 @@ Dump::visit (InlineAsm &e)
{}
void
+Dump::visit (LlvmInlineAsm &e)
+{}
+
+void
Dump::visit (TypeParam &e)
{
begin ("TypeParam");
@@ -1693,7 +1700,8 @@ Dump::visit (Function &e)
put_field ("where clause", e.get_where_clause ().as_string ());
visit_field ("function_body", e.get_definition ());
- put_field ("self", e.get_self_param ().as_string ());
+ if (e.is_method ())
+ put_field ("self", e.get_self_param_unchecked ().as_string ());
end ("Function");
}
@@ -1932,7 +1940,9 @@ Dump::visit (TraitItemConst &e)
put_field ("name", e.get_name ().as_string ());
visit_field ("type", e.get_type ());
- visit_field ("expr", e.get_expr ());
+ if (e.has_expr ())
+ visit_field ("expr", e.get_expr ());
+
end ("TraitItemConst");
}
@@ -2438,7 +2448,9 @@ Dump::visit (BareFunctionType &e)
end_field ("params");
}
- visit_field ("return_type", e.get_return_type ());
+ if (e.has_return_type ())
+ visit_field ("return_type", e.get_return_type ());
+
put_field ("is_variadic", std::to_string (e.get_is_variadic ()));
end ("BareFunctionType");
}
diff --git a/gcc/rust/hir/rust-hir-dump.h b/gcc/rust/hir/rust-hir-dump.h
index afcd668..45b1708 100644
--- a/gcc/rust/hir/rust-hir-dump.h
+++ b/gcc/rust/hir/rust-hir-dump.h
@@ -166,6 +166,7 @@ private:
virtual void visit (AwaitExpr &) override;
virtual void visit (AsyncBlockExpr &) override;
virtual void visit (InlineAsm &) override;
+ virtual void visit (LlvmInlineAsm &) override;
virtual void visit (TypeParam &) override;
virtual void visit (ConstGenericParam &) override;
diff --git a/gcc/rust/hir/tree/rust-hir-bound.h b/gcc/rust/hir/tree/rust-hir-bound.h
index 78bb133..8fa6a22 100644
--- a/gcc/rust/hir/tree/rust-hir-bound.h
+++ b/gcc/rust/hir/tree/rust-hir-bound.h
@@ -44,18 +44,6 @@ public:
{}
// Returns true if the lifetime is in an error state.
- bool is_error () const
- {
- return lifetime_type == AST::Lifetime::LifetimeType::NAMED
- && lifetime_name.empty ();
- }
-
- static Lifetime error ()
- {
- return Lifetime (Analysis::NodeMapping::get_error (),
- AST::Lifetime::LifetimeType::NAMED, "", UNDEF_LOCATION);
- }
-
std::string as_string () const override;
void accept_vis (HIRFullVisitor &vis) override;
diff --git a/gcc/rust/hir/tree/rust-hir-expr-abstract.h b/gcc/rust/hir/tree/rust-hir-expr-abstract.h
index ecf9bd1..5bc5d89 100644
--- a/gcc/rust/hir/tree/rust-hir-expr-abstract.h
+++ b/gcc/rust/hir/tree/rust-hir-expr-abstract.h
@@ -71,6 +71,7 @@ public:
AsyncBlock,
Path,
InlineAsm,
+ LlvmInlineAsm,
};
BaseKind get_hir_kind () override final { return Node::BaseKind::EXPR; }
diff --git a/gcc/rust/hir/tree/rust-hir-expr.cc b/gcc/rust/hir/tree/rust-hir-expr.cc
index 2ded789..266c79c 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.cc
+++ b/gcc/rust/hir/tree/rust-hir-expr.cc
@@ -81,10 +81,10 @@ OperatorExpr::operator= (OperatorExpr const &other)
BorrowExpr::BorrowExpr (Analysis::NodeMapping mappings,
std::unique_ptr<Expr> borrow_lvalue, Mutability mut,
- AST::AttrVec outer_attribs, location_t locus)
+ bool raw, AST::AttrVec outer_attribs, location_t locus)
: OperatorExpr (std::move (mappings), std::move (borrow_lvalue),
std::move (outer_attribs), locus),
- mut (mut)
+ mut (mut), raw (raw)
{}
DereferenceExpr::DereferenceExpr (Analysis::NodeMapping mappings,
@@ -749,7 +749,7 @@ BlockExpr::BlockExpr (Analysis::NodeMapping mappings,
std::vector<std::unique_ptr<Stmt>> block_statements,
std::unique_ptr<Expr> block_expr, bool tail_reachable,
AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
- LoopLabel label, location_t start_locus,
+ tl::optional<LoopLabel> label, location_t start_locus,
location_t end_locus)
: ExprWithBlock (std::move (mappings), std::move (outer_attribs)),
WithInnerAttrs (std::move (inner_attribs)),
@@ -791,13 +791,15 @@ BlockExpr::operator= (BlockExpr const &other)
}
ContinueExpr::ContinueExpr (Analysis::NodeMapping mappings, location_t locus,
- Lifetime label, AST::AttrVec outer_attribs)
+ tl::optional<Lifetime> label,
+ AST::AttrVec outer_attribs)
: ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
label (std::move (label)), locus (locus)
{}
BreakExpr::BreakExpr (Analysis::NodeMapping mappings, location_t locus,
- Lifetime break_label, std::unique_ptr<Expr> expr_in_break,
+ tl::optional<Lifetime> break_label,
+ std::unique_ptr<Expr> expr_in_break,
AST::AttrVec outer_attribs)
: ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
label (std::move (break_label)), break_expr (std::move (expr_in_break)),
@@ -985,7 +987,8 @@ UnsafeBlockExpr::operator= (UnsafeBlockExpr const &other)
BaseLoopExpr::BaseLoopExpr (Analysis::NodeMapping mappings,
std::unique_ptr<BlockExpr> loop_block,
- location_t locus, LoopLabel loop_label,
+ location_t locus,
+ tl::optional<LoopLabel> loop_label,
AST::AttrVec outer_attribs)
: ExprWithBlock (std::move (mappings), std::move (outer_attribs)),
loop_label (std::move (loop_label)), loop_block (std::move (loop_block)),
@@ -1011,7 +1014,8 @@ BaseLoopExpr::operator= (BaseLoopExpr const &other)
LoopExpr::LoopExpr (Analysis::NodeMapping mappings,
std::unique_ptr<BlockExpr> loop_block, location_t locus,
- LoopLabel loop_label, AST::AttrVec outer_attribs)
+ tl::optional<LoopLabel> loop_label,
+ AST::AttrVec outer_attribs)
: BaseLoopExpr (std::move (mappings), std::move (loop_block), locus,
std::move (loop_label), std::move (outer_attribs))
{}
@@ -1019,7 +1023,8 @@ LoopExpr::LoopExpr (Analysis::NodeMapping mappings,
WhileLoopExpr::WhileLoopExpr (Analysis::NodeMapping mappings,
std::unique_ptr<Expr> loop_condition,
std::unique_ptr<BlockExpr> loop_block,
- location_t locus, LoopLabel loop_label,
+ location_t locus,
+ tl::optional<LoopLabel> loop_label,
AST::AttrVec outer_attribs)
: BaseLoopExpr (std::move (mappings), std::move (loop_block), locus,
std::move (loop_label), std::move (outer_attribs)),
@@ -1046,7 +1051,8 @@ WhileLetLoopExpr::WhileLetLoopExpr (
Analysis::NodeMapping mappings,
std::vector<std::unique_ptr<Pattern>> match_arm_patterns,
std::unique_ptr<Expr> condition, std::unique_ptr<BlockExpr> loop_block,
- location_t locus, LoopLabel loop_label, AST::AttrVec outer_attribs)
+ location_t locus, tl::optional<LoopLabel> loop_label,
+ AST::AttrVec outer_attribs)
: BaseLoopExpr (std::move (mappings), std::move (loop_block), locus,
std::move (loop_label), std::move (outer_attribs)),
match_arm_patterns (std::move (match_arm_patterns)),
diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h
index f8f2128..375f474 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.h
+++ b/gcc/rust/hir/tree/rust-hir-expr.h
@@ -45,9 +45,6 @@ public:
LoopLabel (Analysis::NodeMapping mapping, Lifetime loop_label,
location_t locus);
- // Returns whether the LoopLabel is in an error state.
- bool is_error () const { return label.is_error (); }
-
location_t get_locus () const { return locus; }
Analysis::NodeMapping &get_mappings () { return mappings; }
@@ -199,12 +196,13 @@ public:
class BorrowExpr : public OperatorExpr
{
Mutability mut;
+ bool raw;
public:
std::string as_string () const override;
BorrowExpr (Analysis::NodeMapping mappings,
- std::unique_ptr<Expr> borrow_lvalue, Mutability mut,
+ std::unique_ptr<Expr> borrow_lvalue, Mutability mut, bool raw,
AST::AttrVec outer_attribs, location_t locus);
void accept_vis (HIRFullVisitor &vis) override;
@@ -212,6 +210,7 @@ public:
Mutability get_mut () const { return mut; }
bool is_mut () const { return mut == Mutability::Mut; }
+ bool is_raw_borrow () const { return raw; }
protected:
/* Use covariance to implement clone function as returning this object rather
@@ -1715,7 +1714,7 @@ public:
std::vector<std::unique_ptr<Stmt>> statements;
std::unique_ptr<Expr> expr;
bool tail_reachable;
- LoopLabel label;
+ tl::optional<LoopLabel> label;
location_t start_locus;
location_t end_locus;
@@ -1735,7 +1734,8 @@ public:
std::vector<std::unique_ptr<Stmt>> block_statements,
std::unique_ptr<Expr> block_expr, bool tail_reachable,
AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
- LoopLabel label, location_t start_locus, location_t end_locus);
+ tl::optional<LoopLabel> label, location_t start_locus,
+ location_t end_locus);
// Copy constructor with clone
BlockExpr (BlockExpr const &other);
@@ -1774,8 +1774,8 @@ public:
return ExprType::Block;
}
- bool has_label () const { return !label.is_error (); }
- LoopLabel &get_label () { return label; }
+ bool has_label () const { return label.has_value (); }
+ LoopLabel &get_label () { return label.value (); }
protected:
/* Use covariance to implement clone function as returning this object rather
@@ -1803,25 +1803,27 @@ protected:
// HIR node representing continue expression within loops
class ContinueExpr : public ExprWithoutBlock
{
- Lifetime label;
+ tl::optional<Lifetime> label;
location_t locus;
public:
std::string as_string () const override;
// Returns true if the continue expr has a label.
- bool has_label () const { return !label.is_error (); }
+ bool has_label () const { return label.has_value (); }
// Constructor for a ContinueExpr with a label.
ContinueExpr (Analysis::NodeMapping mappings, location_t locus,
- Lifetime label, AST::AttrVec outer_attribs = AST::AttrVec ());
+ tl::optional<Lifetime> label,
+ AST::AttrVec outer_attribs = AST::AttrVec ());
location_t get_locus () const override final { return locus; }
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
- Lifetime &get_label () { return label; }
+ Lifetime &get_label () { return label.value (); }
+ const Lifetime &get_label () const { return label.value (); }
ExprType get_expression_type () const final override
{
@@ -1848,7 +1850,7 @@ protected:
class BreakExpr : public ExprWithoutBlock
{
// bool has_label;
- Lifetime label;
+ tl::optional<Lifetime> label;
// bool has_break_expr;
std::unique_ptr<Expr> break_expr;
@@ -1859,7 +1861,7 @@ public:
std::string as_string () const override;
// Returns whether the break expression has a label or not.
- bool has_label () const { return !label.is_error (); }
+ bool has_label () const { return label.has_value (); }
/* Returns whether the break expression has an expression used in the break or
* not. */
@@ -1867,7 +1869,7 @@ public:
// Constructor for a break expression
BreakExpr (Analysis::NodeMapping mappings, location_t locus,
- Lifetime break_label,
+ tl::optional<Lifetime> break_label,
std::unique_ptr<Expr> expr_in_break = nullptr,
AST::AttrVec outer_attribs = AST::AttrVec ());
@@ -1886,7 +1888,8 @@ public:
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
- Lifetime &get_label () { return label; }
+ Lifetime &get_label () { return label.value (); }
+ const Lifetime &get_label () const { return label.value (); }
Expr &get_expr () { return *break_expr; }
@@ -2293,7 +2296,7 @@ protected:
class BaseLoopExpr : public ExprWithBlock
{
protected:
- LoopLabel loop_label;
+ tl::optional<LoopLabel> loop_label;
std::unique_ptr<BlockExpr> loop_block;
private:
@@ -2303,7 +2306,7 @@ protected:
// Constructor for BaseLoopExpr
BaseLoopExpr (Analysis::NodeMapping mappings,
std::unique_ptr<BlockExpr> loop_block, location_t locus,
- LoopLabel loop_label,
+ tl::optional<LoopLabel> loop_label,
AST::AttrVec outer_attribs = AST::AttrVec ());
// Copy constructor for BaseLoopExpr with clone
@@ -2322,13 +2325,14 @@ protected:
}
public:
- bool has_loop_label () const { return !loop_label.is_error (); }
+ bool has_loop_label () const { return loop_label.has_value (); }
location_t get_locus () const override final { return locus; }
HIR::BlockExpr &get_loop_block () { return *loop_block; };
- LoopLabel &get_loop_label () { return loop_label; }
+ LoopLabel &get_loop_label () { return loop_label.value (); }
+ const LoopLabel &get_loop_label () const { return loop_label.value (); }
};
// 'Loop' expression (i.e. the infinite loop) HIR node
@@ -2340,7 +2344,8 @@ public:
// Constructor for LoopExpr
LoopExpr (Analysis::NodeMapping mappings,
std::unique_ptr<BlockExpr> loop_block, location_t locus,
- LoopLabel loop_label, AST::AttrVec outer_attribs = AST::AttrVec ());
+ tl::optional<LoopLabel> loop_label,
+ AST::AttrVec outer_attribs = AST::AttrVec ());
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRExpressionVisitor &vis) override;
@@ -2370,7 +2375,7 @@ public:
WhileLoopExpr (Analysis::NodeMapping mappings,
std::unique_ptr<Expr> loop_condition,
std::unique_ptr<BlockExpr> loop_block, location_t locus,
- LoopLabel loop_label,
+ tl::optional<LoopLabel> loop_label,
AST::AttrVec outer_attribs = AST::AttrVec ());
// Copy constructor with clone
@@ -2419,7 +2424,7 @@ public:
std::vector<std::unique_ptr<Pattern>> match_arm_patterns,
std::unique_ptr<Expr> condition,
std::unique_ptr<BlockExpr> loop_block, location_t locus,
- LoopLabel loop_label,
+ tl::optional<LoopLabel> loop_label,
AST::AttrVec outer_attribs = AST::AttrVec ());
// Copy constructor with clone
@@ -3113,6 +3118,80 @@ public:
AST::AttrVec outer_attribs = AST::AttrVec ());
};
+struct LlvmOperand
+{
+ std::string constraint;
+ std::unique_ptr<Expr> expr;
+
+ LlvmOperand (std::string constraint, std::unique_ptr<Expr> &&expr)
+ : constraint (constraint), expr (std::move (expr))
+ {}
+
+ LlvmOperand (const LlvmOperand &other)
+ : constraint (other.constraint), expr (other.expr->clone_expr ())
+ {}
+ LlvmOperand &operator= (const LlvmOperand &other)
+ {
+ constraint = other.constraint;
+ expr = other.expr->clone_expr ();
+
+ return *this;
+ }
+};
+
+class LlvmInlineAsm : public ExprWithoutBlock
+{
+public:
+ struct Options
+ {
+ bool is_volatile;
+ bool align_stack;
+ AST::LlvmInlineAsm::Dialect dialect;
+ };
+
+ location_t locus;
+ AST::AttrVec outer_attrs;
+ std::vector<LlvmOperand> inputs;
+ std::vector<LlvmOperand> outputs;
+ std::vector<AST::TupleTemplateStr> templates;
+ std::vector<AST::TupleClobber> clobbers;
+ Options options;
+
+ LlvmInlineAsm (location_t locus, std::vector<LlvmOperand> inputs,
+ std::vector<LlvmOperand> outputs,
+ std::vector<AST::TupleTemplateStr> templates,
+ std::vector<AST::TupleClobber> clobbers, Options options,
+ AST::AttrVec outer_attrs, Analysis::NodeMapping mappings)
+ : ExprWithoutBlock (mappings, std::move (outer_attrs)), locus (locus),
+ inputs (std::move (inputs)), outputs (std::move (outputs)),
+ templates (std::move (templates)), clobbers (std::move (clobbers)),
+ options (options)
+ {}
+
+ AST::LlvmInlineAsm::Dialect get_dialect () { return options.dialect; }
+
+ location_t get_locus () const override { return locus; }
+
+ std::vector<AST::Attribute> &get_outer_attrs () { return outer_attrs; }
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ LlvmInlineAsm *clone_expr_without_block_impl () const override
+ {
+ return new LlvmInlineAsm (*this);
+ }
+
+ std::vector<AST::TupleTemplateStr> &get_templates () { return templates; }
+
+ Expr::ExprType get_expression_type () const override
+ {
+ return Expr::ExprType::LlvmInlineAsm;
+ }
+
+ std::vector<AST::TupleClobber> get_clobbers () { return clobbers; }
+};
+
} // namespace HIR
} // namespace Rust
diff --git a/gcc/rust/hir/tree/rust-hir-full-decls.h b/gcc/rust/hir/tree/rust-hir-full-decls.h
index 6c19f24..1e313ec 100644
--- a/gcc/rust/hir/tree/rust-hir-full-decls.h
+++ b/gcc/rust/hir/tree/rust-hir-full-decls.h
@@ -126,6 +126,7 @@ class InlineAsmRegClass;
struct AnonConst;
class InlineAsmOperand;
class InlineAsm;
+class LlvmInlineAsm;
// rust-stmt.h
class EmptyStmt;
diff --git a/gcc/rust/hir/tree/rust-hir-generic-param.h b/gcc/rust/hir/tree/rust-hir-generic-param.h
index a1c59bf..960de56 100644
--- a/gcc/rust/hir/tree/rust-hir-generic-param.h
+++ b/gcc/rust/hir/tree/rust-hir-generic-param.h
@@ -97,9 +97,6 @@ public:
AST::AttrVec &get_outer_attrs () override { return outer_attrs; }
- // Returns whether the lifetime param is in an error state.
- bool is_error () const { return lifetime.is_error (); }
-
// Constructor
LifetimeParam (Analysis::NodeMapping mappings, Lifetime lifetime,
location_t locus = UNDEF_LOCATION,
diff --git a/gcc/rust/hir/tree/rust-hir-item.cc b/gcc/rust/hir/tree/rust-hir-item.cc
index cff06d3..160f710 100644
--- a/gcc/rust/hir/tree/rust-hir-item.cc
+++ b/gcc/rust/hir/tree/rust-hir-item.cc
@@ -123,7 +123,8 @@ TypeBoundWhereClauseItem::get_type_param_bounds ()
}
SelfParam::SelfParam (Analysis::NodeMapping mappings,
- ImplicitSelfKind self_kind, Lifetime lifetime, Type *type)
+ ImplicitSelfKind self_kind,
+ tl::optional<Lifetime> lifetime, Type *type)
: self_kind (self_kind), lifetime (std::move (lifetime)), type (type),
mappings (mappings)
{}
@@ -131,13 +132,13 @@ SelfParam::SelfParam (Analysis::NodeMapping mappings,
SelfParam::SelfParam (Analysis::NodeMapping mappings,
std::unique_ptr<Type> type, bool is_mut, location_t locus)
: self_kind (is_mut ? ImplicitSelfKind::MUT : ImplicitSelfKind::IMM),
- lifetime (
- Lifetime (mappings, AST::Lifetime::LifetimeType::NAMED, "", locus)),
- type (std::move (type)), locus (locus), mappings (mappings)
+ lifetime (tl::nullopt), type (std::move (type)), locus (locus),
+ mappings (mappings)
{}
-SelfParam::SelfParam (Analysis::NodeMapping mappings, Lifetime lifetime,
- bool is_mut, location_t locus)
+SelfParam::SelfParam (Analysis::NodeMapping mappings,
+ tl::optional<Lifetime> lifetime, bool is_mut,
+ location_t locus)
: self_kind (is_mut ? ImplicitSelfKind::MUT_REF : ImplicitSelfKind::IMM_REF),
lifetime (std::move (lifetime)), locus (locus), mappings (mappings)
{}
@@ -263,7 +264,8 @@ Function::Function (Analysis::NodeMapping mappings, Identifier function_name,
std::vector<FunctionParam> function_params,
std::unique_ptr<Type> return_type, WhereClause where_clause,
std::unique_ptr<BlockExpr> function_body, Visibility vis,
- AST::AttrVec outer_attrs, SelfParam self, location_t locus)
+ AST::AttrVec outer_attrs, tl::optional<SelfParam> self,
+ Defaultness defaultness, location_t locus)
: VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)),
qualifiers (std::move (qualifiers)),
function_name (std::move (function_name)),
@@ -272,7 +274,7 @@ Function::Function (Analysis::NodeMapping mappings, Identifier function_name,
return_type (std::move (return_type)),
where_clause (std::move (where_clause)),
function_body (std::move (function_body)), self (std::move (self)),
- locus (locus)
+ locus (locus), defaultness (defaultness)
{}
Function::Function (Function const &other)
@@ -280,7 +282,7 @@ Function::Function (Function const &other)
function_name (other.function_name),
function_params (other.function_params), where_clause (other.where_clause),
function_body (other.function_body->clone_block_expr ()), self (other.self),
- locus (other.locus)
+ locus (other.locus), defaultness (other.defaultness)
{
// guard to prevent null dereference (always required)
if (other.return_type != nullptr)
@@ -312,6 +314,8 @@ Function::operator= (Function const &other)
locus = other.locus;
self = other.self;
+ defaultness = other.defaultness;
+
generic_params.reserve (other.generic_params.size ());
for (const auto &e : other.generic_params)
generic_params.push_back (e->clone_generic_param ());
@@ -609,9 +613,9 @@ StaticItem::operator= (StaticItem const &other)
TraitFunctionDecl::TraitFunctionDecl (
Identifier function_name, FunctionQualifiers qualifiers,
- std::vector<std::unique_ptr<GenericParam>> generic_params, SelfParam self,
- std::vector<FunctionParam> function_params, std::unique_ptr<Type> return_type,
- WhereClause where_clause)
+ std::vector<std::unique_ptr<GenericParam>> generic_params,
+ tl::optional<SelfParam> self, std::vector<FunctionParam> function_params,
+ std::unique_ptr<Type> return_type, WhereClause where_clause)
: qualifiers (std::move (qualifiers)),
function_name (std::move (function_name)),
generic_params (std::move (generic_params)),
diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h
index 4744717..37f599c 100644
--- a/gcc/rust/hir/tree/rust-hir-item.h
+++ b/gcc/rust/hir/tree/rust-hir-item.h
@@ -371,13 +371,13 @@ public:
private:
ImplicitSelfKind self_kind;
- Lifetime lifetime;
+ tl::optional<Lifetime> lifetime;
std::unique_ptr<Type> type;
location_t locus;
Analysis::NodeMapping mappings;
SelfParam (Analysis::NodeMapping mappings, ImplicitSelfKind self_kind,
- Lifetime lifetime, Type *type);
+ tl::optional<Lifetime> lifetime, Type *type);
public:
// Type-based self parameter (not ref, no lifetime)
@@ -385,8 +385,8 @@ public:
bool is_mut, location_t locus);
// Lifetime-based self parameter (is ref, no type)
- SelfParam (Analysis::NodeMapping mappings, Lifetime lifetime, bool is_mut,
- location_t locus);
+ SelfParam (Analysis::NodeMapping mappings, tl::optional<Lifetime> lifetime,
+ bool is_mut, location_t locus);
// Copy constructor requires clone
SelfParam (SelfParam const &other);
@@ -398,22 +398,13 @@ public:
SelfParam (SelfParam &&other) = default;
SelfParam &operator= (SelfParam &&other) = default;
- static SelfParam error ()
- {
- return SelfParam (Analysis::NodeMapping::get_error (),
- ImplicitSelfKind::NONE, Lifetime::error (), nullptr);
- }
-
// Returns whether the self-param has a type field.
bool has_type () const { return type != nullptr; }
// Returns whether the self-param has a valid lifetime.
- bool has_lifetime () const { return !lifetime.is_error (); }
-
- const Lifetime &get_lifetime () const { return lifetime; }
+ bool has_lifetime () const { return lifetime.has_value (); }
- // Returns whether the self-param is in an error state.
- bool is_error () const { return self_kind == ImplicitSelfKind::NONE; }
+ const Lifetime &get_lifetime () const { return lifetime.value (); }
std::string as_string () const;
@@ -945,6 +936,12 @@ protected:
class LetStmt;
+enum class Defaultness
+{
+ Default,
+ Final,
+};
+
// Rust function declaration HIR node
class Function : public VisItem, public ImplItem
{
@@ -955,9 +952,14 @@ class Function : public VisItem, public ImplItem
std::unique_ptr<Type> return_type;
WhereClause where_clause;
std::unique_ptr<BlockExpr> function_body;
- SelfParam self;
+ tl::optional<SelfParam> self;
location_t locus;
+ // NOTE: This should be moved to the trait item base class once we start
+ // implementing specialization for real, instead of just stubbing out the
+ // feature
+ Defaultness defaultness;
+
public:
std::string as_string () const override;
@@ -973,6 +975,9 @@ public:
// Returns whether function has a where clause.
bool has_where_clause () const { return !where_clause.is_empty (); }
+ // Returns whether function has a default qualifier
+ bool is_default () const { return defaultness == Defaultness::Default; }
+
ImplItemType get_impl_item_type () const override final
{
return ImplItem::ImplItemType::FUNCTION;
@@ -987,7 +992,8 @@ public:
std::vector<FunctionParam> function_params,
std::unique_ptr<Type> return_type, WhereClause where_clause,
std::unique_ptr<BlockExpr> function_body, Visibility vis,
- AST::AttrVec outer_attrs, SelfParam self, location_t locus);
+ AST::AttrVec outer_attrs, tl::optional<SelfParam> self,
+ Defaultness defaultness, location_t locus);
// Copy constructor with clone
Function (Function const &other);
@@ -1041,9 +1047,13 @@ public:
// TODO: is this better? Or is a "vis_block" better?
Type &get_return_type () { return *return_type; }
- bool is_method () const { return !self.is_error (); }
+ bool is_method () const { return self.has_value (); }
- SelfParam &get_self_param () { return self; }
+ tl::optional<SelfParam> &get_self_param () { return self; }
+ const tl::optional<SelfParam> &get_self_param () const { return self; }
+
+ SelfParam &get_self_param_unchecked () { return self.value (); }
+ const SelfParam &get_self_param_unchecked () const { return self.value (); }
std::string get_impl_item_name () const override final
{
@@ -1898,13 +1908,14 @@ private:
std::vector<FunctionParam> function_params;
std::unique_ptr<Type> return_type;
WhereClause where_clause;
- SelfParam self;
+ tl::optional<SelfParam> self;
public:
// Mega-constructor
TraitFunctionDecl (Identifier function_name, FunctionQualifiers qualifiers,
std::vector<std::unique_ptr<GenericParam>> generic_params,
- SelfParam self, std::vector<FunctionParam> function_params,
+ tl::optional<SelfParam> self,
+ std::vector<FunctionParam> function_params,
std::unique_ptr<Type> return_type,
WhereClause where_clause);
@@ -1936,9 +1947,13 @@ public:
WhereClause &get_where_clause () { return where_clause; }
- bool is_method () const { return !self.is_error (); }
+ bool is_method () const { return self.has_value (); }
+
+ SelfParam &get_self_unchecked () { return self.value (); }
+ const SelfParam &get_self_unchecked () const { return self.value (); }
- SelfParam &get_self () { return self; }
+ tl::optional<SelfParam> &get_self () { return self; }
+ const tl::optional<SelfParam> &get_self () const { return self; }
Identifier get_function_name () const { return function_name; }
@@ -2055,6 +2070,8 @@ public:
Identifier get_name () const { return name; }
+ bool has_type () const { return expr != nullptr; }
+
bool has_expr () const { return expr != nullptr; }
Type &get_type ()
diff --git a/gcc/rust/hir/tree/rust-hir-stmt.cc b/gcc/rust/hir/tree/rust-hir-stmt.cc
index 025f67e..fd58e29 100644
--- a/gcc/rust/hir/tree/rust-hir-stmt.cc
+++ b/gcc/rust/hir/tree/rust-hir-stmt.cc
@@ -26,11 +26,13 @@ namespace HIR {
LetStmt::LetStmt (Analysis::NodeMapping mappings,
std::unique_ptr<Pattern> variables_pattern,
tl::optional<std::unique_ptr<Expr>> init_expr,
+ tl::optional<std::unique_ptr<Expr>> else_expr,
tl::optional<std::unique_ptr<Type>> type,
AST::AttrVec outer_attrs, location_t locus)
: Stmt (std::move (mappings)), outer_attrs (std::move (outer_attrs)),
variables_pattern (std::move (variables_pattern)), type (std::move (type)),
- init_expr (std::move (init_expr)), locus (locus)
+ init_expr (std::move (init_expr)), else_expr (std::move (else_expr)),
+ locus (locus)
{}
LetStmt::LetStmt (LetStmt const &other)
@@ -43,6 +45,8 @@ LetStmt::LetStmt (LetStmt const &other)
// guard to prevent null dereference (always required)
if (other.has_init_expr ())
init_expr = other.get_init_expr ().clone_expr ();
+ if (other.has_else_expr ())
+ else_expr = other.get_else_expr ().clone_expr ();
if (other.has_type ())
type = other.get_type ().clone_type ();
@@ -67,6 +71,12 @@ LetStmt::operator= (LetStmt const &other)
init_expr = other.get_init_expr ().clone_expr ();
else
init_expr = nullptr;
+
+ if (other.has_else_expr ())
+ else_expr = other.get_else_expr ().clone_expr ();
+ else
+ else_expr = tl::nullopt;
+
if (other.has_type ())
type = other.get_type ().clone_type ();
else
diff --git a/gcc/rust/hir/tree/rust-hir-stmt.h b/gcc/rust/hir/tree/rust-hir-stmt.h
index 3db1728..9c1a9ec 100644
--- a/gcc/rust/hir/tree/rust-hir-stmt.h
+++ b/gcc/rust/hir/tree/rust-hir-stmt.h
@@ -101,6 +101,7 @@ class LetStmt : public Stmt
tl::optional<std::unique_ptr<Type>> type;
tl::optional<std::unique_ptr<Expr>> init_expr;
+ tl::optional<std::unique_ptr<Expr>> else_expr;
location_t locus;
@@ -113,12 +114,15 @@ public:
// Returns whether let statement has an initialisation expression.
bool has_init_expr () const { return init_expr.has_value (); }
+ // Returns whether let statement has a diverging else expression.
+ bool has_else_expr () const { return else_expr.has_value (); }
std::string as_string () const override;
LetStmt (Analysis::NodeMapping mappings,
std::unique_ptr<Pattern> variables_pattern,
tl::optional<std::unique_ptr<Expr>> init_expr,
+ tl::optional<std::unique_ptr<Expr>> else_expr,
tl::optional<std::unique_ptr<Type>> type, AST::AttrVec outer_attrs,
location_t locus);
@@ -167,6 +171,18 @@ public:
return *init_expr.value ();
}
+ HIR::Expr &get_else_expr ()
+ {
+ rust_assert (*else_expr);
+ return *else_expr.value ();
+ }
+
+ const HIR::Expr &get_else_expr () const
+ {
+ rust_assert (*else_expr);
+ return *else_expr.value ();
+ }
+
HIR::Pattern &get_pattern () { return *variables_pattern; }
bool is_item () const override final { return false; }
diff --git a/gcc/rust/hir/tree/rust-hir-type.cc b/gcc/rust/hir/tree/rust-hir-type.cc
index 689d86b..ec48425 100644
--- a/gcc/rust/hir/tree/rust-hir-type.cc
+++ b/gcc/rust/hir/tree/rust-hir-type.cc
@@ -162,7 +162,7 @@ RawPointerType::operator= (RawPointerType const &other)
ReferenceType::ReferenceType (Analysis::NodeMapping mappings, Mutability mut,
std::unique_ptr<Type> type_no_bounds,
- location_t locus, Lifetime lifetime)
+ location_t locus, tl::optional<Lifetime> lifetime)
: TypeNoBounds (mappings, locus), lifetime (std::move (lifetime)), mut (mut),
type (std::move (type_no_bounds))
{}
@@ -268,7 +268,8 @@ BareFunctionType::BareFunctionType (BareFunctionType const &other)
for_lifetimes (other.for_lifetimes),
function_qualifiers (other.function_qualifiers), params (other.params),
is_variadic (other.is_variadic),
- return_type (other.return_type->clone_type ())
+ return_type (other.has_return_type () ? other.return_type->clone_type ()
+ : nullptr)
{}
BareFunctionType &
diff --git a/gcc/rust/hir/tree/rust-hir-type.h b/gcc/rust/hir/tree/rust-hir-type.h
index bd0f2b6..cbc20ff 100644
--- a/gcc/rust/hir/tree/rust-hir-type.h
+++ b/gcc/rust/hir/tree/rust-hir-type.h
@@ -291,7 +291,7 @@ protected:
class ReferenceType : public TypeNoBounds
{
// bool has_lifetime; // TODO: handle in lifetime or something?
- Lifetime lifetime;
+ tl::optional<Lifetime> lifetime;
Mutability mut;
std::unique_ptr<Type> type;
@@ -301,12 +301,12 @@ public:
bool is_mut () const { return mut == Mutability::Mut; }
// Returns whether the reference has a lifetime.
- bool has_lifetime () const { return !lifetime.is_error (); }
+ bool has_lifetime () const { return lifetime.has_value (); }
// Constructor
ReferenceType (Analysis::NodeMapping mappings, Mutability mut,
std::unique_ptr<Type> type_no_bounds, location_t locus,
- Lifetime lifetime);
+ tl::optional<Lifetime> lifetime);
// Copy constructor with custom clone method
ReferenceType (ReferenceType const &other);
@@ -323,7 +323,8 @@ public:
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRTypeVisitor &vis) override;
- Lifetime &get_lifetime () { return lifetime; }
+ Lifetime &get_lifetime () { return lifetime.value (); }
+ const Lifetime &get_lifetime () const { return lifetime.value (); }
Mutability get_mut () const { return mut; }
diff --git a/gcc/rust/hir/tree/rust-hir-visitor.h b/gcc/rust/hir/tree/rust-hir-visitor.h
index 800e647..283cc34 100644
--- a/gcc/rust/hir/tree/rust-hir-visitor.h
+++ b/gcc/rust/hir/tree/rust-hir-visitor.h
@@ -84,6 +84,7 @@ public:
virtual void visit (AwaitExpr &expr) = 0;
virtual void visit (AsyncBlockExpr &expr) = 0;
virtual void visit (InlineAsm &expr) = 0;
+ virtual void visit (LlvmInlineAsm &expr) = 0;
virtual void visit (TypeParam &param) = 0;
virtual void visit (ConstGenericParam &param) = 0;
virtual void visit (LifetimeWhereClauseItem &item) = 0;
@@ -220,6 +221,7 @@ public:
virtual void visit (AwaitExpr &) override {}
virtual void visit (AsyncBlockExpr &) override {}
virtual void visit (InlineAsm &) override {}
+ virtual void visit (LlvmInlineAsm &) override {}
virtual void visit (TypeParam &) override {}
virtual void visit (ConstGenericParam &) override {}
@@ -441,6 +443,7 @@ public:
virtual void visit (IfExpr &expr) = 0;
virtual void visit (IfExprConseqElse &expr) = 0;
virtual void visit (InlineAsm &expr) = 0;
+ virtual void visit (LlvmInlineAsm &expr) = 0;
virtual void visit (MatchExpr &expr) = 0;
virtual void visit (AwaitExpr &expr) = 0;
virtual void visit (AsyncBlockExpr &expr) = 0;
diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc
index 822eaff..093d8d5 100644
--- a/gcc/rust/hir/tree/rust-hir.cc
+++ b/gcc/rust/hir/tree/rust-hir.cc
@@ -1314,7 +1314,7 @@ ContinueExpr::as_string () const
if (has_label ())
{
- str += label.as_string ();
+ str += get_label ().as_string ();
}
return str;
@@ -1704,7 +1704,7 @@ WhileLoopExpr::as_string () const
}
else
{
- str += loop_label.as_string ();
+ str += get_loop_label ().as_string ();
}
str += "\n Conditional expr: " + condition->as_string ();
@@ -1726,7 +1726,7 @@ WhileLetLoopExpr::as_string () const
}
else
{
- str += loop_label.as_string ();
+ str += get_loop_label ().as_string ();
}
str += "\n Match arm patterns: ";
@@ -1761,7 +1761,7 @@ LoopExpr::as_string () const
}
else
{
- str += loop_label.as_string ();
+ str += get_loop_label ().as_string ();
}
str += "\n Loop block: " + loop_block->as_string ();
@@ -1816,7 +1816,7 @@ BreakExpr::as_string () const
if (has_label ())
{
- str += label.as_string () + " ";
+ str += get_label ().as_string () + " ";
}
if (has_break_expr ())
@@ -2101,11 +2101,6 @@ QualifiedPathInType::as_string () const
std::string
Lifetime::as_string () const
{
- if (is_error ())
- {
- return "error lifetime";
- }
-
switch (lifetime_type)
{
case AST::Lifetime::LifetimeType::NAMED:
@@ -2760,7 +2755,7 @@ ReferenceType::as_string () const
if (has_lifetime ())
{
- str += lifetime.as_string () + " ";
+ str += get_lifetime ().as_string () + " ";
}
if (is_mut ())
@@ -3411,7 +3406,7 @@ TraitFunctionDecl::as_string () const
str += "\n Function params: ";
if (is_method ())
{
- str += self.as_string () + (has_params () ? ", " : "");
+ str += get_self_unchecked ().as_string () + (has_params () ? ", " : "");
}
if (has_params ())
@@ -3525,70 +3520,63 @@ TraitItemType::as_string () const
std::string
SelfParam::as_string () const
{
- if (is_error ())
- {
- return "error";
- }
- else
+ if (has_type ())
{
- if (has_type ())
+ // type (i.e. not ref, no lifetime)
+ std::string str;
+
+ if (is_mut ())
{
- // type (i.e. not ref, no lifetime)
- std::string str;
+ str += "mut ";
+ }
- if (is_mut ())
- {
- str += "mut ";
- }
+ str += "self : ";
- str += "self : ";
+ str += type->as_string ();
- str += type->as_string ();
+ return str;
+ }
+ else if (has_lifetime ())
+ {
+ // ref and lifetime
+ std::string str = "&" + get_lifetime ().as_string () + " ";
- return str;
- }
- else if (has_lifetime ())
+ if (is_mut ())
{
- // ref and lifetime
- std::string str = "&" + lifetime.as_string () + " ";
+ str += "mut ";
+ }
- if (is_mut ())
- {
- str += "mut ";
- }
+ str += "self";
- str += "self";
+ return str;
+ }
+ else if (is_ref ())
+ {
+ // ref with no lifetime
+ std::string str = "&";
- return str;
- }
- else if (is_ref ())
+ if (is_mut ())
{
- // ref with no lifetime
- std::string str = "&";
+ str += " mut ";
+ }
- if (is_mut ())
- {
- str += " mut ";
- }
+ str += "self";
- str += "self";
+ return str;
+ }
+ else
+ {
+ // no ref, no type
+ std::string str;
- return str;
- }
- else
+ if (is_mut ())
{
- // no ref, no type
- std::string str;
-
- if (is_mut ())
- {
- str += "mut ";
- }
+ str += "mut ";
+ }
- str += "self";
+ str += "self";
- return str;
- }
+ return str;
}
}
@@ -3834,6 +3822,17 @@ InlineAsm::accept_vis (HIRFullVisitor &vis)
}
void
+LlvmInlineAsm::accept_vis (HIRFullVisitor &vis)
+{
+ vis.visit (*this);
+}
+void
+LlvmInlineAsm::accept_vis (HIRExpressionVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
BorrowExpr::accept_vis (HIRExpressionVisitor &vis)
{
vis.visit (*this);
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index dd60868..9dda231 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -3102,7 +3102,7 @@ Parser<ManagedTokenSource>::parse_generic_param (EndTokenPred is_end_token)
{
case LIFETIME: {
auto lifetime = parse_lifetime (false);
- if (lifetime.is_error ())
+ if (!lifetime)
{
rust_error_at (
token->get_locus (),
@@ -3122,7 +3122,7 @@ Parser<ManagedTokenSource>::parse_generic_param (EndTokenPred is_end_token)
}
param = std::unique_ptr<AST::LifetimeParam> (new AST::LifetimeParam (
- std::move (lifetime), std::move (lifetime_bounds),
+ std::move (lifetime.value ()), std::move (lifetime_bounds),
std::move (outer_attrs), token->get_locus ()));
break;
}
@@ -3174,24 +3174,28 @@ Parser<ManagedTokenSource>::parse_generic_param (EndTokenPred is_end_token)
return nullptr;
// optional default value
- auto default_expr = AST::GenericArg::create_error ();
+ tl::optional<AST::GenericArg> default_expr = tl::nullopt;
if (lexer.peek_token ()->get_id () == EQUAL)
{
lexer.skip_token ();
auto tok = lexer.peek_token ();
default_expr = parse_generic_arg ();
- if (default_expr.is_error ())
- rust_error_at (tok->get_locus (),
- "invalid token for start of default value for "
- "const generic parameter: expected %<block%>, "
- "%<identifier%> or %<literal%>, got %qs",
- token_id_to_str (tok->get_id ()));
+ if (!default_expr)
+ {
+ rust_error_at (tok->get_locus (),
+ "invalid token for start of default value for "
+ "const generic parameter: expected %<block%>, "
+ "%<identifier%> or %<literal%>, got %qs",
+ token_id_to_str (tok->get_id ()));
+ return nullptr;
+ }
// At this point, we *know* that we are parsing a const
// expression
- if (default_expr.get_kind () == AST::GenericArg::Kind::Either)
- default_expr = default_expr.disambiguate_to_const ();
+ if (default_expr.value ().get_kind ()
+ == AST::GenericArg::Kind::Either)
+ default_expr = default_expr.value ().disambiguate_to_const ();
}
param = std::unique_ptr<AST::ConstGenericParam> (
@@ -3276,16 +3280,16 @@ Parser<ManagedTokenSource>::parse_lifetime_params ()
while (lexer.peek_token ()->get_id () != END_OF_FILE)
{
- AST::LifetimeParam lifetime_param = parse_lifetime_param ();
+ auto lifetime_param = parse_lifetime_param ();
- if (lifetime_param.is_error ())
+ if (!lifetime_param)
{
// can't treat as error as only way to get out with trailing comma
break;
}
lifetime_params.push_back (std::unique_ptr<AST::LifetimeParam> (
- new AST::LifetimeParam (std::move (lifetime_param))));
+ new AST::LifetimeParam (std::move (lifetime_param.value ()))));
if (lexer.peek_token ()->get_id () != COMMA)
break;
@@ -3311,9 +3315,9 @@ Parser<ManagedTokenSource>::parse_lifetime_params (EndTokenPred is_end_token)
// if end_token is not specified, it defaults to EOF, so should work fine
while (!is_end_token (lexer.peek_token ()->get_id ()))
{
- AST::LifetimeParam lifetime_param = parse_lifetime_param ();
+ auto lifetime_param = parse_lifetime_param ();
- if (lifetime_param.is_error ())
+ if (!lifetime_param)
{
/* TODO: is it worth throwing away all lifetime params just because
* one failed? */
@@ -3351,9 +3355,9 @@ Parser<ManagedTokenSource>::parse_lifetime_params_objs ()
// bad control structure as end token cannot be guaranteed
while (true)
{
- AST::LifetimeParam lifetime_param = parse_lifetime_param ();
+ auto lifetime_param = parse_lifetime_param ();
- if (lifetime_param.is_error ())
+ if (!lifetime_param)
{
// not an error as only way to exit if trailing comma
break;
@@ -3386,9 +3390,9 @@ Parser<ManagedTokenSource>::parse_lifetime_params_objs (
while (!is_end_token (lexer.peek_token ()->get_id ()))
{
- AST::LifetimeParam lifetime_param = parse_lifetime_param ();
+ auto lifetime_param = parse_lifetime_param ();
- if (lifetime_param.is_error ())
+ if (!lifetime_param)
{
/* TODO: is it worth throwing away all lifetime params just because
* one failed? */
@@ -3399,7 +3403,7 @@ Parser<ManagedTokenSource>::parse_lifetime_params_objs (
return {};
}
- lifetime_params.push_back (std::move (lifetime_param));
+ lifetime_params.push_back (std::move (lifetime_param.value ()));
if (lexer.peek_token ()->get_id () != COMMA)
break;
@@ -3458,7 +3462,7 @@ Parser<ManagedTokenSource>::parse_non_ptr_sequence (
/* Parses a single lifetime generic parameter (not including comma). */
template <typename ManagedTokenSource>
-AST::LifetimeParam
+tl::expected<AST::LifetimeParam, ParseLifetimeParamError>
Parser<ManagedTokenSource>::parse_lifetime_param ()
{
// parse outer attributes, which are optional and may not exist
@@ -3468,8 +3472,8 @@ Parser<ManagedTokenSource>::parse_lifetime_param ()
const_TokenPtr lifetime_tok = lexer.peek_token ();
if (lifetime_tok->get_id () != LIFETIME)
{
- // if lifetime is missing, must not be a lifetime param, so return null
- return AST::LifetimeParam::create_error ();
+ // if lifetime is missing, must not be a lifetime param, so return error
+ return tl::make_unexpected<ParseLifetimeParamError> ({});
}
lexer.skip_token ();
AST::Lifetime lifetime (AST::Lifetime::NAMED, lifetime_tok->get_str (),
@@ -3815,12 +3819,13 @@ template <typename ManagedTokenSource>
std::unique_ptr<AST::LifetimeWhereClauseItem>
Parser<ManagedTokenSource>::parse_lifetime_where_clause_item ()
{
- AST::Lifetime lifetime = parse_lifetime (false);
- if (lifetime.is_error ())
+ auto parsed_lifetime = parse_lifetime (false);
+ if (!parsed_lifetime)
{
// TODO: error here?
return nullptr;
}
+ auto lifetime = parsed_lifetime.value ();
if (!skip_token (COLON))
{
@@ -4013,7 +4018,7 @@ Parser<ManagedTokenSource>::parse_type_param_bound ()
{
case LIFETIME:
return std::unique_ptr<AST::Lifetime> (
- new AST::Lifetime (parse_lifetime (false)));
+ new AST::Lifetime (parse_lifetime (false).value ()));
case LEFT_PAREN:
case QUESTION_MARK:
case FOR:
@@ -4086,13 +4091,13 @@ Parser<ManagedTokenSource>::parse_lifetime_bounds ()
while (true)
{
- AST::Lifetime lifetime = parse_lifetime (false);
+ auto lifetime = parse_lifetime (false);
// quick exit for parsing failure
- if (lifetime.is_error ())
+ if (!lifetime)
break;
- lifetime_bounds.push_back (std::move (lifetime));
+ lifetime_bounds.push_back (std::move (lifetime.value ()));
/* plus is maybe not allowed at end - spec defines it weirdly, so
* assuming allowed at end */
@@ -4116,9 +4121,9 @@ Parser<ManagedTokenSource>::parse_lifetime_bounds (EndTokenPred is_end_token)
while (!is_end_token (lexer.peek_token ()->get_id ()))
{
- AST::Lifetime lifetime = parse_lifetime (false);
+ auto lifetime = parse_lifetime (false);
- if (lifetime.is_error ())
+ if (!lifetime)
{
/* TODO: is it worth throwing away all lifetime bound info just
* because one failed? */
@@ -4129,7 +4134,7 @@ Parser<ManagedTokenSource>::parse_lifetime_bounds (EndTokenPred is_end_token)
return {};
}
- lifetime_bounds.push_back (std::move (lifetime));
+ lifetime_bounds.push_back (std::move (lifetime.value ()));
/* plus is maybe not allowed at end - spec defines it weirdly, so
* assuming allowed at end */
@@ -4146,14 +4151,20 @@ Parser<ManagedTokenSource>::parse_lifetime_bounds (EndTokenPred is_end_token)
/* Parses a lifetime token (named, 'static, or '_). Also handles lifetime not
* existing. */
template <typename ManagedTokenSource>
-AST::Lifetime
+tl::expected<AST::Lifetime, ParseLifetimeError>
Parser<ManagedTokenSource>::parse_lifetime (bool allow_elided)
{
const_TokenPtr lifetime_tok = lexer.peek_token ();
if (lifetime_tok->get_id () != LIFETIME)
{
- return (allow_elided) ? AST::Lifetime::elided ()
- : AST::Lifetime::error ();
+ if (allow_elided)
+ {
+ return AST::Lifetime::elided ();
+ }
+ else
+ {
+ return tl::make_unexpected<ParseLifetimeError> ({});
+ }
}
lexer.skip_token ();
@@ -6163,6 +6174,10 @@ Parser<ManagedTokenSource>::parse_let_stmt (AST::AttrVec outer_attrs,
}
}
+ tl::optional<std::unique_ptr<AST::Expr>> else_expr = tl::nullopt;
+ if (maybe_skip_token (ELSE))
+ else_expr = parse_block_expr ();
+
if (restrictions.consume_semi)
{
// `stmt` macro variables are parsed without a semicolon, but should be
@@ -6177,7 +6192,7 @@ Parser<ManagedTokenSource>::parse_let_stmt (AST::AttrVec outer_attrs,
return std::unique_ptr<AST::LetStmt> (
new AST::LetStmt (std::move (pattern), std::move (expr), std::move (type),
- std::move (outer_attrs), locus));
+ std::move (else_expr), std::move (outer_attrs), locus));
}
// Parses a type path.
@@ -6238,7 +6253,7 @@ Parser<ManagedTokenSource>::parse_type_path ()
}
template <typename ManagedTokenSource>
-AST::GenericArg
+tl::optional<AST::GenericArg>
Parser<ManagedTokenSource>::parse_generic_arg ()
{
auto tok = lexer.peek_token ();
@@ -6259,7 +6274,7 @@ Parser<ManagedTokenSource>::parse_generic_arg ()
if (type)
return AST::GenericArg::create_type (std::move (type));
else
- return AST::GenericArg::create_error ();
+ return tl::nullopt;
}
else if (next_tok->get_id () == COLON)
{
@@ -6276,7 +6291,7 @@ Parser<ManagedTokenSource>::parse_generic_arg ()
if (type)
return AST::GenericArg::create_type (std::move (type));
else
- return AST::GenericArg::create_error ();
+ return tl::nullopt;
}
lexer.skip_token ();
return AST::GenericArg::create_ambiguous (tok->get_str (),
@@ -6302,12 +6317,12 @@ Parser<ManagedTokenSource>::parse_generic_arg ()
if (type)
return AST::GenericArg::create_type (std::move (type));
else
- return AST::GenericArg::create_error ();
+ return tl::nullopt;
}
}
if (!expr)
- return AST::GenericArg::create_error ();
+ return tl::nullopt;
return AST::GenericArg::create_const (std::move (expr));
}
@@ -6336,14 +6351,14 @@ Parser<ManagedTokenSource>::parse_path_generic_args ()
location_t locus = t->get_locus ();
while (!is_right_angle_tok (t->get_id ()))
{
- AST::Lifetime lifetime = parse_lifetime (false);
- if (lifetime.is_error ())
+ auto lifetime = parse_lifetime (false);
+ if (!lifetime)
{
// not necessarily an error
break;
}
- lifetime_args.push_back (std::move (lifetime));
+ lifetime_args.push_back (std::move (lifetime.value ()));
// if next token isn't comma, then it must be end of list
if (lexer.peek_token ()->get_id () != COMMA)
@@ -6372,9 +6387,9 @@ Parser<ManagedTokenSource>::parse_path_generic_args ()
break;
auto arg = parse_generic_arg ();
- if (!arg.is_error ())
+ if (arg)
{
- generic_args.emplace_back (std::move (arg));
+ generic_args.emplace_back (std::move (arg.value ()));
}
// FIXME: Do we need to break if we encounter an error?
@@ -6957,10 +6972,12 @@ Parser<ManagedTokenSource>::parse_self_param ()
// now test whether it has a lifetime
if (lexer.peek_token ()->get_id () == LIFETIME)
{
- lifetime = parse_lifetime (true);
-
// something went wrong somehow
- if (lifetime.is_error ())
+ if (auto parsed_lifetime = parse_lifetime (true))
+ {
+ lifetime = parsed_lifetime.value ();
+ }
+ else
{
Error error (lexer.peek_token ()->get_locus (),
"failed to parse lifetime in self param");
@@ -7149,9 +7166,9 @@ Parser<ManagedTokenSource>::parse_expr_stmt (AST::AttrVec outer_attrs,
// Parses a block expression, including the curly braces at start and end.
template <typename ManagedTokenSource>
std::unique_ptr<AST::BlockExpr>
-Parser<ManagedTokenSource>::parse_block_expr (AST::AttrVec outer_attrs,
- AST::LoopLabel label,
- location_t pratt_parsed_loc)
+Parser<ManagedTokenSource>::parse_block_expr (
+ AST::AttrVec outer_attrs, tl::optional<AST::LoopLabel> label,
+ location_t pratt_parsed_loc)
{
location_t locus = pratt_parsed_loc;
if (locus == UNKNOWN_LOCATION)
@@ -7515,12 +7532,10 @@ Parser<ManagedTokenSource>::parse_break_expr (AST::AttrVec outer_attrs,
skip_token (BREAK);
}
- // parse label (lifetime) if it exists - create dummy first
- AST::Lifetime label = AST::Lifetime::error ();
- if (lexer.peek_token ()->get_id () == LIFETIME)
- {
- label = parse_lifetime (false);
- }
+ auto parsed_label = parse_lifetime (false);
+ auto label = (parsed_label)
+ ? tl::optional<AST::Lifetime> (parsed_label.value ())
+ : tl::nullopt;
// parse break return expression if it exists
ParseRestrictions restrictions;
@@ -7546,12 +7561,10 @@ Parser<ManagedTokenSource>::parse_continue_expr (AST::AttrVec outer_attrs,
skip_token (CONTINUE);
}
- // parse label (lifetime) if it exists - create dummy first
- AST::Lifetime label = AST::Lifetime::error ();
- if (lexer.peek_token ()->get_id () == LIFETIME)
- {
- label = parse_lifetime (false);
- }
+ auto parsed_label = parse_lifetime (false);
+ auto label = (parsed_label)
+ ? tl::optional<AST::Lifetime> (parsed_label.value ())
+ : tl::nullopt;
return std::unique_ptr<AST::ContinueExpr> (
new AST::ContinueExpr (std::move (label), std::move (outer_attrs), locus));
@@ -7559,14 +7572,15 @@ Parser<ManagedTokenSource>::parse_continue_expr (AST::AttrVec outer_attrs,
// Parses a loop label used in loop expressions.
template <typename ManagedTokenSource>
-AST::LoopLabel
+tl::expected<AST::LoopLabel, ParseLoopLabelError>
Parser<ManagedTokenSource>::parse_loop_label (const_TokenPtr tok)
{
// parse lifetime - if doesn't exist, assume no label
if (tok->get_id () != LIFETIME)
{
// not necessarily an error
- return AST::LoopLabel::error ();
+ return tl::unexpected<ParseLoopLabelError> (
+ ParseLoopLabelError::NOT_LOOP_LABEL);
}
/* FIXME: check for named lifetime requirement here? or check in semantic
* analysis phase? */
@@ -7575,10 +7589,12 @@ Parser<ManagedTokenSource>::parse_loop_label (const_TokenPtr tok)
if (!skip_token (COLON))
{
// skip somewhere?
- return AST::LoopLabel::error ();
+ return tl::unexpected<ParseLoopLabelError> (
+ ParseLoopLabelError::MISSING_COLON);
}
- return AST::LoopLabel (std::move (label), tok->get_locus ());
+ return tl::expected<AST::LoopLabel, ParseLoopLabelError> (
+ AST::LoopLabel (std::move (label), tok->get_locus ()));
}
/* Parses an if expression of any kind, including with else, else if, else if
@@ -7931,16 +7947,16 @@ Parser<ManagedTokenSource>::parse_if_let_expr (AST::AttrVec outer_attrs,
template <typename ManagedTokenSource>
std::unique_ptr<AST::LoopExpr>
Parser<ManagedTokenSource>::parse_loop_expr (AST::AttrVec outer_attrs,
- AST::LoopLabel label,
+ tl::optional<AST::LoopLabel> label,
location_t pratt_parsed_loc)
{
location_t locus = pratt_parsed_loc;
if (locus == UNKNOWN_LOCATION)
{
- if (label.is_error ())
- locus = lexer.peek_token ()->get_locus ();
+ if (label)
+ locus = label->get_locus ();
else
- locus = label.get_locus ();
+ locus = lexer.peek_token ()->get_locus ();
if (!skip_token (LOOP))
{
@@ -7950,8 +7966,8 @@ Parser<ManagedTokenSource>::parse_loop_expr (AST::AttrVec outer_attrs,
}
else
{
- if (!label.is_error ())
- locus = label.get_locus ();
+ if (label)
+ locus = label->get_locus ();
}
// parse loop body, which is required
@@ -7974,17 +7990,17 @@ Parser<ManagedTokenSource>::parse_loop_expr (AST::AttrVec outer_attrs,
* via parse_labelled_loop_expr, which would call this. */
template <typename ManagedTokenSource>
std::unique_ptr<AST::WhileLoopExpr>
-Parser<ManagedTokenSource>::parse_while_loop_expr (AST::AttrVec outer_attrs,
- AST::LoopLabel label,
- location_t pratt_parsed_loc)
+Parser<ManagedTokenSource>::parse_while_loop_expr (
+ AST::AttrVec outer_attrs, tl::optional<AST::LoopLabel> label,
+ location_t pratt_parsed_loc)
{
location_t locus = pratt_parsed_loc;
if (locus == UNKNOWN_LOCATION)
{
- if (label.is_error ())
- locus = lexer.peek_token ()->get_locus ();
+ if (label)
+ locus = label->get_locus ();
else
- locus = label.get_locus ();
+ locus = lexer.peek_token ()->get_locus ();
if (!skip_token (WHILE))
{
@@ -7994,8 +8010,8 @@ Parser<ManagedTokenSource>::parse_while_loop_expr (AST::AttrVec outer_attrs,
}
else
{
- if (!label.is_error ())
- locus = label.get_locus ();
+ if (label)
+ locus = label->get_locus ();
}
// ensure it isn't a while let loop
@@ -8047,14 +8063,14 @@ Parser<ManagedTokenSource>::parse_while_loop_expr (AST::AttrVec outer_attrs,
* parsed via parse_labelled_loop_expr, which would call this. */
template <typename ManagedTokenSource>
std::unique_ptr<AST::WhileLetLoopExpr>
-Parser<ManagedTokenSource>::parse_while_let_loop_expr (AST::AttrVec outer_attrs,
- AST::LoopLabel label)
+Parser<ManagedTokenSource>::parse_while_let_loop_expr (
+ AST::AttrVec outer_attrs, tl::optional<AST::LoopLabel> label)
{
location_t locus = UNKNOWN_LOCATION;
- if (label.is_error ())
- locus = lexer.peek_token ()->get_locus ();
+ if (label)
+ locus = label->get_locus ();
else
- locus = label.get_locus ();
+ locus = lexer.peek_token ()->get_locus ();
maybe_skip_token (WHILE);
/* check for possible accidental recognition of a while loop as a while let
@@ -8121,14 +8137,14 @@ Parser<ManagedTokenSource>::parse_while_let_loop_expr (AST::AttrVec outer_attrs,
* parse_labelled_loop_expr, which would call this. */
template <typename ManagedTokenSource>
std::unique_ptr<AST::ForLoopExpr>
-Parser<ManagedTokenSource>::parse_for_loop_expr (AST::AttrVec outer_attrs,
- AST::LoopLabel label)
+Parser<ManagedTokenSource>::parse_for_loop_expr (
+ AST::AttrVec outer_attrs, tl::optional<AST::LoopLabel> label)
{
location_t locus = UNKNOWN_LOCATION;
- if (label.is_error ())
- locus = lexer.peek_token ()->get_locus ();
+ if (label)
+ locus = label->get_locus ();
else
- locus = label.get_locus ();
+ locus = lexer.peek_token ()->get_locus ();
maybe_skip_token (FOR);
// parse pattern, which is required
@@ -8206,8 +8222,9 @@ Parser<ManagedTokenSource>::parse_labelled_loop_expr (const_TokenPtr tok,
}
// parse loop label (required)
- AST::LoopLabel label = parse_loop_label (tok);
- if (label.is_error ())
+ // TODO: Convert this return type to tl::expected instead of tl::optional
+ auto parsed_label = parse_loop_label (tok);
+ if (!parsed_label)
{
Error error (lexer.peek_token ()->get_locus (),
"failed to parse loop label in labelled loop expr");
@@ -8217,6 +8234,10 @@ Parser<ManagedTokenSource>::parse_labelled_loop_expr (const_TokenPtr tok,
return nullptr;
}
+ auto label = parsed_label
+ ? tl::optional<AST::LoopLabel> (parsed_label.value ())
+ : tl::nullopt;
+
// branch on next token
const_TokenPtr t = lexer.peek_token ();
switch (t->get_id ())
@@ -9594,8 +9615,12 @@ Parser<ManagedTokenSource>::parse_reference_type_inner (location_t locus)
AST::Lifetime lifetime = AST::Lifetime::elided ();
if (lexer.peek_token ()->get_id () == LIFETIME)
{
- lifetime = parse_lifetime (true);
- if (lifetime.is_error ())
+ auto parsed_lifetime = parse_lifetime (true);
+ if (parsed_lifetime)
+ {
+ lifetime = parsed_lifetime.value ();
+ }
+ else
{
Error error (lexer.peek_token ()->get_locus (),
"failed to parse lifetime in reference type");
@@ -12396,8 +12421,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
return parse_continue_expr (std::move (outer_attrs), tok->get_locus ());
case LEFT_CURLY:
// ok - this is an expression with block for once.
- return parse_block_expr (std::move (outer_attrs),
- AST::LoopLabel::error (), tok->get_locus ());
+ return parse_block_expr (std::move (outer_attrs), tl::nullopt,
+ tok->get_locus ());
case IF:
// if or if let, so more lookahead to find out
if (lexer.peek_token ()->get_id () == LET)
@@ -12413,7 +12438,7 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
case LIFETIME:
return parse_labelled_loop_expr (tok, std::move (outer_attrs));
case LOOP:
- return parse_loop_expr (std::move (outer_attrs), AST::LoopLabel::error (),
+ return parse_loop_expr (std::move (outer_attrs), tl::nullopt,
tok->get_locus ());
case WHILE:
if (lexer.peek_token ()->get_id () == LET)
@@ -12422,13 +12447,11 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
}
else
{
- return parse_while_loop_expr (std::move (outer_attrs),
- AST::LoopLabel::error (),
+ return parse_while_loop_expr (std::move (outer_attrs), tl::nullopt,
tok->get_locus ());
}
case FOR:
- return parse_for_loop_expr (std::move (outer_attrs),
- AST::LoopLabel::error ());
+ return parse_for_loop_expr (std::move (outer_attrs), tl::nullopt);
case MATCH_KW:
// also an expression with block
return parse_match_expr (std::move (outer_attrs), tok->get_locus ());
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index 6c50ba9..827d91d 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -25,6 +25,26 @@ along with GCC; see the file COPYING3. If not see
#include "expected.h"
namespace Rust {
+
+class ParseLifetimeParamError
+{
+};
+
+class ParseLifetimeError
+{
+};
+enum class ParseLoopLabelError
+{
+ NOT_LOOP_LABEL,
+ MISSING_COLON,
+};
+enum ParseSelfError
+{
+ SELF_PTR,
+ PARSING,
+ NOT_SELF,
+};
+
/* HACK: used to resolve the expression-or-statement problem at the end of a
* block by allowing either to be returned (technically). Tagged union would
* probably take up the same amount of space. */
@@ -95,12 +115,6 @@ struct ParseRestrictions
bool allow_close_after_expr_stmt = false;
};
-enum ParseSelfError
-{
- SELF_PTR,
- PARSING,
- NOT_SELF,
-};
// Parser implementation for gccrs.
// TODO: if updated to C++20, ManagedTokenSource would be useful as a concept
template <typename ManagedTokenSource> class Parser
@@ -148,7 +162,7 @@ public:
std::unique_ptr<AST::BlockExpr>
parse_block_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
- AST::LoopLabel label = AST::LoopLabel::error (),
+ tl::optional<AST::LoopLabel> = tl::nullopt,
location_t pratt_parsed_loc = UNKNOWN_LOCATION);
bool is_macro_rules_def (const_TokenPtr t);
@@ -212,7 +226,7 @@ private:
AST::TypePath parse_type_path ();
std::unique_ptr<AST::TypePathSegment> parse_type_path_segment ();
AST::PathIdentSegment parse_path_ident_segment ();
- AST::GenericArg parse_generic_arg ();
+ tl::optional<AST::GenericArg> parse_generic_arg ();
AST::GenericArgs parse_path_generic_args ();
AST::GenericArgsBinding parse_generic_args_binding ();
AST::TypePathFunction parse_type_path_function (location_t locus);
@@ -277,7 +291,8 @@ private:
ParseFunction parsing_function, EndTokenPred is_end_token,
std::string error_msg = "failed to parse generic param in generic params")
-> std::vector<decltype (parsing_function ())>;
- AST::LifetimeParam parse_lifetime_param ();
+ tl::expected<AST::LifetimeParam, ParseLifetimeParamError>
+ parse_lifetime_param ();
std::vector<std::unique_ptr<AST::TypeParam>> parse_type_params ();
template <typename EndTokenPred>
std::vector<std::unique_ptr<AST::TypeParam>>
@@ -306,7 +321,8 @@ private:
std::vector<AST::Lifetime> parse_lifetime_bounds ();
template <typename EndTokenPred>
std::vector<AST::Lifetime> parse_lifetime_bounds (EndTokenPred is_end_token);
- AST::Lifetime parse_lifetime (bool allow_elided);
+ tl::expected<AST::Lifetime, ParseLifetimeError>
+ parse_lifetime (bool allow_elided);
AST::Lifetime lifetime_from_token (const_TokenPtr tok);
std::unique_ptr<AST::ExternalTypeItem>
parse_external_type_item (AST::Visibility vis, AST::AttrVec outer_attrs);
@@ -588,18 +604,18 @@ private:
location_t pratt_parsed_loc = UNKNOWN_LOCATION);
std::unique_ptr<AST::LoopExpr>
parse_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
- AST::LoopLabel label = AST::LoopLabel::error (),
+ tl::optional<AST::LoopLabel> label = tl::nullopt,
location_t pratt_parsed_loc = UNKNOWN_LOCATION);
std::unique_ptr<AST::WhileLoopExpr>
parse_while_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
- AST::LoopLabel label = AST::LoopLabel::error (),
+ tl::optional<AST::LoopLabel> label = tl::nullopt,
location_t pratt_parsed_loc = UNKNOWN_LOCATION);
std::unique_ptr<AST::WhileLetLoopExpr>
parse_while_let_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
- AST::LoopLabel label = AST::LoopLabel::error ());
+ tl::optional<AST::LoopLabel> label = tl::nullopt);
std::unique_ptr<AST::ForLoopExpr>
parse_for_loop_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
- AST::LoopLabel label = AST::LoopLabel::error ());
+ tl::optional<AST::LoopLabel> label = tl::nullopt);
std::unique_ptr<AST::MatchExpr>
parse_match_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
location_t pratt_parsed_loc = UNKNOWN_LOCATION);
@@ -609,7 +625,8 @@ private:
std::unique_ptr<AST::Expr> parse_labelled_loop_expr (const_TokenPtr tok,
AST::AttrVec outer_attrs
= AST::AttrVec ());
- AST::LoopLabel parse_loop_label (const_TokenPtr tok);
+ tl::expected<AST::LoopLabel, ParseLoopLabelError>
+ parse_loop_label (const_TokenPtr tok);
std::unique_ptr<AST::AsyncBlockExpr>
parse_async_block_expr (AST::AttrVec outer_attrs = AST::AttrVec ());
std::unique_ptr<AST::GroupedExpr> parse_grouped_expr (AST::AttrVec outer_attrs
diff --git a/gcc/rust/resolve/rust-ast-resolve-base.cc b/gcc/rust/resolve/rust-ast-resolve-base.cc
index 6c35a22..b781ce33 100644
--- a/gcc/rust/resolve/rust-ast-resolve-base.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-base.cc
@@ -328,6 +328,10 @@ ResolverBase::visit (AST::InlineAsm &)
{}
void
+ResolverBase::visit (AST::LlvmInlineAsm &)
+{}
+
+void
ResolverBase::visit (AST::TypeParam &)
{}
diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h b/gcc/rust/resolve/rust-ast-resolve-base.h
index 0d497f8..5bb9e4f 100644
--- a/gcc/rust/resolve/rust-ast-resolve-base.h
+++ b/gcc/rust/resolve/rust-ast-resolve-base.h
@@ -27,6 +27,11 @@
namespace Rust {
namespace Resolver {
+inline void
+redefined_error (const rich_location &loc)
+{
+ rust_error_at (loc, "redefined multiple times");
+}
class ResolverBase : public AST::ASTVisitor
{
@@ -105,6 +110,7 @@ public:
void visit (AST::AwaitExpr &);
void visit (AST::AsyncBlockExpr &);
void visit (AST::InlineAsm &);
+ void visit (AST::LlvmInlineAsm &);
void visit (AST::TypeParam &);
diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.cc b/gcc/rust/resolve/rust-ast-resolve-expr.cc
index dc7f76d..6242235 100644
--- a/gcc/rust/resolve/rust-ast-resolve-expr.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-expr.cc
@@ -368,6 +368,17 @@ ResolveExpr::visit (AST::InlineAsm &expr)
{
translate_operand (expr, prefix, canonical_prefix);
}
+
+void
+ResolveExpr::visit (AST::LlvmInlineAsm &expr)
+{
+ for (auto &output : expr.get_outputs ())
+ ResolveExpr::go (*output.expr, prefix, canonical_prefix);
+
+ for (auto &input : expr.get_inputs ())
+ ResolveExpr::go (*input.expr, prefix, canonical_prefix);
+}
+
void
ResolveExpr::visit (AST::UnsafeBlockExpr &expr)
{
@@ -471,7 +482,7 @@ ResolveExpr::visit (AST::BreakExpr &expr)
{
if (expr.has_label ())
{
- auto label = expr.get_label ().get_lifetime ();
+ auto label = expr.get_label_unchecked ().get_lifetime ();
if (label.get_lifetime_type () != AST::Lifetime::LifetimeType::NAMED)
{
rust_error_at (label.get_locus (),
@@ -486,8 +497,8 @@ ResolveExpr::visit (AST::BreakExpr &expr)
&resolved_node))
{
rust_error_at (label.get_locus (), ErrorCode::E0426,
- "use of undeclared label %qs in %<break%>",
- label.get_lifetime_name ().c_str ());
+ "use of undeclared label %qs",
+ label.as_string ().c_str ());
return;
}
resolver->insert_resolved_label (label.get_node_id (), resolved_node);
@@ -594,7 +605,7 @@ ResolveExpr::visit (AST::ContinueExpr &expr)
{
if (expr.has_label ())
{
- auto label = expr.get_label ();
+ auto label = expr.get_label_unchecked ();
if (label.get_lifetime_type () != AST::Lifetime::LifetimeType::NAMED)
{
rust_error_at (label.get_locus (),
@@ -608,9 +619,9 @@ ResolveExpr::visit (AST::ContinueExpr &expr)
label.get_lifetime_name ()),
&resolved_node))
{
- rust_error_at (expr.get_label ().get_locus (), ErrorCode::E0426,
- "use of undeclared label %qs in %<continue%>",
- label.get_lifetime_name ().c_str ());
+ rust_error_at (expr.get_label_unchecked ().get_locus (),
+ ErrorCode::E0426, "use of undeclared label %qs",
+ label.as_string ().c_str ());
return;
}
resolver->insert_resolved_label (label.get_node_id (), resolved_node);
diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h
index 562a3bd..b296d66 100644
--- a/gcc/rust/resolve/rust-ast-resolve-expr.h
+++ b/gcc/rust/resolve/rust-ast-resolve-expr.h
@@ -57,6 +57,7 @@ public:
void visit (AST::IfLetExprConseqElse &expr) override;
void visit (AST::BlockExpr &expr) override;
void visit (AST::InlineAsm &expr) override;
+ void visit (AST::LlvmInlineAsm &expr) override;
void visit (AST::UnsafeBlockExpr &expr) override;
void visit (AST::ArrayElemsValues &elems) override;
void visit (AST::ArrayExpr &expr) override;
diff --git a/gcc/rust/resolve/rust-ast-resolve-implitem.h b/gcc/rust/resolve/rust-ast-resolve-implitem.h
index 971bf8f..2081697 100644
--- a/gcc/rust/resolve/rust-ast-resolve-implitem.h
+++ b/gcc/rust/resolve/rust-ast-resolve-implitem.h
@@ -51,7 +51,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, type.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
}
@@ -67,7 +67,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, constant.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
}
@@ -84,7 +84,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, function.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
}
@@ -124,7 +124,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, function.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
mappings.insert_canonical_path (function.get_node_id (), cpath);
@@ -144,7 +144,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, constant.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
mappings.insert_canonical_path (constant.get_node_id (), cpath);
@@ -162,7 +162,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, type.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
mappings.insert_canonical_path (type.get_node_id (), cpath);
@@ -202,7 +202,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, function.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
NodeId current_module = resolver->peek_current_module_scope ();
@@ -221,7 +221,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, item.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
NodeId current_module = resolver->peek_current_module_scope ();
@@ -239,8 +239,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, type.get_locus ());
r.add_range (locus);
-
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
NodeId current_module = resolver->peek_current_module_scope ();
diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc
index d584961..30f6d43 100644
--- a/gcc/rust/resolve/rust-ast-resolve-item.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-item.cc
@@ -356,6 +356,8 @@ ResolveItem::visit (AST::EnumItemDiscriminant &item)
auto cpath = canonical_prefix.append (decl);
mappings.insert_canonical_path (item.get_node_id (), cpath);
+
+ ResolveExpr::go (item.get_expr (), path, cpath);
}
void
diff --git a/gcc/rust/resolve/rust-ast-resolve-path.cc b/gcc/rust/resolve/rust-ast-resolve-path.cc
index b2b1071..fb6715d 100644
--- a/gcc/rust/resolve/rust-ast-resolve-path.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-path.cc
@@ -68,8 +68,7 @@ ResolvePath::resolve_path (AST::PathInExpression &expr)
if (in_middle_of_path && segment.is_lower_self_seg ())
{
rust_error_at (segment.get_locus (), ErrorCode::E0433,
- "leading path segment %qs can only be used at the "
- "beginning of a path",
+ "%qs in paths can only be used in start position",
segment.as_string ().c_str ());
return UNKNOWN_NODEID;
}
@@ -370,6 +369,13 @@ ResolvePath::resolve_path (AST::SimplePath &expr)
}
else if (segment.is_super_path_seg ())
{
+ if (!is_first_segment)
+ {
+ rust_error_at (
+ segment.get_locus (), ErrorCode::E0433,
+ "%<super%> in paths can only be used in start position");
+ return UNKNOWN_NODEID;
+ }
if (module_scope_id == crate_scope_id)
{
rust_error_at (segment.get_locus (),
diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.cc b/gcc/rust/resolve/rust-ast-resolve-stmt.cc
index fefb522..bfba302 100644
--- a/gcc/rust/resolve/rust-ast-resolve-stmt.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-stmt.cc
@@ -70,7 +70,7 @@ ResolveStmt::visit (AST::StaticItem &var)
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, var.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
ResolveType::go (var.get_type ());
diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h
index d3ff14f..d413a7c 100644
--- a/gcc/rust/resolve/rust-ast-resolve-stmt.h
+++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h
@@ -63,7 +63,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, constant.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
ResolveType::go (constant.get_type ());
@@ -73,9 +73,10 @@ public:
void visit (AST::LetStmt &stmt) override
{
if (stmt.has_init_expr ())
- {
- ResolveExpr::go (stmt.get_init_expr (), prefix, canonical_prefix);
- }
+ ResolveExpr::go (stmt.get_init_expr (), prefix, canonical_prefix);
+
+ if (stmt.has_else_expr ())
+ ResolveExpr::go (stmt.get_else_expr (), prefix, canonical_prefix);
PatternDeclaration::go (stmt.get_pattern (), Rib::ItemType::Var);
if (stmt.has_type ())
@@ -97,7 +98,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, struct_decl.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
NodeId scope_node_id = struct_decl.get_node_id ();
@@ -128,7 +129,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, enum_decl.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
NodeId scope_node_id = enum_decl.get_node_id ();
@@ -158,7 +159,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, item.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
// Done, no fields.
@@ -178,7 +179,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, item.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
for (auto &field : item.get_tuple_fields ())
@@ -204,7 +205,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, item.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
for (auto &field : item.get_struct_fields ())
@@ -230,7 +231,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, item.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
// Done, no fields.
@@ -251,7 +252,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, struct_decl.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
NodeId scope_node_id = struct_decl.get_node_id ();
@@ -287,7 +288,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, union_decl.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
NodeId scope_node_id = union_decl.get_node_id ();
@@ -323,7 +324,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, function.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
NodeId scope_node_id = function.get_node_id ();
diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h
index 379ccab..f52fb8a 100644
--- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h
+++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h
@@ -58,7 +58,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, module.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
NodeId current_module = resolver->peek_current_module_scope ();
@@ -88,7 +88,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, alias.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
NodeId current_module = resolver->peek_current_module_scope ();
@@ -110,7 +110,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, struct_decl.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
NodeId current_module = resolver->peek_current_module_scope ();
@@ -132,7 +132,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, enum_decl.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
resolver->push_new_module_scope (enum_decl.get_node_id ());
@@ -158,7 +158,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, item.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
mappings.insert_canonical_path (item.get_node_id (), cpath);
@@ -180,7 +180,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, item.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
mappings.insert_canonical_path (item.get_node_id (), cpath);
@@ -202,7 +202,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, item.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
mappings.insert_canonical_path (item.get_node_id (), cpath);
@@ -224,7 +224,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, item.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
mappings.insert_canonical_path (item.get_node_id (), cpath);
@@ -246,7 +246,7 @@ public:
= [&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, struct_decl.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
};
resolver->get_type_scope ().insert (path, struct_decl.get_node_id (),
@@ -277,7 +277,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, union_decl.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
NodeId current_module = resolver->peek_current_module_scope ();
@@ -297,7 +297,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, var.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
NodeId current_module = resolver->peek_current_module_scope ();
@@ -318,7 +318,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, constant.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
NodeId current_module = resolver->peek_current_module_scope ();
@@ -340,7 +340,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, function.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
NodeId current_module = resolver->peek_current_module_scope ();
@@ -388,7 +388,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, impl_block.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
for (auto &impl_item : impl_block.get_impl_items ())
@@ -408,7 +408,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, trait.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
for (auto &item : trait.get_trait_items ())
@@ -480,7 +480,7 @@ public:
[&] (const CanonicalPath &, NodeId, location_t locus) -> void {
rich_location r (line_table, extern_crate.get_locus ());
r.add_range (locus);
- rust_error_at (r, "defined multiple times");
+ redefined_error (r);
});
}
diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc b/gcc/rust/resolve/rust-ast-resolve-type.cc
index 5ab0c44..8fd69c3 100644
--- a/gcc/rust/resolve/rust-ast-resolve-type.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-type.cc
@@ -176,8 +176,7 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id)
if (in_middle_of_path && segment->is_lower_self_seg ())
{
rust_error_at (segment->get_locus (), ErrorCode::E0433,
- "leading path segment %qs can only be used at the "
- "beginning of a path",
+ "%qs in paths can only be used in start position",
segment->as_string ().c_str ());
return false;
}
@@ -357,7 +356,7 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id)
{
rust_error_at (segment->get_locus (), ErrorCode::E0412,
"could not resolve type path %qs",
- segment->as_string ().c_str ());
+ segment->get_ident_segment ().as_string ().c_str ());
return false;
}
}
diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h
index 8379d0e..f1481fc 100644
--- a/gcc/rust/resolve/rust-ast-resolve-type.h
+++ b/gcc/rust/resolve/rust-ast-resolve-type.h
@@ -141,8 +141,8 @@ public:
if (first_pass)
ResolveType::go (param.get_type ());
else if (param.has_default_value ())
- ResolveExpr::go (param.get_default_value ().get_expression (), prefix,
- canonical_prefix);
+ ResolveExpr::go (param.get_default_value_unchecked ().get_expression (),
+ prefix, canonical_prefix);
}
void visit (AST::TypeParam &param) override
diff --git a/gcc/rust/resolve/rust-default-resolver.cc b/gcc/rust/resolve/rust-default-resolver.cc
index 7528e79..480034c 100644
--- a/gcc/rust/resolve/rust-default-resolver.cc
+++ b/gcc/rust/resolve/rust-default-resolver.cc
@@ -179,5 +179,13 @@ DefaultResolver::visit (AST::StaticItem &item)
ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis);
}
+void
+DefaultResolver::visit (AST::TypeParam &param)
+{
+ auto expr_vis = [this, &param] () { AST::DefaultASTVisitor::visit (param); };
+
+ ctx.scoped (Rib::Kind::ForwardTypeParamBan, param.get_node_id (), expr_vis);
+}
+
} // namespace Resolver2_0
} // namespace Rust
diff --git a/gcc/rust/resolve/rust-default-resolver.h b/gcc/rust/resolve/rust-default-resolver.h
index 587d7d4..2a987ef 100644
--- a/gcc/rust/resolve/rust-default-resolver.h
+++ b/gcc/rust/resolve/rust-default-resolver.h
@@ -50,6 +50,8 @@ public:
void visit (AST::InherentImpl &) override;
void visit (AST::TraitImpl &) override;
+ void visit (AST::TypeParam &) override;
+
// type dec nodes, which visit their fields or variants by default
void visit (AST::StructStruct &) override;
void visit (AST::TupleStruct &) override;
diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
index 492a665..3390f09 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
@@ -70,8 +70,7 @@ Early::go (AST::Crate &crate)
bool
Early::resolve_glob_import (NodeId use_dec_id, TopLevel::ImportKind &&glob)
{
- auto resolved
- = ctx.resolve_path (glob.to_resolve.get_segments (), Namespace::Types);
+ auto resolved = ctx.resolve_path (glob.to_resolve, Namespace::Types);
if (!resolved.has_value ())
return false;
@@ -141,6 +140,10 @@ Early::build_import_mapping (
// be moved into the newly created import mappings
auto path = import.to_resolve;
+ // used to skip the "unresolved import" error
+ // if we output other errors during resolution
+ size_t old_error_count = macro_resolve_errors.size ();
+
switch (import.kind)
{
case TopLevel::ImportKind::Kind::Glob:
@@ -154,7 +157,7 @@ Early::build_import_mapping (
break;
}
- if (!found)
+ if (!found && old_error_count == macro_resolve_errors.size ())
collect_error (Error (path.get_final_segment ().get_locus (),
ErrorCode::E0433, "unresolved import %qs",
path.as_string ().c_str ()));
@@ -325,10 +328,9 @@ Early::visit_attributes (std::vector<AST::Attribute> &attrs)
auto pm_def = mappings.lookup_derive_proc_macro_def (
definition->get_node_id ());
- rust_assert (pm_def.has_value ());
-
- mappings.insert_derive_proc_macro_invocation (trait,
- pm_def.value ());
+ if (pm_def.has_value ())
+ mappings.insert_derive_proc_macro_invocation (trait,
+ pm_def.value ());
}
}
else if (Analysis::BuiltinAttributeMappings::get ()
@@ -417,10 +419,19 @@ Early::finalize_rebind_import (const Early::ImportPair &mapping)
declared_name = rebind.get_identifier ().as_string ();
locus = rebind.get_identifier ().get_locus ();
break;
- case AST::UseTreeRebind::NewBindType::NONE:
- declared_name = path.get_final_segment ().as_string ();
- locus = path.get_final_segment ().get_locus ();
- break;
+ case AST::UseTreeRebind::NewBindType::NONE: {
+ const auto &segments = path.get_segments ();
+ // We don't want to insert `self` with `use module::self`
+ if (path.get_final_segment ().is_lower_self_seg ())
+ {
+ rust_assert (segments.size () > 1);
+ declared_name = segments[segments.size () - 2].as_string ();
+ }
+ else
+ declared_name = path.get_final_segment ().as_string ();
+ locus = path.get_final_segment ().get_locus ();
+ break;
+ }
case AST::UseTreeRebind::NewBindType::WILDCARD:
rust_unreachable ();
break;
diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.h b/gcc/rust/resolve/rust-early-name-resolver-2.0.h
index c4226fe..e78bec0 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.h
@@ -218,7 +218,6 @@ private:
std::vector<std::pair<Rib::Definition, Namespace>>
resolve_path_in_all_ns (const P &path)
{
- const auto &segments = path.get_segments ();
std::vector<std::pair<Rib::Definition, Namespace>> resolved;
// Pair a definition with the namespace it was found in
@@ -229,13 +228,22 @@ private:
};
};
- ctx.resolve_path (segments, Namespace::Values)
+ std::vector<Error> value_errors;
+ std::vector<Error> type_errors;
+ std::vector<Error> macro_errors;
+
+ ctx.resolve_path (path, value_errors, Namespace::Values)
.map (pair_with_ns (Namespace::Values));
- ctx.resolve_path (segments, Namespace::Types)
+ ctx.resolve_path (path, type_errors, Namespace::Types)
.map (pair_with_ns (Namespace::Types));
- ctx.resolve_path (segments, Namespace::Macros)
+ ctx.resolve_path (path, macro_errors, Namespace::Macros)
.map (pair_with_ns (Namespace::Macros));
+ if (!value_errors.empty () && !type_errors.empty ()
+ && !macro_errors.empty ())
+ for (auto &ent : value_errors)
+ collect_error (std::move (ent));
+
return resolved;
}
diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h
index 2a4c734..81468e5 100644
--- a/gcc/rust/resolve/rust-forever-stack.h
+++ b/gcc/rust/resolve/rust-forever-stack.h
@@ -548,7 +548,8 @@ template <Namespace N> class ForeverStack
public:
ForeverStack ()
: root (Node (Rib (Rib::Kind::Normal), UNKNOWN_NODEID)),
- prelude (Node (Rib (Rib::Kind::Prelude), UNKNOWN_NODEID, root)),
+ lang_prelude (Node (Rib (Rib::Kind::Prelude), UNKNOWN_NODEID, root)),
+ extern_prelude (Node (Rib (Rib::Kind::Prelude), UNKNOWN_NODEID)),
cursor_reference (root)
{
rust_assert (root.is_root ());
@@ -658,8 +659,8 @@ public:
* the current map, an empty one otherwise.
*/
tl::optional<Rib::Definition> get (const Identifier &name);
- tl::optional<Rib::Definition> get_prelude (const Identifier &name);
- tl::optional<Rib::Definition> get_prelude (const std::string &name);
+ tl::optional<Rib::Definition> get_lang_prelude (const Identifier &name);
+ tl::optional<Rib::Definition> get_lang_prelude (const std::string &name);
/**
* Resolve a path to its definition in the current `ForeverStack`
@@ -671,8 +672,9 @@ public:
*/
template <typename S>
tl::optional<Rib::Definition> resolve_path (
- const std::vector<S> &segments,
- std::function<void (const S &, NodeId)> insert_segment_resolution);
+ const std::vector<S> &segments, bool has_opening_scope_resolution,
+ std::function<void (const S &, NodeId)> insert_segment_resolution,
+ std::vector<Error> &collect_errors);
// FIXME: Documentation
tl::optional<Resolver::CanonicalPath> to_canonical_path (NodeId id) const;
@@ -767,7 +769,11 @@ private:
* It has the root node as a parent, and acts as a "special case" for name
* resolution
*/
- Node prelude;
+ Node lang_prelude;
+ /*
+ * The extern prelude, used for resolving external crates
+ */
+ Node extern_prelude;
std::reference_wrapper<Node> cursor_reference;
@@ -787,13 +793,19 @@ private:
tl::optional<SegIterator<S>> find_starting_point (
const std::vector<S> &segments,
std::reference_wrapper<Node> &starting_point,
- std::function<void (const S &, NodeId)> insert_segment_resolution);
+ std::function<void (const S &, NodeId)> insert_segment_resolution,
+ std::vector<Error> &collect_errors);
template <typename S>
tl::optional<Node &> resolve_segments (
Node &starting_point, const std::vector<S> &segments,
SegIterator<S> iterator,
- std::function<void (const S &, NodeId)> insert_segment_resolution);
+ std::function<void (const S &, NodeId)> insert_segment_resolution,
+ std::vector<Error> &collect_errors);
+
+ tl::optional<Rib::Definition> resolve_final_segment (Node &final_node,
+ std::string &seg_name,
+ bool is_lower_self);
/* Helper functions for forward resolution (to_canonical_path, to_rib...) */
struct DfsResult
@@ -819,6 +831,21 @@ private:
tl::optional<Node &> dfs_node (Node &starting_point, NodeId to_find);
tl::optional<const Node &> dfs_node (const Node &starting_point,
NodeId to_find) const;
+
+public:
+ bool forward_declared (NodeId definition, NodeId usage)
+ {
+ if (peek ().kind != Rib::Kind::ForwardTypeParamBan)
+ return false;
+
+ const auto &definition_rib = dfs_rib (cursor (), definition);
+
+ if (!definition_rib)
+ return false;
+
+ return (definition_rib
+ && definition_rib.value ().kind == Rib::Kind::ForwardTypeParamBan);
+ }
};
} // namespace Resolver2_0
diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx
index a6e0b30..069111e 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -20,6 +20,7 @@
#include "rust-ast.h"
#include "rust-diagnostics.h"
#include "rust-forever-stack.h"
+#include "rust-edition.h"
#include "rust-rib.h"
#include "rust-unwrap-segment.h"
#include "optional.h"
@@ -77,7 +78,7 @@ ForeverStack<N>::push_inner (Rib rib, Link link)
rust_assert (&cursor_reference.get () == &root);
// Prelude doesn't have an access path
rust_assert (!link.path);
- update_cursor (this->prelude);
+ update_cursor (this->lang_prelude);
return;
}
// If the link does not exist, we create it and emplace a new `Node` with the
@@ -319,16 +320,16 @@ ForeverStack<N>::get (const Identifier &name)
template <Namespace N>
tl::optional<Rib::Definition>
-ForeverStack<N>::get_prelude (const Identifier &name)
+ForeverStack<N>::get_lang_prelude (const Identifier &name)
{
- return prelude.rib.get (name.as_string ());
+ return lang_prelude.rib.get (name.as_string ());
}
template <Namespace N>
tl::optional<Rib::Definition>
-ForeverStack<N>::get_prelude (const std::string &name)
+ForeverStack<N>::get_lang_prelude (const std::string &name)
{
- return prelude.rib.get (name);
+ return lang_prelude.rib.get (name);
}
template <>
@@ -397,12 +398,13 @@ ForeverStack<N>::find_closest_module (Node &starting_point)
* segments */
template <typename S>
static inline bool
-check_leading_kw_at_start (const S &segment, bool condition)
+check_leading_kw_at_start (std::vector<Error> &collect_errors, const S &segment,
+ bool condition)
{
if (condition)
- rust_error_at (
+ collect_errors.emplace_back (
segment.get_locus (), ErrorCode::E0433,
- "leading path segment %qs can only be used at the beginning of a path",
+ "%qs in paths can only be used in start position",
segment.as_string ().c_str ());
return condition;
@@ -418,7 +420,8 @@ template <typename S>
tl::optional<typename std::vector<S>::const_iterator>
ForeverStack<N>::find_starting_point (
const std::vector<S> &segments, std::reference_wrapper<Node> &starting_point,
- std::function<void (const S &, NodeId)> insert_segment_resolution)
+ std::function<void (const S &, NodeId)> insert_segment_resolution,
+ std::vector<Error> &collect_errors)
{
auto iterator = segments.begin ();
@@ -435,8 +438,9 @@ ForeverStack<N>::find_starting_point (
// if we're after the first path segment and meet `self` or `crate`, it's
// an error - we should only be seeing `super` keywords at this point
- if (check_leading_kw_at_start (seg, !is_start (iterator, segments)
- && is_self_or_crate))
+ if (check_leading_kw_at_start (collect_errors, seg,
+ !is_start (iterator, segments)
+ && is_self_or_crate))
return tl::nullopt;
if (seg.is_crate_path_seg ())
@@ -459,8 +463,9 @@ ForeverStack<N>::find_starting_point (
starting_point = find_closest_module (starting_point);
if (starting_point.get ().is_root ())
{
- rust_error_at (seg.get_locus (), ErrorCode::E0433,
- "too many leading %<super%> keywords");
+ collect_errors.emplace_back (
+ seg.get_locus (), ErrorCode::E0433,
+ "too many leading %<super%> keywords");
return tl::nullopt;
}
@@ -486,7 +491,8 @@ tl::optional<typename ForeverStack<N>::Node &>
ForeverStack<N>::resolve_segments (
Node &starting_point, const std::vector<S> &segments,
typename std::vector<S>::const_iterator iterator,
- std::function<void (const S &, NodeId)> insert_segment_resolution)
+ std::function<void (const S &, NodeId)> insert_segment_resolution,
+ std::vector<Error> &collect_errors)
{
Node *current_node = &starting_point;
for (; !is_last (iterator, segments); iterator++)
@@ -508,9 +514,10 @@ ForeverStack<N>::resolve_segments (
rust_debug ("[ARTHUR]: resolving segment part: %s", str.c_str ());
// check that we don't encounter *any* leading keywords afterwards
- if (check_leading_kw_at_start (seg, seg.is_crate_path_seg ()
- || seg.is_super_path_seg ()
- || seg.is_lower_self_seg ()))
+ if (check_leading_kw_at_start (collect_errors, seg,
+ seg.is_crate_path_seg ()
+ || seg.is_super_path_seg ()
+ || seg.is_lower_self_seg ()))
return tl::nullopt;
tl::optional<typename ForeverStack<N>::Node &> child = tl::nullopt;
@@ -571,7 +578,7 @@ ForeverStack<N>::resolve_segments (
if (current_node->is_root () && !searched_prelude)
{
searched_prelude = true;
- current_node = &prelude;
+ current_node = &lang_prelude;
continue;
}
@@ -594,15 +601,49 @@ ForeverStack<N>::resolve_segments (
return *current_node;
}
+template <>
+inline tl::optional<Rib::Definition>
+ForeverStack<Namespace::Types>::resolve_final_segment (Node &final_node,
+ std::string &seg_name,
+ bool is_lower_self)
+{
+ if (is_lower_self)
+ return Rib::Definition::NonShadowable (final_node.id);
+ else
+ return final_node.rib.get (seg_name);
+}
+
+template <Namespace N>
+tl::optional<Rib::Definition>
+ForeverStack<N>::resolve_final_segment (Node &final_node, std::string &seg_name,
+ bool is_lower_self)
+{
+ return final_node.rib.get (seg_name);
+}
+
template <Namespace N>
template <typename S>
tl::optional<Rib::Definition>
ForeverStack<N>::resolve_path (
- const std::vector<S> &segments,
- std::function<void (const S &, NodeId)> insert_segment_resolution)
+ const std::vector<S> &segments, bool has_opening_scope_resolution,
+ std::function<void (const S &, NodeId)> insert_segment_resolution,
+ std::vector<Error> &collect_errors)
{
// TODO: What to do if segments.empty() ?
+ // handle paths with opening scopes
+ std::function<void (void)> cleanup_current = [] () {};
+ if (has_opening_scope_resolution)
+ {
+ Node *last_current = &cursor_reference.get ();
+ if (get_rust_edition () == Edition::E2015)
+ cursor_reference = root;
+ else
+ cursor_reference = extern_prelude;
+ cleanup_current
+ = [this, last_current] () { cursor_reference = *last_current; };
+ }
+
// if there's only one segment, we just use `get`
if (segments.size () == 1)
{
@@ -613,6 +654,7 @@ ForeverStack<N>::resolve_path (
lang_item.value ());
insert_segment_resolution (seg, seg_id);
+ cleanup_current ();
// TODO: does NonShadowable matter?
return Rib::Definition::NonShadowable (seg_id);
}
@@ -621,43 +663,50 @@ ForeverStack<N>::resolve_path (
= get (unwrap_type_segment (segments.back ()).as_string ());
if (!res)
- res = get_prelude (unwrap_type_segment (segments.back ()).as_string ());
+ res = get_lang_prelude (
+ unwrap_type_segment (segments.back ()).as_string ());
if (res && !res->is_ambiguous ())
insert_segment_resolution (segments.back (), res->get_node_id ());
+ cleanup_current ();
return res;
}
std::reference_wrapper<Node> starting_point = cursor ();
- return find_starting_point (segments, starting_point,
- insert_segment_resolution)
- .and_then ([this, &segments, &starting_point, &insert_segment_resolution] (
- typename std::vector<S>::const_iterator iterator) {
- return resolve_segments (starting_point.get (), segments, iterator,
- insert_segment_resolution);
- })
- .and_then ([this, &segments, &insert_segment_resolution] (
- Node final_node) -> tl::optional<Rib::Definition> {
- // leave resolution within impl blocks to type checker
- if (final_node.rib.kind == Rib::Kind::TraitOrImpl)
- return tl::nullopt;
-
- std::string seg_name
- = unwrap_type_segment (segments.back ()).as_string ();
-
- // assuming this can't be a lang item segment
- tl::optional<Rib::Definition> res = final_node.rib.get (seg_name);
-
- // Ok we didn't find it in the rib, Lets try the prelude...
- if (!res)
- res = get_prelude (seg_name);
-
- if (res && !res->is_ambiguous ())
- insert_segment_resolution (segments.back (), res->get_node_id ());
-
- return res;
- });
+ auto res
+ = find_starting_point (segments, starting_point, insert_segment_resolution,
+ collect_errors)
+ .and_then (
+ [this, &segments, &starting_point, &insert_segment_resolution,
+ &collect_errors] (typename std::vector<S>::const_iterator iterator) {
+ return resolve_segments (starting_point.get (), segments, iterator,
+ insert_segment_resolution, collect_errors);
+ })
+ .and_then ([this, &segments, &insert_segment_resolution] (
+ Node &final_node) -> tl::optional<Rib::Definition> {
+ // leave resolution within impl blocks to type checker
+ if (final_node.rib.kind == Rib::Kind::TraitOrImpl)
+ return tl::nullopt;
+
+ auto &seg = unwrap_type_segment (segments.back ());
+ std::string seg_name = seg.as_string ();
+
+ // assuming this can't be a lang item segment
+ tl::optional<Rib::Definition> res
+ = resolve_final_segment (final_node, seg_name,
+ seg.is_lower_self_seg ());
+ // Ok we didn't find it in the rib, Lets try the prelude...
+ if (!res)
+ res = get_lang_prelude (seg_name);
+
+ if (res && !res->is_ambiguous ())
+ insert_segment_resolution (segments.back (), res->get_node_id ());
+
+ return res;
+ });
+ cleanup_current ();
+ return res;
}
template <Namespace N>
diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
index cf7b7dc..6ec0422 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
@@ -129,6 +129,54 @@ Late::new_label (Identifier name, NodeId id)
}
void
+Late::visit (AST::ForLoopExpr &expr)
+{
+ visit_outer_attrs (expr);
+
+ ctx.bindings.enter (BindingSource::For);
+
+ visit (expr.get_pattern ());
+
+ ctx.bindings.exit ();
+
+ visit (expr.get_iterator_expr ());
+ visit (expr.get_loop_label ());
+ visit (expr.get_loop_block ());
+}
+
+void
+Late::visit (AST::IfLetExpr &expr)
+{
+ visit_outer_attrs (expr);
+
+ ctx.bindings.enter (BindingSource::Let);
+
+ for (auto &pattern : expr.get_patterns ())
+ visit (pattern);
+
+ ctx.bindings.exit ();
+
+ visit (expr.get_value_expr ());
+ visit (expr.get_if_block ());
+}
+
+void
+Late::visit (AST::MatchArm &arm)
+{
+ visit_outer_attrs (arm);
+
+ ctx.bindings.enter (BindingSource::Match);
+
+ for (auto &pattern : arm.get_patterns ())
+ visit (pattern);
+
+ ctx.bindings.exit ();
+
+ if (arm.has_match_arm_guard ())
+ visit (arm.get_guard_expr ());
+}
+
+void
Late::visit (AST::LetStmt &let)
{
DefaultASTVisitor::visit_outer_attrs (let);
@@ -138,8 +186,16 @@ Late::visit (AST::LetStmt &let)
// this makes variable shadowing work properly
if (let.has_init_expr ())
visit (let.get_init_expr ());
+
+ ctx.bindings.enter (BindingSource::Let);
+
visit (let.get_pattern ());
+ ctx.bindings.exit ();
+
+ if (let.has_else_expr ())
+ visit (let.get_init_expr ());
+
// how do we deal with the fact that `let a = blipbloup` should look for a
// label and cannot go through function ribs, but `let a = blipbloup()` can?
@@ -164,9 +220,68 @@ Late::visit (AST::IdentifierPattern &identifier)
// but values does not allow shadowing... since functions cannot shadow
// do we insert functions in labels as well?
+ if (ctx.bindings.peek ().is_and_bound (identifier.get_ident ()))
+ {
+ if (ctx.bindings.peek ().get_source () == BindingSource::Param)
+ rust_error_at (
+ identifier.get_locus (), ErrorCode::E0415,
+ "identifier %qs is bound more than once in the same parameter list",
+ identifier.as_string ().c_str ());
+ else
+ rust_error_at (
+ identifier.get_locus (), ErrorCode::E0416,
+ "identifier %qs is bound more than once in the same pattern",
+ identifier.as_string ().c_str ());
+ return;
+ }
+
+ ctx.bindings.peek ().insert_ident (identifier.get_ident ());
+
+ if (ctx.bindings.peek ().is_or_bound (identifier.get_ident ()))
+ {
+ // FIXME: map usage instead
+ std::ignore = ctx.values.insert_shadowable (identifier.get_ident (),
+ identifier.get_node_id ());
+ }
+ else
+ {
+ // We do want to ignore duplicated data because some situations rely on
+ // it.
+ std::ignore = ctx.values.insert_shadowable (identifier.get_ident (),
+ identifier.get_node_id ());
+ }
+}
+
+void
+Late::visit (AST::AltPattern &pattern)
+{
+ ctx.bindings.peek ().push (Binding::Kind::Or);
+ for (auto &alt : pattern.get_alts ())
+ {
+ ctx.bindings.peek ().push (Binding::Kind::Product);
+ visit (alt);
+ ctx.bindings.peek ().merge ();
+ }
+ ctx.bindings.peek ().merge ();
+}
+
+void
+Late::visit_function_params (AST::Function &function)
+{
+ ctx.bindings.enter (BindingSource::Param);
+
+ for (auto &param : function.get_function_params ())
+ visit (param);
+
+ ctx.bindings.exit ();
+}
+
+void
+Late::visit (AST::StructPatternFieldIdent &field)
+{
// We do want to ignore duplicated data because some situations rely on it.
- std::ignore = ctx.values.insert_shadowable (identifier.get_ident (),
- identifier.get_node_id ());
+ std::ignore = ctx.values.insert_shadowable (field.get_identifier (),
+ field.get_node_id ());
}
void
@@ -184,6 +299,9 @@ Late::visit (AST::SelfParam &param)
void
Late::visit (AST::BreakExpr &expr)
{
+ if (expr.has_label ())
+ resolve_label (expr.get_label_unchecked ().get_lifetime ());
+
if (expr.has_break_expr ())
{
auto &break_expr = expr.get_break_expr ();
@@ -210,6 +328,38 @@ Late::visit (AST::BreakExpr &expr)
}
void
+Late::visit (AST::LoopLabel &label)
+{
+ auto &lifetime = label.get_lifetime ();
+ ctx.labels.insert (Identifier (lifetime.as_string (), lifetime.get_locus ()),
+ lifetime.get_node_id ());
+}
+
+void
+Late::resolve_label (AST::Lifetime &lifetime)
+{
+ if (auto resolved = ctx.labels.get (lifetime.as_string ()))
+ {
+ if (resolved->get_node_id () != lifetime.get_node_id ())
+ ctx.map_usage (Usage (lifetime.get_node_id ()),
+ Definition (resolved->get_node_id ()));
+ }
+ else
+ rust_error_at (lifetime.get_locus (), ErrorCode::E0426,
+ "use of undeclared label %qs",
+ lifetime.as_string ().c_str ());
+}
+
+void
+Late::visit (AST::ContinueExpr &expr)
+{
+ if (expr.has_label ())
+ resolve_label (expr.get_label_unchecked ());
+
+ DefaultResolver::visit (expr);
+}
+
+void
Late::visit (AST::IdentifierExpr &expr)
{
// TODO: same thing as visit(PathInExpression) here?
@@ -232,7 +382,7 @@ Late::visit (AST::IdentifierExpr &expr)
}
else
{
- if (auto type = ctx.types.get_prelude (expr.get_ident ()))
+ if (auto type = ctx.types.get_lang_prelude (expr.get_ident ()))
{
resolved = type;
}
@@ -304,14 +454,13 @@ Late::visit (AST::PathInExpression &expr)
return;
}
- auto resolved = ctx.resolve_path (expr.get_segments (), Namespace::Values,
- Namespace::Types);
+ auto resolved = ctx.resolve_path (expr, Namespace::Values, Namespace::Types);
if (!resolved)
{
if (!ctx.lookup (expr.get_segments ().front ().get_node_id ()))
- rust_error_at (expr.get_locus (),
- "could not resolve path expression: %qs",
+ rust_error_at (expr.get_locus (), ErrorCode::E0433,
+ "Cannot find path %qs in this scope",
expr.as_simple_path ().as_string ().c_str ());
return;
}
@@ -337,13 +486,9 @@ Late::visit (AST::TypePath &type)
DefaultResolver::visit (type);
- // take care of only simple cases
- // TODO: remove this?
- rust_assert (!type.has_opening_scope_resolution_op ());
-
// this *should* mostly work
// TODO: make sure typepath-like path resolution (?) is working
- auto resolved = ctx.resolve_path (type.get_segments (), Namespace::Types);
+ auto resolved = ctx.resolve_path (type, Namespace::Types);
if (!resolved.has_value ())
{
@@ -360,6 +505,14 @@ Late::visit (AST::TypePath &type)
return;
}
+ if (ctx.types.forward_declared (resolved->get_node_id (),
+ type.get_node_id ()))
+ {
+ rust_error_at (type.get_locus (), ErrorCode::E0128,
+ "type parameters with a default cannot use forward "
+ "declared identifiers");
+ }
+
ctx.map_usage (Usage (type.get_node_id ()),
Definition (resolved->get_node_id ()));
}
@@ -391,8 +544,7 @@ Late::visit (AST::StructExprStruct &s)
visit_inner_attrs (s);
DefaultResolver::visit (s.get_struct_name ());
- auto resolved
- = ctx.resolve_path (s.get_struct_name ().get_segments (), Namespace::Types);
+ auto resolved = ctx.resolve_path (s.get_struct_name (), Namespace::Types);
ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()),
Definition (resolved->get_node_id ()));
@@ -406,8 +558,7 @@ Late::visit (AST::StructExprStructBase &s)
DefaultResolver::visit (s.get_struct_name ());
visit (s.get_struct_base ());
- auto resolved
- = ctx.resolve_path (s.get_struct_name ().get_segments (), Namespace::Types);
+ auto resolved = ctx.resolve_path (s.get_struct_name (), Namespace::Types);
ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()),
Definition (resolved->get_node_id ()));
@@ -424,8 +575,7 @@ Late::visit (AST::StructExprStructFields &s)
for (auto &field : s.get_fields ())
visit (field);
- auto resolved
- = ctx.resolve_path (s.get_struct_name ().get_segments (), Namespace::Types);
+ auto resolved = ctx.resolve_path (s.get_struct_name (), Namespace::Types);
ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()),
Definition (resolved->get_node_id ()));
@@ -479,14 +629,35 @@ void
Late::visit (AST::ClosureExprInner &closure)
{
add_captures (closure, ctx);
- DefaultResolver::visit (closure);
+
+ visit_outer_attrs (closure);
+
+ ctx.bindings.enter (BindingSource::Param);
+
+ for (auto &param : closure.get_params ())
+ visit (param);
+
+ ctx.bindings.exit ();
+
+ visit (closure.get_definition_expr ());
}
void
Late::visit (AST::ClosureExprInnerTyped &closure)
{
add_captures (closure, ctx);
- DefaultResolver::visit (closure);
+
+ visit_outer_attrs (closure);
+
+ ctx.bindings.enter (BindingSource::Param);
+
+ for (auto &param : closure.get_params ())
+ visit (param);
+
+ ctx.bindings.exit ();
+
+ visit (closure.get_return_type ());
+ visit (closure.get_definition_block ());
}
} // namespace Resolver2_0
diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h b/gcc/rust/resolve/rust-late-name-resolver-2.0.h
index ac376b5..171d9bf 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h
@@ -37,17 +37,27 @@ public:
void new_label (Identifier name, NodeId id);
+ // Specialized visit bits
+ void visit_function_params (AST::Function &function) override;
+
// some more label declarations
void visit (AST::LetStmt &) override;
// TODO: Do we need this?
// void visit (AST::Method &) override;
void visit (AST::IdentifierPattern &) override;
+ void visit (AST::StructPatternFieldIdent &) override;
+ void visit (AST::AltPattern &) override;
void visit (AST::SelfParam &) override;
+ void visit (AST::MatchArm &) override;
+ void visit (AST::ForLoopExpr &) override;
+ void visit (AST::IfLetExpr &) override;
// resolutions
void visit (AST::IdentifierExpr &) override;
void visit (AST::StructExprFieldIdentifier &) override;
void visit (AST::BreakExpr &) override;
+ void visit (AST::ContinueExpr &) override;
+ void visit (AST::LoopLabel &) override;
void visit (AST::PathInExpression &) override;
void visit (AST::TypePath &) override;
void visit (AST::Trait &) override;
@@ -61,6 +71,8 @@ public:
void visit (AST::ClosureExprInnerTyped &) override;
private:
+ void resolve_label (AST::Lifetime &lifetime);
+
/* Setup Rust's builtin types (u8, i32, !...) in the resolver */
void setup_builtin_types ();
diff --git a/gcc/rust/resolve/rust-name-resolution-context.cc b/gcc/rust/resolve/rust-name-resolution-context.cc
index 92c4863..f098e48 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.cc
+++ b/gcc/rust/resolve/rust-name-resolution-context.cc
@@ -23,6 +23,65 @@
namespace Rust {
namespace Resolver2_0 {
+BindingLayer::BindingLayer (BindingSource source) : source (source)
+{
+ push (Binding::Kind::Product);
+}
+
+bool
+BindingLayer::bind_test (Identifier ident, Binding::Kind kind)
+{
+ for (auto &bind : bindings)
+ {
+ if (bind.set.find (ident) != bind.set.cend () && bind.kind == kind)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void
+BindingLayer::push (Binding::Kind kind)
+{
+ bindings.push_back (Binding (kind));
+}
+
+bool
+BindingLayer::is_and_bound (Identifier ident)
+{
+ return bind_test (ident, Binding::Kind::Product);
+}
+
+bool
+BindingLayer::is_or_bound (Identifier ident)
+{
+ return bind_test (ident, Binding::Kind::Or);
+}
+
+void
+BindingLayer::insert_ident (Identifier ident)
+{
+ bindings.back ().set.insert (ident);
+}
+
+void
+BindingLayer::merge ()
+{
+ auto last_binding = bindings.back ();
+ bindings.pop_back ();
+ for (auto &value : last_binding.set)
+ {
+ bindings.back ().set.insert (value);
+ }
+}
+
+BindingSource
+BindingLayer::get_source () const
+{
+ return source;
+}
+
NameResolutionContext::NameResolutionContext ()
: mappings (Analysis::Mappings::get ())
{}
diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h
index ea81bde..19ba750 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.h
+++ b/gcc/rust/resolve/rust-name-resolution-context.h
@@ -23,6 +23,7 @@
#include "rust-forever-stack.h"
#include "rust-hir-map.h"
#include "rust-rib.h"
+#include "rust-stacked-contexts.h"
namespace Rust {
namespace Resolver2_0 {
@@ -156,6 +157,62 @@ public:
NodeId id;
};
+struct Binding
+{
+ enum class Kind
+ {
+ Product,
+ Or,
+ } kind;
+
+ std::unordered_set<Identifier> set;
+
+ Binding (Binding::Kind kind) : kind (kind) {}
+};
+
+/**
+ * Used to identify the source of a binding, and emit the correct error message.
+ */
+enum class BindingSource
+{
+ Match,
+ Let,
+ For,
+ /* Closure param or function param */
+ Param
+};
+
+class BindingLayer
+{
+ BindingSource source;
+ std::vector<Binding> bindings;
+
+ bool bind_test (Identifier ident, Binding::Kind kind);
+
+public:
+ void push (Binding::Kind kind);
+
+ BindingLayer (BindingSource source);
+
+ /**
+ * Identifies if the identifier has been used in a product binding context.
+ * eg. `let (a, a) = test();`
+ */
+ bool is_and_bound (Identifier ident);
+
+ /**
+ * Identifies if the identifier has been used in a or context.
+ * eg. `let (a, 1) | (a, 2) = test()`
+ */
+ bool is_or_bound (Identifier ident);
+
+ void insert_ident (Identifier ident);
+
+ void merge ();
+
+ BindingSource get_source () const;
+};
+
// Now our resolver, which keeps track of all the `ForeverStack`s we could want
class NameResolutionContext
{
@@ -212,6 +269,7 @@ public:
ForeverStack<Namespace::Labels> labels;
Analysis::Mappings &mappings;
+ StackedContexts<BindingLayer> bindings;
// TODO: Rename
// TODO: Use newtype pattern for Usage and Definition
@@ -220,8 +278,10 @@ public:
tl::optional<NodeId> lookup (NodeId usage) const;
template <typename S>
- tl::optional<Rib::Definition> resolve_path (const std::vector<S> &segments,
- Namespace ns)
+ tl::optional<Rib::Definition>
+ resolve_path (const std::vector<S> &segments,
+ bool has_opening_scope_resolution,
+ std::vector<Error> &collect_errors, Namespace ns)
{
std::function<void (const S &, NodeId)> insert_segment_resolution
= [this] (const S &seg, NodeId id) {
@@ -232,33 +292,105 @@ public:
switch (ns)
{
case Namespace::Values:
- return values.resolve_path (segments, insert_segment_resolution);
+ return values.resolve_path (segments, has_opening_scope_resolution,
+ insert_segment_resolution, collect_errors);
case Namespace::Types:
- return types.resolve_path (segments, insert_segment_resolution);
+ return types.resolve_path (segments, has_opening_scope_resolution,
+ insert_segment_resolution, collect_errors);
case Namespace::Macros:
- return macros.resolve_path (segments, insert_segment_resolution);
+ return macros.resolve_path (segments, has_opening_scope_resolution,
+ insert_segment_resolution, collect_errors);
case Namespace::Labels:
- return labels.resolve_path (segments, insert_segment_resolution);
+ return labels.resolve_path (segments, has_opening_scope_resolution,
+ insert_segment_resolution, collect_errors);
default:
rust_unreachable ();
}
}
template <typename S, typename... Args>
- tl::optional<Rib::Definition> resolve_path (const std::vector<S> &segments,
- Args... ns_args)
+ tl::optional<Rib::Definition>
+ resolve_path (const std::vector<S> &segments,
+ bool has_opening_scope_resolution,
+ tl::optional<std::vector<Error> &> collect_errors,
+ Namespace ns_first, Args... ns_args)
{
- std::initializer_list<Namespace> namespaces = {ns_args...};
+ std::initializer_list<Namespace> namespaces = {ns_first, ns_args...};
for (auto ns : namespaces)
{
- if (auto ret = resolve_path (segments, ns))
+ std::vector<Error> collect_errors_inner;
+ if (auto ret = resolve_path (segments, has_opening_scope_resolution,
+ collect_errors_inner, ns))
return ret;
+ if (!collect_errors_inner.empty ())
+ {
+ if (collect_errors.has_value ())
+ {
+ std::move (collect_errors_inner.begin (),
+ collect_errors_inner.end (),
+ std::back_inserter (collect_errors.value ()));
+ }
+ else
+ {
+ for (auto &e : collect_errors_inner)
+ e.emit ();
+ }
+ return tl::nullopt;
+ }
}
return tl::nullopt;
}
+ template <typename... Args>
+ tl::optional<Rib::Definition>
+ resolve_path (const AST::SimplePath &path,
+ tl::optional<std::vector<Error> &> collect_errors,
+ Namespace ns_first, Args... ns_args)
+ {
+ return resolve_path (path.get_segments (),
+ path.has_opening_scope_resolution (), collect_errors,
+ ns_first, ns_args...);
+ }
+
+ template <typename... Args>
+ tl::optional<Rib::Definition>
+ resolve_path (const AST::PathInExpression &path,
+ tl::optional<std::vector<Error> &> collect_errors,
+ Namespace ns_first, Args... ns_args)
+ {
+ return resolve_path (path.get_segments (), path.opening_scope_resolution (),
+ collect_errors, ns_first, ns_args...);
+ }
+
+ template <typename... Args>
+ tl::optional<Rib::Definition>
+ resolve_path (const AST::TypePath &path,
+ tl::optional<std::vector<Error> &> collect_errors,
+ Namespace ns_first, Args... ns_args)
+ {
+ return resolve_path (path.get_segments (),
+ path.has_opening_scope_resolution_op (),
+ collect_errors, ns_first, ns_args...);
+ }
+
+ template <typename P, typename... Args>
+ tl::optional<Rib::Definition> resolve_path (const P &path, Namespace ns_first,
+ Args... ns_args)
+ {
+ return resolve_path (path, tl::nullopt, ns_first, ns_args...);
+ }
+
+ template <typename P, typename... Args>
+ tl::optional<Rib::Definition>
+ resolve_path (const P &path_segments, bool has_opening_scope_resolution,
+ Namespace ns_first, Args... ns_args)
+ {
+ return resolve_path (path_segments, has_opening_scope_resolution,
+ tl::nullopt, ns_first, ns_args...);
+ }
+
private:
/* Map of "usage" nodes which have been resolved to a "definition" node */
std::map<Usage, Definition> resolved_nodes;
diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
index 8863be7..2f036fe 100644
--- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
@@ -113,7 +113,17 @@ TopLevel::visit (AST::Module &module)
// This was copied from the old early resolver method
// 'accumulate_escaped_macros'
if (module.get_kind () == AST::Module::UNLOADED)
- module.load_items ();
+ {
+ module.load_items ();
+
+ // If the module was previously unloaded, then we don't want to visit it
+ // this time around as the CfgStrip hasn't run on its inner items yet.
+ // Skip it for now, mark the visitor as dirty and try again
+
+ dirty = true;
+
+ return;
+ }
DefaultResolver::visit (module);
@@ -125,8 +135,7 @@ TopLevel::visit (AST::Module &module)
void
TopLevel::visit (AST::Trait &trait)
{
- insert_or_error_out (trait.get_identifier ().as_string (), trait,
- Namespace::Types);
+ insert_or_error_out (trait.get_identifier (), trait, Namespace::Types);
DefaultResolver::visit (trait);
}
@@ -538,6 +547,8 @@ flatten_glob (const AST::UseTreeGlob &glob, std::vector<AST::SimplePath> &paths,
{
if (glob.has_path ())
paths.emplace_back (glob.get_path ());
+ else
+ paths.emplace_back (AST::SimplePath ({}, false, glob.get_locus ()));
}
void
diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc
index a6e8ea9..e5319d3 100644
--- a/gcc/rust/rust-gcc.cc
+++ b/gcc/rust/rust-gcc.cc
@@ -61,7 +61,7 @@
tree
Bvariable::get_tree (location_t location) const
{
- if (this->t_ == error_mark_node)
+ if (error_operand_p (this->t_))
return error_mark_node;
TREE_USED (this->t_) = 1;
@@ -431,7 +431,7 @@ float_type (int bits)
tree
pointer_type (tree to_type)
{
- if (to_type == error_mark_node)
+ if (error_operand_p (to_type))
return error_mark_node;
tree type = build_pointer_type (to_type);
return type;
@@ -442,7 +442,7 @@ pointer_type (tree to_type)
tree
reference_type (tree to_type)
{
- if (to_type == error_mark_node)
+ if (error_operand_p (to_type))
return error_mark_node;
tree type = build_reference_type (to_type);
return type;
@@ -453,7 +453,7 @@ reference_type (tree to_type)
tree
immutable_type (tree base)
{
- if (base == error_mark_node)
+ if (error_operand_p (base))
return error_mark_node;
tree constified = build_qualified_type (base, TYPE_QUAL_CONST);
return constified;
@@ -472,17 +472,16 @@ function_type (const typed_identifier &receiver,
if (receiver.type != NULL_TREE)
{
tree t = receiver.type;
- if (t == error_mark_node)
+ if (error_operand_p (t))
return error_mark_node;
*pp = tree_cons (NULL_TREE, t, NULL_TREE);
pp = &TREE_CHAIN (*pp);
}
- for (std::vector<typed_identifier>::const_iterator p = parameters.begin ();
- p != parameters.end (); ++p)
+ for (const auto &p : parameters)
{
- tree t = p->type;
- if (t == error_mark_node)
+ tree t = p.type;
+ if (error_operand_p (t))
return error_mark_node;
*pp = tree_cons (NULL_TREE, t, NULL_TREE);
pp = &TREE_CHAIN (*pp);
@@ -502,11 +501,11 @@ function_type (const typed_identifier &receiver,
gcc_assert (result_struct != NULL);
result = result_struct;
}
- if (result == error_mark_node)
+ if (error_operand_p (result))
return error_mark_node;
tree fntype = build_function_type (result, args);
- if (fntype == error_mark_node)
+ if (error_operand_p (fntype))
return error_mark_node;
return build_pointer_type (fntype);
@@ -521,21 +520,16 @@ function_type_variadic (const typed_identifier &receiver,
size_t n = parameters.size () + (receiver.type != NULL_TREE ? 1 : 0);
tree *args = XALLOCAVEC (tree, n);
size_t offs = 0;
+ if (error_operand_p (receiver.type))
+ return error_mark_node;
if (receiver.type != NULL_TREE)
- {
- tree t = receiver.type;
- if (t == error_mark_node)
- return error_mark_node;
+ args[offs++] = receiver.type;
- args[offs++] = t;
- }
-
- for (std::vector<typed_identifier>::const_iterator p = parameters.begin ();
- p != parameters.end (); ++p)
+ for (const auto &p : parameters)
{
- tree t = p->type;
- if (t == error_mark_node)
+ tree t = p.type;
+ if (error_operand_p (t))
return error_mark_node;
args[offs++] = t;
}
@@ -550,11 +544,11 @@ function_type_variadic (const typed_identifier &receiver,
gcc_assert (result_struct != NULL_TREE);
result = result_struct;
}
- if (result == error_mark_node)
+ if (error_operand_p (result))
return error_mark_node;
tree fntype = build_varargs_function_type_array (result, n, args);
- if (fntype == error_mark_node)
+ if (error_operand_p (fntype))
return error_mark_node;
return build_pointer_type (fntype);
@@ -569,7 +563,7 @@ function_ptr_type (tree result_type, const std::vector<tree> &parameters,
for (auto &param : parameters)
{
- if (param == error_mark_node)
+ if (error_operand_p (param))
return error_mark_node;
*pp = tree_cons (NULL_TREE, param, NULL_TREE);
@@ -583,7 +577,7 @@ function_ptr_type (tree result_type, const std::vector<tree> &parameters,
result = void_type_node;
tree fntype = build_function_type (result, args);
- if (fntype == error_mark_node)
+ if (error_operand_p (fntype))
return error_mark_node;
return build_pointer_type (fntype);
@@ -613,14 +607,13 @@ fill_in_fields (tree fill, const std::vector<typed_identifier> &fields,
{
tree field_trees = NULL_TREE;
tree *pp = &field_trees;
- for (std::vector<typed_identifier>::const_iterator p = fields.begin ();
- p != fields.end (); ++p)
+ for (const auto &p : fields)
{
- tree name_tree = get_identifier_from_string (p->name);
- tree type_tree = p->type;
- if (type_tree == error_mark_node)
+ tree name_tree = get_identifier_from_string (p.name);
+ tree type_tree = p.type;
+ if (error_operand_p (type_tree))
return error_mark_node;
- tree field = build_decl (p->location, FIELD_DECL, name_tree, type_tree);
+ tree field = build_decl (p.location, FIELD_DECL, name_tree, type_tree);
DECL_CONTEXT (field) = fill;
*pp = field;
pp = &DECL_CHAIN (field);
@@ -652,7 +645,7 @@ array_type (tree element_type, tree length)
tree
fill_in_array (tree fill, tree element_type, tree length_tree)
{
- if (element_type == error_mark_node || length_tree == error_mark_node)
+ if (error_operand_p (element_type) || error_operand_p (length_tree))
return error_mark_node;
gcc_assert (TYPE_SIZE (element_type) != NULL_TREE);
@@ -684,7 +677,7 @@ fill_in_array (tree fill, tree element_type, tree length_tree)
tree
named_type (const std::string &name, tree type, location_t location)
{
- if (type == error_mark_node)
+ if (error_operand_p (type))
return error_mark_node;
// The middle-end expects a basic type to have a name. In Rust every
@@ -714,7 +707,7 @@ named_type (const std::string &name, tree type, location_t location)
int64_t
type_size (tree t)
{
- if (t == error_mark_node)
+ if (error_operand_p (t))
return 1;
if (t == void_type_node)
return 0;
@@ -732,7 +725,7 @@ type_size (tree t)
int64_t
type_alignment (tree t)
{
- if (t == error_mark_node)
+ if (error_operand_p (t))
return 1;
return TYPE_ALIGN_UNIT (t);
}
@@ -742,7 +735,7 @@ type_alignment (tree t)
int64_t
type_field_alignment (tree t)
{
- if (t == error_mark_node)
+ if (error_operand_p (t))
return 1;
return rust_field_alignment (t);
}
@@ -752,7 +745,7 @@ type_field_alignment (tree t)
int64_t
type_field_offset (tree struct_tree, size_t index)
{
- if (struct_tree == error_mark_node)
+ if (error_operand_p (struct_tree))
return 0;
gcc_assert (TREE_CODE (struct_tree) == RECORD_TYPE);
tree field = TYPE_FIELDS (struct_tree);
@@ -773,7 +766,7 @@ tree
zero_expression (tree t)
{
tree ret;
- if (t == error_mark_node)
+ if (error_operand_p (t))
ret = error_mark_node;
else
ret = build_zero_cst (t);
@@ -794,7 +787,7 @@ tree
float_constant_expression (tree t, mpfr_t val)
{
tree ret;
- if (t == error_mark_node)
+ if (error_operand_p (t))
return error_mark_node;
REAL_VALUE_TYPE r1;
@@ -845,8 +838,7 @@ boolean_constant_expression (bool val)
tree
convert_expression (tree type_tree, tree expr_tree, location_t location)
{
- if (type_tree == error_mark_node || expr_tree == error_mark_node
- || TREE_TYPE (expr_tree) == error_mark_node)
+ if (error_operand_p (type_tree) || error_operand_p (expr_tree))
return error_mark_node;
tree ret;
@@ -878,8 +870,7 @@ convert_expression (tree type_tree, tree expr_tree, location_t location)
tree
struct_field_expression (tree struct_tree, size_t index, location_t location)
{
- if (struct_tree == error_mark_node
- || TREE_TYPE (struct_tree) == error_mark_node)
+ if (error_operand_p (struct_tree))
return error_mark_node;
gcc_assert (TREE_CODE (TREE_TYPE (struct_tree)) == RECORD_TYPE
|| TREE_CODE (TREE_TYPE (struct_tree)) == UNION_TYPE);
@@ -895,7 +886,7 @@ struct_field_expression (tree struct_tree, size_t index, location_t location)
field = DECL_CHAIN (field);
gcc_assert (field != NULL_TREE);
}
- if (TREE_TYPE (field) == error_mark_node)
+ if (error_operand_p (TREE_TYPE (field)))
return error_mark_node;
tree ret = fold_build3_loc (location, COMPONENT_REF, TREE_TYPE (field),
struct_tree, field, NULL_TREE);
@@ -909,7 +900,7 @@ struct_field_expression (tree struct_tree, size_t index, location_t location)
tree
compound_expression (tree stat, tree expr, location_t location)
{
- if (stat == error_mark_node || expr == error_mark_node)
+ if (error_operand_p (stat) || error_operand_p (expr))
return error_mark_node;
tree ret
= fold_build2_loc (location, COMPOUND_EXPR, TREE_TYPE (expr), stat, expr);
@@ -923,8 +914,8 @@ tree
conditional_expression (tree, tree type_tree, tree cond_expr, tree then_expr,
tree else_expr, location_t location)
{
- if (type_tree == error_mark_node || cond_expr == error_mark_node
- || then_expr == error_mark_node || else_expr == error_mark_node)
+ if (error_operand_p (type_tree) || error_operand_p (cond_expr)
+ || error_operand_p (then_expr) || error_operand_p (else_expr))
return error_mark_node;
tree ret = build3_loc (location, COND_EXPR, type_tree, cond_expr, then_expr,
else_expr);
@@ -1021,12 +1012,12 @@ operator_to_tree_code (LazyBooleanOperator op)
}
}
-/* Helper function for deciding if a tree is a floating point node. */
+/* Returns true if the type of EXP is a floating point type.
+ False otherwise. */
bool
-is_floating_point (tree t)
+is_floating_point (tree exp)
{
- auto tree_type = TREE_CODE (TREE_TYPE (t));
- return tree_type == REAL_TYPE || tree_type == COMPLEX_TYPE;
+ return FLOAT_TYPE_P (TREE_TYPE (exp));
}
// Return an expression for the negation operation OP EXPR.
@@ -1035,7 +1026,7 @@ negation_expression (NegationOperator op, tree expr_tree, location_t location)
{
/* Check if the expression is an error, in which case we return an error
expression. */
- if (expr_tree == error_mark_node || TREE_TYPE (expr_tree) == error_mark_node)
+ if (error_operand_p (expr_tree))
return error_mark_node;
/* For negation operators, the resulting type should be the same as its
@@ -1071,9 +1062,15 @@ arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op, tree left,
{
/* Check if either expression is an error, in which case we return an error
expression. */
- if (left == error_mark_node || right == error_mark_node)
+ if (error_operand_p (left) || error_operand_p (right))
return error_mark_node;
+ // unwrap the const decls if set
+ if (TREE_CODE (left) == CONST_DECL)
+ left = DECL_INITIAL (left);
+ if (TREE_CODE (right) == CONST_DECL)
+ right = DECL_INITIAL (right);
+
/* We need to determine if we're doing floating point arithmetics of integer
arithmetics. */
bool floating_point = is_floating_point (left);
@@ -1112,6 +1109,7 @@ arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op, tree left,
rust_error_at (location, "division by zero");
}
else if (op == ArithmeticOrLogicalOperator::LEFT_SHIFT
+ && TREE_CODE (right) == INTEGER_CST
&& (compare_tree_int (right, TYPE_PRECISION (TREE_TYPE (ret))) >= 0))
{
rust_error_at (location, "left shift count >= width of type");
@@ -1176,7 +1174,7 @@ arithmetic_or_logical_expression_checked (ArithmeticOrLogicalOperator op,
{
/* Check if either expression is an error, in which case we return an error
expression. */
- if (left == error_mark_node || right == error_mark_node)
+ if (error_operand_p (left) || error_operand_p (right))
return error_mark_node;
// FIXME: Add `if (!debug_mode)`
@@ -1216,7 +1214,7 @@ comparison_expression (ComparisonOperator op, tree left_tree, tree right_tree,
{
/* Check if either expression is an error, in which case we return an error
expression. */
- if (left_tree == error_mark_node || right_tree == error_mark_node)
+ if (error_operand_p (left_tree) || error_operand_p (right_tree))
return error_mark_node;
/* For comparison operators, the resulting type should be boolean. */
@@ -1236,7 +1234,7 @@ lazy_boolean_expression (LazyBooleanOperator op, tree left_tree,
{
/* Check if either expression is an error, in which case we return an error
expression. */
- if (left_tree == error_mark_node || right_tree == error_mark_node)
+ if (error_operand_p (left_tree) || error_operand_p (right_tree))
return error_mark_node;
/* For lazy boolean operators, the resulting type should be the same as the
@@ -1257,7 +1255,7 @@ constructor_expression (tree type_tree, bool is_variant,
const std::vector<tree> &vals, int union_index,
location_t location)
{
- if (type_tree == error_mark_node)
+ if (error_operand_p (type_tree))
return error_mark_node;
vec<constructor_elt, va_gc> *init;
@@ -1299,8 +1297,8 @@ constructor_expression (tree type_tree, bool is_variant,
gcc_assert (field != NULL_TREE);
field = DECL_CHAIN (field);
}
- if (TREE_TYPE (field) == error_mark_node || val == error_mark_node
- || TREE_TYPE (val) == error_mark_node)
+
+ if (TREE_TYPE (field) == error_mark_node || error_operand_p (val))
return error_mark_node;
if (int_size_in_bytes (TREE_TYPE (field)) == 0)
@@ -1330,8 +1328,7 @@ constructor_expression (tree type_tree, bool is_variant,
{
gcc_assert (field != NULL_TREE);
tree val = (*p);
- if (TREE_TYPE (field) == error_mark_node || val == error_mark_node
- || TREE_TYPE (val) == error_mark_node)
+ if (TREE_TYPE (field) == error_mark_node || error_operand_p (val))
return error_mark_node;
if (int_size_in_bytes (TREE_TYPE (field)) == 0)
@@ -1370,7 +1367,7 @@ array_constructor_expression (tree type_tree,
const std::vector<tree> &vals,
location_t location)
{
- if (type_tree == error_mark_node)
+ if (error_operand_p (type_tree))
return error_mark_node;
gcc_assert (indexes.size () == vals.size ());
@@ -1387,7 +1384,7 @@ array_constructor_expression (tree type_tree,
tree index = size_int (indexes[i]);
tree val = vals[i];
- if (index == error_mark_node || val == error_mark_node)
+ if (error_operand_p (index) || error_operand_p (val))
return error_mark_node;
if (element_size == 0)
@@ -1491,8 +1488,7 @@ array_initializer (tree fndecl, tree block, tree array_type, tree length,
tree
array_index_expression (tree array_tree, tree index_tree, location_t location)
{
- if (array_tree == error_mark_node || TREE_TYPE (array_tree) == error_mark_node
- || index_tree == error_mark_node)
+ if (error_operand_p (array_tree) || error_operand_p (index_tree))
return error_mark_node;
// A function call that returns a zero sized object will have been
@@ -1514,7 +1510,7 @@ tree
call_expression (tree fn, const std::vector<tree> &fn_args, tree chain_expr,
location_t location)
{
- if (fn == error_mark_node || TREE_TYPE (fn) == error_mark_node)
+ if (error_operand_p (fn))
return error_mark_node;
gcc_assert (FUNCTION_POINTER_TYPE_P (TREE_TYPE (fn)));
@@ -1594,7 +1590,7 @@ tree
init_statement (tree, Bvariable *var, tree init_tree)
{
tree var_tree = var->get_decl ();
- if (var_tree == error_mark_node || init_tree == error_mark_node)
+ if (error_operand_p (var_tree) || error_operand_p (init_tree))
return error_mark_node;
gcc_assert (TREE_CODE (var_tree) == VAR_DECL);
@@ -1625,7 +1621,7 @@ init_statement (tree, Bvariable *var, tree init_tree)
tree
assignment_statement (tree lhs, tree rhs, location_t location)
{
- if (lhs == error_mark_node || rhs == error_mark_node)
+ if (error_operand_p (lhs) || error_operand_p (rhs))
return error_mark_node;
// To avoid problems with GNU ld, we don't make zero-sized
@@ -1650,14 +1646,14 @@ assignment_statement (tree lhs, tree rhs, location_t location)
tree
return_statement (tree fntree, tree val, location_t location)
{
- if (fntree == error_mark_node)
+ if (error_operand_p (fntree))
return error_mark_node;
tree result = DECL_RESULT (fntree);
- if (result == error_mark_node)
+ if (error_operand_p (result))
return error_mark_node;
- if (val == error_mark_node)
+ if (error_operand_p (val))
return error_mark_node;
tree set
@@ -1675,8 +1671,8 @@ tree
exception_handler_statement (tree try_stmt, tree except_stmt, tree finally_stmt,
location_t location)
{
- if (try_stmt == error_mark_node || except_stmt == error_mark_node
- || finally_stmt == error_mark_node)
+ if (error_operand_p (try_stmt) || error_operand_p (except_stmt)
+ || error_operand_p (finally_stmt))
return error_mark_node;
if (except_stmt != NULL_TREE)
@@ -1695,8 +1691,8 @@ tree
if_statement (tree, tree cond_tree, tree then_tree, tree else_tree,
location_t location)
{
- if (cond_tree == error_mark_node || then_tree == error_mark_node
- || else_tree == error_mark_node)
+ if (error_operand_p (cond_tree) || error_operand_p (then_tree)
+ || error_operand_p (else_tree))
return error_mark_node;
tree ret = build3_loc (location, COND_EXPR, void_type_node, cond_tree,
then_tree, else_tree);
@@ -1722,15 +1718,12 @@ exit_expression (tree cond_tree, location_t locus)
tree
compound_statement (tree s1, tree s2)
{
- tree stmt_list = NULL_TREE;
- tree t = s1;
- if (t == error_mark_node)
- return error_mark_node;
- append_to_statement_list (t, &stmt_list);
- t = s2;
- if (t == error_mark_node)
+ if (error_operand_p (s1) || error_operand_p (s2))
return error_mark_node;
- append_to_statement_list (t, &stmt_list);
+
+ tree stmt_list = NULL_TREE;
+ append_to_statement_list (s1, &stmt_list);
+ append_to_statement_list (s2, &stmt_list);
// If neither statement has any side effects, stmt_list can be NULL
// at this point.
@@ -1746,11 +1739,9 @@ tree
statement_list (const std::vector<tree> &statements)
{
tree stmt_list = NULL_TREE;
- for (std::vector<tree>::const_iterator p = statements.begin ();
- p != statements.end (); ++p)
+ for (tree t : statements)
{
- tree t = (*p);
- if (t == error_mark_node)
+ if (error_operand_p (t))
return error_mark_node;
append_to_statement_list (t, &stmt_list);
}
@@ -1802,12 +1793,13 @@ block (tree fndecl, tree enclosing, const std::vector<Bvariable *> &vars,
*pp = block_tree;
}
+ // Chain the variables of the scope together so they are all connected
+ // to the block.
tree *pp = &BLOCK_VARS (block_tree);
- for (std::vector<Bvariable *>::const_iterator pv = vars.begin ();
- pv != vars.end (); ++pv)
+ for (Bvariable *bv : vars)
{
- *pp = (*pv)->get_decl ();
- if (*pp != error_mark_node)
+ *pp = bv->get_decl ();
+ if (!error_operand_p (*pp))
pp = &DECL_CHAIN (*pp);
}
*pp = NULL_TREE;
@@ -1826,11 +1818,9 @@ void
block_add_statements (tree bind_tree, const std::vector<tree> &statements)
{
tree stmt_list = NULL_TREE;
- for (std::vector<tree>::const_iterator p = statements.begin ();
- p != statements.end (); ++p)
+ for (tree s : statements)
{
- tree s = (*p);
- if (s != error_mark_node)
+ if (!error_operand_p (s))
append_to_statement_list (s, &stmt_list);
}
@@ -1908,8 +1898,7 @@ convert_tree (tree type_tree, tree expr_tree, location_t location)
if (type_tree == TREE_TYPE (expr_tree))
return expr_tree;
- if (type_tree == error_mark_node || expr_tree == error_mark_node
- || TREE_TYPE (expr_tree) == error_mark_node)
+ if (error_operand_p (type_tree) || error_operand_p (expr_tree))
return error_mark_node;
if (POINTER_TYPE_P (type_tree) || INTEGRAL_TYPE_P (type_tree)
@@ -1938,7 +1927,7 @@ global_variable (const std::string &var_name, const std::string &asm_name,
tree type_tree, bool is_external, bool is_hidden,
bool in_unique_section, location_t location)
{
- if (type_tree == error_mark_node)
+ if (error_operand_p (type_tree))
return Bvariable::error_variable ();
// The GNU linker does not like dynamic variables with zero size.
@@ -1977,11 +1966,11 @@ global_variable (const std::string &var_name, const std::string &asm_name,
void
global_variable_set_init (Bvariable *var, tree expr_tree)
{
- if (expr_tree == error_mark_node)
+ if (error_operand_p (expr_tree))
return;
gcc_assert (TREE_CONSTANT (expr_tree));
tree var_decl = var->get_decl ();
- if (var_decl == error_mark_node)
+ if (error_operand_p (var_decl))
return;
DECL_INITIAL (var_decl) = expr_tree;
@@ -2002,7 +1991,7 @@ Bvariable *
local_variable (tree function, const std::string &name, tree type_tree,
Bvariable *decl_var, location_t location)
{
- if (type_tree == error_mark_node)
+ if (error_operand_p (type_tree))
return Bvariable::error_variable ();
tree decl = build_decl (location, VAR_DECL, get_identifier_from_string (name),
type_tree);
@@ -2023,7 +2012,7 @@ Bvariable *
parameter_variable (tree function, const std::string &name, tree type_tree,
location_t location)
{
- if (type_tree == error_mark_node)
+ if (error_operand_p (type_tree))
return Bvariable::error_variable ();
tree decl = build_decl (location, PARM_DECL,
get_identifier_from_string (name), type_tree);
@@ -2040,7 +2029,7 @@ Bvariable *
static_chain_variable (tree fndecl, const std::string &name, tree type_tree,
location_t location)
{
- if (type_tree == error_mark_node)
+ if (error_operand_p (type_tree))
return Bvariable::error_variable ();
tree decl = build_decl (location, PARM_DECL,
get_identifier_from_string (name), type_tree);
@@ -2074,8 +2063,8 @@ temporary_variable (tree fndecl, tree bind_tree, tree type_tree, tree init_tree,
tree *pstatement)
{
gcc_assert (fndecl != NULL_TREE);
- if (type_tree == error_mark_node || init_tree == error_mark_node
- || fndecl == error_mark_node)
+ if (error_operand_p (type_tree) || error_operand_p (init_tree)
+ || error_operand_p (fndecl))
{
*pstatement = error_mark_node;
return Bvariable::error_variable ();
@@ -2192,13 +2181,13 @@ tree
function (tree functype, const std::string &name, const std::string &asm_name,
unsigned int flags, location_t location)
{
- if (functype != error_mark_node)
- {
- gcc_assert (FUNCTION_POINTER_TYPE_P (functype));
- functype = TREE_TYPE (functype);
- }
+ if (error_operand_p (functype))
+ return error_mark_node;
+
+ gcc_assert (FUNCTION_POINTER_TYPE_P (functype));
+ functype = TREE_TYPE (functype);
tree id = get_identifier_from_string (name);
- if (functype == error_mark_node || id == error_mark_node)
+ if (error_operand_p (id))
return error_mark_node;
tree decl = build_decl (location, FUNCTION_DECL, id, functype);
@@ -2236,8 +2225,8 @@ tree
function_defer_statement (tree function, tree undefer_tree, tree defer_tree,
location_t location)
{
- if (undefer_tree == error_mark_node || defer_tree == error_mark_node
- || function == error_mark_node)
+ if (error_operand_p (undefer_tree) || error_operand_p (defer_tree)
+ || error_operand_p (function))
return error_mark_node;
if (DECL_STRUCT_FUNCTION (function) == NULL)
@@ -2269,16 +2258,15 @@ bool
function_set_parameters (tree function,
const std::vector<Bvariable *> &param_vars)
{
- if (function == error_mark_node)
+ if (error_operand_p (function))
return false;
tree params = NULL_TREE;
tree *pp = &params;
- for (std::vector<Bvariable *>::const_iterator pv = param_vars.begin ();
- pv != param_vars.end (); ++pv)
+ for (Bvariable *bv : param_vars)
{
- *pp = (*pv)->get_decl ();
- gcc_assert (*pp != error_mark_node);
+ *pp = bv->get_decl ();
+ gcc_assert (!error_operand_p (*pp));
pp = &DECL_CHAIN (*pp);
}
*pp = NULL_TREE;
@@ -2303,23 +2291,19 @@ write_global_definitions (const std::vector<tree> &type_decls,
// Convert all non-erroneous declarations into Gimple form.
size_t i = 0;
- for (std::vector<Bvariable *>::const_iterator p = variable_decls.begin ();
- p != variable_decls.end (); ++p)
+ for (Bvariable *bv : variable_decls)
{
- tree v = (*p)->get_decl ();
- if (v != error_mark_node)
- {
- defs[i] = v;
- rust_preserve_from_gc (defs[i]);
- ++i;
- }
+ tree v = bv->get_decl ();
+ if (error_operand_p (v))
+ continue;
+ defs[i] = v;
+ rust_preserve_from_gc (defs[i]);
+ ++i;
}
- for (std::vector<tree>::const_iterator p = type_decls.begin ();
- p != type_decls.end (); ++p)
+ for (tree type_tree : type_decls)
{
- tree type_tree = (*p);
- if (type_tree != error_mark_node && IS_TYPE_OR_DECL_P (type_tree))
+ if (!error_operand_p (type_tree) && IS_TYPE_OR_DECL_P (type_tree))
{
defs[i] = TYPE_NAME (type_tree);
gcc_assert (defs[i] != NULL);
@@ -2327,21 +2311,18 @@ write_global_definitions (const std::vector<tree> &type_decls,
++i;
}
}
- for (std::vector<tree>::const_iterator p = constant_decls.begin ();
- p != constant_decls.end (); ++p)
+ for (tree t : constant_decls)
{
- if ((*p) != error_mark_node)
+ if (!error_operand_p (t))
{
- defs[i] = (*p);
+ defs[i] = t;
rust_preserve_from_gc (defs[i]);
++i;
}
}
- for (std::vector<tree>::const_iterator p = function_decls.begin ();
- p != function_decls.end (); ++p)
+ for (tree decl : function_decls)
{
- tree decl = (*p);
- if (decl != error_mark_node)
+ if (!error_operand_p (decl))
{
rust_preserve_from_gc (decl);
if (DECL_STRUCT_FUNCTION (decl) == NULL)
diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc
index 15f21ef..48acbf34 100644
--- a/gcc/rust/rust-session-manager.cc
+++ b/gcc/rust/rust-session-manager.cc
@@ -611,7 +611,6 @@ Session::compile_crate (const char *filename)
return;
AST::CollectLangItems ().go (parsed_crate);
- AST::DesugarQuestionMark ().go (parsed_crate);
auto name_resolution_ctx = Resolver2_0::NameResolutionContext ();
// expansion pipeline stage
@@ -619,6 +618,7 @@ Session::compile_crate (const char *filename)
expansion (parsed_crate, name_resolution_ctx);
AST::DesugarForLoops ().go (parsed_crate);
+ AST::DesugarQuestionMark ().go (parsed_crate);
rust_debug ("\033[0;31mSUCCESSFULLY FINISHED EXPANSION \033[0m");
if (options.dump_option_enabled (CompileOptions::EXPANSION_DUMP))
diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.cc b/gcc/rust/typecheck/rust-hir-dot-operator.cc
index 38bd5b7..c1165e9 100644
--- a/gcc/rust/typecheck/rust-hir-dot-operator.cc
+++ b/gcc/rust/typecheck/rust-hir-dot-operator.cc
@@ -472,8 +472,11 @@ MethodResolver::get_predicate_items (
if (ty->get_kind () == TyTy::TypeKind::FNDEF)
{
TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty);
- predicate_candidate candidate{lookup, fnty};
- predicate_items.push_back (candidate);
+ if (fnty->is_method ())
+ {
+ predicate_candidate candidate{lookup, fnty};
+ predicate_items.push_back (candidate);
+ }
}
}
diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.h b/gcc/rust/typecheck/rust-hir-trait-reference.h
index 6a570ed..8b1ac7d 100644
--- a/gcc/rust/typecheck/rust-hir-trait-reference.h
+++ b/gcc/rust/typecheck/rust-hir-trait-reference.h
@@ -254,10 +254,9 @@ public:
void setup_raw_associated_types ();
- TyTy::BaseType *
- setup_associated_types (const TyTy::BaseType *self,
- const TyTy::TypeBoundPredicate &bound,
- TyTy::SubstitutionArgumentMappings *args = nullptr);
+ TyTy::BaseType *setup_associated_types (
+ const TyTy::BaseType *self, const TyTy::TypeBoundPredicate &bound,
+ TyTy::SubstitutionArgumentMappings *args = nullptr, bool infer = true);
void reset_associated_types ();
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
index c07425d..032bb58 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
@@ -157,7 +157,13 @@ TraitResolver::resolve_path_to_trait (const HIR::TypePath &path,
}
auto resolved_item = mappings.lookup_hir_item (hid.value ());
- rust_assert (resolved_item.has_value ());
+ if (!resolved_item.has_value ())
+ {
+ rust_error_at (path.get_locus (),
+ "Failed to resolve trait by looking up hir node");
+ return false;
+ }
+
if (resolved_item.value ()->get_item_kind () != HIR::Item::ItemKind::Trait)
{
rich_location r (line_table, path.get_locus ());
@@ -228,7 +234,9 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference)
// The one exception is the implicit Self type of a trait
bool apply_sized = !is_self;
auto param_type
- = TypeResolveGenericParam::Resolve (*generic_param, apply_sized);
+ = TypeResolveGenericParam::Resolve (*generic_param, true,
+ apply_sized);
+
context->insert_type (generic_param->get_mappings (), param_type);
substitutions.push_back (
TyTy::SubstitutionParamMapping (typaram, param_type));
@@ -376,7 +384,26 @@ TraitItemReference::resolve_item (HIR::TraitItemType &type)
void
TraitItemReference::resolve_item (HIR::TraitItemConst &constant)
{
- // TODO
+ TyTy::BaseType *ty = nullptr;
+ if (constant.has_type ())
+ ty = TypeCheckType::Resolve (constant.get_type ());
+
+ TyTy::BaseType *expr = nullptr;
+ if (constant.has_expr ())
+ expr = TypeCheckExpr::Resolve (constant.get_expr ());
+
+ bool have_specified_ty = ty != nullptr && !ty->is<TyTy::ErrorType> ();
+ bool have_expr_ty = expr != nullptr && !expr->is<TyTy::ErrorType> ();
+
+ if (have_specified_ty && have_expr_ty)
+ {
+ coercion_site (constant.get_mappings ().get_hirid (),
+ TyTy::TyWithLocation (ty,
+ constant.get_type ().get_locus ()),
+ TyTy::TyWithLocation (expr,
+ constant.get_expr ().get_locus ()),
+ constant.get_locus ());
+ }
}
void
@@ -485,7 +512,7 @@ AssociatedImplTrait::setup_raw_associated_types ()
TyTy::BaseType *
AssociatedImplTrait::setup_associated_types (
const TyTy::BaseType *self, const TyTy::TypeBoundPredicate &bound,
- TyTy::SubstitutionArgumentMappings *args)
+ TyTy::SubstitutionArgumentMappings *args, bool infer)
{
// compute the constrained impl block generic arguments based on self and the
// higher ranked trait bound
@@ -545,7 +572,7 @@ AssociatedImplTrait::setup_associated_types (
std::vector<TyTy::SubstitutionArg> subst_args;
for (auto &p : substitutions)
{
- if (p.needs_substitution ())
+ if (p.needs_substitution () && infer)
{
TyTy::TyVar infer_var = TyTy::TyVar::get_implicit_infer_var (locus);
subst_args.push_back (
@@ -619,7 +646,7 @@ AssociatedImplTrait::setup_associated_types (
= unify_site_and (a->get_ref (), TyTy::TyWithLocation (a),
TyTy::TyWithLocation (b), impl_predicate.get_locus (),
true /*emit-errors*/, true /*commit-if-ok*/,
- false /*infer*/, true /*cleanup-on-fail*/);
+ true /*infer*/, true /*cleanup-on-fail*/);
rust_assert (result->get_kind () != TyTy::TypeKind::ERROR);
}
@@ -632,7 +659,7 @@ AssociatedImplTrait::setup_associated_types (
TyTy::TyWithLocation (impl_self_infer),
impl_predicate.get_locus (),
true /*emit-errors*/, true /*commit-if-ok*/,
- false /*infer*/, true /*cleanup-on-fail*/);
+ true /*infer*/, true /*cleanup-on-fail*/);
rust_assert (result->get_kind () != TyTy::TypeKind::ERROR);
TyTy::BaseType *self_result = result;
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc
index 8f2471d..14b8ab8 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc
@@ -31,6 +31,16 @@ TypeCheckBase::TypeCheckBase ()
context (TypeCheckContext::get ())
{}
+void
+TypeCheckBase::ResolveGenericParams (
+ const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params,
+ std::vector<TyTy::SubstitutionParamMapping> &substitutions, bool is_foreign,
+ ABI abi)
+{
+ TypeCheckBase ctx;
+ ctx.resolve_generic_params (generic_params, substitutions, is_foreign, abi);
+}
+
static void
walk_types_to_constrain (std::set<HirId> &constrained_symbols,
const TyTy::SubstitutionArgumentMappings &constraints)
@@ -298,13 +308,20 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus)
repr.pack = 0;
repr.align = 0;
- // FIXME handle repr types....
+ // Default repr for enums is isize, but we now check for other repr in the
+ // attributes.
bool ok = context->lookup_builtin ("isize", &repr.repr);
rust_assert (ok);
for (const auto &attr : attrs)
{
bool is_repr = attr.get_path ().as_string () == Values::Attributes::REPR;
+ if (is_repr && !attr.has_attr_input ())
+ {
+ rust_error_at (attr.get_locus (), "malformed %qs attribute", "repr");
+ continue;
+ }
+
if (is_repr)
{
const AST::AttrInput &input = attr.get_attr_input ();
@@ -315,21 +332,51 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus)
AST::AttrInputMetaItemContainer *meta_items
= option.parse_to_meta_item ();
- const std::string inline_option
- = meta_items->get_items ().at (0)->as_string ();
+ if (meta_items == nullptr)
+ {
+ rust_error_at (attr.get_locus (), "malformed %qs attribute",
+ "repr");
+ continue;
+ }
+
+ auto &items = meta_items->get_items ();
+ if (items.size () == 0)
+ {
+ // nothing to do with this its empty
+ delete meta_items;
+ continue;
+ }
+
+ const std::string inline_option = items.at (0)->as_string ();
// TODO: it would probably be better to make the MetaItems more aware
// of constructs with nesting like #[repr(packed(2))] rather than
// manually parsing the string "packed(2)" here.
size_t oparen = inline_option.find ('(', 0);
- bool is_pack = false, is_align = false;
+ bool is_pack = false;
+ bool is_align = false;
+ bool is_c = false;
+ bool is_integer = false;
unsigned char value = 1;
if (oparen == std::string::npos)
{
is_pack = inline_option.compare ("packed") == 0;
is_align = inline_option.compare ("align") == 0;
+ is_c = inline_option.compare ("C") == 0;
+ is_integer = (inline_option.compare ("isize") == 0
+ || inline_option.compare ("i8") == 0
+ || inline_option.compare ("i16") == 0
+ || inline_option.compare ("i32") == 0
+ || inline_option.compare ("i64") == 0
+ || inline_option.compare ("i128") == 0
+ || inline_option.compare ("usize") == 0
+ || inline_option.compare ("u8") == 0
+ || inline_option.compare ("u16") == 0
+ || inline_option.compare ("u32") == 0
+ || inline_option.compare ("u64") == 0
+ || inline_option.compare ("u128") == 0);
}
else
@@ -349,9 +396,30 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus)
}
if (is_pack)
- repr.pack = value;
+ {
+ repr.repr_kind = TyTy::ADTType::ReprKind::PACKED;
+ repr.pack = value;
+ }
else if (is_align)
- repr.align = value;
+ {
+ repr.repr_kind = TyTy::ADTType::ReprKind::ALIGN;
+ repr.align = value;
+ }
+ else if (is_c)
+ {
+ repr.repr_kind = TyTy::ADTType::ReprKind::C;
+ }
+ else if (is_integer)
+ {
+ repr.repr_kind = TyTy::ADTType::ReprKind::INT;
+ bool ok = context->lookup_builtin (inline_option, &repr.repr);
+ if (!ok)
+ {
+ rust_error_at (attr.get_locus (), "Invalid repr type");
+ }
+ }
+
+ delete meta_items;
// Multiple repr options must be specified with e.g. #[repr(C,
// packed(2))].
@@ -365,7 +433,8 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus)
void
TypeCheckBase::resolve_generic_params (
const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params,
- std::vector<TyTy::SubstitutionParamMapping> &substitutions)
+ std::vector<TyTy::SubstitutionParamMapping> &substitutions, bool is_foreign,
+ ABI abi)
{
for (auto &generic_param : generic_params)
{
@@ -375,15 +444,18 @@ TypeCheckBase::resolve_generic_params (
auto lifetime_param
= static_cast<HIR::LifetimeParam &> (*generic_param);
auto lifetime = lifetime_param.get_lifetime ();
- rust_assert (lifetime.get_lifetime_type ()
- == AST::Lifetime::LifetimeType::NAMED);
context->get_lifetime_resolver ().insert_mapping (
context->intern_lifetime (lifetime));
}
-
break;
case HIR::GenericParam::GenericKind::CONST: {
+ if (is_foreign && abi != Rust::ABI::INTRINSIC)
+ {
+ rust_error_at (generic_param->get_locus (), ErrorCode::E0044,
+ "foreign items may not have const parameters");
+ }
+
auto &param
= static_cast<HIR::ConstGenericParam &> (*generic_param);
auto specified_type = TypeCheckType::Resolve (param.get_type ());
@@ -407,15 +479,31 @@ TypeCheckBase::resolve_generic_params (
break;
case HIR::GenericParam::GenericKind::TYPE: {
- auto param_type = TypeResolveGenericParam::Resolve (*generic_param);
+ if (is_foreign && abi != Rust::ABI::INTRINSIC)
+ {
+ rust_error_at (generic_param->get_locus (), ErrorCode::E0044,
+ "foreign items may not have type parameters");
+ }
+
+ auto param_type = TypeResolveGenericParam::Resolve (
+ *generic_param, false /*resolve_trait_bounds*/);
context->insert_type (generic_param->get_mappings (), param_type);
- substitutions.push_back (TyTy::SubstitutionParamMapping (
- static_cast<HIR::TypeParam &> (*generic_param), param_type));
+ auto &param = static_cast<HIR::TypeParam &> (*generic_param);
+ TyTy::SubstitutionParamMapping p (param, param_type);
+ substitutions.push_back (p);
}
break;
}
}
+
+ // now walk them to setup any specified type param bounds
+ for (auto &subst : substitutions)
+ {
+ auto pty = subst.get_param_ty ();
+ TypeResolveGenericParam::ApplyAnyTraitBounds (subst.get_generic_param (),
+ pty);
+ }
}
TyTy::TypeBoundPredicate
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h b/gcc/rust/typecheck/rust-hir-type-check-base.h
index 8a1bf6f..580082a 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.h
@@ -32,6 +32,11 @@ class TypeCheckBase
public:
virtual ~TypeCheckBase () {}
+ static void ResolveGenericParams (
+ const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params,
+ std::vector<TyTy::SubstitutionParamMapping> &substitutions, bool is_foreign,
+ ABI abi);
+
protected:
TypeCheckBase ();
@@ -57,7 +62,8 @@ protected:
void resolve_generic_params (
const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params,
- std::vector<TyTy::SubstitutionParamMapping> &substitutions);
+ std::vector<TyTy::SubstitutionParamMapping> &substitutions,
+ bool is_foreign = false, ABI abi = ABI::RUST);
TyTy::TypeBoundPredicate get_marker_predicate (LangItem::Kind item_type,
location_t locus);
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index b7fdc13..cbf529a 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -16,6 +16,8 @@
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
+#include "optional.h"
+#include "rust-hir-expr.h"
#include "rust-system.h"
#include "rust-tyty-call.h"
#include "rust-hir-type-check-struct-field.h"
@@ -842,6 +844,19 @@ TypeCheckExpr::visit (HIR::InlineAsm &expr)
}
void
+TypeCheckExpr::visit (HIR::LlvmInlineAsm &expr)
+{
+ for (auto &i : expr.inputs)
+ TypeCheckExpr::Resolve (*i.expr);
+
+ for (auto &o : expr.outputs)
+ TypeCheckExpr::Resolve (*o.expr);
+
+ // Black box hint is unit type
+ infered = TyTy::TupleType::get_unit_type ();
+}
+
+void
TypeCheckExpr::visit (HIR::RangeFullExpr &expr)
{
auto lang_item_type = LangItem::Kind::RANGE_FULL;
@@ -1127,33 +1142,119 @@ TypeCheckExpr::visit (HIR::FieldAccessExpr &expr)
bool is_valid_type = struct_base->get_kind () == TyTy::TypeKind::ADT;
if (!is_valid_type)
{
- rust_error_at (expr.get_locus (),
- "expected algebraic data type got: [%s]",
- struct_base->as_string ().c_str ());
+ rust_error_at (expr.get_locus (), "expected algebraic data type got %qs",
+ struct_base->get_name ().c_str ());
return;
}
TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (struct_base);
- rust_assert (!adt->is_enum ());
- rust_assert (adt->number_of_variants () == 1);
-
+ rust_assert (adt->number_of_variants () > 0);
TyTy::VariantDef *vaiant = adt->get_variants ().at (0);
TyTy::StructFieldType *lookup = nullptr;
bool found = vaiant->lookup_field (expr.get_field_name ().as_string (),
&lookup, nullptr);
- if (!found)
+ if (!found || adt->is_enum ())
{
- rust_error_at (expr.get_locus (), ErrorCode::E0609,
- "no field %qs on type %qs",
+ rich_location r (line_table, expr.get_locus ());
+ r.add_range (expr.get_field_name ().get_locus ());
+ rust_error_at (r, ErrorCode::E0609, "no field %qs on type %qs",
expr.get_field_name ().as_string ().c_str (),
- adt->as_string ().c_str ());
+ adt->get_name ().c_str ());
return;
}
infered = lookup->get_field_type ();
}
+bool
+is_default_fn (const MethodCandidate &candidate)
+{
+ if (candidate.candidate.is_impl_candidate ())
+ {
+ auto *item = candidate.candidate.item.impl.impl_item;
+
+ if (item->get_impl_item_type () == HIR::ImplItem::FUNCTION)
+ {
+ auto &fn = static_cast<HIR::Function &> (*item);
+
+ return fn.is_default ();
+ }
+ }
+
+ return false;
+}
+
+void
+emit_ambiguous_resolution_error (HIR::MethodCallExpr &expr,
+ std::set<MethodCandidate> &candidates)
+{
+ rich_location r (line_table, expr.get_method_name ().get_locus ());
+ std::string rich_msg = "multiple "
+ + expr.get_method_name ().get_segment ().as_string ()
+ + " found";
+
+ // We have to filter out default candidates
+ for (auto &c : candidates)
+ if (!is_default_fn (c))
+ r.add_range (c.candidate.locus);
+
+ r.add_fixit_replace (rich_msg.c_str ());
+
+ rust_error_at (r, ErrorCode::E0592, "duplicate definitions with name %qs",
+ expr.get_method_name ().get_segment ().as_string ().c_str ());
+}
+
+// We are allowed to have multiple candidates if they are all specializable
+// functions or if all of them except one are specializable functions.
+// In the later case, we just return a valid candidate without erroring out
+// about ambiguity. If there are two or more specialized functions, then we
+// error out.
+//
+// FIXME: The first case is not handled at the moment, so we error out
+tl::optional<const MethodCandidate &>
+handle_multiple_candidates (HIR::MethodCallExpr &expr,
+ std::set<MethodCandidate> &candidates)
+{
+ auto all_default = true;
+ tl::optional<const MethodCandidate &> found = tl::nullopt;
+
+ for (auto &c : candidates)
+ {
+ if (!is_default_fn (c))
+ {
+ all_default = false;
+
+ // We haven't found a final candidate yet, so we can select
+ // this one. However, if we already have a candidate, then
+ // that means there are multiple non-default candidates - we
+ // must error out
+ if (!found)
+ {
+ found = c;
+ }
+ else
+ {
+ emit_ambiguous_resolution_error (expr, candidates);
+ return tl::nullopt;
+ }
+ }
+ }
+
+ // None of the candidates were a non-default (specialized) function, so we
+ // error out
+ if (all_default)
+ {
+ rust_sorry_at (expr.get_locus (),
+ "cannot resolve method calls to non-specialized methods "
+ "(all function candidates are %qs)",
+ "default");
+ return tl::nullopt;
+ }
+
+ return found;
+}
+
void
TypeCheckExpr::visit (HIR::MethodCallExpr &expr)
{
@@ -1181,34 +1282,25 @@ TypeCheckExpr::visit (HIR::MethodCallExpr &expr)
return;
}
- if (candidates.size () > 1)
- {
- rich_location r (line_table, expr.get_method_name ().get_locus ());
- std::string rich_msg
- = "multiple " + expr.get_method_name ().get_segment ().as_string ()
- + " found";
+ tl::optional<const MethodCandidate &> candidate = *candidates.begin ();
- for (auto &c : candidates)
- r.add_range (c.candidate.locus);
+ if (candidates.size () > 1)
+ candidate = handle_multiple_candidates (expr, candidates);
- r.add_fixit_replace (rich_msg.c_str ());
+ if (!candidate)
+ return;
- rust_error_at (
- r, ErrorCode::E0592, "duplicate definitions with name %qs",
- expr.get_method_name ().get_segment ().as_string ().c_str ());
- return;
- }
+ auto found_candidate = *candidate;
- auto candidate = *candidates.begin ();
rust_debug_loc (expr.get_method_name ().get_locus (),
"resolved method to: {%u} {%s} with [%lu] adjustments",
- candidate.candidate.ty->get_ref (),
- candidate.candidate.ty->debug_str ().c_str (),
- (unsigned long) candidate.adjustments.size ());
+ found_candidate.candidate.ty->get_ref (),
+ found_candidate.candidate.ty->debug_str ().c_str (),
+ (unsigned long) found_candidate.adjustments.size ());
// Get the adjusted self
Adjuster adj (receiver_tyty);
- TyTy::BaseType *adjusted_self = adj.adjust_type (candidate.adjustments);
+ TyTy::BaseType *adjusted_self = adj.adjust_type (found_candidate.adjustments);
rust_debug ("receiver: %s adjusted self %s",
receiver_tyty->debug_str ().c_str (),
adjusted_self->debug_str ().c_str ());
@@ -1219,10 +1311,10 @@ TypeCheckExpr::visit (HIR::MethodCallExpr &expr)
HirId autoderef_mappings_id
= expr.get_receiver ().get_mappings ().get_hirid ();
context->insert_autoderef_mappings (autoderef_mappings_id,
- std::move (candidate.adjustments));
+ std::move (found_candidate.adjustments));
- PathProbeCandidate &resolved_candidate = candidate.candidate;
- TyTy::BaseType *lookup_tyty = candidate.candidate.ty;
+ PathProbeCandidate &resolved_candidate = found_candidate.candidate;
+ TyTy::BaseType *lookup_tyty = found_candidate.candidate.ty;
NodeId resolved_node_id
= resolved_candidate.is_impl_candidate ()
? resolved_candidate.item.impl.impl_item->get_impl_mappings ()
@@ -1249,8 +1341,8 @@ TypeCheckExpr::visit (HIR::MethodCallExpr &expr)
fn->prepare_higher_ranked_bounds ();
rust_debug_loc (expr.get_locus (), "resolved method call to: {%u} {%s}",
- candidate.candidate.ty->get_ref (),
- candidate.candidate.ty->debug_str ().c_str ());
+ found_candidate.candidate.ty->get_ref (),
+ found_candidate.candidate.ty->debug_str ().c_str ());
if (resolved_candidate.is_impl_candidate ())
{
@@ -1463,6 +1555,15 @@ TypeCheckExpr::visit (HIR::BorrowExpr &expr)
}
}
+ if (expr.is_raw_borrow ())
+ {
+ infered = new TyTy::PointerType (expr.get_mappings ().get_hirid (),
+ TyTy::TyVar (resolved_base->get_ref ()),
+ expr.get_mut ());
+
+ return;
+ }
+
infered = new TyTy::ReferenceType (expr.get_mappings ().get_hirid (),
TyTy::TyVar (resolved_base->get_ref ()),
expr.get_mut ());
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index 2a0022c..79121b3 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -70,6 +70,7 @@ public:
void visit (HIR::WhileLoopExpr &expr) override;
void visit (HIR::ClosureExpr &expr) override;
void visit (HIR::InlineAsm &expr) override;
+ void visit (HIR::LlvmInlineAsm &expr) override;
// TODO
void visit (HIR::ErrorPropagationExpr &) override {}
diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
index a5ae54b..bc7f6dc 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
@@ -73,44 +73,8 @@ TypeCheckTopLevelExternItem::visit (HIR::ExternalFunctionItem &function)
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (function.has_generics ())
{
- for (auto &generic_param : function.get_generic_params ())
- {
- switch (generic_param.get ()->get_kind ())
- {
- case HIR::GenericParam::GenericKind::LIFETIME:
- context->intern_and_insert_lifetime (
- static_cast<HIR::LifetimeParam &> (*generic_param)
- .get_lifetime ());
- // TODO: handle bounds
- break;
- case HIR::GenericParam::GenericKind::CONST:
- // FIXME: Skipping Lifetime and Const completely until better
- // handling.
- if (parent.get_abi () != Rust::ABI::INTRINSIC)
- {
- rust_error_at (function.get_locus (), ErrorCode::E0044,
- "foreign items may not have const parameters");
- }
- break;
-
- case HIR::GenericParam::GenericKind::TYPE: {
- if (parent.get_abi () != Rust::ABI::INTRINSIC)
- {
- rust_error_at (
- function.get_locus (), ErrorCode::E0044,
- "foreign items may not have type parameters");
- }
- auto param_type
- = TypeResolveGenericParam::Resolve (*generic_param);
- context->insert_type (generic_param->get_mappings (),
- param_type);
-
- substitutions.push_back (TyTy::SubstitutionParamMapping (
- static_cast<HIR::TypeParam &> (*generic_param), param_type));
- }
- break;
- }
- }
+ resolve_generic_params (function.get_generic_params (), substitutions,
+ true /*is_foreign*/, parent.get_abi ());
}
TyTy::RegionConstraints region_constraints;
@@ -200,128 +164,7 @@ void
TypeCheckTopLevelExternItem::visit (HIR::ExternalTypeItem &type)
{
rust_sorry_at (type.get_locus (), "extern types are not supported yet");
- // auto binder_pin = context->push_clean_lifetime_resolver ();
-
- // std::vector<TyTy::SubstitutionParamMapping> substitutions;
- // if (function.has_generics ())
- // {
- // for (auto &generic_param : function.get_generic_params ())
- // {
- // switch (generic_param.get ()->get_kind ())
- // {
- // case HIR::GenericParam::GenericKind::LIFETIME:
- // context->intern_and_insert_lifetime (
- // static_cast<HIR::LifetimeParam &> (*generic_param)
- // .get_lifetime ());
- // // TODO: handle bounds
- // break;
- // case HIR::GenericParam::GenericKind::CONST:
- // // FIXME: Skipping Lifetime and Const completely until better
- // // handling.
- // break;
-
- // case HIR::GenericParam::GenericKind::TYPE: {
- // auto param_type
- // = TypeResolveGenericParam::Resolve (generic_param.get ());
- // context->insert_type (generic_param->get_mappings (),
- // param_type);
-
- // substitutions.push_back (TyTy::SubstitutionParamMapping (
- // static_cast<HIR::TypeParam &> (*generic_param), param_type));
- // }
- // break;
- // }
- // }
- // }
-
- // TyTy::RegionConstraints region_constraints;
- // if (function.has_where_clause ())
- // {
- // for (auto &where_clause_item : function.get_where_clause ().get_items
- // ())
- // {
- // ResolveWhereClauseItem::Resolve (*where_clause_item.get (),
- // region_constraints);
- // }
- // }
-
- // TyTy::BaseType *ret_type = nullptr;
- // if (!function.has_return_type ())
- // ret_type
- // = TyTy::TupleType::get_unit_type (function.get_mappings ().get_hirid
- // ());
- // else
- // {
- // auto resolved
- // = TypeCheckType::Resolve (function.get_return_type ().get ());
- // if (resolved == nullptr)
- // {
- // rust_error_at (function.get_locus (),
- // "failed to resolve return type");
- // return;
- // }
-
- // ret_type = resolved->clone ();
- // ret_type->set_ref (
- // function.get_return_type ()->get_mappings ().get_hirid ());
- // }
-
- // std::vector<std::pair<HIR::Pattern *, TyTy::BaseType *> > params;
- // for (auto &param : function.get_function_params ())
- // {
- // // get the name as well required for later on
- // auto param_tyty = TypeCheckType::Resolve (param.get_type ().get ());
-
- // // these are implicit mappings and not used
- // auto crate_num = mappings->get_current_crate ();
- // Analysis::NodeMapping mapping (crate_num, mappings->get_next_node_id
- // (),
- // mappings->get_next_hir_id (crate_num),
- // UNKNOWN_LOCAL_DEFID);
-
- // HIR::IdentifierPattern *param_pattern
- // = new HIR::IdentifierPattern (mapping, param.get_param_name (),
- // UNDEF_LOCATION, false, Mutability::Imm,
- // std::unique_ptr<HIR::Pattern> (nullptr));
-
- // params.push_back (
- // std::pair<HIR::Pattern *, TyTy::BaseType *> (param_pattern,
- // param_tyty));
-
- // context->insert_type (param.get_mappings (), param_tyty);
-
- // // FIXME do we need error checking for patterns here?
- // // see https://github.com/Rust-GCC/gccrs/issues/995
- // }
-
- // uint8_t flags = TyTy::FnType::FNTYPE_IS_EXTERN_FLAG;
- // if (function.is_variadic ())
- // {
- // flags |= TyTy::FnType::FNTYPE_IS_VARADIC_FLAG;
- // if (parent.get_abi () != Rust::ABI::C)
- // {
- // rust_error_at (
- // function.get_locus (), ErrorCode::E0045,
- // "C-variadic function must have C or cdecl calling convention");
- // }
- // }
-
- // RustIdent ident{
- // CanonicalPath::new_seg (function.get_mappings ().get_nodeid (),
- // function.get_item_name ().as_string ()),
- // function.get_locus ()};
-
- // auto fnType = new TyTy::FnType (
- // function.get_mappings ().get_hirid (),
- // function.get_mappings ().get_defid (),
- // function.get_item_name ().as_string (), ident, flags, parent.get_abi (),
- // std::move (params), ret_type, std::move (substitutions),
- // TyTy::SubstitutionArgumentMappings::empty (
- // context->get_lifetime_resolver ().get_num_bound_regions ()),
- // region_constraints);
-
- // context->insert_type (function.get_mappings (), fnType);
- // resolved = fnType;
+ // TODO
}
TypeCheckImplItem::TypeCheckImplItem (
@@ -399,7 +242,7 @@ TypeCheckImplItem::visit (HIR::Function &function)
// add the synthetic self param at the front, this is a placeholder for
// compilation to know parameter names. The types are ignored but we
// reuse the HIR identifier pattern which requires it
- HIR::SelfParam &self_param = function.get_self_param ();
+ HIR::SelfParam &self_param = function.get_self_param_unchecked ();
// FIXME: which location should be used for Rust::Identifier for `self`?
std::unique_ptr<HIR::Pattern> self_pattern
= std::make_unique<HIR::IdentifierPattern> (
@@ -424,13 +267,21 @@ TypeCheckImplItem::visit (HIR::Function &function)
break;
case HIR::SelfParam::IMM_REF: {
- auto region = context->lookup_and_resolve_lifetime (
- self_param.get_lifetime ());
- if (!region.has_value ())
+ tl::optional<TyTy::Region> region;
+ if (self_param.has_lifetime ())
{
- rust_inform (self_param.get_locus (),
- "failed to resolve lifetime");
- region = TyTy::Region::make_anonymous (); // FIXME
+ region = context->lookup_and_resolve_lifetime (
+ self_param.get_lifetime ());
+ if (!region.has_value ())
+ {
+ rust_inform (self_param.get_locus (),
+ "failed to resolve lifetime");
+ return;
+ }
+ }
+ else
+ {
+ region = TyTy::Region::make_anonymous ();
}
self_type = new TyTy::ReferenceType (
self_param.get_mappings ().get_hirid (),
@@ -440,13 +291,21 @@ TypeCheckImplItem::visit (HIR::Function &function)
break;
case HIR::SelfParam::MUT_REF: {
- auto region = context->lookup_and_resolve_lifetime (
- self_param.get_lifetime ());
- if (!region.has_value ())
+ tl::optional<TyTy::Region> region;
+ if (self_param.has_lifetime ())
+ {
+ region = context->lookup_and_resolve_lifetime (
+ self_param.get_lifetime ());
+ if (!region.has_value ())
+ {
+ rust_error_at (self_param.get_locus (),
+ "failed to resolve lifetime");
+ return;
+ }
+ }
+ else
{
- rust_error_at (self_param.get_locus (),
- "failed to resolve lifetime");
- return;
+ region = TyTy::Region::make_anonymous ();
}
self_type = new TyTy::ReferenceType (
self_param.get_mappings ().get_hirid (),
diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc
index a003848..aaa04af 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-item.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc
@@ -355,6 +355,18 @@ TypeCheckItem::visit (HIR::Enum &enum_decl)
variants.push_back (field_type);
}
+ // Check for zero-variant enum compatibility
+ if (enum_decl.is_zero_variant ())
+ {
+ if (repr.repr_kind == TyTy::ADTType::ReprKind::INT
+ || repr.repr_kind == TyTy::ADTType::ReprKind::C)
+ {
+ rust_error_at (enum_decl.get_locus (),
+ "unsupported representation for zero-variant enum");
+ return;
+ }
+ }
+
// get the path
tl::optional<CanonicalPath> canonical_path;
@@ -637,6 +649,38 @@ TypeCheckItem::visit (HIR::Function &function)
context->switch_to_fn_body ();
auto block_expr_ty = TypeCheckExpr::Resolve (function.get_definition ());
+ // emit check for
+ // error[E0121]: the type placeholder `_` is not allowed within types on item
+ const auto placeholder = ret_type->contains_infer ();
+ if (placeholder != nullptr && function.has_return_type ())
+ {
+ // FIXME
+ // this will be a great place for the Default Hir Visitor we want to
+ // grab the locations of the placeholders (HIR::InferredType) their
+ // location, for now maybe we can use their hirid to lookup the location
+ location_t placeholder_locus
+ = mappings.lookup_location (placeholder->get_ref ());
+ location_t type_locus = function.get_return_type ().get_locus ();
+ rich_location r (line_table, placeholder_locus);
+
+ bool have_expected_type
+ = block_expr_ty != nullptr && !block_expr_ty->is<TyTy::ErrorType> ();
+ if (!have_expected_type)
+ {
+ r.add_range (type_locus);
+ }
+ else
+ {
+ std::string fixit
+ = "replace with the correct type " + block_expr_ty->get_name ();
+ r.add_fixit_replace (type_locus, fixit.c_str ());
+ }
+
+ rust_error_at (r, ErrorCode::E0121,
+ "the type placeholder %<_%> is not allowed within types "
+ "on item signatures");
+ }
+
location_t fn_return_locus = function.has_function_return_type ()
? function.get_return_type ().get_locus ()
: function.get_locus ();
@@ -725,11 +769,11 @@ TypeCheckItem::resolve_impl_block_substitutions (HIR::ImplBlock &impl_block,
// we don't error out here see: gcc/testsuite/rust/compile/traits2.rs
// for example
- specified_bound = get_predicate_from_bound (ref, impl_block.get_type ());
+ specified_bound = get_predicate_from_bound (ref, impl_block.get_type (),
+ impl_block.get_polarity ());
}
TyTy::BaseType *self = TypeCheckType::Resolve (impl_block.get_type ());
-
if (self->is<TyTy::ErrorType> ())
{
// we cannot check for unconstrained type arguments when the Self type is
@@ -771,7 +815,14 @@ TypeCheckItem::validate_trait_impl_block (
// we don't error out here see: gcc/testsuite/rust/compile/traits2.rs
// for example
- specified_bound = get_predicate_from_bound (ref, impl_block.get_type ());
+ specified_bound = get_predicate_from_bound (ref, impl_block.get_type (),
+ impl_block.get_polarity ());
+
+ // need to check that if this specified bound has super traits does this
+ // Self
+ // implement them?
+ specified_bound.validate_type_implements_super_traits (
+ *self, impl_block.get_type (), impl_block.get_trait_ref ());
}
bool is_trait_impl_block = !trait_reference->is_error ();
diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc
index 33570ff..5662da5 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-path.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc
@@ -336,7 +336,7 @@ TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset,
TyTy::BaseType *lookup = nullptr;
if (!query_type (ref, &lookup))
{
- if (is_root)
+ if (is_root || root_tyty == nullptr)
{
rust_error_at (expr.get_locus (), ErrorCode::E0425,
"cannot find value %qs in this scope",
@@ -535,8 +535,8 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id,
= impl_block_ty->lookup_predicate (trait_ref.get_defid ());
if (!predicate.is_error ())
impl_block_ty
- = associated->setup_associated_types (prev_segment,
- predicate);
+ = associated->setup_associated_types (prev_segment, predicate,
+ nullptr, false);
}
}
diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
index 3f9557a..bd13f7a 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
@@ -277,7 +277,15 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern)
infered = pattern_ty;
TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (infered);
- rust_assert (adt->number_of_variants () > 0);
+ if (adt->number_of_variants () == 0)
+ {
+ HIR::PathInExpression &path = pattern.get_path ();
+ const AST::SimplePath &sp = path.as_simple_path ();
+ rust_error_at (pattern.get_locus (), ErrorCode::E0574,
+ "expected struct, variant or union type, found enum %qs",
+ sp.as_string ().c_str ());
+ return;
+ }
TyTy::VariantDef *variant = adt->get_variants ().at (0);
if (adt->is_enum ())
@@ -285,7 +293,16 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern)
HirId variant_id = UNKNOWN_HIRID;
bool ok = context->lookup_variant_definition (
pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
- rust_assert (ok);
+ if (!ok)
+ {
+ HIR::PathInExpression &path = pattern.get_path ();
+ const AST::SimplePath &sp = path.as_simple_path ();
+ rust_error_at (
+ pattern.get_locus (), ErrorCode::E0574,
+ "expected struct, variant or union type, found enum %qs",
+ sp.as_string ().c_str ());
+ return;
+ }
ok = adt->lookup_variant_by_id (variant_id, &variant);
rust_assert (ok);
diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h
index 800f7ca..7e3a57a 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-struct-field.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-struct-field.h
@@ -60,6 +60,9 @@ private:
TyTy::BaseType *resolved_field_value_expr;
std::set<std::string> fields_assigned;
std::map<size_t, HIR::StructExprField *> adtFieldIndexToField;
+
+ // parent
+ HIR::Expr &parent;
};
} // namespace Resolver
diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct.cc b/gcc/rust/typecheck/rust-hir-type-check-struct.cc
index 40c42b2..df1636a 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-struct.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-struct.cc
@@ -28,7 +28,7 @@ TypeCheckStructExpr::TypeCheckStructExpr (HIR::Expr &e)
: TypeCheckBase (),
resolved (new TyTy::ErrorType (e.get_mappings ().get_hirid ())),
struct_path_resolved (nullptr),
- variant (&TyTy::VariantDef::get_error_node ())
+ variant (&TyTy::VariantDef::get_error_node ()), parent (e)
{}
TyTy::BaseType *
@@ -65,7 +65,7 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr)
if (base_unify->get_kind () != struct_path_ty->get_kind ())
{
- rust_fatal_error (
+ rust_error_at (
struct_expr.get_struct_base ().get_base ().get_locus (),
"incompatible types for base struct reference");
return;
@@ -82,7 +82,16 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr)
bool ok = context->lookup_variant_definition (
struct_expr.get_struct_name ().get_mappings ().get_hirid (),
&variant_id);
- rust_assert (ok);
+ if (!ok)
+ {
+ rich_location r (line_table, struct_expr.get_locus ());
+ r.add_range (struct_expr.get_struct_name ().get_locus ());
+ rust_error_at (
+ struct_expr.get_struct_name ().get_locus (), ErrorCode::E0574,
+ "expected a struct, variant or union type, found enum %qs",
+ struct_path_resolved->get_name ().c_str ());
+ return;
+ }
ok = struct_path_resolved->lookup_variant_by_id (variant_id, &variant);
rust_assert (ok);
@@ -118,29 +127,14 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr)
break;
}
- if (!ok)
- {
- return;
- }
-
- if (resolved_field_value_expr == nullptr)
- {
- rust_fatal_error (field->get_locus (),
- "failed to resolve type for field");
- ok = false;
- break;
- }
-
- context->insert_type (field->get_mappings (), resolved_field_value_expr);
+ if (ok)
+ context->insert_type (field->get_mappings (),
+ resolved_field_value_expr);
}
- // something failed setting up the fields
+ // something failed setting up the fields and error's emitted
if (!ok)
- {
- rust_error_at (struct_expr.get_locus (),
- "constructor type resolution failure");
- return;
- }
+ return;
// check the arguments are all assigned and fix up the ordering
std::vector<std::string> missing_field_names;
@@ -271,8 +265,11 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field)
&field_index);
if (!ok)
{
- rust_error_at (field.get_locus (), "unknown field");
- return true;
+ rich_location r (line_table, parent.get_locus ());
+ r.add_range (field.get_locus ());
+ rust_error_at (r, ErrorCode::E0560, "unknown field %qs",
+ field.field_name.as_string ().c_str ());
+ return false;
}
auto it = adtFieldIndexToField.find (field_index);
@@ -317,8 +314,11 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field)
bool ok = variant->lookup_field (field_name, &field_type, &field_index);
if (!ok)
{
- rust_error_at (field.get_locus (), "unknown field");
- return true;
+ rich_location r (line_table, parent.get_locus ());
+ r.add_range (field.get_locus ());
+ rust_error_at (r, ErrorCode::E0560, "unknown field %qs",
+ field_name.c_str ());
+ return false;
}
auto it = adtFieldIndexToField.find (field_index);
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc
index e56fa39..6919093 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc
@@ -360,6 +360,13 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset,
seg->as_string ().c_str ());
return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
}
+ else if (root_tyty == nullptr)
+ {
+ rust_error_at (seg->get_locus (),
+ "unknown reference for resolved name: %qs",
+ seg->as_string ().c_str ());
+ return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
+ }
return root_tyty;
}
@@ -410,8 +417,13 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset,
TyTy::BaseType *lookup = nullptr;
if (!query_type (ref, &lookup))
{
- if (is_root)
- return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
+ if (is_root || root_tyty == nullptr)
+ {
+ rust_error_at (seg->get_locus (),
+ "failed to resolve type path segment: %qs",
+ seg->as_string ().c_str ());
+ return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
+ }
return root_tyty;
}
@@ -566,6 +578,7 @@ TypeCheckType::resolve_segments (
ignore_mandatory_trait_items);
if (candidates.size () == 0)
{
+ prev_segment->debug ();
rust_error_at (
seg->get_locus (),
"failed to resolve path segment using an impl Probe");
@@ -790,9 +803,10 @@ TypeCheckType::visit (HIR::ImplTraitType &type)
}
TyTy::ParamType *
-TypeResolveGenericParam::Resolve (HIR::GenericParam &param, bool apply_sized)
+TypeResolveGenericParam::Resolve (HIR::GenericParam &param,
+ bool resolve_trait_bounds, bool apply_sized)
{
- TypeResolveGenericParam resolver (apply_sized);
+ TypeResolveGenericParam resolver (apply_sized, resolve_trait_bounds);
switch (param.get_kind ())
{
case HIR::GenericParam::GenericKind::TYPE:
@@ -811,6 +825,14 @@ TypeResolveGenericParam::Resolve (HIR::GenericParam &param, bool apply_sized)
}
void
+TypeResolveGenericParam::ApplyAnyTraitBounds (HIR::TypeParam &param,
+ TyTy::ParamType *pty)
+{
+ TypeResolveGenericParam resolver (true, true);
+ resolver.apply_trait_bounds (param, pty);
+}
+
+void
TypeResolveGenericParam::visit (HIR::LifetimeParam &param)
{
// nothing to do
@@ -828,6 +850,19 @@ TypeResolveGenericParam::visit (HIR::TypeParam &param)
if (param.has_type ())
TypeCheckType::Resolve (param.get_type ());
+ resolved
+ = new TyTy::ParamType (param.get_type_representation ().as_string (),
+ param.get_locus (),
+ param.get_mappings ().get_hirid (), param, {});
+
+ if (resolve_trait_bounds)
+ apply_trait_bounds (param, resolved);
+}
+
+void
+TypeResolveGenericParam::apply_trait_bounds (HIR::TypeParam &param,
+ TyTy::ParamType *pty)
+{
std::unique_ptr<HIR::Type> implicit_self_bound = nullptr;
if (param.has_type_param_bounds ())
{
@@ -858,8 +893,6 @@ TypeResolveGenericParam::visit (HIR::TypeParam &param)
//
// We can only do this when we are not resolving the implicit Self for Sized
// itself
- rust_debug_loc (param.get_locus (), "apply_sized: %s",
- apply_sized ? "true" : "false");
if (apply_sized)
{
TyTy::TypeBoundPredicate sized_predicate
@@ -934,10 +967,8 @@ TypeResolveGenericParam::visit (HIR::TypeParam &param)
}
}
- resolved = new TyTy::ParamType (param.get_type_representation ().as_string (),
- param.get_locus (),
- param.get_mappings ().get_hirid (), param,
- specified_bounds);
+ // inherit them
+ pty->inherit_bounds (specified_bounds);
}
void
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h
index fc272e6..cc991b6 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.h
@@ -91,20 +91,27 @@ class TypeResolveGenericParam : public TypeCheckBase
{
public:
static TyTy::ParamType *Resolve (HIR::GenericParam &param,
+ bool resolve_trait_bounds = true,
bool apply_sized = true);
+ static void ApplyAnyTraitBounds (HIR::TypeParam &param, TyTy::ParamType *pty);
+
protected:
void visit (HIR::TypeParam &param);
void visit (HIR::LifetimeParam &param);
void visit (HIR::ConstGenericParam &param);
+ void apply_trait_bounds (HIR::TypeParam &param, TyTy::ParamType *pty);
+
private:
- TypeResolveGenericParam (bool apply_sized)
- : TypeCheckBase (), resolved (nullptr), apply_sized (apply_sized)
+ TypeResolveGenericParam (bool apply_sized, bool resolve_trait_bounds)
+ : TypeCheckBase (), resolved (nullptr), apply_sized (apply_sized),
+ resolve_trait_bounds (resolve_trait_bounds)
{}
TyTy::ParamType *resolved;
bool apply_sized;
+ bool resolve_trait_bounds;
};
class ResolveWhereClauseItem : public TypeCheckBase
diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc
index a198ad3..fbaf323 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check.cc
@@ -165,36 +165,9 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const
HIR::TraitFunctionDecl &function = fn.get_decl ();
if (function.has_generics ())
{
- for (auto &generic_param : function.get_generic_params ())
- {
- switch (generic_param.get ()->get_kind ())
- {
- case HIR::GenericParam::GenericKind::LIFETIME: {
- auto lifetime_param
- = static_cast<HIR::LifetimeParam &> (*generic_param);
-
- context->intern_and_insert_lifetime (
- lifetime_param.get_lifetime ());
- // TODO: Handle lifetime bounds
- }
- break;
- case HIR::GenericParam::GenericKind::CONST:
- // FIXME: Skipping Lifetime and Const completely until better
- // handling.
- break;
-
- case HIR::GenericParam::GenericKind::TYPE: {
- auto param_type
- = TypeResolveGenericParam::Resolve (*generic_param);
- context->insert_type (generic_param->get_mappings (),
- param_type);
-
- substitutions.push_back (TyTy::SubstitutionParamMapping (
- static_cast<HIR::TypeParam &> (*generic_param), param_type));
- }
- break;
- }
- }
+ TypeCheckBase::ResolveGenericParams (function.get_generic_params (),
+ substitutions, false /*is_foreign*/,
+ ABI::RUST);
}
if (function.has_where_clause ())
@@ -235,7 +208,7 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const
// add the synthetic self param at the front, this is a placeholder
// for compilation to know parameter names. The types are ignored
// but we reuse the HIR identifier pattern which requires it
- HIR::SelfParam &self_param = function.get_self ();
+ HIR::SelfParam &self_param = function.get_self_unchecked ();
std::unique_ptr<HIR::Pattern> self_pattern
= std::make_unique<HIR::IdentifierPattern> (HIR::IdentifierPattern (
mapping, {"self"}, self_param.get_locus (), self_param.is_ref (),
diff --git a/gcc/rust/typecheck/rust-substitution-mapper.cc b/gcc/rust/typecheck/rust-substitution-mapper.cc
index 212ab3f..f0bd1f8 100644
--- a/gcc/rust/typecheck/rust-substitution-mapper.cc
+++ b/gcc/rust/typecheck/rust-substitution-mapper.cc
@@ -34,6 +34,15 @@ SubstMapper::Resolve (TyTy::BaseType *base, location_t locus,
HIR::GenericArgs *generics,
const std::vector<TyTy::Region> &regions)
{
+ if (!valid_type (base))
+ {
+ rich_location r (line_table, locus);
+ r.add_fixit_remove (generics->get_locus ());
+ rust_error_at (r, ErrorCode::E0109,
+ "generic arguments are not allowed for this type");
+ return base;
+ }
+
SubstMapper mapper (base->get_ref (), generics, regions, locus);
base->accept_vis (mapper);
rust_assert (mapper.resolved != nullptr);
@@ -47,6 +56,17 @@ SubstMapper::InferSubst (TyTy::BaseType *base, location_t locus)
}
bool
+SubstMapper::valid_type (TyTy::BaseType *base)
+{
+ bool is_fn = base->is<TyTy::FnType> ();
+ bool is_adt = base->is<TyTy::ADTType> ();
+ bool is_placeholder = base->is<TyTy::PlaceholderType> ();
+ bool is_projection = base->is<TyTy::ProjectionType> ();
+
+ return is_fn || is_adt || is_placeholder || is_projection;
+}
+
+bool
SubstMapper::have_generic_args () const
{
return generics != nullptr;
@@ -103,7 +123,12 @@ SubstMapper::visit (TyTy::ADTType &type)
void
SubstMapper::visit (TyTy::PlaceholderType &type)
{
- rust_assert (type.can_resolve ());
+ if (!type.can_resolve ())
+ {
+ resolved = &type;
+ return;
+ }
+
resolved = SubstMapper::Resolve (type.resolve (), locus, generics, regions);
}
diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h
index bc54f56..32ab71c 100644
--- a/gcc/rust/typecheck/rust-substitution-mapper.h
+++ b/gcc/rust/typecheck/rust-substitution-mapper.h
@@ -37,6 +37,8 @@ public:
bool have_generic_args () const;
+ static bool valid_type (TyTy::BaseType *base);
+
void visit (TyTy::FnType &type) override;
void visit (TyTy::ADTType &type) override;
void visit (TyTy::PlaceholderType &type) override;
diff --git a/gcc/rust/typecheck/rust-type-util.cc b/gcc/rust/typecheck/rust-type-util.cc
index 4abfbae..c6c5b4b 100644
--- a/gcc/rust/typecheck/rust-type-util.cc
+++ b/gcc/rust/typecheck/rust-type-util.cc
@@ -22,10 +22,13 @@
#include "rust-hir-type-check-implitem.h"
#include "rust-hir-type-check-item.h"
#include "rust-hir-type-check.h"
+#include "rust-hir-type-check-type.h"
#include "rust-casts.h"
#include "rust-unify.h"
#include "rust-coercion.h"
#include "rust-hir-type-bounds.h"
+#include "rust-immutable-name-resolution-context.h"
+#include "options.h"
namespace Rust {
namespace Resolver {
@@ -34,6 +37,7 @@ bool
query_type (HirId reference, TyTy::BaseType **result)
{
auto &mappings = Analysis::Mappings::get ();
+ auto &resolver = *Resolver::get ();
TypeCheckContext *context = TypeCheckContext::get ();
if (context->query_in_progress (reference))
@@ -91,6 +95,39 @@ query_type (HirId reference, TyTy::BaseType **result)
HIR::ImplBlock *impl = impl_block_by_type.value ();
rust_debug_loc (impl->get_locus (), "resolved impl block type {%u} to",
reference);
+
+ // this could be recursive to the root type
+ if (impl->has_type ())
+ {
+ HIR::Type &ty = impl->get_type ();
+ NodeId ref_node_id = UNKNOWN_NODEID;
+ NodeId ast_node_id = ty.get_mappings ().get_nodeid ();
+
+ if (flag_name_resolution_2_0)
+ {
+ auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ()
+ .resolver ();
+
+ // assign the ref_node_id if we've found something
+ nr_ctx.lookup (ast_node_id)
+ .map (
+ [&ref_node_id] (NodeId resolved) { ref_node_id = resolved; });
+ }
+ else if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id))
+ resolver.lookup_resolved_type (ast_node_id, &ref_node_id);
+
+ if (ref_node_id != UNKNOWN_NODEID)
+ {
+ tl::optional<HirId> hid
+ = mappings.lookup_node_to_hir (ref_node_id);
+ if (hid.has_value () && context->query_in_progress (hid.value ()))
+ {
+ context->query_completed (reference);
+ return false;
+ }
+ }
+ }
+
*result = TypeCheckItem::ResolveImplBlockSelf (*impl);
context->query_completed (reference);
return true;
diff --git a/gcc/rust/typecheck/rust-typecheck-context.cc b/gcc/rust/typecheck/rust-typecheck-context.cc
index f02e484..9112b99 100644
--- a/gcc/rust/typecheck/rust-typecheck-context.cc
+++ b/gcc/rust/typecheck/rust-typecheck-context.cc
@@ -514,7 +514,16 @@ TypeCheckContext::lookup_lifetime (const HIR::Lifetime &lifetime) const
{
if (lifetime.get_lifetime_type () == AST::Lifetime::NAMED)
{
- rust_assert (lifetime.get_name () != "static");
+ if (lifetime.get_name () == "static")
+ {
+ rich_location r (line_table, lifetime.get_locus ());
+ r.add_fixit_insert_after (lifetime.get_locus (),
+ "static is a reserved lifetime name");
+ rust_error_at (r, ErrorCode::E0262,
+ "invalid lifetime parameter name: %qs",
+ lifetime.get_name ().c_str ());
+ return tl::nullopt;
+ }
const auto name = lifetime.get_name ();
auto it = lifetime_name_interner.find (name);
if (it == lifetime_name_interner.end ())
diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc
index 65f24c0..e028a0a 100644
--- a/gcc/rust/typecheck/rust-tyty-bounds.cc
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -828,6 +828,65 @@ TypeBoundPredicate::is_equal (const TypeBoundPredicate &other) const
return true;
}
+bool
+TypeBoundPredicate::validate_type_implements_super_traits (
+ TyTy::BaseType &self, HIR::Type &impl_type, HIR::Type &trait) const
+{
+ if (get_polarity () != BoundPolarity::RegularBound)
+ return true;
+
+ auto &ptref = *get ();
+ for (auto &super : super_traits)
+ {
+ if (super.get_polarity () != BoundPolarity::RegularBound)
+ continue;
+
+ if (!super.validate_type_implements_this (self, impl_type, trait))
+ {
+ auto &sptref = *super.get ();
+
+ // emit error
+ std::string fixit1
+ = "required by this bound in: " + ptref.get_name ();
+ std::string fixit2 = "the trait " + sptref.get_name ()
+ + " is not implemented for "
+ + impl_type.as_string ();
+
+ rich_location r (line_table, trait.get_locus ());
+ r.add_fixit_insert_after (super.get_locus (), fixit1.c_str ());
+ r.add_fixit_insert_after (trait.get_locus (), fixit2.c_str ());
+ rust_error_at (r, ErrorCode::E0277,
+ "the trait bound %<%s: %s%> is not satisfied",
+ impl_type.as_string ().c_str (),
+ sptref.get_name ().c_str ());
+
+ return false;
+ }
+
+ if (!super.validate_type_implements_super_traits (self, impl_type, trait))
+ return false;
+ }
+
+ return true;
+}
+
+bool
+TypeBoundPredicate::validate_type_implements_this (TyTy::BaseType &self,
+ HIR::Type &impl_type,
+ HIR::Type &trait) const
+{
+ const auto &ptref = *get ();
+ auto probed_bounds = Resolver::TypeBoundsProbe::Probe (&self);
+ for (auto &elem : probed_bounds)
+ {
+ auto &tref = *(elem.first);
+ if (ptref.is_equal (tref))
+ return true;
+ }
+
+ return false;
+}
+
// trait item reference
const Resolver::TraitItemReference *
diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc
index 95f18b9..bdb6474 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.cc
+++ b/gcc/rust/typecheck/rust-tyty-subst.cc
@@ -28,8 +28,8 @@
namespace Rust {
namespace TyTy {
-SubstitutionParamMapping::SubstitutionParamMapping (
- const HIR::TypeParam &generic, ParamType *param)
+SubstitutionParamMapping::SubstitutionParamMapping (HIR::TypeParam &generic,
+ ParamType *param)
: generic (generic), param (param)
{}
@@ -66,8 +66,8 @@ SubstitutionParamMapping::get_param_ty () const
return param;
}
-const HIR::TypeParam &
-SubstitutionParamMapping::get_generic_param () const
+HIR::TypeParam &
+SubstitutionParamMapping::get_generic_param ()
{
return generic;
}
diff --git a/gcc/rust/typecheck/rust-tyty-subst.h b/gcc/rust/typecheck/rust-tyty-subst.h
index b8e928d..e6ed1fc 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.h
+++ b/gcc/rust/typecheck/rust-tyty-subst.h
@@ -44,7 +44,7 @@ class SubstitutionArgumentMappings;
class SubstitutionParamMapping
{
public:
- SubstitutionParamMapping (const HIR::TypeParam &generic, ParamType *param);
+ SubstitutionParamMapping (HIR::TypeParam &generic, ParamType *param);
SubstitutionParamMapping (const SubstitutionParamMapping &other);
@@ -59,7 +59,7 @@ public:
const ParamType *get_param_ty () const;
- const HIR::TypeParam &get_generic_param () const;
+ HIR::TypeParam &get_generic_param ();
// this is used for the backend to override the HirId ref of the param to
// what the concrete type is for the rest of the context
@@ -76,7 +76,7 @@ public:
bool need_substitution () const;
private:
- const HIR::TypeParam &generic;
+ HIR::TypeParam &generic;
ParamType *param;
};
@@ -125,7 +125,7 @@ public:
std::vector<Region> subst)
{
RegionParamList list (num_regions);
- for (size_t i = 0; i < subst.size (); i++)
+ for (size_t i = 0; i < MIN (num_regions, subst.size ()); i++)
list.regions.at (i) = subst.at (i);
for (size_t i = subst.size (); i < num_regions; i++)
{
diff --git a/gcc/rust/typecheck/rust-tyty-variance-analysis.cc b/gcc/rust/typecheck/rust-tyty-variance-analysis.cc
index 1aba576..38f9d52 100644
--- a/gcc/rust/typecheck/rust-tyty-variance-analysis.cc
+++ b/gcc/rust/typecheck/rust-tyty-variance-analysis.cc
@@ -238,7 +238,7 @@ GenericTyVisitorCtx::process_type (ADTType &ty)
first_lifetime = lookup_or_add_type (ty.get_orig_ref ());
first_type = first_lifetime + ty.get_used_arguments ().get_regions ().size ();
- for (const auto &param : ty.get_substs ())
+ for (auto &param : ty.get_substs ())
param_names.push_back (
param.get_generic_param ().get_type_representation ().as_string ());
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index efad5f6..f0f4a07 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -682,6 +682,91 @@ BaseType::debug () const
debug_str ().c_str ());
}
+const TyTy::BaseType *
+BaseType::contains_infer () const
+{
+ const TyTy::BaseType *x = destructure ();
+
+ if (auto fn = x->try_as<const FnType> ())
+ {
+ for (const auto &param : fn->get_params ())
+ {
+ auto infer = param.get_type ()->contains_infer ();
+ if (infer)
+ return infer;
+ }
+ return fn->get_return_type ()->contains_infer ();
+ }
+ else if (auto fn = x->try_as<const FnPtr> ())
+ {
+ for (const auto &param : fn->get_params ())
+ {
+ auto infer = param.get_tyty ()->contains_infer ();
+ if (infer)
+ return infer;
+ }
+ return fn->get_return_type ()->contains_infer ();
+ }
+ else if (auto adt = x->try_as<const ADTType> ())
+ {
+ for (auto &variant : adt->get_variants ())
+ {
+ bool is_num_variant
+ = variant->get_variant_type () == VariantDef::VariantType::NUM;
+ if (is_num_variant)
+ continue;
+
+ for (auto &field : variant->get_fields ())
+ {
+ const BaseType *field_type = field->get_field_type ();
+ auto infer = (field_type->contains_infer ());
+ if (infer)
+ return infer;
+ }
+ }
+ return nullptr;
+ }
+ else if (auto arr = x->try_as<const ArrayType> ())
+ {
+ return arr->get_element_type ()->contains_infer ();
+ }
+ else if (auto slice = x->try_as<const SliceType> ())
+ {
+ return slice->get_element_type ()->contains_infer ();
+ }
+ else if (auto ptr = x->try_as<const PointerType> ())
+ {
+ return ptr->get_base ()->contains_infer ();
+ }
+ else if (auto ref = x->try_as<const ReferenceType> ())
+ {
+ return ref->get_base ()->contains_infer ();
+ }
+ else if (auto tuple = x->try_as<const TupleType> ())
+ {
+ for (size_t i = 0; i < tuple->num_fields (); i++)
+ {
+ auto infer = (tuple->get_field (i)->contains_infer ());
+ if (infer)
+ return infer;
+ }
+ return nullptr;
+ }
+ else if (auto closure = x->try_as<const ClosureType> ())
+ {
+ auto infer = (closure->get_parameters ().contains_infer ());
+ if (infer)
+ return infer;
+ return closure->get_result_type ().contains_infer ();
+ }
+ else if (x->is<InferType> ())
+ {
+ return x;
+ }
+
+ return nullptr;
+}
+
bool
BaseType::is_concrete () const
{
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 0bfd29d..1cada9a 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -137,6 +137,9 @@ public:
void inherit_bounds (
const std::vector<TyTy::TypeBoundPredicate> &specified_bounds);
+ // contains_infer checks if there is an inference variable inside the type
+ const TyTy::BaseType *contains_infer () const;
+
// is_unit returns whether this is just a unit-struct
bool is_unit () const;
@@ -578,6 +581,14 @@ public:
bool is_equal (const TypeBoundPredicate &other) const;
+ bool validate_type_implements_super_traits (TyTy::BaseType &self,
+ HIR::Type &impl_type,
+ HIR::Type &trait) const;
+
+ bool validate_type_implements_this (TyTy::BaseType &self,
+ HIR::Type &impl_type,
+ HIR::Type &trait) const;
+
private:
struct mark_is_error
{
@@ -703,12 +714,22 @@ public:
ENUM
};
+ enum ReprKind
+ {
+ RUST,
+ C,
+ INT,
+ ALIGN,
+ PACKED,
+ // TRANSPARENT,
+ // SIMD,
+ // ...
+ };
+
// Representation options, specified via attributes e.g. #[repr(packed)]
struct ReprOptions
{
- // bool is_c;
- // bool is_transparent;
- //...
+ ReprKind repr_kind = ReprKind::RUST;
// For align and pack: 0 = unspecified. Nonzero = byte alignment.
// It is an error for both to be nonzero, this should be caught when
diff --git a/gcc/rust/util/expected.h b/gcc/rust/util/expected.h
index a9e3bc2..07ba877 100644
--- a/gcc/rust/util/expected.h
+++ b/gcc/rust/util/expected.h
@@ -212,10 +212,8 @@ template <typename E>
throw std::forward<E>(e);
#else
(void)e;
-#ifdef _MSC_VER
gcc_unreachable();
#endif
-#endif
}
#ifndef TL_TRAITS_MUTEX
@@ -2437,4 +2435,4 @@ void swap(expected<T, E> &lhs,
}
} // namespace tl
-#endif \ No newline at end of file
+#endif
diff --git a/gcc/rust/util/rust-attribute-values.h b/gcc/rust/util/rust-attribute-values.h
index 9ef5cc5..47e6a17 100644
--- a/gcc/rust/util/rust-attribute-values.h
+++ b/gcc/rust/util/rust-attribute-values.h
@@ -40,12 +40,14 @@ public:
static constexpr auto &NO_MANGLE = "no_mangle";
static constexpr auto &REPR = "repr";
static constexpr auto &RUSTC_BUILTIN_MACRO = "rustc_builtin_macro";
+ static constexpr auto &RUSTC_MACRO_TRANSPARENCY = "rustc_macro_transparency";
static constexpr auto &PATH = "path";
static constexpr auto &MACRO_USE = "macro_use";
static constexpr auto &MACRO_EXPORT = "macro_export";
static constexpr auto &PROC_MACRO = "proc_macro";
static constexpr auto &PROC_MACRO_DERIVE = "proc_macro_derive";
static constexpr auto &PROC_MACRO_ATTRIBUTE = "proc_macro_attribute";
+
static constexpr auto &TARGET_FEATURE = "target_feature";
// From now on, these are reserved by the compiler and gated through
// #![feature(rustc_attrs)]
@@ -54,10 +56,35 @@ public:
= "rustc_inherit_overflow_checks";
static constexpr auto &STABLE = "stable";
static constexpr auto &UNSTABLE = "unstable";
+
+ static constexpr auto &RUSTC_PROMOTABLE = "rustc_promotable";
static constexpr auto &RUSTC_CONST_STABLE = "rustc_const_stable";
static constexpr auto &RUSTC_CONST_UNSTABLE = "rustc_const_unstable";
+
+ static constexpr auto &RUSTC_SPECIALIZATION_TRAIT
+ = "rustc_specialization_trait";
+ static constexpr auto &RUSTC_UNSAFE_SPECIALIZATION_MARKER
+ = "rustc_unsafe_specialization_marker";
+ static constexpr auto &RUSTC_RESERVATION_IMPL = "rustc_reservation_impl";
+ static constexpr auto &RUSTC_PAREN_SUGAR = "rustc_paren_sugar";
+ static constexpr auto &RUSTC_NONNULL_OPTIMIZATION_GUARANTEED
+ = "rustc_nonnull_optimization_guaranteed";
+
+ static constexpr auto &RUSTC_LAYOUT_SCALAR_VALID_RANGE_START
+ = "rustc_layout_scalar_valid_range_start";
+
static constexpr auto &MAY_DANGLE = "may_dangle";
static constexpr auto &PRELUDE_IMPORT = "prelude_import";
+ static constexpr auto &TRACK_CALLER = "track_caller";
+
+ static constexpr auto &RUSTC_DIAGNOSTIC_ITEM = "rustc_diagnostic_item";
+ static constexpr auto &RUSTC_ON_UNIMPLEMENTED = "rustc_on_unimplemented";
+
+ static constexpr auto &FUNDAMENTAL = "fundamental";
+
+ static constexpr auto &NON_EXHAUSTIVE = "non_exhaustive";
+
+ static constexpr auto &RUSTFMT = "rustfmt";
};
} // namespace Values
} // namespace Rust
diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc
index 03452c7..c77e99c 100644
--- a/gcc/rust/util/rust-attributes.cc
+++ b/gcc/rust/util/rust-attributes.cc
@@ -57,6 +57,7 @@ static const BuiltinAttrDefinition __definitions[]
{Attrs::NO_MANGLE, CODE_GENERATION},
{Attrs::REPR, CODE_GENERATION},
{Attrs::RUSTC_BUILTIN_MACRO, EXPANSION},
+ {Attrs::RUSTC_MACRO_TRANSPARENCY, EXPANSION},
{Attrs::PATH, EXPANSION},
{Attrs::MACRO_USE, NAME_RESOLUTION},
{Attrs::MACRO_EXPORT, NAME_RESOLUTION},
@@ -72,10 +73,29 @@ static const BuiltinAttrDefinition __definitions[]
{Attrs::RUSTC_INHERIT_OVERFLOW_CHECKS, CODE_GENERATION},
{Attrs::STABLE, STATIC_ANALYSIS},
{Attrs::UNSTABLE, STATIC_ANALYSIS},
+
// assuming we keep these for static analysis
+ {Attrs::RUSTC_PROMOTABLE, CODE_GENERATION},
{Attrs::RUSTC_CONST_STABLE, STATIC_ANALYSIS},
{Attrs::RUSTC_CONST_UNSTABLE, STATIC_ANALYSIS},
- {Attrs::PRELUDE_IMPORT, NAME_RESOLUTION}};
+ {Attrs::PRELUDE_IMPORT, NAME_RESOLUTION},
+ {Attrs::TRACK_CALLER, CODE_GENERATION},
+ {Attrs::RUSTC_SPECIALIZATION_TRAIT, TYPE_CHECK},
+ {Attrs::RUSTC_UNSAFE_SPECIALIZATION_MARKER, TYPE_CHECK},
+ {Attrs::RUSTC_RESERVATION_IMPL, TYPE_CHECK},
+ {Attrs::RUSTC_PAREN_SUGAR, TYPE_CHECK},
+ {Attrs::RUSTC_NONNULL_OPTIMIZATION_GUARANTEED, TYPE_CHECK},
+
+ {Attrs::RUSTC_LAYOUT_SCALAR_VALID_RANGE_START, CODE_GENERATION},
+
+ {Attrs::PRELUDE_IMPORT, NAME_RESOLUTION},
+
+ {Attrs::RUSTC_DIAGNOSTIC_ITEM, STATIC_ANALYSIS},
+ {Attrs::RUSTC_ON_UNIMPLEMENTED, STATIC_ANALYSIS},
+
+ {Attrs::FUNDAMENTAL, TYPE_CHECK},
+ {Attrs::NON_EXHAUSTIVE, TYPE_CHECK},
+ {Attrs::RUSTFMT, EXTERNAL}};
BuiltinAttributeMappings *
BuiltinAttributeMappings::get ()
diff --git a/gcc/rust/util/rust-attributes.h b/gcc/rust/util/rust-attributes.h
index c928c8e..7c7a1fc 100644
--- a/gcc/rust/util/rust-attributes.h
+++ b/gcc/rust/util/rust-attributes.h
@@ -40,7 +40,12 @@ enum CompilerPass
HIR_LOWERING,
TYPE_CHECK,
STATIC_ANALYSIS,
- CODE_GENERATION
+ CODE_GENERATION,
+
+ // External Rust tooling attributes, like #[rustfmt::skip]
+ EXTERNAL,
+
+ // Do we need to add something here for const fns?
};
struct BuiltinAttrDefinition
diff --git a/gcc/rust/util/rust-lang-item.cc b/gcc/rust/util/rust-lang-item.cc
index a76cc7f..9aff31b 100644
--- a/gcc/rust/util/rust-lang-item.cc
+++ b/gcc/rust/util/rust-lang-item.cc
@@ -118,6 +118,7 @@ const BiMap<std::string, LangItem::Kind> Rust::LangItem::lang_items = {{
{"discriminant_kind", Kind::DISCRIMINANT_KIND},
{"discriminant_type", Kind::DISCRIMINANT_TYPE},
+ {"manually_drop", Kind::MANUALLY_DROP},
}};
tl::optional<LangItem::Kind>
diff --git a/gcc/rust/util/rust-lang-item.h b/gcc/rust/util/rust-lang-item.h
index 8f3af36..67a5d9c 100644
--- a/gcc/rust/util/rust-lang-item.h
+++ b/gcc/rust/util/rust-lang-item.h
@@ -150,6 +150,8 @@ public:
DISCRIMINANT_TYPE,
DISCRIMINANT_KIND,
+
+ MANUALLY_DROP,
};
static const BiMap<std::string, Kind> lang_items;
diff --git a/gcc/rust/util/rust-stacked-contexts.h b/gcc/rust/util/rust-stacked-contexts.h
index fe0bc8a..b263d75 100644
--- a/gcc/rust/util/rust-stacked-contexts.h
+++ b/gcc/rust/util/rust-stacked-contexts.h
@@ -71,7 +71,14 @@ public:
return last;
}
- const T &peek ()
+ const T &peek () const
+ {
+ rust_assert (!stack.empty ());
+
+ return stack.back ();
+ }
+
+ T &peek ()
{
rust_assert (!stack.empty ());