aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog460
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/ada/ChangeLog115
-rw-r--r--gcc/ada/atree.adb4
-rw-r--r--gcc/ada/contracts.adb5
-rw-r--r--gcc/ada/exp_ch3.adb7
-rw-r--r--gcc/ada/exp_ch6.adb14
-rw-r--r--gcc/ada/exp_disp.adb5
-rw-r--r--gcc/ada/exp_prag.adb16
-rw-r--r--gcc/ada/exp_spark.adb5
-rw-r--r--gcc/ada/exp_util.adb29
-rw-r--r--gcc/ada/expander.adb5
-rw-r--r--gcc/ada/freeze.adb15
-rw-r--r--gcc/ada/frontend.adb2
-rw-r--r--gcc/ada/ghost.adb33
-rw-r--r--gcc/ada/ghost.ads2
-rw-r--r--gcc/ada/gnat1drv.adb5
-rw-r--r--gcc/ada/lib-writ.adb2
-rw-r--r--gcc/ada/lib-xref.adb4
-rw-r--r--gcc/ada/opt.adb9
-rw-r--r--gcc/ada/opt.ads21
-rw-r--r--gcc/ada/par-ch12.adb29
-rw-r--r--gcc/ada/par-ch3.adb208
-rw-r--r--gcc/ada/par-ch6.adb30
-rw-r--r--gcc/ada/par-util.adb29
-rw-r--r--gcc/ada/par.adb169
-rw-r--r--gcc/ada/rtsfind.adb15
-rw-r--r--gcc/ada/sem.adb10
-rw-r--r--gcc/ada/sem_attr.adb2
-rw-r--r--gcc/ada/sem_ch12.adb24
-rw-r--r--gcc/ada/sem_ch13.adb19
-rw-r--r--gcc/ada/sem_ch3.adb10
-rw-r--r--gcc/ada/sem_ch5.adb7
-rw-r--r--gcc/ada/sem_ch6.adb19
-rw-r--r--gcc/ada/sem_ch7.adb9
-rw-r--r--gcc/ada/sem_prag.adb292
-rw-r--r--gcc/ada/sem_util.adb60
-rw-r--r--gcc/ada/sem_util.ads12
-rw-r--r--gcc/ada/table.adb3
-rw-r--r--gcc/ada/table.ads3
-rw-r--r--gcc/ada/treepr.adb16
-rw-r--r--gcc/avoid-store-forwarding.cc9
-rw-r--r--gcc/c/c-parser.cc157
-rw-r--r--gcc/c/c-typeck.cc21
-rw-r--r--gcc/config/aarch64/aarch64-protos.h3
-rw-r--r--gcc/config/aarch64/aarch64-sve-builtins-base.cc45
-rw-r--r--gcc/config/aarch64/aarch64-sve-builtins-functions.h8
-rw-r--r--gcc/config/aarch64/aarch64-sve-builtins-sve2.cc4
-rw-r--r--gcc/config/aarch64/aarch64-sve-builtins.cc22
-rw-r--r--gcc/config/aarch64/aarch64-sve.md645
-rw-r--r--gcc/config/aarch64/aarch64-sve2.md88
-rw-r--r--gcc/config/aarch64/aarch64.cc56
-rw-r--r--gcc/config/aarch64/aarch64.md1
-rw-r--r--gcc/config/aarch64/iterators.md7
-rw-r--r--gcc/config/aarch64/predicates.md6
-rw-r--r--gcc/config/avr/avr-dimode.md87
-rw-r--r--gcc/config/avr/avr-fixed.md129
-rw-r--r--gcc/config/avr/avr-log.cc1
-rw-r--r--gcc/config/avr/avr-protos.h2
-rw-r--r--gcc/config/avr/avr.cc134
-rw-r--r--gcc/config/avr/avr.h18
-rw-r--r--gcc/config/avr/avr.md1253
-rw-r--r--gcc/config/avr/avr.opt4
-rw-r--r--gcc/config/avr/avr.opt.urls2
-rw-r--r--gcc/config/i386/i386-expand.cc5
-rw-r--r--gcc/config/i386/i386-features.cc107
-rw-r--r--gcc/config/i386/i386.md407
-rw-r--r--gcc/config/i386/predicates.md8
-rw-r--r--gcc/config/riscv/riscv.cc4
-rw-r--r--gcc/cp/ChangeLog23
-rw-r--r--gcc/cp/class.cc25
-rw-r--r--gcc/cp/constexpr.cc67
-rw-r--r--gcc/cp/decl.cc2
-rw-r--r--gcc/cp/init.cc43
-rw-r--r--gcc/cp/parser.cc167
-rw-r--r--gcc/cp/semantics.cc21
-rw-r--r--gcc/defaults.h2
-rw-r--r--gcc/diagnostics/buffering.h10
-rw-r--r--gcc/diagnostics/context.cc20
-rw-r--r--gcc/diagnostics/context.h128
-rw-r--r--gcc/diagnostics/counters.h51
-rw-r--r--gcc/diagnostics/html-sink.cc12
-rw-r--r--gcc/diagnostics/lazy-paths.cc6
-rw-r--r--gcc/diagnostics/option-id-manager.h56
-rw-r--r--gcc/diagnostics/source-printing-options.h76
-rw-r--r--gcc/doc/install.texi4
-rw-r--r--gcc/doc/invoke.texi17
-rw-r--r--gcc/doc/libgdiagnostics/topics/compatibility.rst9
-rw-r--r--gcc/doc/libgdiagnostics/topics/physical-locations.rst16
-rw-r--r--gcc/doc/tm.texi8
-rw-r--r--gcc/doc/tm.texi.in8
-rw-r--r--gcc/dump-context.h10
-rw-r--r--gcc/dumpfile.cc57
-rw-r--r--gcc/explow.cc24
-rw-r--r--gcc/expr.cc12
-rw-r--r--gcc/expr.h4
-rw-r--r--gcc/fortran/ChangeLog65
-rw-r--r--gcc/fortran/trans-array.cc28
-rw-r--r--gcc/fortran/trans-array.h1
-rw-r--r--gcc/fortran/trans-decl.cc39
-rw-r--r--gcc/fortran/trans-expr.cc9
-rw-r--r--gcc/fortran/trans-stmt.cc36
-rw-r--r--gcc/fortran/trans.cc4
-rw-r--r--gcc/fortran/trans.h4
-rw-r--r--gcc/function.cc4
-rw-r--r--gcc/gimple-pretty-print.cc6
-rw-r--r--gcc/gimple-warn-recursion.cc1
-rw-r--r--gcc/gimple.cc8
-rw-r--r--gcc/gimple.def2
-rw-r--r--gcc/gimple.h43
-rw-r--r--gcc/gimplify.cc440
-rw-r--r--gcc/gimplify.h4
-rw-r--r--gcc/gsstruct.def1
-rw-r--r--gcc/libgdiagnostics++.h10
-rw-r--r--gcc/libgdiagnostics-private.h7
-rw-r--r--gcc/libgdiagnostics.cc77
-rw-r--r--gcc/libgdiagnostics.h10
-rw-r--r--gcc/libgdiagnostics.map8
-rw-r--r--gcc/libsarifreplay.cc12
-rw-r--r--gcc/libsarifreplay.h1
-rw-r--r--gcc/lto-wrapper.cc13
-rw-r--r--gcc/omp-low.cc82
-rw-r--r--gcc/opt-problem.cc2
-rw-r--r--gcc/optinfo-emit-json.cc12
-rw-r--r--gcc/optinfo.cc40
-rw-r--r--gcc/optinfo.h57
-rw-r--r--gcc/opts-common.cc2
-rw-r--r--gcc/opts-diagnostic.h19
-rw-r--r--gcc/opts.cc4
-rw-r--r--gcc/rust/ChangeLog2388
-rw-r--r--gcc/rust/Make-lang.in15
-rw-r--r--gcc/rust/ast/rust-ast-builder-type.cc163
-rw-r--r--gcc/rust/ast/rust-ast-builder-type.h57
-rw-r--r--gcc/rust/ast/rust-ast-builder.cc85
-rw-r--r--gcc/rust/ast/rust-ast-builder.h43
-rw-r--r--gcc/rust/ast/rust-ast-collector.cc213
-rw-r--r--gcc/rust/ast/rust-ast-collector.h8
-rw-r--r--gcc/rust/ast/rust-ast-dump.h6
-rw-r--r--gcc/rust/ast/rust-ast-formatting.h15
-rw-r--r--gcc/rust/ast/rust-ast-full-decls.h8
-rw-r--r--gcc/rust/ast/rust-ast-visitor.cc98
-rw-r--r--gcc/rust/ast/rust-ast-visitor.h16
-rw-r--r--gcc/rust/ast/rust-ast.cc372
-rw-r--r--gcc/rust/ast/rust-ast.h82
-rw-r--r--gcc/rust/ast/rust-builtin-ast-nodes.h53
-rw-r--r--gcc/rust/ast/rust-collect-lang-items.cc24
-rw-r--r--gcc/rust/ast/rust-collect-lang-items.h3
-rw-r--r--gcc/rust/ast/rust-cond-compilation.h4
-rw-r--r--gcc/rust/ast/rust-desugar-apit.cc522
-rw-r--r--gcc/rust/ast/rust-desugar-apit.h42
-rw-r--r--gcc/rust/ast/rust-desugar-for-loops.cc69
-rw-r--r--gcc/rust/ast/rust-desugar-for-loops.h17
-rw-r--r--gcc/rust/ast/rust-desugar-question-mark.cc54
-rw-r--r--gcc/rust/ast/rust-desugar-question-mark.h16
-rw-r--r--gcc/rust/ast/rust-desugar-try-block.cc62
-rw-r--r--gcc/rust/ast/rust-desugar-try-block.h42
-rw-r--r--gcc/rust/ast/rust-desugar-while-let.cc104
-rw-r--r--gcc/rust/ast/rust-desugar-while-let.h71
-rw-r--r--gcc/rust/ast/rust-expr.h443
-rw-r--r--gcc/rust/ast/rust-expression-yeast.cc118
-rw-r--r--gcc/rust/ast/rust-expression-yeast.h52
-rw-r--r--gcc/rust/ast/rust-fmt.h7
-rw-r--r--gcc/rust/ast/rust-item.h35
-rw-r--r--gcc/rust/ast/rust-macro.h49
-rw-r--r--gcc/rust/ast/rust-path.cc21
-rw-r--r--gcc/rust/ast/rust-path.h45
-rw-r--r--gcc/rust/ast/rust-pattern.cc58
-rw-r--r--gcc/rust/ast/rust-pattern.h238
-rw-r--r--gcc/rust/ast/rust-type.h165
-rw-r--r--gcc/rust/backend/rust-compile-asm.cc105
-rw-r--r--gcc/rust/backend/rust-compile-base.cc37
-rw-r--r--gcc/rust/backend/rust-compile-base.h3
-rw-r--r--gcc/rust/backend/rust-compile-block.cc1
-rw-r--r--gcc/rust/backend/rust-compile-block.h12
-rw-r--r--gcc/rust/backend/rust-compile-context.cc28
-rw-r--r--gcc/rust/backend/rust-compile-context.h6
-rw-r--r--gcc/rust/backend/rust-compile-expr.cc159
-rw-r--r--gcc/rust/backend/rust-compile-expr.h3
-rw-r--r--gcc/rust/backend/rust-compile-implitem.cc42
-rw-r--r--gcc/rust/backend/rust-compile-intrinsic.cc82
-rw-r--r--gcc/rust/backend/rust-compile-item.cc129
-rw-r--r--gcc/rust/backend/rust-compile-item.h8
-rw-r--r--gcc/rust/backend/rust-compile-pattern.cc456
-rw-r--r--gcc/rust/backend/rust-compile-pattern.h24
-rw-r--r--gcc/rust/backend/rust-compile-resolve-path.cc58
-rw-r--r--gcc/rust/backend/rust-compile-stmt.cc3
-rw-r--r--gcc/rust/backend/rust-compile-type.cc50
-rw-r--r--gcc/rust/backend/rust-compile-type.h1
-rw-r--r--gcc/rust/backend/rust-compile-var-decl.h3
-rw-r--r--gcc/rust/backend/rust-constexpr.cc193
-rw-r--r--gcc/rust/backend/rust-constexpr.h3
-rw-r--r--gcc/rust/backend/rust-mangle-v0.cc18
-rw-r--r--gcc/rust/backend/rust-mangle.h11
-rw-r--r--gcc/rust/backend/rust-tree.cc82
-rw-r--r--gcc/rust/backend/rust-tree.h183
-rw-r--r--gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h20
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc22
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h4
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h54
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h9
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc21
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h4
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-dump.cc3
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h30
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-place.h11
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-bir-visitor.h2
-rw-r--r--gcc/rust/checks/errors/borrowck/rust-function-collector.h4
-rw-r--r--gcc/rust/checks/errors/privacy/rust-privacy-check.cc3
-rw-r--r--gcc/rust/checks/errors/privacy/rust-privacy-ctx.h3
-rw-r--r--gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc35
-rw-r--r--gcc/rust/checks/errors/privacy/rust-privacy-reporter.h4
-rw-r--r--gcc/rust/checks/errors/privacy/rust-reachability.cc6
-rw-r--r--gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc3
-rw-r--r--gcc/rust/checks/errors/rust-const-checker.cc24
-rw-r--r--gcc/rust/checks/errors/rust-const-checker.h3
-rw-r--r--gcc/rust/checks/errors/rust-feature.cc2
-rw-r--r--gcc/rust/checks/errors/rust-hir-pattern-analysis.cc142
-rw-r--r--gcc/rust/checks/errors/rust-hir-pattern-analysis.h9
-rw-r--r--gcc/rust/checks/errors/rust-readonly-check2.cc253
-rw-r--r--gcc/rust/checks/errors/rust-readonly-check2.h67
-rw-r--r--gcc/rust/checks/errors/rust-unsafe-checker.cc18
-rw-r--r--gcc/rust/checks/errors/rust-unsafe-checker.h3
-rw-r--r--gcc/rust/checks/lints/rust-lint-unused-var.cc4
-rw-r--r--gcc/rust/expand/rust-cfg-strip.cc67
-rw-r--r--gcc/rust/expand/rust-cfg-strip.h2
-rw-r--r--gcc/rust/expand/rust-derive-clone.h10
-rw-r--r--gcc/rust/expand/rust-derive-cmp-common.cc191
-rw-r--r--gcc/rust/expand/rust-derive-cmp-common.h99
-rw-r--r--gcc/rust/expand/rust-derive-copy.h8
-rw-r--r--gcc/rust/expand/rust-derive-default.cc5
-rw-r--r--gcc/rust/expand/rust-derive-eq.cc17
-rw-r--r--gcc/rust/expand/rust-derive-eq.h10
-rw-r--r--gcc/rust/expand/rust-derive-hash.cc9
-rw-r--r--gcc/rust/expand/rust-derive-hash.h10
-rw-r--r--gcc/rust/expand/rust-derive-ord.cc323
-rw-r--r--gcc/rust/expand/rust-derive-ord.h122
-rw-r--r--gcc/rust/expand/rust-derive-partial-eq.cc147
-rw-r--r--gcc/rust/expand/rust-derive-partial-eq.h29
-rw-r--r--gcc/rust/expand/rust-derive.cc36
-rw-r--r--gcc/rust/expand/rust-derive.h8
-rw-r--r--gcc/rust/expand/rust-expand-format-args.cc6
-rw-r--r--gcc/rust/expand/rust-expand-visitor.cc41
-rw-r--r--gcc/rust/expand/rust-expand-visitor.h14
-rw-r--r--gcc/rust/expand/rust-macro-builtins-asm.cc70
-rw-r--r--gcc/rust/expand/rust-macro-builtins-asm.h32
-rw-r--r--gcc/rust/expand/rust-macro-builtins-format-args.cc11
-rw-r--r--gcc/rust/expand/rust-macro-builtins-helpers.cc7
-rw-r--r--gcc/rust/expand/rust-macro-builtins-helpers.h35
-rw-r--r--gcc/rust/expand/rust-macro-builtins-offset-of.cc78
-rw-r--r--gcc/rust/expand/rust-macro-builtins.cc3
-rw-r--r--gcc/rust/expand/rust-macro-builtins.h4
-rw-r--r--gcc/rust/expand/rust-macro-expand.cc66
-rw-r--r--gcc/rust/expand/rust-macro-substitute-ctx.cc3
-rw-r--r--gcc/rust/expand/rust-proc-macro.h6
-rw-r--r--gcc/rust/expand/rust-token-tree-desugar.cc4
-rw-r--r--gcc/rust/expand/rust-token-tree-desugar.h4
-rw-r--r--gcc/rust/hir/rust-ast-lower-base.cc60
-rw-r--r--gcc/rust/hir/rust-ast-lower-base.h14
-rw-r--r--gcc/rust/hir/rust-ast-lower-block.h2
-rw-r--r--gcc/rust/hir/rust-ast-lower-expr.cc91
-rw-r--r--gcc/rust/hir/rust-ast-lower-expr.h7
-rw-r--r--gcc/rust/hir/rust-ast-lower-extern.h2
-rw-r--r--gcc/rust/hir/rust-ast-lower-implitem.cc22
-rw-r--r--gcc/rust/hir/rust-ast-lower-item.cc34
-rw-r--r--gcc/rust/hir/rust-ast-lower-item.h1
-rw-r--r--gcc/rust/hir/rust-ast-lower-pattern.cc57
-rw-r--r--gcc/rust/hir/rust-ast-lower-type.cc62
-rw-r--r--gcc/rust/hir/rust-ast-lower-type.h13
-rw-r--r--gcc/rust/hir/rust-ast-lower.cc6
-rw-r--r--gcc/rust/hir/rust-ast-lower.h8
-rw-r--r--gcc/rust/hir/rust-hir-dump.cc126
-rw-r--r--gcc/rust/hir/rust-hir-dump.h6
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr-abstract.h5
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr.cc124
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr.h206
-rw-r--r--gcc/rust/hir/tree/rust-hir-full-decls.h4
-rw-r--r--gcc/rust/hir/tree/rust-hir-generic-param.h4
-rw-r--r--gcc/rust/hir/tree/rust-hir-item.cc9
-rw-r--r--gcc/rust/hir/tree/rust-hir-item.h22
-rw-r--r--gcc/rust/hir/tree/rust-hir-path.h16
-rw-r--r--gcc/rust/hir/tree/rust-hir-pattern.h18
-rw-r--r--gcc/rust/hir/tree/rust-hir-visibility.h2
-rw-r--r--gcc/rust/hir/tree/rust-hir-visitor.cc1187
-rw-r--r--gcc/rust/hir/tree/rust-hir-visitor.h316
-rw-r--r--gcc/rust/hir/tree/rust-hir.cc64
-rw-r--r--gcc/rust/lang.opt6
-rw-r--r--gcc/rust/lex/rust-lex.cc19
-rw-r--r--gcc/rust/lex/rust-lex.h3
-rw-r--r--gcc/rust/lex/rust-token.cc11
-rw-r--r--gcc/rust/lex/rust-token.h25
-rw-r--r--gcc/rust/metadata/rust-export-metadata.cc3
-rw-r--r--gcc/rust/metadata/rust-import-archive.cc2
-rw-r--r--gcc/rust/metadata/rust-imports.h3
-rw-r--r--gcc/rust/parse/rust-cfg-parser.h7
-rw-r--r--gcc/rust/parse/rust-parse-impl-lexer.cc (renamed from gcc/rust/ast/rust-macro.cc)8
-rw-r--r--gcc/rust/parse/rust-parse-impl-macro.cc26
-rw-r--r--gcc/rust/parse/rust-parse-impl-proc-macro.cc34
-rw-r--r--gcc/rust/parse/rust-parse-impl.h627
-rw-r--r--gcc/rust/parse/rust-parse.cc46
-rw-r--r--gcc/rust/parse/rust-parse.h39
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-base.cc26
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-base.h10
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-expr.cc38
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-expr.h2
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-item.cc37
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-item.h3
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-pattern.cc57
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-stmt.h3
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-type.cc11
-rw-r--r--gcc/rust/resolve/rust-ast-resolve.cc3
-rw-r--r--gcc/rust/resolve/rust-default-resolver.cc323
-rw-r--r--gcc/rust/resolve/rust-default-resolver.h16
-rw-r--r--gcc/rust/resolve/rust-early-name-resolver-2.0.cc58
-rw-r--r--gcc/rust/resolve/rust-early-name-resolver-2.0.h14
-rw-r--r--gcc/rust/resolve/rust-early-name-resolver.cc2
-rw-r--r--gcc/rust/resolve/rust-early-name-resolver.h2
-rw-r--r--gcc/rust/resolve/rust-finalize-imports-2.0.cc29
-rw-r--r--gcc/rust/resolve/rust-finalize-imports-2.0.h7
-rw-r--r--gcc/rust/resolve/rust-forever-stack.h15
-rw-r--r--gcc/rust/resolve/rust-forever-stack.hxx264
-rw-r--r--gcc/rust/resolve/rust-late-name-resolver-2.0.cc229
-rw-r--r--gcc/rust/resolve/rust-late-name-resolver-2.0.h13
-rw-r--r--gcc/rust/resolve/rust-name-resolution-context.cc116
-rw-r--r--gcc/rust/resolve/rust-name-resolution-context.h371
-rw-r--r--gcc/rust/resolve/rust-rib.h10
-rw-r--r--gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc165
-rw-r--r--gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h5
-rw-r--r--gcc/rust/rust-attribs.cc162
-rw-r--r--gcc/rust/rust-backend.h291
-rw-r--r--gcc/rust/rust-diagnostics.cc49
-rw-r--r--gcc/rust/rust-diagnostics.h21
-rw-r--r--gcc/rust/rust-gcc.cc124
-rw-r--r--gcc/rust/rust-lang.cc19
-rw-r--r--gcc/rust/rust-object-export.h13
-rw-r--r--gcc/rust/rust-session-manager.cc70
-rw-r--r--gcc/rust/rust-session-manager.h3
-rw-r--r--gcc/rust/rust-system.h6
-rw-r--r--gcc/rust/rust-target.h3
-rw-r--r--gcc/rust/typecheck/rust-autoderef.cc4
-rw-r--r--gcc/rust/typecheck/rust-casts.cc72
-rw-r--r--gcc/rust/typecheck/rust-casts.h10
-rw-r--r--gcc/rust/typecheck/rust-coercion.cc34
-rw-r--r--gcc/rust/typecheck/rust-hir-dot-operator.cc183
-rw-r--r--gcc/rust/typecheck/rust-hir-dot-operator.h35
-rw-r--r--gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h40
-rw-r--r--gcc/rust/typecheck/rust-hir-path-probe.cc8
-rw-r--r--gcc/rust/typecheck/rust-hir-path-probe.h16
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-reference.cc18
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-reference.h4
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-resolve.cc65
-rw-r--r--gcc/rust/typecheck/rust-hir-type-bounds.h6
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-base.cc128
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-base.h7
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-enumitem.cc91
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.cc356
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h12
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-implitem.cc56
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-item.cc164
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-item.h2
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-path.cc70
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-pattern.cc216
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-stmt.cc6
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-struct.cc5
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.cc107
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.cc36
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.h55
-rw-r--r--gcc/rust/typecheck/rust-substitution-mapper.cc8
-rw-r--r--gcc/rust/typecheck/rust-substitution-mapper.h6
-rw-r--r--gcc/rust/typecheck/rust-type-util.cc44
-rw-r--r--gcc/rust/typecheck/rust-type-util.h39
-rw-r--r--gcc/rust/typecheck/rust-typecheck-context.cc142
-rw-r--r--gcc/rust/typecheck/rust-tyty-bounds.cc155
-rw-r--r--gcc/rust/typecheck/rust-tyty-call.cc17
-rw-r--r--gcc/rust/typecheck/rust-tyty-call.h1
-rw-r--r--gcc/rust/typecheck/rust-tyty-cmp.h39
-rw-r--r--gcc/rust/typecheck/rust-tyty-subst.cc209
-rw-r--r--gcc/rust/typecheck/rust-tyty-subst.h28
-rw-r--r--gcc/rust/typecheck/rust-tyty-util.cc34
-rw-r--r--gcc/rust/typecheck/rust-tyty-util.h4
-rw-r--r--gcc/rust/typecheck/rust-tyty-variance-analysis-private.h2
-rw-r--r--gcc/rust/typecheck/rust-tyty-variance-analysis.cc7
-rw-r--r--gcc/rust/typecheck/rust-tyty-variance-analysis.h7
-rw-r--r--gcc/rust/typecheck/rust-tyty-visitor.h2
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc376
-rw-r--r--gcc/rust/typecheck/rust-tyty.h125
-rw-r--r--gcc/rust/typecheck/rust-unify.cc501
-rw-r--r--gcc/rust/typecheck/rust-unify.h4
-rw-r--r--gcc/rust/util/optional.h6
-rw-r--r--gcc/rust/util/rust-abi.h6
-rw-r--r--gcc/rust/util/rust-attribute-values.h7
-rw-r--r--gcc/rust/util/rust-attributes.cc13
-rw-r--r--gcc/rust/util/rust-attributes.h2
-rw-r--r--gcc/rust/util/rust-base62.h3
-rw-r--r--gcc/rust/util/rust-canonical-path.h13
-rw-r--r--gcc/rust/util/rust-dir-owner.h3
-rw-r--r--gcc/rust/util/rust-edition.h3
-rw-r--r--gcc/rust/util/rust-ggc.cc41
-rw-r--r--gcc/rust/util/rust-ggc.h63
-rw-r--r--gcc/rust/util/rust-hir-map.cc16
-rw-r--r--gcc/rust/util/rust-hir-map.h6
-rw-r--r--gcc/rust/util/rust-punycode.h6
-rw-r--r--gcc/rust/util/rust-token-converter.cc8
-rw-r--r--gcc/rust/util/rust-token-converter.h9
-rw-r--r--gcc/rust/util/rust-unicode.h27
-rw-r--r--gcc/rust/util/rust-unwrap-segment.h9
-rw-r--r--gcc/sarif-replay.cc13
-rw-r--r--gcc/testsuite/ChangeLog755
-rw-r--r--gcc/testsuite/c-c++-common/cpp/va-opt-6.c10
-rw-r--r--gcc/testsuite/c-c++-common/gomp/map-6.c20
-rw-r--r--gcc/testsuite/c-c++-common/gomp/target-map-iterators-1.c23
-rw-r--r--gcc/testsuite/c-c++-common/gomp/target-map-iterators-2.c41
-rw-r--r--gcc/testsuite/c-c++-common/gomp/target-map-iterators-3.c23
-rw-r--r--gcc/testsuite/c-c++-common/gomp/target-map-iterators-4.c18
-rw-r--r--gcc/testsuite/c-c++-common/gomp/target-update-iterators-1.c21
-rw-r--r--gcc/testsuite/c-c++-common/gomp/target-update-iterators-2.c23
-rw-r--r--gcc/testsuite/c-c++-common/gomp/target-update-iterators-3.c17
-rw-r--r--gcc/testsuite/g++.dg/DRs/dr1709.C18
-rw-r--r--gcc/testsuite/g++.dg/DRs/dr2578.C10
-rw-r--r--gcc/testsuite/g++.dg/DRs/dr2579.C9
-rw-r--r--gcc/testsuite/g++.dg/DRs/dr2580.C87
-rw-r--r--gcc/testsuite/g++.dg/cpp26/constexpr-new5.C43
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-using5.C19
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-using5a.C20
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-using6.C20
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic19.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic1a.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/cpp-21.C8
-rw-r--r--gcc/testsuite/gcc.dg/bitintext.h22
-rw-r--r--gcc/testsuite/gcc.dg/c23-attr-syntax-6.c4
-rw-r--r--gcc/testsuite/gcc.dg/cpp/paste12-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/paste12.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/paste14-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/cpp/paste14.c4
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-graphs-html.py2
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-html.c13
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-html.py69
-rw-r--r--gcc/testsuite/gcc.dg/plugin/plugin.exp1
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr121370.c25
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr121382.c23
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-105.c33
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-106.c33
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr59984.c4
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/acge_1.c104
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/acgt_1.c104
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/acle_1.c104
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/aclt_1.c104
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_1.c54
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_2.c106
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_4.c157
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_5.c52
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_6.c104
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_1.c140
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_2.c140
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_3.c169
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_4.c169
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_5.c74
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_6.c74
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_7.c52
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_8.c52
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_9.c104
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_1.c140
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_2.c140
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_3.c157
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_4.c157
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_5.c74
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_6.c74
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_7.c52
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_8.c52
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_9.c104
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_1.c140
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_2.c140
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_3.c157
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_4.c157
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_5.c74
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_6.c74
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_7.c52
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_8.c52
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_9.c104
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_1.c140
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_2.c140
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_3.c169
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_4.c169
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_5.c74
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_6.c74
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_7.c52
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_8.c52
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_9.c104
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpne_1.c140
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpne_2.c157
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpne_3.c74
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpne_4.c52
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpne_5.c104
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpuo_1.c104
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/dup_1.c47
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_13.c45
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_lane_9.c8
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/perm_2.c96
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/perm_3.c96
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/perm_4.c96
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/perm_5.c96
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/perm_6.c96
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/perm_7.c96
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/pnext_3.c130
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr121118_1.c16
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/rev_2.c27
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/unpkhi_1.c24
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/unpklo_1.c24
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_13.c130
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilelt_6.c130
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/pred_clobber_1.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/pred_clobber_2.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/pred_clobber_3.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve2/acle/general/match_4.c30
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve2/acle/general/nmatch_1.c30
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilege_1.c130
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilegt_1.c130
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilerw_5.c130
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilewr_5.c130
-rw-r--r--gcc/testsuite/gcc.target/avr/torture/pr118591-1.c2
-rw-r--r--gcc/testsuite/gcc.target/avr/torture/pr118591-2.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr120941-1.c49
-rw-r--r--gcc/testsuite/gcc.target/i386/pr121303.c26
-rw-r--r--gcc/testsuite/gcc.target/i386/pr121410.c11
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u32-from-u64.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u64-from-u128.c1
-rw-r--r--gcc/testsuite/gfortran.dg/pointer_assign_16.f9025
-rw-r--r--gcc/testsuite/gfortran.dg/pr121234.f9028
-rw-r--r--gcc/testsuite/lib/rust.exp5
-rw-r--r--gcc/testsuite/libgdiagnostics.dg/test-multiple-lines.c1
-rw-r--r--gcc/testsuite/rust/compile/additional-trait-bounds2nr2.rs2
-rw-r--r--gcc/testsuite/rust/compile/all-cast.rs2
-rw-r--r--gcc/testsuite/rust/compile/arrays2.rs3
-rw-r--r--gcc/testsuite/rust/compile/auto_traits2.rs2
-rw-r--r--gcc/testsuite/rust/compile/bad-rpit1.rs26
-rw-r--r--gcc/testsuite/rust/compile/bug-with-default-generic.rs15
-rw-r--r--gcc/testsuite/rust/compile/const3.rs2
-rw-r--r--gcc/testsuite/rust/compile/const_generics_10.rs32
-rw-r--r--gcc/testsuite/rust/compile/const_generics_11.rs14
-rw-r--r--gcc/testsuite/rust/compile/const_generics_12.rs14
-rw-r--r--gcc/testsuite/rust/compile/const_generics_13.rs11
-rw-r--r--gcc/testsuite/rust/compile/const_generics_14.rs13
-rw-r--r--gcc/testsuite/rust/compile/const_generics_15.rs16
-rw-r--r--gcc/testsuite/rust/compile/const_generics_16.rs10
-rw-r--r--gcc/testsuite/rust/compile/const_generics_3.rs25
-rw-r--r--gcc/testsuite/rust/compile/const_generics_5.rs4
-rw-r--r--gcc/testsuite/rust/compile/const_generics_8.rs7
-rw-r--r--gcc/testsuite/rust/compile/const_generics_9.rs13
-rw-r--r--gcc/testsuite/rust/compile/deferred_const_inference.rs7
-rw-r--r--gcc/testsuite/rust/compile/derive-debug1.rs6
-rw-r--r--gcc/testsuite/rust/compile/derive_macro1.rs2
-rw-r--r--gcc/testsuite/rust/compile/derive_partial_ord1.rs464
-rw-r--r--gcc/testsuite/rust/compile/enum_variant_name.rs2
-rw-r--r--gcc/testsuite/rust/compile/format_args_basic_expansion.rs1
-rw-r--r--gcc/testsuite/rust/compile/format_args_extra_comma.rs1
-rw-r--r--gcc/testsuite/rust/compile/generics8.rs2
-rw-r--r--gcc/testsuite/rust/compile/generics9.rs1
-rw-r--r--gcc/testsuite/rust/compile/glob_import_enum.rs16
-rw-r--r--gcc/testsuite/rust/compile/impl_trait_diag.rs17
-rw-r--r--gcc/testsuite/rust/compile/impl_trait_generic_arg.rs24
-rw-r--r--gcc/testsuite/rust/compile/invalid_label_name.rs1
-rw-r--r--gcc/testsuite/rust/compile/issue-1048.rs8
-rw-r--r--gcc/testsuite/rust/compile/issue-1485.rs16
-rw-r--r--gcc/testsuite/rust/compile/issue-1487.rs15
-rw-r--r--gcc/testsuite/rust/compile/issue-2015.rs3
-rw-r--r--gcc/testsuite/rust/compile/issue-2043.rs1
-rw-r--r--gcc/testsuite/rust/compile/issue-2166.rs2
-rw-r--r--gcc/testsuite/rust/compile/issue-2238.rs1
-rw-r--r--gcc/testsuite/rust/compile/issue-2680.rs6
-rw-r--r--gcc/testsuite/rust/compile/issue-2907.rs1
-rw-r--r--gcc/testsuite/rust/compile/issue-3144.rs29
-rw-r--r--gcc/testsuite/rust/compile/issue-3304.rs1
-rw-r--r--gcc/testsuite/rust/compile/issue-3454.rs20
-rw-r--r--gcc/testsuite/rust/compile/issue-3524.rs9
-rw-r--r--gcc/testsuite/rust/compile/issue-3525.rs6
-rw-r--r--gcc/testsuite/rust/compile/issue-3546.rs16
-rw-r--r--gcc/testsuite/rust/compile/issue-3551.rs15
-rw-r--r--gcc/testsuite/rust/compile/issue-3599.rs8
-rw-r--r--gcc/testsuite/rust/compile/issue-3618.rs2
-rw-r--r--gcc/testsuite/rust/compile/issue-3642.rs9
-rw-r--r--gcc/testsuite/rust/compile/issue-3660.rs3
-rw-r--r--gcc/testsuite/rust/compile/issue-3661.rs10
-rw-r--r--gcc/testsuite/rust/compile/issue-3671.rs2
-rw-r--r--gcc/testsuite/rust/compile/issue-3836.rs67
-rw-r--r--gcc/testsuite/rust/compile/issue-3874.rs4
-rw-r--r--gcc/testsuite/rust/compile/issue-3876.rs8
-rw-r--r--gcc/testsuite/rust/compile/issue-3885.rs7
-rw-r--r--gcc/testsuite/rust/compile/issue-3915.rs28
-rw-r--r--gcc/testsuite/rust/compile/issue-3916.rs36
-rw-r--r--gcc/testsuite/rust/compile/issue-3960.rs7
-rw-r--r--gcc/testsuite/rust/compile/issue-3978.rs8
-rw-r--r--gcc/testsuite/rust/compile/issue-4006.rs13
-rw-r--r--gcc/testsuite/rust/compile/loop_constant_context.rs5
-rw-r--r--gcc/testsuite/rust/compile/macros/builtin/recurse2.rs2
-rw-r--r--gcc/testsuite/rust/compile/macros/mbe/macro-issue3708.rs2
-rw-r--r--gcc/testsuite/rust/compile/macros/mbe/macro-issue3709-2.rs2
-rw-r--r--gcc/testsuite/rust/compile/macros/mbe/meta-param.rs7
-rw-r--r--gcc/testsuite/rust/compile/match-identifierpattern-enum.rs12
-rw-r--r--gcc/testsuite/rust/compile/match-identifierpattern.rs9
-rw-r--r--gcc/testsuite/rust/compile/match-restpattern-tuple-1.rs8
-rw-r--r--gcc/testsuite/rust/compile/match-restpattern-tuple-2.rs8
-rw-r--r--gcc/testsuite/rust/compile/match-slicepattern-array.rs8
-rw-r--r--gcc/testsuite/rust/compile/match-slicepattern-slice.rs10
-rw-r--r--gcc/testsuite/rust/compile/match-tuplestructpattern.rs9
-rw-r--r--gcc/testsuite/rust/compile/min_specialization1.rs2
-rw-r--r--gcc/testsuite/rust/compile/name_resolution10.rs2
-rw-r--r--gcc/testsuite/rust/compile/name_resolution11.rs2
-rw-r--r--gcc/testsuite/rust/compile/name_resolution12.rs2
-rw-r--r--gcc/testsuite/rust/compile/name_resolution13.rs2
-rw-r--r--gcc/testsuite/rust/compile/name_resolution14.rs2
-rw-r--r--gcc/testsuite/rust/compile/name_resolution15.rs1
-rw-r--r--gcc/testsuite/rust/compile/name_resolution16.rs1
-rw-r--r--gcc/testsuite/rust/compile/name_resolution17.rs2
-rw-r--r--gcc/testsuite/rust/compile/name_resolution18.rs2
-rw-r--r--gcc/testsuite/rust/compile/name_resolution2.rs2
-rw-r--r--gcc/testsuite/rust/compile/name_resolution20.rs2
-rw-r--r--gcc/testsuite/rust/compile/name_resolution22.rs1
-rw-r--r--gcc/testsuite/rust/compile/name_resolution23.rs2
-rw-r--r--gcc/testsuite/rust/compile/name_resolution24.rs2
-rw-r--r--gcc/testsuite/rust/compile/name_resolution25.rs2
-rw-r--r--gcc/testsuite/rust/compile/name_resolution4.rs2
-rw-r--r--gcc/testsuite/rust/compile/name_resolution6.rs2
-rw-r--r--gcc/testsuite/rust/compile/name_resolution7.rs2
-rw-r--r--gcc/testsuite/rust/compile/name_resolution8.rs2
-rw-r--r--gcc/testsuite/rust/compile/name_resolution9.rs2
-rw-r--r--gcc/testsuite/rust/compile/nested_macro_definition.rs2
-rw-r--r--gcc/testsuite/rust/compile/nr2/compile.exp149
-rw-r--r--gcc/testsuite/rust/compile/nr2/exclude17
-rw-r--r--gcc/testsuite/rust/compile/offset_of1.rs11
-rw-r--r--gcc/testsuite/rust/compile/offset_of2.rs9
-rw-r--r--gcc/testsuite/rust/compile/parse_simple_path_fail_1.rs3
-rw-r--r--gcc/testsuite/rust/compile/parse_simple_path_fail_2.rs9
-rw-r--r--gcc/testsuite/rust/compile/pub_restricted_1.rs6
-rw-r--r--gcc/testsuite/rust/compile/pub_restricted_2.rs8
-rw-r--r--gcc/testsuite/rust/compile/same_field_name.rs (renamed from gcc/testsuite/rust/execute/same_field_name.rs)2
-rw-r--r--gcc/testsuite/rust/compile/self-in-impl.rs15
-rw-r--r--gcc/testsuite/rust/compile/self_import_namespace.rs2
-rw-r--r--gcc/testsuite/rust/compile/silly-order-bug.rs8
-rw-r--r--gcc/testsuite/rust/compile/slicepattern-size-mismatch.rs8
-rw-r--r--gcc/testsuite/rust/compile/torture/extern_mod2.rs6
-rw-r--r--gcc/testsuite/rust/compile/torture/generics29.rs1
-rw-r--r--gcc/testsuite/rust/compile/torture/generics30.rs1
-rw-r--r--gcc/testsuite/rust/compile/torture/traits3.rs1
-rw-r--r--gcc/testsuite/rust/compile/torture/traits7.rs1
-rw-r--r--gcc/testsuite/rust/compile/torture/unended-raw-byte-string.rs6
-rw-r--r--gcc/testsuite/rust/compile/traits9.rs3
-rw-r--r--gcc/testsuite/rust/compile/try_block1.rs89
-rw-r--r--gcc/testsuite/rust/compile/tuple_mismatch.rs1
-rw-r--r--gcc/testsuite/rust/compile/unify-errors1.rs49
-rw-r--r--gcc/testsuite/rust/compile/use_1.rs1
-rw-r--r--gcc/testsuite/rust/compile/usize1.rs2
-rw-r--r--gcc/testsuite/rust/compile/while_let1.rs109
-rw-r--r--gcc/testsuite/rust/compile/while_let_without_label.rs11
-rw-r--r--gcc/testsuite/rust/compile/xfail/name_resolution21.rs2
-rw-r--r--gcc/testsuite/rust/execute/black_box.rs3
-rw-r--r--gcc/testsuite/rust/execute/execute.exp33
-rw-r--r--gcc/testsuite/rust/execute/inline_asm_inout_ident.rs23
-rw-r--r--gcc/testsuite/rust/execute/inline_asm_inout_var.rs24
-rw-r--r--gcc/testsuite/rust/execute/torture/basic_partial_ord1.rs189
-rw-r--r--gcc/testsuite/rust/execute/torture/basic_partial_ord2.rs197
-rw-r--r--gcc/testsuite/rust/execute/torture/builtin_abort.rs2
-rw-r--r--gcc/testsuite/rust/execute/torture/const-generics-1.rs24
-rw-r--r--gcc/testsuite/rust/execute/torture/const_block1.rs9
-rw-r--r--gcc/testsuite/rust/execute/torture/derive-partialeq2.rs80
-rw-r--r--gcc/testsuite/rust/execute/torture/for-loop1.rs38
-rw-r--r--gcc/testsuite/rust/execute/torture/for-loop2.rs38
-rw-r--r--gcc/testsuite/rust/execute/torture/impl_desugar-2.rs32
-rw-r--r--gcc/testsuite/rust/execute/torture/impl_desugar.rs32
-rw-r--r--gcc/testsuite/rust/execute/torture/impl_rpit1.rs28
-rw-r--r--gcc/testsuite/rust/execute/torture/impl_rpit2.rs36
-rw-r--r--gcc/testsuite/rust/execute/torture/impl_rpit3.rs25
-rw-r--r--gcc/testsuite/rust/execute/torture/impl_trait1.rs31
-rw-r--r--gcc/testsuite/rust/execute/torture/impl_trait2.rs31
-rw-r--r--gcc/testsuite/rust/execute/torture/impl_trait3.rs45
-rw-r--r--gcc/testsuite/rust/execute/torture/impl_trait4.rs31
-rw-r--r--gcc/testsuite/rust/execute/torture/issue-1481.rs35
-rw-r--r--gcc/testsuite/rust/execute/torture/issue-1482.rs23
-rw-r--r--gcc/testsuite/rust/execute/torture/issue-2005.rs465
-rw-r--r--gcc/testsuite/rust/execute/torture/issue-3836.rs454
-rw-r--r--gcc/testsuite/rust/execute/torture/iter1.rs38
-rw-r--r--gcc/testsuite/rust/execute/torture/match-identifierpattern.rs10
-rw-r--r--gcc/testsuite/rust/execute/torture/match-restpattern-tuple.rs27
-rw-r--r--gcc/testsuite/rust/execute/torture/match-slicepattern-array-1.rs23
-rw-r--r--gcc/testsuite/rust/execute/torture/match-slicepattern-slice-1.rs24
-rw-r--r--gcc/testsuite/rust/execute/torture/match-tuplestructpattern.rs12
-rw-r--r--gcc/testsuite/rust/execute/torture/min_specialization2.rs2
-rw-r--r--gcc/testsuite/rust/execute/torture/name_resolution.rs1
-rw-r--r--gcc/testsuite/rust/execute/torture/offset_of1.rs16
-rw-r--r--gcc/testsuite/rust/execute/torture/partial-eq-1.rs103
-rw-r--r--gcc/testsuite/rust/execute/torture/partial-eq-2.rs60
-rw-r--r--gcc/testsuite/rust/execute/torture/partial-eq-3.rs457
-rw-r--r--gcc/testsuite/rust/execute/torture/partial-eq-4.rs457
-rw-r--r--gcc/testsuite/rust/execute/torture/partial-ord-1.rs101
-rw-r--r--gcc/testsuite/rust/execute/torture/partial-ord-2.rs469
-rw-r--r--gcc/testsuite/rust/execute/torture/partial-ord-3.rs489
-rw-r--r--gcc/testsuite/rust/execute/torture/partial-ord-4.rs115
-rw-r--r--gcc/testsuite/rust/execute/torture/partial-ord-5.rs487
-rw-r--r--gcc/testsuite/rust/execute/torture/partial-ord-6.rs518
-rw-r--r--gcc/testsuite/rust/execute/torture/sip-hasher.rs438
-rw-r--r--gcc/testsuite/rust/execute/torture/struct-pattern-match.rs13
-rw-r--r--gcc/testsuite/rust/execute/torture/struct_pattern1.rs19
-rw-r--r--gcc/testsuite/rust/execute/torture/trait10.rs1
-rw-r--r--gcc/testsuite/rust/execute/torture/trait11.rs1
-rw-r--r--gcc/testsuite/rust/execute/torture/trait12.rs1
-rw-r--r--gcc/testsuite/rust/execute/torture/trait13.rs1
-rw-r--r--gcc/testsuite/rust/execute/torture/trait9.rs1
-rw-r--r--gcc/testsuite/rust/execute/xfail/match-identifierpattern-enum.rs15
-rw-r--r--gcc/testsuite/sarif-replay.dg/2.1.0-valid/embedded-links-check-html.py2
-rw-r--r--gcc/testsuite/sarif-replay.dg/2.1.0-valid/graphs-check-html.py2
-rw-r--r--gcc/testsuite/sarif-replay.dg/2.1.0-valid/nested-diagnostics-1.sarif164
-rw-r--r--gcc/toplev.cc8
-rw-r--r--gcc/tree-nested.cc7
-rw-r--r--gcc/tree-pretty-print.cc24
-rw-r--r--gcc/tree-scalar-evolution.cc11
-rw-r--r--gcc/tree-ssa-loop-ivopts.cc20
-rw-r--r--gcc/tree-ssa-sccvn.cc108
-rw-r--r--gcc/tree-vect-data-refs.cc11
-rw-r--r--gcc/tree-vect-loop.cc13
-rw-r--r--gcc/tree-vect-slp.cc353
-rw-r--r--gcc/tree-vect-stmts.cc10
-rw-r--r--gcc/tree-vectorizer.cc2
-rw-r--r--gcc/tree-vectorizer.h28
-rw-r--r--gcc/tree.cc9
-rw-r--r--gcc/tree.h10
723 files changed, 35773 insertions, 7768 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index fec8c7a..d975768 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,463 @@
+2025-08-05 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/121410
+ * config/i386/i386-expand.cc (ix86_expand_set_or_cpymem): Use
+ STORE_MAX_PIECES to get the widest vector mode in vector loop
+ for memset.
+
+2025-08-05 Georg-Johann Lay <avr@gjlay.de>
+
+ * config/avr/avr.cc (avr_rtx_costs_1) [SIGN_EXTEND]: Adjust cost.
+ * config/avr/avr.md (*sext.ashift<QIPSI:mode><HISI:mode>2): New
+ insn and a cc split.
+
+2025-08-05 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR target/121306
+ * config/i386/predicates.md (extract_operator): Replace with...
+ (extract_high_operator): ...this new predicate.
+ * config/i386/i386.md (*cmpqi_ext<mode>_1, *cmpqi_ext<mode>_2)
+ (*cmpqi_ext<mode>_3, *cmpqi_ext<mode>_4, *movstrictqi_ext<mode>_1)
+ (*extzv<mode>, *insvqi_2, *extendqi<SWI24:mode>_ext_1)
+ (*addqi_ext<mode>_1_slp, *addqi_ext<mode>_1_slp, *addqi_ext<mode>_0)
+ (*addqi_ext2<mode>_0, *addqi_ext<mode>_1, *<insn>qi_ext<mode>_2)
+ (*subqi_ext<mode>_1_slp, *subqi_ext<mode>_2_slp, *subqi_ext<mode>_0)
+ (*subqi_ext2<mode>_0, *subqi_ext<mode>_1, *testqi_ext<mode>_1)
+ (*testqi_ext<mode>_2, *<code>qi_ext<mode>_1_slp)
+ (*<code>qi_ext<mode>_2_slp. *<code>qi_ext<mode>_0)
+ (*<code>qi_ext2<mode>_0, *<code>qi_ext<mode>_1)
+ (*<code>qi_ext<mode>_1_cc, *<code>qi_ext<mode>_1_cc)
+ (*<code>qi_ext<mode>_2, *<code>qi_ext<mode>_3, *negqi_ext<mode>_1)
+ (*one_cmplqi_ext<mode>_1, *ashlqi_ext<mode>_1, *<insn>qi_ext<mode>_1)
+ (define_peephole2): Replace uses of extract_operator with
+ extract_high_operator, matching only the first operand.
+ Use zero_extract rather than match_op_dup when splitting.
+
+2025-08-05 Richard Biener <rguenther@suse.de>
+
+ * tree-vectorizer.h (vect_relevant::hybrid): Remove.
+ * tree-vect-loop.cc (vect_analyze_loop_2): Do not call
+ vect_detect_hybrid_slp.
+ * tree-vect-slp.cc (maybe_push_to_hybrid_worklist): Remove.
+ (vect_detect_hybrid_slp): Likewise.
+
+2025-08-05 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/121359
+ * config/avr/avr.h: Remove -mlra and remains of reload.
+ * config/avr/avr.cc: Same.
+ * config/avr/avr.md: Same.
+ * config/avr/avr-log.cc: Same.
+ * config/avr/avr-protos.h: Same.
+ * config/avr/avr.opt: Same.
+ * config/avr/avr.opt.urls: Same.
+
+2025-08-05 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/121306
+ * config/i386/i386.md (*one_cmplqi_ext<mode>_1): Updated to
+ support the new pattern.
+
+2025-08-05 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/121395
+ * tree-vectorizer.h (_loop_vec_info::alternate_defs): New member.
+ (LOOP_VINFO_ALTERNATE_DEFS): New.
+ * tree-vect-stmts.cc (vect_stmt_relevant_p): Populate it.
+ (vectorizable_simd_clone_call): Do not register a SLP def
+ when there is none.
+ * tree-vect-slp.cc (vect_build_slp_tree_1): Allow a NULL
+ vectype when there's no LHS. Allow all calls w/o LHS.
+ (vect_analyze_slp): Process LOOP_VINFO_ALTERNATE_DEFS as
+ SLP graph entries.
+ (vect_make_slp_decision): Handle a NULL SLP_TREE_VECTYPE.
+ (vect_slp_analyze_node_operations_1): Likewise.
+ (vect_schedule_slp_node): Likewise.
+
+2025-08-05 Richard Biener <rguenther@suse.de>
+
+ * tree-vectorizer.h (enum slp_vect_type): Rename loop_vect
+ to not_vect, clarify docs.
+ (HYBRID_SLP_STMT): Remove.
+ * tree-vectorizer.cc (vec_info::new_stmt_vec_info): Adjust.
+ * tree-vect-loop.cc (vect_analyze_loop_2): Likewise.
+
+2025-08-05 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-data-refs.cc (vect_get_data_access_cost): Use
+ ncopies == 1.
+ * tree-vect-slp.cc (vect_remove_slp_scalar_calls): Remove
+ hybrid/loop SLP skip.
+ * tree-vect-stmts.cc (vectorizable_store): Remove pure SLP assert.
+
+2025-08-05 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/121382
+ * tree-ssa-loop-ivopts.cc (create_new_iv): Rewrite the IV
+ step to defined form.
+
+2025-08-05 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/121370
+ * tree-scalar-evolution.cc (scev_dfs::add_to_evolution_1):
+ Avoid UB integer overflow in accumulating CHREC_RIGHT.
+
+2025-08-05 Yang Yujie <yangyujie@loongson.cn>
+
+ * expr.cc (expand_expr_real_1): Do not call
+ reduce_to_bit_field_precision if the target assumes the _BitInt
+ results to be already extended.
+ (EXTEND_BITINT): Same.
+ * expr.h (bitint_extended): Declare the cache variable.
+ * function.cc (prepare_function_start): Initialize it.
+
+2025-08-05 Yang Yujie <yangyujie@loongson.cn>
+
+ * explow.cc (promote_function_mode): Add a case for
+ small/medium _BitInts.
+ (promote_mode): Same.
+
+2025-08-05 Gerald Pfeifer <gerald@pfeifer.com>
+
+ PR target/69374
+ * doc/install.texi (Configuration): Mark up atexit as code.
+
+2025-08-05 Pan Li <pan2.li@intel.com>
+
+ * config/riscv/riscv.cc (riscv_expand_xmode_usmul): Take
+ umulhu for high bits mul result.
+
+2025-08-04 Hans-Peter Nilsson <hp@bitrange.com>
+
+ * defaults.h (MAX_FIXED_MODE_SIZE): Default to 2 * BITS_PER_WORD
+ for larger-than-32-bitters.
+ * doc/tm.texi.in (MAX_FIXED_MODE_SIZE): Adjust accordingly. Tweak
+ wording.
+ * doc/tm.texi: Regenerate.
+
+2025-08-04 David Malcolm <dmalcolm@redhat.com>
+
+ * dump-context.h: Convert "enum optinfo_item_kind" into
+ "enum class kind" within class optinfo_item.
+ * dumpfile.cc: Likewise. Use "auto" in a few places.
+ Convert "enum optinfo_kind" to "enum class kind" within
+ class optinfo.
+ * opt-problem.cc: Likewise.
+ * optinfo-emit-json.cc: Likewise.
+ * optinfo.cc: Likewise.
+ * optinfo.h: Likewise.
+
+2025-08-04 David Malcolm <dmalcolm@redhat.com>
+
+ PR diagnostics/116253
+ * diagnostics/context.cc (context::set_nesting_level): New.
+ * diagnostics/context.h (context::set_nesting_level): New decl.
+ * doc/libgdiagnostics/topics/compatibility.rst
+ (LIBGDIAGNOSTICS_ABI_5): New.
+ * doc/libgdiagnostics/topics/physical-locations.rst
+ (diagnostic_manager_set_debug_physical_locations): New.
+ * libgdiagnostics++.h (manager::set_debug_physical_locations):
+ New.
+ * libgdiagnostics-private.h
+ (private_diagnostic_set_nesting_level): New decl.
+ * libgdiagnostics.cc (diagnostic_manager::diagnostic_manager):
+ Initialize m_debug_physical_locations.
+ (diagnostic_manager::new_location_from_file_and_line): Add debug
+ printing.
+ (diagnostic_manager::new_location_from_file_line_column):
+ Likewise.
+ (diagnostic_manager::new_location_from_range): Likewise.
+ (diagnostic_manager::set_debug_physical_locations): New.
+ (diagnostic_manager::ensure_linemap_for_file_and_line): Avoid
+ redundant calls to linemap_add.
+ (diagnostic_manager::new_location): Add debug printing.
+ (diagnostic_manager::m_debug_physical_locations): New field.
+ (diagnostic::diagnostic): Initialize m_nesting_level.
+ (diagnostic::get_nesting_level): New accessor.
+ (diagnostic::set_nesting_level): New.
+ (diagnostic::m_nesting_level): New field.
+ (diagnostic_manager::emit_va): Set and reset the nesting level
+ of the context from that of the diagnostic.
+ (diagnostic_manager_set_debug_physical_locations): New.
+ (private_diagnostic_set_nesting_level): New.
+ * libgdiagnostics.h
+ (diagnostic_manager_set_debug_physical_locations): New decl.
+ * libgdiagnostics.map (LIBGDIAGNOSTICS_ABI_5): New.
+ * libsarifreplay.cc (sarif_replayer::handle_result_obj): Support
+ the "nestingLevel" property.
+ * libsarifreplay.h (replay_options::m_debug_physical_locations):
+ New field.
+ * sarif-replay.cc: Add -fdebug-physical-locations.
+
+2025-08-04 David Malcolm <dmalcolm@redhat.com>
+
+ PR diagnostics/116792
+ * diagnostics/html-sink.cc
+ (html_builder::make_element_for_diagnostic): Don't add the
+ metadata element if it's empty.
+ (html_builder::make_element_for_metadata): Return null rather than
+ an empty element.
+
+2025-08-04 David Malcolm <dmalcolm@redhat.com>
+
+ * diagnostics/context.h: Move struct counters to its own header
+ and include it.
+ * diagnostics/counters.h: New file, from the above.
+
+2025-08-04 David Malcolm <dmalcolm@redhat.com>
+
+ * diagnostics/context.h: Split struct source_printing_options out
+ into "diagnostics/source-printing-options.h" and include it.
+ * diagnostics/source-printing-options.h: New file, from the above.
+
+2025-08-04 David Malcolm <dmalcolm@redhat.com>
+
+ * diagnostics/context.cc: Update for renaming of option_manager to
+ option_id_manager and of context::m_option_mgr to
+ context::m_option_id_mgr.
+ * diagnostics/context.h: Likewise, moving class declaration to a
+ new diagnostics/option-id-manager.h.
+ * diagnostics/lazy-paths.cc: Likewise.
+ * diagnostics/option-id-manager.h: New file, from material in
+ diagnostics/context.h.
+ * lto-wrapper.cc: Update for renaming of option_manager to
+ option_id_manager.
+ * opts-common.cc: Likewise.
+ * opts-diagnostic.h: Likewise.
+ * opts.cc: Likewise.
+ * toplev.cc: Likewise.
+
+2025-08-04 David Malcolm <dmalcolm@redhat.com>
+
+ * diagnostics/buffering.h: Update comment to refer to output sinks
+ rather than output formats.
+
+2025-08-04 David Malcolm <dmalcolm@redhat.com>
+
+ * gimple-warn-recursion.cc (pass_warn_recursion::execute): Add
+ missing auto_diagnostic_group.
+
+2025-08-04 Konstantinos Eleftheriou <konstantinos.eleftheriou@vrull.eu>
+
+ PR rtl-optimization/121303
+ * avoid-store-forwarding.cc (is_store_forwarding): Add check
+ for `off_val` in `is_store_forwarding`.
+
+2025-08-04 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-slp.cc (vect_analyze_slp): When analyzing a loop
+ and slp instance discovery fails, immediately fail the whole
+ process.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/aarch64/aarch64-sve-builtins.cc
+ (function_expander::expand): Assert that the return value
+ has an appropriate mode.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/aarch64/aarch64-protos.h
+ (aarch64_convert_sve_data_to_pred): Remove the mode argument.
+ * config/aarch64/aarch64.cc
+ (aarch64_sve_emit_int_cmp): Allow PRED_MODE to be VNx16BI or
+ the natural predicate mode for the data mode.
+ (aarch64_convert_sve_data_to_pred): Remove the mode argument
+ and instead always create a VNx16BI result.
+ (aarch64_expand_sve_const_pred): Update call accordingly.
+ * config/aarch64/aarch64-sve-builtins-base.cc
+ (svdupq_impl::expand): Likewise, ensuring that the result
+ has mode VNx16BI.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/aarch64/aarch64-protos.h
+ (aarch64_emit_sve_pred_vec_duplicate): Declare.
+ * config/aarch64/aarch64.cc
+ (aarch64_emit_sve_pred_vec_duplicate): New function.
+ * config/aarch64/aarch64-sve.md (vec_duplicate<PRED_ALL:mode>): Use it.
+ * config/aarch64/aarch64-sve-builtins-base.cc
+ (svdup_impl::expand): Handle boolean values specially. Check for
+ constants and fall back on aarch64_emit_sve_pred_vec_duplicate
+ for the variable case, ensuring that the result has mode VNx16BI.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/aarch64/iterators.md (PNEXT_ONLY): New int iterator.
+ * config/aarch64/aarch64-sve.md
+ (@aarch64_sve_<sve_pred_op><mode>): Restrict SVE_PITER pattern
+ to VNx16BI_ONLY.
+ (@aarch64_sve_<sve_pred_op><mode>): New PNEXT_ONLY pattern for
+ PRED_HSD.
+ (*aarch64_sve_<sve_pred_op><mode>): Likewise.
+ (*aarch64_sve_<sve_pred_op><mode>_cc): Likewise.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/aarch64/aarch64-sve2.md (@aarch64_pred_<sve_int_op><mode>):
+ Split SVE2_MATCH pattern into a VNx16QI_ONLY define_ins and a
+ VNx8HI_ONLY define_expand. Use a VNx16BI destination for the latter.
+ (*aarch64_pred_<sve_int_op><mode>): New SVE2_MATCH pattern for
+ VNx8HI_ONLY.
+ (*aarch64_pred_<sve_int_op><mode>_cc): Likewise.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/aarch64/aarch64-sve.md (@aarch64_pred_fac<cmp_op><mode>):
+ Replace with...
+ (@aarch64_pred_fac<cmp_op><mode>_acle): ...this new expander.
+ (*aarch64_pred_fac<cmp_op><mode>_strict_acle): New pattern.
+ * config/aarch64/aarch64-sve-builtins-base.cc
+ (svac_impl::expand): Update accordingly.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/aarch64/aarch64-sve.md (@aarch64_pred_fcm<cmp_op><mode>_acle)
+ (*aarch64_pred_fcm<cmp_op><mode>_acle, @aarch64_pred_fcmuo<mode>_acle)
+ (*aarch64_pred_fcmuo<mode>_acle): New patterns.
+ * config/aarch64/aarch64-sve-builtins-base.cc
+ (svcmp_impl::expand, svcmpuo_impl::expand): Use them.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/aarch64/aarch64-sve.md (@aarch64_pred_cmp<cmp_op><mode>_wide):
+ Split into VNx16QI_ONLY and SVE_FULL_HSI patterns. Use VNx16BI
+ results for both.
+ (*aarch64_pred_cmp<cmp_op><mode>_wide): New pattern.
+ (*aarch64_pred_cmp<cmp_op><mode>_wide_cc): Likewise.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/aarch64/aarch64-sve.md
+ (*aarch64_pred_cmp<cmp_op><mode>_wide_cc): Turn into a
+ define_insn_and_rewrite and rewrite the governing predicate
+ of the comparison so that it is identical to the PTEST's.
+ (*aarch64_pred_cmp<cmp_op><mode>_wide_ptest): Likewise.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/aarch64/aarch64-sve.md (@aarch64_pred_cmp<cmp_op><mode>_wide)
+ (*aarch64_pred_cmp<cmp_op><mode>_wide_cc): Use <VPRED> instead of
+ VNx16BI for the governing predicate.
+ (*aarch64_pred_cmp<cmp_op><mode>_wide_ptest): Likewise.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/aarch64/aarch64-sve.md (@aarch64_pred_cmp<cmp_op><mode>_acle)
+ (*aarch64_pred_cmp<cmp_op><mode>_acle, *cmp<cmp_op><mode>_acle_cc)
+ (*cmp<cmp_op><mode>_acle_and): New patterns that yield VNx16BI
+ results for all element types.
+ * config/aarch64/aarch64-sve-builtins-base.cc
+ (svcmp_impl::expand): Use them.
+ (svcmp_wide_impl::expand): Likewise when implementing an svcmp_wide
+ against an in-range constant.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/aarch64/aarch64-sve.md (@aarch64_sve_punpk<perm_hilo>_acle)
+ (*aarch64_sve_punpk<perm_hilo>_acle): New patterns.
+ * config/aarch64/aarch64-sve-builtins-base.cc
+ (svunpk_impl::expand): Use them for boolean svunpk*.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR target/121294
+ * config/aarch64/aarch64.md (UNSPEC_REV_PRED): New unspec.
+ * config/aarch64/aarch64-sve.md (@aarch64_sve_rev<mode>_acle)
+ (*aarch64_sve_rev<mode>_acle): New patterns.
+ * config/aarch64/aarch64-sve-builtins-base.cc
+ (svrev_impl::expand): Use the new patterns for boolean svrev.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR target/121294
+ * config/aarch64/iterators.md (UNSPEC_TRN1_CONV): Delete.
+ (UNSPEC_PERMUTE_PRED): New unspec.
+ * config/aarch64/aarch64-sve.md (@aarch64_sve_trn1_conv<mode>):
+ Replace with...
+ (@aarch64_sve_<perm_insn><mode>_acle)
+ (*aarch64_sve_<perm_insn><mode>_acle): ...these new patterns.
+ * config/aarch64/aarch64.cc (aarch64_expand_sve_const_pred_trn):
+ Update accordingly.
+ * config/aarch64/aarch64-sve-builtins-functions.h
+ (binary_permute::expand): Use the new _acle patterns for
+ predicate operations.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR testsuite/121118
+ * config/aarch64/iterators.md (VNx16BI_ONLY): New mode iterator.
+ * config/aarch64/predicates.md (aarch64_ptrue_all_operand): New
+ predicate.
+ * config/aarch64/aarch64-sve.md
+ (@aarch64_sve_while_<while_optab_cmp><GPI:mode><VNx16BI_ONLY:mode>_acle)
+ (@aarch64_sve_while_<while_optab_cmp><GPI:mode><PRED_HSD:mode>_acle)
+ (*aarch64_sve_while_<while_optab_cmp><GPI:mode><PRED_HSD:mode>_acle)
+ (*while_<while_optab_cmp><GPI:mode><PRED_HSD:mode>_acle_cc): New
+ patterns.
+ * config/aarch64/aarch64-sve-builtins-functions.h
+ (while_comparison::expand): Use the new _acle patterns that
+ always return a VNx16BI.
+ * config/aarch64/aarch64-sve-builtins-sve2.cc
+ (svwhilerw_svwhilewr_impl::expand): Likewise.
+ * config/aarch64/aarch64.cc
+ (aarch64_sve_move_pred_via_while): Likewise.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR target/121293
+ * config/aarch64/aarch64-sve-builtins-base.cc (svdupq_lane::expand):
+ Use aarch64_sve_reinterpret instead of subregs. Explicitly
+ reinterpret the result back to the required mode, rather than
+ leaving the caller to take a subreg.
+
+2025-08-04 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/121362
+ * tree-ssa-sccvn.cc (vn_reference_lookup_3): Generalize
+ aggregate copy handling.
+
+2025-08-04 Filip Kastl <fkastl@suse.cz>
+
+ * doc/invoke.texi: Add remark about -options being documented
+ under -fdump-tree. Remove remark about -graph working only for
+ RTL.
+
+2025-08-04 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/120941
+ * config/i386/i386-features.cc (x86_cse_kind): Moved before
+ ix86_place_single_vector_set.
+ (redundant_load): Likewise.
+ (ix86_place_single_vector_set): Replace the last argument to the
+ pointer to redundant_load. For X86_CSE_VEC_DUP, don't place the
+ vector set outside of the loop to avoid extra spills.
+ (remove_redundant_vector_load): Pass load to
+ ix86_place_single_vector_set.
+
+2025-08-03 Georg-Johann Lay <avr@gjlay.de>
+
+ * config/avr/avr.md (define_insn_and_split) [reload_completed]:
+ For splits that just append a (clobber (reg:CC REG_CC)) to
+ the pattern, use avr_add_ccclobber (curr_insn) instead of
+ repeating the original pattern.
+ * config/avr/avr-dimode.md: Same.
+ * config/avr/avr-fixed.md: Same.
+
+2025-08-03 Georg-Johann Lay <avr@gjlay.de>
+
+ * config/avr/avr.cc (avr_add_ccclobber): New function.
+ * config/avr/avr-protos.h (avr_add_ccclobber): New proto.
+ (DONE_ADD_CCC): New define.
+
+2025-08-03 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/90242
+ * tree-ssa-sccvn.cc (vn_reference_compute_hash): Use
+ poly_offset_int for offset accumulation. For hashing
+ truncate to 64 bits and also hash 64 bits.
+ (vn_reference_eq): Likewise.
+
2025-08-02 Gerald Pfeifer <gerald@pfeifer.com>
PR target/69374
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 963d4c7..cf43af9 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20250803
+20250806
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 85464e3..063d6a7 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,118 @@
+2025-08-04 Viljar Indus <indus@adacore.com>
+
+ * contracts.adb: Use Is_Ignored_In_Codegen instead of just
+ using Is_Ignored.
+ * exp_ch6.adb: Likewise.
+ * exp_prag.adb: Likewise.
+ * exp_util.adb: Likewise.
+ * frontend.adb: Avoid removal of ignored nodes in GNATProve_Mode.
+ * gnat1drv.adb: Avoid forcing Assertions_Enabled in GNATProve_Mode.
+ * lib-writ.adb (Write_With_File_Names): Avoid early exit
+ with ignored entities in GNATProve_Mode.
+ * lib-xref.adb: Likewise.
+ * opt.adb: Remove check for Assertions_Enabled.
+ * sem_attr.adb: Use Is_Ignored_In_Codegen instead of Is_Ignored.
+ * sem_ch13.adb: Likewise. Additionally always add predicates in
+ GNATProve_Mode.
+ * sem_prag.adb: Likewise. Additionally remove modifications
+ to applied policies in GNATProve_Mode.
+ * sem_util.adb (Is_Ignored_In_Codegen): New function that overrides
+ Is_Ignored in GNATProve_Mode and Codepeer_Mode.
+ (Is_Ignored_Ghost_Pragma_In_Codegen): Likewise for
+ Is_Ignored_Ghost_Pragma.
+ (Is_Ignored_Ghost_Entity_In_Codegen): Likewise for
+ Is_Ignored_Ghost_Entity.
+ (Policy_In_List): Remove overriding of policies in GNATProve_Mode.
+ * sem_util.ads: Add specs for new functions.
+ * (Predicates_Enabled): Always generate predicates in
+ GNATProve_Mode.
+
+2025-08-04 Bob Duff <duff@adacore.com>
+
+ * treepr.adb (Print_Node_Ref): Protect against
+ Entity (N) being empty before calling
+ Compile_Time_Known_Value.
+
+2025-08-04 Viljar Indus <indus@adacore.com>
+
+ * sem_prag.adb (Validate_Compile_Time_Warning_Errors):
+ Check if the original compile time pragma was replaced and
+ validate the original node instead.
+
+2025-08-04 Viljar Indus <indus@adacore.com>
+
+ * sem_prag.adb (Validate_Compile_Time_Warning_Or_Error):
+ simplify the implementation.
+
+2025-08-04 Steve Baird <baird@adacore.com>
+
+ * exp_ch6.adb (Apply_Access_Discrims_Accessibility_Check): If the
+ accessibility level being checked is known statically, then
+ statically check it against the level of the function being
+ returned from.
+
+2025-08-04 Viljar Indus <indus@adacore.com>
+
+ * atree.adb: update references to Ghost_Mode.
+ * exp_ch3.adb: use a structure type to store all of the existing
+ ghost mode related state variables.
+ * exp_disp.adb: Likewise.
+ * exp_spark.adb: Likewise.
+ * exp_util.adb: Likewise.
+ * expander.adb: Likewise.
+ * freeze.adb: Likewise and replace references to existing ghost
+ mode variables.
+ * ghost.adb (Install_Ghost_Region): install the changes of
+ the region in to the new Ghost_Config structure.
+ (Restore_Ghost_Region): Use the new Ghost_Config instead.
+ In general replace all references to the existing ghost mode
+ variables with the new structure equivalent.
+ * ghost.ads (Restore_Ghost_Region): update the spec.
+ * opt.ads (Ghost_Config_Type): A new type that has two of the
+ previous ghost code related global variables as memembers -
+ Ghost_Mode and Ignored_Ghost_Region.
+ (Ghost_Config) New variable to store the previous Ghost_Mode and
+ Ignored_Ghost_Region info.
+ * rtsfind.adb: Replace references to existing ghost mode variables.
+ * sem.adb: Likewise.
+ * sem_ch12.adb: Likewise.
+ * sem_ch13.adb: Likewise.
+ * sem_ch3.adb: Likewise.
+ * sem_ch5.adb: Likewise.
+ * sem_ch6.adb: Likewise.
+ * sem_ch7.adb: Likewise.
+ * sem_prag.adb: Likewise.
+ * sem_util.adb: Likewise.
+
+2025-08-04 Steve Baird <baird@adacore.com>
+
+ * freeze.adb (Freeze_Profile): Do not emit a warning stating that
+ a formal parameter's size is 8 if the parameter's size is not 8.
+
+2025-08-04 Viljar Indus <indus@adacore.com>
+
+ * table.adb (Max): Move variable to the body and initialize
+ it with the same value as in the Init function.
+ * table.ads (Max): Likewise.
+
+2025-08-04 Bob Duff <duff@adacore.com>
+
+ * par.adb: Move and rewrite some comments.
+ (Util): Shared code and comments for dealing with
+ defining_identifier_lists.
+ * par-util.adb (Append): Shared code for appending
+ one identifier onto Defining_Identifiers.
+ (P_Def_Ids): Shared code for parsing a defining_identifier_list.
+ Unfortunately, this is not used in all cases, because some of
+ them mix in sophisticated error recovery, which we do not
+ modify here.
+ * par-ch12.adb (P_Formal_Object_Declarations):
+ Use Defining_Identifiers and related code.
+ * par-ch3.adb (P_Identifier_Declarations): Likewise.
+ (P_Known_Discriminant_Part_Opt): Likewise.
+ (P_Component_Items): Likewise.
+ * par-ch6.adb (P_Formal_Part): Likewise.
+
2025-07-31 Eric Botcazou <ebotcazou@gcc.gnu.org>
Revert:
diff --git a/gcc/ada/atree.adb b/gcc/ada/atree.adb
index 20ca189..0ff3d6e 100644
--- a/gcc/ada/atree.adb
+++ b/gcc/ada/atree.adb
@@ -1802,12 +1802,12 @@ package body Atree is
-- The Ghost node is created within a Ghost region
- if Ghost_Mode = Check then
+ if Ghost_Config.Ghost_Mode = Check then
if Nkind (N) in N_Entity then
Set_Is_Checked_Ghost_Entity (N);
end if;
- elsif Ghost_Mode = Ignore then
+ elsif Ghost_Config.Ghost_Mode = Ignore then
if Nkind (N) in N_Entity then
Set_Is_Ignored_Ghost_Entity (N);
end if;
diff --git a/gcc/ada/contracts.adb b/gcc/ada/contracts.adb
index 70e9487..7e4e4a2 100644
--- a/gcc/ada/contracts.adb
+++ b/gcc/ada/contracts.adb
@@ -2714,10 +2714,11 @@ package body Contracts is
procedure Append_Enabled_Item (Item : Node_Id; List : in out List_Id) is
begin
- -- Do not chain ignored or disabled pragmas
+ -- Do not chain ignored or disabled pragmas. Note that disabled
+ -- pragmas are also considered ignored.
if Nkind (Item) = N_Pragma
- and then (Is_Ignored (Item) or else Is_Disabled (Item))
+ and then Is_Ignored_In_Codegen (Item)
then
null;
diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb
index 6cf7c9c..00b3aae 100644
--- a/gcc/ada/exp_ch3.adb
+++ b/gcc/ada/exp_ch3.adb
@@ -9601,8 +9601,7 @@ package body Exp_Ch3 is
Def_Id : constant Entity_Id := Entity (N);
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
-- Save the Ghost-related attributes to restore on exit
Result : Boolean := False;
@@ -9956,13 +9955,13 @@ package body Exp_Ch3 is
end if;
end if;
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
return Result;
exception
when RE_Not_Available =>
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
return False;
end Freeze_Type;
diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb
index eb7422c..e877469 100644
--- a/gcc/ada/exp_ch6.adb
+++ b/gcc/ada/exp_ch6.adb
@@ -921,7 +921,8 @@ package body Exp_Ch6 is
-- in accessibility.adb (which can cause the extra formal parameter
-- needed for the check(s) generated here to be missing in the case
-- of a tagged result type); this is a workaround and can
- -- prevent generation of a required check.
+ -- prevent generation of a required check (or even a required
+ -- legality check - see "statically too deep" check below).
if No (Extra_Accessibility_Of_Result (Func)) then
return;
@@ -969,6 +970,15 @@ package body Exp_Ch6 is
Accessibility_Level (Discr_Exp, Level => Dynamic_Level);
Analyze (Discrim_Level);
+ if Nkind (Discrim_Level) = N_Integer_Literal
+ and then Intval (Discrim_Level) > Scope_Depth (Func)
+ then
+ Error_Msg_N
+ ("level of type of access discriminant value of "
+ & "return expression is statically too deep",
+ Enclosing_Declaration_Or_Statement (Exp));
+ end if;
+
Insert_Action (Exp,
Make_Raise_Program_Error (Loc,
Condition =>
@@ -8089,7 +8099,7 @@ package body Exp_Ch6 is
Get_Class_Wide_Pragma (Id, Pragma_Precondition);
begin
- if No (Prag) or else Is_Ignored (Prag) then
+ if No (Prag) or else Is_Ignored_In_Codegen (Prag) then
return;
end if;
diff --git a/gcc/ada/exp_disp.adb b/gcc/ada/exp_disp.adb
index 619ac40..1c09e20 100644
--- a/gcc/ada/exp_disp.adb
+++ b/gcc/ada/exp_disp.adb
@@ -4593,8 +4593,7 @@ package body Exp_Disp is
Name_TSD : constant Name_Id :=
New_External_Name (Tname, 'B', Suffix_Index => -1);
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
-- Save the Ghost-related attributes to restore on exit
AI : Elmt_Id;
@@ -6526,7 +6525,7 @@ package body Exp_Disp is
Register_CG_Node (Typ);
<<Leave>>
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
return Result;
end Make_DT;
diff --git a/gcc/ada/exp_prag.adb b/gcc/ada/exp_prag.adb
index 340f2dc..7ec963a 100644
--- a/gcc/ada/exp_prag.adb
+++ b/gcc/ada/exp_prag.adb
@@ -134,7 +134,9 @@ package body Exp_Prag is
-- Analyze_xxx_In_Decl_Part). The second part of the analysis will
-- not happen if the pragma is rewritten.
- if Assertion_Expression_Pragma (Prag_Id) and then Is_Ignored (N) then
+ if Assertion_Expression_Pragma (Prag_Id)
+ and then Is_Ignored_In_Codegen (N)
+ then
return;
-- Rewrite the pragma into a null statement when it is ignored using
@@ -143,7 +145,7 @@ package body Exp_Prag is
elsif Should_Ignore_Pragma_Sem (N)
or else (Prag_Id = Pragma_Default_Scalar_Storage_Order
- and then Ignore_Rep_Clauses)
+ and then Ignore_Rep_Clauses)
then
Rewrite (N, Make_Null_Statement (Sloc (N)));
return;
@@ -480,7 +482,7 @@ package body Exp_Prag is
begin
-- Nothing to do if pragma is ignored
- if Is_Ignored (N) then
+ if Is_Ignored_In_Codegen (N) then
return;
end if;
@@ -1837,7 +1839,7 @@ package body Exp_Prag is
-- Do nothing if pragma is not enabled. If pragma is disabled, it has
-- already been rewritten as a Null statement.
- if Is_Ignored (CCs) then
+ if Is_Ignored_In_Codegen (CCs) then
return;
-- Guard against malformed contract cases
@@ -2538,7 +2540,7 @@ package body Exp_Prag is
-- Nothing to do when the pragma is ignored because its semantics are
-- suppressed.
- if Is_Ignored (IC_Prag) then
+ if Is_Ignored_In_Codegen (IC_Prag) then
return;
-- Nothing to do when the pragma or its argument are illegal because
@@ -3001,7 +3003,7 @@ package body Exp_Prag is
-- Also do this in CodePeer mode, because the expanded code is too
-- complicated for CodePeer to analyse.
- if Is_Ignored (N)
+ if Is_Ignored_In_Codegen (N)
or else Chars (Last_Var) = Name_Structural
or else CodePeer_Mode
then
@@ -3391,7 +3393,7 @@ package body Exp_Prag is
-- Do nothing if pragma is not present or is disabled.
-- Also ignore structural variants for execution.
- if Is_Ignored (Prag)
+ if Is_Ignored_In_Codegen (Prag)
or else Chars (Nlists.Last (Choices (Last_Variant))) = Name_Structural
then
return;
diff --git a/gcc/ada/exp_spark.adb b/gcc/ada/exp_spark.adb
index a75a507..0f92034 100644
--- a/gcc/ada/exp_spark.adb
+++ b/gcc/ada/exp_spark.adb
@@ -1128,8 +1128,7 @@ package body Exp_SPARK is
Wrapper_Decl_List : List_Id;
Wrapper_Body_List : List_Id := No_List;
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
-- Save the Ghost-related attributes to restore on exit
begin
@@ -1253,7 +1252,7 @@ package body Exp_SPARK is
end if;
end if;
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
end SPARK_Freeze_Type;
end Exp_SPARK;
diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb
index 5a6fca0..e9ec7b7 100644
--- a/gcc/ada/exp_util.adb
+++ b/gcc/ada/exp_util.adb
@@ -1903,7 +1903,7 @@ package body Exp_Util is
begin
-- The DIC pragma is ignored, nothing left to do
- if Is_Ignored (DIC_Prag) then
+ if Is_Ignored_In_Codegen (DIC_Prag) then
null;
-- Otherwise the DIC expression must be checked at run time.
@@ -2311,8 +2311,7 @@ package body Exp_Util is
Loc : constant Source_Ptr := Sloc (Typ);
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
-- Save the Ghost-related attributes to restore on exit
DIC_Prag : Node_Id;
@@ -2558,7 +2557,7 @@ package body Exp_Util is
end if;
<<Leave>>
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
end Build_DIC_Procedure_Body;
-------------------------------------
@@ -2575,8 +2574,7 @@ package body Exp_Util is
is
Loc : constant Source_Ptr := Sloc (Typ);
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
-- Save the Ghost-related attributes to restore on exit
DIC_Prag : Node_Id;
@@ -2783,7 +2781,7 @@ package body Exp_Util is
end if;
<<Leave>>
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
end Build_DIC_Procedure_Declaration;
------------------------------------
@@ -3237,7 +3235,7 @@ package body Exp_Util is
begin
-- The invariant is ignored, nothing left to do
- if Is_Ignored (Prag) then
+ if Is_Ignored_In_Codegen (Prag) then
null;
-- Otherwise the invariant is checked. Build a pragma Check to verify
@@ -3709,8 +3707,7 @@ package body Exp_Util is
-- Local variables
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
-- Save the Ghost-related attributes to restore on exit
Dummy : Entity_Id;
@@ -4058,7 +4055,7 @@ package body Exp_Util is
end if;
<<Leave>>
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
end Build_Invariant_Procedure_Body;
-------------------------------------------
@@ -4075,8 +4072,7 @@ package body Exp_Util is
is
Loc : constant Source_Ptr := Sloc (Typ);
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
-- Save the Ghost-related attributes to restore on exit
Proc_Decl : Node_Id;
@@ -4292,7 +4288,7 @@ package body Exp_Util is
end if;
<<Leave>>
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
end Build_Invariant_Procedure_Declaration;
------------------------
@@ -10640,8 +10636,7 @@ package body Exp_Util is
is
Loc : constant Source_Ptr := Sloc (Expr);
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
-- Save the Ghost-related attributes to restore on exit
Call : Node_Id;
@@ -10685,7 +10680,7 @@ package body Exp_Util is
Name => New_Occurrence_Of (Func_Id, Loc),
Parameter_Associations => Param_Assocs);
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
return Call;
end Make_Predicate_Call;
diff --git a/gcc/ada/expander.adb b/gcc/ada/expander.adb
index 3d7b0d7..25f4950 100644
--- a/gcc/ada/expander.adb
+++ b/gcc/ada/expander.adb
@@ -84,8 +84,7 @@ package body Expander is
-- Ghost mode.
procedure Expand (N : Node_Id) is
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
-- Save the Ghost-related attributes to restore on exit
begin
@@ -559,7 +558,7 @@ package body Expander is
end if;
<<Leave>>
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
end Expand;
---------------------------
diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb
index dbd7cf4..2ebffff 100644
--- a/gcc/ada/freeze.adb
+++ b/gcc/ada/freeze.adb
@@ -2878,8 +2878,7 @@ package body Freeze is
is
Loc : constant Source_Ptr := Sloc (N);
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
-- Save the Ghost-related attributes to restore on exit
Atype : Entity_Id;
@@ -4813,6 +4812,8 @@ package body Freeze is
and then Convention (F_Type) = Convention_Ada
and then not Has_Warnings_Off (F_Type)
and then not Has_Size_Clause (F_Type)
+ and then Present (Esize (F_Type))
+ and then Esize (F_Type) = 8
then
Error_Msg_N
("& is an 8-bit Ada Boolean?x?", Formal);
@@ -8358,12 +8359,12 @@ package body Freeze is
-- and Per-Object Expressions" will suppress the insertion, and the
-- freeze node will be dropped on the floor.
- if Saved_GM = Ignore
- and then Ghost_Mode /= Ignore
- and then Present (Ignored_Ghost_Region)
+ if Saved_Ghost_Config.Ghost_Mode = Ignore
+ and then Ghost_Config.Ghost_Mode /= Ignore
+ and then Present (Ghost_Config.Ignored_Ghost_Region)
then
Insert_Actions
- (Assoc_Node => Ignored_Ghost_Region,
+ (Assoc_Node => Ghost_Config.Ignored_Ghost_Region,
Ins_Actions => Result,
Spec_Expr_OK => True);
@@ -8371,7 +8372,7 @@ package body Freeze is
end if;
<<Leave>>
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
return Result;
end Freeze_Entity;
diff --git a/gcc/ada/frontend.adb b/gcc/ada/frontend.adb
index 564f153..92bc3c6 100644
--- a/gcc/ada/frontend.adb
+++ b/gcc/ada/frontend.adb
@@ -477,7 +477,7 @@ begin
-- executable. This action must be performed very late because it
-- heavily alters the tree.
- if Operating_Mode = Generate_Code or else GNATprove_Mode then
+ if Operating_Mode = Generate_Code and not CodePeer_Mode then
Remove_Ignored_Ghost_Code;
end if;
diff --git a/gcc/ada/ghost.adb b/gcc/ada/ghost.adb
index 6f648f2..f9c2853 100644
--- a/gcc/ada/ghost.adb
+++ b/gcc/ada/ghost.adb
@@ -447,7 +447,7 @@ package body Ghost is
-- The context is Ghost when it appears within a Ghost package or
-- subprogram.
- if Ghost_Mode > None then
+ if Ghost_Config.Ghost_Mode > None then
return True;
-- Routine Expand_Record_Extension creates a parent subtype without
@@ -719,7 +719,7 @@ package body Ghost is
-- The context is ghost when it appears within a Ghost package or
-- subprogram.
- if Ghost_Mode > None then
+ if Ghost_Config.Ghost_Mode > None then
return;
-- The context is ghost if Formal is explicitly marked as ghost
@@ -1130,22 +1130,22 @@ package body Ghost is
-- The context is already within an ignored Ghost region. Maintain the
-- start of the outermost ignored Ghost region.
- if Present (Ignored_Ghost_Region) then
+ if Present (Ghost_Config.Ignored_Ghost_Region) then
null;
-- The current region is the outermost ignored Ghost region. Save its
-- starting node.
elsif Present (N) and then Mode = Ignore then
- Ignored_Ghost_Region := N;
+ Ghost_Config.Ignored_Ghost_Region := N;
-- Otherwise the current region is not ignored, nothing to save
else
- Ignored_Ghost_Region := Empty;
+ Ghost_Config.Ignored_Ghost_Region := Empty;
end if;
- Ghost_Mode := Mode;
+ Ghost_Config.Ghost_Mode := Mode;
end Install_Ghost_Region;
procedure Install_Ghost_Region (Mode : Name_Id; N : Node_Id) is
@@ -1504,10 +1504,10 @@ package body Ghost is
-- A body declared within a Ghost region is automatically Ghost
-- (SPARK RM 6.9(2)).
- elsif Ghost_Mode = Check then
+ elsif Ghost_Config.Ghost_Mode = Check then
Policy := Name_Check;
- elsif Ghost_Mode = Ignore then
+ elsif Ghost_Config.Ghost_Mode = Ignore then
Policy := Name_Ignore;
-- Inherit the "ghostness" of the previous declaration when the body
@@ -1553,10 +1553,10 @@ package body Ghost is
-- A completion elaborated in a Ghost region is automatically Ghost
-- (SPARK RM 6.9(2)).
- if Ghost_Mode = Check then
+ if Ghost_Config.Ghost_Mode = Check then
Policy := Name_Check;
- elsif Ghost_Mode = Ignore then
+ elsif Ghost_Config.Ghost_Mode = Ignore then
Policy := Name_Ignore;
-- The completion becomes Ghost when its initial declaration is also
@@ -1603,10 +1603,10 @@ package body Ghost is
-- A declaration elaborated in a Ghost region is automatically Ghost
-- (SPARK RM 6.9(2)).
- elsif Ghost_Mode = Check then
+ elsif Ghost_Config.Ghost_Mode = Check then
Policy := Name_Check;
- elsif Ghost_Mode = Ignore then
+ elsif Ghost_Config.Ghost_Mode = Ignore then
Policy := Name_Ignore;
-- A child package or subprogram declaration becomes Ghost when its
@@ -1698,10 +1698,10 @@ package body Ghost is
-- An instantiation declaration within a Ghost region is automatically
-- Ghost (SPARK RM 6.9(2)).
- elsif Ghost_Mode = Check then
+ elsif Ghost_Config.Ghost_Mode = Check then
Policy := Name_Check;
- elsif Ghost_Mode = Ignore then
+ elsif Ghost_Config.Ghost_Mode = Ignore then
Policy := Name_Ignore;
-- Inherit the "ghostness" of the generic unit, but the current Ghost
@@ -2018,10 +2018,9 @@ package body Ghost is
-- Restore_Ghost_Region --
--------------------------
- procedure Restore_Ghost_Region (Mode : Ghost_Mode_Type; N : Node_Id) is
+ procedure Restore_Ghost_Region (Config : Ghost_Config_Type) is
begin
- Ghost_Mode := Mode;
- Ignored_Ghost_Region := N;
+ Ghost_Config := Config;
end Restore_Ghost_Region;
--------------------
diff --git a/gcc/ada/ghost.ads b/gcc/ada/ghost.ads
index 3863e50..62c809c 100644
--- a/gcc/ada/ghost.ads
+++ b/gcc/ada/ghost.ads
@@ -243,7 +243,7 @@ package Ghost is
-- WARNING: this is a separate front end pass, care should be taken to keep
-- it optimized.
- procedure Restore_Ghost_Region (Mode : Ghost_Mode_Type; N : Node_Id);
+ procedure Restore_Ghost_Region (Config : Ghost_Config_Type);
pragma Inline (Restore_Ghost_Region);
-- Restore a Ghost region to a previous state described by mode Mode and
-- ignored region start node N. This routine must be used in conjunction
diff --git a/gcc/ada/gnat1drv.adb b/gcc/ada/gnat1drv.adb
index 52063c8..ee2c329 100644
--- a/gcc/ada/gnat1drv.adb
+++ b/gcc/ada/gnat1drv.adb
@@ -503,11 +503,6 @@ procedure Gnat1drv is
Operating_Mode := Check_Semantics;
- -- Enable assertions, since they give valuable extra information for
- -- formal verification.
-
- Assertions_Enabled := True;
-
-- Disable validity checks, since it generates code raising
-- exceptions for invalid data, which confuses GNATprove. Invalid
-- data is directly detected by GNATprove's flow analysis.
diff --git a/gcc/ada/lib-writ.adb b/gcc/ada/lib-writ.adb
index b7a7f12..fb7c416 100644
--- a/gcc/ada/lib-writ.adb
+++ b/gcc/ada/lib-writ.adb
@@ -905,7 +905,7 @@ package body Lib.Writ is
-- Do not generate a with line for an ignored Ghost unit because
-- the unit does not have an ALI file.
- if Is_Ignored_Ghost_Entity (Cunit_Entity (Unum)) then
+ if Is_Ignored_Ghost_Entity_In_Codegen (Cunit_Entity (Unum)) then
goto Next_With_Line;
end if;
diff --git a/gcc/ada/lib-xref.adb b/gcc/ada/lib-xref.adb
index 145d314..aa9ae57 100644
--- a/gcc/ada/lib-xref.adb
+++ b/gcc/ada/lib-xref.adb
@@ -1729,7 +1729,7 @@ package body Lib.Xref is
-- entity because neither the entity nor its references will
-- appear in the final tree.
- if Is_Ignored_Ghost_Entity (Ent) then
+ if Is_Ignored_Ghost_Entity_In_Codegen (Ent) then
goto Orphan_Continue;
end if;
@@ -2190,7 +2190,7 @@ package body Lib.Xref is
-- entity because neither the entity nor its references will
-- appear in the final tree.
- if Is_Ignored_Ghost_Entity (Ent) then
+ if Is_Ignored_Ghost_Entity_In_Codegen (Ent) then
goto Continue;
end if;
diff --git a/gcc/ada/opt.adb b/gcc/ada/opt.adb
index d2291a9..bd74215 100644
--- a/gcc/ada/opt.adb
+++ b/gcc/ada/opt.adb
@@ -204,14 +204,7 @@ package body Opt is
SPARK_Mode_Pragma := SPARK_Mode_Pragma_Config;
else
- -- In GNATprove mode assertions should be always enabled, even
- -- when analysing internal units.
-
- if GNATprove_Mode then
- pragma Assert (Assertions_Enabled);
- null;
-
- elsif GNAT_Mode_Config then
+ if GNAT_Mode_Config then
Assertions_Enabled := Assertions_Enabled_Config;
else
Assertions_Enabled := False;
diff --git a/gcc/ada/opt.ads b/gcc/ada/opt.ads
index e595b08..73f9fe8 100644
--- a/gcc/ada/opt.ads
+++ b/gcc/ada/opt.ads
@@ -746,9 +746,20 @@ package Opt is
-- Possible legal modes that can be set by aspect/pragma Ghost as well as
-- value None, which indicates that no such aspect/pragma applies.
- Ghost_Mode : Ghost_Mode_Type := None;
+ type Ghost_Config_Type is record
+ Ghost_Mode : Ghost_Mode_Type := None;
+ -- The current Ghost mode in effect
+
+ Ignored_Ghost_Region : Node_Id := Empty;
+ -- The start of the current ignored Ghost region. This value must always
+ -- reflect the starting node of the outermost ignored Ghost region. If a
+ -- nested ignored Ghost region is entered, the value must remain
+ -- unchanged.
+ end record;
+
+ Ghost_Config : Ghost_Config_Type;
-- GNAT
- -- The current Ghost mode in effect
+ -- All relevant Ghost mode settings
Global_Discard_Names : Boolean := False;
-- GNAT, GNATBIND
@@ -810,12 +821,6 @@ package Opt is
-- use of -gnateu, causing subsequent unrecognized switches to result in
-- a warning rather than an error.
- Ignored_Ghost_Region : Node_Id := Empty;
- -- GNAT
- -- The start of the current ignored Ghost region. This value must always
- -- reflect the starting node of the outermost ignored Ghost region. If a
- -- nested ignored Ghost region is entered, the value must remain unchanged.
-
Implicit_Packing : Boolean := False;
-- GNAT
-- If set True, then a Size attribute clause on an array is allowed to
diff --git a/gcc/ada/par-ch12.adb b/gcc/ada/par-ch12.adb
index b539a29..5fb6f8c 100644
--- a/gcc/ada/par-ch12.adb
+++ b/gcc/ada/par-ch12.adb
@@ -420,32 +420,17 @@ package body Ch12 is
procedure P_Formal_Object_Declarations (Decls : List_Id) is
Decl_Node : Node_Id;
- Ident : Pos;
Not_Null_Present : Boolean := False;
- Num_Idents : Pos;
Scan_State : Saved_Scan_State;
- Idents : array (Pos range 1 .. 4096) of Entity_Id;
- -- This array holds the list of defining identifiers. The upper bound
- -- of 4096 is intended to be essentially infinite, and we do not even
- -- bother to check for it being exceeded.
+ Def_Ids : Defining_Identifiers;
+ Ident : Pos;
begin
- Idents (1) := P_Defining_Identifier (C_Comma_Colon);
- Num_Idents := 1;
- while Comma_Present loop
- Num_Idents := Num_Idents + 1;
- Idents (Num_Idents) := P_Defining_Identifier (C_Comma_Colon);
- end loop;
-
+ P_Def_Ids (Def_Ids);
T_Colon;
- -- If there are multiple identifiers, we repeatedly scan the
- -- type and initialization expression information by resetting
- -- the scan pointer (so that we get completely separate trees
- -- for each occurrence).
-
- if Num_Idents > 1 then
+ if Def_Ids.Num_Idents > 1 then
Save_Scan_State (Scan_State);
end if;
@@ -454,7 +439,7 @@ package body Ch12 is
Ident := 1;
Ident_Loop : loop
Decl_Node := New_Node (N_Formal_Object_Declaration, Token_Ptr);
- Set_Defining_Identifier (Decl_Node, Idents (Ident));
+ Set_Defining_Identifier (Decl_Node, Def_Ids.Idents (Ident));
P_Mode (Decl_Node);
Not_Null_Present := P_Null_Exclusion; -- Ada 2005 (AI-423)
@@ -488,13 +473,13 @@ package body Ch12 is
Set_Prev_Ids (Decl_Node, True);
end if;
- if Ident < Num_Idents then
+ if Ident < Def_Ids.Num_Idents then
Set_More_Ids (Decl_Node, True);
end if;
Append (Decl_Node, Decls);
- exit Ident_Loop when Ident = Num_Idents;
+ exit Ident_Loop when Ident = Def_Ids.Num_Idents;
Ident := Ident + 1;
Restore_Scan_State (Scan_State);
end loop Ident_Loop;
diff --git a/gcc/ada/par-ch3.adb b/gcc/ada/par-ch3.adb
index fe727d7..a685812 100644
--- a/gcc/ada/par-ch3.adb
+++ b/gcc/ada/par-ch3.adb
@@ -1302,19 +1302,13 @@ package body Ch3 is
Ident_Sloc : Source_Ptr;
Scan_State : Saved_Scan_State;
List_OK : Boolean := True;
- Ident : Nat;
Init_Expr : Node_Id;
Init_Loc : Source_Ptr;
Con_Loc : Source_Ptr;
Not_Null_Present : Boolean := False;
- Idents : array (Int range 1 .. 4096) of Entity_Id;
- -- Used to save identifiers in the identifier list. The upper bound
- -- of 4096 is expected to be infinite in practice, and we do not even
- -- bother to check if this upper bound is exceeded.
-
- Num_Idents : Nat := 1;
- -- Number of identifiers stored in Idents
+ Def_Ids : Defining_Identifiers;
+ Ident : Pos;
function Identifier_Starts_Statement return Boolean;
-- Called with Token being an identifier that might start a declaration
@@ -1389,10 +1383,9 @@ package body Ch3 is
procedure No_List is
begin
- if Num_Idents > 1 then
+ if Def_Ids.Num_Idents > 1 then
Error_Msg_N
- ("identifier list not allowed for RENAMES",
- Idents (2));
+ ("identifier list not allowed for RENAMES", Def_Ids.Idents (2));
end if;
List_OK := False;
@@ -1443,7 +1436,7 @@ package body Ch3 is
Ident_Sloc := Token_Ptr;
Save_Scan_State (Scan_State); -- at first identifier
- Idents (1) := P_Defining_Identifier (C_Comma_Colon);
+ Append (Def_Ids, P_Defining_Identifier (C_Comma_Colon));
-- If we have a colon after the identifier, then we can assume that
-- this is in fact a valid identifier declaration and can steam ahead.
@@ -1455,8 +1448,7 @@ package body Ch3 is
elsif Token = Tok_Comma then
while Comma_Present loop
- Num_Idents := Num_Idents + 1;
- Idents (Num_Idents) := P_Defining_Identifier (C_Comma_Colon);
+ Append (Def_Ids, P_Defining_Identifier (C_Comma_Colon));
end loop;
Save_Scan_State (Scan_State); -- at colon
@@ -1510,7 +1502,7 @@ package body Ch3 is
Decl_Node :=
New_Node (N_Object_Renaming_Declaration, Ident_Sloc);
Set_Name (Decl_Node, P_Name);
- Set_Defining_Identifier (Decl_Node, Idents (1));
+ Set_Defining_Identifier (Decl_Node, Def_Ids.Idents (1));
P_Aspect_Specifications (Decl_Node, Semicolon => False);
@@ -1917,7 +1909,7 @@ package body Ch3 is
end if;
end if;
- Set_Defining_Identifier (Decl_Node, Idents (Ident));
+ Set_Defining_Identifier (Decl_Node, Def_Ids.Idents (Ident));
P_Aspect_Specifications (Decl_Node, Semicolon => False);
-- Allow initialization expression to follow aspects (note that in
@@ -1945,17 +1937,17 @@ package body Ch3 is
T_Semicolon;
if List_OK then
- if Ident < Num_Idents then
- Set_More_Ids (Decl_Node, True);
- end if;
-
if Ident > 1 then
Set_Prev_Ids (Decl_Node, True);
end if;
+
+ if Ident < Def_Ids.Num_Idents then
+ Set_More_Ids (Decl_Node, True);
+ end if;
end if;
Append (Decl_Node, Decls);
- exit Ident_Loop when Ident = Num_Idents;
+ exit Ident_Loop when Ident = Def_Ids.Num_Idents;
Restore_Scan_State (Scan_State);
T_Colon;
Ident := Ident + 1;
@@ -3191,14 +3183,7 @@ package body Ch3 is
Specification_List : List_Id;
Ident_Sloc : Source_Ptr;
Scan_State : Saved_Scan_State;
- Num_Idents : Nat;
Not_Null_Present : Boolean;
- Ident : Nat;
-
- Idents : array (Int range 1 .. 4096) of Entity_Id;
- -- This array holds the list of defining identifiers. The upper bound
- -- of 4096 is intended to be essentially infinite, and we do not even
- -- bother to check for it being exceeded.
begin
if Token = Tok_Left_Paren then
@@ -3207,97 +3192,91 @@ package body Ch3 is
P_Pragmas_Misplaced;
Specification_Loop : loop
+ declare
+ Def_Ids : Defining_Identifiers;
+ Ident : Pos;
+ begin
+ Ident_Sloc := Token_Ptr;
+ P_Def_Ids (Def_Ids);
- Ident_Sloc := Token_Ptr;
- Idents (1) := P_Defining_Identifier (C_Comma_Colon);
- Num_Idents := 1;
-
- while Comma_Present loop
- Num_Idents := Num_Idents + 1;
- Idents (Num_Idents) := P_Defining_Identifier (C_Comma_Colon);
- end loop;
-
- -- If there are multiple identifiers, we repeatedly scan the
- -- type and initialization expression information by resetting
- -- the scan pointer (so that we get completely separate trees
- -- for each occurrence).
+ if Def_Ids.Num_Idents > 1 then
+ Save_Scan_State (Scan_State);
+ end if;
- if Num_Idents > 1 then
- Save_Scan_State (Scan_State);
- end if;
+ T_Colon;
- T_Colon;
+ -- Loop through defining identifiers in list
- -- Loop through defining identifiers in list
+ Ident := 1;
+ Ident_Loop : loop
+ Specification_Node :=
+ New_Node (N_Discriminant_Specification, Ident_Sloc);
+ Set_Defining_Identifier
+ (Specification_Node, Def_Ids.Idents (Ident));
+ Not_Null_Present := -- Ada 2005 (AI-231, AI-447)
+ P_Null_Exclusion (Allow_Anonymous_In_95 => True);
- Ident := 1;
- Ident_Loop : loop
- Specification_Node :=
- New_Node (N_Discriminant_Specification, Ident_Sloc);
- Set_Defining_Identifier (Specification_Node, Idents (Ident));
- Not_Null_Present := -- Ada 2005 (AI-231, AI-447)
- P_Null_Exclusion (Allow_Anonymous_In_95 => True);
+ if Token = Tok_Access then
+ if Ada_Version = Ada_83 then
+ Error_Msg_SC
+ ("(Ada 83) access discriminant not allowed!");
+ end if;
- if Token = Tok_Access then
- if Ada_Version = Ada_83 then
- Error_Msg_SC
- ("(Ada 83) access discriminant not allowed!");
- end if;
+ Set_Discriminant_Type
+ (Specification_Node,
+ P_Access_Definition (Not_Null_Present));
- Set_Discriminant_Type
- (Specification_Node,
- P_Access_Definition (Not_Null_Present));
+ -- Catch ouf-of-order keywords
- -- Catch ouf-of-order keywords
+ elsif Token = Tok_Constant then
+ Scan;
- elsif Token = Tok_Constant then
- Scan;
+ if Token = Tok_Access then
+ Error_Msg_SC -- CODEFIX
+ ("ACCESS must come before CONSTANT");
+ Set_Discriminant_Type
+ (Specification_Node,
+ P_Access_Definition (Not_Null_Present));
- if Token = Tok_Access then
- Error_Msg_SC -- CODEFIX
- ("ACCESS must come before CONSTANT");
- Set_Discriminant_Type
- (Specification_Node,
- P_Access_Definition (Not_Null_Present));
+ else
+ Error_Msg_SC ("misplaced CONSTANT");
+ end if;
else
- Error_Msg_SC ("misplaced CONSTANT");
+ Set_Discriminant_Type
+ (Specification_Node, P_Subtype_Mark);
+ No_Constraint;
+ Set_Null_Exclusion_Present -- Ada 2005 (AI-231)
+ (Specification_Node, Not_Null_Present);
end if;
- else
- Set_Discriminant_Type
- (Specification_Node, P_Subtype_Mark);
- No_Constraint;
- Set_Null_Exclusion_Present -- Ada 2005 (AI-231)
- (Specification_Node, Not_Null_Present);
- end if;
-
- Set_Expression
- (Specification_Node, Init_Expr_Opt (True));
+ Set_Expression
+ (Specification_Node, Init_Expr_Opt (True));
- if Token = Tok_With then
- P_Aspect_Specifications
- (Specification_Node, Semicolon => False);
- end if;
+ if Token = Tok_With then
+ P_Aspect_Specifications
+ (Specification_Node, Semicolon => False);
+ end if;
- if Ident > 1 then
- Set_Prev_Ids (Specification_Node, True);
- end if;
+ if Ident > 1 then
+ Set_Prev_Ids (Specification_Node, True);
+ end if;
- if Ident < Num_Idents then
- Set_More_Ids (Specification_Node, True);
- end if;
+ if Ident < Def_Ids.Num_Idents then
+ Set_More_Ids (Specification_Node, True);
+ end if;
- Append (Specification_Node, Specification_List);
- exit Ident_Loop when Ident = Num_Idents;
- Ident := Ident + 1;
- Restore_Scan_State (Scan_State);
- T_Colon;
- end loop Ident_Loop;
+ Append (Specification_Node, Specification_List);
+ exit Ident_Loop when Ident = Def_Ids.Num_Idents;
+ Ident := Ident + 1;
+ Restore_Scan_State (Scan_State);
+ T_Colon;
+ end loop Ident_Loop;
- exit Specification_Loop when Token /= Tok_Semicolon;
- Scan; -- past ;
- P_Pragmas_Misplaced;
+ exit Specification_Loop when Token /= Tok_Semicolon;
+ Scan; -- past ;
+ P_Pragmas_Misplaced;
+ end;
end loop Specification_Loop;
T_Right_Paren;
@@ -3770,14 +3749,10 @@ package body Ch3 is
Decl_Node : Node_Id := Empty; -- initialize to prevent warning
Scan_State : Saved_Scan_State;
Not_Null_Present : Boolean := False;
- Num_Idents : Nat;
- Ident : Nat;
Ident_Sloc : Source_Ptr;
- Idents : array (Int range 1 .. 4096) of Entity_Id;
- -- This array holds the list of defining identifiers. The upper bound
- -- of 4096 is intended to be essentially infinite, and we do not even
- -- bother to check for it being exceeded.
+ Def_Ids : Defining_Identifiers;
+ Ident : Pos;
begin
if Token /= Tok_Identifier then
@@ -3788,20 +3763,9 @@ package body Ch3 is
Ident_Sloc := Token_Ptr;
Check_Bad_Layout;
- Idents (1) := P_Defining_Identifier (C_Comma_Colon);
- Num_Idents := 1;
-
- while Comma_Present loop
- Num_Idents := Num_Idents + 1;
- Idents (Num_Idents) := P_Defining_Identifier (C_Comma_Colon);
- end loop;
-
- -- If there are multiple identifiers, we repeatedly scan the
- -- type and initialization expression information by resetting
- -- the scan pointer (so that we get completely separate trees
- -- for each occurrence).
+ P_Def_Ids (Def_Ids);
- if Num_Idents > 1 then
+ if Def_Ids.Num_Idents > 1 then
Save_Scan_State (Scan_State);
end if;
@@ -3817,7 +3781,7 @@ package body Ch3 is
begin
Decl_Node := New_Node (N_Component_Declaration, Ident_Sloc);
- Set_Defining_Identifier (Decl_Node, Idents (Ident));
+ Set_Defining_Identifier (Decl_Node, Def_Ids.Idents (Ident));
if Token = Tok_Constant then
Error_Msg_SC ("constant component not permitted");
@@ -3876,7 +3840,7 @@ package body Ch3 is
Set_Prev_Ids (Decl_Node, True);
end if;
- if Ident < Num_Idents then
+ if Ident < Def_Ids.Num_Idents then
Set_More_Ids (Decl_Node, True);
end if;
@@ -3890,7 +3854,7 @@ package body Ch3 is
end if;
end;
- exit Ident_Loop when Ident = Num_Idents;
+ exit Ident_Loop when Ident = Def_Ids.Num_Idents;
Ident := Ident + 1;
Restore_Scan_State (Scan_State);
T_Colon;
diff --git a/gcc/ada/par-ch6.adb b/gcc/ada/par-ch6.adb
index 0f7765b..2465108 100644
--- a/gcc/ada/par-ch6.adb
+++ b/gcc/ada/par-ch6.adb
@@ -1384,20 +1384,16 @@ package body Ch6 is
Specification_List : List_Id;
Specification_Node : Node_Id;
Scan_State : Saved_Scan_State;
- Num_Idents : Nat;
- Ident : Nat;
Ident_Sloc : Source_Ptr;
Not_Null_Present : Boolean := False;
Not_Null_Sloc : Source_Ptr;
- Idents : array (Int range 1 .. 4096) of Entity_Id;
- -- This array holds the list of defining identifiers. The upper bound
- -- of 4096 is intended to be essentially infinite, and we do not even
- -- bother to check for it being exceeded.
-
begin
Specification_List := New_List;
Specification_Loop : loop
+ declare
+ Def_Ids : Defining_Identifiers;
+ Ident : Pos;
begin
if Token = Tok_Pragma then
Error_Msg_SC ("pragma not allowed in formal part");
@@ -1406,8 +1402,7 @@ package body Ch6 is
Ignore (Tok_Left_Paren);
Ident_Sloc := Token_Ptr;
- Idents (1) := P_Defining_Identifier (C_Comma_Colon);
- Num_Idents := 1;
+ Append (Def_Ids, P_Defining_Identifier (C_Comma_Colon));
Ident_Loop : loop
exit Ident_Loop when Token = Tok_Colon;
@@ -1457,8 +1452,7 @@ package body Ch6 is
-- Here if a comma is present, or to be assumed
T_Comma;
- Num_Idents := Num_Idents + 1;
- Idents (Num_Idents) := P_Defining_Identifier (C_Comma_Colon);
+ Append (Def_Ids, P_Defining_Identifier (C_Comma_Colon));
end loop Ident_Loop;
-- Fall through the loop on encountering a colon, or deciding
@@ -1466,12 +1460,7 @@ package body Ch6 is
T_Colon;
- -- If there are multiple identifiers, we repeatedly scan the
- -- type and initialization expression information by resetting
- -- the scan pointer (so that we get completely separate trees
- -- for each occurrence).
-
- if Num_Idents > 1 then
+ if Def_Ids.Num_Idents > 1 then
Save_Scan_State (Scan_State);
end if;
@@ -1482,7 +1471,8 @@ package body Ch6 is
Ident_List_Loop : loop
Specification_Node :=
New_Node (N_Parameter_Specification, Ident_Sloc);
- Set_Defining_Identifier (Specification_Node, Idents (Ident));
+ Set_Defining_Identifier
+ (Specification_Node, Def_Ids.Idents (Ident));
-- Scan possible ALIASED for Ada 2012 (AI-142)
@@ -1574,12 +1564,12 @@ package body Ch6 is
Set_Prev_Ids (Specification_Node, True);
end if;
- if Ident < Num_Idents then
+ if Ident < Def_Ids.Num_Idents then
Set_More_Ids (Specification_Node, True);
end if;
Append (Specification_Node, Specification_List);
- exit Ident_List_Loop when Ident = Num_Idents;
+ exit Ident_List_Loop when Ident = Def_Ids.Num_Idents;
Ident := Ident + 1;
Restore_Scan_State (Scan_State);
end loop Ident_List_Loop;
diff --git a/gcc/ada/par-util.adb b/gcc/ada/par-util.adb
index 78a76b3..6a6afd0 100644
--- a/gcc/ada/par-util.adb
+++ b/gcc/ada/par-util.adb
@@ -34,6 +34,22 @@ with GNAT.Spelling_Checker; use GNAT.Spelling_Checker;
separate (Par)
package body Util is
+ ------------
+ -- Append --
+ ------------
+
+ procedure Append
+ (Def_Ids : in out Defining_Identifiers; Def_Id : Entity_Id)
+ is
+ begin
+ if Def_Ids.Num_Idents >= Defining_Identifiers_Array'Last then
+ raise Program_Error;
+ end if;
+
+ Def_Ids.Num_Idents := Def_Ids.Num_Idents + 1;
+ Def_Ids.Idents (Def_Ids.Num_Idents) := Def_Id;
+ end Append;
+
---------------------
-- Bad_Spelling_Of --
---------------------
@@ -691,6 +707,19 @@ package body Util is
end if;
end No_Constraint;
+ ---------------
+ -- P_Def_Ids --
+ ---------------
+
+ procedure P_Def_Ids (Def_Ids : out Defining_Identifiers) is
+ pragma Assert (Def_Ids.Num_Idents = 0);
+ begin
+ loop
+ Append (Def_Ids, P_Defining_Identifier (C_Comma_Colon));
+ exit when not Comma_Present;
+ end loop;
+ end P_Def_Ids;
+
---------------------
-- Pop_Scope_Stack --
---------------------
diff --git a/gcc/ada/par.adb b/gcc/ada/par.adb
index e11ec7e..99bbed2 100644
--- a/gcc/ada/par.adb
+++ b/gcc/ada/par.adb
@@ -227,6 +227,69 @@ function Par (Configuration_Pragmas : Boolean) return List_Id is
-- that there is a missing body, but it seems more reasonable to let the
-- later semantic checking discover this.
+ --------------------------------------------
+ -- Handling IS Used in Place of Semicolon --
+ --------------------------------------------
+
+ -- This is a somewhat trickier situation, and we can't catch it in all
+ -- cases, but we do our best to detect common situations resulting from
+ -- a "cut and paste" operation which forgets to change the IS to semicolon.
+ -- Consider the following example:
+
+ -- package body X is
+ -- procedure A;
+ -- procedure B is -- Error: IS should be semicolon
+ -- procedure C;
+ -- ...
+ -- procedure D is
+ -- begin
+ -- ...
+ -- end;
+ -- begin
+ -- ...
+ -- end; -- end of B?
+
+ -- The trouble is that the section of text from PROCEDURE B through the
+ -- END; marked "-- end of B?" constitutes a valid procedure body, and the
+ -- danger is that we find out far too late that something is wrong.
+
+ -- We have two approaches to helping to control this situation. First we
+ -- make every attempt to avoid swallowing the last END; if we can be sure
+ -- that some error will result from doing so. In particular, we won't
+ -- accept the END; unless it is exactly correct (in particular it must not
+ -- have incorrect name tokens), and we won't accept it if it is immediately
+ -- followed by end of file, WITH or SEPARATE (tokens that unmistakeably
+ -- signal the start of a compilation unit, and which therefore allow us to
+ -- reserve the END; for the outer level.) For more details on this aspect
+ -- of the handling, see package Par.Endh.
+
+ -- If we can avoid eating up the END; then the result in the absence of
+ -- any additional steps would be to post a missing END referring back to
+ -- the subprogram with the bogus IS. Similarly, if the enclosing package
+ -- has no BEGIN, then the result is a missing BEGIN message, which again
+ -- refers back to the subprogram header.
+
+ -- Such an error message is not too bad, but it's not ideal, because
+ -- the declarations following the IS have been absorbed into the wrong
+ -- scope. In the above case, this could result for example in a bogus
+ -- complaint that the body of D was missing from the package.
+
+ -- To catch at least some of these cases, we take the following additional
+ -- steps. First, a subprogram body is marked as having a suspicious IS if
+ -- the declaration line is followed by a line that starts with a symbol
+ -- that can start a declaration in the same column, or to the left of the
+ -- column in which the FUNCTION or PROCEDURE starts (normal style is to
+ -- indent any declarations that really belong a subprogram). If such a
+ -- subprogram encounters a missing BEGIN or missing END, then we decide
+ -- that the IS should have been a semicolon, and the subprogram body node
+ -- is marked (by setting the Bad_Is_Detected flag true. Note that we do
+ -- not do this for library level procedures, only for nested procedures,
+ -- since for library level procedures, we must have a body.
+
+ -- The processing for a declarative part checks to see if the last
+ -- declaration scanned is marked in this way, and if it is, the tree
+ -- is modified to reflect the IS being interpreted as a semicolon.
+
----------------------------------------------------
-- Handling of Reserved Words Used as Identifiers --
----------------------------------------------------
@@ -294,71 +357,6 @@ function Par (Configuration_Pragmas : Boolean) return List_Id is
C_Vertical_Bar_Arrow);
-- Consider as identifier if followed by | or =>
- --------------------------------------------
- -- Handling IS Used in Place of Semicolon --
- --------------------------------------------
-
- -- This is a somewhat trickier situation, and we can't catch it in all
- -- cases, but we do our best to detect common situations resulting from
- -- a "cut and paste" operation which forgets to change the IS to semicolon.
- -- Consider the following example:
-
- -- package body X is
- -- procedure A;
- -- procedure B is
- -- procedure C;
- -- ...
- -- procedure D is
- -- begin
- -- ...
- -- end;
- -- begin
- -- ...
- -- end;
-
- -- The trouble is that the section of text from PROCEDURE B through END;
- -- constitutes a valid procedure body, and the danger is that we find out
- -- far too late that something is wrong (indeed most compilers will behave
- -- uncomfortably on the above example).
-
- -- We have two approaches to helping to control this situation. First we
- -- make every attempt to avoid swallowing the last END; if we can be sure
- -- that some error will result from doing so. In particular, we won't
- -- accept the END; unless it is exactly correct (in particular it must not
- -- have incorrect name tokens), and we won't accept it if it is immediately
- -- followed by end of file, WITH or SEPARATE (all tokens that unmistakeably
- -- signal the start of a compilation unit, and which therefore allow us to
- -- reserve the END; for the outer level.) For more details on this aspect
- -- of the handling, see package Par.Endh.
-
- -- If we can avoid eating up the END; then the result in the absence of
- -- any additional steps would be to post a missing END referring back to
- -- the subprogram with the bogus IS. Similarly, if the enclosing package
- -- has no BEGIN, then the result is a missing BEGIN message, which again
- -- refers back to the subprogram header.
-
- -- Such an error message is not too bad (it's already a big improvement
- -- over what many parsers do), but it's not ideal, because the declarations
- -- following the IS have been absorbed into the wrong scope. In the above
- -- case, this could result for example in a bogus complaint that the body
- -- of D was missing from the package.
-
- -- To catch at least some of these cases, we take the following additional
- -- steps. First, a subprogram body is marked as having a suspicious IS if
- -- the declaration line is followed by a line which starts with a symbol
- -- that can start a declaration in the same column, or to the left of the
- -- column in which the FUNCTION or PROCEDURE starts (normal style is to
- -- indent any declarations which really belong a subprogram). If such a
- -- subprogram encounters a missing BEGIN or missing END, then we decide
- -- that the IS should have been a semicolon, and the subprogram body node
- -- is marked (by setting the Bad_Is_Detected flag true. Note that we do
- -- not do this for library level procedures, only for nested procedures,
- -- since for library level procedures, we must have a body.
-
- -- The processing for a declarative part checks to see if the last
- -- declaration scanned is marked in this way, and if it is, the tree
- -- is modified to reflect the IS being interpreted as a semicolon.
-
---------------------------------------------------
-- Parser Type Definitions and Control Variables --
---------------------------------------------------
@@ -1450,6 +1448,47 @@ function Par (Configuration_Pragmas : Boolean) return List_Id is
-- the Node N (which is a Defining_Identifier node with the Chars field
-- set) is a renaming of an entity in package Standard.
+ -----------------------------------
+ -- Multiple defining identifiers --
+ -----------------------------------
+
+ -- RM-3.3.1(7) says:
+ --
+ -- Any declaration that includes a defining_identifier_list with
+ -- more than one defining_identifier is equivalent to a series of
+ -- declarations each containing one defining_identifier from the list,
+ -- with the rest of the text of the declaration copied for each
+ -- declaration in the series, in the same order as the list.
+ --
+ -- We parse such declarations by first calling P_Def_Ids (see below).
+ -- Then, if there are multiple identifiers, we repeatedly scan the
+ -- type and initialization expression information by resetting the
+ -- scan pointer (so that we get completely separate trees for each
+ -- occurrence).
+
+ -- Defining_Identifiers is a sequence of identifiers parsed by
+ -- P_Def_Ids. Idents holds the identifiers, and Num_Idents
+ -- points to the last-used array elements. The upper bound
+ -- is intended to be essentially infinite, so we don't bother
+ -- giving a good error message when it is exceeded -- we
+ -- simply raise an exception.
+
+ type Defining_Identifiers_Array is
+ array (Pos range 1 .. 4096) of Entity_Id;
+
+ type Defining_Identifiers is record
+ Num_Idents : Nat := 0;
+ Idents : Defining_Identifiers_Array;
+ end record;
+
+ procedure Append
+ (Def_Ids : in out Defining_Identifiers; Def_Id : Entity_Id);
+ -- Append one defining identifier onto Def_Ids.
+
+ procedure P_Def_Ids (Def_Ids : out Defining_Identifiers);
+ -- Parse a defining_identifier_list, appending the identifiers
+ -- onto Def_Ids, which should be initially empty.
+
end Util;
--------------
diff --git a/gcc/ada/rtsfind.adb b/gcc/ada/rtsfind.adb
index 86713ff..f47aacc 100644
--- a/gcc/ada/rtsfind.adb
+++ b/gcc/ada/rtsfind.adb
@@ -1030,8 +1030,7 @@ package body Rtsfind is
U : RT_Unit_Table_Record renames RT_Unit_Table (U_Id);
Priv_Par : constant Elist_Id := New_Elmt_List;
Lib_Unit : Node_Id;
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
Saved_ISMP : constant Boolean :=
Ignore_SPARK_Mode_Pragmas_In_Instance;
Saved_SM : constant SPARK_Mode_Type := SPARK_Mode;
@@ -1099,7 +1098,7 @@ package body Rtsfind is
procedure Restore_SPARK_Context is
begin
Ignore_SPARK_Mode_Pragmas_In_Instance := Saved_ISMP;
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
Restore_SPARK_Mode (Saved_SM, Saved_SMP);
end Restore_SPARK_Context;
@@ -1289,7 +1288,7 @@ package body Rtsfind is
declare
LibUnit : constant Node_Id := Unit (Cunit (U.Unum));
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
+ Saved_GM : constant Ghost_Mode_Type := Ghost_Config.Ghost_Mode;
Clause : Node_Id;
Withn : Node_Id;
@@ -1308,13 +1307,13 @@ package body Rtsfind is
-- later, after ignored ghost code is converted to a null
-- statement.
- Ghost_Mode := None;
+ Ghost_Config.Ghost_Mode := None;
Withn :=
Make_With_Clause (Standard_Location,
Name =>
Make_Unit_Name
(U, Defining_Unit_Name (Specification (LibUnit))));
- Ghost_Mode := Saved_GM;
+ Ghost_Config.Ghost_Mode := Saved_GM;
Set_Corresponding_Spec (Withn, U.Entity);
Set_First_Name (Withn);
@@ -1627,7 +1626,9 @@ package body Rtsfind is
-- is pulled within an ignored Ghost context because all this code will
-- disappear.
- if U_Id = System_Secondary_Stack and then Ghost_Mode /= Ignore then
+ if U_Id = System_Secondary_Stack
+ and then Ghost_Config.Ghost_Mode /= Ignore
+ then
Sec_Stack_Used := True;
end if;
diff --git a/gcc/ada/sem.adb b/gcc/ada/sem.adb
index e168d62..944ece1 100644
--- a/gcc/ada/sem.adb
+++ b/gcc/ada/sem.adb
@@ -104,8 +104,7 @@ package body Sem is
-- Ghost mode.
procedure Analyze (N : Node_Id) is
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
-- Save the Ghost-related attributes to restore on exit
begin
@@ -842,7 +841,7 @@ package body Sem is
Expand_SPARK_Potential_Renaming (N);
end if;
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
end Analyze;
-- Version with check(s) suppressed
@@ -1440,8 +1439,7 @@ package body Sem is
-- the Ghost mode.
procedure Do_Analyze is
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
Saved_ISMP : constant Boolean :=
Ignore_SPARK_Mode_Pragmas_In_Instance;
-- Save Ghost and SPARK mode-related data to restore on exit
@@ -1489,7 +1487,7 @@ package body Sem is
Style_Max_Line_Length := Saved_ML;
Style_Check_Max_Line_Length := Saved_CML;
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
Ignore_SPARK_Mode_Pragmas_In_Instance := Saved_ISMP;
end Do_Analyze;
diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb
index f38380c..78b6318 100644
--- a/gcc/ada/sem_attr.adb
+++ b/gcc/ada/sem_attr.adb
@@ -5092,7 +5092,7 @@ package body Sem_Attr is
-- early transformation also avoids the generation of a useless loop
-- entry constant.
- if Present (Encl_Prag) and then Is_Ignored (Encl_Prag) then
+ if Present (Encl_Prag) and then Is_Ignored_In_Codegen (Encl_Prag) then
Rewrite (N, Relocate_Node (P));
Preanalyze_And_Resolve (N);
diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb
index b5c9e88..1ba76dc 100644
--- a/gcc/ada/sem_ch12.adb
+++ b/gcc/ada/sem_ch12.adb
@@ -4900,8 +4900,7 @@ package body Sem_Ch12 is
Loc : constant Source_Ptr := Sloc (N);
Is_Abbrev : constant Boolean :=
Is_Abbreviated_Instance (Defining_Entity (N));
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
Saved_ISMP : constant Boolean :=
Ignore_SPARK_Mode_Pragmas_In_Instance;
Saved_SM : constant SPARK_Mode_Type := SPARK_Mode;
@@ -5680,7 +5679,7 @@ package body Sem_Ch12 is
end if;
Ignore_SPARK_Mode_Pragmas_In_Instance := Saved_ISMP;
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
Restore_SPARK_Mode (Saved_SM, Saved_SMP);
Style_Check := Saved_Style_Check;
@@ -5695,7 +5694,7 @@ package body Sem_Ch12 is
end if;
Ignore_SPARK_Mode_Pragmas_In_Instance := Saved_ISMP;
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
Restore_SPARK_Mode (Saved_SM, Saved_SMP);
Style_Check := Saved_Style_Check;
end Analyze_Package_Instantiation;
@@ -6340,8 +6339,7 @@ package body Sem_Ch12 is
-- Local variables
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
Saved_ISMP : constant Boolean :=
Ignore_SPARK_Mode_Pragmas_In_Instance;
Saved_SM : constant SPARK_Mode_Type := SPARK_Mode;
@@ -6736,7 +6734,7 @@ package body Sem_Ch12 is
end if;
Ignore_SPARK_Mode_Pragmas_In_Instance := Saved_ISMP;
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
Restore_SPARK_Mode (Saved_SM, Saved_SMP);
exception
@@ -6750,7 +6748,7 @@ package body Sem_Ch12 is
end if;
Ignore_SPARK_Mode_Pragmas_In_Instance := Saved_ISMP;
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
Restore_SPARK_Mode (Saved_SM, Saved_SMP);
end Analyze_Subprogram_Instantiation;
@@ -12874,8 +12872,7 @@ package body Sem_Ch12 is
-- the package body.
Saved_CS : constant Config_Switches_Type := Save_Config_Switches;
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
Saved_ISMP : constant Boolean :=
Ignore_SPARK_Mode_Pragmas_In_Instance;
Saved_LSST : constant Suppress_Stack_Entry_Ptr :=
@@ -13405,7 +13402,7 @@ package body Sem_Ch12 is
Expander_Mode_Restore;
Restore_Config_Switches (Saved_CS);
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
Restore_SPARK_Mode (Saved_SM, Saved_SMP);
Restore_Warnings (Saved_Warn);
end Instantiate_Package_Body;
@@ -13436,8 +13433,7 @@ package body Sem_Ch12 is
-- the subprogram body.
Saved_CS : constant Config_Switches_Type := Save_Config_Switches;
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
Saved_ISMP : constant Boolean :=
Ignore_SPARK_Mode_Pragmas_In_Instance;
Saved_LSST : constant Suppress_Stack_Entry_Ptr :=
@@ -13740,7 +13736,7 @@ package body Sem_Ch12 is
Expander_Mode_Restore;
Restore_Config_Switches (Saved_CS);
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
Restore_SPARK_Mode (Saved_SM, Saved_SMP);
Restore_Warnings (Saved_Warn);
end Instantiate_Subprogram_Body;
diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb
index b7ada50..31735e4 100644
--- a/gcc/ada/sem_ch13.adb
+++ b/gcc/ada/sem_ch13.adb
@@ -4799,7 +4799,7 @@ package body Sem_Ch13 is
and then not Is_Ignored_Ghost_Entity (E)
then
if A_Id = Aspect_Pre then
- if Is_Ignored (Aspect) then
+ if Is_Ignored_In_Codegen (Aspect) then
Set_Ignored_Class_Preconditions (E,
New_Copy_Tree (Expr));
else
@@ -4813,7 +4813,7 @@ package body Sem_Ch13 is
elsif No (Class_Postconditions (E))
and then No (Ignored_Class_Postconditions (E))
then
- if Is_Ignored (Aspect) then
+ if Is_Ignored_In_Codegen (Aspect) then
Set_Ignored_Class_Postconditions (E,
New_Copy_Tree (Expr));
else
@@ -10282,8 +10282,7 @@ package body Sem_Ch13 is
procedure Build_Predicate_Function (Typ : Entity_Id; N : Node_Id) is
Loc : constant Source_Ptr := Sloc (Typ);
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
-- Save the Ghost-related attributes to restore on exit
Expr : Node_Id;
@@ -10449,7 +10448,7 @@ package body Sem_Ch13 is
-- which is needed to generate the corresponding predicate
-- function.
- if Is_Ignored_Ghost_Pragma (Prag) then
+ if Is_Ignored_Ghost_Pragma_In_Codegen (Prag) then
Add_Condition (New_Occurrence_Of (Standard_True, Sloc (Prag)));
else
@@ -10490,7 +10489,8 @@ package body Sem_Ch13 is
-- "and"-in the Arg2 condition to evolving expression
- if not Is_Ignored_Ghost_Pragma (Prag) then
+ if not Is_Ignored_Ghost_Pragma_In_Codegen (Prag)
+ then
Add_Condition (Arg2_Copy);
end if;
end;
@@ -11090,7 +11090,7 @@ package body Sem_Ch13 is
end;
end if;
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
if Restore_Scope then
Pop_Scope;
@@ -11110,8 +11110,7 @@ package body Sem_Ch13 is
is
Loc : constant Source_Ptr := Sloc (Typ);
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
-- Save the Ghost-related attributes to restore on exit
Func_Decl : Node_Id;
@@ -11192,7 +11191,7 @@ package body Sem_Ch13 is
Insert_After (Parent (Typ), Func_Decl);
Analyze (Func_Decl);
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
return Func_Decl;
end Build_Predicate_Function_Declaration;
diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb
index 3726169..9f69e4f 100644
--- a/gcc/ada/sem_ch3.adb
+++ b/gcc/ada/sem_ch3.adb
@@ -4386,8 +4386,7 @@ package body Sem_Ch3 is
-- Local variables
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
-- Save the Ghost-related attributes to restore on exit
Prev_Entity : Entity_Id := Empty;
@@ -5475,7 +5474,7 @@ package body Sem_Ch3 is
Check_No_Hidden_State (Id);
end if;
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
end Analyze_Object_Declaration;
---------------------------
@@ -21707,8 +21706,7 @@ package body Sem_Ch3 is
-- Local variables
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
-- Save the Ghost-related attributes to restore on exit
Full_Indic : Node_Id;
@@ -22401,7 +22399,7 @@ package body Sem_Ch3 is
end if;
<<Leave>>
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
end Process_Full_View;
-----------------------------------
diff --git a/gcc/ada/sem_ch5.adb b/gcc/ada/sem_ch5.adb
index 0661e64..9e4936b 100644
--- a/gcc/ada/sem_ch5.adb
+++ b/gcc/ada/sem_ch5.adb
@@ -385,8 +385,7 @@ package body Sem_Ch5 is
-- Local variables
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
-- Save the Ghost-related attributes to restore on exit
T1 : Entity_Id;
@@ -1193,7 +1192,7 @@ package body Sem_Ch5 is
Analyze_Dimension (N);
<<Leave>>
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
-- If the right-hand side contains target names, expansion has been
-- disabled to prevent expansion that might move target names out of
@@ -2108,7 +2107,7 @@ package body Sem_Ch5 is
-- A label declared within a Ghost region becomes Ghost (SPARK RM
-- 6.9(2)).
- if Ghost_Mode > None then
+ if Ghost_Config.Ghost_Mode > None then
Set_Is_Ghost_Entity (Id);
end if;
end Analyze_Implicit_Label_Declaration;
diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb
index 709f625..b7ddc4b 100644
--- a/gcc/ada/sem_ch6.adb
+++ b/gcc/ada/sem_ch6.adb
@@ -1372,8 +1372,7 @@ package body Sem_Ch6 is
Loc : constant Source_Ptr := Sloc (N);
Spec : constant Node_Id := Specification (N);
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
Saved_ISMP : constant Boolean :=
Ignore_SPARK_Mode_Pragmas_In_Instance;
-- Save the Ghost and SPARK mode-related data to restore on exit
@@ -1529,7 +1528,7 @@ package body Sem_Ch6 is
<<Leave>>
Ignore_SPARK_Mode_Pragmas_In_Instance := Saved_ISMP;
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
end Analyze_Null_Procedure;
-----------------------------
@@ -1624,8 +1623,7 @@ package body Sem_Ch6 is
Loc : constant Source_Ptr := Sloc (N);
P : constant Node_Id := Name (N);
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
-- Save the Ghost-related attributes to restore on exit
Actual : Node_Id;
@@ -1890,7 +1888,7 @@ package body Sem_Ch6 is
end if;
<<Leave>>
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
end Analyze_Procedure_Call;
------------------------------
@@ -3608,8 +3606,7 @@ package body Sem_Ch6 is
-- Local variables
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
Saved_EA : constant Boolean := Expander_Active;
Saved_ISMP : constant Boolean :=
Ignore_SPARK_Mode_Pragmas_In_Instance;
@@ -3836,7 +3833,7 @@ package body Sem_Ch6 is
-- user entities, as internally generated entitities might still need
-- to be expanded (e.g. those generated for types).
- if Present (Ignored_Ghost_Region)
+ if Present (Ghost_Config.Ignored_Ghost_Region)
and then Comes_From_Source (Body_Id)
then
Expander_Active := False;
@@ -5022,12 +5019,12 @@ package body Sem_Ch6 is
end if;
<<Leave>>
- if Present (Ignored_Ghost_Region) then
+ if Present (Ghost_Config.Ignored_Ghost_Region) then
Expander_Active := Saved_EA;
end if;
Ignore_SPARK_Mode_Pragmas_In_Instance := Saved_ISMP;
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
end Analyze_Subprogram_Body_Helper;
------------------------------------
diff --git a/gcc/ada/sem_ch7.adb b/gcc/ada/sem_ch7.adb
index c2e60aa..d28bafb 100644
--- a/gcc/ada/sem_ch7.adb
+++ b/gcc/ada/sem_ch7.adb
@@ -714,8 +714,7 @@ package body Sem_Ch7 is
-- Local variables
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
Saved_EA : constant Boolean := Expander_Active;
Saved_ISMP : constant Boolean :=
Ignore_SPARK_Mode_Pragmas_In_Instance;
@@ -836,7 +835,7 @@ package body Sem_Ch7 is
-- user entities, as internally generated entities might still need
-- to be expanded (e.g. those generated for types).
- if Present (Ignored_Ghost_Region)
+ if Present (Ghost_Config.Ignored_Ghost_Region)
and then Comes_From_Source (Body_Id)
then
Expander_Active := False;
@@ -1149,12 +1148,12 @@ package body Sem_Ch7 is
end if;
end if;
- if Present (Ignored_Ghost_Region) then
+ if Present (Ghost_Config.Ignored_Ghost_Region) then
Expander_Active := Saved_EA;
end if;
Ignore_SPARK_Mode_Pragmas_In_Instance := Saved_ISMP;
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
end Analyze_Package_Body_Helper;
---------------------------------
diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb
index 2717c38..4fd5b65 100644
--- a/gcc/ada/sem_prag.adb
+++ b/gcc/ada/sem_prag.adb
@@ -436,8 +436,7 @@ package body Sem_Prag is
Arg1 : constant Node_Id :=
First (Pragma_Argument_Associations (N));
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
-- Save the Ghost-related attributes to restore on exit
Errors : Nat;
@@ -492,7 +491,7 @@ package body Sem_Prag is
End_Scope;
end if;
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
end if;
Set_Is_Analyzed_Pragma (N);
@@ -607,8 +606,7 @@ package body Sem_Prag is
CCases : constant Node_Id := Expression (Get_Argument (N, Spec_Id));
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
-- Save the Ghost-related attributes to restore on exit
CCase : Node_Id;
@@ -695,7 +693,7 @@ package body Sem_Prag is
Set_Is_Analyzed_Pragma (N);
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
end Analyze_Contract_Cases_In_Decl_Part;
----------------------------------
@@ -2464,8 +2462,7 @@ package body Sem_Prag is
Exceptional_Contracts : constant Node_Id :=
Expression (Get_Argument (N, Spec_Id));
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
-- Save the Ghost-related attributes to restore on exit
Exceptional_Contract : Node_Id;
@@ -2556,7 +2553,7 @@ package body Sem_Prag is
Set_Is_Analyzed_Pragma (N);
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
end Analyze_Exceptional_Cases_In_Decl_Part;
-------------------------------------
@@ -2772,8 +2769,7 @@ package body Sem_Prag is
Exit_Contracts : constant Node_Id :=
Expression (Get_Argument (N, Spec_Id));
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
-- Save the Ghost-related attributes to restore on exit
Exit_Contract : Node_Id;
@@ -2863,7 +2859,7 @@ package body Sem_Prag is
Set_Is_Analyzed_Pragma (N);
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
end Analyze_Exit_Cases_In_Decl_Part;
--------------------------------------------
@@ -3688,8 +3684,7 @@ package body Sem_Prag is
Pack_Id : constant Entity_Id := Defining_Entity (Pack_Decl);
Expr : constant Node_Id := Expression (Get_Argument (N, Pack_Id));
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
-- Save the Ghost-related attributes to restore on exit
begin
@@ -3713,7 +3708,7 @@ package body Sem_Prag is
Preanalyze_And_Resolve (Expr, Standard_Boolean);
Set_Is_Analyzed_Pragma (N);
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
end Analyze_Initial_Condition_In_Decl_Part;
--------------------------------------
@@ -5766,7 +5761,7 @@ package body Sem_Prag is
begin
if Pname = Name_Pre_Class then
- if Is_Ignored (N) then
+ if Is_Ignored_In_Codegen (N) then
Set_Ignored_Class_Preconditions (Subp_Id,
New_Copy_Tree (Expr));
else
@@ -5774,7 +5769,7 @@ package body Sem_Prag is
end if;
else
- if Is_Ignored (N) then
+ if Is_Ignored_In_Codegen (N) then
Set_Ignored_Class_Postconditions (Subp_Id,
New_Copy_Tree (Expr));
else
@@ -12987,7 +12982,9 @@ package body Sem_Prag is
-- An abstract state declared within a Ghost region becomes
-- Ghost (SPARK RM 6.9(2)).
- if Ghost_Mode > None or else Is_Ghost_Entity (Pack_Id) then
+ if Ghost_Config.Ghost_Mode > None
+ or else Is_Ghost_Entity (Pack_Id)
+ then
Set_Is_Ghost_Entity (State_Id);
end if;
@@ -14302,7 +14299,7 @@ package body Sem_Prag is
-- cannot occur within a Ghost subprogram or package
-- (SPARK RM 6.9(16)).
- if Ghost_Mode > None then
+ if Ghost_Config.Ghost_Mode > None then
Error_Pragma
("pragma % cannot appear within ghost subprogram or "
& "package");
@@ -14871,25 +14868,15 @@ package body Sem_Prag is
Set_Is_Ignored (N, False);
else
- -- In CodePeer mode and GNATprove mode, we need to
- -- consider all assertions, unless they are disabled,
- -- because transformations of the AST may depend on
- -- assertions being checked.
+ Set_Is_Checked (N, False);
+ Set_Is_Ignored (N, True);
- if CodePeer_Mode or GNATprove_Mode then
- Set_Is_Checked (N, True);
- Set_Is_Ignored (N, False);
- else
- Set_Is_Checked (N, False);
- Set_Is_Ignored (N, True);
- end if;
end if;
end Handle_Dynamic_Predicate_Check;
-- Local variables
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
-- Save the Ghost-related attributes to restore on exit
Cname : Name_Id;
@@ -15047,7 +15034,7 @@ package body Sem_Prag is
-- False at compile time, and we do not want to delete this
-- warning when we delete the if statement.
- if Expander_Active and Is_Ignored (N) then
+ if Expander_Active and Is_Ignored_In_Codegen (N) then
Eloc := Sloc (Expr);
Rewrite (N,
@@ -15100,7 +15087,7 @@ package body Sem_Prag is
In_Assertion_Expr := In_Assertion_Expr - 1;
end if;
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
end Check;
--------------------------
@@ -16246,10 +16233,10 @@ package body Sem_Prag is
Cond :=
New_Occurrence_Of
(Boolean_Literals
- (Expander_Active and then not Is_Ignored (N)),
+ (Expander_Active and then not Is_Ignored_In_Codegen (N)),
Loc);
- if not Is_Ignored (N) then
+ if not Is_Ignored_In_Codegen (N) then
Set_SCO_Pragma_Enabled (Loc);
end if;
@@ -18720,7 +18707,7 @@ package body Sem_Prag is
-- region (SPARK RM 6.9(6)).
if Is_False (Expr_Value (Expr))
- and then Ghost_Mode > None
+ and then Ghost_Config.Ghost_Mode > None
then
Error_Pragma
("pragma % with value False cannot appear in enabled "
@@ -28323,8 +28310,7 @@ package body Sem_Prag is
Expr : constant Node_Id := Expression (Get_Argument (N, Spec_Id));
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
-- Save the Ghost-related attributes to restore on exit
Errors : Nat;
@@ -28417,7 +28403,7 @@ package body Sem_Prag is
Check_Postcondition_Use_In_Inlined_Subprogram (N, Spec_Id);
Set_Is_Analyzed_Pragma (N);
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
end Analyze_Pre_Post_Condition_In_Decl_Part;
---------------------------------------
@@ -28437,8 +28423,7 @@ package body Sem_Prag is
Arg1 : constant Node_Id :=
First (Pragma_Argument_Associations (N));
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
-- Save the Ghost-related attributes to restore on exit
Errors : Nat;
@@ -28561,7 +28546,7 @@ package body Sem_Prag is
Check_Postcondition_Use_In_Inlined_Subprogram (N, Spec_Id);
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
end if;
Set_Is_Analyzed_Pragma (N);
@@ -31803,8 +31788,7 @@ package body Sem_Prag is
Variants : constant Node_Id := Expression (Get_Argument (N, Spec_Id));
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
-- Save the Ghost-related attributes to restore on exit
Variant : Node_Id;
@@ -31899,7 +31883,7 @@ package body Sem_Prag is
Set_Is_Analyzed_Pragma (N);
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
end Analyze_Subprogram_Variant_In_Decl_Part;
------------------------------------
@@ -32195,20 +32179,8 @@ package body Sem_Prag is
when Name_Ignore
| Name_Off
=>
- -- In CodePeer mode and GNATprove mode, we need to
- -- consider all assertions, unless they are disabled.
- -- Force Is_Checked on ignored assertions, in particular
- -- because transformations of the AST may depend on
- -- assertions being checked (e.g. the translation of
- -- attribute 'Loop_Entry).
-
- if CodePeer_Mode or GNATprove_Mode then
- Set_Is_Checked (N, True);
- Set_Is_Ignored (N, False);
- else
- Set_Is_Checked (N, False);
- Set_Is_Ignored (N, True);
- end if;
+ Set_Is_Checked (N, False);
+ Set_Is_Ignored (N, True);
when Name_Check
| Name_On
@@ -34270,113 +34242,123 @@ package body Sem_Prag is
(N : Node_Id;
Eloc : Source_Ptr)
is
- Arg1 : constant Node_Id := First (Pragma_Argument_Associations (N));
- Arg1x : constant Node_Id := Get_Pragma_Arg (Arg1);
- Arg2 : constant Node_Id := Next (Arg1);
+ Arg1 : constant Node_Id := First (Pragma_Argument_Associations (N));
+ Arg1x : constant Node_Id := Get_Pragma_Arg (Arg1);
+ Prag_Id : constant Pragma_Id := Get_Pragma_Id (N);
- Pname : constant Name_Id := Pragma_Name_Unmapped (N);
- Prag_Id : constant Pragma_Id := Get_Pragma_Id (Pname);
+ procedure Emit_Compile_Time_Message (Msg_Arg : Node_Id);
+ -- Emit the pragma a as diagnostic message. New_Line characters are
+ -- considered separators for those messages where the following lines
+ -- are considered as continuation messages for the same diagnostic.
- begin
- Analyze_And_Resolve (Arg1x, Standard_Boolean);
+ -------------------------------
+ -- Emit_Compile_Time_Message --
+ -------------------------------
- if Compile_Time_Known_Value (Arg1x) then
- if Is_True (Expr_Value (Arg1x)) then
+ procedure Emit_Compile_Time_Message (Msg_Arg : Node_Id) is
+ -- We have already verified that the Msg_Arg is a static
+ -- string expression. Its string value must be retrieved
+ -- explicitly if it is a declared constant, otherwise it has
+ -- been constant-folded previously.
+
+ Cent : constant Entity_Id := Cunit_Entity (Current_Sem_Unit);
+ Str : constant String_Id :=
+ Strval (Expr_Value_S (Get_Pragma_Arg (Msg_Arg)));
+ Str_Len : constant Nat := String_Length (Str);
+
+ Force : constant Boolean :=
+ Prag_Id = Pragma_Compile_Time_Warning
+ and then Is_Spec_Name (Unit_Name (Current_Sem_Unit))
+ and then (Ekind (Cent) /= E_Package
+ or else not In_Private_Part (Cent));
+ -- Set True if this is the warning case, and we are in the
+ -- visible part of a package spec, or in a subprogram spec,
+ -- in which case we want to force the client to see the
+ -- warning, even though it is not in the main unit.
+
+ Msg_Ctrl : Bounded_String (6);
+ -- Control characters for the message.
+ -- The longest value contains 6 characters: "\<<~!!"
+
+ C : Character;
+ CC : Char_Code;
+ Cont : Boolean;
+ Ptr : Nat;
- -- We have already verified that the second argument is a static
- -- string expression. Its string value must be retrieved
- -- explicitly if it is a declared constant, otherwise it has
- -- been constant-folded previously.
+ begin
+ -- Loop through segments of message separated by line feeds.
+ -- We output these segments as separate messages with
+ -- continuation marks for all but the first.
- declare
- Cent : constant Entity_Id := Cunit_Entity (Current_Sem_Unit);
- Str : constant String_Id :=
- Strval (Expr_Value_S (Get_Pragma_Arg (Arg2)));
- Str_Len : constant Nat := String_Length (Str);
-
- Force : constant Boolean :=
- Prag_Id = Pragma_Compile_Time_Warning
- and then Is_Spec_Name (Unit_Name (Current_Sem_Unit))
- and then (Ekind (Cent) /= E_Package
- or else not In_Private_Part (Cent));
- -- Set True if this is the warning case, and we are in the
- -- visible part of a package spec, or in a subprogram spec,
- -- in which case we want to force the client to see the
- -- warning, even though it is not in the main unit.
-
- C : Character;
- CC : Char_Code;
- Cont : Boolean;
- Ptr : Nat;
+ Cont := False;
+ Ptr := 1;
+ loop
+ Error_Msg_Strlen := 0;
+ Msg_Ctrl.Length := 0;
- begin
- -- Loop through segments of message separated by line feeds.
- -- We output these segments as separate messages with
- -- continuation marks for all but the first.
+ -- Loop to copy characters from argument to error message
+ -- string buffer.
- Cont := False;
- Ptr := 1;
- loop
- Error_Msg_Strlen := 0;
+ loop
+ exit when Ptr > Str_Len;
+ CC := Get_String_Char (Str, Ptr);
+ Ptr := Ptr + 1;
- -- Loop to copy characters from argument to error message
- -- string buffer.
+ -- Ignore wide chars ??? else store character
- loop
- exit when Ptr > Str_Len;
- CC := Get_String_Char (Str, Ptr);
- Ptr := Ptr + 1;
+ if In_Character_Range (CC) then
+ C := Get_Character (CC);
+ exit when C = ASCII.LF;
+ Error_Msg_Strlen := Error_Msg_Strlen + 1;
+ Error_Msg_String (Error_Msg_Strlen) := C;
+ end if;
+ end loop;
- -- Ignore wide chars ??? else store character
+ -- Here with one line ready to go
- if In_Character_Range (CC) then
- C := Get_Character (CC);
- exit when C = ASCII.LF;
- Error_Msg_Strlen := Error_Msg_Strlen + 1;
- Error_Msg_String (Error_Msg_Strlen) := C;
- end if;
- end loop;
+ Error_Msg_Warn := Prag_Id = Pragma_Compile_Time_Warning;
- -- Here with one line ready to go
+ if Cont then
+ Append (Msg_Ctrl, "\");
+ end if;
- Error_Msg_Warn := Prag_Id = Pragma_Compile_Time_Warning;
+ Append (Msg_Ctrl, "<<~");
- -- If this is a warning in a spec, then we want clients
- -- to see the warning, so mark the message with the
- -- special sequence !! to force the warning. In the case
- -- of a package spec, we do not force this if we are in
- -- the private part of the spec.
+ -- If this is a warning in a spec, then we want clients
+ -- to see the warning, so mark the message with the
+ -- special sequence !! to force the warning. In the case
+ -- of a package spec, we do not force this if we are in
+ -- the private part of the spec.
- if Force then
- if Cont = False then
- Error_Msg
- ("<<~!!", Eloc, N, Is_Compile_Time_Pragma => True);
- Cont := True;
- else
- Error_Msg
- ("\<<~!!", Eloc, N, Is_Compile_Time_Pragma => True);
- end if;
+ if Force then
+ Append (Msg_Ctrl, "!!");
+ end if;
- -- Error, rather than warning, or in a body, so we do not
- -- need to force visibility for client (error will be
- -- output in any case, and this is the situation in which
- -- we do not want a client to get a warning, since the
- -- warning is in the body or the spec private part).
+ -- Error, rather than warning, or in a body, so we do not
+ -- need to force visibility for client (error will be
+ -- output in any case, and this is the situation in which
+ -- we do not want a client to get a warning, since the
+ -- warning is in the body or the spec private part).
- else
- if Cont = False then
- Error_Msg
- ("<<~", Eloc, N, Is_Compile_Time_Pragma => True);
- Cont := True;
- else
- Error_Msg
- ("\<<~", Eloc, N, Is_Compile_Time_Pragma => True);
- end if;
- end if;
+ Error_Msg
+ (To_String (Msg_Ctrl), Eloc, N, Is_Compile_Time_Pragma => True);
- exit when Ptr > Str_Len;
- end loop;
- end;
+ -- The next lines are considered continuation messages
+
+ Cont := True;
+
+ exit when Ptr > Str_Len;
+ end loop;
+ end Emit_Compile_Time_Message;
+
+ -- Start of processing for Validate_Compile_Time_Warning_Or_Error
+
+ begin
+ Analyze_And_Resolve (Arg1x, Standard_Boolean);
+
+ if Compile_Time_Known_Value (Arg1x) then
+ if Is_True (Expr_Value (Arg1x)) then
+ Emit_Compile_Time_Message (Next (Arg1));
end if;
-- Arg1x is not known at compile time, so possibly issue an error
@@ -35101,7 +35083,17 @@ package body Sem_Prag is
begin
Set_Scope (T.Scope);
Reset_Analyzed_Flags (T.Prag);
- Validate_Compile_Time_Warning_Or_Error (T.Prag, T.Eloc);
+ if Nkind (T.Prag) = N_Pragma then
+ Validate_Compile_Time_Warning_Or_Error (T.Prag, T.Eloc);
+ else
+ pragma Assert (Nkind (Original_Node (T.Prag)) = N_Pragma);
+
+ -- The pragma was likely removed in ignored ghost code. Check
+ -- the original node instead.
+
+ Validate_Compile_Time_Warning_Or_Error
+ (Original_Node (T.Prag), T.Eloc);
+ end if;
Unset_Scope (T.Scope);
end;
end loop;
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index b2b4fed..d19b3b9 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -1963,8 +1963,7 @@ package body Sem_Util is
-- Local variables
- Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
- Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ Saved_Ghost_Config : constant Ghost_Config_Type := Ghost_Config;
-- Save the Ghost-related attributes to restore on exit
-- Start of processing for Build_Elaboration_Entity
@@ -2060,7 +2059,7 @@ package body Sem_Util is
Set_Has_Qualified_Name (Elab_Ent);
Set_Has_Fully_Qualified_Name (Elab_Ent);
- Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ Restore_Ghost_Region (Saved_Ghost_Config);
end Build_Elaboration_Entity;
--------------------------------
@@ -12473,6 +12472,41 @@ package body Sem_Util is
end if;
end Is_Extended_Access_Type;
+ ----------------------------------------
+ -- Is_Ignored_Ghost_Entity_In_Codegen --
+ ----------------------------------------
+
+ function Is_Ignored_Ghost_Entity_In_Codegen (N : Entity_Id) return Boolean
+ is
+ begin
+ return
+ Is_Ignored_Ghost_Entity (N)
+ and then not GNATprove_Mode
+ and then not CodePeer_Mode;
+ end Is_Ignored_Ghost_Entity_In_Codegen;
+
+ ----------------------------------------
+ -- Is_Ignored_Ghost_Pragma_In_Codegen --
+ ----------------------------------------
+
+ function Is_Ignored_Ghost_Pragma_In_Codegen (N : Node_Id) return Boolean is
+ begin
+ return
+ Is_Ignored_Ghost_Pragma (N)
+ and then not GNATprove_Mode
+ and then not CodePeer_Mode;
+ end Is_Ignored_Ghost_Pragma_In_Codegen;
+
+ ---------------------------
+ -- Is_Ignored_In_Codegen --
+ ---------------------------
+
+ function Is_Ignored_In_Codegen (N : Node_Id) return Boolean is
+ begin
+ return
+ Is_Ignored (N) and then not GNATprove_Mode and then not CodePeer_Mode;
+ end Is_Ignored_In_Codegen;
+
---------------------------------
-- Side_Effect_Free_Statements --
---------------------------------
@@ -22574,7 +22608,7 @@ package body Sem_Util is
-- Mark the Ghost and SPARK mode in effect
if Modes then
- if Ghost_Mode = Ignore then
+ if Ghost_Config.Ghost_Mode = Ignore then
Set_Is_Ignored_Ghost_Node (N);
end if;
@@ -26439,16 +26473,6 @@ package body Sem_Util is
end if;
end if;
- -- In CodePeer mode and GNATprove mode, we need to consider all
- -- assertions, unless they are disabled. Force Name_Check on
- -- ignored assertions.
-
- if Kind in Name_Ignore | Name_Off
- and then (CodePeer_Mode or GNATprove_Mode)
- then
- Kind := Name_Check;
- end if;
-
return Kind;
end Policy_In_Effect;
@@ -26482,9 +26506,11 @@ package body Sem_Util is
function Predicate_Enabled (Typ : Entity_Id) return Boolean is
begin
- return Present (Predicate_Function (Typ))
- and then not Predicates_Ignored (Typ)
- and then not Predicate_Checks_Suppressed (Empty);
+ return
+ Present (Predicate_Function (Typ))
+ and then (GNATprove_Mode
+ or else (not Predicates_Ignored (Typ)
+ and then not Predicate_Checks_Suppressed (Empty)));
end Predicate_Enabled;
----------------------------------
diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads
index 4554f24..47fcc7d 100644
--- a/gcc/ada/sem_util.ads
+++ b/gcc/ada/sem_util.ads
@@ -2079,6 +2079,18 @@ package Sem_Util is
-- . machine_emax = 2**14
-- . machine_emin = 3 - machine_emax
+ function Is_Ignored_Ghost_Entity_In_Codegen (N : Node_Id) return Boolean;
+ -- True if N Is_Ignored_Ghost_Entity and GNATProve_mode and Codepeer_Mode
+ -- are not active.
+
+ function Is_Ignored_Ghost_Pragma_In_Codegen (N : Node_Id) return Boolean;
+ -- True if N Is_Ignored_Ghost_Pragma and GNATProve_mode and Codepeer_Mode
+ -- are not active.
+
+ function Is_Ignored_In_Codegen (N : Node_Id) return Boolean;
+ -- True if N Is_Ignored and GNATProve_mode and Codepeer_Mode are not
+ -- active.
+
function Is_EVF_Expression (N : Node_Id) return Boolean;
-- Determine whether node N denotes a reference to a formal parameter of
-- a specific tagged type whose related subprogram is subject to pragma
diff --git a/gcc/ada/table.adb b/gcc/ada/table.adb
index 37c4949..31891de 100644
--- a/gcc/ada/table.adb
+++ b/gcc/ada/table.adb
@@ -40,6 +40,9 @@ package body Table is
Min : constant Int := Int (Table_Low_Bound);
-- Subscript of the minimum entry in the currently allocated table
+ Max : Int := Min + (Table_Initial * Table_Factor) - 1;
+ -- Subscript of the maximum entry in the currently allocated table
+
Length : Int := 0;
-- Number of entries in currently allocated table. The value of zero
-- ensures that we initially allocate the table.
diff --git a/gcc/ada/table.ads b/gcc/ada/table.ads
index 22e9172..623ce14 100644
--- a/gcc/ada/table.ads
+++ b/gcc/ada/table.ads
@@ -223,9 +223,6 @@ package Table is
-- the official interfaces (since a modification to Last may require a
-- reallocation of the table).
- Max : Int;
- -- Subscript of the maximum entry in the currently allocated table
-
type Saved_Table is record
Last_Val : Int;
Max : Int;
diff --git a/gcc/ada/treepr.adb b/gcc/ada/treepr.adb
index 375608d..857b926 100644
--- a/gcc/ada/treepr.adb
+++ b/gcc/ada/treepr.adb
@@ -1600,19 +1600,17 @@ package body Treepr is
-- If this is a discrete expression whose value is known, print that
-- value.
- if Nkind (N) in N_Subexpr
+ if ((Is_Entity_Name (N) -- e.g. enumeration literal
+ and then Present (Entity (N)))
+ or else Nkind (N) in N_Integer_Literal
+ | N_Character_Literal
+ | N_Unchecked_Type_Conversion)
and then Compile_Time_Known_Value (N)
and then Present (Etype (N))
and then Is_Discrete_Type (Etype (N))
then
- if Is_Entity_Name (N) -- e.g. enumeration literal
- or else Nkind (N) in N_Integer_Literal
- | N_Character_Literal
- | N_Unchecked_Type_Conversion
- then
- Print_Str (" val = ");
- UI_Write (Expr_Value (N));
- end if;
+ Print_Str (" val = ");
+ UI_Write (Expr_Value (N));
end if;
if Nkind (N) in N_Entity then
diff --git a/gcc/avoid-store-forwarding.cc b/gcc/avoid-store-forwarding.cc
index 1de6fd6..78ed736 100644
--- a/gcc/avoid-store-forwarding.cc
+++ b/gcc/avoid-store-forwarding.cc
@@ -145,11 +145,18 @@ is_store_forwarding (rtx store_mem, rtx load_mem, HOST_WIDE_INT *off_val)
poly_int64 load_offset, store_offset;
rtx load_base = strip_offset (XEXP (load_mem, 0), &load_offset);
rtx store_base = strip_offset (XEXP (store_mem, 0), &store_offset);
+ poly_int64 off_diff = store_offset - load_offset;
+
+ HOST_WIDE_INT off_val_tmp = 0;
+ bool is_off_diff_constant = off_diff.is_constant (&off_val_tmp);
+ if (off_val)
+ *off_val = off_val_tmp;
+
return (MEM_SIZE (load_mem).is_constant ()
&& rtx_equal_p (load_base, store_base)
&& known_subrange_p (store_offset, MEM_SIZE (store_mem),
load_offset, MEM_SIZE (load_mem))
- && (store_offset - load_offset).is_constant (off_val));
+ && is_off_diff_constant);
}
/* Given a list of small stores that are forwarded to LOAD_INSN, try to
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 4a13fc0..814accf 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -16659,7 +16659,7 @@ c_parser_omp_variable_list (c_parser *parser,
|| CONVERT_EXPR_P (decl))
decl = TREE_OPERAND (decl, 0);
- tree u = build_omp_clause (clause_loc, kind);
+ tree u = build_omp_clause (loc, kind);
OMP_CLAUSE_DECL (u) = decl;
OMP_CLAUSE_CHAIN (u) = list;
list = u;
@@ -20072,7 +20072,7 @@ c_parser_omp_clause_doacross (c_parser *parser, tree list)
map ( [map-type-modifier[,] ...] map-kind: variable-list )
map-type-modifier:
- always | close */
+ always | close | present | iterator (iterators-definition) */
static tree
c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p)
@@ -20087,15 +20087,35 @@ c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p)
int pos = 1;
int map_kind_pos = 0;
- while (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_NAME)
+ int iterator_length = 0;
+ for (;;)
{
- if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COLON)
+ c_token *tok = c_parser_peek_nth_token_raw (parser, pos);
+ if (tok->type != CPP_NAME)
+ break;
+
+ const char *p = IDENTIFIER_POINTER (tok->value);
+ c_token *next_tok = c_parser_peek_nth_token_raw (parser, pos + 1);
+ if (strcmp (p, "iterator") == 0 && next_tok->type == CPP_OPEN_PAREN)
+ {
+ unsigned n = pos + 2;
+ if (c_parser_check_balanced_raw_token_sequence (parser, &n)
+ && c_parser_peek_nth_token_raw (parser, n)->type
+ == CPP_CLOSE_PAREN)
+ {
+ iterator_length = n - pos + 1;
+ pos = n;
+ next_tok = c_parser_peek_nth_token_raw (parser, pos + 1);
+ }
+ }
+
+ if (next_tok->type == CPP_COLON)
{
map_kind_pos = pos;
break;
}
- if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COMMA)
+ if (next_tok->type == CPP_COMMA)
pos++;
else if (c_parser_peek_nth_token_raw (parser, pos + 1)->type
== CPP_OPEN_PAREN)
@@ -20117,6 +20137,7 @@ c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p)
int present_modifier = 0;
int mapper_modifier = 0;
tree mapper_name = NULL_TREE;
+ tree iterators = NULL_TREE;
for (int pos = 1; pos < map_kind_pos; ++pos)
{
c_token *tok = c_parser_peek_token (parser);
@@ -20150,6 +20171,17 @@ c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p)
close_modifier++;
c_parser_consume_token (parser);
}
+ else if (strcmp ("iterator", p) == 0)
+ {
+ if (iterators)
+ {
+ c_parser_error (parser, "too many %<iterator%> modifiers");
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ iterators = c_parser_omp_iterators (parser);
+ pos += iterator_length - 1;
+ }
else if (strcmp ("mapper", p) == 0)
{
c_parser_consume_token (parser);
@@ -20223,8 +20255,8 @@ c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p)
else
{
c_parser_error (parser, "%<map%> clause with map-type modifier other "
- "than %<always%>, %<close%>, %<mapper%> or "
- "%<present%>");
+ "than %<always%>, %<close%>, %<iterator%>, "
+ "%<mapper%> or %<present%>");
parens.skip_until_found_close (parser);
return list;
}
@@ -20273,9 +20305,19 @@ c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p)
tree last_new = NULL_TREE;
+ if (iterators)
+ {
+ tree block = pop_scope ();
+ if (iterators == error_mark_node)
+ iterators = NULL_TREE;
+ else
+ TREE_VEC_ELT (iterators, 5) = block;
+ }
+
for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
{
OMP_CLAUSE_SET_MAP_KIND (c, kind);
+ OMP_CLAUSE_ITERATORS (c) = iterators;
last_new = c;
}
@@ -20534,8 +20576,11 @@ c_parser_omp_clause_device_type (c_parser *parser, tree list)
to ( variable-list )
OpenMP 5.1:
- from ( [present :] variable-list )
- to ( [present :] variable-list ) */
+ from ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list )
+ to ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list )
+
+ motion-modifier:
+ present | iterator (iterators-definition) */
static tree
c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind,
@@ -20546,18 +20591,85 @@ c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind,
if (!parens.require_open (parser))
return list;
+ int pos = 1, colon_pos = 0;
+ int iterator_length = 0;
+
+ while (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_NAME)
+ {
+ const char *identifier =
+ IDENTIFIER_POINTER (c_parser_peek_nth_token_raw (parser, pos)->value);
+ if (c_parser_peek_nth_token_raw (parser, pos + 1)->type
+ == CPP_OPEN_PAREN)
+ {
+ unsigned int npos = pos + 2;
+ if (c_parser_check_balanced_raw_token_sequence (parser, &npos)
+ && (c_parser_peek_nth_token_raw (parser, npos)->type
+ == CPP_CLOSE_PAREN))
+ {
+ if (strcmp (identifier, "iterator") == 0)
+ iterator_length = npos - pos + 1;
+ pos = npos;
+ }
+ }
+ if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COMMA)
+ pos += 2;
+ else
+ pos++;
+ if (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_COLON)
+ {
+ colon_pos = pos;
+ break;
+ }
+ }
+
bool present = false;
- c_token *token = c_parser_peek_token (parser);
+ tree iterators = NULL_TREE;
- if (token->type == CPP_NAME
- && strcmp (IDENTIFIER_POINTER (token->value), "present") == 0
- && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+ for (int pos = 1; pos < colon_pos; ++pos)
{
- present = true;
- c_parser_consume_token (parser);
- c_parser_consume_token (parser);
+ c_token *token = c_parser_peek_token (parser);
+ if (token->type == CPP_COMMA)
+ {
+ c_parser_consume_token (parser);
+ continue;
+ }
+ const char *p = IDENTIFIER_POINTER (token->value);
+ if (strcmp ("present", p) == 0)
+ {
+ if (present)
+ {
+ c_parser_error (parser, "too many %<present%> modifiers");
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ present = true;
+ c_parser_consume_token (parser);
+ }
+ else if (strcmp ("iterator", p) == 0)
+ {
+ if (iterators)
+ {
+ c_parser_error (parser, "too many %<iterator%> modifiers");
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ iterators = c_parser_omp_iterators (parser);
+ pos += iterator_length - 1;
+ }
+ else
+ {
+ error_at (token->location,
+ "%qs clause with modifier other than %<iterator%> or "
+ "%<present%>",
+ kind == OMP_CLAUSE_TO ? "to" : "from");
+ parens.skip_until_found_close (parser);
+ return list;
+ }
}
+ if (colon_pos)
+ c_parser_require (parser, CPP_COLON, "expected %<:%>");
+
tree nl = c_parser_omp_variable_list (parser, loc, kind, list);
parens.skip_until_found_close (parser);
@@ -20565,6 +20677,19 @@ c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind,
for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
OMP_CLAUSE_MOTION_PRESENT (c) = 1;
+ if (iterators)
+ {
+ tree block = pop_scope ();
+ if (iterators == error_mark_node)
+ iterators = NULL_TREE;
+ else
+ TREE_VEC_ELT (iterators, 5) = block;
+ }
+
+ if (iterators)
+ for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_ITERATORS (c) = iterators;
+
return nl;
}
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index ed6e56e..b192663 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -16204,7 +16204,14 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
/* We've reached the end of a list of expanded nodes. Reset the group
start pointer. */
if (c == grp_sentinel)
- grp_start_p = NULL;
+ {
+ if (grp_start_p
+ && OMP_CLAUSE_HAS_ITERATORS (*grp_start_p))
+ for (tree gc = *grp_start_p; gc != grp_sentinel;
+ gc = OMP_CLAUSE_CHAIN (gc))
+ OMP_CLAUSE_ITERATORS (gc) = OMP_CLAUSE_ITERATORS (*grp_start_p);
+ grp_start_p = NULL;
+ }
switch (OMP_CLAUSE_CODE (c))
{
@@ -16962,6 +16969,13 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
/* FALLTHRU */
case OMP_CLAUSE_TO:
case OMP_CLAUSE_FROM:
+ if (OMP_CLAUSE_ITERATORS (c)
+ && c_omp_finish_iterators (OMP_CLAUSE_ITERATORS (c)))
+ {
+ t = error_mark_node;
+ break;
+ }
+ /* FALLTHRU */
case OMP_CLAUSE__CACHE_:
{
using namespace omp_addr_tokenizer;
@@ -17690,6 +17704,11 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
pc = &OMP_CLAUSE_CHAIN (c);
}
+ if (grp_start_p
+ && OMP_CLAUSE_HAS_ITERATORS (*grp_start_p))
+ for (tree gc = *grp_start_p; gc; gc = OMP_CLAUSE_CHAIN (gc))
+ OMP_CLAUSE_ITERATORS (gc) = OMP_CLAUSE_ITERATORS (*grp_start_p);
+
if (simdlen
&& safelen
&& tree_int_cst_lt (OMP_CLAUSE_SAFELEN_EXPR (safelen),
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 38c307c..36bd885 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -1020,7 +1020,7 @@ void aarch64_err_no_fpadvsimd (machine_mode);
void aarch64_expand_epilogue (rtx_call_insn *);
rtx aarch64_ptrue_all (unsigned int);
opt_machine_mode aarch64_ptrue_all_mode (rtx);
-rtx aarch64_convert_sve_data_to_pred (rtx, machine_mode, rtx);
+rtx aarch64_convert_sve_data_to_pred (rtx, rtx);
rtx aarch64_expand_sve_dupq (rtx, machine_mode, rtx);
void aarch64_expand_mov_immediate (rtx, rtx);
rtx aarch64_stack_protect_canary_mem (machine_mode, rtx, aarch64_salt_type);
@@ -1039,6 +1039,7 @@ void aarch64_expand_sve_mem_move (rtx, rtx, machine_mode);
bool aarch64_maybe_expand_sve_subreg_move (rtx, rtx);
rtx aarch64_replace_reg_mode (rtx, machine_mode);
void aarch64_split_sve_subreg_move (rtx, rtx, rtx);
+void aarch64_emit_sve_pred_vec_duplicate (machine_mode, rtx, rtx);
void aarch64_expand_prologue (void);
void aarch64_decompose_vec_struct_index (machine_mode, rtx *, rtx *, bool);
void aarch64_expand_vector_init (rtx, rtx);
diff --git a/gcc/config/aarch64/aarch64-sve-builtins-base.cc b/gcc/config/aarch64/aarch64-sve-builtins-base.cc
index b439683..ecc0687 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins-base.cc
+++ b/gcc/config/aarch64/aarch64-sve-builtins-base.cc
@@ -214,7 +214,8 @@ public:
expand (function_expander &e) const override
{
e.add_ptrue_hint (0, e.gp_mode (0));
- insn_code icode = code_for_aarch64_pred_fac (m_unspec, e.vector_mode (0));
+ insn_code icode = code_for_aarch64_pred_fac_acle (m_unspec,
+ e.vector_mode (0));
return e.use_exact_insn (icode);
}
@@ -497,10 +498,10 @@ public:
{
bool unsigned_p = e.type_suffix (0).unsigned_p;
rtx_code code = get_rtx_code (m_code, unsigned_p);
- return e.use_exact_insn (code_for_aarch64_pred_cmp (code, mode));
+ return e.use_exact_insn (code_for_aarch64_pred_cmp_acle (code, mode));
}
- insn_code icode = code_for_aarch64_pred_fcm (m_unspec_for_fp, mode);
+ insn_code icode = code_for_aarch64_pred_fcm_acle (m_unspec_for_fp, mode);
return e.use_exact_insn (icode);
}
@@ -542,7 +543,7 @@ public:
/* If the argument is a constant that the unwidened comparisons
can handle directly, use them instead. */
- insn_code icode = code_for_aarch64_pred_cmp (code, mode);
+ insn_code icode = code_for_aarch64_pred_cmp_acle (code, mode);
rtx op2 = unwrap_const_vec_duplicate (e.args[3]);
if (CONSTANT_P (op2)
&& insn_data[icode].operand[4].predicate (op2, DImode))
@@ -581,7 +582,8 @@ public:
expand (function_expander &e) const override
{
e.add_ptrue_hint (0, e.gp_mode (0));
- return e.use_exact_insn (code_for_aarch64_pred_fcmuo (e.vector_mode (0)));
+ auto mode = e.vector_mode (0);
+ return e.use_exact_insn (code_for_aarch64_pred_fcmuo_acle (mode));
}
};
@@ -1048,6 +1050,23 @@ public:
rtx
expand (function_expander &e) const override
{
+ machine_mode mode = e.vector_mode (0);
+ if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL)
+ {
+ gcc_assert (e.pred == PRED_none);
+
+ rtx src = e.args[0];
+ if (GET_CODE (src) == CONST_INT)
+ return (src == const0_rtx
+ ? CONST0_RTX (VNx16BImode)
+ : aarch64_ptrue_all (e.type_suffix (0).element_bytes));
+
+ rtx dest = e.get_reg_target ();
+ src = force_reg (GET_MODE (src), src);
+ aarch64_emit_sve_pred_vec_duplicate (mode, dest, src);
+ return dest;
+ }
+
if (e.pred == PRED_none || e.pred == PRED_x)
/* There's no benefit to using predicated instructions for _x here. */
return e.use_unpred_insn (e.direct_optab_handler (vec_duplicate_optab));
@@ -1056,7 +1075,6 @@ public:
the duplicate of the function argument and the "false" value
is the value of inactive lanes. */
insn_code icode;
- machine_mode mode = e.vector_mode (0);
if (valid_for_const_vector_p (GET_MODE_INNER (mode), e.args.last ()))
/* Duplicate the constant to fill a vector. The pattern optimizes
various cases involving constant operands, falling back to SEL
@@ -1197,8 +1215,7 @@ public:
if (mode != e.vector_mode (0))
{
rtx data_dupq = aarch64_expand_sve_dupq (NULL, mode, vq_reg);
- return aarch64_convert_sve_data_to_pred (e.possible_target,
- e.vector_mode (0), data_dupq);
+ return aarch64_convert_sve_data_to_pred (e.possible_target, data_dupq);
}
return aarch64_expand_sve_dupq (e.possible_target, mode, vq_reg);
@@ -1259,9 +1276,10 @@ public:
index = target;
}
- e.args[0] = gen_lowpart (VNx2DImode, e.args[0]);
+ e.args[0] = aarch64_sve_reinterpret (VNx2DImode, e.args[0]);
e.args[1] = index;
- return e.use_exact_insn (CODE_FOR_aarch64_sve_tblvnx2di);
+ rtx res = e.use_exact_insn (CODE_FOR_aarch64_sve_tblvnx2di);
+ return aarch64_sve_reinterpret (mode, res);
}
};
@@ -2857,7 +2875,10 @@ public:
rtx
expand (function_expander &e) const override
{
- return e.use_exact_insn (code_for_aarch64_sve_rev (e.vector_mode (0)));
+ auto mode = e.vector_mode (0);
+ return e.use_exact_insn (e.type_suffix (0).bool_p
+ ? code_for_aarch64_sve_rev_acle (mode)
+ : code_for_aarch64_sve_rev (mode));
}
};
@@ -3248,7 +3269,7 @@ public:
unsigned int unpacks = m_high_p ? UNSPEC_UNPACKSHI : UNSPEC_UNPACKSLO;
insn_code icode;
if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL)
- icode = code_for_aarch64_sve_punpk (unpacku, mode);
+ icode = code_for_aarch64_sve_punpk_acle (unpacku);
else
{
int unspec = e.type_suffix (0).unsigned_p ? unpacku : unpacks;
diff --git a/gcc/config/aarch64/aarch64-sve-builtins-functions.h b/gcc/config/aarch64/aarch64-sve-builtins-functions.h
index 6f1c694..c05946d 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins-functions.h
+++ b/gcc/config/aarch64/aarch64-sve-builtins-functions.h
@@ -630,7 +630,10 @@ public:
rtx
expand (function_expander &e) const override
{
- insn_code icode = code_for_aarch64_sve (m_unspec, e.vector_mode (0));
+ auto mode = e.vector_mode (0);
+ insn_code icode = (e.type_suffix (0).bool_p
+ ? code_for_aarch64_sve_acle (m_unspec, mode)
+ : code_for_aarch64_sve (m_unspec, mode));
return e.use_exact_insn (icode);
}
@@ -838,7 +841,8 @@ public:
machine_mode pred_mode = e.vector_mode (0);
scalar_mode reg_mode = GET_MODE_INNER (e.vector_mode (1));
- return e.use_exact_insn (code_for_while (unspec, reg_mode, pred_mode));
+ auto icode = code_for_aarch64_sve_while_acle (unspec, reg_mode, pred_mode);
+ return e.use_exact_insn (icode);
}
/* The unspec codes associated with signed and unsigned operations
diff --git a/gcc/config/aarch64/aarch64-sve-builtins-sve2.cc b/gcc/config/aarch64/aarch64-sve-builtins-sve2.cc
index 73004a8..95c5ed8 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins-sve2.cc
+++ b/gcc/config/aarch64/aarch64-sve-builtins-sve2.cc
@@ -881,7 +881,9 @@ public:
{
for (unsigned int i = 0; i < 2; ++i)
e.args[i] = e.convert_to_pmode (e.args[i]);
- return e.use_exact_insn (code_for_while (m_unspec, Pmode, e.gp_mode (0)));
+ auto icode = code_for_aarch64_sve_while_acle (m_unspec, Pmode,
+ e.gp_mode (0));
+ return e.use_exact_insn (icode);
}
int m_unspec;
diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc
index 01833a8..e394c9a 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins.cc
+++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
@@ -4593,7 +4593,27 @@ function_expander::expand ()
gcc_assert (args.last ()->mode == DImode);
emit_move_insn (gen_rtx_REG (DImode, FPM_REGNUM), args.last ());
}
- return base->expand (*this);
+ rtx result = base->expand (*this);
+ if (function_returns_void_p ())
+ gcc_assert (result == const0_rtx);
+ else
+ {
+ auto expected_mode = result_mode ();
+ if (GET_MODE_CLASS (expected_mode) == MODE_INT)
+ /* Scalar integer constants don't store a mode.
+
+ It's OK for a variable result to have a different mode from the
+ function return type. In particular, some functions that return int
+ expand into instructions that have a DImode result, with all 64 bits
+ of the DImode being well-defined (usually zero). */
+ gcc_assert (CONST_SCALAR_INT_P (result)
+ || GET_MODE_CLASS (GET_MODE (result)) == MODE_INT);
+ else
+ /* In other cases, the return value should have the same mode
+ as the return type. */
+ gcc_assert (GET_MODE (result) == expected_mode);
+ }
+ return result;
}
/* Return a structure type that contains a single field of type FIELD_TYPE.
diff --git a/gcc/config/aarch64/aarch64-sve.md b/gcc/config/aarch64/aarch64-sve.md
index 80a3288..88d323a 100644
--- a/gcc/config/aarch64/aarch64-sve.md
+++ b/gcc/config/aarch64/aarch64-sve.md
@@ -2990,10 +2990,7 @@
(vec_duplicate:PRED_ALL (match_operand:QI 1 "register_operand")))]
"TARGET_SVE"
{
- rtx tmp = gen_reg_rtx (DImode);
- rtx op1 = gen_lowpart (DImode, operands[1]);
- emit_insn (gen_ashldi3 (tmp, op1, gen_int_mode (63, DImode)));
- emit_insn (gen_while_ultdi<mode> (operands[0], const0_rtx, tmp));
+ aarch64_emit_sve_pred_vec_duplicate (<MODE>mode, operands[0], operands[1]);
DONE;
}
)
@@ -8361,6 +8358,71 @@
}
)
+;; Likewise, but yield a VNx16BI result regardless of the element width.
+;; The .b case is equivalent to the above.
+(define_expand "@aarch64_pred_cmp<cmp_op><mode>_acle"
+ [(parallel
+ [(set (match_operand:<VPRED> 0 "register_operand")
+ (unspec:<VPRED>
+ [(match_operand:<VPRED> 1 "register_operand")
+ (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+ (SVE_INT_CMP:<VPRED>
+ (match_operand:VNx16QI_ONLY 3 "register_operand")
+ (match_operand:VNx16QI_ONLY 4 "aarch64_sve_cmp_<sve_imm_con>_operand"))]
+ UNSPEC_PRED_Z))
+ (clobber (reg:CC_NZC CC_REGNUM))])]
+ "TARGET_SVE"
+)
+
+;; For wider elements, bitcast the predicate result to a VNx16BI and use
+;; an (and ...) to indicate that only every second, fourth, or eighth bit
+;; is set.
+(define_expand "@aarch64_pred_cmp<cmp_op><mode>_acle"
+ [(parallel
+ [(set (match_operand:VNx16BI 0 "register_operand")
+ (and:VNx16BI
+ (subreg:VNx16BI
+ (unspec:<VPRED>
+ [(match_operand:<VPRED> 1 "register_operand")
+ (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+ (SVE_INT_CMP:<VPRED>
+ (match_operand:SVE_FULL_HSDI 3 "register_operand")
+ (match_operand:SVE_FULL_HSDI 4 "aarch64_sve_cmp_<sve_imm_con>_operand"))]
+ UNSPEC_PRED_Z)
+ 0)
+ (match_dup 5)))
+ (clobber (reg:CC_NZC CC_REGNUM))])]
+ "TARGET_SVE"
+ {
+ operands[5] = aarch64_ptrue_all (GET_MODE_UNIT_SIZE (<MODE>mode));
+ }
+)
+
+(define_insn "*aarch64_pred_cmp<cmp_op><mode>_acle"
+ [(set (match_operand:VNx16BI 0 "register_operand")
+ (and:VNx16BI
+ (subreg:VNx16BI
+ (unspec:<VPRED>
+ [(match_operand:<VPRED> 1 "register_operand")
+ (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+ (SVE_INT_CMP:<VPRED>
+ (match_operand:SVE_FULL_HSDI 3 "register_operand")
+ (match_operand:SVE_FULL_HSDI 4 "aarch64_sve_cmp_<sve_imm_con>_operand"))]
+ UNSPEC_PRED_Z)
+ 0)
+ (match_operand:<VPRED> 5 "aarch64_ptrue_all_operand")))
+ (clobber (reg:CC_NZC CC_REGNUM))]
+ "TARGET_SVE"
+ {@ [ cons: =0 , 1 , 3 , 4 ; attrs: pred_clobber ]
+ [ &Upa , Upl, w , <sve_imm_con>; yes ] cmp<cmp_op>\t%0.<Vetype>, %1/z, %3.<Vetype>, #%4
+ [ ?Upl , 0 , w , <sve_imm_con>; yes ] ^
+ [ Upa , Upl, w , <sve_imm_con>; no ] ^
+ [ &Upa , Upl, w , w ; yes ] cmp<cmp_op>\t%0.<Vetype>, %1/z, %3.<Vetype>, %4.<Vetype>
+ [ ?Upl , 0 , w , w ; yes ] ^
+ [ Upa , Upl, w , w ; no ] ^
+ }
+)
+
;; Predicated integer comparisons in which both the flag and predicate
;; results are interesting.
(define_insn_and_rewrite "*cmp<cmp_op><mode>_cc"
@@ -8402,6 +8464,49 @@
}
)
+(define_insn_and_rewrite "*cmp<cmp_op><mode>_acle_cc"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand:VNx16BI 1 "register_operand")
+ (match_operand 4)
+ (match_operand:SI 5 "aarch64_sve_ptrue_flag")
+ (unspec:<VPRED>
+ [(match_operand 6)
+ (match_operand:SI 7 "aarch64_sve_ptrue_flag")
+ (SVE_INT_CMP:<VPRED>
+ (match_operand:SVE_FULL_HSDI 2 "register_operand")
+ (match_operand:SVE_FULL_HSDI 3 "aarch64_sve_cmp_<sve_imm_con>_operand"))]
+ UNSPEC_PRED_Z)]
+ UNSPEC_PTEST))
+ (set (match_operand:VNx16BI 0 "register_operand")
+ (and:VNx16BI
+ (subreg:VNx16BI
+ (unspec:<VPRED>
+ [(match_dup 6)
+ (match_dup 7)
+ (SVE_INT_CMP:<VPRED>
+ (match_dup 2)
+ (match_dup 3))]
+ UNSPEC_PRED_Z)
+ 0)
+ (match_operand:<VPRED> 8 "aarch64_ptrue_all_operand")))]
+ "TARGET_SVE
+ && aarch64_sve_same_pred_for_ptest_p (&operands[4], &operands[6])"
+ {@ [ cons: =0 , 1 , 2 , 3 ; attrs: pred_clobber ]
+ [ &Upa , Upl, w , <sve_imm_con>; yes ] cmp<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, #%3
+ [ ?Upl , 0 , w , <sve_imm_con>; yes ] ^
+ [ Upa , Upl, w , <sve_imm_con>; no ] ^
+ [ &Upa , Upl, w , w ; yes ] cmp<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>
+ [ ?Upl , 0 , w , w ; yes ] ^
+ [ Upa , Upl, w , w ; no ] ^
+ }
+ "&& !rtx_equal_p (operands[4], operands[6])"
+ {
+ operands[6] = copy_rtx (operands[4]);
+ operands[7] = operands[5];
+ }
+)
+
;; Predicated integer comparisons in which only the flags result is
;; interesting.
(define_insn_and_rewrite "*cmp<cmp_op><mode>_ptest"
@@ -8467,14 +8572,52 @@
(clobber (reg:CC_NZC CC_REGNUM))])]
)
+(define_insn_and_split "*cmp<cmp_op><mode>_acle_and"
+ [(set (match_operand:VNx16BI 0 "register_operand" "=Upa, Upa")
+ (and:VNx16BI
+ (and:VNx16BI
+ (subreg:VNx16BI
+ (unspec:<VPRED>
+ [(match_operand 4)
+ (const_int SVE_KNOWN_PTRUE)
+ (SVE_INT_CMP:<VPRED>
+ (match_operand:SVE_FULL_HSDI 2 "register_operand" "w, w")
+ (match_operand:SVE_FULL_HSDI 3 "aarch64_sve_cmp_<sve_imm_con>_operand" "<sve_imm_con>, w"))]
+ UNSPEC_PRED_Z)
+ 0)
+ (match_operand:VNx16BI 1 "register_operand" "Upl, Upl"))
+ (match_operand:<VPRED> 5 "aarch64_ptrue_all_operand")))
+ (clobber (reg:CC_NZC CC_REGNUM))]
+ "TARGET_SVE"
+ "#"
+ "&& 1"
+ [(parallel
+ [(set (match_dup 0)
+ (and:VNx16BI
+ (subreg:VNx16BI
+ (unspec:<VPRED>
+ [(match_dup 1)
+ (const_int SVE_MAYBE_NOT_PTRUE)
+ (SVE_INT_CMP:<VPRED>
+ (match_dup 2)
+ (match_dup 3))]
+ UNSPEC_PRED_Z)
+ 0)
+ (match_dup 5)))
+ (clobber (reg:CC_NZC CC_REGNUM))])]
+ {
+ operands[1] = gen_lowpart (<VPRED>mode, operands[1]);
+ }
+)
+
;; Predicated integer wide comparisons.
(define_insn "@aarch64_pred_cmp<cmp_op><mode>_wide"
[(set (match_operand:<VPRED> 0 "register_operand")
(unspec:<VPRED>
- [(match_operand:VNx16BI 1 "register_operand")
+ [(match_operand:<VPRED> 1 "register_operand")
(match_operand:SI 2 "aarch64_sve_ptrue_flag")
(unspec:<VPRED>
- [(match_operand:SVE_FULL_BHSI 3 "register_operand")
+ [(match_operand:VNx16QI_ONLY 3 "register_operand")
(match_operand:VNx2DI 4 "register_operand")]
SVE_COND_INT_CMP_WIDE)]
UNSPEC_PRED_Z))
@@ -8487,16 +8630,61 @@
}
)
+(define_expand "@aarch64_pred_cmp<cmp_op><mode>_wide"
+ [(parallel
+ [(set (match_operand:VNx16BI 0 "register_operand")
+ (and:VNx16BI
+ (subreg:VNx16BI
+ (unspec:<VPRED>
+ [(match_operand:<VPRED> 1 "register_operand")
+ (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+ (unspec:<VPRED>
+ [(match_operand:SVE_FULL_HSI 3 "register_operand")
+ (match_operand:VNx2DI 4 "register_operand")]
+ SVE_COND_INT_CMP_WIDE)]
+ UNSPEC_PRED_Z)
+ 0)
+ (match_dup 5)))
+ (clobber (reg:CC_NZC CC_REGNUM))])]
+ "TARGET_SVE"
+ {
+ operands[5] = aarch64_ptrue_all (GET_MODE_UNIT_SIZE (<MODE>mode));
+ }
+)
+
+(define_insn "*aarch64_pred_cmp<cmp_op><mode>_wide"
+ [(set (match_operand:VNx16BI 0 "register_operand")
+ (and:VNx16BI
+ (subreg:VNx16BI
+ (unspec:<VPRED>
+ [(match_operand:<VPRED> 1 "register_operand")
+ (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+ (unspec:<VPRED>
+ [(match_operand:SVE_FULL_HSI 3 "register_operand")
+ (match_operand:VNx2DI 4 "register_operand")]
+ SVE_COND_INT_CMP_WIDE)]
+ UNSPEC_PRED_Z)
+ 0)
+ (match_operand:<VPRED> 5 "aarch64_ptrue_all_operand")))
+ (clobber (reg:CC_NZC CC_REGNUM))]
+ "TARGET_SVE"
+ {@ [ cons: =0, 1 , 2, 3, 4; attrs: pred_clobber ]
+ [ &Upa , Upl, , w, w; yes ] cmp<cmp_op>\t%0.<Vetype>, %1/z, %3.<Vetype>, %4.d
+ [ ?Upl , 0 , , w, w; yes ] ^
+ [ Upa , Upl, , w, w; no ] ^
+ }
+)
+
;; Predicated integer wide comparisons in which both the flag and
;; predicate results are interesting.
-(define_insn "*aarch64_pred_cmp<cmp_op><mode>_wide_cc"
+(define_insn_and_rewrite "*aarch64_pred_cmp<cmp_op><mode>_wide_cc"
[(set (reg:CC_NZC CC_REGNUM)
(unspec:CC_NZC
[(match_operand:VNx16BI 1 "register_operand")
(match_operand 4)
(match_operand:SI 5 "aarch64_sve_ptrue_flag")
(unspec:<VPRED>
- [(match_operand:VNx16BI 6 "register_operand")
+ [(match_operand:<VPRED> 6 "register_operand")
(match_operand:SI 7 "aarch64_sve_ptrue_flag")
(unspec:<VPRED>
[(match_operand:SVE_FULL_BHSI 2 "register_operand")
@@ -8520,18 +8708,65 @@
[ ?Upl , 0 , w, w, Upl; yes ] ^
[ Upa , Upl, w, w, Upl; no ] ^
}
+ "&& !rtx_equal_p (operands[4], operands[6])"
+ {
+ operands[6] = copy_rtx (operands[4]);
+ operands[7] = operands[5];
+ }
+)
+
+(define_insn_and_rewrite "*aarch64_pred_cmp<cmp_op><mode>_wide_cc"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand:VNx16BI 1 "register_operand")
+ (match_operand 4)
+ (match_operand:SI 5 "aarch64_sve_ptrue_flag")
+ (unspec:<VPRED>
+ [(match_operand:<VPRED> 6 "register_operand")
+ (match_operand:SI 7 "aarch64_sve_ptrue_flag")
+ (unspec:<VPRED>
+ [(match_operand:SVE_FULL_HSI 2 "register_operand")
+ (match_operand:VNx2DI 3 "register_operand")]
+ SVE_COND_INT_CMP_WIDE)]
+ UNSPEC_PRED_Z)]
+ UNSPEC_PTEST))
+ (set (match_operand:VNx16BI 0 "register_operand")
+ (and:VNx16BI
+ (subreg:VNx16BI
+ (unspec:<VPRED>
+ [(match_dup 6)
+ (match_dup 7)
+ (unspec:<VPRED>
+ [(match_dup 2)
+ (match_dup 3)]
+ SVE_COND_INT_CMP_WIDE)]
+ UNSPEC_PRED_Z)
+ 0)
+ (match_operand:<VPRED> 8 "aarch64_ptrue_all_operand")))]
+ "TARGET_SVE
+ && aarch64_sve_same_pred_for_ptest_p (&operands[4], &operands[6])"
+ {@ [ cons: =0, 1 , 2, 3, 6 ; attrs: pred_clobber ]
+ [ &Upa , Upl, w, w, Upl; yes ] cmp<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.d
+ [ ?Upl , 0 , w, w, Upl; yes ] ^
+ [ Upa , Upl, w, w, Upl; no ] ^
+ }
+ "&& !rtx_equal_p (operands[4], operands[6])"
+ {
+ operands[6] = copy_rtx (operands[4]);
+ operands[7] = operands[5];
+ }
)
;; Predicated integer wide comparisons in which only the flags result
;; is interesting.
-(define_insn "*aarch64_pred_cmp<cmp_op><mode>_wide_ptest"
+(define_insn_and_rewrite "*aarch64_pred_cmp<cmp_op><mode>_wide_ptest"
[(set (reg:CC_NZC CC_REGNUM)
(unspec:CC_NZC
[(match_operand:VNx16BI 1 "register_operand")
(match_operand 4)
(match_operand:SI 5 "aarch64_sve_ptrue_flag")
(unspec:<VPRED>
- [(match_operand:VNx16BI 6 "register_operand")
+ [(match_operand:<VPRED> 6 "register_operand")
(match_operand:SI 7 "aarch64_sve_ptrue_flag")
(unspec:<VPRED>
[(match_operand:SVE_FULL_BHSI 2 "register_operand")
@@ -8547,6 +8782,11 @@
[ ?Upl , 0 , w, w, Upl; yes ] ^
[ Upa , Upl, w, w, Upl; no ] ^
}
+ "&& !rtx_equal_p (operands[4], operands[6])"
+ {
+ operands[6] = copy_rtx (operands[4]);
+ operands[7] = operands[5];
+ }
)
;; -------------------------------------------------------------------------
@@ -8584,6 +8824,58 @@
"while<cmp_op>\t%0.<PRED_ALL:Vetype>, %<w>1, %<w>2"
)
+;; Likewise, but yield a VNx16BI result regardless of the element width.
+;; The .b case is equivalent to the above.
+(define_expand "@aarch64_sve_while_<while_optab_cmp><GPI:mode><VNx16BI_ONLY:mode>_acle"
+ [(parallel
+ [(set (match_operand:VNx16BI_ONLY 0 "register_operand")
+ (unspec:VNx16BI_ONLY
+ [(const_int SVE_WHILE_B)
+ (match_operand:GPI 1 "aarch64_reg_or_zero")
+ (match_operand:GPI 2 "aarch64_reg_or_zero")]
+ SVE_WHILE))
+ (clobber (reg:CC_NZC CC_REGNUM))])]
+ "TARGET_SVE"
+)
+
+;; For wider elements, bitcast the predicate result to a VNx16BI and use
+;; an (and ...) to indicate that only every second, fourth, or eighth bit
+;; is set.
+(define_expand "@aarch64_sve_while_<while_optab_cmp><GPI:mode><PRED_HSD:mode>_acle"
+ [(parallel
+ [(set (match_operand:VNx16BI 0 "register_operand")
+ (and:VNx16BI
+ (subreg:VNx16BI
+ (unspec:PRED_HSD
+ [(const_int SVE_WHILE_B)
+ (match_operand:GPI 1 "aarch64_reg_or_zero")
+ (match_operand:GPI 2 "aarch64_reg_or_zero")]
+ SVE_WHILE)
+ 0)
+ (match_dup 3)))
+ (clobber (reg:CC_NZC CC_REGNUM))])]
+ "TARGET_SVE"
+ {
+ operands[3] = aarch64_ptrue_all (<data_bytes>);
+ }
+)
+
+(define_insn "*aarch64_sve_while_<while_optab_cmp><GPI:mode><PRED_HSD:mode>_acle"
+ [(set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+ (and:VNx16BI
+ (subreg:VNx16BI
+ (unspec:PRED_HSD
+ [(const_int SVE_WHILE_B)
+ (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
+ (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")]
+ SVE_WHILE)
+ 0)
+ (match_operand:PRED_HSD 3 "aarch64_ptrue_all_operand")))
+ (clobber (reg:CC_NZC CC_REGNUM))]
+ "TARGET_SVE"
+ "while<cmp_op>\t%0.<PRED_HSD:Vetype>, %<w>1, %<w>2"
+)
+
;; The WHILE instructions set the flags in the same way as a PTEST with
;; a PTRUE GP. Handle the case in which both results are useful. The GP
;; operands to the PTEST aren't needed, so we allow them to be anything.
@@ -8615,6 +8907,38 @@
}
)
+(define_insn_and_rewrite "*while_<while_optab_cmp><GPI:mode><PRED_HSD:mode>_acle_cc"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand 3)
+ (match_operand 4)
+ (const_int SVE_KNOWN_PTRUE)
+ (unspec:PRED_HSD
+ [(const_int SVE_WHILE_B)
+ (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
+ (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")]
+ SVE_WHILE)]
+ UNSPEC_PTEST))
+ (set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+ (and:VNx16BI
+ (subreg:VNx16BI
+ (unspec:PRED_HSD [(const_int SVE_WHILE_B)
+ (match_dup 1)
+ (match_dup 2)]
+ SVE_WHILE)
+ 0)
+ (match_operand:PRED_HSD 5 "aarch64_ptrue_all_operand")))]
+ "TARGET_SVE"
+ "while<cmp_op>\t%0.<PRED_HSD:Vetype>, %<w>1, %<w>2"
+ ;; Force the compiler to drop the unused predicate operand, so that we
+ ;; don't have an unnecessary PTRUE.
+ "&& (!CONSTANT_P (operands[3]) || !CONSTANT_P (operands[4]))"
+ {
+ operands[3] = CONSTM1_RTX (VNx16BImode);
+ operands[4] = CONSTM1_RTX (<PRED_HSD:MODE>mode);
+ }
+)
+
;; Same, but handle the case in which only the flags result is useful.
(define_insn_and_rewrite "@while_<while_optab_cmp><GPI:mode><PRED_ALL:mode>_ptest"
[(set (reg:CC_NZC CC_REGNUM)
@@ -8685,6 +9009,43 @@
}
)
+(define_expand "@aarch64_pred_fcm<cmp_op><mode>_acle"
+ [(set (match_operand:VNx16BI 0 "register_operand")
+ (and:VNx16BI
+ (subreg:VNx16BI
+ (unspec:<VPRED>
+ [(match_operand:<VPRED> 1 "aarch64_predicate_operand")
+ (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+ (match_operand:SVE_F 3 "register_operand")
+ (match_operand:SVE_F 4 "aarch64_simd_reg_or_zero")]
+ SVE_COND_FP_CMP_I0)
+ 0)
+ (match_dup 5)))]
+ "TARGET_SVE"
+ {
+ operands[5] = aarch64_ptrue_all (GET_MODE_UNIT_SIZE (<MODE>mode));
+ }
+)
+
+(define_insn "*aarch64_pred_fcm<cmp_op><mode>_acle"
+ [(set (match_operand:VNx16BI 0 "register_operand")
+ (and:VNx16BI
+ (subreg:VNx16BI
+ (unspec:<VPRED>
+ [(match_operand:<VPRED> 1 "aarch64_predicate_operand")
+ (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+ (match_operand:SVE_F 3 "register_operand")
+ (match_operand:SVE_F 4 "aarch64_simd_reg_or_zero")]
+ SVE_COND_FP_CMP_I0)
+ 0)
+ (match_operand:<VPRED> 5 "aarch64_ptrue_all_operand")))]
+ "TARGET_SVE"
+ {@ [ cons: =0 , 1 , 3 , 4 ]
+ [ Upa , Upl , w , Dz ] fcm<cmp_op>\t%0.<Vetype>, %1/z, %3.<Vetype>, #0.0
+ [ Upa , Upl , w , w ] fcm<cmp_op>\t%0.<Vetype>, %1/z, %3.<Vetype>, %4.<Vetype>
+ }
+)
+
;; Same for unordered comparisons.
(define_insn "@aarch64_pred_fcmuo<mode>"
[(set (match_operand:<VPRED> 0 "register_operand" "=Upa")
@@ -8698,6 +9059,40 @@
"fcmuo\t%0.<Vetype>, %1/z, %3.<Vetype>, %4.<Vetype>"
)
+(define_expand "@aarch64_pred_fcmuo<mode>_acle"
+ [(set (match_operand:VNx16BI 0 "register_operand")
+ (and:VNx16BI
+ (subreg:VNx16BI
+ (unspec:<VPRED>
+ [(match_operand:<VPRED> 1 "aarch64_predicate_operand")
+ (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+ (match_operand:SVE_F 3 "register_operand")
+ (match_operand:SVE_F 4 "register_operand")]
+ UNSPEC_COND_FCMUO)
+ 0)
+ (match_dup 5)))]
+ "TARGET_SVE"
+ {
+ operands[5] = aarch64_ptrue_all (GET_MODE_UNIT_SIZE (<MODE>mode));
+ }
+)
+
+(define_insn "*aarch64_pred_fcmuo<mode>_acle"
+ [(set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+ (and:VNx16BI
+ (subreg:VNx16BI
+ (unspec:<VPRED>
+ [(match_operand:<VPRED> 1 "aarch64_predicate_operand" "Upl")
+ (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+ (match_operand:SVE_F 3 "register_operand" "w")
+ (match_operand:SVE_F 4 "register_operand" "w")]
+ UNSPEC_COND_FCMUO)
+ 0)
+ (match_operand:<VPRED> 5 "aarch64_ptrue_all_operand")))]
+ "TARGET_SVE"
+ "fcmuo\t%0.<Vetype>, %1/z, %3.<Vetype>, %4.<Vetype>"
+)
+
;; Floating-point comparisons predicated on a PTRUE, with the results ANDed
;; with another predicate P. This does not have the same trapping behavior
;; as predicating the comparison itself on P, but it's a legitimate fold,
@@ -8916,23 +9311,30 @@
;; -------------------------------------------------------------------------
;; Predicated floating-point absolute comparisons.
-(define_expand "@aarch64_pred_fac<cmp_op><mode>"
- [(set (match_operand:<VPRED> 0 "register_operand")
- (unspec:<VPRED>
- [(match_operand:<VPRED> 1 "register_operand")
- (match_operand:SI 2 "aarch64_sve_ptrue_flag")
- (unspec:SVE_FULL_F
- [(match_dup 1)
- (match_dup 2)
- (match_operand:SVE_FULL_F 3 "register_operand")]
- UNSPEC_COND_FABS)
- (unspec:SVE_FULL_F
- [(match_dup 1)
- (match_dup 2)
- (match_operand:SVE_FULL_F 4 "register_operand")]
- UNSPEC_COND_FABS)]
- SVE_COND_FP_ABS_CMP))]
+(define_expand "@aarch64_pred_fac<cmp_op><mode>_acle"
+ [(set (match_operand:VNx16BI 0 "register_operand")
+ (and:VNx16BI
+ (subreg:VNx16BI
+ (unspec:<VPRED>
+ [(match_operand:<VPRED> 1 "register_operand")
+ (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+ (unspec:SVE_FULL_F
+ [(match_dup 1)
+ (match_dup 2)
+ (match_operand:SVE_FULL_F 3 "register_operand")]
+ UNSPEC_COND_FABS)
+ (unspec:SVE_FULL_F
+ [(match_dup 1)
+ (match_dup 2)
+ (match_operand:SVE_FULL_F 4 "register_operand")]
+ UNSPEC_COND_FABS)]
+ SVE_COND_FP_ABS_CMP)
+ 0)
+ (match_dup 5)))]
"TARGET_SVE"
+ {
+ operands[5] = aarch64_ptrue_all (GET_MODE_UNIT_SIZE (<MODE>mode));
+ }
)
(define_insn_and_rewrite "*aarch64_pred_fac<cmp_op><mode>_relaxed"
@@ -8981,6 +9383,30 @@
"fac<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
)
+(define_insn "*aarch64_pred_fac<cmp_op><mode>_strict_acle"
+ [(set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+ (and:VNx16BI
+ (subreg:VNx16BI
+ (unspec:<VPRED>
+ [(match_operand:<VPRED> 1 "register_operand" "Upl")
+ (match_operand:SI 4 "aarch64_sve_ptrue_flag")
+ (unspec:SVE_FULL_F
+ [(match_dup 1)
+ (match_operand:SI 5 "aarch64_sve_gp_strictness")
+ (match_operand:SVE_FULL_F 2 "register_operand" "w")]
+ UNSPEC_COND_FABS)
+ (unspec:SVE_FULL_F
+ [(match_dup 1)
+ (match_operand:SI 6 "aarch64_sve_gp_strictness")
+ (match_operand:SVE_FULL_F 3 "register_operand" "w")]
+ UNSPEC_COND_FABS)]
+ SVE_COND_FP_ABS_CMP)
+ 0)
+ (match_operand:<VPRED> 7 "aarch64_ptrue_all_operand")))]
+ "TARGET_SVE"
+ "fac<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
+)
+
;; -------------------------------------------------------------------------
;; ---- [PRED] Select
;; -------------------------------------------------------------------------
@@ -9429,7 +9855,30 @@
(unspec:PRED_ALL [(match_operand:PRED_ALL 1 "register_operand" "Upa")]
UNSPEC_REV))]
"TARGET_SVE"
- "rev\t%0.<Vetype>, %1.<Vetype>")
+ "rev\t%0.<Vetype>, %1.<Vetype>"
+)
+
+(define_expand "@aarch64_sve_rev<mode>_acle"
+ [(set (match_operand:VNx16BI 0 "register_operand")
+ (unspec:VNx16BI
+ [(match_operand:VNx16BI 1 "register_operand")
+ (match_dup:PRED_ALL 2)]
+ UNSPEC_REV_PRED))]
+ "TARGET_SVE"
+ {
+ operands[2] = CONST0_RTX (<MODE>mode);
+ }
+)
+
+(define_insn "*aarch64_sve_rev<mode>_acle"
+ [(set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+ (unspec:VNx16BI
+ [(match_operand:VNx16BI 1 "register_operand" "Upa")
+ (match_operand:PRED_ALL 2 "aarch64_simd_imm_zero")]
+ UNSPEC_REV_PRED))]
+ "TARGET_SVE"
+ "rev\t%0.<Vetype>, %1.<Vetype>"
+)
;; -------------------------------------------------------------------------
;; ---- [PRED] Special-purpose binary permutes
@@ -9454,18 +9903,39 @@
"<perm_insn>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
)
-;; Special purpose permute used by the predicate generation instructions.
-;; Unlike the normal permute patterns, these instructions operate on VNx16BI
-;; regardless of the element size, so that all input and output bits are
-;; well-defined. Operand 3 then indicates the size of the permute.
-(define_insn "@aarch64_sve_trn1_conv<mode>"
+;; Special-purpose permutes used by the ACLE intrinsics and predicate
+;; generation instructions. Unlike the normal permute patterns, these
+;; instructions operate on VNx16BI regardless of the element size, so that
+;; all input and output bits are well-defined. Operand 3 then indicates
+;; the size of the permute.
+;;
+;; To make generation easier, this pattern embeds the permute type as the
+;; fourth operand to the unspec. On the one hand, this avoids overloading
+;; unspecs like UNSPEC_ZIP1 to represent two different operations. On the
+;; other hand, it avoids having a separate unspec for each variant, and
+;; having to map from one kind of unspec to the other.
+(define_expand "@aarch64_sve_<perm_insn><mode>_acle"
+ [(set (match_operand:VNx16BI 0 "register_operand")
+ (unspec:VNx16BI [(match_operand:VNx16BI 1 "register_operand")
+ (match_operand:VNx16BI 2 "register_operand")
+ (match_dup:PRED_ALL 3)
+ (const_int PERMUTE)]
+ UNSPEC_PERMUTE_PRED))]
+ "TARGET_SVE"
+ {
+ operands[3] = CONST0_RTX (<MODE>mode);
+ }
+)
+
+(define_insn "*aarch64_sve_<perm_insn><mode>_acle"
[(set (match_operand:VNx16BI 0 "register_operand" "=Upa")
(unspec:VNx16BI [(match_operand:VNx16BI 1 "register_operand" "Upa")
(match_operand:VNx16BI 2 "register_operand" "Upa")
- (match_operand:PRED_ALL 3 "aarch64_simd_imm_zero")]
- UNSPEC_TRN1_CONV))]
+ (match_operand:PRED_ALL 3 "aarch64_simd_imm_zero")
+ (const_int PERMUTE)]
+ UNSPEC_PERMUTE_PRED))]
"TARGET_SVE"
- "trn1\t%0.<PRED_ALL:Vetype>, %1.<PRED_ALL:Vetype>, %2.<PRED_ALL:Vetype>"
+ "<perm_insn>\t%0.<PRED_ALL:Vetype>, %1.<PRED_ALL:Vetype>, %2.<PRED_ALL:Vetype>"
)
;; =========================================================================
@@ -10454,6 +10924,34 @@
"punpk<perm_hilo>\t%0.h, %1.b"
)
+(define_expand "@aarch64_sve_punpk<perm_hilo>_acle"
+ [(set (match_operand:VNx16BI 0 "register_operand")
+ (and:VNx16BI
+ (subreg:VNx16BI
+ (unspec:VNx8BI
+ [(match_operand:VNx16BI 1 "register_operand")]
+ UNPACK_UNSIGNED)
+ 0)
+ (match_dup 2)))]
+ "TARGET_SVE"
+ {
+ operands[2] = aarch64_ptrue_all (2);
+ }
+)
+
+(define_insn "*aarch64_sve_punpk<perm_hilo>_acle"
+ [(set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+ (and:VNx16BI
+ (subreg:VNx16BI
+ (unspec:VNx8BI
+ [(match_operand:VNx16BI 1 "register_operand" "Upa")]
+ UNPACK_UNSIGNED)
+ 0)
+ (match_operand:VNx8BI 2 "aarch64_ptrue_all_operand")))]
+ "TARGET_SVE"
+ "punpk<perm_hilo>\t%0.h, %1.b"
+)
+
;; =========================================================================
;; == Vector partitioning
;; =========================================================================
@@ -10678,14 +11176,49 @@
;; -------------------------------------------------------------------------
(define_insn "@aarch64_sve_<sve_pred_op><mode>"
- [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
- (unspec:PRED_ALL
- [(match_operand:PRED_ALL 1 "register_operand" "Upa")
+ [(set (match_operand:VNx16BI_ONLY 0 "register_operand" "=Upa")
+ (unspec:VNx16BI_ONLY
+ [(match_operand:VNx16BI_ONLY 1 "register_operand" "Upa")
(match_operand:SI 2 "aarch64_sve_ptrue_flag")
- (match_operand:PRED_ALL 3 "register_operand" "0")]
+ (match_operand:VNx16BI_ONLY 3 "register_operand" "0")]
SVE_PITER))
(clobber (reg:CC_NZC CC_REGNUM))]
- "TARGET_SVE && <max_elem_bits> >= <elem_bits>"
+ "TARGET_SVE"
+ "<sve_pred_op>\t%0.<Vetype>, %1, %0.<Vetype>"
+)
+
+(define_expand "@aarch64_sve_<sve_pred_op><mode>"
+ [(parallel
+ [(set (match_operand:VNx16BI 0 "register_operand")
+ (and:VNx16BI
+ (subreg:VNx16BI
+ (unspec:PRED_HSD
+ [(match_operand:PRED_HSD 1 "register_operand")
+ (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+ (match_operand:PRED_HSD 3 "register_operand")]
+ PNEXT_ONLY)
+ 0)
+ (match_dup 4)))
+ (clobber (reg:CC_NZC CC_REGNUM))])]
+ "TARGET_SVE"
+ {
+ operands[4] = aarch64_ptrue_all (<data_bytes>);
+ }
+)
+
+(define_insn "*aarch64_sve_<sve_pred_op><mode>"
+ [(set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+ (and:VNx16BI
+ (subreg:VNx16BI
+ (unspec:PRED_HSD
+ [(match_operand:PRED_HSD 1 "register_operand" "Upa")
+ (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+ (match_operand:PRED_HSD 3 "register_operand" "0")]
+ PNEXT_ONLY)
+ 0)
+ (match_operand:PRED_HSD 4 "aarch64_ptrue_all_operand")))
+ (clobber (reg:CC_NZC CC_REGNUM))]
+ "TARGET_SVE"
"<sve_pred_op>\t%0.<Vetype>, %1, %0.<Vetype>"
)
@@ -10719,6 +11252,38 @@
}
)
+(define_insn_and_rewrite "*aarch64_sve_<sve_pred_op><mode>_cc"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand:VNx16BI 1 "register_operand" "Upa")
+ (match_operand 2)
+ (match_operand:SI 3 "aarch64_sve_ptrue_flag")
+ (unspec:PRED_HSD
+ [(match_operand 4)
+ (match_operand:SI 5 "aarch64_sve_ptrue_flag")
+ (match_operand:PRED_HSD 6 "register_operand" "0")]
+ PNEXT_ONLY)]
+ UNSPEC_PTEST))
+ (set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+ (and:VNx16BI
+ (subreg:VNx16BI
+ (unspec:PRED_HSD
+ [(match_dup 4)
+ (match_dup 5)
+ (match_dup 6)]
+ PNEXT_ONLY)
+ 0)
+ (match_operand:PRED_HSD 7 "aarch64_ptrue_all_operand")))]
+ "TARGET_SVE
+ && aarch64_sve_same_pred_for_ptest_p (&operands[2], &operands[4])"
+ "<sve_pred_op>\t%0.<Vetype>, %1, %0.<Vetype>"
+ "&& !rtx_equal_p (operands[2], operands[4])"
+ {
+ operands[4] = operands[2];
+ operands[5] = operands[3];
+ }
+)
+
;; Same, but with only the flags result being interesting.
(define_insn_and_rewrite "*aarch64_sve_<sve_pred_op><mode>_ptest"
[(set (reg:CC_NZC CC_REGNUM)
diff --git a/gcc/config/aarch64/aarch64-sve2.md b/gcc/config/aarch64/aarch64-sve2.md
index 31bdd85..a4c3257 100644
--- a/gcc/config/aarch64/aarch64-sve2.md
+++ b/gcc/config/aarch64/aarch64-sve2.md
@@ -4068,8 +4068,8 @@
[(match_operand:<VPRED> 1 "register_operand")
(match_operand:SI 2 "aarch64_sve_ptrue_flag")
(unspec:<VPRED>
- [(match_operand:SVE_FULL_BHI 3 "register_operand")
- (match_operand:SVE_FULL_BHI 4 "register_operand")]
+ [(match_operand:VNx16QI_ONLY 3 "register_operand")
+ (match_operand:VNx16QI_ONLY 4 "register_operand")]
SVE2_MATCH)]
UNSPEC_PRED_Z))
(clobber (reg:CC_NZC CC_REGNUM))]
@@ -4081,6 +4081,51 @@
}
)
+(define_expand "@aarch64_pred_<sve_int_op><mode>"
+ [(parallel
+ [(set (match_operand:VNx16BI 0 "register_operand")
+ (and:VNx16BI
+ (subreg:VNx16BI
+ (unspec:<VPRED>
+ [(match_operand:<VPRED> 1 "register_operand")
+ (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+ (unspec:<VPRED>
+ [(match_operand:VNx8HI_ONLY 3 "register_operand")
+ (match_operand:VNx8HI_ONLY 4 "register_operand")]
+ SVE2_MATCH)]
+ UNSPEC_PRED_Z)
+ 0)
+ (match_dup 5)))
+ (clobber (reg:CC_NZC CC_REGNUM))])]
+ "TARGET_SVE2 && TARGET_NON_STREAMING"
+ {
+ operands[5] = aarch64_ptrue_all (GET_MODE_UNIT_SIZE (<MODE>mode));
+ }
+)
+
+(define_insn "*aarch64_pred_<sve_int_op><mode>"
+ [(set (match_operand:VNx16BI 0 "register_operand")
+ (and:VNx16BI
+ (subreg:VNx16BI
+ (unspec:<VPRED>
+ [(match_operand:<VPRED> 1 "register_operand")
+ (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+ (unspec:<VPRED>
+ [(match_operand:VNx8HI_ONLY 3 "register_operand")
+ (match_operand:VNx8HI_ONLY 4 "register_operand")]
+ SVE2_MATCH)]
+ UNSPEC_PRED_Z)
+ 0)
+ (match_operand:<VPRED> 5 "aarch64_ptrue_all_operand")))
+ (clobber (reg:CC_NZC CC_REGNUM))]
+ "TARGET_SVE2 && TARGET_NON_STREAMING"
+ {@ [ cons: =0, 1 , 3, 4; attrs: pred_clobber ]
+ [ &Upa , Upl, w, w; yes ] <sve_int_op>\t%0.<Vetype>, %1/z, %3.<Vetype>, %4.<Vetype>
+ [ ?Upl , 0 , w, w; yes ] ^
+ [ Upa , Upl, w, w; no ] ^
+ }
+)
+
;; Predicated string matching in which both the flag and predicate results
;; are interesting.
(define_insn_and_rewrite "*aarch64_pred_<sve_int_op><mode>_cc"
@@ -4118,6 +4163,45 @@
}
)
+(define_insn_and_rewrite "*aarch64_pred_<sve_int_op><mode>_cc"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand:VNx16BI 1 "register_operand" "Upl")
+ (match_operand 4)
+ (match_operand:SI 5 "aarch64_sve_ptrue_flag")
+ (unspec:<VPRED>
+ [(match_operand 6)
+ (match_operand:SI 7 "aarch64_sve_ptrue_flag")
+ (unspec:<VPRED>
+ [(match_operand:VNx8HI_ONLY 2 "register_operand" "w")
+ (match_operand:VNx8HI_ONLY 3 "register_operand" "w")]
+ SVE2_MATCH)]
+ UNSPEC_PRED_Z)]
+ UNSPEC_PTEST))
+ (set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+ (and:VNx16BI
+ (subreg:VNx16BI
+ (unspec:<VPRED>
+ [(match_dup 6)
+ (match_dup 7)
+ (unspec:<VPRED>
+ [(match_dup 2)
+ (match_dup 3)]
+ SVE2_MATCH)]
+ UNSPEC_PRED_Z)
+ 0)
+ (match_operand:<VPRED> 8 "aarch64_ptrue_all_operand")))]
+ "TARGET_SVE2
+ && TARGET_NON_STREAMING
+ && aarch64_sve_same_pred_for_ptest_p (&operands[4], &operands[6])"
+ "<sve_int_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
+ "&& !rtx_equal_p (operands[4], operands[6])"
+ {
+ operands[6] = copy_rtx (operands[4]);
+ operands[7] = operands[5];
+ }
+)
+
;; Predicated string matching in which only the flags result is interesting.
(define_insn_and_rewrite "*aarch64_pred_<sve_int_op><mode>_ptest"
[(set (reg:CC_NZC CC_REGNUM)
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index f4a2062..d30c9c7 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -3962,16 +3962,24 @@ aarch64_sve_emit_masked_fp_pred (machine_mode data_mode, rtx pred)
/* Emit a comparison CMP between OP0 and OP1, both of which have mode
DATA_MODE, and return the result in a predicate of mode PRED_MODE.
- Use TARGET as the target register if nonnull and convenient. */
+ Use TARGET as the target register if nonnull and convenient.
+
+ PRED_MODE can be either VNx16BI or the natural predicate mode for
+ DATA_MODE. */
static rtx
aarch64_sve_emit_int_cmp (rtx target, machine_mode pred_mode, rtx_code cmp,
machine_mode data_mode, rtx op1, rtx op2)
{
- insn_code icode = code_for_aarch64_pred_cmp (cmp, data_mode);
+ auto src_pred_mode = aarch64_sve_pred_mode (data_mode);
+ insn_code icode;
+ if (known_eq (GET_MODE_NUNITS (pred_mode), GET_MODE_NUNITS (data_mode)))
+ icode = code_for_aarch64_pred_cmp (cmp, data_mode);
+ else
+ icode = code_for_aarch64_pred_cmp_acle (cmp, data_mode);
expand_operand ops[5];
create_output_operand (&ops[0], target, pred_mode);
- create_input_operand (&ops[1], CONSTM1_RTX (pred_mode), pred_mode);
+ create_input_operand (&ops[1], CONSTM1_RTX (src_pred_mode), src_pred_mode);
create_integer_operand (&ops[2], SVE_KNOWN_PTRUE);
create_input_operand (&ops[3], op1, data_mode);
create_input_operand (&ops[4], op2, data_mode);
@@ -3979,15 +3987,14 @@ aarch64_sve_emit_int_cmp (rtx target, machine_mode pred_mode, rtx_code cmp,
return ops[0].value;
}
-/* Use a comparison to convert integer vector SRC into MODE, which is
- the corresponding SVE predicate mode. Use TARGET for the result
- if it's nonnull and convenient. */
+/* Use a comparison to convert integer vector SRC into VNx16BI.
+ Use TARGET for the result if it's nonnull and convenient. */
rtx
-aarch64_convert_sve_data_to_pred (rtx target, machine_mode mode, rtx src)
+aarch64_convert_sve_data_to_pred (rtx target, rtx src)
{
machine_mode src_mode = GET_MODE (src);
- return aarch64_sve_emit_int_cmp (target, mode, NE, src_mode,
+ return aarch64_sve_emit_int_cmp (target, VNx16BImode, NE, src_mode,
src, CONST0_RTX (src_mode));
}
@@ -6069,9 +6076,9 @@ aarch64_sve_move_pred_via_while (rtx target, machine_mode mode,
unsigned int vl)
{
rtx limit = force_reg (DImode, gen_int_mode (vl, DImode));
- target = aarch64_target_reg (target, mode);
- emit_insn (gen_while (UNSPEC_WHILELO, DImode, mode,
- target, const0_rtx, limit));
+ target = aarch64_target_reg (target, VNx16BImode);
+ emit_insn (gen_aarch64_sve_while_acle (UNSPEC_WHILELO, DImode, mode,
+ target, const0_rtx, limit));
return target;
}
@@ -6217,8 +6224,7 @@ aarch64_expand_sve_const_pred_trn (rtx target, rtx_vector_builder &builder,
operands but permutes them as though they had mode MODE. */
machine_mode mode = aarch64_sve_pred_mode (permute_size).require ();
target = aarch64_target_reg (target, GET_MODE (a));
- rtx type_reg = CONST0_RTX (mode);
- emit_insn (gen_aarch64_sve_trn1_conv (mode, target, a, b, type_reg));
+ emit_insn (gen_aarch64_sve_acle (UNSPEC_TRN1, mode, target, a, b));
return target;
}
@@ -6300,8 +6306,7 @@ aarch64_expand_sve_const_pred (rtx target, rtx_vector_builder &builder)
for (unsigned int i = 0; i < builder.encoded_nelts (); ++i)
int_builder.quick_push (INTVAL (builder.elt (i))
? constm1_rtx : const0_rtx);
- return aarch64_convert_sve_data_to_pred (target, VNx16BImode,
- int_builder.build ());
+ return aarch64_convert_sve_data_to_pred (target, int_builder.build ());
}
/* Set DEST to immediate IMM. */
@@ -6753,6 +6758,27 @@ aarch64_split_sve_subreg_move (rtx dest, rtx ptrue, rtx src)
dest, ptrue, src));
}
+/* Set predicate register DEST such that every element has the scalar
+ boolean value in SRC, with any nonzero source counting as "true".
+ MODE is a MODE_VECTOR_BOOL that determines the element size;
+ DEST can have this mode or VNx16BImode. In the latter case,
+ the upper bits of each element are defined to be zero, as for
+ the .H, .S, and .D forms of PTRUE. */
+
+void
+aarch64_emit_sve_pred_vec_duplicate (machine_mode mode, rtx dest, rtx src)
+{
+ rtx tmp = gen_reg_rtx (DImode);
+ emit_insn (gen_ashldi3 (tmp, gen_lowpart (DImode, src),
+ gen_int_mode (63, DImode)));
+ if (GET_MODE (dest) == VNx16BImode)
+ emit_insn (gen_aarch64_sve_while_acle (UNSPEC_WHILELO, DImode, mode,
+ dest, const0_rtx, tmp));
+ else
+ emit_insn (gen_while (UNSPEC_WHILELO, DImode, mode,
+ dest, const0_rtx, tmp));
+}
+
static bool
aarch64_function_ok_for_sibcall (tree, tree exp)
{
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index a4ae685..dc2be81 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -280,6 +280,7 @@
UNSPEC_PACIBSP
UNSPEC_PRLG_STK
UNSPEC_REV
+ UNSPEC_REV_PRED
UNSPEC_SADALP
UNSPEC_SCVTF
UNSPEC_SET_LANE
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index 8533912..8f8237e 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -455,6 +455,7 @@
(define_mode_iterator VCVTFPM [V4HF V8HF V4SF])
;; Iterators for single modes, for "@" patterns.
+(define_mode_iterator VNx16BI_ONLY [VNx16BI])
(define_mode_iterator VNx16QI_ONLY [VNx16QI])
(define_mode_iterator VNx16SI_ONLY [VNx16SI])
(define_mode_iterator VNx8HI_ONLY [VNx8HI])
@@ -930,7 +931,6 @@
UNSPEC_UZP2Q ; Used in aarch64-sve.md.
UNSPEC_ZIP1Q ; Used in aarch64-sve.md.
UNSPEC_ZIP2Q ; Used in aarch64-sve.md.
- UNSPEC_TRN1_CONV ; Used in aarch64-sve.md.
UNSPEC_COND_CMPEQ_WIDE ; Used in aarch64-sve.md.
UNSPEC_COND_CMPGE_WIDE ; Used in aarch64-sve.md.
UNSPEC_COND_CMPGT_WIDE ; Used in aarch64-sve.md.
@@ -1185,6 +1185,9 @@
UNSPEC_LUTI2 ; Used in aarch64-simd.md.
UNSPEC_LUTI4 ; Used in aarch64-simd.md.
+ ;; All used in aarch64-sve.md
+ UNSPEC_PERMUTE_PRED
+
;; All used in aarch64-sve2.md
UNSPEC_ADDQV
UNSPEC_ANDQV
@@ -3877,6 +3880,8 @@
(define_int_iterator SVE_PITER [UNSPEC_PFIRST UNSPEC_PNEXT])
+(define_int_iterator PNEXT_ONLY [UNSPEC_PNEXT])
+
(define_int_iterator MATMUL [UNSPEC_SMATMUL UNSPEC_UMATMUL
UNSPEC_USMATMUL])
diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md
index 32056da..4d5d57f 100644
--- a/gcc/config/aarch64/predicates.md
+++ b/gcc/config/aarch64/predicates.md
@@ -1078,3 +1078,9 @@
(define_predicate "aarch64_maskload_else_operand"
(and (match_code "const_vector")
(match_test "op == CONST0_RTX (GET_MODE (op))")))
+
+;; Check for a VNx16BI predicate that is a canonical PTRUE for the given
+;; predicate mode.
+(define_special_predicate "aarch64_ptrue_all_operand"
+ (and (match_code "const_vector")
+ (match_test "aarch64_ptrue_all_mode (op) == mode")))
diff --git a/gcc/config/avr/avr-dimode.md b/gcc/config/avr/avr-dimode.md
index 903bfbf..66ba5a9 100644
--- a/gcc/config/avr/avr-dimode.md
+++ b/gcc/config/avr/avr-dimode.md
@@ -101,10 +101,8 @@
"avr_have_dimode"
"#"
"&& reload_completed"
- [(parallel [(set (reg:ALL8 ACC_A)
- (plus:ALL8 (reg:ALL8 ACC_A)
- (reg:ALL8 ACC_B)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*add<mode>3_insn"
[(set (reg:ALL8 ACC_A)
@@ -122,10 +120,8 @@
"avr_have_dimode"
"#"
"&& reload_completed"
- [(parallel [(set (reg:DI ACC_A)
- (plus:DI (reg:DI ACC_A)
- (sign_extend:DI (reg:QI REG_X))))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*adddi3_const8_insn"
[(set (reg:DI ACC_A)
@@ -146,12 +142,10 @@
(match_operand:ALL8 0 "const_operand" "n Ynn")))]
"avr_have_dimode
&& !s8_operand (operands[0], VOIDmode)"
- "#"
- "&& reload_completed"
- [(parallel [(set (reg:ALL8 ACC_A)
- (plus:ALL8 (reg:ALL8 ACC_A)
- (match_dup 0)))
- (clobber (reg:CC REG_CC))])])
+ "#"
+ "&& reload_completed"
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*add<mode>3_const_insn"
[(set (reg:ALL8 ACC_A)
@@ -211,10 +205,8 @@
"avr_have_dimode"
"#"
"&& reload_completed"
- [(parallel [(set (reg:ALL8 ACC_A)
- (minus:ALL8 (reg:ALL8 ACC_A)
- (reg:ALL8 ACC_B)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*sub<mode>3_insn"
[(set (reg:ALL8 ACC_A)
@@ -236,10 +228,8 @@
"avr_have_dimode"
"#"
"&& reload_completed"
- [(parallel [(set (reg:ALL8 ACC_A)
- (minus:ALL8 (reg:ALL8 ACC_A)
- (match_dup 0)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*sub<mode>3_const_insn"
[(set (reg:ALL8 ACC_A)
@@ -288,10 +278,8 @@
"avr_have_dimode"
"#"
"&& reload_completed"
- [(parallel [(set (reg:ALL8S ACC_A)
- (ss_addsub:ALL8S (reg:ALL8S ACC_A)
- (reg:ALL8S ACC_B)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*<code_stdname><mode>3_insn"
[(set (reg:ALL8S ACC_A)
@@ -309,10 +297,8 @@
"avr_have_dimode"
"#"
"&& reload_completed"
- [(parallel [(set (reg:ALL8S ACC_A)
- (ss_addsub:ALL8S (reg:ALL8S ACC_A)
- (match_dup 0)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*<code_stdname><mode>3_const_insn"
[(set (reg:ALL8S ACC_A)
@@ -361,10 +347,8 @@
"avr_have_dimode"
"#"
"&& reload_completed"
- [(parallel [(set (reg:ALL8U ACC_A)
- (us_addsub:ALL8U (reg:ALL8U ACC_A)
- (reg:ALL8U ACC_B)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*<code_stdname><mode>3_insn"
[(set (reg:ALL8U ACC_A)
@@ -382,10 +366,8 @@
"avr_have_dimode"
"#"
"&& reload_completed"
- [(parallel [(set (reg:ALL8U ACC_A)
- (us_addsub:ALL8U (reg:ALL8U ACC_A)
- (match_operand:ALL8U 0 "const_operand" "n Ynn")))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*<code_stdname><mode>3_const_insn"
[(set (reg:ALL8U ACC_A)
@@ -421,9 +403,8 @@
"avr_have_dimode"
"#"
"&& reload_completed"
- [(parallel [(set (reg:DI ACC_A)
- (neg:DI (reg:DI ACC_A)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*negdi2_insn"
[(set (reg:DI ACC_A)
@@ -500,7 +481,7 @@
"avr_have_dimode"
"#"
"&& reload_completed"
- [(const_int 0)]
+ [(scratch)]
{
emit_insn (gen_compare_<mode>2 ());
emit_jump_insn (gen_conditional_jump (operands[0], operands[1]));
@@ -529,7 +510,7 @@
"avr_have_dimode"
"#"
"&& reload_completed"
- [(const_int 0)]
+ [(scratch)]
{
emit_insn (gen_compare_const8_di2 ());
emit_jump_insn (gen_conditional_jump (operands[0], operands[1]));
@@ -556,7 +537,7 @@
&& !s8_operand (operands[1], VOIDmode)"
"#"
"&& reload_completed"
- [(const_int 0)]
+ [(scratch)]
{
emit_insn (gen_compare_const_<mode>2 (operands[1], operands[3]));
emit_jump_insn (gen_conditional_jump (operands[0], operands[2]));
@@ -629,10 +610,8 @@
"avr_have_dimode"
"#"
"&& reload_completed"
- [(parallel [(set (reg:ALL8 ACC_A)
- (di_shifts:ALL8 (reg:ALL8 ACC_A)
- (reg:QI 16)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*<code_stdname><mode>3_insn"
[(set (reg:ALL8 ACC_A)
@@ -674,14 +653,10 @@
(clobber (reg:HI REG_Z))]
"avr_have_dimode
&& AVR_HAVE_MUL"
- "#"
- "&& reload_completed"
- [(parallel [(set (reg:DI ACC_A)
- (mult:DI (any_extend:DI (reg:SI 18))
- (any_extend:DI (reg:SI 22))))
- (clobber (reg:HI REG_X))
- (clobber (reg:HI REG_Z))
- (clobber (reg:CC REG_CC))])])
+ "#"
+ "&& reload_completed"
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*<extend_u>mulsidi3_insn"
[(set (reg:DI ACC_A)
diff --git a/gcc/config/avr/avr-fixed.md b/gcc/config/avr/avr-fixed.md
index ce46beb..22061fc 100644
--- a/gcc/config/avr/avr-fixed.md
+++ b/gcc/config/avr/avr-fixed.md
@@ -62,10 +62,8 @@
"<FIXED_B:MODE>mode != <FIXED_A:MODE>mode"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (fract_convert:FIXED_A
- (match_dup 1)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*fract<FIXED_B:mode><FIXED_A:mode>2"
[(set (match_operand:FIXED_A 0 "register_operand" "=r")
@@ -86,10 +84,8 @@
"<FIXED_B:MODE>mode != <FIXED_A:MODE>mode"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (unsigned_fract_convert:FIXED_A
- (match_dup 1)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*fractuns<FIXED_B:mode><FIXED_A:mode>2"
[(set (match_operand:FIXED_A 0 "register_operand" "=r")
@@ -124,10 +120,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (ss_addsub:ALL124S (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*<code_stdname><mode>3"
[(set (match_operand:ALL124S 0 "register_operand" "=??d,d")
@@ -149,10 +143,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (us_addsub:ALL124U (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*<code_stdname><mode>3"
[(set (match_operand:ALL124U 0 "register_operand" "=??r,d")
@@ -189,9 +181,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (ss_neg:QQ (match_dup 1)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*ssnegqq2"
[(set (match_operand:QQ 0 "register_operand" "=r")
@@ -207,9 +198,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (ss_abs:QQ (match_dup 1)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*ssabsqq2"
[(set (match_operand:QQ 0 "register_operand" "=r")
@@ -241,9 +231,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:ALL2S 24)
- (ss_abs_neg:ALL2S (reg:ALL2S 24)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*<code_stdname><mode>2"
[(set (reg:ALL2S 24)
@@ -261,9 +250,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:ALL4S 22)
- (ss_abs_neg:ALL4S (reg:ALL4S 22)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*<code_stdname><mode>2"
[(set (reg:ALL4S 22)
@@ -296,10 +284,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (mult:QQ (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*mulqq3_enh"
[(set (match_operand:QQ 0 "register_operand" "=r")
@@ -317,10 +303,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (mult:UQQ (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*muluqq3_enh"
[(set (match_operand:UQQ 0 "register_operand" "=r")
@@ -377,12 +361,8 @@
"!AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (reg:QQ 23)
- (mult:QQ (reg:QQ 24)
- (reg:QQ 25)))
- (clobber (reg:QI 22))
- (clobber (reg:HI 24))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*mulqq3.call"
[(set (reg:QQ 23)
@@ -425,11 +405,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (reg:ALL2QA 24)
- (mult:ALL2QA (reg:ALL2QA 18)
- (reg:ALL2QA 26)))
- (clobber (reg:HI 22))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*mul<mode>3.call"
[(set (reg:ALL2QA 24)
@@ -468,10 +445,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (reg:ALL4A 24)
- (mult:ALL4A (reg:ALL4A 16)
- (reg:ALL4A 20)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*mul<mode>3.call"
[(set (reg:ALL4A 24)
@@ -514,11 +489,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:ALL1Q 24)
- (usdiv:ALL1Q (reg:ALL1Q 25)
- (reg:ALL1Q 22)))
- (clobber (reg:QI 25))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*<code><mode>3.call"
[(set (reg:ALL1Q 24)
@@ -560,12 +532,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:ALL2QA 24)
- (usdiv:ALL2QA (reg:ALL2QA 26)
- (reg:ALL2QA 22)))
- (clobber (reg:HI 26))
- (clobber (reg:QI 21))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*<code><mode>3.call"
[(set (reg:ALL2QA 24)
@@ -608,12 +576,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:ALL4A 22)
- (usdiv:ALL4A (reg:ALL4A 24)
- (reg:ALL4A 18)))
- (clobber (reg:HI 26))
- (clobber (reg:HI 30))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*<code><mode>3.call"
[(set (reg:ALL4A 22)
@@ -684,12 +648,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (unspec:ALL124QA [(match_dup 1)
- (match_dup 2)
- (const_int 0)]
- UNSPEC_ROUND))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*round<mode>3_const"
[(set (match_operand:ALL124QA 0 "register_operand" "=d")
@@ -714,11 +674,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:ALL1Q 24)
- (unspec:ALL1Q [(reg:ALL1Q 22)
- (reg:QI 24)] UNSPEC_ROUND))
- (clobber (reg:ALL1Q 22))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*round<mode>3.libgcc"
[(set (reg:ALL1Q 24)
@@ -740,11 +697,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:ALL2QA 24)
- (unspec:ALL2QA [(reg:ALL2QA 22)
- (reg:QI 24)] UNSPEC_ROUND))
- (clobber (reg:ALL2QA 22))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*round<mode>3.libgcc"
[(set (reg:ALL2QA 24)
@@ -766,11 +720,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:ALL4QA 22)
- (unspec:ALL4QA [(reg:ALL4QA 18)
- (reg:QI 24)] UNSPEC_ROUND))
- (clobber (reg:ALL4QA 18))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*round<mode>3.libgcc"
[(set (reg:ALL4QA 22)
diff --git a/gcc/config/avr/avr-log.cc b/gcc/config/avr/avr-log.cc
index fadb3ca..972ba6b 100644
--- a/gcc/config/avr/avr-log.cc
+++ b/gcc/config/avr/avr-log.cc
@@ -373,7 +373,6 @@ avr_log_set_avr_log (void)
SET_DUMP_DETAIL (insn_addresses);
SET_DUMP_DETAIL (legitimate_address_p);
SET_DUMP_DETAIL (legitimize_address);
- SET_DUMP_DETAIL (legitimize_reload_address);
SET_DUMP_DETAIL (progmem);
SET_DUMP_DETAIL (rtx_costs);
diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index 9aa00d3..8ba1945 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -146,7 +146,6 @@ extern void out_shift_with_cnt (const char *templ, rtx_insn *insn,
extern enum reg_class avr_mode_code_base_reg_class (machine_mode, addr_space_t, rtx_code, rtx_code);
extern bool avr_regno_mode_code_ok_for_base_p (int, machine_mode, addr_space_t, rtx_code, rtx_code);
extern rtx avr_incoming_return_addr_rtx (void);
-extern rtx avr_legitimize_reload_address (rtx*, machine_mode, int, int, int, int, rtx (*)(rtx,int));
extern bool avr_adiw_reg_p (rtx);
extern bool avr_mem_flash_p (rtx);
extern bool avr_mem_flashx_p (rtx);
@@ -241,7 +240,6 @@ typedef struct
unsigned insn_addresses :1;
unsigned legitimate_address_p :1;
unsigned legitimize_address :1;
- unsigned legitimize_reload_address :1;
unsigned progmem :1;
unsigned rtx_costs :1;
} avr_log_t;
diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 2afea95..ae49d4d 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -453,13 +453,6 @@ avr_ld_regno_p (int regno)
}
-static bool
-ra_in_progress ()
-{
- return avropt_lra_p ? lra_in_progress : reload_in_progress;
-}
-
-
/* Set `avr_arch' as specified by `-mmcu='.
Return true on success. */
@@ -2347,8 +2340,8 @@ avr_legitimate_address_p (machine_mode mode, rtx x, bool strict)
if (avr_log.legitimate_address_p)
{
avr_edump ("\n%?: ret=%d, mode=%m strict=%d "
- "reload_completed=%d ra_in_progress=%d %s:",
- ok, mode, strict, reload_completed, ra_in_progress (),
+ "reload_completed=%d lra_in_progress=%d %s:",
+ ok, mode, strict, reload_completed, lra_in_progress,
reg_renumber ? "(reg_renumber)" : "");
if (GET_CODE (x) == PLUS
@@ -2418,88 +2411,6 @@ avr_legitimize_address (rtx x, rtx oldx, machine_mode mode)
}
-/* Implement `LEGITIMIZE_RELOAD_ADDRESS'. */
-/* This will allow register R26/27 to be used where it is no worse than normal
- base pointers R28/29 or R30/31. For example, if base offset is greater
- than 63 bytes or for R++ or --R addressing. */
-
-rtx
-avr_legitimize_reload_address (rtx *px, machine_mode mode, int opnum,
- int type, int addr_type, int /*ind_levels*/,
- rtx (*mk_memloc)(rtx,int))
-{
- rtx x = *px;
-
- if (avr_log.legitimize_reload_address)
- avr_edump ("\n%?:%m %r\n", mode, x);
-
- if (1 && (GET_CODE (x) == POST_INC
- || GET_CODE (x) == PRE_DEC))
- {
- push_reload (XEXP (x, 0), XEXP (x, 0), &XEXP (x, 0), &XEXP (x, 0),
- POINTER_REGS, GET_MODE (x), GET_MODE (x), 0, 0,
- opnum, RELOAD_OTHER);
-
- if (avr_log.legitimize_reload_address)
- avr_edump (" RCLASS.1 = %R\n IN = %r\n OUT = %r\n",
- POINTER_REGS, XEXP (x, 0), XEXP (x, 0));
-
- return x;
- }
-
- if (GET_CODE (x) == PLUS
- && REG_P (XEXP (x, 0))
- && reg_equiv_constant (REGNO (XEXP (x, 0))) == 0
- && CONST_INT_P (XEXP (x, 1))
- && INTVAL (XEXP (x, 1)) >= 1)
- {
- bool fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
-
- if (fit)
- {
- if (reg_equiv_address (REGNO (XEXP (x, 0))) != 0)
- {
- int regno = REGNO (XEXP (x, 0));
- rtx mem = mk_memloc (x, regno);
-
- push_reload (XEXP (mem, 0), NULL_RTX, &XEXP (mem, 0), NULL,
- POINTER_REGS, Pmode, VOIDmode, 0, 0,
- 1, (enum reload_type) addr_type);
-
- if (avr_log.legitimize_reload_address)
- avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
- POINTER_REGS, XEXP (mem, 0), NULL_RTX);
-
- push_reload (mem, NULL_RTX, &XEXP (x, 0), NULL,
- BASE_POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
- opnum, (enum reload_type) type);
-
- if (avr_log.legitimize_reload_address)
- avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
- BASE_POINTER_REGS, mem, NULL_RTX);
-
- return x;
- }
- }
- else if (! (frame_pointer_needed
- && XEXP (x, 0) == frame_pointer_rtx))
- {
- push_reload (x, NULL_RTX, px, NULL,
- POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
- opnum, (enum reload_type) type);
-
- if (avr_log.legitimize_reload_address)
- avr_edump (" RCLASS.3 = %R\n IN = %r\n OUT = %r\n",
- POINTER_REGS, x, NULL_RTX);
-
- return x;
- }
- }
-
- return NULL_RTX;
-}
-
-
/* Helper function to print assembler resp. track instruction
sequence lengths. Always return "".
@@ -12847,6 +12758,16 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
return true;
case SIGN_EXTEND:
+ if (GET_CODE (XEXP (x, 0)) == ASHIFT
+ && CONST_INT_P (XEXP (XEXP (x, 0), 1)))
+ {
+ // "*sext.ashift<QIPSI:mode><HISI:mode>2_split"
+ int m0 = GET_MODE_SIZE (GET_MODE (XEXP (x, 0)));
+ int m1 = GET_MODE_SIZE (mode);
+ *total = COSTS_N_INSNS (m0 * INTVAL (XEXP (XEXP (x, 0), 1))
+ + m1 - m0);
+ return true;
+ }
*total = COSTS_N_INSNS (n_bytes + 2
- GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
*total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
@@ -13959,8 +13880,8 @@ extra_constraint_Q (rtx x)
|| xx == arg_pointer_rtx);
if (avr_log.constraints)
- avr_edump ("\n%?=%d reload_completed=%d ra_in_progress=%d\n %r\n",
- ok, reload_completed, ra_in_progress (), x);
+ avr_edump ("\n%?=%d reload_completed=%d lra_in_progress=%d\n %r\n",
+ ok, reload_completed, lra_in_progress, x);
}
return ok;
@@ -14165,17 +14086,6 @@ avr_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
if (GET_MODE_SIZE (mode) == 1)
return true;
- /* FIXME: Ideally, the following test is not needed.
- However, it turned out that it can reduce the number
- of spill fails. AVR and it's poor endowment with
- address registers is extreme stress test for reload. */
-
- if (GET_MODE_SIZE (mode) >= 4
- && regno + GET_MODE_SIZE (mode) >= REG_30
- // This problem only concerned the old reload.
- && ! avropt_lra_p)
- return false;
-
/* All modes larger than 8 bits should start in an even register. */
return !(regno & 1);
@@ -14937,8 +14847,8 @@ avr_addr_space_legitimate_address_p (machine_mode mode, rtx x, bool strict,
if (avr_log.legitimate_address_p)
{
avr_edump ("\n%?: ret=%b, mode=%m strict=%d "
- "reload_completed=%d ra_in_progress=%d %s:",
- ok, mode, strict, reload_completed, ra_in_progress (),
+ "reload_completed=%d lra_in_progress=%d %s:",
+ ok, mode, strict, reload_completed, lra_in_progress,
reg_renumber ? "(reg_renumber)" : "");
if (GET_CODE (x) == PLUS
@@ -16716,15 +16626,6 @@ avr_unwind_word_mode ()
return Pmode;
}
-
-/* Implement `TARGET_LRA_P'. */
-
-static bool
-avr_use_lra_p ()
-{
- return avropt_lra_p;
-}
-
/* Initialize the GCC target structure. */
@@ -16866,9 +16767,6 @@ avr_use_lra_p ()
#undef TARGET_CONVERT_TO_TYPE
#define TARGET_CONVERT_TO_TYPE avr_convert_to_type
-#undef TARGET_LRA_P
-#define TARGET_LRA_P avr_use_lra_p
-
#undef TARGET_ADDR_SPACE_SUBSET_P
#define TARGET_ADDR_SPACE_SUBSET_P avr_addr_space_subset_p
diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h
index cb818c3..335f9fa5 100644
--- a/gcc/config/avr/avr.h
+++ b/gcc/config/avr/avr.h
@@ -309,12 +309,6 @@ enum reg_class {
#define STATIC_CHAIN_REGNUM ((AVR_TINY) ? 18 :2)
-#define RELOAD_ELIMINABLE_REGS { \
- { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM }, \
- { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM }, \
- { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM }, \
- { FRAME_POINTER_REGNUM + 1, STACK_POINTER_REGNUM + 1 } }
-
#define ELIMINABLE_REGS \
{ \
{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM }, \
@@ -358,18 +352,6 @@ typedef struct avr_args
#define MAX_REGS_PER_ADDRESS 1
-#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_L,WIN) \
- do { \
- rtx new_x = avr_legitimize_reload_address (&(X), MODE, OPNUM, TYPE, \
- ADDR_TYPE (TYPE), \
- IND_L, make_memloc); \
- if (new_x) \
- { \
- X = new_x; \
- goto WIN; \
- } \
- } while (0)
-
/* We increase branch costs after reload in order to keep basic-block
reordering from introducing out-of-line jumps and to prefer fall-through
edges instead. The default branch costs are 0, mainly because otherwise
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index f8bbdc7..60b1f60 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -574,9 +574,8 @@
&& REG_Z == REGNO (XEXP (operands[0], 0))"
"#"
"&& reload_completed"
- [(parallel [(set (reg:MOVMODE 22)
- (match_dup 0))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*load_<mode>_libgcc"
[(set (reg:MOVMODE 22)
@@ -716,14 +715,8 @@
|| avr_load_libgcc_insn_p (insn, ADDR_SPACE_FLASHX, true)"
"#"
"&& reload_completed"
- [(parallel [(set (reg:MOVMODE REG_22)
- (match_dup 0))
- (clobber (reg:QI REG_21))
- (clobber (reg:HI REG_Z))
- (clobber (reg:CC REG_CC))])]
- {
- operands[0] = SET_SRC (single_set (curr_insn));
- })
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*fxload_<mode>_libgcc"
[(set (reg:MOVMODE REG_22)
@@ -853,9 +846,8 @@
|| reg_or_0_operand (operands[1], <MODE>mode)"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (match_dup 1))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
;; "movqi_insn"
;; "movqq_insn" "movuqq_insn"
@@ -964,9 +956,8 @@
|| reg_or_0_operand (operands[1], <MODE>mode)"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (match_dup 1))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*mov<mode>"
[(set (match_operand:ALL2 0 "nonimmediate_operand" "=r,r ,r,m ,d,*r,q,r")
@@ -1137,9 +1128,8 @@
|| const0_rtx == operands[1]"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (match_dup 1))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*movpsi"
[(set (match_operand:PSI 0 "nonimmediate_operand" "=r,r,r ,Qm,!d,r")
@@ -1197,9 +1187,8 @@
|| reg_or_0_operand (operands[1], <MODE>mode)"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (match_dup 1))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*mov<mode>"
[(set (match_operand:ALL4 0 "nonimmediate_operand" "=r,r ,r ,Qm ,!d,r")
@@ -1245,9 +1234,8 @@
|| reg_or_0_operand (operands[1], SFmode)"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (match_dup 1))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*movsf"
[(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r ,Qm,!d,r")
@@ -1326,16 +1314,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (mem:BLK (reg:HI REG_X))
- (mem:BLK (reg:HI REG_Z)))
- (unspec [(match_dup 0)]
- UNSPEC_CPYMEM)
- (use (match_dup 1))
- (clobber (reg:HI REG_X))
- (clobber (reg:HI REG_Z))
- (clobber (reg:QI LPM_REGNO))
- (clobber (match_dup 2))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*cpymem_<mode>"
[(set (mem:BLK (reg:HI REG_X))
@@ -1382,22 +1362,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (mem:BLK (reg:HI REG_X))
- (match_dup 2))
- (unspec [(match_dup 0)]
- UNSPEC_CPYMEM)
- (use (reg:QIHI 24))
- (clobber (reg:HI REG_X))
- (clobber (reg:HI REG_Z))
- (clobber (reg:QI LPM_REGNO))
- (clobber (reg:HI 24))
- (clobber (reg:QI 23))
- (clobber (mem:QI (match_dup 1)))
- (clobber (reg:CC REG_CC))])]
- {
- rtx xset = XVECEXP (PATTERN (curr_insn), 0, 0);
- operands[2] = SET_SRC (xset);
- })
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*cpymemx_<mode>"
[(set (mem:BLK (reg:HI REG_X))
@@ -1461,13 +1427,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (mem:BLK (match_dup 0))
- (const_int 0))
- (use (match_dup 1))
- (use (match_dup 2))
- (clobber (match_dup 3))
- (clobber (match_dup 4))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*clrmemqi"
[(set (mem:BLK (match_operand:HI 0 "register_operand" "e"))
@@ -1492,14 +1453,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (mem:BLK (match_dup 0))
- (const_int 0))
- (use (match_dup 1))
- (use (match_dup 2))
- (clobber (match_dup 3))
- (clobber (match_dup 4))
- (clobber (reg:CC REG_CC))])]
- ""
+ [(scratch)]
+ { DONE_ADD_CCC }
[(set_attr "isa" "adiw,*")])
@@ -1550,13 +1505,8 @@
""
"#"
"&& reload_completed"
- [(parallel
- [(set (match_dup 0)
- (unspec:HI [(mem:BLK (match_dup 1))
- (const_int 0)
- (match_dup 2)]
- UNSPEC_STRLEN))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*strlenhi"
[(set (match_operand:HI 0 "register_operand" "=e")
@@ -1581,10 +1531,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (plus:ALL1 (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*add<mode>3"
[(set (match_operand:ALL1 0 "register_operand" "=r,d ,r ,r ,r ,r")
@@ -1640,10 +1588,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (plus:HI (zero_extend:HI (match_dup 1))
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*addhi3_zero_extend"
[(set (match_operand:HI 0 "register_operand" "=r,*?r")
@@ -1663,10 +1609,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (plus:HI (match_dup 1)
- (zero_extend:HI (match_dup 2))))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*addhi3_zero_extend1"
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -1684,10 +1628,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (plus:HI (zero_extend:HI (match_dup 1))
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*addhi3_zero_extend.const"
[(set (match_operand:HI 0 "register_operand" "=d")
@@ -1723,11 +1665,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (plus:HI (ashift:HI (zero_extend:HI (match_dup 1))
- (const_int 1))
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*addhi3_zero_extend.ashift1"
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -1752,11 +1691,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (plus:HI (zero_extend:HI (match_dup 1))
- (zero_extend:HI (match_dup 2))))
- (clobber (reg:CC REG_CC))])])
-
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*usum_widenqihi3"
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -1774,10 +1710,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (minus:HI (zero_extend:HI (match_dup 1))
- (zero_extend:HI (match_dup 2))))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*udiff_widenqihi3"
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -1797,7 +1731,7 @@
return avr_out_addto_sp (operands, NULL);
}
""
- [(const_int 0)]
+ [(scratch)]
{
// Do not attempt to split this pattern. This FAIL is necessary
// to prevent the splitter from matching *add<ALL2>3_split, splitting
@@ -1909,11 +1843,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (plus:ALL2 (match_dup 1)
- (match_dup 2)))
- (clobber (match_dup 3))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
;; "*addhi3_clobber"
;; "*addhq3_clobber" "*adduhq3_clobber"
@@ -1943,11 +1874,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (plus:ALL4 (match_dup 1)
- (match_dup 2)))
- (clobber (match_dup 3))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*add<mode>3"
[(set (match_operand:ALL4 0 "register_operand" "=??r,d ,r")
@@ -1979,10 +1907,8 @@
&& (<HISI:SIZE> > 2 || <CODE> == SIGN_EXTEND)"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (plus:HISI (any_extend:HISI (match_dup 1))
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
;; "*addhi3.sign_extend.qi"
;; "*addpsi3.zero_extend.qi" "*addpsi3.sign_extend.qi"
@@ -2019,10 +1945,8 @@
"<HISI:SIZE> > <QIPSI:SIZE>"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (minus:HISI (match_dup 1)
- (any_extend:HISI (match_dup 2))))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
;; "*subhi3.zero_extend.qi" "*subhi3.sign_extend.qi"
;; "*subpsi3.zero_extend.qi" "*subpsi3.sign_extend.qi"
@@ -2053,11 +1977,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (plus:PSI (match_dup 1)
- (match_dup 2)))
- (clobber (match_dup 3 ))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*addpsi3"
[(set (match_operand:PSI 0 "register_operand" "=??r,d ,d,r")
@@ -2079,10 +2000,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (minus:PSI (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*subpsi3"
[(set (match_operand:PSI 0 "register_operand" "=r")
@@ -2106,10 +2025,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (minus:ALL1 (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*sub<mode>3"
[(set (match_operand:ALL1 0 "register_operand" "=??r,d ,r ,r ,r ,r")
@@ -2137,11 +2054,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (minus:ALL2 (match_dup 1)
- (match_dup 2)))
- (clobber (match_dup 3))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*sub<mode>3"
[(set (match_operand:ALL2 0 "register_operand" "=??r,d ,*r")
@@ -2167,11 +2081,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (minus:ALL4 (match_dup 1)
- (match_dup 2)))
- (clobber (match_dup 3))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*sub<mode>3"
[(set (match_operand:ALL4 0 "register_operand" "=??r,d ,r")
@@ -2209,10 +2120,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (mult:QI (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*mulqi3_enh"
[(set (match_operand:QI 0 "register_operand" "=r")
@@ -2243,10 +2152,8 @@
"!AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (reg:QI 24)
- (mult:QI (reg:QI 24) (reg:QI 22)))
- (clobber (reg:QI 22))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*mulqi3_call"
[(set (reg:QI 24)
@@ -2269,12 +2176,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (truncate:QI
- (lshiftrt:HI (mult:HI (any_extend:HI (match_dup 1))
- (any_extend:HI (match_dup 2)))
- (const_int 8))))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*<extend_su>mulqi3_highpart"
[(set (match_operand:QI 0 "register_operand" "=r")
@@ -2361,21 +2264,21 @@
(const_int 0))))
(clobber (reg:CC REG_CC))])])
-;; *subqi3.lt0 *subqi3.ge0
-;; *subhi3.lt0 *subhi3.ge0
-;; *subpsi3.lt0 *subpsi3.ge0
-;; *subsi3.lt0 *subsi3.ge0
-(define_insn "*sub<QISI:mode>3.<code>0"
- [(set (match_operand:QISI 0 "register_operand" "=r")
- (minus:QISI (match_operand:QISI 1 "register_operand" "0")
- (gelt:QISI (match_operand:QISI2 2 "register_operand" "r")
- (const_int 0))))
- (clobber (reg:CC REG_CC))]
- "reload_completed"
- {
- return avr_out_add_msb (insn, operands, <CODE>, nullptr);
- }
- [(set_attr "adjust_len" "add_<code>0")])
+;; *addqi3.lt0_split *addqi3.ge0_split
+;; *addhi3.lt0_split *addhi3.ge0_split
+;; *addpsi3.lt0_split *addpsi3.ge0_split
+;; *addsi3.lt0_split *addsi3.ge0_split
+(define_insn_and_split "*add<QISI:mode>3.<code>0_split"
+ [(set (match_operand:QISI 0 "register_operand" "=r")
+ (plus:QISI (gelt:QISI (match_operand:QISI2 1 "register_operand" "r")
+ (const_int 0))
+ (match_operand:QISI 2 "register_operand" "0")))]
+ ""
+ "#"
+ "&& reload_completed"
+ ; *add<QISI:mode>3.<code>0
+ [(scratch)]
+ { DONE_ADD_CCC })
;; *addqi3.lt0 *addqi3.ge0
;; *addhi3.lt0 *addhi3.ge0
@@ -2393,25 +2296,6 @@
}
[(set_attr "adjust_len" "add_<code>0")])
-;; *addqi3.lt0_split *addqi3.ge0_split
-;; *addhi3.lt0_split *addhi3.ge0_split
-;; *addpsi3.lt0_split *addpsi3.ge0_split
-;; *addsi3.lt0_split *addsi3.ge0_split
-(define_insn_and_split "*add<QISI:mode>3.<code>0_split"
- [(set (match_operand:QISI 0 "register_operand" "=r")
- (plus:QISI (gelt:QISI (match_operand:QISI2 1 "register_operand" "r")
- (const_int 0))
- (match_operand:QISI 2 "register_operand" "0")))]
- ""
- "#"
- "&& reload_completed"
- [; *add<QISI:mode>3.<code>0
- (parallel [(set (match_dup 0)
- (plus:QISI (gelt:QISI (match_dup 1)
- (const_int 0))
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])])
-
;; *subqi3.lt0_split *subqi3.ge0_split
;; *subhi3.lt0_split *subhi3.ge0_split
;; *subpsi3.lt0_split *subpsi3.ge0_split
@@ -2424,13 +2308,25 @@
""
"#"
"&& reload_completed"
- [; *sub<QISI:mode>3.<code>0
- (parallel [(set (match_dup 0)
- (minus:QISI (match_dup 1)
- (gelt:QISI (match_dup 2)
- (const_int 0))))
- (clobber (reg:CC REG_CC))])])
+ ; *sub<QISI:mode>3.<code>0
+ [(scratch)]
+ { DONE_ADD_CCC })
+;; *subqi3.lt0 *subqi3.ge0
+;; *subhi3.lt0 *subhi3.ge0
+;; *subpsi3.lt0 *subpsi3.ge0
+;; *subsi3.lt0 *subsi3.ge0
+(define_insn "*sub<QISI:mode>3.<code>0"
+ [(set (match_operand:QISI 0 "register_operand" "=r")
+ (minus:QISI (match_operand:QISI 1 "register_operand" "0")
+ (gelt:QISI (match_operand:QISI2 2 "register_operand" "r")
+ (const_int 0))))
+ (clobber (reg:CC REG_CC))]
+ "reload_completed"
+ {
+ return avr_out_add_msb (insn, operands, <CODE>, nullptr);
+ }
+ [(set_attr "adjust_len" "add_<code>0")])
(define_insn_and_split "*umulqihi3.call_split"
[(set (reg:HI 24)
@@ -2441,12 +2337,8 @@
"!AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (reg:HI 24)
- (mult:HI (zero_extend:HI (reg:QI 22))
- (zero_extend:HI (reg:QI 24))))
- (clobber (reg:QI 21))
- (clobber (reg:HI 22))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*umulqihi3.call"
[(set (reg:HI 24)
@@ -2469,10 +2361,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (mult:HI (any_extend:HI (match_dup 1))
- (any_extend:HI (match_dup 2))))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "<extend_u>mulqihi3"
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -2492,10 +2382,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (mult:HI (zero_extend:HI (match_dup 1))
- (sign_extend:HI (match_dup 2))))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*usmulqihi3"
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -2517,10 +2405,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (mult:HI (sign_extend:HI (match_dup 1))
- (zero_extend:HI (match_dup 2))))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*sumulqihi3"
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -2542,10 +2428,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (mult:HI (not:HI (zero_extend:HI (not:QI (match_dup 1))))
- (sign_extend:HI (match_dup 2))))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*osmulqihi3"
[(set (match_operand:HI 0 "register_operand" "=&r")
@@ -2566,10 +2450,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (mult:HI (not:HI (zero_extend:HI (not:QI (match_dup 1))))
- (zero_extend:HI (match_dup 2))))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*oumulqihi3"
[(set (match_operand:HI 0 "register_operand" "=&r")
@@ -2596,11 +2478,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (plus:QI (mult:QI (match_dup 1)
- (match_dup 2))
- (match_dup 3)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*maddqi4"
[(set (match_operand:QI 0 "register_operand" "=r")
@@ -2622,11 +2501,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (minus:QI (match_dup 3)
- (mult:QI (match_dup 1)
- (match_dup 2))))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*msubqi4"
[(set (match_operand:QI 0 "register_operand" "=r")
@@ -2705,11 +2581,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (plus:HI (mult:HI (any_extend:HI (match_dup 1))
- (any_extend:HI (match_dup 2)))
- (match_dup 3)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*<extend_u>maddqihi4"
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -2734,11 +2607,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (minus:HI (match_dup 3)
- (mult:HI (any_extend:HI (match_dup 1))
- (any_extend:HI (match_dup 2)))))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*<extend_u>msubqihi4"
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -2765,11 +2635,8 @@
&& <any_extend:CODE> != <any_extend2:CODE>"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (plus:HI (mult:HI (any_extend:HI (match_dup 1))
- (any_extend2:HI (match_dup 2)))
- (match_dup 3)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*<any_extend:extend_su><any_extend2:extend_su>msubqihi4"
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -2800,11 +2667,8 @@
&& <any_extend:CODE> != <any_extend2:CODE>"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (minus:HI (match_dup 3)
- (mult:HI (any_extend:HI (match_dup 1))
- (any_extend2:HI (match_dup 2)))))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*<any_extend:extend_su><any_extend2:extend_su>msubqihi4"
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -3072,16 +2936,14 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (ashift:HI (sign_extend:HI (match_dup 1))
- (const_int 1)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*ashiftqihi2.signx.1"
[(set (match_operand:HI 0 "register_operand" "=r,*r")
(ashift:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "0,r"))
(const_int 1)))
- (clobber (reg:CC REG_CC)) ]
+ (clobber (reg:CC REG_CC))]
"reload_completed"
"@
lsl %A0\;sbc %B0,%B0
@@ -3142,6 +3004,41 @@
operands[2] = gen_int_mode (1 << INTVAL (operands[2]), QImode);
})
+(define_insn_and_split "*sext.ashift<QIPSI:mode><HISI:mode>2_split"
+ [(set (match_operand:HISI 0 "register_operand" "=r")
+ (sign_extend:HISI (ashift:QIPSI (match_operand:QIPSI 1 "register_operand" "0")
+ (match_operand:QI 2 "const_int_operand" "PKC03"))))]
+ "<HISI:SIZE> > <QIPSI:SIZE>
+ && IN_RANGE (INTVAL (operands[2]), 1, 2 + (<QIPSI:SIZE> <= 2))"
+ "#"
+ "&& reload_completed"
+ [(scratch)]
+ { DONE_ADD_CCC })
+
+(define_insn "*sext.ashift<QIPSI:mode><HISI:mode>2"
+ [(set (match_operand:HISI 0 "register_operand" "=r")
+ (sign_extend:HISI (ashift:QIPSI (match_operand:QIPSI 1 "register_operand" "0")
+ (match_operand:QI 2 "const_int_operand" "PKC03"))))
+ (clobber (reg:CC REG_CC))]
+ "reload_completed
+ && <HISI:SIZE> > <QIPSI:SIZE>
+ && IN_RANGE (INTVAL (operands[2]), 1, 2 + (<QIPSI:SIZE> <= 2))"
+ {
+ const int regno = REGNO (operands[0]);
+ // The shift.
+ for (int s = 0; s < (int) INTVAL (operands[2]); ++s)
+ for (int b = 0; b < <QIPSI:SIZE>; ++b)
+ output_asm_insn (b == 0 ? "lsl %0" : "rol %0",
+ &all_regs_rtx[regno + b]);
+ // Sign-extend can use carry.
+ for (int b = <QIPSI:SIZE>; b < <HISI:SIZE>; ++b)
+ output_asm_insn ("sbc %0,%0", &all_regs_rtx[regno + b]);
+ return "";
+ }
+ [(set (attr "length")
+ (plus (symbol_ref "<QIPSI:SIZE> * INTVAL (operands[2])")
+ (symbol_ref "<HISI:SIZE> - <QIPSI:SIZE>")))])
+
;******************************************************************************
; mul HI: $1 = sign-/zero-/one-extend, $2 = reg
;******************************************************************************
@@ -3153,10 +3050,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (mult:HI (sign_extend:HI (match_dup 1))
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*mulsqihi3"
[(set (match_operand:HI 0 "register_operand" "=&r")
@@ -3178,10 +3073,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (mult:HI (zero_extend:HI (match_dup 1))
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*muluqihi3"
[(set (match_operand:HI 0 "register_operand" "=&r")
@@ -3205,10 +3098,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (mult:HI (not:HI (zero_extend:HI (not:QI (match_dup 1))))
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*muloqihi3"
[(set (match_operand:HI 0 "register_operand" "=&r")
@@ -3277,10 +3168,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (mult:HI (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*mulhi3_enh"
[(set (match_operand:HI 0 "register_operand" "=&r")
@@ -3319,11 +3208,8 @@
"!AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (reg:HI 24)
- (mult:HI (reg:HI 24) (reg:HI 22)))
- (clobber (reg:HI 22))
- (clobber (reg:QI 21))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*mulhi3_call"
[(set (reg:HI 24)
@@ -3719,11 +3605,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (reg:SI 22)
- (mult:SI (reg:SI 22)
- (reg:SI 18)))
- (clobber (reg:HI 26))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn_and_split "*mulsi3_call_pr118012_split"
[(set (reg:SI 22)
@@ -3737,13 +3620,8 @@
&& ! AVR_TINY"
"#"
"&& reload_completed"
- [(parallel [(set (reg:SI 22)
- (mult:SI (reg:SI 22)
- (reg:SI 18)))
- (clobber (reg:SI 18))
- (clobber (reg:HI 26))
- (clobber (reg:HI 30))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*mulsi3_call"
[(set (reg:SI 22)
@@ -3779,10 +3657,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (reg:SI 22)
- (mult:SI (any_extend:SI (reg:HI 18))
- (any_extend:SI (reg:HI 26))))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*<extend_u>mulhisi3_call"
[(set (reg:SI 22)
@@ -3804,12 +3680,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (reg:HI 24)
- (truncate:HI (lshiftrt:SI (mult:SI (any_extend:SI (reg:HI 18))
- (any_extend:SI (reg:HI 26)))
- (const_int 16))))
- (clobber (reg:HI 22))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*<extend_su>mulhi3_highpart_call"
[(set (reg:HI 24)
@@ -3829,10 +3701,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (reg:SI 22)
- (mult:SI (zero_extend:SI (reg:HI 18))
- (sign_extend:SI (reg:HI 26))))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*usmulhisi3_call"
[(set (reg:SI 22)
@@ -3850,10 +3720,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (reg:SI 22)
- (mult:SI (any_extend:SI (reg:HI 26))
- (reg:SI 18)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*mul<extend_su>hisi3_call"
[(set (reg:SI 22)
@@ -3871,10 +3739,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (reg:SI 22)
- (mult:SI (not:SI (zero_extend:SI (not:HI (reg:HI 26))))
- (reg:SI 18)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*mulohisi3_call"
[(set (reg:SI 22)
@@ -3925,11 +3791,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:QI 24) (div:QI (reg:QI 24) (reg:QI 22)))
- (set (reg:QI 25) (mod:QI (reg:QI 24) (reg:QI 22)))
- (clobber (reg:QI 22))
- (clobber (reg:QI 23))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*divmodqi4_call"
[(set (reg:QI 24) (div:QI (reg:QI 24) (reg:QI 22)))
@@ -3969,10 +3832,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:QI 24) (udiv:QI (reg:QI 24) (reg:QI 22)))
- (set (reg:QI 25) (umod:QI (reg:QI 24) (reg:QI 22)))
- (clobber (reg:QI 23))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*udivmodqi4_call"
[(set (reg:QI 24) (udiv:QI (reg:QI 24) (reg:QI 22)))
@@ -4013,11 +3874,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:HI 22) (div:HI (reg:HI 24) (reg:HI 22)))
- (set (reg:HI 24) (mod:HI (reg:HI 24) (reg:HI 22)))
- (clobber (reg:HI 26))
- (clobber (reg:QI 21))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*divmodhi4_call"
[(set (reg:HI 22) (div:HI (reg:HI 24) (reg:HI 22)))
@@ -4059,11 +3917,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:HI 22) (udiv:HI (reg:HI 24) (reg:HI 22)))
- (set (reg:HI 24) (umod:HI (reg:HI 24) (reg:HI 22)))
- (clobber (reg:HI 26))
- (clobber (reg:QI 21))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*udivmodhi4_call"
[(set (reg:HI 22) (udiv:HI (reg:HI 24) (reg:HI 22)))
@@ -4112,10 +3967,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (mult:PSI (zero_extend:PSI (match_dup 1))
- (zero_extend:PSI (match_dup 2))))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*umulqihipsi3"
[(set (match_operand:PSI 0 "register_operand" "=&r")
@@ -4134,31 +3987,17 @@
(define_insn_and_split "*umulhiqipsi3_split"
[(set (match_operand:PSI 0 "register_operand" "=&r")
- (mult:PSI (zero_extend:PSI (match_operand:HI 2 "register_operand" "r"))
- (zero_extend:PSI (match_operand:QI 1 "register_operand" "r"))))]
+ (mult:PSI (zero_extend:PSI (match_operand:HI 1 "register_operand" "r"))
+ (zero_extend:PSI (match_operand:QI 2 "register_operand" "r"))))]
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
+ ; "*umulqihipsi3"
[(parallel [(set (match_dup 0)
(mult:PSI (zero_extend:PSI (match_dup 2))
(zero_extend:PSI (match_dup 1))))
(clobber (reg:CC REG_CC))])])
-(define_insn "*umulhiqipsi3"
- [(set (match_operand:PSI 0 "register_operand" "=&r")
- (mult:PSI (zero_extend:PSI (match_operand:HI 2 "register_operand" "r"))
- (zero_extend:PSI (match_operand:QI 1 "register_operand" "r"))))
- (clobber (reg:CC REG_CC))]
- "AVR_HAVE_MUL && reload_completed"
- "mul %1,%A2
- movw %A0,r0
- mul %1,%B2
- add %B0,r0
- mov %C0,r1
- clr __zero_reg__
- adc %C0,__zero_reg__"
- [(set_attr "length" "7")])
-
(define_expand "mulsqipsi3"
[(parallel [(set (match_operand:PSI 0 "pseudo_register_operand" "")
(mult:PSI (sign_extend:PSI (match_operand:QI 1 "pseudo_register_operand" ""))
@@ -4229,10 +4068,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (reg:PSI 18)
- (mult:PSI (sign_extend:PSI (reg:QI 25))
- (reg:PSI 22)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*mulsqipsi3.libgcc"
[(set (reg:PSI 18)
@@ -4253,13 +4090,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (reg:PSI 22)
- (mult:PSI (reg:PSI 22)
- (reg:PSI 18)))
- (clobber (reg:QI 21))
- (clobber (reg:QI 25))
- (clobber (reg:HI 26))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*mulpsi3.libgcc"
[(set (reg:PSI 22)
@@ -4311,12 +4143,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:PSI 22) (div:PSI (reg:PSI 22) (reg:PSI 18)))
- (set (reg:PSI 18) (mod:PSI (reg:PSI 22) (reg:PSI 18)))
- (clobber (reg:QI 21))
- (clobber (reg:QI 25))
- (clobber (reg:QI 26))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*divmodpsi4_call"
[(set (reg:PSI 22) (div:PSI (reg:PSI 22) (reg:PSI 18)))
@@ -4360,12 +4188,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:PSI 22) (udiv:PSI (reg:PSI 22) (reg:PSI 18)))
- (set (reg:PSI 18) (umod:PSI (reg:PSI 22) (reg:PSI 18)))
- (clobber (reg:QI 21))
- (clobber (reg:QI 25))
- (clobber (reg:QI 26))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*udivmodpsi4_call"
[(set (reg:PSI 22) (udiv:PSI (reg:PSI 22) (reg:PSI 18)))
@@ -4411,11 +4235,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:SI 18) (div:SI (reg:SI 22) (reg:SI 18)))
- (set (reg:SI 22) (mod:SI (reg:SI 22) (reg:SI 18)))
- (clobber (reg:HI 26))
- (clobber (reg:HI 30))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*divmodsi4_call"
[(set (reg:SI 18) (div:SI (reg:SI 22) (reg:SI 18)))
@@ -4458,11 +4279,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:SI 18) (udiv:SI (reg:SI 22) (reg:SI 18)))
- (set (reg:SI 22) (umod:SI (reg:SI 22) (reg:SI 18)))
- (clobber (reg:HI 26))
- (clobber (reg:HI 30))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*udivmodsi4_call"
[(set (reg:SI 18) (udiv:SI (reg:SI 22) (reg:SI 18)))
@@ -4484,10 +4302,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (and:QI (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*andqi3"
[(set (match_operand:QI 0 "register_operand" "=??r,d,*l ,r")
@@ -4511,11 +4327,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (and:HI (match_dup 1)
- (match_dup 2)))
- (clobber (match_dup 3))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*andhi3"
[(set (match_operand:HI 0 "register_operand" "=??r,d,d,r ,r ,r")
@@ -4545,11 +4358,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (and:PSI (match_dup 1)
- (match_dup 2)))
- (clobber (match_dup 3))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*andpsi3"
[(set (match_operand:PSI 0 "register_operand" "=??r,d,r ,r ,r")
@@ -4580,11 +4390,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (and:SI (match_dup 1)
- (match_dup 2)))
- (clobber (match_dup 3))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*andsi3"
[(set (match_operand:SI 0 "register_operand" "=??r,d,r ,r ,r")
@@ -4634,10 +4441,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (ior:QI (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*iorqi3"
[(set (match_operand:QI 0 "register_operand" "=??r,d,*l")
@@ -4659,11 +4464,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (ior:HI (match_dup 1)
- (match_dup 2)))
- (clobber (match_dup 3))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*iorhi3"
[(set (match_operand:HI 0 "register_operand" "=??r,d,d,r ,r")
@@ -4691,11 +4493,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (ior:PSI (match_dup 1)
- (match_dup 2)))
- (clobber (match_dup 3))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*iorpsi3"
[(set (match_operand:PSI 0 "register_operand" "=??r,d,r ,r")
@@ -4723,11 +4522,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (ior:SI (match_dup 1)
- (match_dup 2)))
- (clobber (match_dup 3))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*iorsi3"
[(set (match_operand:SI 0 "register_operand" "=??r,d,r ,r")
@@ -4758,10 +4554,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (xor:QI (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*xorqi3"
[(set (match_operand:QI 0 "register_operand" "=r")
@@ -4780,11 +4574,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (xor:HI (match_dup 1)
- (match_dup 2)))
- (clobber (match_dup 3))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*xorhi3"
[(set (match_operand:HI 0 "register_operand" "=??r,r ,d ,r")
@@ -4810,11 +4601,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (xor:PSI (match_dup 1)
- (match_dup 2)))
- (clobber (match_dup 3))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*xorpsi3"
[(set (match_operand:PSI 0 "register_operand" "=??r,r ,d ,r")
@@ -4842,11 +4630,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (xor:SI (match_dup 1)
- (match_dup 2)))
- (clobber (match_dup 3))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*xorsi3"
[(set (match_operand:SI 0 "register_operand" "=??r,r ,d ,r")
@@ -4918,7 +4703,7 @@
(clobber (reg:CC REG_CC))])]
"optimize
&& reload_completed"
- [(const_int 1)]
+ [(scratch)]
{
for (int i = 0; i < <SIZE>; i++)
{
@@ -5026,10 +4811,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (rotate:QI (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*rotlqi3"
[(set (match_operand:QI 0 "register_operand" "=r,r,r ,r ,r ,r ,r ,r")
@@ -5099,10 +4882,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (rotate:HI (match_dup 1)
- (const_int 1)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*rotlhi2.1"
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -5120,10 +4901,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (rotate:HI (match_dup 1)
- (const_int 15)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*rotlhi2.15"
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -5141,10 +4920,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (rotate:PSI (match_dup 1)
- (const_int 1)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*rotlpsi2.1"
[(set (match_operand:PSI 0 "register_operand" "=r")
@@ -5162,10 +4939,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (rotate:PSI (match_dup 1)
- (const_int 23)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*rotlpsi2.23"
[(set (match_operand:PSI 0 "register_operand" "=r")
@@ -5183,10 +4958,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (rotate:SI (match_dup 1)
- (const_int 1)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*rotlsi2.1"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -5204,10 +4977,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (rotate:SI (match_dup 1)
- (const_int 31)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*rotlsi2.31"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -5239,7 +5010,7 @@
&& 0 == INTVAL (operands[2]) % 16"
"#"
"&& reload_completed"
- [(const_int 0)]
+ [(scratch)]
{
avr_rotate_bytes (operands);
DONE;
@@ -5263,7 +5034,7 @@
&& 0 == INTVAL (operands[2]) % 16))"
"#"
"&& reload_completed"
- [(const_int 0)]
+ [(scratch)]
{
avr_rotate_bytes (operands);
DONE;
@@ -5273,41 +5044,6 @@
;;<< << << << << << << << << << << << << << << << << << << << << << << << << <<
;; arithmetic shift left
-;; Work around PR120423: Transform left shift of a paradoxical subreg
-;; into left shift of the zero-extended entity.
-(define_split ; PR120423
- [(set (match_operand:HISI 0 "register_operand")
- (ashift:HISI (subreg:HISI (match_operand:QIPSI 1 "nonimmediate_operand")
- 0)
- (match_operand:QI 2 "const_int_operand")))]
- "!reload_completed
- && !avropt_lra_p
- && <HISI:SIZE> > <QIPSI:SIZE>"
- [(set (match_dup 4)
- (zero_extend:HISI (match_dup 5)))
- (set (match_dup 0)
- (ashift:HISI (match_dup 4)
- (match_dup 2)))]
- {
- operands[4] = gen_reg_rtx (<HISI:MODE>mode);
- operands[5] = force_reg (<QIPSI:MODE>mode, operands[1]);
- })
-
-;; Similar happens for PR116389.
-(define_split ; PR116389
- [(set (match_operand:HISI 0 "register_operand")
- (subreg:HISI (match_operand:QIPSI 1 "nonimmediate_operand")
- 0))]
- "!reload_completed
- && !avropt_lra_p
- && <HISI:SIZE> > <QIPSI:SIZE>"
- [(set (match_dup 0)
- (zero_extend:HISI (match_dup 2)))]
- {
- operands[2] = force_reg (<QIPSI:MODE>mode, operands[1]);
- })
-
-
;; "ashlqi3"
;; "ashlqq3" "ashluqq3"
(define_expand "ashl<mode>3"
@@ -5363,10 +5099,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (ashift:ALL1 (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*ashl<mode>3"
[(set (match_operand:ALL1 0 "register_operand" "=r,r ,r ,r,r")
@@ -5390,11 +5124,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (ashift:ALL2 (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])]
- ""
+ [(scratch)]
+ { DONE_ADD_CCC }
[(set_attr "isa" "*,*,*,3op,*,*")])
;; "*ashlhi3"
@@ -5506,11 +5237,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (ashift:ALL4 (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])]
- ""
+ [(scratch)]
+ { DONE_ADD_CCC }
[(set_attr "isa" "*,*,*,3op,*,*")])
(define_insn "*ashl<mode>3"
@@ -5749,12 +5477,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (ashift:PSI (match_dup 1)
- (match_dup 2)))
- (clobber (match_dup 3))
- (clobber (reg:CC REG_CC))])]
- ""
+ [(scratch)]
+ { DONE_ADD_CCC }
[(set_attr "isa" "*,*,*,3op,*")])
(define_insn "*ashlpsi3"
@@ -5808,10 +5532,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (ashiftrt:ALL1 (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*ashr<mode>3"
[(set (match_operand:ALL1 0 "register_operand" "=r,r ,r ,r")
@@ -5835,11 +5557,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (ashiftrt:ALL2 (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])]
- ""
+ [(scratch)]
+ { DONE_ADD_CCC }
[(set_attr "isa" "*,*,*,3op,*,*")])
;; "*ashrhi3"
@@ -5866,12 +5585,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (ashiftrt:PSI (match_dup 1)
- (match_dup 2)))
- (clobber (match_dup 3))
- (clobber (reg:CC REG_CC))])]
- ""
+ [(scratch)]
+ { DONE_ADD_CCC }
[(set_attr "isa" "*,*,*,3op,*")])
(define_insn "*ashrpsi3"
@@ -5898,11 +5613,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (ashiftrt:ALL4 (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])]
- ""
+ [(scratch)]
+ { DONE_ADD_CCC }
[(set_attr "isa" "*,*,*,3op,*,*")])
(define_insn "*ashr<mode>3"
@@ -6013,10 +5725,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (lshiftrt:ALL1 (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*lshr<mode>3"
[(set (match_operand:ALL1 0 "register_operand" "=r,r ,r ,r,r")
@@ -6039,11 +5749,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (lshiftrt:ALL2 (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])]
- ""
+ [(scratch)]
+ { DONE_ADD_CCC }
[(set_attr "isa" "*,*,*,3op,*,*")])
(define_insn "*lshr<mode>3"
@@ -6066,12 +5773,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (lshiftrt:PSI (match_dup 1)
- (match_dup 2)))
- (clobber (match_dup 3))
- (clobber (reg:CC REG_CC))])]
- ""
+ [(scratch)]
+ { DONE_ADD_CCC }
[(set_attr "isa" "*,*,*,3op,*")])
(define_insn "*lshrpsi3"
@@ -6098,11 +5801,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (lshiftrt:ALL4 (match_dup 1)
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])]
- ""
+ [(scratch)]
+ { DONE_ADD_CCC }
[(set_attr "isa" "*,*,*,3op,*,*")])
(define_insn "*lshr<mode>3"
@@ -6217,9 +5917,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (abs:QI (match_dup 1)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*absqi2"
[(set (match_operand:QI 0 "register_operand" "=r")
@@ -6237,9 +5936,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (abs:SF (match_dup 1)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*abssf2"
[(set (match_operand:SF 0 "register_operand" "=d,r")
@@ -6260,9 +5958,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (neg:QI (match_dup 1)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*negqi2"
[(set (match_operand:QI 0 "register_operand" "=r")
@@ -6278,9 +5975,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (neg:HI (sign_extend:HI (match_dup 1))))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*negqihi2"
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -6296,9 +5992,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (neg:HI (match_dup 1)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*neghi2"
[(set (match_operand:HI 0 "register_operand" "=r,&r")
@@ -6316,9 +6011,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (neg:PSI (match_dup 1)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*negpsi2"
[(set (match_operand:PSI 0 "register_operand" "=!d,r,&r")
@@ -6337,10 +6031,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (neg:SI (match_dup 1)))
- (clobber (reg:CC REG_CC))])]
- ""
+ [(scratch)]
+ { DONE_ADD_CCC }
[(set_attr "isa" "*,*,mov,movw")])
(define_insn "*negsi2.libgcc"
@@ -6371,9 +6063,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (neg:SF (match_dup 1)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*negsf2"
[(set (match_operand:SF 0 "register_operand" "=d,r")
@@ -6394,9 +6085,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (not:QI (match_dup 1)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*one_cmplqi2"
[(set (match_operand:QI 0 "register_operand" "=r")
@@ -6412,9 +6102,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (not:HI (match_dup 1)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*one_cmplhi2"
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -6431,9 +6120,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (not:PSI (match_dup 1)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*one_cmplpsi2"
[(set (match_operand:PSI 0 "register_operand" "=r")
@@ -6449,9 +6137,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (not:SI (match_dup 1)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*one_cmplsi2"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -6480,9 +6167,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (sign_extend:HI (match_dup 1)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*extendqihi2"
[(set (match_operand:HI 0 "register_operand" "=r,r")
@@ -6501,9 +6187,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (sign_extend:PSI (match_dup 1)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*extendqipsi2"
[(set (match_operand:PSI 0 "register_operand" "=r,r")
@@ -6522,9 +6207,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (sign_extend:SI (match_dup 1)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*extendqisi2"
[(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -6543,9 +6227,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (sign_extend:PSI (match_dup 1)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*extendhipsi2"
[(set (match_operand:PSI 0 "register_operand" "=r,r")
@@ -6564,9 +6247,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (sign_extend:SI (match_dup 1)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*extendhisi2"
[(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -6585,9 +6267,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (sign_extend:SI (match_dup 1)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*extendpsisi2"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -7032,10 +6713,11 @@
"#"
"reload_completed"
[(set (reg:CC REG_CC)
- (compare:CC (match_dup 1) (match_dup 2)))
+ (compare:CC (match_dup 1)
+ (match_dup 2)))
(set (pc)
- (if_then_else (match_op_dup 0
- [(reg:CC REG_CC) (const_int 0)])
+ (if_then_else (match_op_dup 0 [(reg:CC REG_CC)
+ (const_int 0)])
(label_ref (match_dup 3))
(pc)))])
@@ -7054,11 +6736,12 @@
"#"
"reload_completed"
[(parallel [(set (reg:CC REG_CC)
- (compare:CC (match_dup 1) (match_dup 2)))
+ (compare:CC (match_dup 1)
+ (match_dup 2)))
(clobber (match_dup 4))])
(set (pc)
- (if_then_else (match_op_dup 0
- [(reg:CC REG_CC) (const_int 0)])
+ (if_then_else (match_op_dup 0 [(reg:CC REG_CC)
+ (const_int 0)])
(label_ref (match_dup 3))
(pc)))]
{
@@ -7081,11 +6764,12 @@
"#"
"reload_completed"
[(parallel [(set (reg:CC REG_CC)
- (compare:CC (match_dup 1) (match_dup 2)))
+ (compare:CC (match_dup 1)
+ (match_dup 2)))
(clobber (match_dup 4))])
(set (pc)
- (if_then_else (match_op_dup 0
- [(reg:CC REG_CC) (const_int 0)])
+ (if_then_else (match_op_dup 0 [(reg:CC REG_CC)
+ (const_int 0)])
(label_ref (match_dup 3))
(pc)))]
{
@@ -7109,11 +6793,12 @@
"#"
"reload_completed"
[(parallel [(set (reg:CC REG_CC)
- (compare:CC (match_dup 1) (match_dup 2)))
+ (compare:CC (match_dup 1)
+ (match_dup 2)))
(clobber (match_dup 4))])
(set (pc)
- (if_then_else (match_op_dup 0
- [(reg:CC REG_CC) (const_int 0)])
+ (if_then_else (match_op_dup 0 [(reg:CC REG_CC)
+ (const_int 0)])
(label_ref (match_dup 3))
(pc)))]
{
@@ -7668,17 +7353,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (pc)
- (if_then_else
- (match_op_dup 0
- [(zero_extract:QIDI
- (match_dup 1)
- (const_int 1)
- (match_dup 2))
- (const_int 0)])
- (label_ref (match_dup 3))
- (pc)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*sbrx_branch<mode>"
[(set (pc)
@@ -7721,13 +7397,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (pc)
- (if_then_else (match_op_dup 0 [(and:QISI (match_dup 1)
- (match_dup 2))
- (const_int 0)])
- (label_ref (match_dup 3))
- (pc)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*sbrx_and_branch<mode>"
[(set (pc)
@@ -7968,14 +7639,8 @@
"!AVR_HAVE_EIJMP_EICALL"
"#"
"&& reload_completed"
- [(parallel [(set (pc)
- (unspec:HI [(match_dup 0)]
- UNSPEC_INDEX_JMP))
- (use (label_ref (match_dup 1)))
- (clobber (match_dup 2))
- (clobber (const_int 0))
- (clobber (reg:CC REG_CC))])]
- ""
+ [(scratch)]
+ { DONE_ADD_CCC }
[(set_attr "isa" "rjmp,rjmp,jmp")])
(define_insn "*tablejump"
@@ -8004,14 +7669,8 @@
"AVR_HAVE_EIJMP_EICALL"
"#"
"&& reload_completed"
- [(parallel [(set (pc)
- (unspec:HI [(reg:HI REG_Z)]
- UNSPEC_INDEX_JMP))
- (use (label_ref (match_dup 0)))
- (clobber (reg:HI REG_Z))
- (clobber (reg:QI 24))
- (clobber (reg:CC REG_CC))])]
- ""
+ [(scratch)]
+ { DONE_ADD_CCC }
[(set_attr "isa" "eijmp")])
@@ -8182,17 +7841,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (pc)
- (if_then_else
- (match_operator 0 "eqne_operator"
- [(zero_extract:QIHI
- (mem:QI (match_dup 1))
- (const_int 1)
- (match_dup 2))
- (const_int 0)])
- (label_ref (match_dup 3))
- (pc)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*sbix_branch"
[(set (pc)
@@ -8230,14 +7880,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (pc)
- (if_then_else
- (match_operator 0 "gelt_operator"
- [(mem:QI (match_dup 1))
- (const_int 0)])
- (label_ref (match_dup 2))
- (pc)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*sbix_branch_bit7"
[(set (pc)
@@ -8277,17 +7921,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (pc)
- (if_then_else
- (match_operator 0 "eqne_operator"
- [(zero_extract:QIHI
- (mem:QI (match_dup 1))
- (const_int 1)
- (match_dup 2))
- (const_int 0)])
- (label_ref (match_dup 3))
- (pc)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*sbix_branch_tmp"
[(set (pc)
@@ -8324,14 +7959,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (pc)
- (if_then_else
- (match_operator 0 "gelt_operator"
- [(mem:QI (match_dup 1))
- (const_int 0)])
- (label_ref (match_dup 2))
- (pc)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*sbix_branch_tmp_bit7"
[(set (pc)
@@ -8784,13 +8413,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(unspec_volatile [(match_dup 0)
- (const_int 1)]
- UNSPECV_DELAY_CYCLES)
- (set (match_dup 1)
- (unspec_volatile:BLK [(match_dup 1)] UNSPECV_MEMORY_BARRIER))
- (clobber (match_dup 2))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*delay_cycles_1"
[(unspec_volatile [(match_operand:QI 0 "const_int_operand" "n")
@@ -8816,14 +8440,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(unspec_volatile [(match_dup 0)
- (const_int 2)]
- UNSPECV_DELAY_CYCLES)
- (set (match_dup 1)
- (unspec_volatile:BLK [(match_dup 1)] UNSPECV_MEMORY_BARRIER))
- (clobber (match_dup 2))
- (clobber (reg:CC REG_CC))])]
- ""
+ [(scratch)]
+ { DONE_ADD_CCC }
[(set_attr "isa" "adiw,no_adiw")])
(define_insn "*delay_cycles_2"
@@ -8853,15 +8471,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(unspec_volatile [(match_dup 0)
- (const_int 3)]
- UNSPECV_DELAY_CYCLES)
- (set (match_dup 1)
- (unspec_volatile:BLK [(match_dup 1)] UNSPECV_MEMORY_BARRIER))
- (clobber (match_dup 2))
- (clobber (match_dup 3))
- (clobber (match_dup 4))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*delay_cycles_3"
[(unspec_volatile [(match_operand:SI 0 "const_int_operand" "n")
@@ -8896,16 +8507,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(unspec_volatile [(match_dup 0)
- (const_int 4)]
- UNSPECV_DELAY_CYCLES)
- (set (match_dup 1)
- (unspec_volatile:BLK [(match_dup 1)] UNSPECV_MEMORY_BARRIER))
- (clobber (match_dup 2))
- (clobber (match_dup 3))
- (clobber (match_dup 4))
- (clobber (match_dup 5))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*delay_cycles_4"
[(unspec_volatile [(match_operand:SI 0 "const_int_operand" "n")
@@ -8942,12 +8545,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (unspec:QI [(match_dup 1)
- (match_dup 2)
- (match_dup 3)]
- UNSPEC_INSERT_BITS))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*insert_bits"
[(set (match_operand:QI 0 "register_operand" "=r ,d ,r")
@@ -9127,12 +8726,13 @@
"#"
"reload_completed"
[(set (reg:CC REG_CC)
- (compare:CC (match_dup 0) (const_int 0)))
+ (compare:CC (match_dup 0)
+ (const_int 0)))
(set (pc)
- (if_then_else (ge (reg:CC REG_CC) (const_int 0))
+ (if_then_else (ge (reg:CC REG_CC)
+ (const_int 0))
(label_ref (match_dup 1))
- (pc)))]
- "")
+ (pc)))])
(define_expand "flash_segment"
[(parallel [(match_operand:QI 0 "register_operand" "")
@@ -9235,9 +8835,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:HI 24)
- (parity:HI (reg:HI 24)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*parityhi2.libgcc"
[(set (reg:HI 24)
@@ -9253,9 +8852,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:HI 24)
- (zero_extend:HI (parity:QI (reg:QI 24))))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*parityqihi2.libgcc"
[(set (reg:HI 24)
@@ -9271,9 +8869,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:HI 24)
- (truncate:HI (parity:SI (reg:SI 22))))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*paritysihi2.libgcc"
[(set (reg:HI 24)
@@ -9329,9 +8926,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:HI 24)
- (popcount:HI (reg:HI 24)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*popcounthi2.libgcc"
[(set (reg:HI 24)
@@ -9347,9 +8943,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:HI 24)
- (truncate:HI (popcount:SI (reg:SI 22))))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*popcountsi2.libgcc"
[(set (reg:HI 24)
@@ -9365,9 +8960,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:QI 24)
- (popcount:QI (reg:QI 24)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*popcountqi2.libgcc"
[(set (reg:QI 24)
@@ -9421,10 +9015,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:HI 24)
- (clz:HI (reg:HI 24)))
- (clobber (reg:QI 26))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*clzhi2.libgcc"
[(set (reg:HI 24)
@@ -9442,10 +9034,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:HI 24)
- (truncate:HI (clz:SI (reg:SI 22))))
- (clobber (reg:QI 26))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*clzsihi2.libgcc"
[(set (reg:HI 24)
@@ -9490,10 +9080,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:HI 24)
- (ctz:HI (reg:HI 24)))
- (clobber (reg:QI 26))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*ctzhi2.libgcc"
[(set (reg:HI 24)
@@ -9512,11 +9100,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:HI 24)
- (truncate:HI (ctz:SI (reg:SI 22))))
- (clobber (reg:QI 22))
- (clobber (reg:QI 26))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*ctzsihi2.libgcc"
[(set (reg:HI 24)
@@ -9562,10 +9147,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:HI 24)
- (ffs:HI (reg:HI 24)))
- (clobber (reg:QI 26))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*ffshi2.libgcc"
[(set (reg:HI 24)
@@ -9584,11 +9167,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:HI 24)
- (truncate:HI (ffs:SI (reg:SI 22))))
- (clobber (reg:QI 22))
- (clobber (reg:QI 26))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*ffssihi2.libgcc"
[(set (reg:HI 24)
@@ -9633,9 +9213,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (reg:SI 22)
- (bswap:SI (reg:SI 22)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*bswapsi2.libgcc"
[(set (reg:SI 22)
@@ -9742,11 +9321,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (unspec:HI [(match_dup 1)
- (match_dup 2)]
- UNSPEC_FMUL))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*fmul_insn"
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -9768,11 +9344,8 @@
"!AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (reg:HI 22)
- (unspec:HI [(reg:QI 24)
- (reg:QI 25)] UNSPEC_FMUL))
- (clobber (reg:HI 24))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*fmul.call"
[(set (reg:HI 22)
@@ -9814,11 +9387,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (unspec:HI [(match_dup 1)
- (match_dup 2)]
- UNSPEC_FMULS))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*fmuls_insn"
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -9840,11 +9410,8 @@
"!AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (reg:HI 22)
- (unspec:HI [(reg:QI 24)
- (reg:QI 25)] UNSPEC_FMULS))
- (clobber (reg:HI 24))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*fmuls.call"
[(set (reg:HI 22)
@@ -9886,11 +9453,8 @@
"AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (unspec:HI [(match_dup 1)
- (match_dup 2)]
- UNSPEC_FMULSU))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*fmulsu_insn"
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -9912,11 +9476,8 @@
"!AVR_HAVE_MUL"
"#"
"&& reload_completed"
- [(parallel [(set (reg:HI 22)
- (unspec:HI [(reg:QI 24)
- (reg:QI 25)] UNSPEC_FMULSU))
- (clobber (reg:HI 24))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*fmulsu.call"
[(set (reg:HI 22)
@@ -10037,11 +9598,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (zero_extract:QI (match_dup 0)
- (const_int 1)
- (match_dup 1))
- (match_dup 2))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*insv.reg"
[(set (zero_extract:QI (match_operand:QI 0 "register_operand" "+r,d,d,l,l")
@@ -10478,11 +10036,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (zero_extract:QI (not:QI (match_dup 1))
- (const_int 1)
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*extzv.not"
[(set (match_operand:QI 0 "register_operand" "=r")
@@ -10619,11 +10174,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (and:QISI (any_shift:QISI (match_dup 1)
- (match_dup 2))
- (match_dup 3)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*insv.any_shift.<mode>"
[(set (match_operand:QISI 0 "register_operand" "=r")
@@ -10686,11 +10238,8 @@
""
"#"
"&& reload_completed"
- [(parallel [(set (match_dup 0)
- (sign_extract:QISI (match_dup 1)
- (const_int 1)
- (match_dup 2)))
- (clobber (reg:CC REG_CC))])])
+ [(scratch)]
+ { DONE_ADD_CCC })
(define_insn "*sextr.<QISI:mode>.<QISI2:mode>"
[(set (match_operand:QISI 0 "register_operand" "=r")
diff --git a/gcc/config/avr/avr.opt b/gcc/config/avr/avr.opt
index 7f6f18c..2bed8ea 100644
--- a/gcc/config/avr/avr.opt
+++ b/gcc/config/avr/avr.opt
@@ -18,10 +18,6 @@
; along with GCC; see the file COPYING3. If not see
; <http://www.gnu.org/licenses/>.
-mlra
-Target Var(avropt_lra_p) UInteger Init(1) Optimization Undocumented
-Usa LRA for reload instead of the old reload framework. This option is experimental, on per default, and it may be removed in future versions of the compiler.
-
mcall-prologues
Target Mask(CALL_PROLOGUES) Optimization
Optimization. Use subroutines for function prologues and epilogues.
diff --git a/gcc/config/avr/avr.opt.urls b/gcc/config/avr/avr.opt.urls
index 87c26b2..fa560bc 100644
--- a/gcc/config/avr/avr.opt.urls
+++ b/gcc/config/avr/avr.opt.urls
@@ -1,7 +1,5 @@
; Autogenerated by regenerate-opt-urls.py from gcc/config/avr/avr.opt and generated HTML
-; skipping UrlSuffix for 'mlra' due to finding no URLs
-
mcall-prologues
UrlSuffix(gcc/AVR-Options.html#index-mcall-prologues)
diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
index 09aa9b1..12cec61 100644
--- a/gcc/config/i386/i386-expand.cc
+++ b/gcc/config/i386/i386-expand.cc
@@ -9574,8 +9574,9 @@ ix86_expand_set_or_cpymem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
case vector_loop:
need_zero_guard = true;
unroll_factor = 4;
- /* Get the vector mode to move MOVE_MAX bytes. */
- nunits = MOVE_MAX / GET_MODE_SIZE (word_mode);
+ /* Get the vector mode to move STORE_MAX_PIECES/MOVE_MAX bytes. */
+ nunits = issetmem ? STORE_MAX_PIECES : MOVE_MAX;
+ nunits /= GET_MODE_SIZE (word_mode);
if (nunits > 1)
{
move_mode = mode_for_vector (word_mode, nunits).require ();
diff --git a/gcc/config/i386/i386-features.cc b/gcc/config/i386/i386-features.cc
index 53e86c8..9941e61 100644
--- a/gcc/config/i386/i386-features.cc
+++ b/gcc/config/i386/i386-features.cc
@@ -3085,21 +3085,63 @@ ix86_rpad_gate ()
&& optimize_function_for_speed_p (cfun));
}
+enum x86_cse_kind
+{
+ X86_CSE_CONST0_VECTOR,
+ X86_CSE_CONSTM1_VECTOR,
+ X86_CSE_VEC_DUP
+};
+
+struct redundant_load
+{
+ /* Bitmap of basic blocks with broadcast instructions. */
+ auto_bitmap bbs;
+ /* Bitmap of broadcast instructions. */
+ auto_bitmap insns;
+ /* The broadcast inner scalar. */
+ rtx val;
+ /* The inner scalar mode. */
+ machine_mode mode;
+ /* The instruction which sets the inner scalar. Nullptr if the inner
+ scalar is applied to the whole function, instead of within the same
+ block. */
+ rtx_insn *def_insn;
+ /* The widest broadcast source. */
+ rtx broadcast_source;
+ /* The widest broadcast register. */
+ rtx broadcast_reg;
+ /* The basic block of the broadcast instruction. */
+ basic_block bb;
+ /* The number of broadcast instructions with the same inner scalar. */
+ unsigned HOST_WIDE_INT count;
+ /* The threshold of broadcast instructions with the same inner
+ scalar. */
+ unsigned int threshold;
+ /* The widest broadcast size in bytes. */
+ unsigned int size;
+ /* Load kind. */
+ x86_cse_kind kind;
+};
+
/* Generate a vector set, DEST = SRC, at entry of the nearest dominator
for basic block map BBS, which is in the fake loop that contains the
whole function, so that there is only a single vector set in the
- whole function. If not nullptr, INNER_SCALAR is the inner scalar of
- SRC, as (reg:SI 99) in (vec_duplicate:V4SI (reg:SI 99)). */
+ whole function. If not nullptr, LOAD is a pointer to the load. */
static void
ix86_place_single_vector_set (rtx dest, rtx src, bitmap bbs,
- rtx inner_scalar = nullptr)
+ redundant_load *load = nullptr)
{
basic_block bb = nearest_common_dominator_for_set (CDI_DOMINATORS, bbs);
- while (bb->loop_father->latch
- != EXIT_BLOCK_PTR_FOR_FN (cfun))
- bb = get_immediate_dominator (CDI_DOMINATORS,
- bb->loop_father->header);
+ /* For X86_CSE_VEC_DUP, don't place the vector set outside of the loop
+ to avoid extra spills. */
+ if (!load || load->kind != X86_CSE_VEC_DUP)
+ {
+ while (bb->loop_father->latch
+ != EXIT_BLOCK_PTR_FOR_FN (cfun))
+ bb = get_immediate_dominator (CDI_DOMINATORS,
+ bb->loop_father->header);
+ }
rtx set = gen_rtx_SET (dest, src);
@@ -3141,8 +3183,14 @@ ix86_place_single_vector_set (rtx dest, rtx src, bitmap bbs,
}
}
- if (inner_scalar)
+ if (load && load->kind == X86_CSE_VEC_DUP)
{
+ /* Get the source from LOAD as (reg:SI 99) in
+
+ (vec_duplicate:V4SI (reg:SI 99))
+
+ */
+ rtx inner_scalar = load->val;
/* Set the source in (vec_duplicate:V4SI (reg:SI 99)). */
rtx reg = XEXP (src, 0);
if ((REG_P (inner_scalar) || MEM_P (inner_scalar))
@@ -3489,44 +3537,6 @@ replace_vector_const (machine_mode vector_mode, rtx vector_const,
}
}
-enum x86_cse_kind
-{
- X86_CSE_CONST0_VECTOR,
- X86_CSE_CONSTM1_VECTOR,
- X86_CSE_VEC_DUP
-};
-
-struct redundant_load
-{
- /* Bitmap of basic blocks with broadcast instructions. */
- auto_bitmap bbs;
- /* Bitmap of broadcast instructions. */
- auto_bitmap insns;
- /* The broadcast inner scalar. */
- rtx val;
- /* The inner scalar mode. */
- machine_mode mode;
- /* The instruction which sets the inner scalar. Nullptr if the inner
- scalar is applied to the whole function, instead of within the same
- block. */
- rtx_insn *def_insn;
- /* The widest broadcast source. */
- rtx broadcast_source;
- /* The widest broadcast register. */
- rtx broadcast_reg;
- /* The basic block of the broadcast instruction. */
- basic_block bb;
- /* The number of broadcast instructions with the same inner scalar. */
- unsigned HOST_WIDE_INT count;
- /* The threshold of broadcast instructions with the same inner
- scalar. */
- unsigned int threshold;
- /* The widest broadcast size in bytes. */
- unsigned int size;
- /* Load kind. */
- x86_cse_kind kind;
-};
-
/* Return the inner scalar if OP is a broadcast, else return nullptr. */
static rtx
@@ -3872,10 +3882,7 @@ remove_redundant_vector_load (void)
else
ix86_place_single_vector_set (load->broadcast_reg,
load->broadcast_source,
- load->bbs,
- (load->kind == X86_CSE_VEC_DUP
- ? load->val
- : nullptr));
+ load->bbs, load);
}
loop_optimizer_finalize ();
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index a50475b..2b0dd66 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -1618,10 +1618,8 @@
(compare
(match_operand:QI 0 "nonimmediate_operand" "QBn")
(subreg:QI
- (match_operator:SWI248 2 "extract_operator"
- [(match_operand 1 "int248_register_operand" "Q")
- (const_int 8)
- (const_int 8)]) 0)))]
+ (match_operator:SWI248 2 "extract_high_operator"
+ [(match_operand 1 "int248_register_operand" "Q")]) 0)))]
"ix86_match_ccmode (insn, CCmode)"
"cmp{b}\t{%h1, %0|%0, %h1}"
[(set_attr "addr" "gpr8")
@@ -1632,10 +1630,8 @@
[(set (reg FLAGS_REG)
(compare
(subreg:QI
- (match_operator:SWI248 2 "extract_operator"
- [(match_operand 0 "int248_register_operand" "Q")
- (const_int 8)
- (const_int 8)]) 0)
+ (match_operator:SWI248 2 "extract_high_operator"
+ [(match_operand 0 "int248_register_operand" "Q")]) 0)
(match_operand:QI 1 "const0_operand")))]
"ix86_match_ccmode (insn, CCNOmode)"
"test{b}\t%h0, %h0"
@@ -1657,10 +1653,8 @@
[(set (reg FLAGS_REG)
(compare
(subreg:QI
- (match_operator:SWI248 2 "extract_operator"
- [(match_operand 0 "int248_register_operand" "Q")
- (const_int 8)
- (const_int 8)]) 0)
+ (match_operator:SWI248 2 "extract_high_operator"
+ [(match_operand 0 "int248_register_operand" "Q")]) 0)
(match_operand:QI 1 "general_operand" "QnBn")))]
"ix86_match_ccmode (insn, CCmode)"
"cmp{b}\t{%1, %h0|%h0, %1}"
@@ -1672,15 +1666,11 @@
[(set (reg FLAGS_REG)
(compare
(subreg:QI
- (match_operator:SWI248 2 "extract_operator"
- [(match_operand 0 "int248_register_operand" "Q")
- (const_int 8)
- (const_int 8)]) 0)
+ (match_operator:SWI248 2 "extract_high_operator"
+ [(match_operand 0 "int248_register_operand" "Q")]) 0)
(subreg:QI
- (match_operator:SWI248 3 "extract_operator"
- [(match_operand 1 "int248_register_operand" "Q")
- (const_int 8)
- (const_int 8)]) 0)))]
+ (match_operator:SWI248 3 "extract_high_operator"
+ [(match_operand 1 "int248_register_operand" "Q")]) 0)))]
"ix86_match_ccmode (insn, CCmode)"
"cmp{b}\t{%h1, %h0|%h0, %h1}"
[(set_attr "type" "icmp")
@@ -3480,10 +3470,8 @@
[(set (strict_low_part
(match_operand:QI 0 "register_operand" "+Q"))
(subreg:QI
- (match_operator:SWI248 2 "extract_operator"
- [(match_operand 1 "int248_register_operand" "Q")
- (const_int 8)
- (const_int 8)]) 0))]
+ (match_operator:SWI248 2 "extract_high_operator"
+ [(match_operand 1 "int248_register_operand" "Q")]) 0))]
"!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
"mov{b}\t{%h1, %0|%0, %h1}"
[(set_attr "type" "imov")
@@ -3566,10 +3554,8 @@
(define_insn "*extzvqi"
[(set (match_operand:QI 0 "nonimmediate_operand" "=QBn,?R")
(subreg:QI
- (match_operator:SWI248 2 "extract_operator"
- [(match_operand 1 "int248_register_operand" "Q,Q")
- (const_int 8)
- (const_int 8)]) 0))]
+ (match_operator:SWI248 2 "extract_high_operator"
+ [(match_operand 1 "int248_register_operand" "Q,Q")]) 0))]
""
{
switch (get_attr_type (insn))
@@ -3690,10 +3676,8 @@
(match_operand 0 "int248_register_operand" "+Q")
(const_int 8)
(const_int 8))
- (match_operator:SWI248 2 "extract_operator"
- [(match_operand 1 "int248_register_operand" "Q")
- (const_int 8)
- (const_int 8)]))]
+ (match_operator:SWI248 2 "extract_high_operator"
+ [(match_operand 1 "int248_register_operand" "Q")]))]
""
"mov{b}\t{%h1, %h0|%h0, %h1}"
[(set_attr "type" "imov")
@@ -5260,10 +5244,8 @@
[(set (match_operand:SWI24 0 "register_operand" "=R")
(sign_extend:SWI24
(subreg:QI
- (match_operator:SWI248 2 "extract_operator"
- [(match_operand 1 "int248_register_operand" "Q")
- (const_int 8)
- (const_int 8)]) 0)))]
+ (match_operator:SWI248 2 "extract_high_operator"
+ [(match_operand 1 "int248_register_operand" "Q")]) 0)))]
""
"movs{b<SWI24:imodesuffix>|x}\t{%h1, %0|%0, %h1}"
[(set_attr "type" "imovx")
@@ -7009,10 +6991,8 @@
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+Q,&Q"))
(plus:QI
(subreg:QI
- (match_operator:SWI248 3 "extract_operator"
- [(match_operand 2 "int248_register_operand" "Q,Q")
- (const_int 8)
- (const_int 8)]) 0)
+ (match_operator:SWI248 3 "extract_high_operator"
+ [(match_operand 2 "int248_register_operand" "Q,Q")]) 0)
(match_operand:QI 1 "nonimmediate_operand" "0,!qm")))
(clobber (reg:CC FLAGS_REG))]
"!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
@@ -7026,8 +7006,8 @@
[(set (strict_low_part (match_dup 0))
(plus:QI
(subreg:QI
- (match_op_dup 3
- [(match_dup 2) (const_int 8) (const_int 8)]) 0)
+ (zero_extract:SWI248
+ (match_dup 2) (const_int 8) (const_int 8)) 0)
(match_dup 0)))
(clobber (reg:CC FLAGS_REG))])]
""
@@ -7038,29 +7018,25 @@
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+&Q"))
(plus:QI
(subreg:QI
- (match_operator:SWI248 3 "extract_operator"
- [(match_operand 1 "int248_register_operand" "Q")
- (const_int 8)
- (const_int 8)]) 0)
+ (match_operator:SWI248 3 "extract_high_operator"
+ [(match_operand 1 "int248_register_operand" "Q")]) 0)
(subreg:QI
- (match_operator:SWI248 4 "extract_operator"
- [(match_operand 2 "int248_register_operand" "Q")
- (const_int 8)
- (const_int 8)]) 0)))
+ (match_operator:SWI248 4 "extract_high_operator"
+ [(match_operand 2 "int248_register_operand" "Q")]) 0)))
(clobber (reg:CC FLAGS_REG))]
"!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
"#"
"&& reload_completed"
[(set (strict_low_part (match_dup 0))
(subreg:QI
- (match_op_dup 4
- [(match_dup 2) (const_int 8) (const_int 8)]) 0))
+ (zero_extract:SWI248
+ (match_dup 2) (const_int 8) (const_int 8)) 0))
(parallel
[(set (strict_low_part (match_dup 0))
(plus:QI
(subreg:QI
- (match_op_dup 3
- [(match_dup 1) (const_int 8) (const_int 8)]) 0)
+ (zero_extract:SWI248
+ (match_dup 1) (const_int 8) (const_int 8)) 0)
(match_dup 0)))
(clobber (reg:CC FLAGS_REG))])]
""
@@ -7475,10 +7451,8 @@
[(set (match_operand:QI 0 "nonimmediate_operand" "=QBn")
(plus:QI
(subreg:QI
- (match_operator:SWI248 3 "extract_operator"
- [(match_operand 2 "int248_register_operand" "Q")
- (const_int 8)
- (const_int 8)]) 0)
+ (match_operator:SWI248 3 "extract_high_operator"
+ [(match_operand 2 "int248_register_operand" "Q")]) 0)
(match_operand:QI 1 "nonimmediate_operand" "0")))
(clobber (reg:CC FLAGS_REG))]
""
@@ -7491,29 +7465,25 @@
[(set (match_operand:QI 0 "register_operand" "=&Q")
(plus:QI
(subreg:QI
- (match_operator:SWI248 3 "extract_operator"
- [(match_operand 1 "int248_register_operand" "Q")
- (const_int 8)
- (const_int 8)]) 0)
+ (match_operator:SWI248 3 "extract_high_operator"
+ [(match_operand 1 "int248_register_operand" "Q")]) 0)
(subreg:QI
- (match_operator:SWI248 4 "extract_operator"
- [(match_operand 2 "int248_register_operand" "Q")
- (const_int 8)
- (const_int 8)]) 0)))
+ (match_operator:SWI248 4 "extract_high_operator"
+ [(match_operand 2 "int248_register_operand" "Q")]) 0)))
(clobber (reg:CC FLAGS_REG))]
""
"#"
"&& reload_completed"
[(set (match_dup 0)
(subreg:QI
- (match_op_dup 4
- [(match_dup 2) (const_int 8) (const_int 8)]) 0))
+ (zero_extract:SWI248
+ (match_dup 2) (const_int 8) (const_int 8)) 0))
(parallel
[(set (match_dup 0)
(plus:QI
(subreg:QI
- (match_op_dup 3
- [(match_dup 1) (const_int 8) (const_int 8)]) 0)
+ (zero_extract:SWI248
+ (match_dup 1) (const_int 8) (const_int 8)) 0)
(match_dup 0)))
(clobber (reg:CC FLAGS_REG))])]
""
@@ -7543,10 +7513,8 @@
(subreg:SWI248
(plus:QI
(subreg:QI
- (match_operator:SWI248 3 "extract_operator"
- [(match_operand 1 "int248_register_operand" "0,!Q")
- (const_int 8)
- (const_int 8)]) 0)
+ (match_operator:SWI248 3 "extract_high_operator"
+ [(match_operand 1 "int248_register_operand" "0,!Q")]) 0)
(match_operand:QI 2 "general_operand" "QnBn,QnBn")) 0))
(clobber (reg:CC FLAGS_REG))]
""
@@ -7581,8 +7549,8 @@
(subreg:SWI248
(plus:QI
(subreg:QI
- (match_op_dup 3
- [(match_dup 0) (const_int 8) (const_int 8)]) 0)
+ (zero_extract:SWI248
+ (match_dup 0) (const_int 8) (const_int 8)) 0)
(match_dup 2)) 0))
(clobber (reg:CC FLAGS_REG))])]
""
@@ -7602,15 +7570,11 @@
(subreg:SWI248
(plusminus:QI
(subreg:QI
- (match_operator:SWI248 3 "extract_operator"
- [(match_operand 1 "int248_register_operand" "<comm>0,!Q")
- (const_int 8)
- (const_int 8)]) 0)
+ (match_operator:SWI248 3 "extract_high_operator"
+ [(match_operand 1 "int248_register_operand" "<comm>0,!Q")]) 0)
(subreg:QI
- (match_operator:SWI248 4 "extract_operator"
- [(match_operand 2 "int248_register_operand" "Q,Q")
- (const_int 8)
- (const_int 8)]) 0)) 0))
+ (match_operator:SWI248 4 "extract_high_operator"
+ [(match_operand 2 "int248_register_operand" "Q,Q")]) 0)) 0))
(clobber (reg:CC FLAGS_REG))]
""
"@
@@ -7629,11 +7593,11 @@
(subreg:SWI248
(plusminus:QI
(subreg:QI
- (match_op_dup 3
- [(match_dup 0) (const_int 8) (const_int 8)]) 0)
+ (zero_extract:SWI248
+ (match_dup 0) (const_int 8) (const_int 8)) 0)
(subreg:QI
- (match_op_dup 4
- [(match_dup 2) (const_int 8) (const_int 8)]) 0)) 0))
+ (zero_extract:SWI248
+ (match_dup 2) (const_int 8) (const_int 8)) 0)) 0))
(clobber (reg:CC FLAGS_REG))])]
""
[(set_attr "type" "alu")
@@ -8230,10 +8194,8 @@
(minus:QI
(match_operand:QI 1 "nonimmediate_operand" "0,!qm")
(subreg:QI
- (match_operator:SWI248 3 "extract_operator"
- [(match_operand 2 "int248_register_operand" "Q,Q")
- (const_int 8)
- (const_int 8)]) 0)))
+ (match_operator:SWI248 3 "extract_high_operator"
+ [(match_operand 2 "int248_register_operand" "Q,Q")]) 0)))
(clobber (reg:CC FLAGS_REG))]
"!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
"@
@@ -8247,8 +8209,8 @@
(minus:QI
(match_dup 0)
(subreg:QI
- (match_op_dup 3
- [(match_dup 2) (const_int 8) (const_int 8)]) 0)))
+ (zero_extract:SWI248
+ (match_dup 2) (const_int 8) (const_int 8)) 0)))
(clobber (reg:CC FLAGS_REG))])]
""
[(set_attr "type" "alu")
@@ -8258,30 +8220,26 @@
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+&Q"))
(minus:QI
(subreg:QI
- (match_operator:SWI248 3 "extract_operator"
- [(match_operand 1 "int248_register_operand" "Q")
- (const_int 8)
- (const_int 8)]) 0)
+ (match_operator:SWI248 3 "extract_high_operator"
+ [(match_operand 1 "int248_register_operand" "Q")]) 0)
(subreg:QI
- (match_operator:SWI248 4 "extract_operator"
- [(match_operand 2 "int248_register_operand" "Q")
- (const_int 8)
- (const_int 8)]) 0)))
+ (match_operator:SWI248 4 "extract_high_operator"
+ [(match_operand 2 "int248_register_operand" "Q")]) 0)))
(clobber (reg:CC FLAGS_REG))]
"!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
"#"
"&& reload_completed"
[(set (strict_low_part (match_dup 0))
(subreg:QI
- (match_op_dup 3
- [(match_dup 1) (const_int 8) (const_int 8)]) 0))
+ (zero_extract:SWI248
+ (match_dup 1) (const_int 8) (const_int 8)) 0))
(parallel
[(set (strict_low_part (match_dup 0))
(minus:QI
(match_dup 0)
(subreg:QI
- (match_op_dup 4
- [(match_dup 2) (const_int 8) (const_int 8)]) 0)))
+ (zero_extract:SWI248
+ (match_dup 2) (const_int 8) (const_int 8)) 0)))
(clobber (reg:CC FLAGS_REG))])]
""
[(set_attr "type" "alu")
@@ -8332,10 +8290,8 @@
(minus:QI
(match_operand:QI 1 "nonimmediate_operand" "0")
(subreg:QI
- (match_operator:SWI248 3 "extract_operator"
- [(match_operand 2 "int248_register_operand" "Q")
- (const_int 8)
- (const_int 8)]) 0)))
+ (match_operator:SWI248 3 "extract_high_operator"
+ [(match_operand 2 "int248_register_operand" "Q")]) 0)))
(clobber (reg:CC FLAGS_REG))]
""
"sub{b}\t{%h2, %0|%0, %h2}"
@@ -8347,30 +8303,26 @@
[(set (match_operand:QI 0 "register_operand" "=&Q")
(minus:QI
(subreg:QI
- (match_operator:SWI248 3 "extract_operator"
- [(match_operand 1 "int248_register_operand" "Q")
- (const_int 8)
- (const_int 8)]) 0)
+ (match_operator:SWI248 3 "extract_high_operator"
+ [(match_operand 1 "int248_register_operand" "Q")]) 0)
(subreg:QI
- (match_operator:SWI248 4 "extract_operator"
- [(match_operand 2 "int248_register_operand" "Q")
- (const_int 8)
- (const_int 8)]) 0)))
+ (match_operator:SWI248 4 "extract_high_operator"
+ [(match_operand 2 "int248_register_operand" "Q")]) 0)))
(clobber (reg:CC FLAGS_REG))]
""
"#"
"&& reload_completed"
[(set (match_dup 0)
(subreg:QI
- (match_op_dup 3
- [(match_dup 1) (const_int 8) (const_int 8)]) 0))
+ (zero_extract:SWI248
+ (match_dup 1) (const_int 8) (const_int 8)) 0))
(parallel
[(set (match_dup 0)
(minus:QI
(match_dup 0)
(subreg:QI
- (match_op_dup 4
- [(match_dup 2) (const_int 8) (const_int 8)]) 0)))
+ (zero_extract:SWI248
+ (match_dup 2) (const_int 8) (const_int 8)) 0)))
(clobber (reg:CC FLAGS_REG))])]
""
[(set_attr "type" "alu")
@@ -8385,10 +8337,8 @@
(subreg:SWI248
(minus:QI
(subreg:QI
- (match_operator:SWI248 3 "extract_operator"
- [(match_operand 1 "int248_register_operand" "0,!Q")
- (const_int 8)
- (const_int 8)]) 0)
+ (match_operator:SWI248 3 "extract_high_operator"
+ [(match_operand 1 "int248_register_operand" "0,!Q")]) 0)
(match_operand:QI 2 "general_operand" "QnBn,QnBn")) 0))
(clobber (reg:CC FLAGS_REG))]
""
@@ -8407,8 +8357,8 @@
(subreg:SWI248
(minus:QI
(subreg:QI
- (match_op_dup 3
- [(match_dup 0) (const_int 8) (const_int 8)]) 0)
+ (zero_extract:SWI248
+ (match_dup 0) (const_int 8) (const_int 8)) 0)
(match_dup 2)) 0))
(clobber (reg:CC FLAGS_REG))])]
""
@@ -12356,10 +12306,8 @@
(compare
(and:QI
(subreg:QI
- (match_operator:SWI248 2 "extract_operator"
- [(match_operand 0 "int248_register_operand" "Q")
- (const_int 8)
- (const_int 8)]) 0)
+ (match_operator:SWI248 2 "extract_high_operator"
+ [(match_operand 0 "int248_register_operand" "Q")]) 0)
(match_operand:QI 1 "general_operand" "QnBn"))
(const_int 0)))]
"ix86_match_ccmode (insn, CCNOmode)"
@@ -12373,15 +12321,11 @@
(compare
(and:QI
(subreg:QI
- (match_operator:SWI248 2 "extract_operator"
- [(match_operand 0 "int248_register_operand" "Q")
- (const_int 8)
- (const_int 8)]) 0)
+ (match_operator:SWI248 2 "extract_high_operator"
+ [(match_operand 0 "int248_register_operand" "Q")]) 0)
(subreg:QI
- (match_operator:SWI248 3 "extract_operator"
- [(match_operand 1 "int248_register_operand" "Q")
- (const_int 8)
- (const_int 8)]) 0))
+ (match_operator:SWI248 3 "extract_high_operator"
+ [(match_operand 1 "int248_register_operand" "Q")]) 0))
(const_int 0)))]
"ix86_match_ccmode (insn, CCNOmode)"
"test{b}\t{%h1, %h0|%h0, %h1}"
@@ -12970,10 +12914,8 @@
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+Q,&Q"))
(any_logic:QI
(subreg:QI
- (match_operator:SWI248 3 "extract_operator"
- [(match_operand 2 "int248_register_operand" "Q,Q")
- (const_int 8)
- (const_int 8)]) 0)
+ (match_operator:SWI248 3 "extract_high_operator"
+ [(match_operand 2 "int248_register_operand" "Q,Q")]) 0)
(match_operand:QI 1 "nonimmediate_operand" "0,!qm")))
(clobber (reg:CC FLAGS_REG))]
"!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
@@ -12987,8 +12929,8 @@
[(set (strict_low_part (match_dup 0))
(any_logic:QI
(subreg:QI
- (match_op_dup 3
- [(match_dup 2) (const_int 8) (const_int 8)]) 0)
+ (zero_extract:SWI248
+ (match_dup 2) (const_int 8) (const_int 8)) 0)
(match_dup 0)))
(clobber (reg:CC FLAGS_REG))])]
""
@@ -12999,29 +12941,25 @@
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+&Q"))
(any_logic:QI
(subreg:QI
- (match_operator:SWI248 3 "extract_operator"
- [(match_operand 1 "int248_register_operand" "Q")
- (const_int 8)
- (const_int 8)]) 0)
+ (match_operator:SWI248 3 "extract_high_operator"
+ [(match_operand 1 "int248_register_operand" "Q")]) 0)
(subreg:QI
- (match_operator:SWI248 4 "extract_operator"
- [(match_operand 2 "int248_register_operand" "Q")
- (const_int 8)
- (const_int 8)]) 0)))
+ (match_operator:SWI248 4 "extract_high_operator"
+ [(match_operand 2 "int248_register_operand" "Q")]) 0)))
(clobber (reg:CC FLAGS_REG))]
"!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
"#"
"&& reload_completed"
[(set (strict_low_part (match_dup 0))
(subreg:QI
- (match_op_dup 4
- [(match_dup 2) (const_int 8) (const_int 8)]) 0))
+ (zero_extract:SWI248
+ (match_dup 2) (const_int 8) (const_int 8)) 0))
(parallel
[(set (strict_low_part (match_dup 0))
(any_logic:QI
(subreg:QI
- (match_op_dup 3
- [(match_dup 1) (const_int 8) (const_int 8)]) 0)
+ (zero_extract:SWI248
+ (match_dup 1) (const_int 8) (const_int 8)) 0)
(match_dup 0)))
(clobber (reg:CC FLAGS_REG))])]
""
@@ -13224,10 +13162,8 @@
[(set (match_operand:QI 0 "nonimmediate_operand" "=QBn")
(any_logic:QI
(subreg:QI
- (match_operator:SWI248 3 "extract_operator"
- [(match_operand 2 "int248_register_operand" "Q")
- (const_int 8)
- (const_int 8)]) 0)
+ (match_operator:SWI248 3 "extract_high_operator"
+ [(match_operand 2 "int248_register_operand" "Q")]) 0)
(match_operand:QI 1 "nonimmediate_operand" "0")))
(clobber (reg:CC FLAGS_REG))]
""
@@ -13240,29 +13176,25 @@
[(set (match_operand:QI 0 "register_operand" "=&Q")
(any_logic:QI
(subreg:QI
- (match_operator:SWI248 3 "extract_operator"
- [(match_operand 1 "int248_register_operand" "Q")
- (const_int 8)
- (const_int 8)]) 0)
+ (match_operator:SWI248 3 "extract_high_operator"
+ [(match_operand 1 "int248_register_operand" "Q")]) 0)
(subreg:QI
- (match_operator:SWI248 4 "extract_operator"
- [(match_operand 2 "int248_register_operand" "Q")
- (const_int 8)
- (const_int 8)]) 0)))
+ (match_operator:SWI248 4 "extract_high_operator"
+ [(match_operand 2 "int248_register_operand" "Q")]) 0)))
(clobber (reg:CC FLAGS_REG))]
""
"#"
"&& reload_completed"
[(set (match_dup 0)
(subreg:QI
- (match_op_dup 4
- [(match_dup 2) (const_int 8) (const_int 8)]) 0))
+ (zero_extract:SWI248
+ (match_dup 2) (const_int 8) (const_int 8)) 0))
(parallel
[(set (match_dup 0)
(any_logic:QI
(subreg:QI
- (match_op_dup 3
- [(match_dup 1) (const_int 8) (const_int 8)]) 0)
+ (zero_extract:SWI248
+ (match_dup 1) (const_int 8) (const_int 8)) 0)
(match_dup 0)))
(clobber (reg:CC FLAGS_REG))])]
""
@@ -13292,10 +13224,8 @@
(subreg:SWI248
(any_logic:QI
(subreg:QI
- (match_operator:SWI248 3 "extract_operator"
- [(match_operand 1 "int248_register_operand" "0,!Q")
- (const_int 8)
- (const_int 8)]) 0)
+ (match_operator:SWI248 3 "extract_high_operator"
+ [(match_operand 1 "int248_register_operand" "0,!Q")]) 0)
(match_operand:QI 2 "general_operand" "QnBn,QnBn")) 0))
(clobber (reg:CC FLAGS_REG))]
""
@@ -13314,8 +13244,8 @@
(subreg:SWI248
(any_logic:QI
(subreg:QI
- (match_op_dup 3
- [(match_dup 0) (const_int 8) (const_int 8)]) 0)
+ (zero_extract:SWI248
+ (match_dup 0) (const_int 8) (const_int 8)) 0)
(match_dup 2)) 0))
(clobber (reg:CC FLAGS_REG))])]
""
@@ -13329,10 +13259,8 @@
(match_operator 5 "compare_operator"
[(any_logic:QI
(subreg:QI
- (match_operator:SWI248 3 "extract_operator"
- [(match_operand 1 "int248_register_operand" "0,!Q")
- (const_int 8)
- (const_int 8)]) 0)
+ (match_operator:SWI248 3 "extract_high_operator"
+ [(match_operand 1 "int248_register_operand" "0,!Q")]) 0)
(match_operand:QI 2 "general_operand" "QnBn,QnBn"))
(const_int 0)]))
(set (zero_extract:SWI248
@@ -13342,8 +13270,8 @@
(subreg:SWI248
(any_logic:QI
(subreg:QI
- (match_op_dup 3
- [(match_dup 0) (const_int 8) (const_int 8)]) 0)
+ (zero_extract:SWI248
+ (match_dup 0) (const_int 8) (const_int 8)) 0)
(match_dup 2)) 0))]
"ix86_match_ccmode (insn, CCNOmode)"
"@
@@ -13359,9 +13287,9 @@
[(set (match_dup 4)
(match_op_dup 5
[(any_logic:QI
- (subreg:QI
- (match_op_dup 3
- [(match_dup 0) (const_int 8) (const_int 8)]) 0)
+ (subreg:QI
+ (zero_extract:SWI248
+ (match_dup 0) (const_int 8) (const_int 8)) 0)
(match_dup 2))
(const_int 0)]))
(set (zero_extract:SWI248
@@ -13369,8 +13297,8 @@
(subreg:SWI248
(any_logic:QI
(subreg:QI
- (match_op_dup 3
- [(match_dup 1) (const_int 8) (const_int 8)]) 0)
+ (zero_extract:SWI248
+ (match_dup 1) (const_int 8) (const_int 8)) 0)
(match_dup 2)) 0))])]
""
[(set_attr "addr" "gpr8")
@@ -13386,15 +13314,11 @@
(subreg:SWI248
(any_logic:QI
(subreg:QI
- (match_operator:SWI248 3 "extract_operator"
- [(match_operand 1 "int248_register_operand" "%0,!Q")
- (const_int 8)
- (const_int 8)]) 0)
+ (match_operator:SWI248 3 "extract_high_operator"
+ [(match_operand 1 "int248_register_operand" "%0,!Q")]) 0)
(subreg:QI
- (match_operator:SWI248 4 "extract_operator"
- [(match_operand 2 "int248_register_operand" "Q,Q")
- (const_int 8)
- (const_int 8)]) 0)) 0))
+ (match_operator:SWI248 4 "extract_high_operator"
+ [(match_operand 2 "int248_register_operand" "Q,Q")]) 0)) 0))
(clobber (reg:CC FLAGS_REG))]
""
"@
@@ -13413,11 +13337,11 @@
(subreg:SWI248
(any_logic:QI
(subreg:QI
- (match_op_dup 3
- [(match_dup 0) (const_int 8) (const_int 8)]) 0)
+ (zero_extract:SWI248
+ (match_dup 0) (const_int 8) (const_int 8)) 0)
(subreg:QI
- (match_op_dup 4
- [(match_dup 2) (const_int 8) (const_int 8)]) 0)) 0))
+ (zero_extract:SWI248
+ (match_dup 2) (const_int 8) (const_int 8)) 0)) 0))
(clobber (reg:CC FLAGS_REG))])]
""
[(set_attr "type" "alu")
@@ -13429,12 +13353,10 @@
(match_operand 0 "int248_register_operand" "+Q,&Q")
(const_int 8)
(const_int 8))
- (match_operator:SWI248 3 "extract_operator"
+ (match_operator:SWI248 3 "extract_high_operator"
[(any_logic
(match_operand 1 "int248_register_operand" "%0,!Q")
- (match_operand 2 "int248_register_operand" "Q,Q"))
- (const_int 8)
- (const_int 8)]))
+ (match_operand 2 "int248_register_operand" "Q,Q"))]))
(clobber (reg:CC FLAGS_REG))]
"GET_MODE (operands[1]) == GET_MODE (operands[2])"
"@
@@ -13450,9 +13372,9 @@
(parallel
[(set (zero_extract:SWI248
(match_dup 0) (const_int 8) (const_int 8))
- (match_op_dup 3
- [(any_logic (match_dup 4) (match_dup 2))
- (const_int 8) (const_int 8)]))
+ (zero_extract:SWI248
+ (any_logic (match_dup 4) (match_dup 2))
+ (const_int 8) (const_int 8)))
(clobber (reg:CC FLAGS_REG))])]
"operands[4] = gen_lowpart (GET_MODE (operands[1]), operands[0]);"
[(set_attr "type" "alu")
@@ -14697,10 +14619,8 @@
(subreg:SWI248
(neg:QI
(subreg:QI
- (match_operator:SWI248 2 "extract_operator"
- [(match_operand 1 "int248_register_operand" "0,!Q")
- (const_int 8)
- (const_int 8)]) 0)) 0))
+ (match_operator:SWI248 2 "extract_high_operator"
+ [(match_operand 1 "int248_register_operand" "0,!Q")]) 0)) 0))
(clobber (reg:CC FLAGS_REG))]
""
"@
@@ -14718,8 +14638,8 @@
(subreg:SWI248
(neg:QI
(subreg:QI
- (match_op_dup 2
- [(match_dup 0) (const_int 8) (const_int 8)]) 0)) 0))
+ (zero_extract:SWI248
+ (match_dup 0) (const_int 8) (const_int 8)) 0)) 0))
(clobber (reg:CC FLAGS_REG))])]
""
[(set_attr "type" "negnot")
@@ -15351,13 +15271,9 @@
(match_operand 0 "int248_register_operand" "+Q,&Q")
(const_int 8)
(const_int 8))
- (subreg:SWI248
- (not:QI
- (subreg:QI
- (match_operator:SWI248 2 "extract_operator"
- [(match_operand 1 "int248_register_operand" "0,!Q")
- (const_int 8)
- (const_int 8)]) 0)) 0))]
+ (not:SWI248
+ (match_operator:SWI248 2 "extract_high_operator"
+ [(match_operand 1 "int248_register_operand" "0,!Q")])))]
""
"@
not{b}\t%h0
@@ -15370,11 +15286,8 @@
(match_dup 1) (const_int 8) (const_int 8)))
(set (zero_extract:SWI248
(match_dup 0) (const_int 8) (const_int 8))
- (subreg:SWI248
- (not:QI
- (subreg:QI
- (match_op_dup 2
- [(match_dup 0) (const_int 8) (const_int 8)]) 0)) 0))]
+ (not:SWI248
+ (zero_extract:SWI248 (match_dup 0) (const_int 8) (const_int 8))))]
""
[(set_attr "type" "negnot")
(set_attr "mode" "QI")])
@@ -16721,10 +16634,8 @@
(subreg:SWI248
(ashift:QI
(subreg:QI
- (match_operator:SWI248 3 "extract_operator"
- [(match_operand 1 "int248_register_operand" "0,!Q")
- (const_int 8)
- (const_int 8)]) 0)
+ (match_operator:SWI248 3 "extract_high_operator"
+ [(match_operand 1 "int248_register_operand" "0,!Q")]) 0)
(match_operand:QI 2 "nonmemory_operand" "cI,cI")) 0))
(clobber (reg:CC FLAGS_REG))]
""
@@ -16758,8 +16669,8 @@
(subreg:SWI248
(ashift:QI
(subreg:QI
- (match_op_dup 3
- [(match_dup 0) (const_int 8) (const_int 8)]) 0)
+ (zero_extract:SWI248
+ (match_dup 0) (const_int 8) (const_int 8)) 0)
(match_dup 2)) 0))
(clobber (reg:CC FLAGS_REG))])]
""
@@ -18005,10 +17916,8 @@
(subreg:SWI248
(any_shiftrt:QI
(subreg:QI
- (match_operator:SWI248 3 "extract_operator"
- [(match_operand 1 "int248_register_operand" "0,!Q")
- (const_int 8)
- (const_int 8)]) 0)
+ (match_operator:SWI248 3 "extract_high_operator"
+ [(match_operand 1 "int248_register_operand" "0,!Q")]) 0)
(match_operand:QI 2 "nonmemory_operand" "cI,cI")) 0))
(clobber (reg:CC FLAGS_REG))]
""
@@ -18034,8 +17943,8 @@
(subreg:SWI248
(any_shiftrt:QI
(subreg:QI
- (match_op_dup 3
- [(match_dup 0) (const_int 8) (const_int 8)]) 0)
+ (zero_extract:SWI248
+ (match_dup 0) (const_int 8) (const_int 8)) 0)
(match_dup 2)) 0))
(clobber (reg:CC FLAGS_REG))])]
""
@@ -28252,10 +28161,8 @@
(match_operator 1 "compare_operator"
[(and:QI
(subreg:QI
- (match_operator:SWI248 4 "extract_operator"
- [(match_operand 2 "int248_register_operand")
- (const_int 8)
- (const_int 8)]) 0)
+ (match_operator:SWI248 4 "extract_high_operator"
+ [(match_operand 2 "int248_register_operand")]) 0)
(match_operand 3 "const_int_operand"))
(const_int 0)]))]
"! TARGET_PARTIAL_REG_STALL
@@ -28267,9 +28174,9 @@
(match_op_dup 1
[(and:QI
(subreg:QI
- (match_op_dup 4 [(match_dup 2)
- (const_int 8)
- (const_int 8)]) 0)
+ (zero_extract:SWI248 (match_dup 2)
+ (const_int 8)
+ (const_int 8)) 0)
(match_dup 3))
(const_int 0)]))
(set (zero_extract:SWI248 (match_dup 2)
@@ -28278,9 +28185,9 @@
(subreg:SWI248
(and:QI
(subreg:QI
- (match_op_dup 4 [(match_dup 2)
- (const_int 8)
- (const_int 8)]) 0)
+ (zero_extract:SWI248 (match_dup 2)
+ (const_int 8)
+ (const_int 8)) 0)
(match_dup 3)) 0))])])
;; Don't do logical operations with memory inputs.
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index b2d2eec..0f31090 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -1740,8 +1740,12 @@
(define_predicate "compare_operator"
(match_code "compare"))
-(define_predicate "extract_operator"
- (match_code "zero_extract,sign_extract"))
+(define_predicate "extract_high_operator"
+ (match_code "zero_extract,sign_extract,ashiftrt,lshiftrt")
+{
+ return (const8_operand (XEXP (op, 1), VOIDmode)
+ && (BINARY_P (op) || const8_operand (XEXP (op, 2), VOIDmode)));
+})
;; Return true if OP is a memory operand, aligned to
;; less than its natural alignment.
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 0a9fcef..e0d8904 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -13867,9 +13867,9 @@ riscv_expand_xmode_usmul (rtx dest, rtx x, rtx y)
riscv_emit_binary (MULT, mul, x, y);
if (TARGET_64BIT)
- emit_insn (gen_usmuldi3_highpart (mulhu, x, y));
+ emit_insn (gen_umuldi3_highpart (mulhu, x, y));
else
- emit_insn (gen_usmulsi3_highpart (mulhu, x, y));
+ emit_insn (gen_umulsi3_highpart (mulhu, x, y));
riscv_emit_binary (NE, overflow_p, mulhu, CONST0_RTX (Xmode));
riscv_emit_unary (NEG, overflow_p, overflow_p);
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3f76afd..cb4ff09 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,26 @@
+2025-08-05 Jason Merrill <jason@redhat.com>
+
+ PR c++/121068
+ * constexpr.cc (cxx_eval_store_expression): Handle clobbers.
+ (potential_constant_expression_1): Handle clobbers more.
+ * decl.cc (build_clobber_this): Use INIT_EXPR for initial clobber.
+ * init.cc (build_new_1): Clobber on placement new.
+ (build_vec_init): Don't clean up after clobber.
+
+2025-08-04 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/121351
+ PR c++/119859
+ * class.cc (add_method): Substitute outer template arguments
+ into constraints before comparing them if the declarations are
+ from different classes.
+
+2025-08-04 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/120620
+ * constexpr.cc (cxx_dynamic_cast_fn_p): Return true only
+ for synthesized __dynamic_cast.
+
2025-08-01 Nathaniel Shead <nathanieloshead@gmail.com>
PR c++/108080
diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
index f5d20e5..14acb9c 100644
--- a/gcc/cp/class.cc
+++ b/gcc/cp/class.cc
@@ -1356,7 +1356,30 @@ add_method (tree type, tree method, bool via_using)
if (!compparms (parms1, parms2))
continue;
- if (!equivalently_constrained (fn, method))
+ tree fn_constraints = get_constraints (fn);
+ tree method_constraints = get_constraints (method);
+
+ if (fn_constraints && method_constraints
+ && DECL_CONTEXT (fn) != type
+ && !processing_template_decl)
+ {
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ ++processing_template_decl;
+ if (tree ti = CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (fn)))
+ fn_constraints = tsubst_constraint_info (fn_constraints,
+ TI_ARGS (ti),
+ tf_warning_or_error,
+ fn);
+ if (tree ti = CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (method)))
+ method_constraints = tsubst_constraint_info (method_constraints,
+ TI_ARGS (ti),
+ tf_warning_or_error,
+ method);
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ --processing_template_decl;
+ }
+
+ if (!equivalent_constraints (fn_constraints, method_constraints))
{
if (processing_template_decl)
/* We can't check satisfaction in dependent context, wait until
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index be24ae2..65b91ec 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -3240,7 +3240,11 @@ cxx_dynamic_cast_fn_p (tree fndecl)
{
return (cxx_dialect >= cxx20
&& id_equal (DECL_NAME (fndecl), "__dynamic_cast")
- && CP_DECL_CONTEXT (fndecl) == abi_node);
+ && CP_DECL_CONTEXT (fndecl) == abi_node
+ /* Only consider implementation-detail __dynamic_cast calls that
+ correspond to a dynamic_cast, and ignore direct calls to
+ abi::__dynamic_cast. */
+ && DECL_ARTIFICIAL (fndecl));
}
/* Often, we have an expression in the form of address + offset, e.g.
@@ -7448,12 +7452,6 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
tree init = TREE_OPERAND (t, 1);
- if (TREE_CLOBBER_P (init)
- && CLOBBER_KIND (init) < CLOBBER_OBJECT_END)
- /* Only handle clobbers ending the lifetime of objects.
- ??? We should probably set CONSTRUCTOR_NO_CLEARING. */
- return void_node;
-
/* First we figure out where we're storing to. */
tree target = TREE_OPERAND (t, 0);
@@ -7640,11 +7638,14 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
}
/* Handle explicit end-of-lifetime. */
- if (TREE_CLOBBER_P (init))
+ if (TREE_CLOBBER_P (init)
+ && CLOBBER_KIND (init) >= CLOBBER_OBJECT_END)
{
if (refs->is_empty ())
- ctx->global->destroy_value (object);
- return void_node;
+ {
+ ctx->global->destroy_value (object);
+ return void_node;
+ }
}
type = TREE_TYPE (object);
@@ -7781,6 +7782,8 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
*non_constant_p = true;
}
else if (!is_access_expr
+ || (TREE_CLOBBER_P (init)
+ && CLOBBER_KIND (init) >= CLOBBER_OBJECT_END)
|| (TREE_CODE (t) == MODIFY_EXPR
&& CLASS_TYPE_P (inner)
&& !type_has_non_deleted_trivial_default_ctor (inner)))
@@ -7844,11 +7847,17 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
type = reftype;
}
+ /* Change an "as-base" clobber to the real type;
+ we don't need to worry about padding in constexpr. */
+ tree itype = initialized_type (init);
+ if (IS_FAKE_BASE_TYPE (itype))
+ itype = TYPE_CONTEXT (itype);
+
/* For initialization of an empty base, the original target will be
*(base*)this, evaluation of which resolves to the object
argument, which has the derived type rather than the base type. */
if (!empty_base && !(same_type_ignoring_top_level_qualifiers_p
- (initialized_type (init), type)))
+ (itype, type)))
{
gcc_assert (is_empty_class (TREE_TYPE (target)));
empty_base = true;
@@ -7955,8 +7964,10 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
/* Don't share a CONSTRUCTOR that might be changed later. */
init = unshare_constructor (init);
- gcc_checking_assert (!*valp || (same_type_ignoring_top_level_qualifiers_p
- (TREE_TYPE (*valp), type)));
+ gcc_checking_assert (!*valp
+ || *valp == void_node
+ || (same_type_ignoring_top_level_qualifiers_p
+ (TREE_TYPE (*valp), type)));
if (empty_base)
{
/* Just evaluate the initializer and return, since there's no actual data
@@ -7969,6 +7980,22 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
CONSTRUCTOR_ZERO_PADDING_BITS (*valp) = zero_padding_bits;
}
}
+ else if (TREE_CLOBBER_P (init))
+ {
+ if (AGGREGATE_TYPE_P (type))
+ {
+ if (*valp)
+ CONSTRUCTOR_ELTS (*valp) = nullptr;
+ else
+ *valp = build_constructor (type, nullptr);
+ TREE_CONSTANT (*valp) = true;
+ TREE_SIDE_EFFECTS (*valp) = false;
+ CONSTRUCTOR_NO_CLEARING (*valp) = true;
+ CONSTRUCTOR_ZERO_PADDING_BITS (*valp) = zero_padding_bits;
+ }
+ else
+ *valp = void_node;
+ }
else if (*valp && TREE_CODE (*valp) == CONSTRUCTOR
&& TREE_CODE (init) == CONSTRUCTOR)
{
@@ -7993,6 +8020,9 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
&& TREE_CODE (*valp) == CONSTRUCTOR
&& TYPE_READONLY (type))
{
+ tree target_type = TREE_TYPE (target);
+ if (IS_FAKE_BASE_TYPE (target_type))
+ target_type = TYPE_CONTEXT (target_type);
if (INDIRECT_REF_P (target)
&& (is_this_parameter
(tree_strip_nop_conversions (TREE_OPERAND (target, 0)))))
@@ -8000,7 +8030,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
constructor of a delegating constructor). Leave it up to the
caller that set 'this' to set TREE_READONLY appropriately. */
gcc_checking_assert (same_type_ignoring_top_level_qualifiers_p
- (TREE_TYPE (target), type) || empty_base);
+ (target_type, type) || empty_base);
else
TREE_READONLY (*valp) = true;
}
@@ -11304,6 +11334,13 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
&& !FUNC_OR_METHOD_TYPE_P (TREE_TYPE (t))
&& !NULLPTR_TYPE_P (TREE_TYPE (t)))
{
+ if (TREE_CLOBBER_P (t))
+ {
+ /* We should have caught any clobbers in INIT/MODIFY_EXPR. */
+ gcc_checking_assert (false);
+ return true;
+ }
+
if (flags & tf_error)
constexpr_error (loc, fundef_p, "lvalue-to-rvalue conversion of "
"a volatile lvalue %qE with type %qT", t,
@@ -12127,6 +12164,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
}
/* FALLTHRU */
case INIT_EXPR:
+ if (TREE_CLOBBER_P (TREE_OPERAND (t, 1)))
+ return true;
return RECUR (TREE_OPERAND (t, 1), rval);
case CONSTRUCTOR:
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index cb3ebff..8122fca 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -18440,6 +18440,8 @@ build_clobber_this (clobber_kind kind)
}
tree exprstmt = build2 (MODIFY_EXPR, void_type_node, thisref, clobber);
+ if (kind == CLOBBER_OBJECT_BEGIN)
+ TREE_SET_CODE (exprstmt, INIT_EXPR);
if (vbases)
exprstmt = build_if_in_charge (exprstmt);
diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index 09fb4f3..f19794c 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -3557,9 +3557,19 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
alloc_expr = maybe_wrap_new_for_constexpr (alloc_expr, type,
cookie_size);
+ bool std_placement = std_placement_new_fn_p (alloc_fn);
+
+ /* For std placement new, clobber the object if the constructor won't do it
+ in start_preparsed_function. This is most important for activating an
+ array in a union (c++/121068), but should also help the optimizers. */
+ const bool do_clobber
+ = (std_placement && !*init && flag_lifetime_dse > 1
+ && (!CLASS_TYPE_P (elt_type)
+ || type_has_non_user_provided_default_constructor (elt_type)));
+
/* In the simple case, we can stop now. */
pointer_type = build_pointer_type (type);
- if (!cookie_size && !is_initialized && !member_delete_p)
+ if (!cookie_size && !is_initialized && !member_delete_p && !do_clobber)
return build_nop (pointer_type, alloc_expr);
/* Store the result of the allocation call in a variable so that we can
@@ -3593,8 +3603,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
So check for a null exception spec on the op new we just called. */
nothrow = TYPE_NOTHROW_P (TREE_TYPE (alloc_fn));
- check_new
- = flag_check_new || (nothrow && !std_placement_new_fn_p (alloc_fn));
+ check_new = flag_check_new || (nothrow && !std_placement);
if (cookie_size)
{
@@ -3649,6 +3658,29 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
/* Any further uses of alloc_node will want this type, too. */
alloc_node = fold_convert (non_const_pointer_type, alloc_node);
+ tree clobber_expr = NULL_TREE;
+ if (do_clobber)
+ {
+ tree clobber = build_clobber (elt_type, CLOBBER_OBJECT_BEGIN);
+ CONSTRUCTOR_IS_DIRECT_INIT (clobber) = true;
+ if (array_p)
+ {
+ /* Clobber each element rather than the array at once. */
+ tree maxindex = cp_build_binary_op (input_location,
+ MINUS_EXPR, outer_nelts,
+ integer_one_node,
+ complain);
+ clobber_expr = build_vec_init (data_addr, maxindex, clobber,
+ /*valinit*/false, /*from_arr*/0,
+ complain, nullptr);
+ }
+ else
+ {
+ tree targ = cp_build_fold_indirect_ref (data_addr);
+ clobber_expr = cp_build_init_expr (targ, clobber);
+ }
+ }
+
/* Now initialize the allocated object. Note that we preevaluate the
initialization expression, apart from the actual constructor call or
assignment--we do this because we want to delay the allocation as long
@@ -3877,6 +3909,8 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
if (init_expr)
rval = build2 (COMPOUND_EXPR, TREE_TYPE (rval), init_expr, rval);
+ if (clobber_expr)
+ rval = build2 (COMPOUND_EXPR, TREE_TYPE (rval), clobber_expr, rval);
if (cookie_expr)
rval = build2 (COMPOUND_EXPR, TREE_TYPE (rval), cookie_expr, rval);
@@ -4717,6 +4751,9 @@ build_vec_init (tree base, tree maxindex, tree init,
the partially constructed array if an exception is thrown.
But don't do this if we're assigning. */
if (flag_exceptions && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
+ /* And don't clean up from clobbers, the actual initialization will
+ follow as a separate build_vec_init. */
+ && !(init && TREE_CLOBBER_P (init))
&& from_array != 2)
{
tree e;
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 860f3f0..a8c54c7 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -42636,8 +42636,11 @@ cp_parser_omp_clause_doacross (cp_parser *parser, tree list, location_t loc)
to ( variable-list )
OpenMP 5.1:
- from ( [present :] variable-list )
- to ( [present :] variable-list ) */
+ from ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list )
+ to ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list )
+
+ motion-modifier:
+ present | iterator (iterators-definition) */
static tree
cp_parser_omp_clause_from_to (cp_parser *parser, enum omp_clause_code kind,
@@ -42646,23 +42649,113 @@ cp_parser_omp_clause_from_to (cp_parser *parser, enum omp_clause_code kind,
if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
return list;
- bool present = false;
- cp_token *token = cp_lexer_peek_token (parser->lexer);
+ int pos = 1;
+ int colon_pos = 0;
+ int iterator_length = 0;
- if (token->type == CPP_NAME
- && strcmp (IDENTIFIER_POINTER (token->u.value), "present") == 0
- && cp_lexer_nth_token_is (parser->lexer, 2, CPP_COLON))
+ while (cp_lexer_peek_nth_token (parser->lexer, pos)->type == CPP_NAME)
{
- present = true;
- cp_lexer_consume_token (parser->lexer);
- cp_lexer_consume_token (parser->lexer);
+ const char *identifier =
+ IDENTIFIER_POINTER (cp_lexer_peek_nth_token (parser->lexer,
+ pos)->u.value);
+ if (cp_lexer_nth_token_is (parser->lexer, pos + 1, CPP_OPEN_PAREN))
+ {
+ int n = cp_parser_skip_balanced_tokens (parser, pos + 1);
+ if (n != pos + 1)
+ {
+ if (strcmp (identifier, "iterator") == 0)
+ iterator_length = n - pos;
+ pos = n - 1;
+ }
+ }
+ if (cp_lexer_peek_nth_token (parser->lexer, pos + 1)->type == CPP_COMMA)
+ pos += 2;
+ else
+ pos++;
+ if (cp_lexer_peek_nth_token (parser->lexer, pos)->type == CPP_COLON)
+ {
+ colon_pos = pos;
+ break;
+ }
}
+ bool present = false;
+ tree iterators = NULL_TREE;
+
+ for (int pos = 1; pos < colon_pos; ++pos)
+ {
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+ if (token->type == CPP_COMMA)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ continue;
+ }
+ const char *p = IDENTIFIER_POINTER (token->u.value);
+ if (strcmp ("present", p) == 0)
+ {
+ if (present)
+ {
+ cp_parser_error (parser, "too many %<present%> modifiers");
+ cp_parser_skip_to_closing_parenthesis (parser,
+ /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+ return list;
+ }
+ present = true;
+ cp_lexer_consume_token (parser->lexer);
+ }
+ else if (strcmp ("iterator", p) == 0)
+ {
+ if (iterators)
+ {
+ cp_parser_error (parser, "too many %<iterator%> modifiers");
+ cp_parser_skip_to_closing_parenthesis (parser,
+ /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+ return list;
+ }
+ begin_scope (sk_omp, NULL);
+ iterators = cp_parser_omp_iterators (parser);
+ pos += iterator_length - 1;
+ }
+
+ else
+ {
+ error_at (token->location,
+ "%qs clause with modifier other than %<iterator%> "
+ "or %<present%>",
+ kind == OMP_CLAUSE_TO ? "to" : "from");
+ cp_parser_skip_to_closing_parenthesis (parser,
+ /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+ return list;
+ }
+ }
+
+ if (colon_pos)
+ cp_parser_require (parser, CPP_COLON, RT_COLON);
+
tree nl = cp_parser_omp_var_list_no_open (parser, kind, list, NULL, true);
if (present)
for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
OMP_CLAUSE_MOTION_PRESENT (c) = 1;
+ if (iterators)
+ {
+ tree block = poplevel (1, 1, 0);
+ if (iterators == error_mark_node)
+ iterators = NULL_TREE;
+ else
+ TREE_VEC_ELT (iterators, 5) = block;
+ }
+
+ if (iterators)
+ for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_ITERATORS (c) = iterators;
+
return nl;
}
@@ -42696,16 +42789,34 @@ cp_parser_omp_clause_map (cp_parser *parser, tree list, bool declare_mapper_p)
int pos = 1;
int map_kind_pos = 0;
- while (cp_lexer_peek_nth_token (parser->lexer, pos)->type == CPP_NAME
- || cp_lexer_peek_nth_token (parser->lexer, pos)->keyword == RID_DELETE)
+ int iterator_length = 0;
+ for (;;)
{
- if (cp_lexer_peek_nth_token (parser->lexer, pos + 1)->type == CPP_COLON)
+ cp_token *tok = cp_lexer_peek_nth_token (parser->lexer, pos);
+ if (!(tok->type == CPP_NAME || tok->keyword == RID_DELETE))
+ break;
+
+ cp_token *next_tok = cp_lexer_peek_nth_token (parser->lexer, pos + 1);
+ if (tok->type == CPP_NAME
+ && strcmp (IDENTIFIER_POINTER (tok->u.value), "iterator") == 0
+ && next_tok->type == CPP_OPEN_PAREN)
+ {
+ int n = cp_parser_skip_balanced_tokens (parser, pos + 1);
+ if (n != pos + 1)
+ {
+ iterator_length = n - pos;
+ pos = n - 1;
+ next_tok = cp_lexer_peek_nth_token (parser->lexer, n);
+ }
+ }
+
+ if (next_tok->type == CPP_COLON)
{
map_kind_pos = pos;
break;
}
- if (cp_lexer_peek_nth_token (parser->lexer, pos + 1)->type == CPP_COMMA)
+ if (next_tok->type == CPP_COMMA)
pos++;
else if (cp_lexer_peek_nth_token (parser->lexer, pos + 1)->type
== CPP_OPEN_PAREN)
@@ -42718,6 +42829,7 @@ cp_parser_omp_clause_map (cp_parser *parser, tree list, bool declare_mapper_p)
bool present_modifier = false;
bool mapper_modifier = false;
tree mapper_name = NULL_TREE;
+ tree iterators = NULL_TREE;
for (int pos = 1; pos < map_kind_pos; ++pos)
{
cp_token *tok = cp_lexer_peek_token (parser->lexer);
@@ -42756,6 +42868,21 @@ cp_parser_omp_clause_map (cp_parser *parser, tree list, bool declare_mapper_p)
close_modifier = true;
cp_lexer_consume_token (parser->lexer);
}
+ else if (strcmp ("iterator", p) == 0)
+ {
+ if (iterators)
+ {
+ cp_parser_error (parser, "too many %<iterator%> modifiers");
+ cp_parser_skip_to_closing_parenthesis (parser,
+ /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+ return list;
+ }
+ begin_scope (sk_omp, NULL);
+ iterators = cp_parser_omp_iterators (parser);
+ pos += iterator_length - 1;
+ }
else if (strcmp ("mapper", p) == 0)
{
cp_lexer_consume_token (parser->lexer);
@@ -42844,7 +42971,7 @@ cp_parser_omp_clause_map (cp_parser *parser, tree list, bool declare_mapper_p)
{
cp_parser_error (parser, "%<map%> clause with map-type modifier "
"other than %<always%>, %<close%>, "
- "%<mapper%> or %<present%>");
+ "%<iterator%>, %<mapper%> or %<present%>");
cp_parser_skip_to_closing_parenthesis (parser,
/*recovering=*/true,
/*or_comma=*/false,
@@ -42908,9 +43035,19 @@ cp_parser_omp_clause_map (cp_parser *parser, tree list, bool declare_mapper_p)
tree last_new = NULL_TREE;
+ if (iterators)
+ {
+ tree block = poplevel (1, 1, 0);
+ if (iterators == error_mark_node)
+ iterators = NULL_TREE;
+ else
+ TREE_VEC_ELT (iterators, 5) = block;
+ }
+
for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
{
OMP_CLAUSE_SET_MAP_KIND (c, kind);
+ OMP_CLAUSE_ITERATORS (c) = iterators;
last_new = c;
}
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index be79b50..0c7788d 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -7751,7 +7751,14 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
/* We've reached the end of a list of expanded nodes. Reset the group
start pointer. */
if (c == grp_sentinel)
- grp_start_p = NULL;
+ {
+ if (grp_start_p
+ && OMP_CLAUSE_HAS_ITERATORS (*grp_start_p))
+ for (tree gc = *grp_start_p; gc != grp_sentinel;
+ gc = OMP_CLAUSE_CHAIN (gc))
+ OMP_CLAUSE_ITERATORS (gc) = OMP_CLAUSE_ITERATORS (*grp_start_p);
+ grp_start_p = NULL;
+ }
switch (OMP_CLAUSE_CODE (c))
{
@@ -9003,6 +9010,13 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
/* FALLTHRU */
case OMP_CLAUSE_TO:
case OMP_CLAUSE_FROM:
+ if (OMP_CLAUSE_ITERATORS (c)
+ && cp_omp_finish_iterators (OMP_CLAUSE_ITERATORS (c)))
+ {
+ t = error_mark_node;
+ break;
+ }
+ /* FALLTHRU */
case OMP_CLAUSE__CACHE_:
{
using namespace omp_addr_tokenizer;
@@ -9906,6 +9920,11 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
pc = &OMP_CLAUSE_CHAIN (c);
}
+ if (grp_start_p
+ && OMP_CLAUSE_HAS_ITERATORS (*grp_start_p))
+ for (tree gc = *grp_start_p; gc; gc = OMP_CLAUSE_CHAIN (gc))
+ OMP_CLAUSE_ITERATORS (gc) = OMP_CLAUSE_ITERATORS (*grp_start_p);
+
if (reduction_seen < 0 && (ordered_seen || schedule_seen))
reduction_seen = -2;
diff --git a/gcc/defaults.h b/gcc/defaults.h
index 16f6dc2..f807ef6 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -1158,7 +1158,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#endif
#ifndef MAX_FIXED_MODE_SIZE
-#define MAX_FIXED_MODE_SIZE GET_MODE_BITSIZE (DImode)
+#define MAX_FIXED_MODE_SIZE MAX (BITS_PER_WORD * 2, 64)
#endif
/* Nonzero if structures and unions should be returned in memory.
diff --git a/gcc/diagnostics/buffering.h b/gcc/diagnostics/buffering.h
index c3ac070..9b86fee 100644
--- a/gcc/diagnostics/buffering.h
+++ b/gcc/diagnostics/buffering.h
@@ -36,7 +36,7 @@ class sink;
A diagnostics::buffer can be:
* flushed to the diagnostics::context, which issues
- the diagnostics within the buffer to the output format
+ the diagnostics within the buffer to the output sinks
and checks for limits such as -fmax-errors=, or
* moved to another diagnostics::buffer, which moves the diagnostics
@@ -45,13 +45,13 @@ class sink;
source buffer, or
* cleared, which discards any diagnostics within the buffer
- without issuing them to the output format.
+ without issuing them to the output sinks.
- Since a buffer needs to contain output-format-specific data,
- it's not possible to change the output format of the
+ Since a buffer needs to contain sink-specific data,
+ it's not possible to change the output sink(s) of the
diagnostics::context once any buffers are non-empty.
- To simplify implementing output formats, it's not possible
+ To simplify implementing output sinks, it's not possible
to change buffering on a diagnostics::context whilst within a
diagnostic group. */
diff --git a/gcc/diagnostics/context.cc b/gcc/diagnostics/context.cc
index 85f7d2a..a1441ca 100644
--- a/gcc/diagnostics/context.cc
+++ b/gcc/diagnostics/context.cc
@@ -170,7 +170,7 @@ context::initialize (int n_opts)
m_text_callbacks.m_html_start_span
= default_start_span_fn<to_html>;
m_text_callbacks.m_end_diagnostic = default_text_finalizer;
- m_option_mgr = nullptr;
+ m_option_id_mgr = nullptr;
m_urlifier_stack = new auto_vec<urlifier_stack_node> ();
m_last_location = UNKNOWN_LOCATION;
m_client_aux_data = nullptr;
@@ -337,8 +337,8 @@ context::finish ()
m_client_data_hooks = nullptr;
}
- delete m_option_mgr;
- m_option_mgr = nullptr;
+ delete m_option_id_mgr;
+ m_option_id_mgr = nullptr;
if (m_urlifier_stack)
{
@@ -465,11 +465,11 @@ context::set_original_argv (unique_argv original_argv)
}
void
-context::set_option_manager (std::unique_ptr<option_manager> mgr,
- unsigned lang_mask)
+context::set_option_id_manager (std::unique_ptr<option_id_manager> mgr,
+ unsigned lang_mask)
{
- delete m_option_mgr;
- m_option_mgr = mgr.release ();
+ delete m_option_id_mgr;
+ m_option_id_mgr = mgr.release ();
m_lang_mask = lang_mask;
}
@@ -1682,6 +1682,12 @@ context::pop_nesting_level ()
}
void
+context::set_nesting_level (int new_level)
+{
+ m_diagnostic_groups.m_diagnostic_nesting_level = new_level;
+}
+
+void
sink::dump (FILE *out, int indent) const
{
fprintf (out, "%*sprinter:\n", indent, "");
diff --git a/gcc/diagnostics/context.h b/gcc/diagnostics/context.h
index f47370b..b6ec85c 100644
--- a/gcc/diagnostics/context.h
+++ b/gcc/diagnostics/context.h
@@ -23,7 +23,10 @@ along with GCC; see the file COPYING3. If not see
#include "lazily-created.h"
#include "unique-argv.h"
#include "diagnostics/option-classifier.h"
+#include "diagnostics/option-id-manager.h"
#include "diagnostics/context-options.h"
+#include "diagnostics/source-printing-options.h"
+#include "diagnostics/counters.h"
namespace diagnostics {
@@ -81,84 +84,6 @@ typedef void (*text_finalizer_fn) (text_sink &,
const diagnostic_info *,
enum kind);
-/* Abstract base class for the diagnostic subsystem to make queries
- about command-line options. */
-
-class option_manager
-{
-public:
- virtual ~option_manager () {}
-
- /* Return 1 if option OPT_ID is enabled, 0 if it is disabled,
- or -1 if it isn't a simple on-off switch
- (or if the value is unknown, typically set later in target). */
- virtual int option_enabled_p (option_id opt_id) const = 0;
-
- /* Return malloced memory for the name of the option OPT_ID
- which enabled a diagnostic, originally of type ORIG_DIAG_KIND but
- possibly converted to DIAG_KIND by options such as -Werror.
- May return NULL if no name is to be printed.
- May be passed 0 as well as the index of a particular option. */
- virtual char *make_option_name (option_id opt_id,
- enum kind orig_diag_kind,
- enum kind diag_kind) const = 0;
-
- /* Return malloced memory for a URL describing the option that controls
- a diagnostic.
- May return NULL if no URL is available.
- May be passed 0 as well as the index of a particular option. */
- virtual char *make_option_url (option_id opt_id) const = 0;
-};
-
-/* A bundle of options relating to printing the user's source code
- (potentially with a margin, underlining, labels, etc). */
-
-struct source_printing_options
-{
- /* True if we should print the source line with a caret indicating
- the location.
- Corresponds to -fdiagnostics-show-caret. */
- bool enabled;
-
- /* Maximum width of the source line printed. */
- int max_width;
-
- /* Character used at the caret when printing source locations. */
- char caret_chars[rich_location::STATICALLY_ALLOCATED_RANGES];
-
- /* When printing source code, should the characters at carets and ranges
- be colorized? (assuming colorization is on at all).
- This should be true for frontends that generate range information
- (so that the ranges of code are colorized),
- and false for frontends that merely specify points within the
- source code (to avoid e.g. colorizing just the first character in
- a token, which would look strange). */
- bool colorize_source_p;
-
- /* When printing source code, should labelled ranges be printed?
- Corresponds to -fdiagnostics-show-labels. */
- bool show_labels_p;
-
- /* When printing source code, should there be a left-hand margin
- showing line numbers?
- Corresponds to -fdiagnostics-show-line-numbers. */
- bool show_line_numbers_p;
-
- /* If printing source code, what should the minimum width of the margin
- be? Line numbers will be right-aligned, and padded to this width.
- Corresponds to -fdiagnostics-minimum-margin-width=VALUE. */
- int min_margin_width;
-
- /* Usable by plugins; if true, print a debugging ruler above the
- source output. */
- bool show_ruler_p;
-
- /* When printing events in an inline path, should we print lines
- visualizing links between related events (e.g. for CFG paths)?
- Corresponds to -fdiagnostics-show-event-links. */
- bool show_event_links_p;
-};
-
/* A bundle of state for determining column numbers in diagnostics
(tab stops, whether to start at 0 or 1, etc).
Uses a file_cache to handle tabs. */
@@ -291,28 +216,6 @@ private:
enum diagnostics_escape_format m_escape_format;
};
-/* A collection of counters of diagnostics, per-kind
- (e.g. "3 errors and 1 warning"), for use by both context
- and by diagnostics::buffer. */
-
-struct counters
-{
- counters ();
-
- void dump (FILE *out, int indent) const;
- void DEBUG_FUNCTION dump () const { dump (stderr, 0); }
-
- int get_count (enum kind kind) const
- {
- return m_count_for_kind[static_cast<size_t> (kind)];
- }
-
- void move_to (counters &dest);
- void clear ();
-
- int m_count_for_kind[static_cast<size_t> (kind::last_diagnostic_kind)];
-};
-
/* This class encapsulates the state of the diagnostics subsystem
as a whole (either directly, or via owned objects of other classes, to
avoid global variables).
@@ -334,7 +237,7 @@ struct counters
- an optional urlifier to inject URLs into formatted messages
- counting the number of diagnostics reported of each kind
(class diagnostics::counters)
- - calling out to a option_manager to determine if
+ - calling out to a option_id_manager to determine if
a particular warning is enabled or disabled
- tracking pragmas that enable/disable warnings in a range of
source code
@@ -398,6 +301,7 @@ public:
void push_nesting_level ();
void pop_nesting_level ();
+ void set_nesting_level (int new_level);
bool warning_enabled_at (location_t loc, option_id opt_id);
@@ -546,32 +450,32 @@ public:
/* Option-related member functions. */
inline bool option_enabled_p (option_id opt_id) const
{
- if (!m_option_mgr)
+ if (!m_option_id_mgr)
return true;
- return m_option_mgr->option_enabled_p (opt_id);
+ return m_option_id_mgr->option_enabled_p (opt_id);
}
inline char *make_option_name (option_id opt_id,
enum kind orig_diag_kind,
enum kind diag_kind) const
{
- if (!m_option_mgr)
+ if (!m_option_id_mgr)
return nullptr;
- return m_option_mgr->make_option_name (opt_id,
- orig_diag_kind,
- diag_kind);
+ return m_option_id_mgr->make_option_name (opt_id,
+ orig_diag_kind,
+ diag_kind);
}
inline char *make_option_url (option_id opt_id) const
{
- if (!m_option_mgr)
+ if (!m_option_id_mgr)
return nullptr;
- return m_option_mgr->make_option_url (opt_id);
+ return m_option_id_mgr->make_option_url (opt_id);
}
void
- set_option_manager (std::unique_ptr<option_manager> mgr,
- unsigned lang_mask);
+ set_option_id_manager (std::unique_ptr<option_id_manager> option_id_mgr,
+ unsigned lang_mask);
unsigned get_lang_mask () const
{
@@ -808,7 +712,7 @@ private:
/* Owned by the context; this would be a std::unique_ptr if
context had a proper ctor. */
- option_manager *m_option_mgr;
+ option_id_manager *m_option_id_mgr;
unsigned m_lang_mask;
/* A stack of optional hooks for adding URLs to quoted text strings in
diff --git a/gcc/diagnostics/counters.h b/gcc/diagnostics/counters.h
new file mode 100644
index 0000000..42db3fe
--- /dev/null
+++ b/gcc/diagnostics/counters.h
@@ -0,0 +1,51 @@
+/* Counts of per-kind diagnostics.
+ Copyright (C) 2000-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 GCC_DIAGNOSTICS_COUNTERS_H
+#define GCC_DIAGNOSTICS_COUNTERS_H
+
+#include "diagnostics/kinds.h"
+
+namespace diagnostics {
+
+/* A collection of counters of diagnostics, per-kind
+ (e.g. "3 errors and 1 warning"), for use by both diagnostics::context
+ and by diagnostics::buffer. */
+
+struct counters
+{
+ counters ();
+
+ void dump (FILE *out, int indent) const;
+ void DEBUG_FUNCTION dump () const { dump (stderr, 0); }
+
+ int get_count (enum kind kind) const
+ {
+ return m_count_for_kind[static_cast<size_t> (kind)];
+ }
+
+ void move_to (counters &dest);
+ void clear ();
+
+ int m_count_for_kind[static_cast<size_t> (kind::last_diagnostic_kind)];
+};
+
+} // namespace diagnostics
+
+#endif /* ! GCC_DIAGNOSTICS_COUNTERS_H */
diff --git a/gcc/diagnostics/html-sink.cc b/gcc/diagnostics/html-sink.cc
index 13d6309..934d8e2 100644
--- a/gcc/diagnostics/html-sink.cc
+++ b/gcc/diagnostics/html-sink.cc
@@ -1018,10 +1018,11 @@ html_builder::make_element_for_diagnostic (const diagnostic_info &diagnostic,
// Add any metadata as a suffix to the message
if (diagnostic.m_metadata)
- {
- xp.add_text (" ");
- xp.append (make_element_for_metadata (*diagnostic.m_metadata));
- }
+ if (auto e = make_element_for_metadata (*diagnostic.m_metadata))
+ {
+ xp.add_text (" ");
+ xp.append (std::move (e));
+ }
// Add any option as a suffix to the message
@@ -1234,6 +1235,9 @@ html_builder::make_element_for_metadata (const metadata &m)
(make_metadata_element (std::move (label), std::move (url)));
}
+ if (span_metadata->m_children.empty ())
+ return nullptr;
+
return span_metadata;
}
diff --git a/gcc/diagnostics/lazy-paths.cc b/gcc/diagnostics/lazy-paths.cc
index 4934651..f246eea 100644
--- a/gcc/diagnostics/lazy-paths.cc
+++ b/gcc/diagnostics/lazy-paths.cc
@@ -125,12 +125,12 @@ test_intraprocedural_path (pretty_printer *event_pp)
"double `free'");
}
-/* Implementation of diagnostics::option_manager for which all
+/* Implementation of diagnostics::option_id_manager for which all
options are disabled, for use in selftests.
Note that this is *not* called for option_id (0), which
means "always warn" */
-class all_warnings_disabled : public diagnostics::option_manager
+class all_warnings_disabled : public diagnostics::option_id_manager
{
public:
int option_enabled_p (diagnostics::option_id) const final override
@@ -168,7 +168,7 @@ test_emission (pretty_printer *event_pp)
is skipped. */
{
test_context dc;
- dc.set_option_manager (std::make_unique<all_warnings_disabled> (), 0);
+ dc.set_option_id_manager (std::make_unique<all_warnings_disabled> (), 0);
test_rich_location rich_loc (*event_pp);
ASSERT_FALSE (rich_loc.m_path.generated_p ());
diff --git a/gcc/diagnostics/option-id-manager.h b/gcc/diagnostics/option-id-manager.h
new file mode 100644
index 0000000..08add5b
--- /dev/null
+++ b/gcc/diagnostics/option-id-manager.h
@@ -0,0 +1,56 @@
+/* Hooks for giving client-specific meaning to option ids.
+ Copyright (C) 2000-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 GCC_DIAGNOSTICS_OPTION_ID_MANAGER_H
+#define GCC_DIAGNOSTICS_OPTION_ID_MANAGER_H
+
+namespace diagnostics {
+
+/* Abstract base class for the diagnostic subsystem to make queries
+ about command-line options. */
+
+class option_id_manager
+{
+public:
+ virtual ~option_id_manager () {}
+
+ /* Return 1 if option OPT_ID is enabled, 0 if it is disabled,
+ or -1 if it isn't a simple on-off switch
+ (or if the value is unknown, typically set later in target). */
+ virtual int option_enabled_p (option_id opt_id) const = 0;
+
+ /* Return malloced memory for the name of the option OPT_ID
+ which enabled a diagnostic, originally of type ORIG_DIAG_KIND but
+ possibly converted to DIAG_KIND by options such as -Werror.
+ May return NULL if no name is to be printed.
+ May be passed 0 as well as the index of a particular option. */
+ virtual char *make_option_name (option_id opt_id,
+ enum kind orig_diag_kind,
+ enum kind diag_kind) const = 0;
+
+ /* Return malloced memory for a URL describing the option that controls
+ a diagnostic.
+ May return NULL if no URL is available.
+ May be passed 0 as well as the index of a particular option. */
+ virtual char *make_option_url (option_id opt_id) const = 0;
+};
+
+} // namespace diagnostics
+
+#endif /* ! GCC_DIAGNOSTICS_OPTION_ID_MANAGER_H */
diff --git a/gcc/diagnostics/source-printing-options.h b/gcc/diagnostics/source-printing-options.h
new file mode 100644
index 0000000..362b691
--- /dev/null
+++ b/gcc/diagnostics/source-printing-options.h
@@ -0,0 +1,76 @@
+/* Options relating to printing the user's source code.
+ Copyright (C) 2000-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 GCC_DIAGNOSTICS_SOURCE_PRINTING_OPTIONS_H
+#define GCC_DIAGNOSTICS_SOURCE_PRINTING_OPTIONS_H
+
+namespace diagnostics {
+
+/* A bundle of options relating to printing the user's source code
+ (potentially with a margin, underlining, labels, etc). */
+
+struct source_printing_options
+{
+ /* True if we should print the source line with a caret indicating
+ the location.
+ Corresponds to -fdiagnostics-show-caret. */
+ bool enabled;
+
+ /* Maximum width of the source line printed. */
+ int max_width;
+
+ /* Character used at the caret when printing source locations. */
+ char caret_chars[rich_location::STATICALLY_ALLOCATED_RANGES];
+
+ /* When printing source code, should the characters at carets and ranges
+ be colorized? (assuming colorization is on at all).
+ This should be true for frontends that generate range information
+ (so that the ranges of code are colorized),
+ and false for frontends that merely specify points within the
+ source code (to avoid e.g. colorizing just the first character in
+ a token, which would look strange). */
+ bool colorize_source_p;
+
+ /* When printing source code, should labelled ranges be printed?
+ Corresponds to -fdiagnostics-show-labels. */
+ bool show_labels_p;
+
+ /* When printing source code, should there be a left-hand margin
+ showing line numbers?
+ Corresponds to -fdiagnostics-show-line-numbers. */
+ bool show_line_numbers_p;
+
+ /* If printing source code, what should the minimum width of the margin
+ be? Line numbers will be right-aligned, and padded to this width.
+ Corresponds to -fdiagnostics-minimum-margin-width=VALUE. */
+ int min_margin_width;
+
+ /* Usable by plugins; if true, print a debugging ruler above the
+ source output. */
+ bool show_ruler_p;
+
+ /* When printing events in an inline path, should we print lines
+ visualizing links between related events (e.g. for CFG paths)?
+ Corresponds to -fdiagnostics-show-event-links. */
+ bool show_event_links_p;
+};
+
+} // namespace diagnostics
+
+#endif /* ! GCC_DIAGNOSTICS_SOURCE_PRINTING_OPTIONS_H */
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index f3f1445..64c1217 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -1887,8 +1887,8 @@ Produce code conforming to version 20191213.
In the absence of this configuration option the default version is 20191213.
@item --enable-__cxa_atexit
-Define if you want to use @code{__cxa_atexit}, rather than atexit, to
-register C++ destructors for local statics and global objects.
+Define if you want to use @code{__cxa_atexit}, rather than @code{atexit},
+to register C++ destructors for local statics and global objects.
This is essential for fully standards-compliant handling of
destructors, but requires @code{__cxa_atexit} in libc. This option is
currently only available on systems with GNU libc. When enabled, this
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index c1e708b..105a60d 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -20612,18 +20612,22 @@ LTO output files.
@opindex fdump-rtl-@var{pass}
@item -d@var{letters}
@itemx -fdump-rtl-@var{pass}
-@itemx -fdump-rtl-@var{pass}=@var{filename}
+@itemx -fdump-rtl-@var{pass}-@var{options}
+@itemx -fdump-rtl-@var{pass}-@var{options}=@var{filename}
Says to make debugging dumps during compilation at times specified by
-@var{letters}. This is used for debugging the RTL-based passes of the
+@var{letters} when using @option{-d} or by @var{pass} when using
+@option{-fdump-rtl}. This is used for debugging the RTL-based passes of the
compiler.
Some @option{-d@var{letters}} switches have different meaning when
@option{-E} is used for preprocessing. @xref{Preprocessor Options},
for information about preprocessor-specific dump options.
-Debug dumps can be enabled with a @option{-fdump-rtl} switch or some
-@option{-d} option @var{letters}. Here are the possible
-letters for use in @var{pass} and @var{letters}, and their meanings:
+The @samp{-@var{options}} form allows greater control over the details of the
+dump. See @option{-fdump-tree}.
+
+Here are actual instances of command-line options following these patterns and
+their meanings:
@table @gcctabopt
@@ -21150,8 +21154,7 @@ GraphViz to @file{@var{file}.@var{passid}.@var{pass}.dot}. Each function in
the file is pretty-printed as a subgraph, so that GraphViz can render them
all in a single plot.
-This option currently only works for RTL dumps, and the RTL is always
-dumped in slim form.
+RTL is always dumped in slim form.
@item vops
Enable showing virtual operands for every statement.
@item lineno
diff --git a/gcc/doc/libgdiagnostics/topics/compatibility.rst b/gcc/doc/libgdiagnostics/topics/compatibility.rst
index 0ca41a3..ccf1236 100644
--- a/gcc/doc/libgdiagnostics/topics/compatibility.rst
+++ b/gcc/doc/libgdiagnostics/topics/compatibility.rst
@@ -262,3 +262,12 @@ working with :type:`diagnostic_message_buffer`.
* :func:`diagnostic_add_location_with_label_via_msg_buf`
* :func:`diagnostic_execution_path_add_event_via_msg_buf`
+
+.. _LIBGDIAGNOSTICS_ABI_5:
+
+``LIBGDIAGNOSTICS_ABI_5``
+-------------------------
+
+``LIBGDIAGNOSTICS_ABI_5`` covers the addition of this function:
+
+ * :func:`diagnostic_manager_set_debug_physical_locations`
diff --git a/gcc/doc/libgdiagnostics/topics/physical-locations.rst b/gcc/doc/libgdiagnostics/topics/physical-locations.rst
index be8e7eb..fcd81a0 100644
--- a/gcc/doc/libgdiagnostics/topics/physical-locations.rst
+++ b/gcc/doc/libgdiagnostics/topics/physical-locations.rst
@@ -304,3 +304,19 @@ This diagnostic has three locations
.. code-block:: c
#ifdef LIBDIAGNOSTICS_HAVE_diagnostic_message_buffer
+
+.. function:: void diagnostic_manager_set_debug_physical_locations (diagnostic_manager *mgr, \
+ int value)
+
+ Calling ``diagnostic_manager_set_debug_physical_locations (mgr, 1);``
+ will lead to debugging information being printed to ``stderr`` when
+ creating :type:`diagnostic_physical_location` instances.
+
+ The precise format of these messages is subject to change.
+
+ This function was added in :ref:`LIBGDIAGNOSTICS_ABI_5`; you can
+ test for its presence using
+
+ .. code-block:: c
+
+ #ifdef LIBDIAGNOSTICS_HAVE_diagnostic_manager_set_debug_physical_locations
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 215552c..4d4e676 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -1424,10 +1424,10 @@ the smaller of @var{computed} and @code{BIGGEST_ALIGNMENT}
@defmac MAX_FIXED_MODE_SIZE
An integer expression for the size in bits of the largest integer
-machine mode that should actually be used. All integer machine modes of
-this size or smaller can be used for structures and unions with the
-appropriate sizes. If this macro is undefined, @code{GET_MODE_BITSIZE
-(DImode)} is assumed.
+machine mode that should actually be used by GCC internally.
+All integer machine modes of this size or smaller can be used for
+structures and unions with the appropriate sizes. If this macro is
+undefined, @code{MAX (BITS_PER_WORD * 2, 64)} is assumed.
@end defmac
@defmac STACK_SAVEAREA_MODE (@var{save_level})
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index b03ad4c..1a51ad5 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -1251,10 +1251,10 @@ the smaller of @var{computed} and @code{BIGGEST_ALIGNMENT}
@defmac MAX_FIXED_MODE_SIZE
An integer expression for the size in bits of the largest integer
-machine mode that should actually be used. All integer machine modes of
-this size or smaller can be used for structures and unions with the
-appropriate sizes. If this macro is undefined, @code{GET_MODE_BITSIZE
-(DImode)} is assumed.
+machine mode that should actually be used by GCC internally.
+All integer machine modes of this size or smaller can be used for
+structures and unions with the appropriate sizes. If this macro is
+undefined, @code{MAX (BITS_PER_WORD * 2, 64)} is assumed.
@end defmac
@defmac STACK_SAVEAREA_MODE (@var{save_level})
diff --git a/gcc/dump-context.h b/gcc/dump-context.h
index 9c52f03..336cb23 100644
--- a/gcc/dump-context.h
+++ b/gcc/dump-context.h
@@ -267,7 +267,7 @@ extern void verify_dumped_text (const location &loc,
void
verify_item (const location &loc,
const optinfo_item *item,
- enum optinfo_item_kind expected_kind,
+ enum optinfo_item::kind expected_kind,
location_t expected_location,
const char *expected_text);
@@ -275,7 +275,7 @@ verify_item (const location &loc,
#define ASSERT_IS_TEXT(ITEM, EXPECTED_TEXT) \
SELFTEST_BEGIN_STMT \
- verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_TEXT, \
+ verify_item (SELFTEST_LOCATION, (ITEM), optinfo_item::kind::text, \
UNKNOWN_LOCATION, (EXPECTED_TEXT)); \
SELFTEST_END_STMT
@@ -283,7 +283,7 @@ verify_item (const location &loc,
#define ASSERT_IS_TREE(ITEM, EXPECTED_LOCATION, EXPECTED_TEXT) \
SELFTEST_BEGIN_STMT \
- verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_TREE, \
+ verify_item (SELFTEST_LOCATION, (ITEM), optinfo_item::kind::tree, \
(EXPECTED_LOCATION), (EXPECTED_TEXT)); \
SELFTEST_END_STMT
@@ -291,7 +291,7 @@ verify_item (const location &loc,
#define ASSERT_IS_GIMPLE(ITEM, EXPECTED_LOCATION, EXPECTED_TEXT) \
SELFTEST_BEGIN_STMT \
- verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_GIMPLE, \
+ verify_item (SELFTEST_LOCATION, (ITEM), optinfo_item::kind::gimple, \
(EXPECTED_LOCATION), (EXPECTED_TEXT)); \
SELFTEST_END_STMT
@@ -299,7 +299,7 @@ verify_item (const location &loc,
#define ASSERT_IS_SYMTAB_NODE(ITEM, EXPECTED_LOCATION, EXPECTED_TEXT) \
SELFTEST_BEGIN_STMT \
- verify_item (SELFTEST_LOCATION, (ITEM), OPTINFO_ITEM_KIND_SYMTAB_NODE, \
+ verify_item (SELFTEST_LOCATION, (ITEM), optinfo_item::kind::symtab_node, \
(EXPECTED_LOCATION), (EXPECTED_TEXT)); \
SELFTEST_END_STMT
diff --git a/gcc/dumpfile.cc b/gcc/dumpfile.cc
index ebee8e5..bca8b38 100644
--- a/gcc/dumpfile.cc
+++ b/gcc/dumpfile.cc
@@ -636,8 +636,8 @@ make_item_for_dump_gimple_stmt (gimple *stmt, int spc, dump_flags_t dump_flags)
pp_gimple_stmt_1 (&pp, stmt, spc, dump_flags);
pp_newline (&pp);
- std::unique_ptr<optinfo_item> item
- = std::make_unique<optinfo_item> (OPTINFO_ITEM_KIND_GIMPLE,
+ auto item
+ = std::make_unique<optinfo_item> (optinfo_item::kind::gimple,
gimple_location (stmt),
xstrdup (pp_formatted_text (&pp)));
return item;
@@ -684,8 +684,8 @@ make_item_for_dump_gimple_expr (gimple *stmt, int spc, dump_flags_t dump_flags)
pp_needs_newline (&pp) = true;
pp_gimple_stmt_1 (&pp, stmt, spc, dump_flags);
- std::unique_ptr<optinfo_item> item
- = std::make_unique<optinfo_item> (OPTINFO_ITEM_KIND_GIMPLE,
+ auto item
+ = std::make_unique<optinfo_item> (optinfo_item::kind::gimple,
gimple_location (stmt),
xstrdup (pp_formatted_text (&pp)));
return item;
@@ -738,8 +738,8 @@ make_item_for_dump_generic_expr (tree node, dump_flags_t dump_flags)
if (EXPR_HAS_LOCATION (node))
loc = EXPR_LOCATION (node);
- std::unique_ptr<optinfo_item> item
- = std::make_unique<optinfo_item> (OPTINFO_ITEM_KIND_TREE, loc,
+ auto item
+ = std::make_unique<optinfo_item> (optinfo_item::kind::tree, loc,
xstrdup (pp_formatted_text (&pp)));
return item;
}
@@ -783,8 +783,8 @@ static std::unique_ptr<optinfo_item>
make_item_for_dump_symtab_node (symtab_node *node)
{
location_t loc = DECL_SOURCE_LOCATION (node->decl);
- std::unique_ptr<optinfo_item> item
- = std::make_unique<optinfo_item> (OPTINFO_ITEM_KIND_SYMTAB_NODE, loc,
+ auto item
+ = std::make_unique<optinfo_item> (optinfo_item::kind::symtab_node, loc,
xstrdup (node->dump_name ()));
return item;
}
@@ -1011,8 +1011,9 @@ emit_any_pending_textual_chunks ()
return;
char *formatted_text = xstrdup (pp_formatted_text (pp));
- std::unique_ptr<optinfo_item> item
- = std::make_unique<optinfo_item> (OPTINFO_ITEM_KIND_TEXT, UNKNOWN_LOCATION,
+ auto item
+ = std::make_unique<optinfo_item> (optinfo_item::kind::text,
+ UNKNOWN_LOCATION,
formatted_text);
pp->emit_item (std::move (item), m_optinfo);
@@ -1084,7 +1085,8 @@ make_item_for_dump_dec (const poly_int<N, C> &value)
}
auto item
- = std::make_unique<optinfo_item> (OPTINFO_ITEM_KIND_TEXT, UNKNOWN_LOCATION,
+ = std::make_unique<optinfo_item> (optinfo_item::kind::text,
+ UNKNOWN_LOCATION,
xstrdup (pp_formatted_text (&pp)));
return item;
}
@@ -1162,8 +1164,9 @@ dump_context::begin_scope (const char *name,
pretty_printer pp;
pp_printf (&pp, "%s %s %s", "===", name, "===");
pp_newline (&pp);
- std::unique_ptr<optinfo_item> item
- = std::make_unique<optinfo_item> (OPTINFO_ITEM_KIND_TEXT, UNKNOWN_LOCATION,
+ auto item
+ = std::make_unique<optinfo_item> (optinfo_item::kind::text,
+ UNKNOWN_LOCATION,
xstrdup (pp_formatted_text (&pp)));
emit_item (*item.get (), MSG_NOTE);
@@ -1172,7 +1175,7 @@ dump_context::begin_scope (const char *name,
optinfo &info
= begin_next_optinfo (dump_metadata_t (MSG_NOTE, impl_location),
user_location);
- info.m_kind = OPTINFO_KIND_SCOPE;
+ info.m_kind = optinfo::kind::scope;
info.add_item (std::move (item));
end_any_optinfo ();
}
@@ -1221,7 +1224,7 @@ dump_context::begin_next_optinfo (const dump_metadata_t &metadata,
end_any_optinfo ();
gcc_assert (m_pending == NULL);
dump_location_t loc (user_loc, metadata.get_impl_location ());
- m_pending = new optinfo (loc, OPTINFO_KIND_NOTE, current_pass);
+ m_pending = new optinfo (loc, optinfo::kind::note, current_pass);
m_pending->handle_dump_file_kind (metadata.get_dump_flags ());
return *m_pending;
}
@@ -2265,7 +2268,7 @@ verify_dumped_text (const location &loc,
void
verify_item (const location &loc,
const optinfo_item *item,
- enum optinfo_item_kind expected_kind,
+ enum optinfo_item::kind expected_kind,
location_t expected_location,
const char *expected_text)
{
@@ -2324,7 +2327,7 @@ test_capture_of_dump_calls (const line_table_case &case_)
{
optinfo *info = tmp.get_pending_optinfo ();
ASSERT_TRUE (info != NULL);
- ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
+ ASSERT_EQ (info->get_kind (), optinfo::kind::note);
ASSERT_EQ (info->num_items (), 1);
ASSERT_IS_TEXT (info->get_item (0), "int: 42 str: foo");
ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
@@ -2345,7 +2348,7 @@ test_capture_of_dump_calls (const line_table_case &case_)
{
optinfo *info = tmp.get_pending_optinfo ();
ASSERT_TRUE (info != NULL);
- ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
+ ASSERT_EQ (info->get_kind (), optinfo::kind::note);
ASSERT_EQ (info->num_items (), 2);
ASSERT_IS_TEXT (info->get_item (0), "tree: ");
ASSERT_IS_TREE (info->get_item (1), UNKNOWN_LOCATION, "0");
@@ -2367,7 +2370,7 @@ test_capture_of_dump_calls (const line_table_case &case_)
{
optinfo *info = tmp.get_pending_optinfo ();
ASSERT_TRUE (info != NULL);
- ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
+ ASSERT_EQ (info->get_kind (), optinfo::kind::note);
ASSERT_EQ (info->num_items (), 2);
ASSERT_IS_TEXT (info->get_item (0), "gimple: ");
ASSERT_IS_GIMPLE (info->get_item (1), stmt_loc, "return;");
@@ -2389,7 +2392,7 @@ test_capture_of_dump_calls (const line_table_case &case_)
{
optinfo *info = tmp.get_pending_optinfo ();
ASSERT_TRUE (info != NULL);
- ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
+ ASSERT_EQ (info->get_kind (), optinfo::kind::note);
ASSERT_EQ (info->num_items (), 2);
ASSERT_IS_TEXT (info->get_item (0), "gimple: ");
ASSERT_IS_GIMPLE (info->get_item (1), stmt_loc, "return;\n");
@@ -2411,7 +2414,7 @@ test_capture_of_dump_calls (const line_table_case &case_)
{
optinfo *info = tmp.get_pending_optinfo ();
ASSERT_TRUE (info != NULL);
- ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
+ ASSERT_EQ (info->get_kind (), optinfo::kind::note);
ASSERT_EQ (info->num_items (), 2);
ASSERT_IS_TEXT (info->get_item (0), "node: ");
ASSERT_IS_SYMTAB_NODE (info->get_item (1), decl_loc, "test_decl/1");
@@ -2441,7 +2444,7 @@ test_capture_of_dump_calls (const line_table_case &case_)
{
optinfo *info = tmp.get_pending_optinfo ();
ASSERT_TRUE (info != NULL);
- ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
+ ASSERT_EQ (info->get_kind (), optinfo::kind::note);
ASSERT_EQ (info->num_items (), 8);
ASSERT_IS_TEXT (info->get_item (0), "before ");
ASSERT_IS_TREE (info->get_item (1), UNKNOWN_LOCATION, "0");
@@ -2471,7 +2474,7 @@ test_capture_of_dump_calls (const line_table_case &case_)
optinfo *info = tmp.get_pending_optinfo ();
ASSERT_TRUE (info != NULL);
ASSERT_EQ (info->get_location_t (), stmt_loc);
- ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
+ ASSERT_EQ (info->get_kind (), optinfo::kind::note);
ASSERT_EQ (info->num_items (), 2);
ASSERT_IS_TEXT (info->get_item (0), "test of tree: ");
ASSERT_IS_TREE (info->get_item (1), UNKNOWN_LOCATION, "0");
@@ -2494,7 +2497,7 @@ test_capture_of_dump_calls (const line_table_case &case_)
optinfo *info = tmp.get_pending_optinfo ();
ASSERT_TRUE (info != NULL);
ASSERT_EQ (info->get_location_t (), stmt_loc);
- ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
+ ASSERT_EQ (info->get_kind (), optinfo::kind::note);
ASSERT_EQ (info->num_items (), 1);
ASSERT_IS_TREE (info->get_item (0), UNKNOWN_LOCATION, "1");
ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
@@ -2598,7 +2601,7 @@ test_capture_of_dump_calls (const line_table_case &case_)
{
optinfo *info = tmp.get_pending_optinfo ();
ASSERT_TRUE (info != NULL);
- ASSERT_EQ (info->get_kind (), OPTINFO_KIND_NOTE);
+ ASSERT_EQ (info->get_kind (), optinfo::kind::note);
ASSERT_EQ (info->num_items (), 1);
ASSERT_IS_SYMTAB_NODE (info->get_item (0), decl_loc, "test_decl/1");
ASSERT_IMPL_LOCATION_EQ (info->get_impl_location (),
@@ -2727,7 +2730,7 @@ test_capture_of_dump_calls (const line_table_case &case_)
temp_dump_context tmp (true, true, MSG_ALL_KINDS);
dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc, "test");
ASSERT_EQ (tmp.get_pending_optinfo ()->get_kind (),
- OPTINFO_KIND_SUCCESS);
+ optinfo::kind::success);
}
/* MSG_MISSED_OPTIMIZATION. */
@@ -2735,7 +2738,7 @@ test_capture_of_dump_calls (const line_table_case &case_)
temp_dump_context tmp (true, true, MSG_ALL_KINDS);
dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc, "test");
ASSERT_EQ (tmp.get_pending_optinfo ()->get_kind (),
- OPTINFO_KIND_FAILURE);
+ optinfo::kind::failure);
}
}
diff --git a/gcc/explow.cc b/gcc/explow.cc
index 7799a98..8f8ca7f 100644
--- a/gcc/explow.cc
+++ b/gcc/explow.cc
@@ -854,6 +854,18 @@ promote_function_mode (const_tree type, machine_mode mode, int *punsignedp,
switch (TREE_CODE (type))
{
+ case BITINT_TYPE:
+ if (TYPE_MODE (type) == BLKmode)
+ return mode;
+
+ struct bitint_info info;
+ bool ok;
+ ok = targetm.c.bitint_type_info (TYPE_PRECISION (type), &info);
+ gcc_assert (ok);
+
+ if (!info.extended)
+ return mode;
+ /* FALLTHRU */
case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
case REAL_TYPE: case OFFSET_TYPE: case FIXED_POINT_TYPE:
case POINTER_TYPE: case REFERENCE_TYPE:
@@ -893,6 +905,18 @@ promote_mode (const_tree type ATTRIBUTE_UNUSED, machine_mode mode,
switch (code)
{
+ case BITINT_TYPE:
+ if (TYPE_MODE (type) == BLKmode)
+ return mode;
+
+ struct bitint_info info;
+ bool ok;
+ ok = targetm.c.bitint_type_info (TYPE_PRECISION (type), &info);
+ gcc_assert (ok);
+
+ if (!info.extended)
+ return mode;
+ /* FALLTHRU */
case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
case REAL_TYPE: case OFFSET_TYPE: case FIXED_POINT_TYPE:
/* Values of these types always have scalar mode. */
diff --git a/gcc/expr.cc b/gcc/expr.cc
index 3f2b121..3d2b253 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -76,6 +76,10 @@ along with GCC; see the file COPYING3. If not see
the same indirect address eventually. */
int cse_not_expected;
+/* Cache of the "extended" flag in the target's _BitInt description
+ for use during expand. */
+int bitint_extended = -1;
+
static bool block_move_libcall_safe_for_call_parm (void);
static bool emit_block_move_via_pattern (rtx, rtx, rtx, unsigned, unsigned,
HOST_WIDE_INT, unsigned HOST_WIDE_INT,
@@ -11280,6 +11284,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
when reading from SSA_NAMEs of vars. */
#define EXTEND_BITINT(expr) \
((TREE_CODE (type) == BITINT_TYPE \
+ && !bitint_extended \
&& reduce_bit_field \
&& mode != BLKmode \
&& modifier != EXPAND_MEMORY \
@@ -11291,6 +11296,13 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
type = TREE_TYPE (exp);
mode = TYPE_MODE (type);
unsignedp = TYPE_UNSIGNED (type);
+ if (TREE_CODE (type) == BITINT_TYPE && bitint_extended == -1)
+ {
+ struct bitint_info info;
+ bool ok = targetm.c.bitint_type_info (TYPE_PRECISION (type), &info);
+ gcc_assert (ok);
+ bitint_extended = info.extended;
+ }
treeop0 = treeop1 = treeop2 = NULL_TREE;
if (!VL_EXP_CLASS_P (exp))
diff --git a/gcc/expr.h b/gcc/expr.h
index 53ab625..060151d 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -388,4 +388,8 @@ extern void expand_crc_table_based (rtx, rtx, rtx, rtx, machine_mode);
extern void expand_reversed_crc_table_based (rtx, rtx, rtx, rtx, machine_mode,
void (*) (rtx *));
+/* Cache of the "extended" flag in the target's _BitInt description
+ for use during expand. */
+extern int bitint_extended;
+
#endif /* GCC_EXPR_H */
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index d75d64f..20e4a76 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,68 @@
+2025-08-05 Mikael Morin <morin-mikael@orange.fr>
+
+ * trans-stmt.cc (trans_associate_var): Remove overwrite of
+ the polymorphic associate variable's array descriptor offset.
+
+2025-08-05 Mikael Morin <morin-mikael@orange.fr>
+
+ * trans-array.cc (trans_array_constructor): Remove the update of
+ the array descriptor upper bound after array constructor
+ expansion.
+
+2025-08-05 Mikael Morin <morin-mikael@orange.fr>
+
+ * trans-array.cc (gfc_conv_expr_descriptor): Remove
+ isolated initialization of the span field before passing to
+ the function that will do the initialization.
+
+2025-08-05 Mikael Morin <morin-mikael@orange.fr>
+
+ * trans-decl.cc (gfc_trans_deferred_vars): Don't default
+ initialize the span of local pointer arrays.
+
+2025-08-05 Mikael Morin <morin-mikael@orange.fr>
+
+ * trans-stmt.cc (trans_associate_var): Remove overwrite of the
+ span field of the associate variable's array descriptor.
+
+2025-08-05 Mikael Morin <morin-mikael@orange.fr>
+
+ * trans-expr.cc (gfc_trans_pointer_assignment): Remove overwrite
+ of the span after assignment of the array descriptor in the
+ polymorphic function result to non-polymorphic pointer case.
+
+2025-08-05 Mikael Morin <mikael@gcc.gnu.org>
+
+ * trans.h (gfc_se): Remove field use_offset.
+ * trans-expr.cc (gfc_conv_intrinsic_to_class): Remove use_offset
+ initialization.
+ (gfc_conv_procedure_call): Likewise.
+ * trans-stmt.cc (trans_associate_var): Likewise.
+
+2025-08-05 Mikael Morin <mikael@gcc.gnu.org>
+
+ * trans-array.cc (gfc_alloc_allocatable_for_assignment): Use the
+ offset setter instead of generating a write to the offset.
+ (gfc_conv_array_parameter): Use the offset setter instead of
+ generating a write to the value returned by the offset getter.
+ * trans-expr.cc (gfc_trans_alloc_subarray_assign): Likewise.
+
+2025-08-05 Mikael Morin <mikael@gcc.gnu.org>
+
+ * trans-array.cc (gfc_conv_descriptor_data_addr): Remove.
+ * trans-array.h (gfc_conv_descriptor_data_addr): Remove.
+ * trans-decl.cc (gfc_trans_deferred_vars): Use
+ gfc_conv_descriptor_data_get.
+
+2025-08-05 Mikael Morin <mikael@gcc.gnu.org>
+
+ * trans.cc (gfc_finalize_tree_expr): Use the data setter instead
+ of writing to the value returned by the data getter.
+ * trans-decl.cc (gfc_trans_deferred_vars): Likewise.
+ * trans-stmt.cc (trans_associate_var): Use the data setter
+ instead of writing to the value dereferenced from the data
+ address.
+
2025-08-01 Mikael Morin <mikael@gcc.gnu.org>
* trans-decl.cc (gfc_trans_deferred_vars): Fix closing brace in
diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 990aaaf..7e6437b 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -284,16 +284,6 @@ gfc_conv_descriptor_data_set (stmtblock_t *block, tree desc, tree value)
}
-/* This provides address access to the data field. This should only be
- used by array allocation, passing this on to the runtime. */
-
-tree
-gfc_conv_descriptor_data_addr (tree desc)
-{
- tree field = gfc_get_descriptor_field (desc, DATA_FIELD);
- return gfc_build_addr_expr (NULL_TREE, field);
-}
-
static tree
gfc_conv_descriptor_offset (tree desc)
{
@@ -3115,7 +3105,6 @@ trans_array_constructor (gfc_ss * ss, locus * where)
gfc_array_index_type,
offsetvar, gfc_index_one_node);
tmp = gfc_evaluate_now (tmp, &outer_loop->pre);
- gfc_conv_descriptor_ubound_set (&loop->pre, desc, gfc_rank_cst[0], tmp);
if (*loop_ubound0 && VAR_P (*loop_ubound0))
gfc_add_modify (&outer_loop->pre, *loop_ubound0, tmp);
else
@@ -8509,14 +8498,6 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
else
gcc_assert (se->ss == ss);
- if (!is_pointer_array (se->expr))
- {
- tmp = gfc_get_element_type (TREE_TYPE (se->expr));
- tmp = fold_convert (gfc_array_index_type,
- size_in_bytes (tmp));
- gfc_conv_descriptor_span_set (&se->pre, se->expr, tmp);
- }
-
se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
gfc_conv_expr (se, expr);
@@ -9588,9 +9569,8 @@ gfc_conv_array_parameter (gfc_se *se, gfc_expr *expr, bool g77,
new_field = gfc_conv_descriptor_dtype (new_desc);
gfc_add_modify (&se->pre, new_field, old_field);
- old_field = gfc_conv_descriptor_offset (old_desc);
- new_field = gfc_conv_descriptor_offset (new_desc);
- gfc_add_modify (&se->pre, new_field, old_field);
+ old_field = gfc_conv_descriptor_offset_get (old_desc);
+ gfc_conv_descriptor_offset_set (&se->pre, new_desc, old_field);
for (int i = 0; i < expr->rank; i++)
{
@@ -11760,8 +11740,8 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
gfc_index_zero_node);
}
- tmp = gfc_conv_descriptor_offset (desc);
- gfc_add_modify (&loop_pre_block, tmp, gfc_index_zero_node);
+ gfc_conv_descriptor_offset_set (&loop_pre_block, desc,
+ gfc_index_zero_node);
tmp = fold_build2_loc (input_location, EQ_EXPR,
logical_type_node, array1,
diff --git a/gcc/fortran/trans-array.h b/gcc/fortran/trans-array.h
index 29098fd..345a975 100644
--- a/gcc/fortran/trans-array.h
+++ b/gcc/fortran/trans-array.h
@@ -173,7 +173,6 @@ void gfc_get_descriptor_offsets_for_info (const_tree, tree *, tree *, tree *, tr
tree *, tree *, tree *, tree *);
tree gfc_conv_descriptor_data_get (tree);
-tree gfc_conv_descriptor_data_addr (tree);
tree gfc_conv_descriptor_offset_get (tree);
tree gfc_conv_descriptor_span_get (tree);
tree gfc_conv_descriptor_dtype (tree);
diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc
index 3b49b18..8992dbc 100644
--- a/gcc/fortran/trans-decl.cc
+++ b/gcc/fortran/trans-decl.cc
@@ -4936,20 +4936,6 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
}
}
- if (sym->attr.pointer && sym->attr.dimension
- && sym->attr.save == SAVE_NONE
- && !sym->attr.use_assoc
- && !sym->attr.host_assoc
- && !sym->attr.dummy
- && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (sym->backend_decl)))
- {
- gfc_init_block (&tmpblock);
- gfc_conv_descriptor_span_set (&tmpblock, sym->backend_decl,
- build_int_cst (gfc_array_index_type, 0));
- gfc_add_init_cleanup (block, gfc_finish_block (&tmpblock),
- NULL_TREE);
- }
-
if (sym->ts.type == BT_CLASS
&& (sym->attr.save || flag_max_stack_var_size == 0)
&& CLASS_DATA (sym)->attr.allocatable)
@@ -5148,18 +5134,31 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
se.descriptor_only = 1;
gfc_conv_expr (&se, e);
descriptor = se.expr;
- se.expr = gfc_conv_descriptor_data_addr (se.expr);
- se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
+ se.expr = gfc_conv_descriptor_data_get (se.expr);
}
gfc_free_expr (e);
if (!sym->attr.dummy || sym->attr.intent == INTENT_OUT)
{
/* Nullify when entering the scope. */
- tmp = fold_build2_loc (input_location, MODIFY_EXPR,
- TREE_TYPE (se.expr), se.expr,
- fold_convert (TREE_TYPE (se.expr),
- null_pointer_node));
+ if (sym->ts.type == BT_CLASS
+ && (CLASS_DATA (sym)->attr.dimension
+ || CLASS_DATA (sym)->attr.codimension))
+ {
+ stmtblock_t nullify;
+ gfc_init_block (&nullify);
+ gfc_conv_descriptor_data_set (&nullify, descriptor,
+ null_pointer_node);
+ tmp = gfc_finish_block (&nullify);
+ }
+ else
+ {
+ tree typed_null = fold_convert (TREE_TYPE (se.expr),
+ null_pointer_node);
+ tmp = fold_build2_loc (input_location, MODIFY_EXPR,
+ TREE_TYPE (se.expr), se.expr,
+ typed_null);
+ }
if (sym->attr.optional)
{
tree present = gfc_conv_expr_present (sym);
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index ec24084..69952b3 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -1168,7 +1168,6 @@ gfc_conv_intrinsic_to_class (gfc_se *parmse, gfc_expr *e,
else
{
parmse->ss = ss;
- parmse->use_offset = 1;
gfc_conv_expr_descriptor (parmse, e);
/* Array references with vector subscripts and non-variable expressions
@@ -7542,7 +7541,6 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
|| CLASS_DATA (fsym)->attr.codimension))
{
/* Pass a class array. */
- parmse.use_offset = 1;
gfc_conv_expr_descriptor (&parmse, e);
bool defer_to_dealloc_blk = false;
@@ -9583,8 +9581,8 @@ gfc_trans_alloc_subarray_assign (tree dest, gfc_component * cm,
/* Shift the lbound and ubound of temporaries to being unity,
rather than zero, based. Always calculate the offset. */
+ gfc_conv_descriptor_offset_set (&block, dest, gfc_index_zero_node);
offset = gfc_conv_descriptor_offset_get (dest);
- gfc_add_modify (&block, offset, gfc_index_zero_node);
tmp2 =gfc_create_var (gfc_array_index_type, NULL);
for (n = 0; n < expr->rank; n++)
@@ -11148,11 +11146,6 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2)
{
rse.expr = gfc_class_data_get (rse.expr);
gfc_add_modify (&lse.pre, desc, rse.expr);
- /* Set the lhs span. */
- tmp = TREE_TYPE (rse.expr);
- tmp = TYPE_SIZE_UNIT (gfc_get_element_type (tmp));
- tmp = fold_convert (gfc_array_index_type, tmp);
- gfc_conv_descriptor_span_set (&lse.pre, desc, tmp);
}
else
{
diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc
index b4ddf75..f4e6c57 100644
--- a/gcc/fortran/trans-stmt.cc
+++ b/gcc/fortran/trans-stmt.cc
@@ -1876,9 +1876,6 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
bool class_target;
bool unlimited;
tree desc;
- tree offset;
- tree dim;
- int n;
tree charlen;
bool need_len_assign;
bool whole_array = true;
@@ -2116,7 +2113,6 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
if (sym->assoc->variable || cst_array_ctor)
{
se.direct_byref = 1;
- se.use_offset = 1;
se.expr = desc;
GFC_DECL_PTR_ARRAY_P (sym->backend_decl) = 1;
}
@@ -2183,16 +2179,6 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
dim, gfc_index_one_node);
}
- /* If this is a subreference array pointer associate name use the
- associate variable element size for the value of 'span'. */
- if (sym->attr.subref_array_pointer && !se.direct_byref)
- {
- gcc_assert (e->expr_type == EXPR_VARIABLE);
- tmp = gfc_get_array_span (se.expr, e);
-
- gfc_conv_descriptor_span_set (&se.pre, desc, tmp);
- }
-
if (e->expr_type == EXPR_FUNCTION
&& sym->ts.type == BT_DERIVED
&& sym->ts.u.derived
@@ -2303,21 +2289,6 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
desc = gfc_class_data_get (se.expr);
- /* Set the offset. */
- offset = gfc_index_zero_node;
- for (n = 0; n < e->rank; n++)
- {
- dim = gfc_rank_cst[n];
- tmp = fold_build2_loc (input_location, MULT_EXPR,
- gfc_array_index_type,
- gfc_conv_descriptor_stride_get (desc, dim),
- gfc_conv_descriptor_lbound_get (desc, dim));
- offset = fold_build2_loc (input_location, MINUS_EXPR,
- gfc_array_index_type,
- offset, tmp);
- }
- gfc_conv_descriptor_offset_set (&se.pre, desc, offset);
-
if (need_len_assign)
{
if (e->symtree
@@ -2494,9 +2465,10 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
{
tmp = sym->backend_decl;
if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)))
- tmp = gfc_conv_descriptor_data_get (tmp);
- gfc_add_modify (&se.pre, tmp, fold_convert (TREE_TYPE (tmp),
- null_pointer_node));
+ gfc_conv_descriptor_data_set (&se.pre, tmp, null_pointer_node);
+ else
+ gfc_add_modify (&se.pre, tmp,
+ fold_convert (TREE_TYPE (tmp), null_pointer_node));
}
lhs = gfc_lval_expr_from_sym (sym);
diff --git a/gcc/fortran/trans.cc b/gcc/fortran/trans.cc
index 13fd5ad..47396c3 100644
--- a/gcc/fortran/trans.cc
+++ b/gcc/fortran/trans.cc
@@ -1740,7 +1740,7 @@ gfc_finalize_tree_expr (gfc_se *se, gfc_symbol *derived,
gfc_call_free (data_ptr),
build_empty_stmt (input_location));
gfc_add_expr_to_block (&se->loop->post, tmp);
- gfc_add_modify (&se->loop->post, data_ptr, data_null);
+ gfc_conv_descriptor_data_set (&se->loop->post, desc, data_null);
}
else
{
@@ -1754,7 +1754,7 @@ gfc_finalize_tree_expr (gfc_se *se, gfc_symbol *derived,
gfc_call_free (data_ptr),
build_empty_stmt (input_location));
gfc_add_expr_to_block (&se->finalblock, tmp);
- gfc_add_modify (&se->finalblock, data_ptr, data_null);
+ gfc_conv_descriptor_data_set (&se->finalblock, desc, data_null);
}
}
}
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index 40680e9..5554184 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -105,10 +105,6 @@ typedef struct gfc_se
/* If set, will pass subref descriptors without a temporary. */
unsigned force_no_tmp:1;
- /* Unconditionally calculate offset for array segments and constant
- arrays in gfc_conv_expr_descriptor. */
- unsigned use_offset:1;
-
unsigned want_coarray:1;
/* Scalarization parameters. */
diff --git a/gcc/function.cc b/gcc/function.cc
index 2b77bbd..5a054a9 100644
--- a/gcc/function.cc
+++ b/gcc/function.cc
@@ -4965,6 +4965,10 @@ prepare_function_start (void)
/* Indicate we have no need of a frame pointer yet. */
frame_pointer_needed = 0;
+
+ /* Reset the cache of the "extended" flag in the target's
+ _BitInt info struct. */
+ bitint_extended = -1;
}
void
diff --git a/gcc/gimple-pretty-print.cc b/gcc/gimple-pretty-print.cc
index 4e20b4c..6929cd0 100644
--- a/gcc/gimple-pretty-print.cc
+++ b/gcc/gimple-pretty-print.cc
@@ -1837,6 +1837,12 @@ dump_gimple_omp_target (pretty_printer *pp, const gomp_target *gs,
default:
gcc_unreachable ();
}
+ if (gimple_omp_target_iterator_loops (gs))
+ {
+ pp_string (pp, "// Expanded iterator loops for #pragma omp target\n");
+ dump_gimple_seq (pp, gimple_omp_target_iterator_loops (gs), spc, flags);
+ pp_newline (pp);
+ }
if (flags & TDF_RAW)
{
dump_gimple_fmt (pp, spc, flags, "%G%s <%+BODY <%S>%nCLAUSES <", gs,
diff --git a/gcc/gimple-warn-recursion.cc b/gcc/gimple-warn-recursion.cc
index e6a0c4c..d061e7e 100644
--- a/gcc/gimple-warn-recursion.cc
+++ b/gcc/gimple-warn-recursion.cc
@@ -190,6 +190,7 @@ pass_warn_recursion::execute (function *func)
if (find_function_exit (entry_bb) || m_calls->length () == 0)
return 0;
+ auto_diagnostic_group d;
if (warning_at (DECL_SOURCE_LOCATION (func->decl),
OPT_Winfinite_recursion,
"infinite recursion detected"))
diff --git a/gcc/gimple.cc b/gcc/gimple.cc
index 41908d4..102e21f 100644
--- a/gcc/gimple.cc
+++ b/gcc/gimple.cc
@@ -1295,10 +1295,13 @@ gimple_build_omp_interop (tree clauses)
BODY is the sequence of statements that will be executed.
KIND is the kind of the region.
- CLAUSES are any of the construct's clauses. */
+ CLAUSES are any of the construct's clauses.
+ ITERATOR_LOOPS is an optional sequence containing constructed loops
+ for OpenMP iterators. */
gomp_target *
-gimple_build_omp_target (gimple_seq body, int kind, tree clauses)
+gimple_build_omp_target (gimple_seq body, int kind, tree clauses,
+ gimple_seq iterator_loops)
{
gomp_target *p
= as_a <gomp_target *> (gimple_alloc (GIMPLE_OMP_TARGET, 0));
@@ -1306,6 +1309,7 @@ gimple_build_omp_target (gimple_seq body, int kind, tree clauses)
gimple_omp_set_body (p, body);
gimple_omp_target_set_clauses (p, clauses);
gimple_omp_target_set_kind (p, kind);
+ gimple_omp_target_set_iterator_loops (p, iterator_loops);
return p;
}
diff --git a/gcc/gimple.def b/gcc/gimple.def
index 54248a8..3e1e13e 100644
--- a/gcc/gimple.def
+++ b/gcc/gimple.def
@@ -393,7 +393,7 @@ DEFGSCODE(GIMPLE_OMP_SINGLE, "gimple_omp_single", GSS_OMP_SINGLE_LAYOUT)
DATA_ARG is a vec of 3 local variables in the parent function
containing data to be mapped to CHILD_FN. This is used to
implement the MAP clauses. */
-DEFGSCODE(GIMPLE_OMP_TARGET, "gimple_omp_target", GSS_OMP_PARALLEL_LAYOUT)
+DEFGSCODE(GIMPLE_OMP_TARGET, "gimple_omp_target", GSS_OMP_TARGET)
/* GIMPLE_OMP_TEAMS <BODY, CLAUSES, CHILD_FN, DATA_ARG> represents
#pragma omp teams
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 5c970ce..da32651 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -682,11 +682,14 @@ struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT")))
};
/* GIMPLE_OMP_TARGET */
-struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT")))
+struct GTY((tag("GSS_OMP_TARGET")))
gomp_target : public gimple_statement_omp_parallel_layout
{
- /* No extra fields; adds invariant:
- stmt->code == GIMPLE_OMP_TARGET. */
+ /* [ WORD 1-10 ] : base class */
+
+ /* [ WORD 11 ]
+ Iterator loops. */
+ gimple_seq iterator_loops;
};
/* GIMPLE_OMP_TASK */
@@ -1607,7 +1610,7 @@ gomp_scan *gimple_build_omp_scan (gimple_seq, tree);
gomp_sections *gimple_build_omp_sections (gimple_seq, tree);
gimple *gimple_build_omp_sections_switch (void);
gomp_single *gimple_build_omp_single (gimple_seq, tree);
-gomp_target *gimple_build_omp_target (gimple_seq, int, tree);
+gomp_target *gimple_build_omp_target (gimple_seq, int, tree, gimple_seq = NULL);
gomp_teams *gimple_build_omp_teams (gimple_seq, tree);
gomp_atomic_load *gimple_build_omp_atomic_load (tree, tree,
enum omp_memory_order);
@@ -6380,6 +6383,38 @@ gimple_omp_target_set_data_arg (gomp_target *omp_target_stmt,
}
+/* Return the Gimple sequence used to store loops for OpenMP iterators used
+ by OMP_TARGET_STMT. */
+
+inline gimple_seq
+gimple_omp_target_iterator_loops (const gomp_target *omp_target_stmt)
+{
+ return omp_target_stmt->iterator_loops;
+}
+
+
+/* Return a pointer to the Gimple sequence used to store loops for OpenMP
+ iterators used by OMP_TARGET GS. */
+
+inline gimple_seq *
+gimple_omp_target_iterator_loops_ptr (gimple *gs)
+{
+ gomp_target *omp_target_stmt = as_a <gomp_target *> (gs);
+ return &omp_target_stmt->iterator_loops;
+}
+
+
+/* Set ITERATOR_LOOPS to be the Gimple sequence used to store loops
+ constructed for OpenMP iterators in OMP_TARGET_STMT. */
+
+inline void
+gimple_omp_target_set_iterator_loops (gomp_target *omp_target_stmt,
+ gimple_seq iterator_loops)
+{
+ omp_target_stmt->iterator_loops = iterator_loops;
+}
+
+
/* Return the clauses associated with OMP_TEAMS GS. */
inline tree
diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index fbf47dd..ca1fa21 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -9891,6 +9891,373 @@ build_omp_iterator_loop (tree it, gimple_seq *pre_p, tree *last_bind)
return p;
}
+
+/* Callback for walk_tree to find a VAR_DECL (stored in DATA) in the
+ tree TP. */
+
+static tree
+find_var_decl (tree *tp, int *, void *data)
+{
+ if (*tp == (tree) data)
+ return *tp;
+
+ return NULL_TREE;
+}
+
+/* Returns an element-by-element copy of OMP iterator tree IT. */
+
+static tree
+copy_omp_iterator (tree it, int elem_count = -1)
+{
+ if (elem_count < 0)
+ elem_count = TREE_VEC_LENGTH (it);
+ tree new_it = make_tree_vec (elem_count);
+ for (int i = 0; i < TREE_VEC_LENGTH (it); i++)
+ TREE_VEC_ELT (new_it, i) = TREE_VEC_ELT (it, i);
+
+ return new_it;
+}
+
+/* Helper function for walk_tree in remap_omp_iterator_var. */
+
+static tree
+remap_omp_iterator_var_1 (tree *tp, int *, void *data)
+{
+ tree old_var = ((tree *) data)[0];
+ tree new_var = ((tree *) data)[1];
+
+ if (*tp == old_var)
+ *tp = new_var;
+ return NULL_TREE;
+}
+
+/* Replace instances of OLD_VAR in TP with NEW_VAR. */
+
+static void
+remap_omp_iterator_var (tree *tp, tree old_var, tree new_var)
+{
+ tree vars[2] = { old_var, new_var };
+ walk_tree (tp, remap_omp_iterator_var_1, vars, NULL);
+}
+
+/* Scan through all clauses using OpenMP iterators in LIST_P. If any
+ clauses have iterators with variables that are not used by the clause
+ decl or size, issue a warning and replace the iterator with a copy with
+ the unused variables removed. */
+
+static void
+remove_unused_omp_iterator_vars (tree *list_p)
+{
+ auto_vec< vec<tree> > iter_vars;
+ auto_vec<tree> new_iterators;
+
+ for (tree c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
+ {
+ if (!OMP_CLAUSE_HAS_ITERATORS (c))
+ continue;
+ auto_vec<tree> vars;
+ bool need_new_iterators = false;
+ for (tree it = OMP_CLAUSE_ITERATORS (c); it; it = TREE_CHAIN (it))
+ {
+ tree var = TREE_VEC_ELT (it, 0);
+ tree t = walk_tree (&OMP_CLAUSE_DECL (c), find_var_decl, var, NULL);
+ if (t == NULL_TREE)
+ t = walk_tree (&OMP_CLAUSE_SIZE (c), find_var_decl, var, NULL);
+ if (t == NULL_TREE)
+ {
+ need_new_iterators = true;
+ if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FROM))
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM)
+ warning_at (OMP_CLAUSE_LOCATION (c), OPT_Wopenmp,
+ "iterator variable %qE not used in clause "
+ "expression", DECL_NAME (var));
+ }
+ else
+ vars.safe_push (var);
+ }
+ if (!need_new_iterators)
+ continue;
+ if (need_new_iterators && vars.is_empty ())
+ {
+ /* No iteration variables are used in the clause - remove the
+ iterator from the clause. */
+ OMP_CLAUSE_ITERATORS (c) = NULL_TREE;
+ continue;
+ }
+
+ /* If a new iterator has been created for the current set of used
+ iterator variables, then use that as the iterator. Otherwise,
+ create a new iterator for the current iterator variable set. */
+ unsigned i;
+ for (i = 0; i < iter_vars.length (); i++)
+ {
+ if (vars.length () != iter_vars[i].length ())
+ continue;
+ bool identical_p = true;
+ for (unsigned j = 0; j < vars.length () && identical_p; j++)
+ identical_p = vars[j] == iter_vars[i][j];
+
+ if (identical_p)
+ break;
+ }
+ if (i < iter_vars.length ())
+ OMP_CLAUSE_ITERATORS (c) = new_iterators[i];
+ else
+ {
+ tree new_iters = NULL_TREE;
+ tree *new_iters_p = &new_iters;
+ tree new_vars = NULL_TREE;
+ tree *new_vars_p = &new_vars;
+ i = 0;
+ for (tree it = OMP_CLAUSE_ITERATORS (c); it && i < vars.length();
+ it = TREE_CHAIN (it))
+ {
+ tree var = TREE_VEC_ELT (it, 0);
+ if (var == vars[i])
+ {
+ *new_iters_p = copy_omp_iterator (it);
+ *new_vars_p = build_decl (OMP_CLAUSE_LOCATION (c), VAR_DECL,
+ DECL_NAME (var), TREE_TYPE (var));
+ DECL_ARTIFICIAL (*new_vars_p) = 1;
+ DECL_CONTEXT (*new_vars_p) = DECL_CONTEXT (var);
+ TREE_VEC_ELT (*new_iters_p, 0) = *new_vars_p;
+ new_iters_p = &TREE_CHAIN (*new_iters_p);
+ new_vars_p = &DECL_CHAIN (*new_vars_p);
+ i++;
+ }
+ }
+ tree new_block = make_node (BLOCK);
+ BLOCK_VARS (new_block) = new_vars;
+ TREE_VEC_ELT (new_iters, 5) = new_block;
+ new_iterators.safe_push (new_iters);
+ iter_vars.safe_push (vars.copy ());
+ OMP_CLAUSE_ITERATORS (c) = new_iters;
+ }
+
+ /* Remap clause to use the new variables. */
+ i = 0;
+ for (tree it = OMP_CLAUSE_ITERATORS (c); it; it = TREE_CHAIN (it))
+ {
+ tree old_var = vars[i++];
+ tree new_var = TREE_VEC_ELT (it, 0);
+ remap_omp_iterator_var (&OMP_CLAUSE_DECL (c), old_var, new_var);
+ remap_omp_iterator_var (&OMP_CLAUSE_SIZE (c), old_var, new_var);
+ }
+ }
+
+ for (unsigned i = 0; i < iter_vars.length (); i++)
+ iter_vars[i].release ();
+}
+
+struct iterator_loop_info_t
+{
+ tree bind;
+ tree count;
+ tree index;
+ tree body_label;
+ auto_vec<tree> clauses;
+};
+
+typedef hash_map<tree, iterator_loop_info_t> iterator_loop_info_map_t;
+
+/* Builds a loop to expand any OpenMP iterators in the clauses in LIST_P,
+ reusing any previously built loops if they use the same set of iterators.
+ Generated Gimple statements are placed into LOOPS_SEQ_P. The clause
+ iterators are updated with information on how and where to insert code into
+ the loop body. */
+
+static void
+build_omp_iterators_loops (tree *list_p, gimple_seq *loops_seq_p)
+{
+ iterator_loop_info_map_t loops;
+
+ for (tree c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
+ {
+ if (!OMP_CLAUSE_HAS_ITERATORS (c))
+ continue;
+
+ bool built_p;
+ iterator_loop_info_t &loop
+ = loops.get_or_insert (OMP_CLAUSE_ITERATORS (c), &built_p);
+
+ if (!built_p)
+ {
+ loop.count = compute_omp_iterator_count (OMP_CLAUSE_ITERATORS (c),
+ loops_seq_p);
+ if (!loop.count)
+ continue;
+ if (integer_zerop (loop.count))
+ warning_at (OMP_CLAUSE_LOCATION (c), OPT_Wopenmp,
+ "iteration count is zero");
+
+ loop.bind = NULL_TREE;
+ tree *body = build_omp_iterator_loop (OMP_CLAUSE_ITERATORS (c),
+ loops_seq_p, &loop.bind);
+
+ loop.index = create_tmp_var (sizetype);
+ SET_EXPR_LOCATION (loop.bind, OMP_CLAUSE_LOCATION (c));
+
+ /* BEFORE LOOP: */
+ /* idx = -1; */
+ /* This should be initialized to before the individual elements,
+ as idx is pre-incremented in the loop body. */
+ gimple *assign = gimple_build_assign (loop.index, size_int (-1));
+ gimple_seq_add_stmt (loops_seq_p, assign);
+
+ /* IN LOOP BODY: */
+ /* Create a label so we can find this point later. */
+ loop.body_label = create_artificial_label (OMP_CLAUSE_LOCATION (c));
+ tree tem = build1 (LABEL_EXPR, void_type_node, loop.body_label);
+ append_to_statement_list_force (tem, body);
+
+ /* idx += 2; */
+ tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
+ void_type_node, loop.index,
+ size_binop (PLUS_EXPR, loop.index, size_int (2)));
+ append_to_statement_list_force (tem, body);
+ }
+
+ /* Create array to hold expanded values. */
+ tree last_count_2 = size_binop (MULT_EXPR, loop.count, size_int (2));
+ tree arr_length = size_binop (PLUS_EXPR, last_count_2, size_int (1));
+ tree elems = NULL_TREE;
+ if (TREE_CONSTANT (arr_length))
+ {
+ tree type = build_array_type (ptr_type_node,
+ build_index_type (arr_length));
+ elems = create_tmp_var_raw (type, "omp_iter_data");
+ TREE_ADDRESSABLE (elems) = 1;
+ gimple_add_tmp_var (elems);
+ }
+ else
+ {
+ /* Handle dynamic sizes. */
+ sorry ("dynamic iterator sizes not implemented yet");
+ }
+
+ /* BEFORE LOOP: */
+ /* elems[0] = count; */
+ tree lhs = build4 (ARRAY_REF, ptr_type_node, elems, size_int (0),
+ NULL_TREE, NULL_TREE);
+ tree tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
+ void_type_node, lhs, loop.count);
+ gimplify_and_add (tem, loops_seq_p);
+
+ /* Make a copy of the iterator with extra info at the end. */
+ int elem_count = TREE_VEC_LENGTH (OMP_CLAUSE_ITERATORS (c));
+ tree new_iterator = copy_omp_iterator (OMP_CLAUSE_ITERATORS (c),
+ elem_count + 3);
+ TREE_VEC_ELT (new_iterator, elem_count) = loop.body_label;
+ TREE_VEC_ELT (new_iterator, elem_count + 1) = elems;
+ TREE_VEC_ELT (new_iterator, elem_count + 2) = loop.index;
+ TREE_CHAIN (new_iterator) = TREE_CHAIN (OMP_CLAUSE_ITERATORS (c));
+ OMP_CLAUSE_ITERATORS (c) = new_iterator;
+
+ loop.clauses.safe_push (c);
+ }
+
+ /* Now gimplify and add all the loops that were built. */
+ for (hash_map<tree, iterator_loop_info_t>::iterator it = loops.begin ();
+ it != loops.end (); ++it)
+ gimplify_and_add ((*it).second.bind, loops_seq_p);
+}
+
+/* Helper function for enter_omp_iterator_loop_context. */
+
+static gimple_seq *
+enter_omp_iterator_loop_context_1 (tree iterator, gimple_seq *loops_seq_p)
+{
+ /* Drill into the nested bind expressions to get to the loop body. */
+ for (gimple_stmt_iterator gsi = gsi_start (*loops_seq_p);
+ !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple *stmt = gsi_stmt (gsi);
+
+ switch (gimple_code (stmt))
+ {
+ case GIMPLE_BIND:
+ {
+ gbind *bind_stmt = as_a<gbind *> (stmt);
+ gimple_push_bind_expr (bind_stmt);
+ gimple_seq *bind_body_p = gimple_bind_body_ptr (bind_stmt);
+ gimple_seq *seq =
+ enter_omp_iterator_loop_context_1 (iterator, bind_body_p);
+ if (seq)
+ return seq;
+ gimple_pop_bind_expr ();
+ }
+ break;
+ case GIMPLE_TRY:
+ {
+ gimple_seq *try_eval_p = gimple_try_eval_ptr (stmt);
+ gimple_seq *seq =
+ enter_omp_iterator_loop_context_1 (iterator, try_eval_p);
+ if (seq)
+ return seq;
+ }
+ break;
+ case GIMPLE_LABEL:
+ {
+ glabel *label_stmt = as_a<glabel *> (stmt);
+ tree label = gimple_label_label (label_stmt);
+ if (label == TREE_VEC_ELT (iterator, 6))
+ return loops_seq_p;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ return NULL;
+}
+
+/* Enter the Gimplification context in LOOPS_SEQ_P for the iterator loop
+ associated with OpenMP clause C. Returns the gimple_seq for the loop body
+ if C has OpenMP iterators, or ALT_SEQ_P if not. */
+
+static gimple_seq *
+enter_omp_iterator_loop_context (tree c, gimple_seq *loops_seq_p,
+ gimple_seq *alt_seq_p)
+{
+ if (!OMP_CLAUSE_HAS_ITERATORS (c))
+ return alt_seq_p;
+
+ push_gimplify_context ();
+
+ gimple_seq *seq = enter_omp_iterator_loop_context_1 (OMP_CLAUSE_ITERATORS (c),
+ loops_seq_p);
+ gcc_assert (seq);
+ return seq;
+}
+
+/* Enter the Gimplification context in STMT for the iterator loop associated
+ with OpenMP clause C. Returns the gimple_seq for the loop body if C has
+ OpenMP iterators, or ALT_SEQ_P if not. */
+
+gimple_seq *
+enter_omp_iterator_loop_context (tree c, gomp_target *stmt,
+ gimple_seq *alt_seq_p)
+{
+ gimple_seq *loops_seq_p = gimple_omp_target_iterator_loops_ptr (stmt);
+ return enter_omp_iterator_loop_context (c, loops_seq_p, alt_seq_p);
+}
+
+/* Exit the Gimplification context for the OpenMP clause C. */
+
+void
+exit_omp_iterator_loop_context (tree c)
+{
+ if (!OMP_CLAUSE_HAS_ITERATORS (c))
+ return;
+ while (!gimplify_ctxp->bind_expr_stack.is_empty ())
+ gimple_pop_bind_expr ();
+ pop_gimplify_context (NULL);
+}
+
/* If *LIST_P contains any OpenMP depend clauses with iterators,
lower all the depend clauses by populating corresponding depend
array. Returns 0 if there are no such depend clauses, or
@@ -13217,7 +13584,8 @@ omp_instantiate_implicit_mappers (splay_tree_node n, void *data)
static void
gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
enum omp_region_type region_type,
- enum tree_code code)
+ enum tree_code code,
+ gimple_seq *loops_seq_p = NULL)
{
using namespace omp_addr_tokenizer;
struct gimplify_omp_ctx *ctx, *outer_ctx;
@@ -13988,23 +14356,24 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
OMP_CLAUSE_SIZE (c) = DECL_P (decl) ? DECL_SIZE_UNIT (decl)
: TYPE_SIZE_UNIT (TREE_TYPE (decl));
- if (gimplify_expr (&OMP_CLAUSE_SIZE (c), pre_p,
- NULL, is_gimple_val, fb_rvalue) == GS_ERROR)
+ gimple_seq *seq_p;
+ seq_p = enter_omp_iterator_loop_context (c, loops_seq_p, pre_p);
+ if (gimplify_expr (&OMP_CLAUSE_SIZE (c), seq_p, NULL,
+ is_gimple_val, fb_rvalue) == GS_ERROR)
{
remove = true;
+ exit_omp_iterator_loop_context (c);
break;
}
if (!DECL_P (decl))
{
- if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p,
- NULL, is_gimple_lvalue, fb_lvalue)
- == GS_ERROR)
- {
- remove = true;
- break;
- }
+ if (gimplify_expr (&OMP_CLAUSE_DECL (c), seq_p, NULL,
+ is_gimple_lvalue, fb_lvalue) == GS_ERROR)
+ remove = true;
+ exit_omp_iterator_loop_context (c);
break;
}
+ exit_omp_iterator_loop_context (c);
goto do_notice;
case OMP_CLAUSE__MAPPER_BINDING_:
@@ -15035,7 +15404,8 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
static void
gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
- enum tree_code code)
+ enum tree_code code,
+ gimple_seq *loops_seq_p = NULL)
{
struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
tree *orig_list_p = list_p;
@@ -15406,12 +15776,14 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
: TYPE_SIZE_UNIT (TREE_TYPE (decl));
}
gimplify_omp_ctxp = ctx->outer_context;
- if (gimplify_expr (&OMP_CLAUSE_SIZE (c), pre_p, NULL,
+ gimple_seq *seq_p;
+ seq_p = enter_omp_iterator_loop_context (c, loops_seq_p, pre_p);
+ if (gimplify_expr (&OMP_CLAUSE_SIZE (c), seq_p, NULL,
is_gimple_val, fb_rvalue) == GS_ERROR)
{
gimplify_omp_ctxp = ctx;
remove = true;
- break;
+ goto end_adjust_omp_map_clause;
}
else if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
|| (OMP_CLAUSE_MAP_KIND (c)
@@ -15420,7 +15792,7 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
&& TREE_CODE (OMP_CLAUSE_SIZE (c)) != INTEGER_CST)
{
OMP_CLAUSE_SIZE (c)
- = get_initialized_tmp_var (OMP_CLAUSE_SIZE (c), pre_p, NULL,
+ = get_initialized_tmp_var (OMP_CLAUSE_SIZE (c), seq_p, NULL,
false);
if ((ctx->region_type & ORT_TARGET) != 0)
omp_add_variable (ctx, OMP_CLAUSE_SIZE (c),
@@ -15461,7 +15833,7 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
&& (code == OMP_TARGET_EXIT_DATA || code == OACC_EXIT_DATA))
{
remove = true;
- break;
+ goto end_adjust_omp_map_clause;
}
/* If we have a DECL_VALUE_EXPR (e.g. this is a class member and/or
a variable captured in a lambda closure), look through that now
@@ -15477,7 +15849,7 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
decl = OMP_CLAUSE_DECL (c) = DECL_VALUE_EXPR (decl);
if (TREE_CODE (decl) == TARGET_EXPR)
{
- if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL,
+ if (gimplify_expr (&OMP_CLAUSE_DECL (c), seq_p, NULL,
is_gimple_lvalue, fb_lvalue) == GS_ERROR)
remove = true;
}
@@ -15564,19 +15936,19 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
/* If we have e.g. map(struct: *var), don't gimplify the
argument since omp-low.cc wants to see the decl itself. */
if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT)
- break;
+ goto end_adjust_omp_map_clause;
/* We've already partly gimplified this in
gimplify_scan_omp_clauses. Don't do any more. */
if (code == OMP_TARGET && OMP_CLAUSE_MAP_IN_REDUCTION (c))
- break;
+ goto end_adjust_omp_map_clause;
gimplify_omp_ctxp = ctx->outer_context;
- if (gimplify_expr (pd, pre_p, NULL, is_gimple_lvalue,
+ if (gimplify_expr (pd, seq_p, NULL, is_gimple_lvalue,
fb_lvalue) == GS_ERROR)
remove = true;
gimplify_omp_ctxp = ctx;
- break;
+ goto end_adjust_omp_map_clause;
}
if ((code == OMP_TARGET
@@ -15709,6 +16081,8 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
== GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION)))
move_attach = true;
+end_adjust_omp_map_clause:
+ exit_omp_iterator_loop_context (c);
break;
case OMP_CLAUSE_TO:
@@ -18347,11 +18721,18 @@ gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p)
gcc_unreachable ();
}
+ gimple_seq iterator_loops_seq = NULL;
+ if (TREE_CODE (expr) == OMP_TARGET)
+ {
+ remove_unused_omp_iterator_vars (&OMP_CLAUSES (expr));
+ build_omp_iterators_loops (&OMP_CLAUSES (expr), &iterator_loops_seq);
+ }
+
bool save_in_omp_construct = in_omp_construct;
if ((ort & ORT_ACC) == 0)
in_omp_construct = false;
gimplify_scan_omp_clauses (&OMP_CLAUSES (expr), pre_p, ort,
- TREE_CODE (expr));
+ TREE_CODE (expr), &iterator_loops_seq);
if (TREE_CODE (expr) == OMP_TARGET)
optimize_target_teams (expr, pre_p);
if ((ort & (ORT_TARGET | ORT_TARGET_DATA)) != 0
@@ -18390,7 +18771,7 @@ gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p)
else
gimplify_and_add (OMP_BODY (expr), &body);
gimplify_adjust_omp_clauses (pre_p, body, &OMP_CLAUSES (expr),
- TREE_CODE (expr));
+ TREE_CODE (expr), &iterator_loops_seq);
in_omp_construct = save_in_omp_construct;
switch (TREE_CODE (expr))
@@ -18433,7 +18814,7 @@ gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p)
break;
case OMP_TARGET:
stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_REGION,
- OMP_CLAUSES (expr));
+ OMP_CLAUSES (expr), iterator_loops_seq);
break;
case OMP_TARGET_DATA:
/* Put use_device_{ptr,addr} clauses last, as map clauses are supposed
@@ -18508,10 +18889,16 @@ gimplify_omp_target_update (tree *expr_p, gimple_seq *pre_p)
default:
gcc_unreachable ();
}
+
+ gimple_seq iterator_loops_seq = NULL;
+ remove_unused_omp_iterator_vars (&OMP_STANDALONE_CLAUSES (expr));
+ build_omp_iterators_loops (&OMP_STANDALONE_CLAUSES (expr),
+ &iterator_loops_seq);
+
gimplify_scan_omp_clauses (&OMP_STANDALONE_CLAUSES (expr), pre_p,
- ort, TREE_CODE (expr));
+ ort, TREE_CODE (expr), &iterator_loops_seq);
gimplify_adjust_omp_clauses (pre_p, NULL, &OMP_STANDALONE_CLAUSES (expr),
- TREE_CODE (expr));
+ TREE_CODE (expr), &iterator_loops_seq);
if (TREE_CODE (expr) == OACC_UPDATE
&& omp_find_clause (OMP_STANDALONE_CLAUSES (expr),
OMP_CLAUSE_IF_PRESENT))
@@ -18575,7 +18962,8 @@ gimplify_omp_target_update (tree *expr_p, gimple_seq *pre_p)
gcc_unreachable ();
}
}
- stmt = gimple_build_omp_target (NULL, kind, OMP_STANDALONE_CLAUSES (expr));
+ stmt = gimple_build_omp_target (NULL, kind, OMP_STANDALONE_CLAUSES (expr),
+ iterator_loops_seq);
gimplify_seq_add_stmt (pre_p, stmt);
*expr_p = NULL_TREE;
diff --git a/gcc/gimplify.h b/gcc/gimplify.h
index b66ceb3..80c335e 100644
--- a/gcc/gimplify.h
+++ b/gcc/gimplify.h
@@ -79,6 +79,10 @@ extern enum gimplify_status gimplify_expr (tree *, gimple_seq *, gimple_seq *,
extern tree omp_get_construct_context (void);
int omp_has_novariants (void);
+extern gimple_seq *enter_omp_iterator_loop_context (tree, gomp_target *,
+ gimple_seq * = NULL);
+extern void exit_omp_iterator_loop_context (tree);
+
extern void gimplify_type_sizes (tree, gimple_seq *);
extern void gimplify_one_sizepos (tree *, gimple_seq *);
extern gbind *gimplify_body (tree, bool);
diff --git a/gcc/gsstruct.def b/gcc/gsstruct.def
index bfe0901..34adc86 100644
--- a/gcc/gsstruct.def
+++ b/gcc/gsstruct.def
@@ -44,6 +44,7 @@ DEFGSSTRUCT(GSS_OMP, gimple_statement_omp, false)
DEFGSSTRUCT(GSS_OMP_CRITICAL, gomp_critical, false)
DEFGSSTRUCT(GSS_OMP_FOR, gomp_for, false)
DEFGSSTRUCT(GSS_OMP_PARALLEL_LAYOUT, gimple_statement_omp_parallel_layout, false)
+DEFGSSTRUCT(GSS_OMP_TARGET, gomp_target, false)
DEFGSSTRUCT(GSS_OMP_TASK, gomp_task, false)
DEFGSSTRUCT(GSS_OMP_SECTIONS, gomp_sections, false)
DEFGSSTRUCT(GSS_OMP_SINGLE_LAYOUT, gimple_statement_omp_single_layout, false)
diff --git a/gcc/libgdiagnostics++.h b/gcc/libgdiagnostics++.h
index c955d56..fc20398 100644
--- a/gcc/libgdiagnostics++.h
+++ b/gcc/libgdiagnostics++.h
@@ -477,6 +477,9 @@ public:
void
take_global_graph (graph g);
+ void
+ set_debug_physical_locations (bool value);
+
diagnostic_manager *m_inner;
bool m_owned;
};
@@ -926,6 +929,13 @@ manager::take_global_graph (graph g)
g.m_owned = false;
}
+inline void
+manager::set_debug_physical_locations (bool value)
+{
+ diagnostic_manager_set_debug_physical_locations (m_inner,
+ value ? 1 : 0);
+}
+
// class graph
inline void
diff --git a/gcc/libgdiagnostics-private.h b/gcc/libgdiagnostics-private.h
index 0e90f87..4186c67 100644
--- a/gcc/libgdiagnostics-private.h
+++ b/gcc/libgdiagnostics-private.h
@@ -58,6 +58,13 @@ private_diagnostic_execution_path_add_event_3 (diagnostic_execution_path *path,
LIBGDIAGNOSTICS_PARAM_CAN_BE_NULL (5)
LIBGDIAGNOSTICS_PARAM_MUST_BE_NON_NULL (6);
+/* Entrypoint added in LIBGDIAGNOSTICS_ABI_5. */
+
+extern void
+private_diagnostic_set_nesting_level (diagnostic *diag,
+ int nesting_level)
+ LIBGDIAGNOSTICS_PARAM_MUST_BE_NON_NULL (1);
+
} // extern "C"
#endif /* LIBGDIAGNOSTICS_PRIVATE_H */
diff --git a/gcc/libgdiagnostics.cc b/gcc/libgdiagnostics.cc
index 7351d336..784e281 100644
--- a/gcc/libgdiagnostics.cc
+++ b/gcc/libgdiagnostics.cc
@@ -639,7 +639,8 @@ struct diagnostic_manager
public:
diagnostic_manager ()
: m_current_diag (nullptr),
- m_prev_diag_logical_loc (nullptr)
+ m_prev_diag_logical_loc (nullptr),
+ m_debug_physical_locations (false)
{
linemap_init (&m_line_table, BUILTINS_LOCATION);
m_line_table.m_reallocator = xrealloc;
@@ -747,6 +748,9 @@ public:
new_location_from_file_and_line (const diagnostic_file *file,
diagnostic_line_num_t line_num)
{
+ if (m_debug_physical_locations)
+ fprintf (stderr, "new_location_from_file_and_line (%s, %i)",
+ file->get_name (), line_num);
ensure_linemap_for_file_and_line (file, line_num);
location_t loc = linemap_position_for_column (&m_line_table, 0);
return new_location (loc);
@@ -757,6 +761,9 @@ public:
diagnostic_line_num_t line_num,
diagnostic_column_num_t column_num)
{
+ if (m_debug_physical_locations)
+ fprintf (stderr, "new_location_from_file_line_column (%s, %i, %i)",
+ file->get_name (), line_num, column_num);
ensure_linemap_for_file_and_line (file, line_num);
location_t loc = linemap_position_for_column (&m_line_table, column_num);
return new_location (loc);
@@ -767,12 +774,23 @@ public:
const diagnostic_physical_location *loc_start,
const diagnostic_physical_location *loc_end)
{
+ if (m_debug_physical_locations)
+ fprintf (stderr, "new_location_from_range (%p, %p, %p)",
+ (const void *)loc_caret,
+ (const void *)loc_start,
+ (const void *)loc_end);
return new_location
(m_line_table.make_location (as_location_t (loc_caret),
as_location_t (loc_start),
as_location_t (loc_end)));
}
+ void
+ set_debug_physical_locations (bool value)
+ {
+ m_debug_physical_locations = value;
+ }
+
const diagnostic_logical_location *
new_logical_location (enum diagnostic_logical_location_kind_t kind,
const diagnostic_logical_location *parent,
@@ -874,11 +892,17 @@ private:
linemap_add (&m_line_table, LC_ENTER, false, file->get_name (), 0);
else
{
- line_map *map
- = const_cast<line_map *>
- (linemap_add (&m_line_table, LC_RENAME_VERBATIM, false,
- file->get_name (), 0));
- ((line_map_ordinary *)map)->included_from = UNKNOWN_LOCATION;
+ line_map_ordinary *last_map
+ = LINEMAPS_LAST_ORDINARY_MAP (&m_line_table);
+ if (last_map->to_file != file->get_name ()
+ || linenum < last_map->to_line)
+ {
+ line_map *map
+ = const_cast<line_map *>
+ (linemap_add (&m_line_table, LC_RENAME_VERBATIM, false,
+ file->get_name (), 0));
+ ((line_map_ordinary *)map)->included_from = UNKNOWN_LOCATION;
+ }
}
linemap_line_start (&m_line_table, linenum, 100);
}
@@ -888,11 +912,19 @@ private:
{
if (loc == UNKNOWN_LOCATION)
return nullptr;
+ if (m_debug_physical_locations)
+ fprintf (stderr, ": new_location (%lx)", loc);
if (diagnostic_physical_location **slot = m_location_t_map.get (loc))
- return *slot;
+ {
+ if (m_debug_physical_locations)
+ fprintf (stderr, ": cache hit: %p\n", (const void *)*slot);
+ return *slot;
+ }
diagnostic_physical_location *phys_loc
= new diagnostic_physical_location (this, loc);
m_location_t_map.put (loc, phys_loc);
+ if (m_debug_physical_locations)
+ fprintf (stderr, ": cache miss: %p\n", (const void *)phys_loc);
return phys_loc;
}
@@ -909,6 +941,7 @@ private:
const diagnostic *m_current_diag;
const diagnostic_logical_location *m_prev_diag_logical_loc;
std::unique_ptr<diagnostics::changes::change_set> m_change_set;
+ bool m_debug_physical_locations;
};
class impl_rich_location : public rich_location
@@ -1221,7 +1254,8 @@ public:
m_level (level),
m_rich_loc (diag_mgr.get_line_table ()),
m_logical_loc (nullptr),
- m_path (nullptr)
+ m_path (nullptr),
+ m_nesting_level (0)
{
m_metadata.set_lazy_digraphs (&m_graphs);
}
@@ -1325,6 +1359,9 @@ public:
return m_graphs;
}
+ int get_nesting_level () const { return m_nesting_level; }
+ void set_nesting_level (int value) { m_nesting_level = value; }
+
private:
diagnostic_manager &m_diag_mgr;
enum diagnostic_level m_level;
@@ -1335,6 +1372,7 @@ private:
std::vector<std::unique_ptr<range_label>> m_labels;
std::vector<std::unique_ptr<impl_rule>> m_rules;
std::unique_ptr<diagnostic_execution_path> m_path;
+ int m_nesting_level;
};
static enum diagnostics::kind
@@ -1624,8 +1662,9 @@ GCC_DIAGNOSTIC_PUSH_IGNORED(-Wsuggest-attribute=format)
GCC_DIAGNOSTIC_POP
info.m_metadata = diag.get_metadata ();
info.m_x_data = &diag;
+ m_dc.set_nesting_level (diag.get_nesting_level ());
diagnostic_report_diagnostic (&m_dc, &info);
-
+ m_dc.set_nesting_level (0);
m_dc.end_group ();
}
@@ -2972,3 +3011,23 @@ private_diagnostic_execution_path_add_event_3 (diagnostic_execution_path *path,
return as_diagnostic_event_id (result);
}
+
+/* Public entrypoint. */
+
+void
+diagnostic_manager_set_debug_physical_locations (diagnostic_manager *mgr,
+ int value)
+{
+ FAIL_IF_NULL (mgr);
+ mgr->set_debug_physical_locations (value);
+}
+
+/* Private entrypoint. */
+
+void
+private_diagnostic_set_nesting_level (diagnostic *diag,
+ int nesting_level)
+{
+ FAIL_IF_NULL (diag);
+ diag->set_nesting_level (nesting_level);
+}
diff --git a/gcc/libgdiagnostics.h b/gcc/libgdiagnostics.h
index c202feb..0ae56f0 100644
--- a/gcc/libgdiagnostics.h
+++ b/gcc/libgdiagnostics.h
@@ -1115,6 +1115,16 @@ diagnostic_node_set_label_via_msg_buf (diagnostic_node *node,
LIBGDIAGNOSTICS_PARAM_MUST_BE_NON_NULL (1)
LIBGDIAGNOSTICS_PARAM_CAN_BE_NULL (2);
+/* If non-zero, print debugging information to stderr when
+ creating diagnostic_physical_location instances.
+
+ Added in LIBGDIAGNOSTICS_ABI_5. */
+#define LIBDIAGNOSTICS_HAVE_diagnostic_manager_set_debug_physical_locations
+
+extern void
+diagnostic_manager_set_debug_physical_locations (diagnostic_manager *mgr,
+ int value);
+
/* DEFERRED:
- thread-safety
- plural forms
diff --git a/gcc/libgdiagnostics.map b/gcc/libgdiagnostics.map
index 91f3951..0400ca7 100644
--- a/gcc/libgdiagnostics.map
+++ b/gcc/libgdiagnostics.map
@@ -141,3 +141,11 @@ LIBGDIAGNOSTICS_ABI_4 {
# Private hook used by sarif-replay
private_diagnostic_execution_path_add_event_3;
} LIBGDIAGNOSTICS_ABI_3;
+
+LIBGDIAGNOSTICS_ABI_5 {
+ global:
+ diagnostic_manager_set_debug_physical_locations;
+
+ # Private hook used by sarif-replay
+ private_diagnostic_set_nesting_level;
+} LIBGDIAGNOSTICS_ABI_4;
diff --git a/gcc/libsarifreplay.cc b/gcc/libsarifreplay.cc
index 1e4a74f..e8fc6d0 100644
--- a/gcc/libsarifreplay.cc
+++ b/gcc/libsarifreplay.cc
@@ -1408,10 +1408,22 @@ sarif_replayer::handle_result_obj (const json::object &result_obj,
rule_obj));
if (!msg_buf.m_inner)
return status::err_invalid_sarif;
+
auto note (m_output_mgr.begin_diagnostic (DIAGNOSTIC_LEVEL_NOTE));
note.set_location (physical_loc);
note.set_logical_location (logical_loc);
add_any_annotations (note, annotations);
+
+ /* Look for "nestingLevel" property, as per
+ "P3358R0 SARIF for Structured Diagnostics"
+ https://wg21.link/P3358R0 */
+ if (auto nesting_level
+ = maybe_get_property_bag_value<json::integer_number>
+ (*location_obj,
+ "nestingLevel"))
+ private_diagnostic_set_nesting_level (note.m_inner,
+ nesting_level->get ());
+
notes.push_back ({std::move (note), std::move (msg_buf)});
}
else
diff --git a/gcc/libsarifreplay.h b/gcc/libsarifreplay.h
index fb66014..313a905 100644
--- a/gcc/libsarifreplay.h
+++ b/gcc/libsarifreplay.h
@@ -31,6 +31,7 @@ struct replay_options
bool m_echo_file;
bool m_json_comments;
bool m_verbose;
+ bool m_debug_physical_locations;
enum diagnostic_colorize m_diagnostics_colorize;
};
diff --git a/gcc/lto-wrapper.cc b/gcc/lto-wrapper.cc
index cb293f2..03fca97 100644
--- a/gcc/lto-wrapper.cc
+++ b/gcc/lto-wrapper.cc
@@ -2265,13 +2265,14 @@ cont:
obstack_free (&argv_obstack, NULL);
}
-/* Concrete implementation of diagnostic_option_manager for LTO. */
+/* Concrete implementation of diagnostics::option_id_manager for LTO. */
-class lto_diagnostic_option_manager : public gcc_diagnostic_option_manager
+class lto_diagnostic_option_id_manager
+ : public gcc_diagnostic_option_id_manager
{
public:
- lto_diagnostic_option_manager ()
- : gcc_diagnostic_option_manager (0 /* lang_mask */)
+ lto_diagnostic_option_id_manager ()
+ : gcc_diagnostic_option_id_manager (0 /* lang_mask */)
{
}
int option_enabled_p (diagnostics::option_id) const final override
@@ -2307,8 +2308,8 @@ main (int argc, char *argv[])
diagnostic_initialize (global_dc, 0);
diagnostic_color_init (global_dc);
diagnostic_urls_init (global_dc);
- global_dc->set_option_manager
- (::make_unique<lto_diagnostic_option_manager> (), 0);
+ global_dc->set_option_id_manager
+ (::make_unique<lto_diagnostic_option_id_manager> (), 0);
if (atexit (lto_wrapper_cleanup) != 0)
fatal_error (input_location, "%<atexit%> failed");
diff --git a/gcc/omp-low.cc b/gcc/omp-low.cc
index e1036ad..9d80a35 100644
--- a/gcc/omp-low.cc
+++ b/gcc/omp-low.cc
@@ -12651,6 +12651,63 @@ lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
}
}
+ /* Set EXPR as the hostaddr expression that should result from the clause C
+ in the target statement STMT. Returns the tree that should be
+ passed as the hostaddr (a pointer to the array containing the expanded
+ hostaddrs and sizes of the clause). */
+
+static tree
+lower_omp_map_iterator_expr (tree expr, tree c, gomp_target *stmt)
+{
+ if (!OMP_CLAUSE_HAS_ITERATORS (c))
+ return expr;
+
+ tree iterator = OMP_CLAUSE_ITERATORS (c);
+ tree elems = TREE_VEC_ELT (iterator, 7);
+ tree index = TREE_VEC_ELT (iterator, 8);
+ gimple_seq *loop_body_p = enter_omp_iterator_loop_context (c, stmt);
+
+ /* IN LOOP BODY: */
+ /* elems[idx] = <expr>; */
+ tree lhs = build4 (ARRAY_REF, ptr_type_node, elems, index,
+ NULL_TREE, NULL_TREE);
+ tree mod_expr = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
+ void_type_node, lhs, expr);
+ gimplify_and_add (mod_expr, loop_body_p);
+ exit_omp_iterator_loop_context (c);
+
+ return build_fold_addr_expr_with_type (elems, ptr_type_node);
+}
+
+/* Set SIZE as the size expression that should result from the clause C
+ in the target statement STMT. Returns the tree that should be
+ passed as the clause size (a size_int with the value SIZE_MAX, indicating
+ that the clause uses an iterator). */
+
+static tree
+lower_omp_map_iterator_size (tree size, tree c, gomp_target *stmt)
+{
+ if (!OMP_CLAUSE_HAS_ITERATORS (c))
+ return size;
+
+ tree iterator = OMP_CLAUSE_ITERATORS (c);
+ tree elems = TREE_VEC_ELT (iterator, 7);
+ tree index = TREE_VEC_ELT (iterator, 8);
+ gimple_seq *loop_body_p = enter_omp_iterator_loop_context (c, stmt);
+
+ /* IN LOOP BODY: */
+ /* elems[idx+1] = <size>; */
+ tree lhs = build4 (ARRAY_REF, ptr_type_node, elems,
+ size_binop (PLUS_EXPR, index, size_int (1)),
+ NULL_TREE, NULL_TREE);
+ tree mod_expr = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
+ void_type_node, lhs, size);
+ gimplify_and_add (mod_expr, loop_body_p);
+ exit_omp_iterator_loop_context (c);
+
+ return size_int (SIZE_MAX);
+}
+
/* Lower the GIMPLE_OMP_TARGET in the current statement
in GSI_P. CTX holds context information for the directive. */
@@ -12820,6 +12877,11 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
deep_map_cnt = extra;
}
+ if (deep_map_cnt
+ && OMP_CLAUSE_HAS_ITERATORS (c))
+ sorry ("iterators used together with deep mapping are not "
+ "supported yet");
+
if (!DECL_P (var))
{
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
@@ -13234,6 +13296,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
*p = build_fold_indirect_ref (nd);
}
v = build_fold_addr_expr_with_type (v, ptr_type_node);
+ v = lower_omp_map_iterator_expr (v, c, stmt);
gimplify_assign (x, v, &ilist);
nc = NULL_TREE;
}
@@ -13307,12 +13370,17 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
&& TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
{
gcc_assert (offloaded);
- tree avar
- = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
- mark_addressable (avar);
- gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
- talign = DECL_ALIGN_UNIT (avar);
+ tree avar = build_fold_addr_expr (var);
+ if (!OMP_CLAUSE_ITERATORS (c))
+ {
+ tree tmp = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
+ mark_addressable (tmp);
+ gimplify_assign (tmp, avar, &ilist);
+ avar = tmp;
+ }
+ talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (x)));
avar = build_fold_addr_expr (avar);
+ avar = lower_omp_map_iterator_expr (avar, c, stmt);
gimplify_assign (x, avar, &ilist);
}
else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
@@ -13392,6 +13460,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
if (s == NULL_TREE)
s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
s = fold_convert (size_type_node, s);
+ s = lower_omp_map_iterator_size (s, c, stmt);
purpose = size_int (map_idx++);
CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
if (TREE_CODE (s) != INTEGER_CST)
@@ -14324,6 +14393,9 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
gimple_omp_set_body (stmt, new_body);
}
+ gsi_insert_seq_before (gsi_p, gimple_omp_target_iterator_loops (stmt),
+ GSI_SAME_STMT);
+ gimple_omp_target_set_iterator_loops (stmt, NULL);
bind = gimple_build_bind (NULL, NULL,
tgt_bind ? gimple_bind_block (tgt_bind)
: NULL_TREE);
diff --git a/gcc/opt-problem.cc b/gcc/opt-problem.cc
index 8324feb..e0c7601 100644
--- a/gcc/opt-problem.cc
+++ b/gcc/opt-problem.cc
@@ -42,7 +42,7 @@ along with GCC; see the file COPYING3. If not see
opt_problem::opt_problem (const dump_location_t &loc,
const char *fmt, va_list *ap)
-: m_optinfo (loc, OPTINFO_KIND_FAILURE, current_pass)
+: m_optinfo (loc, optinfo::kind::failure, current_pass)
{
/* We shouldn't be bothering to construct these objects if
dumping isn't enabled. */
diff --git a/gcc/optinfo-emit-json.cc b/gcc/optinfo-emit-json.cc
index 28c8a98..ae686a9 100644
--- a/gcc/optinfo-emit-json.cc
+++ b/gcc/optinfo-emit-json.cc
@@ -143,7 +143,7 @@ optrecord_json_writer::add_record (const optinfo *optinfo)
add_record (obj);
/* Potentially push the scope. */
- if (optinfo->get_kind () == OPTINFO_KIND_SCOPE)
+ if (optinfo->get_kind () == optinfo::kind::scope)
{
json::array *children = new json::array ();
obj->set ("children", children);
@@ -334,7 +334,7 @@ optrecord_json_writer::optinfo_to_json (const optinfo *optinfo)
obj->set ("impl_location",
impl_location_to_json (optinfo->get_impl_location ()));
- const char *kind_str = optinfo_kind_to_string (optinfo->get_kind ());
+ const char *kind_str = optinfo::kind_to_string (optinfo->get_kind ());
obj->set_string ("kind", kind_str);
json::array *message = new json::array ();
obj->set ("message", message);
@@ -345,12 +345,12 @@ optrecord_json_writer::optinfo_to_json (const optinfo *optinfo)
{
default:
gcc_unreachable ();
- case OPTINFO_ITEM_KIND_TEXT:
+ case optinfo_item::kind::text:
{
message->append_string (item->get_text ());
}
break;
- case OPTINFO_ITEM_KIND_TREE:
+ case optinfo_item::kind::tree:
{
json::object *json_item = new json::object ();
json_item->set_string ("expr", item->get_text ());
@@ -363,7 +363,7 @@ optrecord_json_writer::optinfo_to_json (const optinfo *optinfo)
message->append (json_item);
}
break;
- case OPTINFO_ITEM_KIND_GIMPLE:
+ case optinfo_item::kind::gimple:
{
json::object *json_item = new json::object ();
json_item->set_string ("stmt", item->get_text ());
@@ -376,7 +376,7 @@ optrecord_json_writer::optinfo_to_json (const optinfo *optinfo)
message->append (json_item);
}
break;
- case OPTINFO_ITEM_KIND_SYMTAB_NODE:
+ case optinfo_item::kind::symtab_node:
{
json::object *json_item = new json::object ();
json_item->set_string ("symtab_node", item->get_text ());
diff --git a/gcc/optinfo.cc b/gcc/optinfo.cc
index 51e9fd6..dd5a551 100644
--- a/gcc/optinfo.cc
+++ b/gcc/optinfo.cc
@@ -36,9 +36,9 @@ along with GCC; see the file COPYING3. If not see
/* optinfo_item's ctor. Takes ownership of TEXT. */
-optinfo_item::optinfo_item (enum optinfo_item_kind kind, location_t location,
+optinfo_item::optinfo_item (enum kind kind_, location_t location,
char *text)
-: m_kind (kind), m_location (location), m_text (text)
+: m_kind (kind_), m_location (location), m_text (text)
{
}
@@ -52,19 +52,19 @@ optinfo_item::~optinfo_item ()
/* Get a string from KIND. */
const char *
-optinfo_kind_to_string (enum optinfo_kind kind)
+optinfo::kind_to_string (enum kind kind_)
{
- switch (kind)
+ switch (kind_)
{
default:
gcc_unreachable ();
- case OPTINFO_KIND_SUCCESS:
+ case kind::success:
return "success";
- case OPTINFO_KIND_FAILURE:
+ case kind::failure:
return "failure";
- case OPTINFO_KIND_NOTE:
+ case kind::note:
return "note";
- case OPTINFO_KIND_SCOPE:
+ case kind::scope:
return "scope";
}
}
@@ -91,19 +91,19 @@ optinfo::add_item (std::unique_ptr<optinfo_item> item)
/* Get MSG_* flags corresponding to KIND. */
-static dump_flags_t
-optinfo_kind_to_dump_flag (enum optinfo_kind kind)
+dump_flags_t
+optinfo::kind_to_dump_flag (enum kind kind_)
{
- switch (kind)
+ switch (kind_)
{
default:
gcc_unreachable ();
- case OPTINFO_KIND_SUCCESS:
+ case kind::success:
return MSG_OPTIMIZED_LOCATIONS;
- case OPTINFO_KIND_FAILURE:
+ case kind::failure:
return MSG_MISSED_OPTIMIZATION;
- case OPTINFO_KIND_NOTE:
- case OPTINFO_KIND_SCOPE:
+ case kind::note:
+ case kind::scope:
return MSG_NOTE;
}
}
@@ -114,7 +114,7 @@ optinfo_kind_to_dump_flag (enum optinfo_kind kind)
void
optinfo::emit_for_opt_problem () const
{
- dump_flags_t dump_kind = optinfo_kind_to_dump_flag (get_kind ());
+ dump_flags_t dump_kind = kind_to_dump_flag (get_kind ());
dump_kind |= MSG_PRIORITY_REEMITTED;
/* Re-emit to "immediate" destinations, without creating a new optinfo. */
@@ -134,14 +134,14 @@ void
optinfo::handle_dump_file_kind (dump_flags_t dump_kind)
{
/* Any optinfo for a "scope" should have been emitted separately. */
- gcc_assert (m_kind != OPTINFO_KIND_SCOPE);
+ gcc_assert (m_kind != kind::scope);
if (dump_kind & MSG_OPTIMIZED_LOCATIONS)
- m_kind = OPTINFO_KIND_SUCCESS;
+ m_kind = kind::success;
else if (dump_kind & MSG_MISSED_OPTIMIZATION)
- m_kind = OPTINFO_KIND_FAILURE;
+ m_kind = kind::failure;
else if (dump_kind & MSG_NOTE)
- m_kind = OPTINFO_KIND_NOTE;
+ m_kind = kind::note;
}
/* Return true if any of the active optinfo destinations make use
diff --git a/gcc/optinfo.h b/gcc/optinfo.h
index 1e0fb22..ca9457f 100644
--- a/gcc/optinfo.h
+++ b/gcc/optinfo.h
@@ -74,18 +74,6 @@ class optinfo_item;
extern bool optinfo_wants_inlining_info_p ();
-/* The various kinds of optinfo. */
-
-enum optinfo_kind
-{
- OPTINFO_KIND_SUCCESS,
- OPTINFO_KIND_FAILURE,
- OPTINFO_KIND_NOTE,
- OPTINFO_KIND_SCOPE
-};
-
-extern const char *optinfo_kind_to_string (enum optinfo_kind kind);
-
class dump_context;
/* A bundle of information describing part of an optimization. */
@@ -95,10 +83,19 @@ class optinfo
friend class dump_context;
public:
+ /* The various kinds of optinfo. */
+ enum class kind
+ {
+ success,
+ failure,
+ note,
+ scope
+ };
+
optinfo (const dump_location_t &loc,
- enum optinfo_kind kind,
+ enum kind kind_,
opt_pass *pass)
- : m_loc (loc), m_kind (kind), m_pass (pass), m_items ()
+ : m_loc (loc), m_kind (kind_), m_pass (pass), m_items ()
{}
~optinfo ();
@@ -111,7 +108,7 @@ class optinfo
const dump_impl_location_t &
get_impl_location () const { return m_loc.get_impl_location (); }
- enum optinfo_kind get_kind () const { return m_kind; }
+ enum kind get_kind () const { return m_kind; }
opt_pass *get_pass () const { return m_pass; }
unsigned int num_items () const { return m_items.length (); }
const optinfo_item *get_item (unsigned int i) const { return m_items[i]; }
@@ -123,6 +120,9 @@ class optinfo
void emit_for_opt_problem () const;
+ static const char *kind_to_string (enum kind k);
+ static dump_flags_t kind_to_dump_flag (enum kind k);
+
private:
/* Pre-canned ways of manipulating the optinfo, for use by friend class
dump_context. */
@@ -130,37 +130,36 @@ class optinfo
private:
dump_location_t m_loc;
- enum optinfo_kind m_kind;
+ enum kind m_kind;
opt_pass *m_pass;
auto_vec <optinfo_item *> m_items;
};
-/* An enum for discriminating between different kinds of optinfo_item. */
-
-enum optinfo_item_kind
-{
- OPTINFO_ITEM_KIND_TEXT,
- OPTINFO_ITEM_KIND_TREE,
- OPTINFO_ITEM_KIND_GIMPLE,
- OPTINFO_ITEM_KIND_SYMTAB_NODE
-};
-
/* An item within an optinfo. */
class optinfo_item
{
public:
- optinfo_item (enum optinfo_item_kind kind, location_t location,
+ /* An enum for discriminating between different kinds of optinfo_item. */
+ enum class kind
+ {
+ text,
+ tree,
+ gimple,
+ symtab_node
+ };
+
+ optinfo_item (enum kind kind_, location_t location,
char *text);
~optinfo_item ();
- enum optinfo_item_kind get_kind () const { return m_kind; }
+ enum kind get_kind () const { return m_kind; }
location_t get_location () const { return m_location; }
const char *get_text () const { return m_text; }
private:
/* Metadata (e.g. for optimization records). */
- enum optinfo_item_kind m_kind;
+ enum kind m_kind;
location_t m_location;
/* The textual form of the item, owned by the item. */
diff --git a/gcc/opts-common.cc b/gcc/opts-common.cc
index 91cad49..e6d7f4d 100644
--- a/gcc/opts-common.cc
+++ b/gcc/opts-common.cc
@@ -1876,7 +1876,7 @@ option_enabled (int opt_idx, unsigned lang_mask, void *opts)
}
int
-compiler_diagnostic_option_manager::
+compiler_diagnostic_option_id_manager::
option_enabled_p (diagnostics::option_id opt_id) const
{
return option_enabled (opt_id.m_idx, m_lang_mask, m_opts);
diff --git a/gcc/opts-diagnostic.h b/gcc/opts-diagnostic.h
index 4fa4ea8..25ade86 100644
--- a/gcc/opts-diagnostic.h
+++ b/gcc/opts-diagnostic.h
@@ -20,30 +20,31 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_OPTS_DIAGNOSTIC_H
#define GCC_OPTS_DIAGNOSTIC_H
-/* Abstract subclass of diagnostics::option_manager for gcc options. */
+/* Abstract subclass of diagnostics::option_id_manager for gcc options. */
-class gcc_diagnostic_option_manager : public diagnostics::option_manager
+class gcc_diagnostic_option_id_manager : public diagnostics::option_id_manager
{
public:
char *make_option_url (diagnostics::option_id option_id) const final override;
protected:
- gcc_diagnostic_option_manager (unsigned lang_mask)
+ gcc_diagnostic_option_id_manager (unsigned lang_mask)
: m_lang_mask (lang_mask)
{}
unsigned m_lang_mask;
};
-/* Concrete implementation of diagnostic_option_manager for compiler. */
+/* Concrete implementation of diagnostics::option_id_manager for compiler. */
-class compiler_diagnostic_option_manager : public gcc_diagnostic_option_manager
+class compiler_diagnostic_option_id_manager
+ : public gcc_diagnostic_option_id_manager
{
public:
- compiler_diagnostic_option_manager (const diagnostics::context &context,
- unsigned lang_mask,
- void *opts)
- : gcc_diagnostic_option_manager (lang_mask),
+ compiler_diagnostic_option_id_manager (const diagnostics::context &context,
+ unsigned lang_mask,
+ void *opts)
+ : gcc_diagnostic_option_id_manager (lang_mask),
m_context (context),
m_opts (opts)
{
diff --git a/gcc/opts.cc b/gcc/opts.cc
index c21e66b..b6d25bf 100644
--- a/gcc/opts.cc
+++ b/gcc/opts.cc
@@ -3744,7 +3744,7 @@ enable_warning_as_error (const char *arg, int value, unsigned int lang_mask,
as -Werror. */
char *
-compiler_diagnostic_option_manager::
+compiler_diagnostic_option_id_manager::
make_option_name (diagnostics::option_id option_id,
enum diagnostics::kind orig_diag_kind,
enum diagnostics::kind diag_kind) const
@@ -3823,7 +3823,7 @@ get_option_url_suffix (int option_index, unsigned lang_mask)
which enabled a diagnostic. */
char *
-gcc_diagnostic_option_manager::
+gcc_diagnostic_option_id_manager::
make_option_url (diagnostics::option_id option_id) const
{
if (option_id.m_idx)
diff --git a/gcc/rust/ChangeLog b/gcc/rust/ChangeLog
index f103c7e..f960ef2 100644
--- a/gcc/rust/ChangeLog
+++ b/gcc/rust/ChangeLog
@@ -1,3 +1,2391 @@
+2025-08-05 Ryutaro Okada <1015ryu88@gmail.com>
+
+ * Make-lang.in (rust-readonly-check2.cc):
+ Add read-only check on HIR
+ * checks/errors/rust-readonly-check2.cc (ReadonlyChecker):
+ Add read-only check on HIR
+ * checks/errors/rust-readonly-check2.h (ReadonlyChecker):
+ Add read-only check on HIR
+
+2025-08-05 Ryutaro Okada <1015ryu88@gmail.com>
+
+ * hir/tree/rust-hir-visitor.cc (DefaultHIRVisitor::walk):
+ Call base class's accept_vis method
+
+2025-08-05 Ryutaro Okada <1015ryu88@gmail.com>
+
+ * hir/tree/rust-hir-visitor.cc (DefaultHIRVisitor::walk):
+ Add check before calling `get_trait_ref()`
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * expand/rust-macro-builtins-helpers.cc
+ (try_extract_string_literal_from_fragment): Perform static_cast
+ to AST::LiteralExpr only after it's verified that an AST::Expr
+ is a literal.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * util/rust-attribute-values.h
+ (Attributes::RUSTC_ARGS_REQUIRED_CONST): New constexpr variable.
+ * util/rust-attributes.cc (__definitions): New entry for
+ RUSTC_ARGS_REQUIRED_CONST.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-ast.cc (AttributeParser::parse_meta_item_inner):
+ Handle removal of AttributeParser-specific functions.
+ (AttributeParser::parse_path_meta_item): Likewise.
+ (AttributeParser::parse_meta_item_seq): Likewise.
+ (AttributeParser::parse_meta_item_lit): Likewise.
+ (AttributeParser::parse_literal): Remove function.
+ (AttributeParser::parse_simple_path): Likewise.
+ (AttributeParser::parse_simple_path_segment): Likewise.
+ (AttributeParser::peek_token): Likewise.
+ (AttributeParser::skip_token): Likewise.
+ * ast/rust-macro.h (AttributeParser::parse_simple_path):
+ Likewise.
+ (AttributeParser::parse_simple_path_segment): Likewise.
+ (AttributeParser::parse_literal): Likewise.
+ (AttributeParser::peek_token): Likewise.
+ (AttributeParser::skip_token): Likewise.
+ * parse/rust-parse.h (Parser): Make AttributeParser a friend
+ class.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * backend/rust-compile-expr.cc (CompileExpr::visit): Add proper handling
+ of the node.
+ * rust-backend.h (lookup_field): Declare it.
+ * rust-gcc.cc (lookup_field): Add forked implementation from gcc/c/.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-ast.cc (AttributeParser::parse_path_meta_item): Catch
+ parse_expr returning nullptr and remove defunct comment.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * Make-lang.in (GRS_OBJS): Add entries.
+ * parse/rust-parse-impl.h: Adjust header comment.
+ (Parser::parse_lifetime_params_objs): Fix bug and add comment.
+ (Parser::unexpected_token): Likewise.
+ * parse/rust-parse.h: Remove inclusion of "rust-parse-impl.h".
+ * parse/rust-parse-impl-lexer.cc: New file.
+ * parse/rust-parse-impl-macro.cc: New file.
+ * parse/rust-parse-impl-proc-macro.cc: New file.
+
+2025-08-05 Ryutaro Okada <1015ryu88@gmail.com>
+
+ * hir/rust-ast-lower-implitem.cc (ASTLowerTraitItem::visit):
+ Fix object copying issue causing pointer inconsistency
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast.cc (AttributeParser::parse_path_meta_item): Parse
+ expression instead of literal. Update variant name.
+ (MetaItemPathLit::to_attribute): Remove function.
+ (AttributeParser::parse_path_meta_item): Update name.
+ (MetaItemPathLit::check_cfg_predicate): Likewise.
+ (MetaItemPathExpr::check_cfg_predicate): Likewise.
+ (MetaItemPathLit::accept_vis): Likewise.
+ (MetaItemPathExpr::accept_vis): Likewise.
+ * ast/rust-ast-collector.h: Update prototype and adapt code to new
+ expression.
+ * ast/rust-ast-collector.cc: Update code to expr.
+ * ast/rust-ast-full-decls.h (class MetaItemPathLit): Likewise.
+ (class MetaItemPathExpr): Likewise.
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise.
+ * ast/rust-ast-visitor.h: Likewise.
+ * ast/rust-ast.h (class MetaItemPathLit): Rename class from here...
+ (class MetaItemPathExpr): ... to here.
+ * ast/rust-expr.h (class MetaItemPathLit): Rename class from here...
+ (class MetaItemPathExpr): ...to here.
+ * expand/rust-derive.h: Update class name.
+ * expand/rust-expand-visitor.cc (ExpandVisitor::visit): Likewise.
+ * expand/rust-expand-visitor.h: Likewise.
+ * hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Likewise.
+ * hir/rust-ast-lower-base.h: Likewise.
+ * resolve/rust-ast-resolve-base.cc (ResolverBase::visit): Likewise.
+ * resolve/rust-ast-resolve-base.h: Likewise.
+ * resolve/rust-early-name-resolver.cc (EarlyNameResolver::visit):
+ Likewise.
+ * resolve/rust-early-name-resolver.h: Likewise.
+ * util/rust-attributes.cc (AttributeChecker::visit): Likewise.
+ * util/rust-attributes.h: Likewise.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-tyty-subst.cc (SubstitutionRef::infer_substitions): remove debug
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-type-util.cc (unify_site_and): improve debug
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-autoderef.cc: remove useless assertion
+ * typecheck/rust-coercion.cc (TypeCoercionRules::coerce_unsafe_ptr): refactor
+ (TypeCoercionRules::coerce_borrowed_pointer): remove FIXME this is fine
+ * typecheck/rust-hir-inherent-impl-overlap.h: use types_compatable
+ * typecheck/rust-hir-path-probe.cc (PathProbeType::PathProbeType): remove const
+ (PathProbeType::Probe): likewise
+ (PathProbeImplTrait::PathProbeImplTrait): likewise
+ (PathProbeImplTrait::Probe): likewise
+ * typecheck/rust-hir-path-probe.h: likewise
+ * typecheck/rust-hir-type-check-base.cc (walk_types_to_constrain): likewise
+ * typecheck/rust-hir-type-check-base.h: likewise
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): use types_compatable
+ * typecheck/rust-hir-type-check.h: remove const
+ * typecheck/rust-typecheck-context.cc (TypeCheckContext::insert_associated_impl_mapping):
+ likewise
+ (TypeCheckContext::lookup_associated_impl_mapping_for_self): remove can_Eq
+ * typecheck/rust-tyty-bounds.cc (TypeBoundPredicate::is_equal): likewise
+ * typecheck/rust-tyty-subst.cc (SubstitutionArg::get_tyty): remove const version
+ * typecheck/rust-tyty-subst.h: likewise
+ * typecheck/rust-tyty.cc (BaseType::get_root): likewise
+ * typecheck/rust-tyty.h: likewise
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-tyty-subst.cc: track the const generic
+ * typecheck/rust-tyty.cc (ConstType::is_equal): finish the is_equal
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * hir/rust-hir-dump.cc (Dump::Dump): Initialize flag.
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * hir/rust-ast-lower-pattern.cc (ASTLoweringPattern::ASTLoweringPattern):
+ flag was not initialized in the constructor.
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * hir/rust-ast-lower-implitem.cc (ASTLowerTraitItem::visit): Remove
+ use after move.
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * expand/rust-macro-builtins-helpers.cc: Remove use after move.
+
+2025-08-05 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * ast/rust-ast-collector.cc: Add support for the 2 new classes.
+ * ast/rust-ast-collector.h: Header file update for above.
+ * ast/rust-ast-full-decls.h: Add forward decls for the 2 new classes.
+ * ast/rust-ast-visitor.cc: Add visit support for the 2 new classes.
+ * ast/rust-ast-visitor.h: Header file update for above.
+ * ast/rust-pattern.cc: Implementation of certain methods for the 2 new classes.
+ * ast/rust-pattern.h: Define the 2 new classes. Update SlicePattern to be able to hold
+ 2 kinds of items - SlicePatternItemsNoRest or SlicePatternItemsRest.
+ * expand/rust-cfg-strip.cc: Add support for the 2 new classes.
+ * expand/rust-cfg-strip.h: Header file update for above.
+ * expand/rust-derive.h: Add visits for the 2 new classes.
+ * hir/rust-ast-lower-base.cc: Add visits for the 2 new classes.
+ * hir/rust-ast-lower-base.h: Header file update for above.
+ * hir/rust-ast-lower-pattern.cc: Update lowering of SlicePattern to support
+ SlicePatternItemsNoRest.
+ * parse/rust-parse-impl.h (parse_slice_pattern()): Add support for parsing DOT_DOT into
+ respective SlicePatternItems.
+ * resolve/rust-ast-resolve-base.cc: Add visits for the 2 new classes.
+ * resolve/rust-ast-resolve-base.h: Header file update for above.
+ * resolve/rust-ast-resolve-pattern.cc: Update SlicePattern resolution to support new
+ classes.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-tyty-subst.cc: fix check for total arguments
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): create infer variable
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * hir/rust-hir-dump.cc (Dump::visit): check for expression
+ * hir/tree/rust-hir.cc (AnonConst::as_string): likewise
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * ast/rust-ast-collector.cc (TokenCollector::visit): check for value
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): formatting
+ * typecheck/rust-tyty-variance-analysis-private.h: likewise
+ * typecheck/rust-tyty.cc (VariantDef::clone): likewise
+ (VariantDef::monomorphized_clone): likewise
+ * typecheck/rust-tyty.h: likewise
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-base.cc: useful debug
+ * backend/rust-compile-stmt.cc (CompileStmt::visit): likewise
+ * backend/rust-compile-type.cc (TyTyResolveCompile::visit): fold the capacity into ConstType
+ * hir/tree/rust-hir-generic-param.h: make const
+ * hir/tree/rust-hir-path.h: take into account const arguments now
+ * typecheck/rust-hir-type-check-base.cc (TypeCheckBase::resolve_literal): needs const
+ * typecheck/rust-hir-type-check-base.h: add error handling for const supported locations
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): const type the arrays
+ * typecheck/rust-hir-type-check-implitem.cc (TypeCheckTopLevelExternItem::visit): update
+ (TypeCheckImplItem::visit): likewise
+ * typecheck/rust-hir-type-check-item.cc (TypeCheckItem::visit): likewise
+ (TypeCheckItem::resolve_impl_block_substitutions): likewise
+ * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit): wrap up const type
+ * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): likewise
+ (TypeResolveGenericParam::visit): likewise
+ (TypeResolveGenericParam::apply_trait_bounds): remove HIR::Generic from Param
+ * typecheck/rust-hir-type-check.cc (TraitItemReference::get_type_from_fn): cleanup
+ * typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::SubstitutionParamMapping):
+ handle const generics
+ (SubstitutionParamMapping::get_type_representation): likewise
+ (SubstitutionParamMapping::param_has_default_ty): likewise
+ (SubstitutionParamMapping::get_default_ty): likewise
+ (SubstitutionRef::infer_substitions): likewise
+ * typecheck/rust-tyty-subst.h: likewise
+ * typecheck/rust-tyty-util.cc (TyVar::get_implicit_const_infer_var): new helper
+ * typecheck/rust-tyty-util.h (class ConstType): likewise
+ * typecheck/rust-tyty.cc (BaseType::is_concrete): check for array const concrete
+ (ArrayType::as_string): update to const
+ (ArrayType::handle_substitions): likewise
+ (ParamType::ParamType): likewise
+ (ParamType::get_generic_param): likewise
+ (ParamType::clone): likewise
+ (ConstType::ConstType): likewise
+ (ConstType::set_value): likewise
+ (ConstType::clone): likewise
+ (ConstType::get_generic_param): likewise
+ (generate_tree_str): new helper to pretty print gimple
+ (ConstType::get_name): uses the generate_tree_str
+ (ConstType::handle_substitions): handle const infer's
+ * typecheck/rust-tyty.h (RUST_TYTY): likewise
+ * typecheck/rust-unify.cc (UnifyRules::expect_array): likewise
+ (UnifyRules::expect_const): likewise
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-type.cc (TyTyResolveCompile::visit): error_mark_node for const types
+ * backend/rust-compile-type.h: boilerplate
+ * checks/errors/borrowck/rust-bir-fact-collector.h: likewise
+ * checks/errors/borrowck/rust-bir-place.h: likewise
+ * checks/errors/privacy/rust-privacy-reporter.cc (PrivacyReporter::check_base_type_privacy):
+ likewise
+ * typecheck/rust-substitution-mapper.cc (SubstMapperInternal::visit): likewise
+ * typecheck/rust-substitution-mapper.h: likewise
+ * typecheck/rust-tyty-bounds.cc (TypeBoundsProbe::assemble_marker_builtins): likewise
+ * typecheck/rust-tyty-call.h: likewise
+ * typecheck/rust-tyty-cmp.h (class ConstCmp): likewise
+ * typecheck/rust-tyty-variance-analysis-private.h: likewise
+ * typecheck/rust-tyty-visitor.h: likewise
+ * typecheck/rust-tyty.cc (TypeKindFormat::to_string): likewise
+ (BaseType::is_unit): likewise
+ (BaseType::has_substitutions_defined): likewise
+ (BaseType::needs_generic_substitutions): likewise
+ (ConstType::ConstType): likewise
+ (ConstType::accept_vis): likewise
+ (ConstType::as_string): likewise
+ (ConstType::can_eq): likewise
+ (ConstType::clone): likewise
+ (ConstType::get_symbol): likewise
+ (ConstType::get_generic_param): likewise
+ (ConstType::can_resolve): likewise
+ (ConstType::resolve): likewise
+ (ConstType::get_name): likewise
+ (ConstType::is_equal): likewise
+ (ConstType::handle_substitions): likewise
+ * typecheck/rust-tyty.h (enum TypeKind): new tyty_kind
+ (class ConstType): new type
+ * typecheck/rust-unify.cc (UnifyRules::go): Handle a const type unify
+ (UnifyRules::expect_inference_variable): likewise
+ (UnifyRules::expect_adt): likewise
+ (UnifyRules::expect_str): likewise
+ (UnifyRules::expect_reference): likewise
+ (UnifyRules::expect_pointer): likewise
+ (UnifyRules::expect_param): likewise
+ (UnifyRules::expect_array): likewise
+ (UnifyRules::expect_slice): likewise
+ (UnifyRules::expect_fndef): likewise
+ (UnifyRules::expect_fnptr): likewise
+ (UnifyRules::expect_tuple): likewise
+ (UnifyRules::expect_bool): likewise
+ (UnifyRules::expect_char): likewise
+ (UnifyRules::expect_int): likewise
+ (UnifyRules::expect_uint): likewise
+ (UnifyRules::expect_float): likewise
+ (UnifyRules::expect_isize): likewise
+ (UnifyRules::expect_usize): likewise
+ (UnifyRules::expect_placeholder): likewise
+ (UnifyRules::expect_projection): likewise
+ (UnifyRules::expect_dyn): likewise
+ (UnifyRules::expect_closure): likewise
+ (UnifyRules::expect_const): likewise
+ * typecheck/rust-unify.h: new expect_const_type handler
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-intrinsic.cc (sizeof_handler): refactor types
+ (op_with_overflow_inner): likewise
+ (uninit_handler): likewise
+ (move_val_init_handler): likewise
+ * backend/rust-compile-resolve-path.cc (HIRCompileBase::query_compile): likewise
+ * typecheck/rust-hir-trait-resolve.cc: likewise
+ * typecheck/rust-hir-type-check-base.cc: likewise
+ * typecheck/rust-hir-type-check-item.cc: likewise
+ * typecheck/rust-tyty-bounds.cc (TypeBoundPredicate::is_equal): likewise
+ * typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::get_param_ty): likewise
+ (SubstitutionArg::get_param_mapping): likewise
+ (SubstitutionRef::prepare_higher_ranked_bounds): likewise
+ (SubstitutionRef::monomorphize): likewise
+ * typecheck/rust-tyty-subst.h (class BaseGeneric): new generic base
+ * typecheck/rust-tyty.cc (VariantDef::clone): likewise
+ (VariantDef::monomorphized_clone): refactor
+ (ADTType::is_equal): likewise
+ (FnType::is_equal): likewise
+ (ParamType::ParamType): likewise
+ * typecheck/rust-tyty.h (class ParamType): likewise
+ (class BaseGeneric): new base class impl
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-tyty.cc (ADTType::is_equal): let param::is_eq do this
+ (FnType::is_equal): remove whitespace
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-base.cc: check for type param
+ * typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::SubstitutionParamMapping):
+ return HIR::GenericParam base class
+ (SubstitutionParamMapping::get_generic_param): likewise
+ (SubstitutionParamMapping::get_type_representation): new helper
+ (SubstitutionParamMapping::param_has_default_ty): check for param type
+ (SubstitutionParamMapping::get_default_ty): likewise
+ * typecheck/rust-tyty-subst.h: get the locus from the subst HIR::GenericParam now
+ * typecheck/rust-tyty-variance-analysis.cc (GenericTyPerCrateCtx::debug_print_solutions):
+ likwise
+ (GenericTyVisitorCtx::process_type): likewise
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-expr.cc (CompileExpr::visit): check for ADTType instead of assert
+
+2025-08-05 Ryutaro Okada <1015ryu88@gmail.com>
+
+ * checks/lints/rust-lint-unused-var.cc (check_decl):
+ Do not warn about unused `self` parameter.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * Make-lang.in:
+ * ast/rust-expression-yeast.cc (ExpressionYeast::dispatch_loops): Call DesugarWhileLet.
+ * ast/rust-desugar-while-let.cc: New file.
+ * ast/rust-desugar-while-let.h: New file.
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-ast.cc (AttrInputMacro::operator=): Add return type.
+ * ast/rust-expr.h: Likewise.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-desugar-for-loops.cc: Remove functions implemented in AST::Builder.
+ * ast/rust-desugar-for-loops.h: Likewise.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * hir/rust-ast-lower-base.cc: Add rust_unreachable() when lowering desugared exprs.
+ * hir/rust-ast-lower-base.h: Mention this.
+ * hir/rust-ast-lower-block.h: Remove existing definitions.
+ * hir/rust-ast-lower-expr.cc: Likewise.
+ * hir/rust-ast-lower-expr.h: Likewise.
+ * hir/rust-ast-lower.cc: Likewise.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-desugar-question-mark.cc (DesugarQuestionMark::go): Add assertion for the
+ expr's type.
+ * ast/rust-desugar-try-block.cc (DesugarTryBlock::go): Likewise.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-desugar-for-loops.h: Adapt API and remove visitor.
+ * ast/rust-desugar-for-loops.cc: Likewise.
+ * ast/rust-expression-yeast.cc: Call DesugarForLoop.
+ * ast/rust-expression-yeast.h: Declare dispatch_loops function.
+ * rust-session-manager.cc (Session::expansion): Do not call for-loop desugar.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * hir/tree/rust-hir-expr.h (class OffsetOf): New.
+ * hir/tree/rust-hir-expr.cc: Define its methods.
+ * hir/tree/rust-hir-expr-abstract.h: Add ExprType::OffsetOf.
+ * hir/tree/rust-hir-full-decls.h (class OffsetOf): Declare it.
+ * backend/rust-compile-block.h: Add handling for OffsetOf.
+ * backend/rust-compile-expr.cc (CompileExpr::visit): Likewise.
+ * backend/rust-compile-expr.h: Likewise.
+ * checks/errors/borrowck/rust-bir-builder-expr-stmt.cc (ExprStmtBuilder::visit): Likewise.
+ * checks/errors/borrowck/rust-bir-builder-expr-stmt.h (RUST_BIR_BUILDER_EXPR_H): Likewise.
+ * checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h: Likewise.
+ * 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 (RUST_PRIVACY_REPORTER_H): Likewise.
+ * checks/errors/rust-const-checker.cc (ConstChecker::visit): Likewise.
+ * checks/errors/rust-const-checker.h: Likewise.
+ * checks/errors/rust-hir-pattern-analysis.cc (PatternChecker::visit): Likewise.
+ * checks/errors/rust-hir-pattern-analysis.h: Likewise.
+ * checks/errors/rust-unsafe-checker.cc (UnsafeChecker::visit): Likewise.
+ * checks/errors/rust-unsafe-checker.h: Likewise.
+ * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise.
+ * hir/rust-hir-dump.cc (Dump::visit): Likewise.
+ * hir/rust-hir-dump.h: Likewise.
+ * hir/tree/rust-hir-visitor.cc (DefaultHIRVisitor::walk): Likewise.
+ * hir/tree/rust-hir-visitor.h: Likewise.
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Likewise.
+ * typecheck/rust-hir-type-check-expr.h (RUST_HIR_TYPE_CHECK_EXPR): Likewise.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * Make-lang.in: Compile the offset_of handler.
+ * lang.opt: Add -frust-assume-builtin-offset-of option.
+ * ast/rust-ast.h: Add has_str() for const_TokenPtr.
+ * expand/rust-macro-builtins.cc: Map offset_of as builtin.
+ * expand/rust-macro-builtins.h: Declare it.
+ * expand/rust-macro-expand.cc (MacroExpander::expand_invoc): Add hack for calling builtin
+ offset_of!().
+ * resolve/rust-early-name-resolver-2.0.cc (Early::visit): Likewise.
+ * expand/rust-macro-builtins-offset-of.cc: New file.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast.h: Add OffsetOf expression kind.
+ * ast/rust-builtin-ast-nodes.h (class OffsetOf): Add node.
+ * ast/rust-ast.cc: Define it.
+ * ast/rust-ast-collector.cc: Add visitor for OffsetOf.
+ * ast/rust-ast-collector.h: Likewise.
+ * ast/rust-ast-visitor.cc: Likewise.
+ * ast/rust-ast-visitor.h: Likewise.
+ * hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Likewise.
+ * hir/rust-ast-lower-base.h: Likewise.
+ * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise.
+ * hir/rust-ast-lower-expr.h: Likewise.
+ * resolve/rust-ast-resolve-base.cc (ResolverBase::visit): Likewise.
+ * resolve/rust-ast-resolve-base.h: Likewise.
+ * resolve/rust-early-name-resolver-2.0.cc: Likewise.
+ * expand/rust-derive.h:
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * rust-diagnostics.h (struct Error): Add disambiguation.
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * expand/rust-macro-builtins-asm.cc (parse_format_strings): Emit an
+ error when expecting a comma.
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * checks/errors/borrowck/rust-bir-fact-collector.h: Remove spurious
+ comment.
+ * checks/errors/rust-feature.cc: Likewise.
+ * util/optional.h: Likewise.
+ * expand/rust-token-tree-desugar.cc (TokenTreeDesugar::visit): Remove
+ semicolons on namespace.
+ * expand/rust-token-tree-desugar.h: Likewise.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * typecheck/rust-hir-type-check-base.cc
+ (TypeCheckBase::TypeCheckBase): Remove initialization of
+ resolver field.
+ * typecheck/rust-hir-type-check-base.h
+ (TypeCheckBase::resolver): Remove field.
+ * typecheck/rust-hir-trait-resolve.cc: Remove "options.h"
+ include.
+ (TraitResolver::resolve_path_to_trait): Assume name resolution
+ 2.0 is always enabled.
+ * typecheck/rust-hir-type-check-enumitem.cc: Remove "options.h"
+ include.
+ (TypeCheckEnumItem::visit): Assume name resolution 2.0 is always
+ enabled.
+ * typecheck/rust-hir-type-check-expr.cc: Remove "options.h"
+ include.
+ (TypeCheckExpr::visit): Assume name resolution 2.0 is always
+ enabled.
+ (TypeCheckExpr::resolve_operator_overload): Likewise.
+ (TypeCheckExpr::resolve_fn_trait_call): Likewise.
+ * typecheck/rust-hir-type-check-implitem.cc: Remove "options.h"
+ include.
+ (TypeCheckImplItem::visit): Assume name resolution 2.0 is always
+ enabled.
+ * typecheck/rust-hir-type-check-item.cc: Remove "options.h"
+ include.
+ (TypeCheckItem::visit): Assume name resolution 2.0 is always
+ enabled.
+ * typecheck/rust-hir-type-check-path.cc (TypeCheckExpr::visit):
+ Likewise.
+ (TypeCheckExpr::resolve_root_path): Likewise.
+ (TypeCheckExpr::resolve_segments): Likewise.
+ * typecheck/rust-hir-type-check-pattern.cc: Remove "options.h"
+ include.
+ (TypeCheckPattern::visit): Assume name resolution 2.0 is always
+ enabled.
+ * typecheck/rust-hir-type-check-type.cc
+ (TypeCheckType::resolve_root_path): Likewise.
+ (ResolveWhereClauseItem::visit): Likewise.
+ * typecheck/rust-hir-type-check.cc: Remove "options.h" include.
+ (TraitItemReference::get_type_from_fn): Assume name resolution
+ 2.0 is always enabled.
+ * typecheck/rust-type-util.cc (query_type): Likewise.
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * backend/rust-compile-asm.cc (get_out_expr): Return valid output from
+ an operand.
+ (CompileAsm::asm_construct_outputs): Handle every output
+ (get_in_expr): Return valid input from an operand.
+ (CompileAsm::asm_construct_inputs): Handle every input
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * expand/rust-macro-builtins-asm.cc (parse_reg_operand_inout): Parse
+ expressions and build split in out.
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * hir/rust-hir-dump.cc (Dump::visit): Dump inline assembly fields
+ * hir/tree/rust-hir-expr.h: Add non const getter and avoid operand copy
+ from getters.
+ * hir/tree/rust-hir-visitor.cc (DefaultHIRVisitor::walk): Use non const
+ reference.
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * expand/rust-macro-builtins-asm.cc (expand_inline_asm_strings): Handle
+ transformation for indexed positional arguments.
+
+2025-08-05 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * rust-backend.h: New slice_index_expression function.
+ * rust-gcc.cc: Implementation of slice_index_expression to generate tree node for
+ accessing slice elements.
+ * backend/rust-compile-pattern.cc: Implement SlicePattern check expression & binding
+ compilation against SliceType scrutinee.
+
+2025-08-05 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit(SlicePattern)):
+ Add new type check case for SliceType wrapped in ReferenceType.
+ * backend/rust-compile-pattern.cc: Adjusted the asserts accordingly for
+ CompilePatternCheckExpr(SlicePattern) & CompilePatternBindings(SlicePattern).
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * Make-lang.in: Compile it.
+ * ast/rust-expression-yeast.cc (ExpressionYeast::dispatch): Dispatch to try-block
+ desugar.
+ * ast/rust-desugar-try-block.cc: New file.
+ * ast/rust-desugar-try-block.h: New file.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast.h: Add the new variant.
+ * ast/rust-expr.h: Use it for TryExpr class.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-default-resolver.cc (DefaultResolver::visit): Add
+ visitor for IfLetExprConseqElse.
+ * resolve/rust-default-resolver.h (DefaultResolver::visit):
+ Likewise.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Visit a block's loop label if it
+ exists.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * Make-lang.in: Compile it.
+ * rust-session-manager.cc: Call the expression desugar dispatcher.
+ * ast/rust-desugar-question-mark.cc: Rework class API.
+ * ast/rust-desugar-question-mark.h: Likewise.
+ * ast/rust-expression-yeast.cc: New file.
+ * ast/rust-expression-yeast.h: New file.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-expr.h: Fix formatting.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Handle defered consts.
+ * hir/tree/rust-hir-expr.cc (AnonConst::AnonConst): Likewise.
+ (AnonConst::operator=): Likewise.
+ * hir/tree/rust-hir-expr.h: Likewise.
+ * hir/tree/rust-hir-visitor.cc (DefaultHIRVisitor::walk): Likewise.
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Likewise.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-expr.h: Add handling for deferred consts.
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise.
+ * ast/rust-ast.cc (AnonConst::as_string): Likewise.
+ (ArrayType::as_string): Likewise.
+ * ast/rust-type.h (class ArrayType): Use AnonConst for sizes.
+ * parse/rust-parse-impl.h (Parser::parse_anon_const): New function.
+ (Parser::parse_slice_or_array_type): Call it.
+ * parse/rust-parse.h: Declare it.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * resolve/rust-early-name-resolver-2.0.cc (Early::resolve_glob_import): Adapt for enums.
+ (Early::finalize_glob_import): Likewise.
+ * resolve/rust-early-name-resolver-2.0.h: Likewise.
+ * resolve/rust-finalize-imports-2.0.cc (GlobbingVisitor::go): Likewise.
+ (GlobbingVisitor::visit_module_container): New function.
+ (GlobbingVisitor::visit_enum_container): New function.
+ * resolve/rust-finalize-imports-2.0.h: Declare them.
+ * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit): Insert enums as potential
+ containers.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * util/rust-hir-map.cc (Mappings::insert_ast_module): Rename to...
+ (Mappings::insert_glob_container): ...this.
+ (Mappings::lookup_ast_module): Rename to...
+ (Mappings::lookup_glob_container): ...this.
+ * util/rust-hir-map.h: Change declarations.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * expand/rust-cfg-strip.cc (CfgStrip::visit): Load unloaded
+ modules.
+ * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit):
+ Assume modules have been loaded by CfgStrip.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * expand/rust-expand-visitor.cc
+ (ExpandVisitor::expand_inner_items): Adjust call to
+ expand_macro_children.
+ (ExpandVisitor::expand_inner_stmts): Likewise.
+ (ExpandVisitor::visit): Likewise.
+ * expand/rust-expand-visitor.h
+ (ExpandVisitor::expand_macro_children): Take a pointer to member
+ function instead of a std::function.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-resolve-path.cc (HIRCompileBase::query_compile): do another lookup
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-ast.cc: Include "rust-macro-invoc-lexer.h".
+ (AttributeParser::~AttributeParser): Move function definition
+ here.
+ (AttributeParser::AttributeParser): Likewise and adjust member
+ initialization.
+ (AttributeParser::parse_meta_item_inner): Handle changes to
+ peek_token.
+ (AttributeParser::parse_literal): Likewise.
+ (AttributeParser::parse_simple_path_segment): Likewise.
+ (AttributeParser::parse_meta_item_seq): Handle changes to
+ AttributeParser fields.
+ (AttributeParser::peek_token): Move function definition here and
+ wrap MacroInvocLexer.
+ (AttributeParser::skip_token): Likewise.
+ * ast/rust-macro.h (class MacroInvocLexer): Forward declare.
+ (class Parser): Likewise.
+ (AttributeParser::token_stream): Remove field.
+ (AttributeParser::stream_pos): Likewise.
+ (AttributeParser::lexer): New field.
+ (AttributeParser::parser): Likewise.
+ (AttributeParser::AttributeParser): Move definition to
+ "rust-ast.cc".
+ (AttributeParser::~AttributeParser): Likewise.
+ (AttributeParser::peek_token): Likewise.
+ (AttributeParser::skip_token): Likewise.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-resolve-path.cc (ResolvePathRef::resolve): return error_mark_node
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * hir/tree/rust-hir-expr.cc (OperatorExprMeta::OperatorExprMeta): track the rhs
+ * hir/tree/rust-hir-expr.h: likewise
+ * hir/tree/rust-hir-path.h: get rid of old comments
+ * typecheck/rust-hir-trait-reference.cc (TraitReference::get_trait_substs): return
+ references instead of copy
+ * typecheck/rust-hir-trait-reference.h: update header
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::ResolveOpOverload): write ambigious
+ operator overloads to a table and try to resolve it at the end
+ * typecheck/rust-hir-type-check-expr.h: new static helper
+ * typecheck/rust-hir-type-check.h (struct DeferredOpOverload): new model to defer resolution
+ * typecheck/rust-typecheck-context.cc (TypeCheckContext::lookup_operator_overload): new
+ (TypeCheckContext::compute_ambigious_op_overload): likewise
+ (TypeCheckContext::compute_inference_variables): likewise
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-base.cc: check the canonical path
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * parse/rust-parse-impl.h (Parser::parse_simple_path): Be more
+ careful about skipping SCOPE_RESOLUTION tokens.
+ (Parser::parse_simple_path_segment): Allow parsing from a
+ starting offset.
+ (Parser::parse_use_tree): Handle a non-skipped SCOPE_RESOLUTION
+ token.
+ * parse/rust-parse.h (Parser::parse_simple_path_segment): Add
+ parameter for parsing from a starting offset.
+
+2025-08-05 lishin <lishin1008@gmail.com>
+
+ * backend/rust-compile-expr.cc (CompileExpr::visit): Add a catch for const/static.
+
+2025-08-05 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * rust-backend.h: New size_constant_expression function.
+ * rust-gcc.cc: Implementation of size_constant_expression function to generate tree node
+ for array access.
+ * backend/rust-compile-pattern.h: Remove empty visits for SlicePattern.
+ * backend/rust-compile-pattern.cc: Implement SlicePattern check expression & binding
+ compilation against ArrayType scrutinee.
+
+2025-08-05 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * typecheck/rust-hir-type-check-pattern.cc(TypeCheckPattern::visit(SlicePattern)):
+ Implement size checking for SlicePattern when type checking against array parent
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * util/rust-attribute-values.h: Add declarations for them.
+ * util/rust-attributes.cc: Add definitions.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-struct.cc (TypeCheckStructExpr::visit): fix typo
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-casts.cc (TypeCastRules::resolve): optional emit_error flag
+ (TypeCastRules::check): try the simple cast rules then fallback to coercions
+ (TypeCastRules::check_ptr_ptr_cast): ensure the underlying's
+ (TypeCastRules::emit_cast_error): make this a static helper
+ * typecheck/rust-casts.h: new emit_error prototype
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Check for a label
+ before visiting it.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-trait-resolve.cc (TraitResolver::resolve_trait): track is super trait
+ * typecheck/rust-hir-type-bounds.h: refactor bounds scan
+ * typecheck/rust-hir-type-check-base.h: track from super trait
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): likewise
+ * typecheck/rust-tyty-bounds.cc (TypeBoundsProbe::is_bound_satisfied_for_type): refactor
+ (TypeBoundsProbe::scan): likewise
+ (TypeBoundPredicate::apply_generic_arguments): likewise
+ * typecheck/rust-tyty-subst.cc: optional bounds checking on parm subst
+ * typecheck/rust-tyty-subst.h: likewise
+ * typecheck/rust-tyty.h: likewise
+
+2025-08-05 Marc Poulhiès <dkm@kataplop.net>
+
+ * checks/errors/borrowck/rust-bir-place.h (LoanId::value): Make
+ it size_t to match Loan's base type.
+
+2025-08-05 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * typecheck/rust-hir-type-check-pattern.cc(TypeCheckPattern::visit(LiteralPattern)):
+ Check LiteralPattern's type against its parent.
+
+2025-08-05 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit(SlicePattern)):
+ Implement initial type checking for SlicePattern.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * ast/rust-ast-collector.cc (TokenCollector::visit): check for missing borrow
+ * ast/rust-expr.h: add helper
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-base.cc (HIRCompileBase::query_compile_const_expr): new wrapper
+ * backend/rust-compile-base.h: add prototype
+ * backend/rust-compile-context.cc (Context::get): singleton helper
+ * backend/rust-compile-context.h: likewise
+ * backend/rust-compile-type.cc (TyTyResolveCompile::visit): handle infer's that can default
+ * rust-session-manager.cc (Session::compile_crate): create the gcc context earlier for tychk
+ * typecheck/rust-hir-type-check-base.cc (TypeCheckBase::resolve_literal): const fold it
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): likewise
+ * typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): likewise
+ * typecheck/rust-tyty.cc (BaseType::monomorphized_clone): fix constructor call
+ (ArrayType::as_string): print capacity
+ (ArrayType::clone): fix constructor call
+ * typecheck/rust-tyty.h: track capacity
+ * typecheck/rust-unify.cc (UnifyRules::expect_array): check the capacities
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): New visitor.
+ * resolve/rust-late-name-resolver-2.0.h: Declare it.
+ * resolve/rust-name-resolution-context.h (enum class): New binding context.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Check that the WhileLet has a label
+ before visiting it.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-ast-collector.cc (TokenCollector::visit): Add visitor
+ for TryExpr.
+ * ast/rust-ast-collector.h (TokenCollector::visit): Likewise.
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise.
+ * ast/rust-ast-visitor.h (ASTVisitor::visit): Likewise.
+ (DefaultASTVisitor::visit): Likewise.
+ * expand/rust-derive.h (DeriveVisitor::visit): Likewise.
+ * hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Likewise.
+ * hir/rust-ast-lower-base.h (ASTLoweringBase::visit): Likewise.
+ * resolve/rust-ast-resolve-base.cc (ResolverBase::visit):
+ Likewise.
+ * resolve/rust-ast-resolve-base.h (ResolverBase::visit):
+ Likewise.
+ * ast/rust-ast-full-decls.h (class TryExpr): New forward class
+ declaration.
+ * ast/rust-ast.cc (TryExpr::as_string): New function.
+ (TryExpr::accept_vis): Likewise.
+ * ast/rust-expr.h (class TryExpr): New class.
+ * parse/rust-parse.h (Parser::parse_try_expr): New function.
+ * parse/rust-parse-impl.h (Parser::parse_try_expr): Likewise.
+ (Parser::null_denotation_not_path): Use parse_try_expr to parse
+ try expressions.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * expand/rust-macro-builtins-format-args.cc
+ (format_args_parse_arguments): Accept a RAW_STRING_LITERAL token
+ as the first argument.
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * parse/rust-parse-impl.h: Add enum prefix.
+ * parse/rust-parse.h (enum ParseSelfError): Change from enum...
+ (enum class): To enum class.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Replace
+ usages of reinterpret_cast with static_cast.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Remove
+ override for StructStruct visitor.
+ * resolve/rust-late-name-resolver-2.0.h (Late::visit): Likewise.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * backend/rust-compile-context.cc (Context::Context): Remove
+ initialization of resolver field.
+ * backend/rust-compile-context.h (Context::get_resolver): Remove
+ function.
+ (Context::resolver): Remove field.
+ * backend/rust-compile-expr.cc (CompileExpr::visit): Assume name
+ resolution 2.0 is always enabled.
+ (CompileExpr::generate_closure_function): Likewise.
+ * backend/rust-compile-implitem.cc (CompileTraitItem::visit):
+ Likewise.
+ * backend/rust-compile-item.cc (CompileItem::visit): Likewise.
+ * backend/rust-compile-resolve-path.cc
+ (ResolvePathRef::resolve): Likewise.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * lang.opt (frust-name-resolution-2.0): Enable by default.
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * backend/rust-compile-pattern.cc (CompilePatternCheckExpr::visit(TuplePattern)):
+ Implement check expression compilation for TuplePatternItems::RANGED.
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * typecheck/rust-hir-type-check-pattern.cc (visit(TuplePattern)): Fix
+ incorrect logic for field size checking.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast-builder.cc: Remove extra include, fix new formatting.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast.h (reconstruct_vec): Pre-allocate size of vector.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * Make-lang.in: Remove object file for ASTTypeBuilder.
+ * ast/rust-ast-builder.h: Remove function.
+ * ast/rust-ast-builder.cc (Builder::new_type): Likewise.
+ (Builder::new_const_param): Use reconstruct_type() instead.
+ (Builder::new_generic_args): Likewise.
+ * expand/rust-derive-default.cc (DeriveDefault::visit_struct): Likewise.
+ (DeriveDefault::visit_tuple): Likewise.
+ * expand/rust-derive-eq.cc (DeriveEq::visit_tuple): Likewise.
+ (DeriveEq::visit_struct): Likewise.
+ (DeriveEq::visit_enum): Likewise.
+ (DeriveEq::visit_union): Likewise.
+ * ast/rust-ast-builder-type.cc: Removed.
+ * ast/rust-ast-builder-type.h: Removed.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast.h: Add reconstruct() and reconstruct_impl() for Type nodes.
+ * ast/rust-type.h: Implement them.
+ * ast/rust-macro.h: Likewise.
+ * ast/rust-path.h: Likewise.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast.h (reconstruct): New function for calling the `reconstruct_*_impl` method
+ and asserting that the new NodeId is different, and then wrap it in a unique_ptr<T>.
+ (reconstruct_vec): Likewise, but for vectors of unique_ptr<T>
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-forever-stack.hxx (ForeverStack::resolve_path):
+ Resolve final segments which point to modules.
+ * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit):
+ Avoid inserting module names into ribs in the type namespace.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-late-name-resolver-2.0.cc
+ (visit_identifier_as_pattern): Handle is_ref and is_mut.
+ (Late::visit): Likewise.
+ * resolve/rust-name-resolution-context.cc
+ (BindingLayer::insert_ident): Likewise.
+ (BindingLayer::bind_test): Handle changes to BindingLayer
+ fields.
+ (BindingLayer::merge): Likewise and emit more error messages.
+ * resolve/rust-name-resolution-context.h
+ (struct IdentifierMode): New.
+ (Binding::has_expected_bindings): New field.
+ (Binding::set): Rename field to...
+ (Binding::idents): ...here and convert from a set to a map.
+ (Binding::Binding): Initialize has_expected_bindings.
+ (BindingLayer::insert_ident): Adjust parameters.
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * ast/rust-expr.h: Add getter to locus field.
+ * ast/rust-pattern.h (tokenid_to_rangekind): Likewise.
+ * hir/tree/rust-hir-item.h: Likewise.
+ * hir/tree/rust-hir-visibility.h: Likewise.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-default-resolver.cc
+ (DefaultResolver::visit_extern_crate): New function.
+ (DefaultResolver::visit): New visitor function for ExternCrate.
+ * resolve/rust-default-resolver.h
+ (DefaultResolver::visit_extern_crate): New function.
+ (DefaultResolver::visit): New visitor function for ExternCrate.
+ * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit):
+ Adjust ExternCrate visitor and rename to...
+ (TopLevel::visit_extern_crate): ...here.
+ * resolve/rust-toplevel-name-resolver-2.0.h (TopLevel::visit):
+ Remove ExternCrate visitor override.
+ (TopLevel::visit_extern_crate): New function.
+ * rust-session-manager.cc (Session::load_extern_crate): Only run
+ name resolution 1.0 if name resolution 2.0 is disabled.
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit(TuplePattern)):
+ Implement type checking for ItemType::RANGED.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * rust-lang.cc: Move version check from C++11 to C++14.
+
+2025-08-05 Ryutaro Okada <1015ryu88@gmail.com>
+
+ * Make-lang.in: Scaffolding new rust-hir-visitor files
+ * hir/tree/rust-hir-visitor.h (DefaultHIRVisitor): Declare default HIR visitor
+ * hir/tree/rust-hir-visitor.cc (DefaultHIRVisitor): Define default HIR visitor
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * Make-lang.in (GRS_OBJS): Add rust-ggc.o.
+ * backend/rust-compile-base.cc
+ (HIRCompileBase::compile_function): Adjust call to
+ Backend::function.
+ (HIRCompileBase::compile_constant_item): Likewise and adjust
+ initialization of Backend::typed_identifier.
+ * backend/rust-compile-expr.cc (CompileExpr::visit): Adjust call
+ to Backend::label.
+ * backend/rust-compile-type.cc (TyTyResolveCompile::visit):
+ Adjust initialization of Backend::typed_identifier.
+ * rust-backend.h: Add includes.
+ (Backend::GGC::Ident): Use Rust::GGC::Ident.
+ (struct typed_identifier): Store name as a GGC::Ident rather
+ than a std::string and adjust constructors.
+ (named_type): Take GGC::Ident/tl::optional<GGC::Ident> rather
+ than std::string.
+ (global_variable): Likewise.
+ (local_variable): Likewise.
+ (parameter_variable): Likewise.
+ (static_chain_variable): Likewise.
+ (label): Likewise.
+ (function): Likewise.
+ * rust-gcc.cc (named_type): Likewise.
+ (global_variable): Likewise.
+ (local_variable): Likewise.
+ (parameter_variable): Likewise.
+ (static_chain_variable): Likewise.
+ (label): Likewise.
+ (function): Likewise.
+ (function_defer_statement): Adjust call to Backend::label.
+ (get_identifier_from_string): Remove function.
+ (fill_in_fields): Handle adjustments to typed_identifier.
+ * util/rust-ggc.cc: New file.
+ * util/rust-ggc.h: New file.
+
+2025-08-05 Ryutaro Okada <1015ryu88@gmail.com>
+
+ * hir/tree/rust-hir-item.h (SelfParam::get_lifetime): Add getter
+ for non const lifetime object
+
+2025-08-05 Ryutaro Okada <1015ryu88@gmail.com>
+
+ * hir/tree/rust-hir-expr.h (MatchArm::get_outer_attrs): Add getter for outer attributions
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-resolve-path.cc: if this fails fall back to query compile
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-expr.cc (CompileExpr::visit): add const call check
+ * backend/rust-compile-item.cc (CompileItem::visit): ensure we upfront compile types where
+ possible
+ * backend/rust-compile-item.h: update header
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): make parent ctx optional
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * backend/rust-compile-pattern.cc(CompilePatternCheckExpr::visit(TupleStructPattern)):
+ Fix error thrown when compiling non-enum TupleStructPattern.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-default-resolver.cc (DefaultResolver::visit):
+ Call DefaultASTVisitor::visit even on ConstantItem instances
+ without expressions.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-unify.cc (UnifyRules::expect_fnptr): add unify rules
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-trait-reference.cc (TraitReference::on_resolved): ensure associated
+ types are done first
+ * typecheck/rust-hir-type-check-type.cc: Update call site.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-tyty-bounds.cc: Check super traits for type bindings.
+ * typecheck/rust-tyty.h: Add helper methods for bound checking.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-bounds.h: Rename method.
+ * typecheck/rust-tyty-bounds.cc: Refactor marker trait assembly
+ and add proper Fn trait handling for function types.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-dot-operator.cc: Major refactoring and cleanup.
+ * typecheck/rust-hir-dot-operator.h: Add new helper methods.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-trait-resolve.cc: Add cyclical projection
+ protection.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check-expr.cc: Look at bounds behind
+ references.
+ * typecheck/rust-hir-type-check-expr.h: Add helper method.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * rust-session-manager.cc (Session::compile_crate): Move
+ AST desugaring to...
+ (Session::expansion): ...here and add a final TopLevel pass
+ afterwards.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): check for has_expr
+ * hir/rust-hir-dump.cc (Dump::visit): likewise
+ * hir/tree/rust-hir-item.h: add has_expr helper
+ * resolve/rust-ast-resolve-item.cc (ResolveItem::visit): check for has_expr
+ * resolve/rust-ast-resolve-stmt.h: likewise
+ * typecheck/rust-hir-type-check-stmt.cc (TypeCheckStmt::visit): likewise
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): Add
+ visitor for ExternCrate.
+ * hir/rust-ast-lower-item.h (ASTLoweringItem::visit): Likewise.
+ * rust-session-manager.cc (Session::load_extern_crate): Avoid
+ lowering or type resolving external crates here.
+ * typecheck/rust-hir-type-check-item.cc (TypeCheckItem::visit):
+ Add visitor for ExternCrate.
+ * typecheck/rust-hir-type-check-item.h (TypeCheckItem::visit):
+ Replace empty definition with a declaration.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-tyty.cc (ParamType::handle_substitions): make this consistent
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit(IdentifierPattern)):
+ Remove redundant subpattern check.
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * backend/rust-compile-pattern.cc: Add support for IdentifierPattern's
+ subpattern under CompilePatternBindings.
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * resolve/rust-ast-resolve-pattern.cc: Implement name resolution for
+ IdentifierPattern's subpattern.
+ * resolve/rust-late-name-resolver-2.0.cc: Ditto, but for nr2.
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * ast/rust-ast-collector.cc: Rename get_pattern_to_bind to get_subpattern
+ * ast/rust-ast-visitor.cc: Ditto.
+ * ast/rust-pattern.h: Ditto.
+ * expand/rust-cfg-strip.cc: Ditto.
+ * hir/rust-ast-lower-pattern.cc: Ditto.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-default-resolver.cc (DefaultResolver::visit):
+ Adjust scoping of trait definitions and their generic
+ parameters.
+ * resolve/rust-forever-stack.hxx (ForeverStack::get): Prevent
+ lookups inside TraitOrImpl ribs.
+ (ForeverStack::resolve_segments): Prevent lookups of the first
+ segment inside TraitOrImpl ribs.
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * hir/rust-hir-dump.cc: Change pattern dumps to use visit_field.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive.cc: Fix formatting after fork update.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-cmp-common.cc (EnumMatchBuilder::tuple): Create two different
+ variant paths.
+ (EnumMatchBuilder::strukt): Likewise.
+ * expand/rust-derive-cmp-common.h: Change API.
+ * expand/rust-derive-ord.cc (DeriveOrd::visit_enum): Use new EnumMatchBuilder API.
+ * expand/rust-derive-partial-eq.cc (DerivePartialEq::visit_enum): Likewise.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-ord.cc (DeriveOrd::make_cmp_arms): Use new make_equal function.
+ (DeriveOrd::make_equal): New function.
+ (DeriveOrd::recursive_match): Handle the unit struct/tuple case.
+ * expand/rust-derive-ord.h: Declare make_equal.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-ord.cc (DeriveOrd::cmp_call): Use references.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-ord.cc (DeriveOrd::make_cmp_arms): Fix condition.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-ord.cc: Finish implementation for enums.
+ * expand/rust-derive-ord.h: Likewise.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-partial-eq.cc (DerivePartialEq::eq_fn): Change signature.
+ (DerivePartialEq::visit_tuple): Use new eq_fn API.
+ (DerivePartialEq::visit_struct): Likewise.
+ (DerivePartialEq::visit_enum): Implement proper discriminant comparison.
+ * expand/rust-derive-partial-eq.h: Change eq_fn signature.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-cmp-common.h (class EnumMatchBuilder): New helper class.
+ * expand/rust-derive-cmp-common.cc (EnumMatchBuilder::tuple): New function.
+ (EnumMatchBuilder::strukt): New function.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast-builder.h: Put `loc` member in public.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-ord.cc (DeriveOrd::cmp_call): New function.
+ (DeriveOrd::recursive_match): Use it.
+ (DeriveOrd::visit_enum): Likewise.
+ * expand/rust-derive-ord.h: Declare it.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-hash.cc (DeriveHash::visit_enum): Use new APIs.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast-builder.cc (Builder::discriminant_value): New function.
+ * ast/rust-ast-builder.h: Declare it.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-ord.cc (is_last): Remove.
+ (DeriveOrd::visit_tuple): Fix implementation.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-cmp-common.cc (SelfOther::indexes): Fix formatting.
+ (SelfOther::fields): Make iterator const.
+ * expand/rust-derive-cmp-common.h (struct SelfOther): New declaration for indexes.
+ * expand/rust-derive-partial-eq.cc (DerivePartialEq::visit_tuple): Use the new API.
+ (DerivePartialEq::visit_struct): Likewise.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-ord.cc (DeriveOrd::make_cmp_arms): New function.
+ (is_last): Likewise.
+ (recursive_match): Likewise.
+ (DeriveOrd::recursive_match): Likewise.
+ (DeriveOrd::visit_struct): Add proper implementation.
+ (DeriveOrd::visit_union): Likewise.
+ * expand/rust-derive-ord.h: Declare these new functions.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-partial-eq.cc (DerivePartialEq::tuple_indexes): Remove.
+ (DerivePartialEq::field_acccesses): Remove.
+ (DerivePartialEq::visit_tuple): Use new API.
+ (DerivePartialEq::visit_struct): Likewise.
+ * expand/rust-derive-partial-eq.h: Remove declarations.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-cmp-common.cc: New file.
+ * expand/rust-derive-cmp-common.h: New file.
+ * Make-lang.in: Compile them.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast-builder.cc (Builder::block): New function.
+ (Builder::match_case): Likewise.
+ * ast/rust-ast-builder.h: Declare them.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast-builder.cc (Builder::new_const_param): New function.
+ * ast/rust-ast-builder.h (vec): New function for creating 3 elts vector.
+ * expand/rust-derive.cc: Use the new_const_param builder.
+ * ast/rust-path.h: Add get_default_value() method.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * Make-lang.in: Compile it.
+ * expand/rust-derive.cc (DeriveVisitor::derive): Call them.
+ * expand/rust-derive-ord.cc: New file.
+ * expand/rust-derive-ord.h: New file.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-clone.h: Add missing override qualifiers to DeriveVisitor methods.
+ * expand/rust-derive-copy.h: Likewise.
+ * expand/rust-derive-eq.h: Likewise.
+ * expand/rust-derive-hash.h: Likewise.
+ * expand/rust-derive-partial-eq.h: Likewise.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * resolve/rust-rib.h: Add missing switch cases.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-type-util.cc (query_type): early return.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-type.cc (TyTyResolveCompile::visit): reuse GCC's build_array_type
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-late-name-resolver-2.0.cc
+ (visit_identifier_as_pattern): Make sure to map identifiers
+ inside or-bindings to prior identifiers.
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * ast/rust-ast-collector.cc: Rename to_bind to subpattern.
+ * ast/rust-ast-visitor.cc: Ditto.
+ * ast/rust-pattern.cc: Ditto.
+ * ast/rust-pattern.h: Ditto.
+ * backend/rust-compile-pattern.cc: Ditto.
+ * expand/rust-cfg-strip.cc: Ditto.
+ * hir/rust-ast-lower-pattern.cc: Ditto.
+ * hir/rust-hir-dump.cc: Ditto.
+ * hir/tree/rust-hir-pattern.h: Ditto.
+ * hir/tree/rust-hir.cc: Ditto.
+ * typecheck/rust-hir-type-check-pattern.cc: Ditto.
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * backend/rust-compile-pattern.cc: Add CheckExpr compilation for
+ IdentifierPattern with subpattern.
+ * backend/rust-compile-pattern.h: Modify IdentifierPattern's
+ visit func to support the above.
+ * typecheck/rust-hir-type-check-pattern.cc: Add typechecking
+ support for the changes above.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-default-resolver.cc
+ (DefaultResolver::visit_closure_params): New member function
+ definition.
+ (DefaultResolver::visit): New visiting function definition for
+ ClosureExpr called from visiting functions for ClosureExprInner
+ and ClosureExprInnerTyped.
+ * resolve/rust-default-resolver.h
+ (DefaultResolver::visit_closure_params): New member function
+ declaration.
+ (DefaultResolver::visit): New visiting function declaration for
+ ClosureExpr.
+ * resolve/rust-late-name-resolver-2.0.cc (add_captures): Remove
+ function.
+ (Late::visit): New visiting function definition for ClosureExpr,
+ remove visiting function definitions for ClosureExprInner and
+ ClosureExprInnerTyped.
+ (Late::visit_closure_params): New member function definition.
+ * resolve/rust-late-name-resolver-2.0.h (Late::visit): New
+ visiting function declaration for ClosureExpr, remove visiting
+ function declarations for ClosureExprInner and
+ ClosureExprInnerTyped.
+ (Late::visit_closure_params): New member function declaration.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-forever-stack.hxx (ForeverStack::resolve_path):
+ Handle single segment paths "crate", "self", and "super".
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Use
+ visit_identifier_as_pattern to handle IdentifierPattern and
+ StructPatternFieldIdent.
+ (visit_identifier_as_pattern): New function.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-expr.h (ClosureExpr::get_definition_expr): New
+ virtual member function.
+ (ClosureExprInner::get_definition_expr): Add override specifier.
+ (ClosureExprInnerTyped::get_definition_block): Rename to...
+ (ClosureExprInnerTyped::get_definition_expr): ...here and add
+ override specifier.
+ * ast/rust-ast-collector.cc (TokenCollector::visit): Handle
+ rename of ClosureExprInnerTyped::get_definition_block to
+ ClosureExprInnerTyped::get_definition_expr.
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise.
+ * expand/rust-cfg-strip.cc (CfgStrip::visit): Likewise.
+ * expand/rust-expand-visitor.cc (ExpandVisitor::visit):
+ Likewise.
+ * hir/rust-ast-lower-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.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * backend/rust-compile-base.cc
+ (HIRCompileBase::compile_function): Since canonical paths
+ returned from nr2.0 now include the crate name, avoid prepending
+ the crate name again.
+ * backend/rust-compile-implitem.cc (CompileTraitItem::visit):
+ Use NameResolutionContext::to_canonical_path instead of
+ ForeverStack::to_canonical_path.
+ * backend/rust-compile-item.cc (CompileItem::visit): Likewise.
+ * typecheck/rust-hir-type-check-enumitem.cc
+ (TypeCheckEnumItem::visit): Likewise.
+ * typecheck/rust-hir-type-check-implitem.cc
+ (TypeCheckImplItem::visit): Likewise.
+ * typecheck/rust-hir-type-check-item.cc (TypeCheckItem::visit):
+ Likewise.
+ * typecheck/rust-hir-type-check.cc
+ (TraitItemReference::get_type_from_fn): Likewise.
+ * resolve/rust-default-resolver.cc (DefaultResolver::visit): Add
+ Crate and EnumItem instance visitors, handle canonical path
+ context scoping.
+ * resolve/rust-default-resolver.h (DefaultResolver::visit): Add
+ Crate and EnumItem instance visitors.
+ * resolve/rust-early-name-resolver-2.0.cc (Early::go): Visit
+ instances of Crate using the virtual member function visit.
+ * resolve/rust-forever-stack.h
+ (ForeverStack::to_canonical_path): Remove function declaration.
+ * resolve/rust-forever-stack.hxx
+ (ForeverStack::to_canonical_path): Remove function definition.
+ * resolve/rust-late-name-resolver-2.0.cc (Late::go): Visit
+ instances of Crate using the virtual member function visit.
+ * resolve/rust-name-resolution-context.cc
+ (CanonicalPathRecordCrateRoot::as_path): New function definition.
+ (CanonicalPathRecordNormal::as_path): Likewise.
+ (CanonicalPathRecordLookup::as_path): Likewise.
+ (CanonicalPathRecordImpl::as_path): Likewise.
+ (CanonicalPathRecordTraitImpl::as_path): Likewise.
+ (NameResolutionContext::NameResolutionContext): Initialize
+ member variable canonical_ctx.
+ * resolve/rust-name-resolution-context.h: Include "rust-item.h".
+ (class NameResolutionContext): Forward declare class.
+ (class CanonicalPathRecord): New class.
+ (class CanonicalPathRecordWithParent): Likewise.
+ (class CanonicalPathRecordCrateRoot): Likewise.
+ (class CanonicalPathRecordNormal): Likewise.
+ (class CanonicalPathRecordLookup): Likewise.
+ (class CanonicalPathRecordImpl): Likewise.
+ (class CanonicalPathRecordTraitImpl): Likewise.
+ (class CanonicalPathCtx): Likewise.
+ (NameResolutionContext::canonical_ctx): New member variable.
+ (NameResolutionContext::to_canonical_path): New member function.
+ * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::go):
+ Visit instances of Crate with the virtual member function visit.
+ (TopLevel::visit): Handle canonical path context scoping for
+ external crates, use DefaultResolver::visit when visiting
+ instances of StructStruct.
+ * util/rust-canonical-path.h (CanonicalPath::new_seg): Take path
+ parameter by-value, as a duplicate instance will be constructed
+ regardless.
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * hir/rust-ast-lower-pattern.cc: Lower of IdentifierPattern's to_bind to HIR.
+ * hir/rust-hir-dump.cc: Update IdentifierPattern's dump to properly show to_bind's full
+ full properties.
+
+2025-08-05 Vishruth-Thimmaiah <vishruththimmaiah@gmail.com>
+
+ * lex/rust-lex.cc (Lexer::parse_raw_byte_string):
+ Fix infinite looping when a raw byte string is not terminated.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-default-resolver.cc (DefaultResolver::visit): Use
+ visit_impl_type to visit the self types of impl blocks.
+ * resolve/rust-default-resolver.h
+ (DefaultResolver::visit_impl_type): New member function
+ declaration.
+ * resolve/rust-late-name-resolver-2.0.cc (Late::Late):
+ Initialize member variable block_big_self.
+ (Late::visit_impl_type): New member function definition.
+ (Late::visit): Check for Self while inside impl block self
+ types.
+ * resolve/rust-late-name-resolver-2.0.h (Late::visit_impl_type):
+ New member function.
+ (Late::block_big_self): New member variable.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-forever-stack.h
+ (enum ResolutionMode): New.
+ (ForeverStack::get): Add a private overload that takes a
+ starting node as a parameter.
+ (ForeverStack::resolve_path): Replace boolean parameter
+ has_opening_scope_resolution with ResolutionMode parameter mode.
+ * resolve/rust-forever-stack.hxx
+ (ForeverStack::resolve_path): Likewise.
+ (ForeverStack::get): Add a private overload that takes a
+ starting node as a parameter.
+ * resolve/rust-late-name-resolver-2.0.cc
+ (Late::visit): Add Visibility visitor.
+ * resolve/rust-late-name-resolver-2.0.h
+ (Late::visit): Likewise.
+ * resolve/rust-name-resolution-context.h
+ (NameResolutionContext::resolve_path): Rework overloading a bit
+ and accept ResolutionMode parameter.
+
+2025-08-05 Vishruth-Thimmaiah <vishruththimmaiah@gmail.com>
+
+ * parse/rust-parse.cc (Rust::extract_module_path):
+ Handle empty or whitespace-only path attributes.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-ast-collector.cc (TokenCollector::visit): Handle
+ changed type of ConstantItem::identifier.
+ * ast/rust-ast.cc (ConstantItem::as_string): Likewise.
+ * ast/rust-ast.h (operator const std::string &): New member
+ function.
+ * ast/rust-item.h (ConstantItem::identifier): Change type from
+ std::string to Identifier.
+ (ConstantItem::ConstantItem): Handle changed type of identifier
+ field.
+ (ConstantItem::is_unnamed): Likewise.
+ (ConstantItem::get_identifier): Likewise.
+ * hir/rust-ast-lower-extern.h (ASTLoweringExternItem::visit):
+ Avoid discarding location of wildcard patterns.
+ * lex/rust-token.cc: Include "rust-ast.h".
+ (Token::make_identifier): Add overload accepting an Identifier
+ instance.
+ * lex/rust-token.h (class Identifier): Add forward declaration
+ in order to...
+ (Token::make_identifier): ...declare an overload for this static
+ member function.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * hir/tree/rust-hir-expr.h: New classes.
+ * hir/tree/rust-hir-full-decls.h: Likewise.
+ * hir/tree/rust-hir.cc: Handle AnonConst and ConstBlock.
+ * backend/rust-compile-block.cc: Likewise.
+ * backend/rust-compile-block.h: Likewise.
+ * backend/rust-compile-expr.cc (CompileExpr::visit): Likewise.
+ * backend/rust-compile-expr.h: Likewise.
+ * checks/errors/borrowck/rust-bir-builder-expr-stmt.cc (ExprStmtBuilder::visit): Likewise.
+ * checks/errors/borrowck/rust-bir-builder-expr-stmt.h: Likewise.
+ * checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h: Likewise.
+ * 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: Likewise.
+ * checks/errors/rust-const-checker.cc (ConstChecker::visit): Likewise.
+ * checks/errors/rust-const-checker.h: Likewise.
+ * checks/errors/rust-hir-pattern-analysis.cc (PatternChecker::visit): Likewise.
+ * checks/errors/rust-hir-pattern-analysis.h: Likewise.
+ * checks/errors/rust-unsafe-checker.cc (UnsafeChecker::visit): Likewise.
+ * checks/errors/rust-unsafe-checker.h: Likewise.
+ * hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Likewise.
+ (translate_operand_out): Likewise.
+ (translate_operand_inout): Likewise.
+ (translate_operand_const): Likewise.
+ * hir/rust-ast-lower-expr.h: Likewise.
+ * hir/rust-hir-dump.cc (Dump::visit): Likewise.
+ * hir/rust-hir-dump.h: Likewise.
+ * hir/tree/rust-hir-expr-abstract.h: Likewise.
+ * hir/tree/rust-hir-expr.cc (AnonConst::AnonConst): Likewise.
+ (AnonConst::operator=): Likewise.
+ (ConstBlock::ConstBlock): Likewise.
+ (ConstBlock::operator=): Likewise.
+ * hir/tree/rust-hir-visitor.h:
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Likewise.
+ (typecheck_inline_asm_operand): Likewise.
+ * typecheck/rust-hir-type-check-expr.h: Likewise.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * parse/rust-parse-impl.h (Parser::parse_const_block_expr): New function.
+ * parse/rust-parse.h: Declare it.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-expr.h: Declare AnonConst and ConstBlock and use them.
+ * ast/rust-ast-full-decls.h: Likewise.
+ * ast/rust-ast.cc: Add implementation for AnonConst and ConstBlock.
+ * ast/rust-ast.h: Likewise.
+ * ast/rust-ast-collector.cc (TokenCollector::visit): Likewise.
+ * ast/rust-ast-collector.h: Likewise.
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise.
+ * ast/rust-ast-visitor.h: Likewise.
+ * expand/rust-derive.h: Likewise.
+ * hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Likewise.
+ * hir/rust-ast-lower-base.h: Likewise.
+ * hir/rust-ast-lower-expr.cc (translate_operand_const): Likewise.
+ * resolve/rust-ast-resolve-base.cc (ResolverBase::visit): Likewise.
+ * resolve/rust-ast-resolve-base.h: Likewise.
+ * resolve/rust-ast-resolve-expr.h: Likewise.
+ * resolve/rust-ast-resolve-expr.cc: Likewise.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-coercion.cc (TypeCoercionRules::coerce_unsized): dont emit error here
+ * typecheck/rust-unify.cc (UnifyRules::resolve_subtype): new helper to handle emit error
+ (UnifyRules::expect_adt): call resolve_subtype
+ (UnifyRules::expect_reference): likewise
+ (UnifyRules::expect_pointer): likewise
+ (UnifyRules::expect_array): likewise
+ (UnifyRules::expect_slice): likewise
+ (UnifyRules::expect_fndef): likewise
+ (UnifyRules::expect_fnptr): likewise
+ (UnifyRules::expect_tuple): likewise
+ (UnifyRules::expect_closure): likewise
+ (UnifyRules::expect_opaque): likeiwse
+ * typecheck/rust-unify.h: add new helper to header
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-default-resolver.cc
+ (DefaultResolver::visit_if_let_patterns): New function
+ definition.
+ (DefaultResolver::visit): New IfLetExpr visitor definition.
+ * resolve/rust-default-resolver.h
+ (DefaultResolver::visit_if_let_patterns): New function
+ declaration.
+ (DefaultResolver::visit): New IfLetExpr visitor declaration.
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Remove
+ IfLetExpr visitor definition.
+ (Late::visit_if_let_patterns): New function definition.
+ * resolve/rust-late-name-resolver-2.0.h (Late::visit): Remove
+ IfLetExpr visitor declaration.
+ (Late::visit_if_let_patterns): New function declaration.
+ * resolve/rust-name-resolution-context.h (BindingSource::IfLet):
+ New enumerator.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-type.cc (TyTyResolveCompile::visit): we need to resolve the
+ underlying type
+ * typecheck/rust-substitution-mapper.cc (SubstMapperInternal::visit): just clone
+ * typecheck/rust-tyty-call.cc (TypeCheckCallExpr::visit):
+ ensure we monomphize to get the underlying
+ * typecheck/rust-tyty.cc (BaseType::destructure): handle opaque types
+ (OpaqueType::resolve): this is much simpler now
+ (OpaqueType::handle_substitions): no longer needed
+ * typecheck/rust-tyty.h: update header
+ * typecheck/rust-unify.cc (UnifyRules::expect_opaque): unify rules for opaque
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * backend/rust-compile-type.cc (TyTyResolveCompile::visit): use get_name
+ * typecheck/rust-tyty.cc (TupleType::get_name): likewise
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * checks/errors/privacy/rust-privacy-reporter.cc (PrivacyReporter::check_base_type_privacy):
+ no need for unreachable here
+ * typecheck/rust-unify.cc (UnifyRules::commit): dont clone infer vars
+ (UnifyRules::expect_inference_variable): likewise
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * typecheck/rust-hir-type-check.h: new function
+ * typecheck/rust-typecheck-context.cc (TypeCheckContext::compute_inference_variables):
+ call the new helper
+ (TypeCheckContext::compute_infer_var): refactored code
+
+2025-08-05 Tom Schollenberger <tss2344@g.rit.edu>
+
+ * resolve/rust-early-name-resolver-2.0.cc (Early::visit_attributes): rust_assert to if
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * parse/rust-parse-impl.h (Parser::parse_expr_stmt): Avoid
+ reference binding and remove std::move in return statements.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-ast-visitor.cc
+ (DefaultASTVisitor::visit): Only visit the path of an instance
+ of Visibility if the instance has a path.
+ * ast/rust-ast.h
+ (SimplePath::SimplePath): Make sure constructors are explicit.
+ * resolve/rust-early-name-resolver-2.0.cc
+ (Early::visit_attributes): Pass entire paths to
+ NameResolutionContext::resolve_path.
+ (Early::visit): Likewise and avoid copying a path.
+ * resolve/rust-forever-stack.hxx
+ (ForeverStack::resolve_path): Assert that at least one path
+ segment has been passed in.
+
+2025-08-05 Marc Poulhiès <dkm@kataplop.net>
+
+ * rust-attribs.cc (handle_hot_attribute): Remove clang-format comment.
+
+2025-08-05 Marc Poulhiès <dkm@kataplop.net>
+
+ * ast/rust-ast-builder-type.cc (ASTTypeBuilder::visit): Reindent.
+ * ast/rust-ast-builder.cc (Builder::new_generic_args): Likewise.
+ * ast/rust-ast-collector.cc (TokenCollector::visit): Likewise.
+ * ast/rust-ast-dump.h (debug): Likewise.
+ * ast/rust-ast-formatting.h (indent_spaces): Likewise.
+ (get_string_in_delims): Likewise.
+ (get_mode_dump_desc): Likewise.
+ (append_attributes): Likewise.
+ (unquote_string): Likewise.
+ * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise.
+ * ast/rust-ast.cc (Attribute::get_traits_to_derive): Likewise.
+ (UseTreeGlob::as_string): Likewise.
+ (UseTreeList::as_string): Likewise.
+ (AttributeParser::parse_path_meta_item): Likewise.
+ (FormatArgs::set_outer_attrs): Likewise.
+ * ast/rust-ast.h (operator<<): Likewise.
+ * ast/rust-cond-compilation.h: Likewise.
+ * ast/rust-desugar-apit.cc: Likewise.
+ * ast/rust-fmt.h (collect_pieces): Likewise.
+ (clone_pieces): Likewise.
+ * ast/rust-pattern.h (tokenid_to_rangekind): Likewise.
+ * backend/rust-compile-context.cc (Context::type_hasher): Likewise.
+ * backend/rust-compile-expr.cc (CompileExpr::visit): Likewise.
+ * backend/rust-compile-intrinsic.cc (get_identifier): Likewise.
+ (offset_handler): Likewise.
+ (sizeof_handler): Likewise.
+ (transmute_handler): Likewise.
+ (rotate_handler): Likewise.
+ (wrapping_op_handler_inner): Likewise.
+ (op_with_overflow_inner): Likewise.
+ (uninit_handler): Likewise.
+ (move_val_init_handler): Likewise.
+ (assume_handler): Likewise.
+ (discriminant_value_handler): Likewise.
+ (variant_count_handler): Likewise.
+ (prefetch_data_handler): Likewise.
+ (atomic_store_handler_inner): Likewise.
+ (atomic_load_handler_inner): Likewise.
+ (unchecked_op_inner): Likewise.
+ (copy_handler_inner): Likewise.
+ (expect_handler_inner): Likewise.
+ (try_handler_inner): Likewise.
+ * backend/rust-compile-pattern.cc (compile_range_pattern_bound): Likewise.
+ (CompilePatternCheckExpr::visit): Likewise.
+ (CompilePatternBindings::visit): Likewise.
+ (CompilePatternLet::visit): Likewise.
+ * backend/rust-compile-var-decl.h: Likewise.
+ * backend/rust-constexpr.cc (verify_constant): Likewise.
+ (find_array_ctor_elt): Likewise.
+ (array_index_cmp): Likewise.
+ (potential_constant_expression_1): Likewise.
+ (unshare_constructor): Likewise.
+ (maybe_save_constexpr_fundef): Likewise.
+ (returns): Likewise.
+ (breaks): Likewise.
+ (continues): Likewise.
+ (switches): Likewise.
+ (constant_value_1): Likewise.
+ (decl_constant_value): Likewise.
+ (non_const_var_error): Likewise.
+ (eval_constant_expression): Likewise.
+ (constexpr_fn_retval): Likewise.
+ (eval_store_expression): Likewise.
+ (eval_call_expression): Likewise.
+ (eval_binary_expression): Likewise.
+ (get_function_named_in_call): Likewise.
+ (eval_statement_list): Likewise.
+ (extract_string_elt): Likewise.
+ (eval_conditional_expression): Likewise.
+ (eval_bit_field_ref): Likewise.
+ (eval_loop_expr): Likewise.
+ (eval_switch_expr): Likewise.
+ (eval_unary_expression): Likewise.
+ (get_or_insert_ctor_field): Likewise.
+ (eval_and_check_array_index): Likewise.
+ * backend/rust-constexpr.h (maybe_save_constexpr_fundef): Likewise.
+ * backend/rust-mangle-v0.cc (v0_path): Likewise.
+ (v0_complex_type_prefix): Likewise.
+ * backend/rust-mangle.h (legacy_mangle_item): Likewise.
+ (v0_mangle_item): Likewise.
+ * backend/rust-tree.cc (convert_to_void): Likewise.
+ (find_parameter_packs_r): Likewise.
+ (rs_tree_equal): Likewise.
+ (publicly_uniquely_derived_p): Likewise.
+ (instantiation_dependent_expression_p): Likewise.
+ (type_has_nontrivial_copy_init): Likewise.
+ (is_normal_capture_proxy): Likewise.
+ (is_bitfield_expr_with_lowered_type): Likewise.
+ (undeduced_auto_decl): Likewise.
+ (require_deduced_type): Likewise.
+ (gt_pch_nx): Likewise.
+ (lvalue_kind): Likewise.
+ * backend/rust-tree.h (LANG_DECL_MIN_CHECK): Likewise.
+ (LANG_DECL_FN_CHECK): Likewise.
+ (LANG_DECL_NS_CHECK): Likewise.
+ (LANG_DECL_PARM_CHECK): Likewise.
+ (LANG_DECL_DECOMP_CHECK): Likewise.
+ (resort_type_member_vec): Likewise.
+ (convert_to_void): Likewise.
+ (mark_discarded_use): Likewise.
+ (mark_exp_read): Likewise.
+ (mark_use): Likewise.
+ (mark_rvalue_use): Likewise.
+ (mark_lvalue_use): Likewise.
+ (mark_lvalue_use_nonread): Likewise.
+ (convert_from_reference): Likewise.
+ (maybe_warn_nodiscard): Likewise.
+ (expr_loc_or_loc): Likewise.
+ (expr_loc_or_input_loc): Likewise.
+ (get_fndecl_from_callee): Likewise.
+ (pointer_offset_expression): Likewise.
+ (is_empty_class): Likewise.
+ (is_really_empty_class): Likewise.
+ (rs_type_quals): Likewise.
+ (init_modules): Likewise.
+ (lookup_add): Likewise.
+ (ovl_make): Likewise.
+ (struct c_fileinfo): Likewise.
+ (get_fileinfo): Likewise.
+ (cxx_make_type): Likewise.
+ (build_cplus_array_type): Likewise.
+ (comptypes): Likewise.
+ (rs_build_qualified_type_real): Likewise.
+ (vector_targets_convertible_p): Likewise.
+ (get_class_binding_direct): Likewise.
+ (lang_check_failed): Likewise.
+ (check_for_uninitialized_const_var): Likewise.
+ (cp_fold_maybe_rvalue): Likewise.
+ (fold_offsetof): Likewise.
+ (fold_non_dependent_expr): Likewise.
+ (in_immediate_context): Likewise.
+ (cxx_mark_addressable): Likewise.
+ (decl_constant_value): Likewise.
+ (is_class_type): Likewise.
+ (fold_builtin_is_pointer_inverconvertible_with_class): Likewise.
+ (c_common_type_for_mode): Likewise.
+ (next_common_initial_seqence): Likewise.
+ (fold_builtin_is_corresponding_member): Likewise.
+ (maybe_constant_value): Likewise.
+ (rs_walk_subtrees): Likewise.
+ (make_tree_vector): Likewise.
+ (release_tree_vector): Likewise.
+ (location_of): Likewise.
+ (maybe_constant_init): Likewise.
+ (explain_invalid_constexpr_fn): Likewise.
+ (literal_type_p): Likewise.
+ (maybe_constexpr_fn): Likewise.
+ (fold_non_dependent_init): Likewise.
+ * checks/errors/borrowck/polonius/rust-polonius.h (polonius_run): Likewise.
+ (FFIVector__new): Likewise.
+ (FFIVector__new_vec_pair): Likewise.
+ (FFIVector__new_vec_triple): Likewise.
+ (FFIVector__push): Likewise.
+ (FFIVector__push_vec_triple): Likewise.
+ * checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
+ (ExprStmtBuilder::visit): Likewise.
+ * checks/errors/borrowck/rust-bir-builder-pattern.cc
+ (PatternBindingBuilder::visit): Likewise.
+ * checks/errors/borrowck/rust-bir-dump.cc (Dump::visit): Likewise.
+ * checks/errors/borrowck/rust-bir-fact-collector.h (points): Likewise.
+ * checks/errors/borrowck/rust-bir-place.h: Likewise.
+ * checks/errors/borrowck/rust-bir-visitor.h: Likewise.
+ * checks/errors/privacy/rust-privacy-check.cc (saw_errors): Likewise.
+ * checks/errors/privacy/rust-privacy-ctx.h (rust_privacy_ctx_test): Likewise.
+ * checks/errors/privacy/rust-privacy-reporter.cc
+ (PrivacyReporter::check_for_privacy_violation): Likewise.
+ (PrivacyReporter::check_base_type_privacy): Likewise.
+ (PrivacyReporter::visit): Likewise.
+ * checks/errors/privacy/rust-reachability.cc (ReachabilityVisitor::visit): Likewise.
+ * checks/errors/privacy/rust-visibility-resolver.cc
+ (VisibilityResolver::resolve_visibility): Likewise.
+ * checks/errors/rust-hir-pattern-analysis.cc (Constructor::is_covered_by): Likewise.
+ (PlaceInfo::specialize): Likewise.
+ (WitnessPat::to_string): Likewise.
+ (WitnessMatrix::apply_constructor): Likewise.
+ (lower_pattern): Likewise.
+ (lower_tuple_pattern): Likewise.
+ (lower_struct_pattern): Likewise.
+ * checks/errors/rust-hir-pattern-analysis.h (check_match_usefulness): Likewise.
+ * expand/rust-cfg-strip.cc (CfgStrip::maybe_strip_generic_args): Likewise.
+ * expand/rust-derive-eq.cc (DeriveEq::visit_enum): Likewise.
+ * expand/rust-derive.cc: Likewise.
+ * expand/rust-expand-format-args.cc (expand_format_args): Likewise.
+ * expand/rust-expand-visitor.h (is_derive): Likewise.
+ (is_builtin): Likewise.
+ * expand/rust-macro-builtins-asm.cc (expand_inline_asm_strings): Likewise.
+ * expand/rust-macro-builtins-asm.h (parse_asm): Likewise.
+ (check_identifier): Likewise.
+ (check_and_set): Likewise.
+ (parse_label): Likewise.
+ (parse_llvm_outputs): Likewise.
+ (parse_llvm_inputs): Likewise.
+ (parse_llvm_clobbers): Likewise.
+ (parse_llvm_options): Likewise.
+ * expand/rust-macro-builtins-helpers.h (make_macro_path_str): Likewise.
+ (make_token): Likewise.
+ (make_string): Likewise.
+ (macro_end_token): Likewise.
+ (parse_single_string_literal): Likewise.
+ (source_relative_path): Likewise.
+ (load_file_bytes): Likewise.
+ * expand/rust-macro-expand.cc (MacroExpander::match_fragment): Likewise.
+ (MacroExpander::match_matcher): Likewise.
+ (MacroExpander::match_n_matches): Likewise.
+ * expand/rust-macro-substitute-ctx.cc (SubstituteCtx::substitute_token): Likewise.
+ * expand/rust-proc-macro.h (load_macros): Likewise.
+ (generate_proc_macro_decls_symbol): Likewise.
+ * hir/rust-ast-lower-base.cc (ASTLoweringBase::lower_generic_args): Likewise.
+ (ASTLoweringBase::lower_range_pattern_bound): Likewise.
+ * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): Likewise.
+ * hir/rust-ast-lower-pattern.cc (ASTLoweringPattern::visit): Likewise.
+ * hir/rust-ast-lower.h (struct_field_name_exists): Likewise.
+ (translate_visibility): Likewise.
+ * hir/rust-hir-dump.cc (Dump::visit): Likewise.
+ * hir/rust-hir-dump.h (debug): Likewise.
+ * hir/tree/rust-hir.cc (UseTreeGlob::as_string): Likewise.
+ (UseTreeList::as_string): Likewise.
+ * lex/rust-lex.cc (Lexer::parse_escape): Likewise.
+ (Lexer::parse_utf8_escape): Likewise.
+ * lex/rust-lex.h (rust_input_source_test): Likewise.
+ * lex/rust-token.cc (RS_TOKEN_KEYWORD_2015): Likewise.
+ * lex/rust-token.h (get_token_description): Likewise.
+ (token_id_to_str): Likewise.
+ (token_id_is_keyword): Likewise.
+ (token_id_keyword_string): Likewise.
+ (get_type_hint_string): Likewise.
+ (nfc_normalize_token_string): Likewise.
+ * metadata/rust-export-metadata.cc (PublicInterface::write_to_path): Likewise.
+ * metadata/rust-import-archive.cc: Likewise.
+ * metadata/rust-imports.h (add_search_path): Likewise.
+ * parse/rust-cfg-parser.h (parse_cfg_option): Likewise.
+ (rust_cfg_parser_test): Likewise.
+ * parse/rust-parse-impl.h (Parser::skip_generics_right_angle): Likewise.
+ (Parser::parse_attr_input): Likewise.
+ (Parser::parse_macro_match): Likewise.
+ (Parser::parse_visibility): Likewise.
+ (Parser::parse_module): Likewise.
+ (Parser::parse_use_tree): Likewise.
+ (Parser::parse_generic_param): Likewise.
+ (Parser::parse_struct): Likewise.
+ (Parser::parse_enum_item): Likewise.
+ (Parser::parse_inherent_impl_item): Likewise.
+ (Parser::parse_external_item): Likewise.
+ (Parser::parse_generic_arg): Likewise.
+ (Parser::parse_type_path_segment): Likewise.
+ (Parser::parse_expr_stmt): Likewise.
+ (Parser::parse_if_expr): Likewise.
+ (Parser::parse_if_let_expr): Likewise.
+ (Parser::parse_type): Likewise.
+ (Parser::parse_for_prefixed_type): Likewise.
+ (Parser::parse_slice_or_array_type): Likewise.
+ (Parser::parse_type_no_bounds): Likewise.
+ (Parser::parse_range_pattern_bound): Likewise.
+ (Parser::parse_pattern_no_alt): Likewise.
+ (Parser::parse_grouped_or_tuple_pattern): Likewise.
+ (Parser::parse_ident_leading_pattern): Likewise.
+ (Parser::parse_tuple_struct_items): Likewise.
+ (Parser::parse_stmt_or_expr): Likewise.
+ (Parser::parse_struct_expr_field): Likewise.
+ (Parser::null_denotation): Likewise.
+ (Parser::left_denotation): Likewise.
+ (Parser::parse_closure_expr_pratt): Likewise.
+ * parse/rust-parse.cc (peculiar_fragment_match_compatible): Likewise.
+ (is_match_compatible): Likewise.
+ * parse/rust-parse.h (extract_module_path): Likewise.
+ (is_match_compatible): Likewise.
+ * resolve/rust-ast-resolve-expr.cc (translate_operand): Likewise.
+ * resolve/rust-ast-resolve-item.cc (flatten_glob): Likewise.
+ (flatten_rebind): Likewise.
+ (flatten_list): Likewise.
+ (flatten): Likewise.
+ * resolve/rust-ast-resolve-item.h (rust_simple_path_resolve_test): Likewise.
+ * resolve/rust-ast-resolve-pattern.cc (PatternDeclaration::visit): Likewise.
+ (resolve_range_pattern_bound): Likewise.
+ * resolve/rust-ast-resolve-type.cc (ResolveRelativeTypePath::go): Likewise.
+ (ResolveTypeToCanonicalPath::visit): Likewise.
+ * resolve/rust-ast-resolve.cc (saw_errors): Likewise.
+ * resolve/rust-early-name-resolver-2.0.cc (Early::finalize_rebind_import): Likewise.
+ * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Likewise.
+ * resolve/rust-toplevel-name-resolver-2.0.cc (flatten_glob): Likewise.
+ * rust-backend.h (init): Likewise.
+ (debug): Likewise.
+ (get_identifier_node): Likewise.
+ (wchar_type): Likewise.
+ (get_pointer_size): Likewise.
+ (raw_str_type): Likewise.
+ (integer_type): Likewise.
+ (float_type): Likewise.
+ (pointer_type): Likewise.
+ (reference_type): Likewise.
+ (immutable_type): Likewise.
+ (function_type): Likewise.
+ (function_type_variadic): Likewise.
+ (function_ptr_type): Likewise.
+ (struct_type): Likewise.
+ (union_type): Likewise.
+ (array_type): Likewise.
+ (named_type): Likewise.
+ (type_field_offset): Likewise.
+ (var_expression): Likewise.
+ (float_constant_expression): Likewise.
+ (string_constant_expression): Likewise.
+ (char_constant_expression): Likewise.
+ (wchar_constant_expression): Likewise.
+ (boolean_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_initializer): Likewise.
+ (array_index_expression): Likewise.
+ (call_expression): Likewise.
+ (init_statement): Likewise.
+ (assignment_statement): Likewise.
+ (return_statement): Likewise.
+ (if_statement): Likewise.
+ (loop_expression): Likewise.
+ (exit_expression): Likewise.
+ (statement_list): Likewise.
+ (exception_handler_statement): Likewise.
+ (block): Likewise.
+ (block_add_statements): Likewise.
+ (global_variable): Likewise.
+ (global_variable_set_init): Likewise.
+ (local_variable): Likewise.
+ (parameter_variable): Likewise.
+ (static_chain_variable): Likewise.
+ (temporary_variable): Likewise.
+ (label): Likewise.
+ (function): Likewise.
+ (function_defer_statement): Likewise.
+ (function_set_parameters): Likewise.
+ (write_global_definitions): Likewise.
+ (fill_in_fields): Likewise.
+ * rust-diagnostics.cc (expand_format): Likewise.
+ (expand_message): Likewise.
+ (va_constructor): Likewise.
+ * rust-diagnostics.h (RUST_ATTRIBUTE_GCC_DIAG): Likewise.
+ (rust_open_quote): Likewise.
+ (rust_close_quote): Likewise.
+ (rust_debug_loc): Likewise.
+ * rust-gcc.cc (non_zero_size_type): Likewise.
+ * rust-object-export.h (rust_field_alignment): Likewise.
+ (rust_read_export_data): Likewise.
+ (rust_write_export_data): Likewise.
+ * rust-session-manager.cc (saw_errors): Likewise.
+ (rust_get_linemap): Likewise.
+ (validate_crate_name): Likewise.
+ (Session::load_extern_crate): Likewise.
+ * rust-session-manager.h (rust_crate_name_validation_test): Likewise.
+ * rust-system.h (rust_preserve_from_gc): Likewise.
+ (rust_localize_identifier): Likewise.
+ * rust-target.h (rust_add_target_info): Likewise.
+ * typecheck/rust-autoderef.cc:
+ * typecheck/rust-casts.cc (TypeCastRules::cast_rules): Likewise.
+ * typecheck/rust-coercion.cc (TypeCoercionRules::do_coercion): Likewise.
+ (TypeCoercionRules::coerce_unsafe_ptr): Likewise.
+ (TypeCoercionRules::coerce_borrowed_pointer): Likewise.
+ * typecheck/rust-hir-trait-resolve.cc (TraitResolver::resolve_trait): Likewise.
+ (TraitItemReference::is_object_safe): Likewise.
+ * typecheck/rust-hir-type-check-base.cc (TypeCheckBase::resolve_literal): Likewise.
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Likewise.
+ (typecheck_inline_asm_operand): Likewise.
+ * typecheck/rust-hir-type-check-implitem.cc (TypeCheckImplItem::visit): Likewise.
+ (TypeCheckImplItemWithTrait::visit): Likewise.
+ * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit): Likewise.
+ * typecheck/rust-hir-type-check-struct.cc (TypeCheckStructExpr::visit): Likewise.
+ * typecheck/rust-hir-type-check-type.cc
+ (TypeResolveGenericParam::apply_trait_bounds): Likewise.
+ (ResolveWhereClauseItem::visit): Likewise.
+ * typecheck/rust-hir-type-check.cc (saw_errors): Likewise.
+ (TraitItemReference::get_type_from_fn): Likewise.
+ * typecheck/rust-type-util.h (query_type): Likewise.
+ (types_compatable): Likewise.
+ (unify_site): Likewise.
+ (unify_site_and): Likewise.
+ (coercion_site): Likewise.
+ (try_coercion): Likewise.
+ (cast_site): Likewise.
+ * typecheck/rust-tyty-bounds.cc:
+ * typecheck/rust-tyty-call.cc (TypeCheckCallExpr::visit): Likewise.
+ * typecheck/rust-tyty-cmp.h:
+ * typecheck/rust-tyty-variance-analysis.h (query_field_regions): Likewise.
+ * typecheck/rust-tyty.cc (BaseType::is_unit): Likewise.
+ (BaseType::has_substitutions_defined): Likewise.
+ (BaseType::needs_generic_substitutions): Likewise.
+ (BaseType::get_subst_argument_mappings): Likewise.
+ (InferType::default_type): Likewise.
+ (InferType::apply_primitive_type_hint): Likewise.
+ * typecheck/rust-tyty.h (is_primitive_type_kind): Likewise.
+ * typecheck/rust-unify.cc (UnifyRules::expect_inference_variable): Likewise.
+ (UnifyRules::expect_adt): Likewise.
+ (UnifyRules::expect_str): Likewise.
+ (UnifyRules::expect_reference): Likewise.
+ (UnifyRules::expect_pointer): Likewise.
+ (UnifyRules::expect_param): Likewise.
+ (UnifyRules::expect_array): Likewise.
+ (UnifyRules::expect_slice): Likewise.
+ (UnifyRules::expect_fndef): Likewise.
+ (UnifyRules::expect_fnptr): Likewise.
+ (UnifyRules::expect_tuple): Likewise.
+ (UnifyRules::expect_bool): Likewise.
+ (UnifyRules::expect_char): Likewise.
+ (UnifyRules::expect_int): Likewise.
+ (UnifyRules::expect_uint): Likewise.
+ (UnifyRules::expect_float): Likewise.
+ (UnifyRules::expect_isize): Likewise.
+ (UnifyRules::expect_usize): Likewise.
+ (UnifyRules::expect_never): Likewise.
+ (UnifyRules::expect_placeholder): Likewise.
+ (UnifyRules::expect_projection): Likewise.
+ (UnifyRules::expect_dyn): Likewise.
+ (UnifyRules::expect_closure): Likewise.
+ (UnifyRules::expect_opaque): Likewise.
+ * util/rust-abi.h (get_abi_from_string): Likewise.
+ (get_string_from_abi): Likewise.
+ * util/rust-attributes.cc (check_doc_attribute): Likewise.
+ * util/rust-base62.h (base62_integer): Likewise.
+ * util/rust-dir-owner.h (get_file_subdir): Likewise.
+ * util/rust-edition.h (get_rust_edition): Likewise.
+ * util/rust-punycode.h (encode_punycode): Likewise.
+ (rust_punycode_encode_test): Likewise.
+ * util/rust-token-converter.cc (convert): Likewise.
+ (from_tokenstream): Likewise.
+ * util/rust-token-converter.h (convert): Likewise.
+ (convert_literal): Likewise.
+ * util/rust-unicode.h (is_alphabetic): Likewise.
+ (is_ascii_only): Likewise.
+ (is_numeric): Likewise.
+ (is_nfc_qc_no): Likewise.
+ (is_nfc_qc_maybe): Likewise.
+ (nfc_quick_check): Likewise.
+ (rust_nfc_qc_test): Likewise.
+ (rust_utf8_normalize_test): Likewise.
+ (rust_utf8_property_test): Likewise.
+ * util/rust-unwrap-segment.h (unwrap_segment_node_id): Likewise.
+
+2025-08-05 Marc Poulhiès <dkm@kataplop.net>
+
+ * Make-lang.in (GRS_OBJS): Remove rust-macro.o.
+ * ast/rust-macro.cc: Removed.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * parse/rust-parse-impl.h
+ (Parser::parse_attr_input): Handle more delimeter tokens and the
+ END_OF_FILE token.
+ (Parser::skip_after_end_attribute): Handle the END_OF_FILE
+ token.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * hir/rust-ast-lower-item.cc
+ (ASTLoweringItem::visit): Keep going after a duplicate field is
+ found.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * checks/errors/borrowck/rust-bir-builder-internal.h: Include
+ "rust-immutable-name-resolution-context.h" and "options.h".
+ (AbstractBuilder::resolve_label): Use the 2.0 name resolver when
+ it's enabled.
+ (AbstractBuilder::resolve_variable): Likewise.
+ (AbstractBuilder::resolve_variable_or_fn): Likewise.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * expand/rust-derive-default.cc (DeriveDefault::visit_struct): use builder
+ (DeriveDefault::visit_tuple): likewise
+ * expand/rust-derive-eq.cc (DeriveEq::visit_tuple): likewise
+ (DeriveEq::visit_struct): likewise
+ (DeriveEq::visit_enum): likewise
+ (DeriveEq::visit_union): likewise
+
+2025-08-05 Marc Poulhiès <dkm@kataplop.net>
+
+ PR rust/120018
+ * rust-attribs.cc (handle_noreturn_attribute): Reindent declaration.
+ (handle_leaf_attribute): Likewise.
+ (handle_const_attribute): Likewise.
+ (handle_malloc_attribute): Likewise.
+ (handle_pure_attribute): Likewise.
+ (handle_novops_attribute): Likewise.
+ (handle_nonnull_attribute): Likewise.
+ (handle_nothrow_attribute): Likewise.
+ (handle_type_generic_attribute): Likewise.
+ (handle_transaction_pure_attribute): Likewise.
+ (handle_returns_twice_attribute): Likewise.
+ (handle_fnspec_attribute): Likewise.
+ (handle_omp_declare_simd_attribute): Likewise.
+ (handle_cold_attribute): New.
+ (handle_hot_attribute): New.
+ (attribute_spec::exclusions attr_cold_hot_exclusions): New.
+ (grs_langhook_common_attributes): Make it static.
+ (grs_langhook_common_attribute_table): New.
+ (grs_langhook_gnu_attributes): New.
+ (grs_langhook_gnu_attribute_table): New.
+ (handle_malloc_attribute): Make it static.
+ (handle_fnspec_attribute): Likewise.
+ (handle_pure_attribute): Replace gcc_assert by explicit warning.
+ (handle_novops_attribute): Likewise.
+ (handle_nothrow_attribute): Likewise.
+ (handle_returns_twice_attribute): Likewise.
+ (handle_omp_declare_simd_attribute): Likewise and make it static.
+ * rust-lang.cc (grs_langhook_gnu_attribute_table): New.
+ (grs_langhook_common_attribute_table): Adjust type to new hook.
+ (LANG_HOOKS_COMMON_ATTRIBUTE_TABLE): Remove.
+ (LANG_HOOKS_ATTRIBUTE_TABLE): New.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-path.cc
+ (TypePath::make_debug_string): Add definition.
+ * ast/rust-path.h
+ (TypePath::make_debug_string): Add declaration.
+ * resolve/rust-default-resolver.cc
+ (DefaultResolver::visit): Adjust InherentImpl and TraitImpl
+ visitors to better handle associated item scope.
+ * resolve/rust-default-resolver.h
+ (DefaultResolver::maybe_insert_big_self): Add.
+ * resolve/rust-late-name-resolver-2.0.cc
+ (Late::visit): Adjust type path resolution errors.
+ * resolve/rust-rib.h
+ (Rib::Kind): Add Generics kind.
+ * resolve/rust-toplevel-name-resolver-2.0.cc
+ (TopLevel::visit): Remove InherentImpl and TraitImpl visitor
+ overrides.
+ (TopLevel::maybe_insert_big_self): Add override in order to add
+ a definition of 'Self'.
+ * resolve/rust-toplevel-name-resolver-2.0.h
+ (TopLevel::visit): Remove InherentImpl and TraitImpl visitor
+ overrides.
+ (TopLevel::maybe_insert_big_self): Add override.
+
+2025-08-05 0xn4utilus <gyanendrabanjare8@gmail.com>
+
+ * ast/rust-ast-collector.cc (TokenCollector::visit): Implement for InlineAsm.
+ * ast/rust-ast-full-decls.h (enum class): Move InlineAsmOption enum inside InlineAsm.
+ * ast/rust-expr.h (enum class): Likewise.
+ (class InlineAsm): Likewise.
+ * expand/rust-macro-builtins-asm.cc (check_and_set): Likewise.
+ (parse_options): Likewise.
+ * expand/rust-macro-builtins-asm.h (check_and_set): Likewise.
+ * hir/tree/rust-hir-expr.cc (InlineAsm::InlineAsm): Likewise.
+ * hir/tree/rust-hir-expr.h: Likewise.
+ * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Likewise.
+
+2025-08-05 Tom Schollenberger <tss2344@g.rit.edu>
+
+ * backend/rust-constexpr.cc (eval_constant_expression): Check if t is a NULL_TREE
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * ast/rust-desugar-apit.cc: track if this is a impl-trait generic
+ * ast/rust-item.h (class TypeParam): add field to track if from impl trait
+ * hir/rust-ast-lower-type.cc (ASTLowerGenericParam::visit): likewise
+ * hir/tree/rust-hir-item.cc (TypeParam::TypeParam): upate hir as well
+ (TypeParam::operator=): likewise
+ * hir/tree/rust-hir-item.h (class TypeParam): likewise
+ * typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::get_generic_param): add error
+ * typecheck/rust-tyty-subst.h: add const getter for the associated TypeParm
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * ast/rust-ast-visitor.cc
+ (DefaultASTVisitor::visit): Make call to EnumItem visitor from
+ EnumItem derived class visitors non-virtual.
+ * ast/rust-collect-lang-items.cc
+ (CollectLangItems::visit): Handle visitation of classes derived
+ from EnumItem.
+ * ast/rust-collect-lang-items.h
+ (CollectLangItems::visit): Likewise.
+ * resolve/rust-toplevel-name-resolver-2.0.cc
+ (TopLevel::visit): Call DefaultResolver::visit on EnumItem
+ instances.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * backend/rust-compile-pattern.cc
+ (CompilePatternCheckExpr::visit): Fix GENERIC generation in
+ light of enum layout changes since this code was written.
+ (CompilePatternBindings::handle_struct_pattern_ident_pat):
+ Delegate handling of child patterns to another
+ CompilePatternBindings::Compile call.
+ (CompilePatternBindings::make_struct_access): Make field name
+ parameter const qualified.
+ * backend/rust-compile-pattern.h
+ (CompilePatternBindings::make_struct_access): Likewise.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * resolve/rust-ast-resolve-item.cc
+ (ResolveItem::visit): Use the return values of
+ CanonicalPath::inherent_impl_seg and
+ CanonicalPath::trait_impl_projection_seg more directly.
+ * util/rust-canonical-path.h
+ (CanonicalPath::trait_impl_projection_seg): Append "<impl "
+ instead of "<" to the beginning of the returned path segment.
+ (CanonicalPath::inherent_impl_seg): Likewise.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * Make-lang.in: new desugar file
+ * ast/rust-ast.cc (ImplTraitTypeOneBound::as_string): its a unique_ptr now
+ (FormatArgs::set_outer_attrs): reformat
+ * ast/rust-path.h: remove has_generic_args assertion (can be empty because of desugar)
+ * ast/rust-type.h (class ImplTraitTypeOneBound): add copy ctor and use unique_ptr
+ * hir/rust-ast-lower-type.cc (ASTLoweringType::visit): update to use unique_ptr
+ * parse/rust-parse-impl.h (Parser::parse_type): reuse the existing unique_ptr instead
+ (Parser::parse_type_no_bounds): likewise
+ (Parser::parse_pattern): likewise
+ * resolve/rust-ast-resolve-type.cc (ResolveType::visit): its a unique_ptr now
+ * rust-session-manager.cc (Session::compile_crate): call desugar
+ * ast/rust-desugar-apit.cc: New file.
+ * ast/rust-desugar-apit.h: New file.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * hir/rust-ast-lower-implitem.cc (ASTLowerImplItem::visit): allow impl type
+ * hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): likewise
+ * hir/rust-ast-lower-type.cc (ASTLoweringType::ASTLoweringType): new flag for impl trait
+ (ASTLoweringType::translate): pass flag
+ (ASTLoweringType::visit): track impl trait tag
+ (ASTLoweringType::emit_impl_trait_error): new diagnostic
+ * hir/rust-ast-lower-type.h: add new field
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * expand/rust-derive-partial-eq.cc (DerivePartialEq::match_enum_tuple): Remove debug call.
+ (DerivePartialEq::match_enum_struct): Add proper implementation.
+ (DerivePartialEq::visit_enum): Call it.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * ast/rust-ast-builder.cc (Builder::struct_pattern_ident_pattern): New.
+ * ast/rust-ast-builder.h: New declaration.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * backend/rust-compile-pattern.cc (CompilePatternBindings::make_struct_access):
+ New function.
+ (CompilePatternBindings::visit): Properly implement patterns mentioned above
+ and call make_struct_accesss.
+ * backend/rust-compile-pattern.h: New declaration.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * backend/rust-compile-pattern.h: Split struct pattern compilation into three functions.
+ * backend/rust-compile-pattern.cc: Implement them.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * resolve/rust-late-name-resolver-2.0.cc (Late::Late): False initialize the
+ funny_error field.
+
2025-07-25 David Malcolm <dmalcolm@redhat.com>
* resolve/rust-ice-finalizer.cc: Update usage of "diagnostic_info"
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 835e113..8cdf6c9 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -73,6 +73,9 @@ GRS_OBJS = \
rust/rust-lex.o \
rust/rust-cfg-parser.o \
rust/rust-parse.o \
+ rust/rust-parse-impl-proc-macro.o \
+ rust/rust-parse-impl-macro.o \
+ rust/rust-parse-impl-lexer.o \
rust/rust-ast.o \
rust/rust-ast-formatting.o \
rust/rust-path.o \
@@ -81,6 +84,7 @@ GRS_OBJS = \
rust/rust-ast-dump.o \
rust/rust-ast-collector.o \
rust/rust-ast-visitor.o \
+ rust/rust-hir-visitor.o \
rust/rust-hir-dump.o \
rust/rust-session-manager.o \
rust/rust-compile.o \
@@ -92,14 +96,15 @@ GRS_OBJS = \
rust/rust-cfg-strip.o \
rust/rust-expand-visitor.o \
rust/rust-ast-builder.o \
- rust/rust-ast-builder-type.o \
rust/rust-derive.o \
+ rust/rust-derive-cmp-common.o \
rust/rust-derive-clone.o \
rust/rust-derive-copy.o \
rust/rust-derive-debug.o \
rust/rust-derive-default.o \
rust/rust-derive-partial-eq.o \
rust/rust-derive-eq.o \
+ rust/rust-derive-ord.o \
rust/rust-derive-hash.o \
rust/rust-proc-macro.o \
rust/rust-macro-invoc-lexer.o \
@@ -113,6 +118,7 @@ GRS_OBJS = \
rust/rust-macro-builtins-log-debug.o \
rust/rust-macro-builtins-test-bench.o \
rust/rust-macro-builtins-format-args.o \
+ rust/rust-macro-builtins-offset-of.o \
rust/rust-macro-builtins-location.o \
rust/rust-macro-builtins-include.o \
rust/rust-token-tree-desugar.o \
@@ -123,7 +129,6 @@ GRS_OBJS = \
rust/rust-keyword-values.o \
rust/rust-abi.o \
rust/rust-token-converter.o \
- rust/rust-macro.o \
rust/rust-ast-lower.o \
rust/rust-ast-lower-base.o \
rust/rust-ast-lower-pattern.o \
@@ -204,6 +209,7 @@ GRS_OBJS = \
rust/rust-lint-marklive.o \
rust/rust-lint-unused-var.o \
rust/rust-readonly-check.o \
+ rust/rust-readonly-check2.o \
rust/rust-hir-type-check-path.o \
rust/rust-unsafe-checker.o \
rust/rust-hir-pattern-analysis.o \
@@ -237,11 +243,16 @@ GRS_OBJS = \
rust/rust-punycode.o \
rust/rust-unwrap-segment.o \
rust/rust-edition.o \
+ rust/rust-ggc.o \
rust/rust-expand-format-args.o \
rust/rust-lang-item.o \
rust/rust-collect-lang-items.o \
+ rust/rust-expression-yeast.o \
rust/rust-desugar-for-loops.o \
+ rust/rust-desugar-while-let.o \
rust/rust-desugar-question-mark.o \
+ rust/rust-desugar-apit.o \
+ rust/rust-desugar-try-block.o \
$(END)
# removed object files from here
diff --git a/gcc/rust/ast/rust-ast-builder-type.cc b/gcc/rust/ast/rust-ast-builder-type.cc
deleted file mode 100644
index 13126b4..0000000
--- a/gcc/rust/ast/rust-ast-builder-type.cc
+++ /dev/null
@@ -1,163 +0,0 @@
-// Copyright (C) 2020-2024 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#include "rust-ast-builder-type.h"
-#include "rust-ast-builder.h"
-#include "rust-ast-full.h"
-#include "rust-common.h"
-
-namespace Rust {
-namespace AST {
-
-ASTTypeBuilder::ASTTypeBuilder () : translated (nullptr) {}
-
-Type *
-ASTTypeBuilder::build (Type &type)
-{
- ASTTypeBuilder builder;
- type.accept_vis (builder);
- rust_assert (builder.translated != nullptr);
- return builder.translated;
-}
-
-void
-ASTTypeBuilder::visit (BareFunctionType &fntype)
-{
- /* TODO */
-}
-
-void
-ASTTypeBuilder::visit (TupleType &tuple)
-{
- std::vector<std::unique_ptr<Type> > elems;
- for (auto &elem : tuple.get_elems ())
- {
- Type *t = ASTTypeBuilder::build (*elem.get ());
- std::unique_ptr<Type> ty (t);
- elems.push_back (std::move (ty));
- }
- translated = new TupleType (std::move (elems), tuple.get_locus ());
-}
-
-void
-ASTTypeBuilder::visit (TypePath &path)
-{
- std::vector<std::unique_ptr<TypePathSegment> > segments;
- for (auto &seg : path.get_segments ())
- {
- switch (seg->get_type ())
- {
- case TypePathSegment::REG: {
- const TypePathSegment &segment
- = (const TypePathSegment &) (*seg.get ());
- TypePathSegment *s
- = new TypePathSegment (segment.get_ident_segment (),
- segment.get_separating_scope_resolution (),
- segment.get_locus ());
- std::unique_ptr<TypePathSegment> sg (s);
- segments.push_back (std::move (sg));
- }
- break;
-
- case TypePathSegment::GENERIC: {
- TypePathSegmentGeneric &generic
- = (TypePathSegmentGeneric &) (*seg.get ());
-
- GenericArgs args
- = Builder::new_generic_args (generic.get_generic_args ());
- TypePathSegmentGeneric *s
- = new TypePathSegmentGeneric (generic.get_ident_segment (), false,
- std::move (args),
- generic.get_locus ());
- std::unique_ptr<TypePathSegment> sg (s);
- segments.push_back (std::move (sg));
- }
- break;
-
- case TypePathSegment::FUNCTION: {
- rust_unreachable ();
- // TODO
- // const TypePathSegmentFunction &fn
- // = (const TypePathSegmentFunction &) (*seg.get ());
- }
- break;
- }
- }
-
- translated = new TypePath (std::move (segments), path.get_locus (),
- path.has_opening_scope_resolution_op ());
-}
-
-void
-ASTTypeBuilder::visit (QualifiedPathInType &path)
-{
- /* TODO */
-}
-
-void
-ASTTypeBuilder::visit (ArrayType &type)
-{
- /* TODO */
-}
-
-void
-ASTTypeBuilder::visit (ReferenceType &type)
-{
- /* TODO */
-}
-
-void
-ASTTypeBuilder::visit (RawPointerType &type)
-{
- /* TODO */
-}
-
-void
-ASTTypeBuilder::visit (SliceType &type)
-{
- Type *t = ASTTypeBuilder::build (type.get_elem_type ());
- std::unique_ptr<Type> ty (t);
- translated = new SliceType (std::move (ty), type.get_locus ());
-}
-
-void
-ASTTypeBuilder::visit (InferredType &type)
-{
- translated = new InferredType (type.get_locus ());
-}
-
-void
-ASTTypeBuilder::visit (NeverType &type)
-{
- translated = new NeverType (type.get_locus ());
-}
-
-void
-ASTTypeBuilder::visit (TraitObjectTypeOneBound &type)
-{
- /* TODO */
-}
-
-void
-ASTTypeBuilder::visit (TraitObjectType &type)
-{
- /* TODO */
-}
-
-} // namespace AST
-} // namespace Rust
diff --git a/gcc/rust/ast/rust-ast-builder-type.h b/gcc/rust/ast/rust-ast-builder-type.h
deleted file mode 100644
index b67ae3b..0000000
--- a/gcc/rust/ast/rust-ast-builder-type.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (C) 2020-2024 Free Software Foundation, Inc.
-
-// This file is part of GCC.
-
-// GCC is free software; you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3, or (at your option) any later
-// version.
-
-// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-// WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with GCC; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#ifndef RUST_AST_BUILDER_TYPE
-#define RUST_AST_BUILDER_TYPE
-
-#include "rust-ast-visitor.h"
-
-namespace Rust {
-namespace AST {
-
-class ASTTypeBuilder : public DefaultASTVisitor
-{
-protected:
- using DefaultASTVisitor::visit;
-
-public:
- static Type *build (Type &type);
-
- void visit (BareFunctionType &fntype) override;
- void visit (TupleType &tuple) override;
- void visit (TypePath &path) override;
- void visit (QualifiedPathInType &path) override;
- void visit (ArrayType &type) override;
- void visit (ReferenceType &type) override;
- void visit (RawPointerType &type) override;
- void visit (SliceType &type) override;
- void visit (InferredType &type) override;
- void visit (NeverType &type) override;
- void visit (TraitObjectTypeOneBound &type) override;
- void visit (TraitObjectType &type) override;
-
-private:
- ASTTypeBuilder ();
-
- Type *translated;
-};
-
-} // namespace AST
-} // namespace Rust
-
-#endif // RUST_AST_BUILDER_TYPE
diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc
index 08c52b1..ed10ce7 100644
--- a/gcc/rust/ast/rust-ast-builder.cc
+++ b/gcc/rust/ast/rust-ast-builder.cc
@@ -18,7 +18,6 @@
#include "rust-ast-builder.h"
#include "optional.h"
-#include "rust-ast-builder-type.h"
#include "rust-ast.h"
#include "rust-common.h"
#include "rust-expr.h"
@@ -29,7 +28,6 @@
#include "rust-pattern.h"
#include "rust-system.h"
#include "rust-token.h"
-#include <memory>
namespace Rust {
namespace AST {
@@ -332,6 +330,12 @@ Builder::block () const
}
std::unique_ptr<BlockExpr>
+Builder::block (std::unique_ptr<Expr> &&tail_expr) const
+{
+ return block (tl::nullopt, std::move (tail_expr));
+}
+
+std::unique_ptr<BlockExpr>
Builder::block (std::vector<std::unique_ptr<Stmt>> &&stmts,
std::unique_ptr<Expr> &&tail_expr) const
{
@@ -442,6 +446,14 @@ Builder::field_access (std::unique_ptr<Expr> &&instance,
new FieldAccessExpr (std::move (instance), field, {}, loc));
}
+std::unique_ptr<StructPatternField>
+Builder::struct_pattern_ident_pattern (std::string field_name,
+ std::unique_ptr<Pattern> &&pattern)
+{
+ return std::make_unique<StructPatternFieldIdentPat> (
+ field_name, std::move (pattern), std::vector<Attribute> (), loc);
+}
+
std::unique_ptr<Pattern>
Builder::wildcard () const
{
@@ -482,9 +494,14 @@ MatchCase
Builder::match_case (std::unique_ptr<Pattern> &&pattern,
std::unique_ptr<Expr> &&expr)
{
- return MatchCase (match_arm (std::move (pattern)), std::move (expr));
+ return match_case (match_arm (std::move (pattern)), std::move (expr));
}
+MatchCase
+Builder::match_case (MatchArm &&arm, std::unique_ptr<Expr> &&expr)
+{
+ return MatchCase (std::move (arm), std::move (expr));
+}
std::unique_ptr<Expr>
Builder::loop (std::vector<std::unique_ptr<Stmt>> &&stmts)
{
@@ -523,11 +540,14 @@ Builder::generic_type_param (
std::vector<Attribute> ());
}
-std::unique_ptr<Type>
-Builder::new_type (Type &type)
+std::unique_ptr<Stmt>
+Builder::discriminant_value (std::string binding_name, std::string instance)
{
- Type *t = ASTTypeBuilder::build (type);
- return std::unique_ptr<Type> (t);
+ auto intrinsic = ptrify (
+ path_in_expression ({"core", "intrinsics", "discriminant_value"}, true));
+
+ return let (identifier_pattern (binding_name), nullptr,
+ call (std::move (intrinsic), identifier (instance)));
}
std::unique_ptr<GenericParam>
@@ -547,6 +567,16 @@ Builder::new_lifetime_param (LifetimeParam &param)
}
std::unique_ptr<GenericParam>
+Builder::new_const_param (ConstGenericParam &param) const
+{
+ return std::make_unique<ConstGenericParam> (param.get_name (),
+ param.get_type ().clone_type (),
+ param.get_default_value (),
+ param.get_outer_attrs (),
+ param.get_locus ());
+}
+
+std::unique_ptr<GenericParam>
Builder::new_type_param (
TypeParam &param, std::vector<std::unique_ptr<TypeParamBound>> extra_bounds)
{
@@ -557,7 +587,7 @@ Builder::new_type_param (
std::unique_ptr<Type> type = nullptr;
if (param.has_type ())
- type = new_type (param.get_type ());
+ type = param.get_type ().reconstruct ();
for (auto &&extra_bound : extra_bounds)
type_param_bounds.emplace_back (std::move (extra_bound));
@@ -566,7 +596,8 @@ Builder::new_type_param (
{
switch (b->get_bound_type ())
{
- case TypeParamBound::TypeParamBoundType::TRAIT: {
+ case TypeParamBound::TypeParamBoundType::TRAIT:
+ {
const TraitBound &tb = (const TraitBound &) *b.get ();
const TypePath &path = tb.get_type_path ();
@@ -591,7 +622,8 @@ Builder::new_type_param (
{
switch (seg->get_type ())
{
- case TypePathSegment::REG: {
+ case TypePathSegment::REG:
+ {
const TypePathSegment &segment
= (const TypePathSegment &) (*seg.get ());
TypePathSegment *s = new TypePathSegment (
@@ -603,7 +635,8 @@ Builder::new_type_param (
}
break;
- case TypePathSegment::GENERIC: {
+ case TypePathSegment::GENERIC:
+ {
TypePathSegmentGeneric &generic
= (TypePathSegmentGeneric &) (*seg.get ());
@@ -617,7 +650,8 @@ Builder::new_type_param (
}
break;
- case TypePathSegment::FUNCTION: {
+ case TypePathSegment::FUNCTION:
+ {
rust_unreachable ();
// TODO
// const TypePathSegmentFunction &fn
@@ -639,7 +673,8 @@ Builder::new_type_param (
}
break;
- case TypeParamBound::TypeParamBoundType::LIFETIME: {
+ case TypeParamBound::TypeParamBoundType::LIFETIME:
+ {
const Lifetime &l = (const Lifetime &) *b.get ();
auto bl = new Lifetime (l.get_lifetime_type (),
@@ -682,7 +717,7 @@ Builder::new_generic_args (GenericArgs &args)
for (auto &binding : args.get_binding_args ())
{
Type &t = *binding.get_type_ptr ().get ();
- std::unique_ptr<Type> ty = new_type (t);
+ std::unique_ptr<Type> ty = t.reconstruct ();
GenericArgsBinding b (binding.get_identifier (), std::move (ty),
binding.get_locus ());
binding_args.push_back (std::move (b));
@@ -690,19 +725,25 @@ Builder::new_generic_args (GenericArgs &args)
for (auto &arg : args.get_generic_args ())
{
+ tl::optional<GenericArg> new_arg = tl::nullopt;
+
switch (arg.get_kind ())
{
- case GenericArg::Kind::Type: {
- std::unique_ptr<Type> ty = new_type (arg.get_type ());
- GenericArg arg = GenericArg::create_type (std::move (ty));
- }
+ case GenericArg::Kind::Type:
+ new_arg = GenericArg::create_type (arg.get_type ().reconstruct ());
break;
-
- default:
- // FIXME
- rust_unreachable ();
+ case GenericArg::Kind::Either:
+ new_arg
+ = GenericArg::create_ambiguous (arg.get_path (), arg.get_locus ());
+ break;
+ case GenericArg::Kind::Const:
+ new_arg
+ = GenericArg::create_const (arg.get_expression ().clone_expr ());
+ // FIXME: Use `reconstruct()` here, not `clone_expr()`
break;
}
+
+ generic_args.emplace_back (*new_arg);
}
return GenericArgs (std::move (lifetime_args), std::move (generic_args),
diff --git a/gcc/rust/ast/rust-ast-builder.h b/gcc/rust/ast/rust-ast-builder.h
index 41ce118..843bab8 100644
--- a/gcc/rust/ast/rust-ast-builder.h
+++ b/gcc/rust/ast/rust-ast-builder.h
@@ -24,6 +24,7 @@
#include "rust-ast.h"
#include "rust-item.h"
#include "rust-operators.h"
+#include <initializer_list>
namespace Rust {
namespace AST {
@@ -51,6 +52,19 @@ vec (std::unique_ptr<T> &&t1, std::unique_ptr<T> &&t2)
return v;
}
+template <typename T>
+std::vector<std::unique_ptr<T>>
+vec (std::unique_ptr<T> &&t1, std::unique_ptr<T> &&t2, std::unique_ptr<T> &&t3)
+{
+ auto v = std::vector<std::unique_ptr<T>> ();
+
+ v.emplace_back (std::move (t1));
+ v.emplace_back (std::move (t2));
+ v.emplace_back (std::move (t3));
+
+ return v;
+}
+
/* Pointer-ify something */
template <typename T>
static std::unique_ptr<T>
@@ -117,6 +131,9 @@ public:
/* Create an empty block */
std::unique_ptr<BlockExpr> block () const;
+ /* Create a block with just a tail expression */
+ std::unique_ptr<BlockExpr> block (std::unique_ptr<Expr> &&tail_expr) const;
+
/* Create an early return expression with an optional expression */
std::unique_ptr<Expr> return_expr (std::unique_ptr<Expr> &&to_return
= nullptr);
@@ -254,6 +271,10 @@ public:
std::unique_ptr<Expr> field_access (std::unique_ptr<Expr> &&instance,
std::string field) const;
+ std::unique_ptr<StructPatternField>
+ struct_pattern_ident_pattern (std::string field_name,
+ std::unique_ptr<Pattern> &&pattern);
+
/* Create a wildcard pattern (`_`) */
std::unique_ptr<Pattern> wildcard () const;
/* Create a reference pattern (`&pattern`) */
@@ -268,6 +289,7 @@ public:
MatchArm match_arm (std::unique_ptr<Pattern> &&pattern);
MatchCase match_case (std::unique_ptr<Pattern> &&pattern,
std::unique_ptr<Expr> &&expr);
+ MatchCase match_case (MatchArm &&arm, std::unique_ptr<Expr> &&expr);
/* Create a loop expression */
std::unique_ptr<Expr> loop (std::vector<std::unique_ptr<Stmt>> &&stmts);
@@ -285,11 +307,20 @@ public:
std::vector<std::unique_ptr<TypeParamBound>> &&bounds,
std::unique_ptr<Type> &&type = nullptr);
- static std::unique_ptr<Type> new_type (Type &type);
+ /**
+ * Create a let statement with the discriminant value of a given enum
+ * instance. This helper exists since it is a common operation in a lot of the
+ * derive implementations, and it sucks to repeat all the steps every time.
+ */
+ std::unique_ptr<Stmt> discriminant_value (std::string binding_name,
+ std::string instance = "self");
static std::unique_ptr<GenericParam>
new_lifetime_param (LifetimeParam &param);
+ std::unique_ptr<GenericParam>
+ new_const_param (ConstGenericParam &param) const;
+
static std::unique_ptr<GenericParam> new_type_param (
TypeParam &param,
std::vector<std::unique_ptr<TypeParamBound>> extra_trait_bounds = {});
@@ -298,11 +329,13 @@ public:
static GenericArgs new_generic_args (GenericArgs &args);
-private:
- /**
- * Location of the generated AST nodes
- */
+ /* Location of the generated AST nodes */
location_t loc;
+
+private:
+ /* Some constexpr helpers for some of the builders */
+ static constexpr std::initializer_list<const char *> discriminant_value_path
+ = {"core", "intrinsics", "discriminant_value"};
};
} // namespace AST
diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc
index c850e96..3d9ea78 100644
--- a/gcc/rust/ast/rust-ast-collector.cc
+++ b/gcc/rust/ast/rust-ast-collector.cc
@@ -18,6 +18,7 @@
#include "rust-ast-collector.h"
#include "rust-ast.h"
+#include "rust-builtin-ast-nodes.h"
#include "rust-diagnostics.h"
#include "rust-expr.h"
#include "rust-item.h"
@@ -154,20 +155,24 @@ TokenCollector::visit (Attribute &attrib)
{
switch (attrib.get_attr_input ().get_attr_input_type ())
{
- case AST::AttrInput::AttrInputType::LITERAL: {
+ case AST::AttrInput::AttrInputType::LITERAL:
+ {
visit (static_cast<AttrInputLiteral &> (attrib.get_attr_input ()));
break;
}
- case AST::AttrInput::AttrInputType::MACRO: {
+ case AST::AttrInput::AttrInputType::MACRO:
+ {
visit (static_cast<AttrInputMacro &> (attrib.get_attr_input ()));
break;
}
- case AST::AttrInput::AttrInputType::META_ITEM: {
+ case AST::AttrInput::AttrInputType::META_ITEM:
+ {
visit (static_cast<AttrInputMetaItemContainer &> (
attrib.get_attr_input ()));
break;
}
- case AST::AttrInput::AttrInputType::TOKEN_TREE: {
+ case AST::AttrInput::AttrInputType::TOKEN_TREE:
+ {
visit (static_cast<DelimTokenTree &> (attrib.get_attr_input ()));
break;
}
@@ -634,7 +639,8 @@ TokenCollector::visit (GenericArg &arg)
case GenericArg::Kind::Type:
visit (arg.get_type ());
break;
- case GenericArg::Kind::Either: {
+ case GenericArg::Kind::Either:
+ {
auto path = arg.get_path ();
push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (path)));
}
@@ -789,7 +795,8 @@ TokenCollector::visit (Literal &lit, location_t locus)
push (Rust::Token::make_float (locus, std::move (value),
lit.get_type_hint ()));
break;
- case Literal::LitType::BOOL: {
+ case Literal::LitType::BOOL:
+ {
if (value == Values::Keywords::FALSE_LITERAL)
push (Rust::Token::make (FALSE_LITERAL, locus));
else if (value == Values::Keywords::TRUE_LITERAL)
@@ -833,13 +840,13 @@ TokenCollector::visit (MetaItemLitExpr &item)
}
void
-TokenCollector::visit (MetaItemPathLit &item)
+TokenCollector::visit (MetaItemPathExpr &item)
{
- auto path = item.get_path ();
- auto lit = item.get_literal ();
+ auto &path = item.get_path ();
+ auto &expr = item.get_expr ();
visit (path);
- push (Rust::Token::make (COLON, item.get_locus ()));
- visit (lit);
+ push (Rust::Token::make (EQUAL, item.get_locus ()));
+ visit (expr);
}
void
@@ -864,7 +871,8 @@ TokenCollector::visit (BorrowExpr &expr)
push (Rust::Token::make (MUT, UNDEF_LOCATION));
}
- visit (expr.get_borrowed_expr ());
+ if (expr.has_borrow_expr ())
+ visit (expr.get_borrowed_expr ());
}
void
@@ -1264,12 +1272,34 @@ TokenCollector::visit (BlockExpr &expr)
}
void
+TokenCollector::visit (AnonConst &expr)
+{
+ if (!expr.is_deferred ())
+ {
+ visit (expr.get_inner_expr ());
+ return;
+ }
+
+ push (Rust::Token::make_string (expr.get_locus (), "_"));
+}
+
+void
+TokenCollector::visit (ConstBlock &expr)
+{
+ push (Rust::Token::make (CONST, expr.get_locus ()));
+
+ // The inner expression is already a block expr, so we don't need to add
+ // curlies
+ visit (expr.get_const_expr ());
+}
+
+void
TokenCollector::visit (ClosureExprInnerTyped &expr)
{
visit_closure_common (expr);
push (Rust::Token::make (RETURN_TYPE, expr.get_locus ()));
visit (expr.get_return_type ());
- visit (expr.get_definition_block ());
+ visit (expr.get_definition_expr ());
}
void
@@ -1349,6 +1379,13 @@ TokenCollector::visit (ReturnExpr &expr)
}
void
+TokenCollector::visit (TryExpr &expr)
+{
+ push (Rust::Token::make (TRY, expr.get_locus ()));
+ visit (expr.get_block_expr ());
+}
+
+void
TokenCollector::visit (UnsafeBlockExpr &expr)
{
push (Rust::Token::make (UNSAFE, expr.get_locus ()));
@@ -1518,7 +1555,95 @@ TokenCollector::visit (AsyncBlockExpr &expr)
void
TokenCollector::visit (InlineAsm &expr)
-{}
+{
+ push (Rust::Token::make_identifier (expr.get_locus (), "asm"));
+ push (Rust::Token::make (EXCLAM, expr.get_locus ()));
+ push (Rust::Token::make (LEFT_PAREN, expr.get_locus ()));
+
+ for (auto &template_str : expr.get_template_strs ())
+ push (Rust::Token::make_string (template_str.get_locus (),
+ std::move (template_str.symbol)));
+
+ push (Rust::Token::make (COLON, expr.get_locus ()));
+
+ for (auto &operand : expr.get_operands ())
+ {
+ using RegisterType = AST::InlineAsmOperand::RegisterType;
+ switch (operand.get_register_type ())
+ {
+ case RegisterType::In:
+ {
+ visit (operand.get_in ().expr);
+ break;
+ }
+ case RegisterType::Out:
+ {
+ visit (operand.get_out ().expr);
+ break;
+ }
+ case RegisterType::InOut:
+ {
+ visit (operand.get_in_out ().expr);
+ break;
+ }
+ case RegisterType::SplitInOut:
+ {
+ auto split = operand.get_split_in_out ();
+ visit (split.in_expr);
+ visit (split.out_expr);
+ break;
+ }
+ case RegisterType::Const:
+ {
+ visit (operand.get_const ().anon_const.get_inner_expr ());
+ break;
+ }
+ case RegisterType::Sym:
+ {
+ visit (operand.get_sym ().expr);
+ break;
+ }
+ case RegisterType::Label:
+ {
+ visit (operand.get_label ().expr);
+ break;
+ }
+ }
+ push (Rust::Token::make (COMMA, expr.get_locus ()));
+ }
+ push (Rust::Token::make (COLON, expr.get_locus ()));
+
+ for (auto &clobber : expr.get_clobber_abi ())
+ {
+ 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 ()));
+
+ for (auto it = expr.named_args.begin (); it != expr.named_args.end (); ++it)
+ {
+ auto &arg = *it;
+ push (
+ Rust::Token::make_identifier (expr.get_locus (), arg.first.c_str ()));
+ push (Rust::Token::make (EQUAL, expr.get_locus ()));
+ push (Rust::Token::make_identifier (expr.get_locus (),
+ std::to_string (arg.second)));
+
+ push (Rust::Token::make (COMMA, expr.get_locus ()));
+ }
+
+ push (Rust::Token::make (COLON, expr.get_locus ()));
+
+ for (auto &option : expr.get_options ())
+ {
+ push (Rust::Token::make_identifier (
+ expr.get_locus (), InlineAsm::option_to_string (option).c_str ()));
+ push (Rust::Token::make (COMMA, expr.get_locus ()));
+ }
+
+ push (Rust::Token::make (RIGHT_PAREN, expr.get_locus ()));
+}
void
TokenCollector::visit (LlvmInlineAsm &expr)
@@ -1695,7 +1820,8 @@ TokenCollector::visit (UseTreeGlob &use_tree)
{
switch (use_tree.get_glob_type ())
{
- case UseTreeGlob::PathType::PATH_PREFIXED: {
+ case UseTreeGlob::PathType::PATH_PREFIXED:
+ {
auto path = use_tree.get_path ();
visit (path);
push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION));
@@ -1715,7 +1841,8 @@ TokenCollector::visit (UseTreeList &use_tree)
{
switch (use_tree.get_path_type ())
{
- case UseTreeList::PathType::PATH_PREFIXED: {
+ case UseTreeList::PathType::PATH_PREFIXED:
+ {
auto path = use_tree.get_path ();
visit (path);
push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION));
@@ -1743,7 +1870,8 @@ TokenCollector::visit (UseTreeRebind &use_tree)
visit (path);
switch (use_tree.get_new_bind_type ())
{
- case UseTreeRebind::NewBindType::IDENTIFIER: {
+ case UseTreeRebind::NewBindType::IDENTIFIER:
+ {
push (Rust::Token::make (AS, UNDEF_LOCATION));
auto id = use_tree.get_identifier ().as_string ();
push (
@@ -1964,8 +2092,7 @@ TokenCollector::visit (ConstantItem &item)
}
else
{
- auto id = item.get_identifier ();
- push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id)));
+ push (Rust::Token::make_identifier (item.get_identifier ()));
}
push (Rust::Token::make (COLON, UNDEF_LOCATION));
visit (item.get_type ());
@@ -2370,10 +2497,10 @@ TokenCollector::visit (IdentifierPattern &pattern)
auto id = pattern.get_ident ().as_string ();
push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id)));
- if (pattern.has_pattern_to_bind ())
+ if (pattern.has_subpattern ())
{
push (Rust::Token::make (PATTERN_BIND, UNDEF_LOCATION));
- visit (pattern.get_pattern_to_bind ());
+ visit (pattern.get_subpattern ());
}
}
@@ -2591,10 +2718,34 @@ TokenCollector::visit (GroupedPattern &pattern)
}
void
+TokenCollector::visit (SlicePatternItemsNoRest &items)
+{
+ visit_items_joined_by_separator (items.get_patterns (), COMMA);
+}
+
+void
+TokenCollector::visit (SlicePatternItemsHasRest &items)
+{
+ if (!items.get_lower_patterns ().empty ())
+ {
+ visit_items_joined_by_separator (items.get_lower_patterns (), COMMA);
+ push (Rust::Token::make (COMMA, UNDEF_LOCATION));
+ }
+
+ push (Rust::Token::make (DOT_DOT, UNDEF_LOCATION));
+
+ if (!items.get_upper_patterns ().empty ())
+ {
+ push (Rust::Token::make (COMMA, UNDEF_LOCATION));
+ visit_items_joined_by_separator (items.get_upper_patterns (), COMMA);
+ }
+}
+
+void
TokenCollector::visit (SlicePattern &pattern)
{
push (Rust::Token::make (LEFT_SQUARE, pattern.get_locus ()));
- visit_items_joined_by_separator (pattern.get_items (), COMMA);
+ visit (pattern.get_items ());
push (Rust::Token::make (RIGHT_SQUARE, UNDEF_LOCATION));
}
@@ -2862,5 +3013,23 @@ TokenCollector::visit (AST::FormatArgs &fmt)
__FILE__, __LINE__);
}
+void
+TokenCollector::visit (AST::OffsetOf &offset_of)
+{
+ auto loc = offset_of.get_locus ();
+
+ push (Rust::Token::make_identifier (loc, "offset_of"));
+ push (Rust::Token::make (EXCLAM, loc));
+ push (Rust::Token::make (LEFT_PAREN, loc));
+
+ visit (offset_of.get_type ());
+
+ push (Rust::Token::make (COMMA, loc));
+
+ push (Rust::Token::make_identifier (offset_of.get_field ()));
+
+ push (Rust::Token::make (RIGHT_PAREN, loc));
+}
+
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/ast/rust-ast-collector.h b/gcc/rust/ast/rust-ast-collector.h
index f45e3cc..d3ab18a 100644
--- a/gcc/rust/ast/rust-ast-collector.h
+++ b/gcc/rust/ast/rust-ast-collector.h
@@ -246,7 +246,7 @@ public:
void visit (AttrInputLiteral &attr_input);
void visit (AttrInputMacro &attr_input);
void visit (MetaItemLitExpr &meta_item);
- void visit (MetaItemPathLit &meta_item);
+ void visit (MetaItemPathExpr &meta_item);
void visit (BorrowExpr &expr);
void visit (DereferenceExpr &expr);
void visit (ErrorPropagationExpr &expr);
@@ -277,6 +277,8 @@ public:
void visit (ClosureParam &param);
void visit (ClosureExprInner &expr);
void visit (BlockExpr &expr);
+ void visit (AnonConst &expr);
+ void visit (ConstBlock &expr);
void visit (ClosureExprInnerTyped &expr);
void visit (ContinueExpr &expr);
void visit (BreakExpr &expr);
@@ -287,6 +289,7 @@ public:
void visit (RangeFromToInclExpr &expr);
void visit (RangeToInclExpr &expr);
void visit (ReturnExpr &expr);
+ void visit (TryExpr &expr);
void visit (BoxExpr &expr);
void visit (UnsafeBlockExpr &expr);
void visit (LoopExpr &expr);
@@ -375,6 +378,8 @@ public:
void visit (TuplePatternItemsRanged &tuple_items);
void visit (TuplePattern &pattern);
void visit (GroupedPattern &pattern);
+ void visit (SlicePatternItemsNoRest &items);
+ void visit (SlicePatternItemsHasRest &items);
void visit (SlicePattern &pattern);
void visit (AltPattern &pattern);
@@ -400,6 +405,7 @@ public:
void visit (BareFunctionType &type);
void visit (FormatArgs &fmt);
+ void visit (OffsetOf &offset_of);
};
} // namespace AST
diff --git a/gcc/rust/ast/rust-ast-dump.h b/gcc/rust/ast/rust-ast-dump.h
index 02c99b7..0c3875e 100644
--- a/gcc/rust/ast/rust-ast-dump.h
+++ b/gcc/rust/ast/rust-ast-dump.h
@@ -49,7 +49,8 @@ public:
{
switch (item.get_kind ())
{
- case AST::CollectItem::Kind::Token: {
+ case AST::CollectItem::Kind::Token:
+ {
TokenPtr current = item.get_token ();
if (require_spacing (previous, current))
stream << " ";
@@ -90,7 +91,6 @@ private:
} // namespace Rust
// In the global namespace to make it easier to call from debugger
-void
-debug (Rust::AST::Visitable &v);
+void debug (Rust::AST::Visitable &v);
#endif // !RUST_AST_DUMP_H
diff --git a/gcc/rust/ast/rust-ast-formatting.h b/gcc/rust/ast/rust-ast-formatting.h
index 3dfabbc..aace93f 100644
--- a/gcc/rust/ast/rust-ast-formatting.h
+++ b/gcc/rust/ast/rust-ast-formatting.h
@@ -35,23 +35,18 @@ enum AttrMode
INNER
};
-std::string
-indent_spaces (enum indent_mode mode);
+std::string indent_spaces (enum indent_mode mode);
// Gets a string in a certain delim type.
-std::string
-get_string_in_delims (std::string str_input, DelimType delim_type);
+std::string get_string_in_delims (std::string str_input, DelimType delim_type);
-std::string
-get_mode_dump_desc (AttrMode mode);
+std::string get_mode_dump_desc (AttrMode mode);
// Adds lines below adding attributes
-std::string
-append_attributes (std::vector<Attribute> attrs, AttrMode mode);
+std::string append_attributes (std::vector<Attribute> attrs, AttrMode mode);
// Removes the beginning and end quotes of a quoted string.
-std::string
-unquote_string (std::string input);
+std::string unquote_string (std::string input);
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h
index 9359248..09706ce 100644
--- a/gcc/rust/ast/rust-ast-full-decls.h
+++ b/gcc/rust/ast/rust-ast-full-decls.h
@@ -78,7 +78,7 @@ class LiteralExpr;
class AttrInputLiteral;
class AttrInputMacro;
class MetaItemLitExpr;
-class MetaItemPathLit;
+class MetaItemPathExpr;
class OperatorExpr;
class BorrowExpr;
class DereferenceExpr;
@@ -115,6 +115,8 @@ struct ClosureParam;
class ClosureExpr;
class ClosureExprInner;
class BlockExpr;
+class AnonConst;
+class ConstBlock;
class ClosureExprInnerTyped;
class ContinueExpr;
class BreakExpr;
@@ -126,6 +128,7 @@ class RangeFullExpr;
class RangeFromToInclExpr;
class RangeToInclExpr;
class ReturnExpr;
+class TryExpr;
class UnsafeBlockExpr;
class LoopLabel;
class BaseLoopExpr;
@@ -146,7 +149,6 @@ class MatchExpr;
class AwaitExpr;
class AsyncBlockExpr;
enum class InlineAsmOption;
-struct AnonConst;
struct InlineAsmRegOrRegClass;
class InlineAsmOperand;
struct InlineAsmPlaceHolder;
@@ -246,6 +248,8 @@ class TuplePatternItemsMultiple;
class TuplePatternItemsRanged;
class TuplePattern;
class GroupedPattern;
+class SlicePatternItemsNoRest;
+class SlicePatternItemsHasRest;
class SlicePattern;
class AltPattern;
diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc
index b6833f6..ab8cdbe 100644
--- a/gcc/rust/ast/rust-ast-visitor.cc
+++ b/gcc/rust/ast/rust-ast-visitor.cc
@@ -19,6 +19,7 @@
#include "rust-ast-visitor.h"
#include "rust-ast-full-decls.h"
#include "rust-ast.h"
+#include "rust-builtin-ast-nodes.h"
#include "rust-path.h"
#include "rust-token.h"
#include "rust-expr.h"
@@ -223,10 +224,10 @@ DefaultASTVisitor::visit (AST::SimplePath &path)
}
void
-DefaultASTVisitor::visit (AST::MetaItemPathLit &meta_item)
+DefaultASTVisitor::visit (AST::MetaItemPathExpr &meta_item)
{
visit (meta_item.get_path ());
- visit (meta_item.get_literal ());
+ visit (meta_item.get_expr ());
}
void
@@ -449,20 +450,38 @@ DefaultASTVisitor::visit (AST::BlockExpr &expr)
{
visit_outer_attrs (expr);
visit_inner_attrs (expr);
+
+ if (expr.has_label ())
+ visit (expr.get_label ());
+
for (auto &stmt : expr.get_statements ())
visit (stmt);
+
if (expr.has_tail_expr ())
visit (expr.get_tail_expr ());
}
void
+DefaultASTVisitor::visit (AST::ConstBlock &expr)
+{
+ visit (expr.get_const_expr ());
+}
+
+void
+DefaultASTVisitor::visit (AST::AnonConst &expr)
+{
+ if (!expr.is_deferred ())
+ visit (expr.get_inner_expr ());
+}
+
+void
DefaultASTVisitor::visit (AST::ClosureExprInnerTyped &expr)
{
visit_outer_attrs (expr);
for (auto &param : expr.get_params ())
visit (param);
visit (expr.get_return_type ());
- visit (expr.get_definition_block ());
+ visit (expr.get_definition_expr ());
}
void
@@ -538,6 +557,13 @@ DefaultASTVisitor::visit (AST::ReturnExpr &expr)
}
void
+DefaultASTVisitor::visit (AST::TryExpr &expr)
+{
+ visit_outer_attrs (expr);
+ visit (expr.get_block_expr ());
+}
+
+void
DefaultASTVisitor::visit (AST::BoxExpr &expr)
{
visit_outer_attrs (expr);
@@ -582,7 +608,10 @@ DefaultASTVisitor::visit (AST::WhileLetLoopExpr &expr)
visit_outer_attrs (expr);
for (auto &pattern : expr.get_patterns ())
visit (pattern);
- visit (expr.get_loop_label ());
+
+ if (expr.has_loop_label ())
+ visit (expr.get_loop_label ());
+
visit (expr.get_scrutinee_expr ());
visit (expr.get_loop_block ());
}
@@ -680,33 +709,40 @@ DefaultASTVisitor::visit (AST::InlineAsm &expr)
{
switch (operand.get_register_type ())
{
- case RegisterType::In: {
+ case RegisterType::In:
+ {
visit (operand.get_in ().expr);
break;
}
- case RegisterType::Out: {
+ case RegisterType::Out:
+ {
visit (operand.get_out ().expr);
break;
}
- case RegisterType::InOut: {
+ case RegisterType::InOut:
+ {
visit (operand.get_in_out ().expr);
break;
}
- case RegisterType::SplitInOut: {
+ case RegisterType::SplitInOut:
+ {
auto split = operand.get_split_in_out ();
visit (split.in_expr);
visit (split.out_expr);
break;
}
- case RegisterType::Const: {
- visit (operand.get_const ().anon_const.expr);
+ case RegisterType::Const:
+ {
+ visit (operand.get_const ().anon_const.get_inner_expr ());
break;
}
- case RegisterType::Sym: {
+ case RegisterType::Sym:
+ {
visit (operand.get_sym ().expr);
break;
}
- case RegisterType::Label: {
+ case RegisterType::Label:
+ {
visit (operand.get_label ().expr);
break;
}
@@ -755,7 +791,8 @@ DefaultASTVisitor::visit (AST::TypeBoundWhereClauseItem &item)
void
DefaultASTVisitor::visit (AST::Visibility &vis)
{
- visit (vis.get_path ());
+ if (vis.has_path ())
+ visit (vis.get_path ());
}
void
@@ -922,7 +959,7 @@ DefaultASTVisitor::visit (AST::EnumItem &item)
void
DefaultASTVisitor::visit (AST::EnumItemTuple &item)
{
- visit (reinterpret_cast<EnumItem &> (item));
+ DefaultASTVisitor::visit (static_cast<EnumItem &> (item));
for (auto &field : item.get_tuple_fields ())
visit (field);
}
@@ -930,7 +967,7 @@ DefaultASTVisitor::visit (AST::EnumItemTuple &item)
void
DefaultASTVisitor::visit (AST::EnumItemStruct &item)
{
- visit (reinterpret_cast<EnumItem &> (item));
+ DefaultASTVisitor::visit (static_cast<EnumItem &> (item));
for (auto &field : item.get_struct_fields ())
visit (field);
}
@@ -938,7 +975,7 @@ DefaultASTVisitor::visit (AST::EnumItemStruct &item)
void
DefaultASTVisitor::visit (AST::EnumItemDiscriminant &item)
{
- visit (reinterpret_cast<EnumItem &> (item));
+ DefaultASTVisitor::visit (static_cast<EnumItem &> (item));
visit (item.get_expr ());
}
@@ -1179,8 +1216,8 @@ DefaultASTVisitor::visit (AST::LiteralPattern &pattern)
void
DefaultASTVisitor::visit (AST::IdentifierPattern &pattern)
{
- if (pattern.has_pattern_to_bind ())
- visit (pattern.get_pattern_to_bind ());
+ if (pattern.has_subpattern ())
+ visit (pattern.get_subpattern ());
}
void
@@ -1310,13 +1347,28 @@ DefaultASTVisitor::visit (AST::GroupedPattern &pattern)
}
void
-DefaultASTVisitor::visit (AST::SlicePattern &pattern)
+DefaultASTVisitor::visit (AST::SlicePatternItemsNoRest &items)
+{
+ for (auto &item : items.get_patterns ())
+ visit (item);
+}
+
+void
+DefaultASTVisitor::visit (AST::SlicePatternItemsHasRest &items)
{
- for (auto &item : pattern.get_items ())
+ for (auto &item : items.get_lower_patterns ())
+ visit (item);
+ for (auto &item : items.get_upper_patterns ())
visit (item);
}
void
+DefaultASTVisitor::visit (AST::SlicePattern &pattern)
+{
+ visit (pattern.get_items ());
+}
+
+void
DefaultASTVisitor::visit (AST::AltPattern &pattern)
{
for (auto &alt : pattern.get_alts ())
@@ -1454,6 +1506,12 @@ DefaultASTVisitor::visit (AST::FormatArgs &)
}
void
+DefaultASTVisitor::visit (AST::OffsetOf &offset_of)
+{
+ visit (offset_of.get_type ());
+}
+
+void
DefaultASTVisitor::visit (AST::VariadicParam &param)
{
if (param.has_pattern ())
diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h
index b1fc504..2d81aa1 100644
--- a/gcc/rust/ast/rust-ast-visitor.h
+++ b/gcc/rust/ast/rust-ast-visitor.h
@@ -73,7 +73,7 @@ public:
virtual void visit (AttrInputLiteral &attr_input) = 0;
virtual void visit (AttrInputMacro &attr_input) = 0;
virtual void visit (MetaItemLitExpr &meta_item) = 0;
- virtual void visit (MetaItemPathLit &meta_item) = 0;
+ virtual void visit (MetaItemPathExpr &meta_item) = 0;
virtual void visit (BorrowExpr &expr) = 0;
virtual void visit (DereferenceExpr &expr) = 0;
virtual void visit (ErrorPropagationExpr &expr) = 0;
@@ -104,6 +104,8 @@ public:
virtual void visit (FieldAccessExpr &expr) = 0;
virtual void visit (ClosureExprInner &expr) = 0;
virtual void visit (BlockExpr &expr) = 0;
+ virtual void visit (AnonConst &expr) = 0;
+ virtual void visit (ConstBlock &expr) = 0;
virtual void visit (ClosureExprInnerTyped &expr) = 0;
virtual void visit (ContinueExpr &expr) = 0;
virtual void visit (BreakExpr &expr) = 0;
@@ -114,6 +116,7 @@ public:
virtual void visit (RangeFromToInclExpr &expr) = 0;
virtual void visit (RangeToInclExpr &expr) = 0;
virtual void visit (ReturnExpr &expr) = 0;
+ virtual void visit (TryExpr &expr) = 0;
virtual void visit (BoxExpr &expr) = 0;
virtual void visit (UnsafeBlockExpr &expr) = 0;
virtual void visit (LoopExpr &expr) = 0;
@@ -209,6 +212,8 @@ public:
virtual void visit (TuplePatternItemsRanged &tuple_items) = 0;
virtual void visit (TuplePattern &pattern) = 0;
virtual void visit (GroupedPattern &pattern) = 0;
+ virtual void visit (SlicePatternItemsNoRest &items) = 0;
+ virtual void visit (SlicePatternItemsHasRest &items) = 0;
virtual void visit (SlicePattern &pattern) = 0;
virtual void visit (AltPattern &pattern) = 0;
@@ -235,6 +240,7 @@ public:
// special AST nodes for certain builtin macros such as `asm!()`
virtual void visit (FormatArgs &fmt) = 0;
+ virtual void visit (OffsetOf &fmt) = 0;
// TODO: rust-cond-compilation.h visiting? not currently used
};
@@ -264,7 +270,7 @@ public:
virtual void visit (AST::AttrInputLiteral &attr_input) override;
virtual void visit (AST::AttrInputMacro &attr_input) override;
virtual void visit (AST::MetaItemLitExpr &meta_item) override;
- virtual void visit (AST::MetaItemPathLit &meta_item) override;
+ virtual void visit (AST::MetaItemPathExpr &meta_item) override;
virtual void visit (AST::BorrowExpr &expr) override;
virtual void visit (AST::DereferenceExpr &expr) override;
virtual void visit (AST::ErrorPropagationExpr &expr) override;
@@ -293,6 +299,8 @@ public:
virtual void visit (AST::FieldAccessExpr &expr) override;
virtual void visit (AST::ClosureExprInner &expr) override;
virtual void visit (AST::BlockExpr &expr) override;
+ virtual void visit (AST::AnonConst &expr) override;
+ virtual void visit (AST::ConstBlock &expr) override;
virtual void visit (AST::ClosureExprInnerTyped &expr) override;
virtual void visit (AST::ContinueExpr &expr) override;
virtual void visit (AST::BreakExpr &expr) override;
@@ -303,6 +311,7 @@ public:
virtual void visit (AST::RangeFromToInclExpr &expr) override;
virtual void visit (AST::RangeToInclExpr &expr) override;
virtual void visit (AST::ReturnExpr &expr) override;
+ virtual void visit (AST::TryExpr &expr) override;
virtual void visit (AST::BoxExpr &expr) override;
virtual void visit (AST::UnsafeBlockExpr &expr) override;
virtual void visit (AST::LoopExpr &expr) override;
@@ -379,6 +388,8 @@ public:
virtual void visit (AST::TuplePatternItemsRanged &tuple_items) override;
virtual void visit (AST::TuplePattern &pattern) override;
virtual void visit (AST::GroupedPattern &pattern) override;
+ virtual void visit (AST::SlicePatternItemsNoRest &items) override;
+ virtual void visit (AST::SlicePatternItemsHasRest &items) override;
virtual void visit (AST::SlicePattern &pattern) override;
virtual void visit (AST::AltPattern &pattern) override;
virtual void visit (AST::EmptyStmt &stmt) override;
@@ -402,6 +413,7 @@ public:
virtual void visit (AST::FunctionParam &param) override;
virtual void visit (AST::VariadicParam &param) override;
virtual void visit (AST::FormatArgs &fmt) override;
+ virtual void visit (AST::OffsetOf &fmt) override;
template <typename T> void visit (T &node) { node.accept_vis (*this); }
diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc
index 4e82be4..8e856fb 100644
--- a/gcc/rust/ast/rust-ast.cc
+++ b/gcc/rust/ast/rust-ast.cc
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see
#include "rust-operators.h"
#include "rust-dir-owner.h"
#include "rust-attribute-values.h"
+#include "rust-macro-invoc-lexer.h"
/* Compilation unit used for various AST-related functions that would make
* the headers too long if they were defined inline and don't receive any
@@ -249,27 +250,31 @@ Attribute::get_traits_to_derive ()
auto &input = get_attr_input ();
switch (input.get_attr_input_type ())
{
- case AST::AttrInput::META_ITEM: {
+ case AST::AttrInput::META_ITEM:
+ {
auto &meta = static_cast<AST::AttrInputMetaItemContainer &> (input);
for (auto &current : meta.get_items ())
{
// HACK: Find a better way to achieve the downcast.
switch (current->get_kind ())
{
- case AST::MetaItemInner::Kind::MetaItem: {
+ case AST::MetaItemInner::Kind::MetaItem:
+ {
// Let raw pointer go out of scope without freeing, it doesn't
// own the data anyway
auto meta_item
= static_cast<AST::MetaItem *> (current.get ());
switch (meta_item->get_item_kind ())
{
- case AST::MetaItem::ItemKind::Path: {
+ case AST::MetaItem::ItemKind::Path:
+ {
auto path
= static_cast<AST::MetaItemPath *> (meta_item);
result.push_back (path->get_path ());
}
break;
- case AST::MetaItem::ItemKind::Word: {
+ case AST::MetaItem::ItemKind::Word:
+ {
auto word = static_cast<AST::MetaWord *> (meta_item);
// Convert current word to path
current = std::make_unique<AST::MetaItemPath> (
@@ -283,7 +288,7 @@ Attribute::get_traits_to_derive ()
break;
case AST::MetaItem::ItemKind::ListPaths:
case AST::MetaItem::ItemKind::NameValueStr:
- case AST::MetaItem::ItemKind::PathLit:
+ case AST::MetaItem::ItemKind::PathExpr:
case AST::MetaItem::ItemKind::Seq:
case AST::MetaItem::ItemKind::ListNameValueStr:
default:
@@ -620,7 +625,7 @@ ConstantItem::as_string () const
{
std::string str = VisItem::as_string ();
- str += "const " + identifier;
+ str += "const " + identifier.as_string ();
// DEBUG: null pointer check
if (type == nullptr)
@@ -782,7 +787,8 @@ UseTreeGlob::as_string () const
return "*";
case GLOBAL:
return "::*";
- case PATH_PREFIXED: {
+ case PATH_PREFIXED:
+ {
std::string path_str = path.as_string ();
return path_str + "::*";
}
@@ -805,7 +811,8 @@ UseTreeList::as_string () const
case GLOBAL:
path_str = "::{";
break;
- case PATH_PREFIXED: {
+ case PATH_PREFIXED:
+ {
path_str = path.as_string () + "::{";
break;
}
@@ -1272,6 +1279,25 @@ BlockExpr::as_string () const
}
std::string
+AnonConst::as_string () const
+{
+ std::string str = "AnonConst: ";
+
+ if (kind == AnonConst::Kind::DeferredInference)
+ str += "_";
+ else
+ str += expr.value ()->as_string ();
+
+ return str;
+}
+
+std::string
+ConstBlock::as_string () const
+{
+ return "ConstBlock: " + expr.as_string ();
+}
+
+std::string
TraitImpl::as_string () const
{
std::string str = VisItem::as_string ();
@@ -1619,6 +1645,19 @@ ReturnExpr::as_string () const
}
std::string
+TryExpr::as_string () const
+{
+ /* TODO: find way to incorporate outer attrs - may have to represent in
+ * different style (i.e. something more like BorrowExpr: \n outer attrs) */
+
+ std::string str ("try ");
+
+ str += block_expr->as_string ();
+
+ return str;
+}
+
+std::string
RangeToExpr::as_string () const
{
return ".." + to->as_string ();
@@ -2714,7 +2753,7 @@ ImplTraitTypeOneBound::as_string () const
{
std::string str ("ImplTraitTypeOneBound: \n TraitBound: ");
- return str + trait_bound.as_string ();
+ return str + trait_bound->as_string ();
}
std::string
@@ -2736,7 +2775,7 @@ std::string
ArrayType::as_string () const
{
// TODO: rewrite to work with non-linearisable types and exprs
- return "[" + elem_type->as_string () + "; " + size->as_string () + "]";
+ return "[" + elem_type->as_string () + "; " + size.as_string () + "]";
}
std::string
@@ -3477,13 +3516,24 @@ DelimTokenTree::parse_to_meta_item () const
return new AttrInputMetaItemContainer (std::move (meta_items));
}
+AttributeParser::AttributeParser (
+ std::vector<std::unique_ptr<Token>> token_stream, int stream_start_pos)
+ : lexer (new MacroInvocLexer (std::move (token_stream))),
+ parser (new Parser<MacroInvocLexer> (*lexer))
+{
+ if (stream_start_pos)
+ lexer->skip_token (stream_start_pos - 1);
+}
+
+AttributeParser::~AttributeParser () {}
+
std::unique_ptr<MetaItemInner>
AttributeParser::parse_meta_item_inner ()
{
// if first tok not identifier, not a "special" case one
- if (peek_token ()->get_id () != IDENTIFIER)
+ if (lexer->peek_token ()->get_id () != IDENTIFIER)
{
- switch (peek_token ()->get_id ())
+ switch (lexer->peek_token ()->get_id ())
{
case CHAR_LITERAL:
case STRING_LITERAL:
@@ -3504,48 +3554,46 @@ AttributeParser::parse_meta_item_inner ()
return parse_path_meta_item ();
default:
- rust_error_at (peek_token ()->get_locus (),
+ rust_error_at (lexer->peek_token ()->get_locus (),
"unrecognised token '%s' in meta item",
- get_token_description (peek_token ()->get_id ()));
+ get_token_description (
+ lexer->peek_token ()->get_id ()));
return nullptr;
}
}
// else, check for path
- if (peek_token (1)->get_id () == SCOPE_RESOLUTION)
+ if (lexer->peek_token (1)->get_id () == SCOPE_RESOLUTION)
{
// path
return parse_path_meta_item ();
}
- auto ident = peek_token ()->as_string ();
- auto ident_locus = peek_token ()->get_locus ();
+ auto ident = lexer->peek_token ()->get_str ();
+ auto ident_locus = lexer->peek_token ()->get_locus ();
- if (is_end_meta_item_tok (peek_token (1)->get_id ()))
+ if (is_end_meta_item_tok (lexer->peek_token (1)->get_id ()))
{
// meta word syntax
- skip_token ();
+ lexer->skip_token ();
return std::unique_ptr<MetaWord> (new MetaWord (ident, ident_locus));
}
- if (peek_token (1)->get_id () == EQUAL)
+ if (lexer->peek_token (1)->get_id () == EQUAL)
{
// maybe meta name value str syntax - check next 2 tokens
- if (peek_token (2)->get_id () == STRING_LITERAL
- && is_end_meta_item_tok (peek_token (3)->get_id ()))
+ if (lexer->peek_token (2)->get_id () == STRING_LITERAL
+ && is_end_meta_item_tok (lexer->peek_token (3)->get_id ()))
{
// meta name value str syntax
- auto &value_tok = peek_token (2);
- auto value = value_tok->as_string ();
+ const_TokenPtr value_tok = lexer->peek_token (2);
+ auto value = value_tok->get_str ();
auto locus = value_tok->get_locus ();
- skip_token (2);
-
- // remove the quotes from the string value
- std::string raw_value = unquote_string (std::move (value));
+ lexer->skip_token (2);
return std::unique_ptr<MetaNameValueStr> (
- new MetaNameValueStr (ident, ident_locus, std::move (raw_value),
+ new MetaNameValueStr (ident, ident_locus, std::move (value),
locus));
}
else
@@ -3555,16 +3603,16 @@ AttributeParser::parse_meta_item_inner ()
}
}
- if (peek_token (1)->get_id () != LEFT_PAREN)
+ if (lexer->peek_token (1)->get_id () != LEFT_PAREN)
{
- rust_error_at (peek_token (1)->get_locus (),
+ rust_error_at (lexer->peek_token (1)->get_locus (),
"unexpected token '%s' after identifier in attribute",
- get_token_description (peek_token (1)->get_id ()));
+ get_token_description (lexer->peek_token (1)->get_id ()));
return nullptr;
}
// is it one of those special cases like not?
- if (peek_token ()->get_id () == IDENTIFIER)
+ if (lexer->peek_token ()->get_id () == IDENTIFIER)
{
return parse_path_meta_item ();
}
@@ -3643,49 +3691,46 @@ AttributeParser::is_end_meta_item_tok (TokenId id) const
std::unique_ptr<MetaItem>
AttributeParser::parse_path_meta_item ()
{
- SimplePath path = parse_simple_path ();
+ SimplePath path = parser->parse_simple_path ();
if (path.is_empty ())
{
- rust_error_at (peek_token ()->get_locus (),
+ rust_error_at (lexer->peek_token ()->get_locus (),
"failed to parse simple path in attribute");
return nullptr;
}
- switch (peek_token ()->get_id ())
+ switch (lexer->peek_token ()->get_id ())
{
- case LEFT_PAREN: {
+ case LEFT_PAREN:
+ {
std::vector<std::unique_ptr<MetaItemInner>> meta_items
= parse_meta_item_seq ();
return std::unique_ptr<MetaItemSeq> (
new MetaItemSeq (std::move (path), std::move (meta_items)));
}
- case EQUAL: {
- skip_token ();
+ case EQUAL:
+ {
+ lexer->skip_token ();
- location_t locus = peek_token ()->get_locus ();
- Literal lit = parse_literal ();
- if (lit.is_error ())
- {
- rust_error_at (peek_token ()->get_locus (),
- "failed to parse literal in attribute");
- return nullptr;
- }
- LiteralExpr expr (std::move (lit), {}, locus);
- // stream_pos++;
- /* shouldn't be required anymore due to parsing literal actually
- * skipping the token */
- return std::unique_ptr<MetaItemPathLit> (
- new MetaItemPathLit (std::move (path), std::move (expr)));
+ std::unique_ptr<Expr> expr = parser->parse_expr ();
+
+ // handle error
+ // parse_expr should already emit an error and return nullptr
+ if (!expr)
+ return nullptr;
+
+ return std::unique_ptr<MetaItemPathExpr> (
+ new MetaItemPathExpr (std::move (path), std::move (expr)));
}
case COMMA:
// just simple path
return std::unique_ptr<MetaItemPath> (
new MetaItemPath (std::move (path)));
default:
- rust_error_at (peek_token ()->get_locus (),
+ rust_error_at (lexer->peek_token ()->get_locus (),
"unrecognised token '%s' in meta item",
- get_token_description (peek_token ()->get_id ()));
+ get_token_description (lexer->peek_token ()->get_id ()));
return nullptr;
}
}
@@ -3695,41 +3740,41 @@ AttributeParser::parse_path_meta_item ()
std::vector<std::unique_ptr<MetaItemInner>>
AttributeParser::parse_meta_item_seq ()
{
- int vec_length = token_stream.size ();
std::vector<std::unique_ptr<MetaItemInner>> meta_items;
- if (peek_token ()->get_id () != LEFT_PAREN)
+ if (lexer->peek_token ()->get_id () != LEFT_PAREN)
{
- rust_error_at (peek_token ()->get_locus (),
+ rust_error_at (lexer->peek_token ()->get_locus (),
"missing left paren in delim token tree");
return {};
}
- skip_token ();
+ lexer->skip_token ();
- while (stream_pos < vec_length && peek_token ()->get_id () != RIGHT_PAREN)
+ while (lexer->peek_token ()->get_id () != END_OF_FILE
+ && lexer->peek_token ()->get_id () != RIGHT_PAREN)
{
std::unique_ptr<MetaItemInner> inner = parse_meta_item_inner ();
if (inner == nullptr)
{
- rust_error_at (peek_token ()->get_locus (),
+ rust_error_at (lexer->peek_token ()->get_locus (),
"failed to parse inner meta item in attribute");
return {};
}
meta_items.push_back (std::move (inner));
- if (peek_token ()->get_id () != COMMA)
+ if (lexer->peek_token ()->get_id () != COMMA)
break;
- skip_token ();
+ lexer->skip_token ();
}
- if (peek_token ()->get_id () != RIGHT_PAREN)
+ if (lexer->peek_token ()->get_id () != RIGHT_PAREN)
{
- rust_error_at (peek_token ()->get_locus (),
+ rust_error_at (lexer->peek_token ()->get_locus (),
"missing right paren in delim token tree");
return {};
}
- skip_token ();
+ lexer->skip_token ();
return meta_items;
}
@@ -3752,130 +3797,19 @@ DelimTokenTree::to_token_stream () const
return tokens;
}
-Literal
-AttributeParser::parse_literal ()
-{
- const std::unique_ptr<Token> &tok = peek_token ();
- switch (tok->get_id ())
- {
- case CHAR_LITERAL:
- skip_token ();
- return Literal (tok->as_string (), Literal::CHAR, tok->get_type_hint ());
- case STRING_LITERAL:
- skip_token ();
- return Literal (tok->as_string (), Literal::STRING,
- tok->get_type_hint ());
- case BYTE_CHAR_LITERAL:
- skip_token ();
- return Literal (tok->as_string (), Literal::BYTE, tok->get_type_hint ());
- case BYTE_STRING_LITERAL:
- skip_token ();
- return Literal (tok->as_string (), Literal::BYTE_STRING,
- tok->get_type_hint ());
- case RAW_STRING_LITERAL:
- skip_token ();
- return Literal (tok->as_string (), Literal::RAW_STRING,
- tok->get_type_hint ());
- case INT_LITERAL:
- skip_token ();
- return Literal (tok->as_string (), Literal::INT, tok->get_type_hint ());
- case FLOAT_LITERAL:
- skip_token ();
- return Literal (tok->as_string (), Literal::FLOAT, tok->get_type_hint ());
- case TRUE_LITERAL:
- skip_token ();
- return Literal ("true", Literal::BOOL, tok->get_type_hint ());
- case FALSE_LITERAL:
- skip_token ();
- return Literal ("false", Literal::BOOL, tok->get_type_hint ());
- default:
- rust_error_at (tok->get_locus (), "expected literal - found '%s'",
- get_token_description (tok->get_id ()));
- return Literal::create_error ();
- }
-}
-
-SimplePath
-AttributeParser::parse_simple_path ()
-{
- bool has_opening_scope_res = false;
- if (peek_token ()->get_id () == SCOPE_RESOLUTION)
- {
- has_opening_scope_res = true;
- skip_token ();
- }
-
- std::vector<SimplePathSegment> segments;
-
- SimplePathSegment segment = parse_simple_path_segment ();
- if (segment.is_error ())
- {
- rust_error_at (
- peek_token ()->get_locus (),
- "failed to parse simple path segment in attribute simple path");
- return SimplePath::create_empty ();
- }
- segments.push_back (std::move (segment));
-
- while (peek_token ()->get_id () == SCOPE_RESOLUTION)
- {
- skip_token ();
-
- SimplePathSegment segment = parse_simple_path_segment ();
- if (segment.is_error ())
- {
- rust_error_at (
- peek_token ()->get_locus (),
- "failed to parse simple path segment in attribute simple path");
- return SimplePath::create_empty ();
- }
- segments.push_back (std::move (segment));
- }
- segments.shrink_to_fit ();
-
- return SimplePath (std::move (segments), has_opening_scope_res);
-}
-
-SimplePathSegment
-AttributeParser::parse_simple_path_segment ()
-{
- const std::unique_ptr<Token> &tok = peek_token ();
- switch (tok->get_id ())
- {
- case IDENTIFIER:
- skip_token ();
- return SimplePathSegment (tok->as_string (), tok->get_locus ());
- case SUPER:
- skip_token ();
- return SimplePathSegment ("super", tok->get_locus ());
- case SELF:
- skip_token ();
- return SimplePathSegment ("self", tok->get_locus ());
- case CRATE:
- skip_token ();
- return SimplePathSegment ("crate", tok->get_locus ());
- case DOLLAR_SIGN:
- if (peek_token (1)->get_id () == CRATE)
- {
- skip_token (1);
- return SimplePathSegment ("$crate", tok->get_locus ());
- }
- gcc_fallthrough ();
- default:
- rust_error_at (tok->get_locus (),
- "unexpected token '%s' in simple path segment",
- get_token_description (tok->get_id ()));
- return SimplePathSegment::create_error ();
- }
-}
-
std::unique_ptr<MetaItemLitExpr>
AttributeParser::parse_meta_item_lit ()
{
- location_t locus = peek_token ()->get_locus ();
- LiteralExpr lit_expr (parse_literal (), {}, locus);
+ std::unique_ptr<LiteralExpr> lit_expr = parser->parse_literal_expr ({});
+
+ // TODO: return nullptr instead?
+ if (!lit_expr)
+ lit_expr = std::unique_ptr<LiteralExpr> (
+ new LiteralExpr (Literal::create_error (), {},
+ lexer->peek_token ()->get_locus ()));
+
return std::unique_ptr<MetaItemLitExpr> (
- new MetaItemLitExpr (std::move (lit_expr)));
+ new MetaItemLitExpr (std::move (*lit_expr)));
}
bool
@@ -4084,10 +4018,12 @@ MetaNameValueStr::check_cfg_predicate (const Session &session) const
}
bool
-MetaItemPathLit::check_cfg_predicate (const Session &session) const
+MetaItemPathExpr::check_cfg_predicate (const Session &session) const
{
+ // FIXME: Accept path expressions
+ rust_assert (expr->is_literal ());
return session.options.target_data.has_key_value_pair (path.as_string (),
- lit.as_string ());
+ expr->as_string ());
}
std::vector<std::unique_ptr<Token>>
@@ -4175,8 +4111,10 @@ MetaListNameValueStr::to_attribute () const
}
Attribute
-MetaItemPathLit::to_attribute () const
+MetaItemPathExpr::to_attribute () const
{
+ rust_assert (expr->is_literal ());
+ auto &lit = static_cast<LiteralExpr &> (*expr);
return Attribute (path, std::unique_ptr<AttrInputLiteral> (
new AttrInputLiteral (lit)));
}
@@ -4279,11 +4217,12 @@ AttrInputMacro::AttrInputMacro (const AttrInputMacro &oth)
: macro (oth.macro->clone_macro_invocation_impl ())
{}
-void
+AttrInputMacro &
AttrInputMacro::operator= (const AttrInputMacro &oth)
{
macro = std::unique_ptr<MacroInvocation> (
oth.macro->clone_macro_invocation_impl ());
+ return *this;
}
/* Visitor implementations - these are short but inlining can't happen anyway
@@ -4345,7 +4284,7 @@ MetaItemLitExpr::accept_vis (ASTVisitor &vis)
}
void
-MetaItemPathLit::accept_vis (ASTVisitor &vis)
+MetaItemPathExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
}
@@ -4513,6 +4452,18 @@ BlockExpr::accept_vis (ASTVisitor &vis)
}
void
+AnonConst::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
+ConstBlock::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
ClosureExprInnerTyped::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
@@ -4573,6 +4524,12 @@ ReturnExpr::accept_vis (ASTVisitor &vis)
}
void
+TryExpr::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
UnsafeBlockExpr::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
@@ -5010,6 +4967,12 @@ FormatArgs::accept_vis (ASTVisitor &vis)
vis.visit (*this);
}
+void
+OffsetOf::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
std::string
FormatArgs::as_string () const
{
@@ -5017,6 +4980,12 @@ FormatArgs::as_string () const
return "FormatArgs";
}
+std::string
+OffsetOf::as_string () const
+{
+ return "OffsetOf(" + type->as_string () + ", " + field.as_string () + ")";
+}
+
location_t
FormatArgs::get_locus () const
{
@@ -5047,7 +5016,8 @@ FormatArgs::get_outer_attrs ()
rust_unreachable ();
}
-void FormatArgs::set_outer_attrs (std::vector<Attribute>)
+void
+FormatArgs::set_outer_attrs (std::vector<Attribute>)
{
rust_unreachable ();
}
@@ -5060,6 +5030,24 @@ FormatArgs::clone_expr_impl () const
return new FormatArgs (*this);
}
+std::vector<Attribute> &
+OffsetOf::get_outer_attrs ()
+{
+ rust_unreachable ();
+}
+
+void
+OffsetOf::set_outer_attrs (std::vector<Attribute>)
+{
+ rust_unreachable ();
+}
+
+Expr *
+OffsetOf::clone_expr_impl () const
+{
+ return new OffsetOf (*this);
+}
+
} // namespace AST
std::ostream &
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index aa6ad50..2d2c5d0 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -62,13 +62,14 @@ public:
return ident == other.ident;
}
+ operator const std::string & () const { return ident; }
+
private:
std::string ident;
location_t loc;
};
-std::ostream &
-operator<< (std::ostream &os, Identifier const &i);
+std::ostream &operator<< (std::ostream &os, Identifier const &i);
namespace AST {
// foward decl: ast visitor
@@ -82,6 +83,38 @@ public:
virtual void accept_vis (ASTVisitor &vis) = 0;
};
+/**
+ * Base function for reconstructing and asserting that the new NodeId is
+ * different from the old NodeId. It then wraps the given pointer into a unique
+ * pointer and returns it.
+ */
+template <typename T>
+std::unique_ptr<T>
+reconstruct_base (const T *instance)
+{
+ auto *reconstructed = instance->reconstruct_impl ();
+
+ rust_assert (reconstructed->get_node_id () != instance->get_node_id ());
+
+ return std::unique_ptr<T> (reconstructed);
+}
+
+/**
+ * Reconstruct multiple items in a vector
+ */
+template <typename T>
+std::vector<std::unique_ptr<T>>
+reconstruct_vec (const std::vector<std::unique_ptr<T>> &to_reconstruct)
+{
+ std::vector<std::unique_ptr<T>> reconstructed;
+ reconstructed.reserve (to_reconstruct.size ());
+
+ for (const auto &elt : to_reconstruct)
+ reconstructed.emplace_back (std::unique_ptr<T> (elt->reconstruct_impl ()));
+
+ return reconstructed;
+}
+
// Delimiter types - used in macros and whatever.
enum DelimType
{
@@ -250,6 +283,7 @@ public:
std::vector<std::unique_ptr<Token>> to_token_stream () const override;
TokenId get_id () const { return tok_ref->get_id (); }
+ bool has_str () const { return tok_ref->has_str (); }
const std::string &get_str () const { return tok_ref->get_str (); }
location_t get_locus () const { return tok_ref->get_locus (); }
@@ -403,15 +437,15 @@ class SimplePath
public:
// Constructor
- SimplePath (std::vector<SimplePathSegment> path_segments,
- bool has_opening_scope_resolution = false,
- location_t locus = UNDEF_LOCATION)
+ explicit SimplePath (std::vector<SimplePathSegment> path_segments,
+ bool has_opening_scope_resolution = false,
+ location_t locus = UNDEF_LOCATION)
: opening_scope_resolution (has_opening_scope_resolution),
segments (std::move (path_segments)), locus (locus),
node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
- SimplePath (Identifier ident)
+ explicit SimplePath (Identifier ident)
: opening_scope_resolution (false),
segments ({SimplePathSegment (ident.as_string (), ident.get_locus ())}),
locus (ident.get_locus ()),
@@ -1039,7 +1073,7 @@ public:
Path,
Word,
NameValueStr,
- PathLit,
+ PathExpr,
Seq,
ListPaths,
ListNameValueStr,
@@ -1057,7 +1091,7 @@ public:
class MetaItemLitExpr;
// Forward decl - defined in rust-expr.h
-class MetaItemPathLit;
+class MetaItemPathExpr;
// Forward decl - defined in rust-macro.h
class MetaItemPath;
@@ -1256,6 +1290,8 @@ public:
FieldAccess,
Closure,
Block,
+ ConstExpr,
+ ConstBlock,
Continue,
Break,
Range,
@@ -1272,6 +1308,7 @@ public:
LlvmInlineAsm,
Identifier,
FormatArgs,
+ OffsetOf,
MacroInvocation,
Borrow,
Dereference,
@@ -1283,6 +1320,7 @@ public:
TypeCast,
Assignment,
CompoundAssignment,
+ Try,
};
virtual Kind get_expr_kind () const = 0;
@@ -1477,6 +1515,10 @@ public:
return std::unique_ptr<Type> (clone_type_impl ());
}
+ // Similar to `clone_type`, but generates a new instance of the node with a
+ // different NodeId
+ std::unique_ptr<Type> reconstruct () const { return reconstruct_base (this); }
+
// virtual destructor
virtual ~Type () {}
@@ -1495,11 +1537,13 @@ public:
virtual location_t get_locus () const = 0;
NodeId get_node_id () const { return node_id; }
+ virtual Type *reconstruct_impl () const = 0;
protected:
Type () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}
+ Type (NodeId node_id) : node_id (node_id) {}
- // Clone function implementation as pure virtual method
+ // Clone and reconstruct function implementations as pure virtual methods
virtual Type *clone_type_impl () const = 0;
NodeId node_id;
@@ -1515,6 +1559,13 @@ public:
return std::unique_ptr<TypeNoBounds> (clone_type_no_bounds_impl ());
}
+ std::unique_ptr<TypeNoBounds> reconstruct () const
+ {
+ return reconstruct_base (this);
+ }
+
+ virtual TypeNoBounds *reconstruct_impl () const override = 0;
+
protected:
// Clone function implementation as pure virtual method
virtual TypeNoBounds *clone_type_no_bounds_impl () const = 0;
@@ -1549,6 +1600,11 @@ public:
return std::unique_ptr<TypeParamBound> (clone_type_param_bound_impl ());
}
+ std::unique_ptr<TypeParamBound> reconstruct () const
+ {
+ return reconstruct_base (this);
+ }
+
virtual std::string as_string () const = 0;
NodeId get_node_id () const { return node_id; }
@@ -1557,10 +1613,14 @@ public:
virtual TypeParamBoundType get_bound_type () const = 0;
+ virtual TypeParamBound *reconstruct_impl () const = 0;
+
protected:
// Clone function implementation as pure virtual method
virtual TypeParamBound *clone_type_param_bound_impl () const = 0;
+ TypeParamBound () : node_id (Analysis::Mappings::get ().get_next_node_id ())
+ {}
TypeParamBound (NodeId node_id) : node_id (node_id) {}
NodeId node_id;
@@ -1622,6 +1682,10 @@ protected:
{
return new Lifetime (node_id, lifetime_type, lifetime_name, locus);
}
+ Lifetime *reconstruct_impl () const override
+ {
+ return new Lifetime (lifetime_type, lifetime_name, locus);
+ }
};
/* Base generic parameter in AST. Abstract - can be represented by a Lifetime
diff --git a/gcc/rust/ast/rust-builtin-ast-nodes.h b/gcc/rust/ast/rust-builtin-ast-nodes.h
index 3684092..2893e7b 100644
--- a/gcc/rust/ast/rust-builtin-ast-nodes.h
+++ b/gcc/rust/ast/rust-builtin-ast-nodes.h
@@ -225,6 +225,59 @@ protected:
virtual Expr *clone_expr_impl () const override;
};
+/**
+ * The node associated with the builtin offset_of!() macro
+ */
+class OffsetOf : public Expr
+{
+public:
+ OffsetOf (std::unique_ptr<Type> &&type, Identifier field, location_t loc)
+ : type (std::move (type)), field (field), loc (loc)
+ {}
+
+ OffsetOf (const OffsetOf &other)
+ : type (other.type->clone_type ()), field (other.field), loc (other.loc),
+ marked_for_strip (other.marked_for_strip)
+ {}
+
+ OffsetOf &operator= (const OffsetOf &other)
+ {
+ type = other.type->clone_type ();
+ field = other.field;
+ loc = other.loc;
+ marked_for_strip = other.marked_for_strip;
+
+ return *this;
+ }
+
+ void accept_vis (AST::ASTVisitor &vis) override;
+
+ virtual location_t get_locus () const override { return loc; }
+ const Type &get_type () const { return *type; }
+ Type &get_type () { return *type; }
+ const Identifier &get_field () const { return field; }
+
+ bool is_expr_without_block () const override { return false; }
+
+ void mark_for_strip () override { marked_for_strip = true; }
+ bool is_marked_for_strip () const override { return marked_for_strip; }
+
+ std::string as_string () const override;
+
+ std::vector<Attribute> &get_outer_attrs () override;
+ void set_outer_attrs (std::vector<Attribute>) override;
+ Expr *clone_expr_impl () const override;
+
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::OffsetOf; }
+
+private:
+ std::unique_ptr<Type> type;
+ Identifier field;
+
+ location_t loc;
+ bool marked_for_strip = false;
+};
+
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/ast/rust-collect-lang-items.cc b/gcc/rust/ast/rust-collect-lang-items.cc
index cd6be7f..306c6f7 100644
--- a/gcc/rust/ast/rust-collect-lang-items.cc
+++ b/gcc/rust/ast/rust-collect-lang-items.cc
@@ -109,5 +109,29 @@ CollectLangItems::visit (AST::EnumItem &item)
DefaultASTVisitor::visit (item);
}
+void
+CollectLangItems::visit (AST::EnumItemTuple &item)
+{
+ maybe_add_lang_item (item);
+
+ DefaultASTVisitor::visit (item);
+}
+
+void
+CollectLangItems::visit (AST::EnumItemStruct &item)
+{
+ maybe_add_lang_item (item);
+
+ DefaultASTVisitor::visit (item);
+}
+
+void
+CollectLangItems::visit (AST::EnumItemDiscriminant &item)
+{
+ maybe_add_lang_item (item);
+
+ DefaultASTVisitor::visit (item);
+}
+
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/ast/rust-collect-lang-items.h b/gcc/rust/ast/rust-collect-lang-items.h
index ddb34a9..ddc7b51 100644
--- a/gcc/rust/ast/rust-collect-lang-items.h
+++ b/gcc/rust/ast/rust-collect-lang-items.h
@@ -50,6 +50,9 @@ public:
void visit (AST::Function &item) override;
void visit (AST::StructStruct &item) override;
void visit (AST::EnumItem &item) override;
+ void visit (AST::EnumItemTuple &item) override;
+ void visit (AST::EnumItemStruct &item) override;
+ void visit (AST::EnumItemDiscriminant &item) override;
private:
template <typename T> void maybe_add_lang_item (const T &item);
diff --git a/gcc/rust/ast/rust-cond-compilation.h b/gcc/rust/ast/rust-cond-compilation.h
index 610b904..56a5646 100644
--- a/gcc/rust/ast/rust-cond-compilation.h
+++ b/gcc/rust/ast/rust-cond-compilation.h
@@ -42,8 +42,8 @@ public:
protected:
// Clone function impl to be overriden in base classes
- virtual ConfigurationPredicate *
- clone_configuration_predicate_impl () const = 0;
+ virtual ConfigurationPredicate *clone_configuration_predicate_impl () const
+ = 0;
};
// A configuration option - true if option is set, false if option is not set.
diff --git a/gcc/rust/ast/rust-desugar-apit.cc b/gcc/rust/ast/rust-desugar-apit.cc
new file mode 100644
index 0000000..bca14ee
--- /dev/null
+++ b/gcc/rust/ast/rust-desugar-apit.cc
@@ -0,0 +1,522 @@
+// 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-desugar-apit.h"
+#include "rust-ast.h"
+#include "rust-type.h"
+
+namespace Rust {
+namespace AST {
+
+class DesugarApitType : public DefaultASTVisitor
+{
+ using DefaultASTVisitor::visit;
+
+public:
+ static std::pair<AST::Type *, std::vector<std::unique_ptr<GenericParam>>>
+ Desugar (AST::Type &type)
+ {
+ DesugarApitType visitor (&type);
+ type.accept_vis (visitor);
+ rust_assert (visitor.translated != nullptr);
+ return std::make_pair (visitor.translated,
+ std::move (visitor.implicit_generic_params));
+ }
+
+ // Generate a unique impl trait parameter name
+ static Identifier get_impl_name ()
+ {
+ static size_t counter = 0;
+ return Identifier ("Impl_" + std::to_string (counter++));
+ }
+
+ // these can hold other types
+ void visit (AST::TupleType &tuple) override
+ {
+ for (auto &elem : tuple.get_elems ())
+ {
+ auto &type = *elem.get ();
+ auto desugar = Desugar (type);
+ auto tt = desugar.first;
+
+ auto &implicit_generics = desugar.second;
+ if (implicit_generics.empty ())
+ continue;
+
+ if (tt != elem.get ())
+ elem = std::unique_ptr<Type> (tt);
+
+ for (auto &implicit_generic : implicit_generics)
+ implicit_generic_params.push_back (std::move (implicit_generic));
+ }
+ }
+
+ void visit (AST::ArrayType &type) override
+ {
+ auto &element_type = type.get_element_type ();
+ auto desugar = Desugar (*element_type);
+ auto tt = desugar.first;
+
+ auto &implicit_generics = desugar.second;
+ if (implicit_generics.empty ())
+ return;
+
+ if (tt != element_type.get ())
+ element_type = std::unique_ptr<AST::Type> (tt);
+
+ for (auto &implicit_generic : implicit_generics)
+ implicit_generic_params.push_back (std::move (implicit_generic));
+ }
+
+ void visit (AST::ReferenceType &type) override
+ {
+ // Get a reference to the current type for in-place modification
+ auto &referenced_type = type.get_type_referenced ();
+ auto desugar = Desugar (referenced_type);
+ auto tt = desugar.first;
+
+ auto &implicit_generics = desugar.second;
+ if (implicit_generics.empty ())
+ return;
+
+ // Update the reference type's contents rather than creating a new one
+ if (&referenced_type != tt)
+ {
+ std::unique_ptr<AST::TypeNoBounds> new_type_no_bounds (
+ static_cast<AST::TypeNoBounds *> (tt));
+ type.get_type_ptr () = std::move (new_type_no_bounds);
+ }
+
+ // Collect all the implicit generic parameters we found
+ for (auto &implicit_generic : implicit_generics)
+ implicit_generic_params.push_back (std::move (implicit_generic));
+ }
+
+ void visit (AST::RawPointerType &type) override
+ {
+ auto &pointed_type = type.get_type_pointed_to ();
+ auto desugar = Desugar (pointed_type);
+ auto tt = desugar.first;
+
+ auto &implicit_generics = desugar.second;
+ if (implicit_generics.empty ())
+ return;
+
+ // Update the pointer's inner type directly using the new accessor
+ if (&pointed_type != tt)
+ {
+ std::unique_ptr<AST::TypeNoBounds> new_type_no_bounds (
+ static_cast<AST::TypeNoBounds *> (tt));
+ type.get_type_ptr () = std::move (new_type_no_bounds);
+ }
+
+ // Collect all the implicit generic parameters we found
+ for (auto &implicit_generic : implicit_generics)
+ implicit_generic_params.push_back (std::move (implicit_generic));
+ }
+
+ void visit (AST::SliceType &type) override
+ {
+ auto &element_type = type.get_elem_type ();
+ auto desugar = Desugar (element_type);
+ auto tt = desugar.first;
+
+ auto &implicit_generics = desugar.second;
+ if (implicit_generics.empty ())
+ return;
+
+ if (&element_type != tt)
+ {
+ std::unique_ptr<AST::Type> new_elem_type (tt);
+ type.get_elem_type_ptr () = std::move (new_elem_type);
+ }
+
+ // Collect all the implicit generic parameters we found
+ for (auto &implicit_generic : implicit_generics)
+ implicit_generic_params.push_back (std::move (implicit_generic));
+ }
+
+ void visit (AST::ParenthesisedType &type) override
+ {
+ auto &inner_type_ptr = type.get_type_in_parens ();
+ auto desugar = Desugar (*inner_type_ptr);
+ auto tt = desugar.first;
+
+ auto &implicit_generics = desugar.second;
+ if (implicit_generics.empty ())
+ return;
+
+ if (inner_type_ptr.get () != tt)
+ {
+ std::unique_ptr<AST::Type> new_inner_type (tt);
+ inner_type_ptr = std::move (new_inner_type);
+ }
+
+ // Collect all the implicit generic parameters we found
+ for (auto &implicit_generic : implicit_generics)
+ implicit_generic_params.push_back (std::move (implicit_generic));
+ }
+
+ // this is where the desugar happens
+ void visit (AST::ImplTraitType &type) override
+ {
+ // Generate a unique name using the static method
+ auto ident = get_impl_name ();
+
+ // Create a type path for the new generic parameter
+ // Create a SimplePathSegment with the identifier string
+ auto simple_seg = SimplePathSegment (ident.as_string (), type.get_locus ());
+ // Create a vector of SimplePathSegments for SimplePath constructor
+ std::vector<SimplePathSegment> simple_segs = {simple_seg};
+ // Create a SimplePath
+ auto simple_path = SimplePath (simple_segs, false, type.get_locus ());
+
+ // Convert to TypePath by creating path segments
+ std::vector<std::unique_ptr<TypePathSegment>> segments;
+ segments.push_back (std::unique_ptr<TypePathSegment> (new TypePathSegment (
+ PathIdentSegment (ident.as_string (), type.get_locus ()), false,
+ type.get_locus ())));
+
+ // Create TypePath from segments
+ auto type_path
+ = new TypePath (std::move (segments), type.get_locus (), false);
+
+ // Convert bounds from impl trait to generic parameter bounds
+ std::vector<std::unique_ptr<TypeParamBound>> bounds;
+ for (auto &bound : type.get_type_param_bounds ())
+ bounds.push_back (bound->clone_type_param_bound ());
+
+ // Create the new generic parameter
+ auto generic_param = std::unique_ptr<TypeParam> (
+ new TypeParam (ident, type.get_locus (), std::move (bounds), nullptr, {},
+ true /*from impl trait*/));
+
+ // Store the generic parameter to be added to the function signature
+ implicit_generic_params.push_back (std::move (generic_param));
+
+ // Replace impl trait with the new type parameter
+ translated = type_path;
+ }
+
+ void visit (AST::ImplTraitTypeOneBound &type) override
+ {
+ // Generate a unique name using the static method
+ auto ident = get_impl_name ();
+
+ // Create a type path for the new generic parameter
+ // Create a SimplePathSegment with the identifier string
+ auto simple_seg = SimplePathSegment (ident.as_string (), type.get_locus ());
+ // Create a vector of SimplePathSegments for SimplePath constructor
+ std::vector<SimplePathSegment> simple_segs = {simple_seg};
+ // Create a SimplePath
+ auto simple_path = SimplePath (simple_segs, false, type.get_locus ());
+
+ // Convert to TypePath by creating path segments
+ std::vector<std::unique_ptr<TypePathSegment>> segments;
+ segments.push_back (std::unique_ptr<TypePathSegment> (new TypePathSegment (
+ PathIdentSegment (ident.as_string (), type.get_locus ()), false,
+ type.get_locus ())));
+
+ // Create TypePath from segments
+ auto type_path
+ = new TypePath (std::move (segments), type.get_locus (), false);
+
+ // Convert the bound to a generic parameter bound
+ std::vector<std::unique_ptr<TypeParamBound>> bounds;
+ bounds.push_back (std::move (type.get_trait_bound ()));
+
+ // Create the new generic parameter
+ auto generic_param = std::unique_ptr<TypeParam> (
+ new TypeParam (ident, type.get_locus (), std::move (bounds), nullptr, {},
+ true /*from impl trait*/));
+
+ // Store the generic parameter to be added to the function signature
+ implicit_generic_params.push_back (std::move (generic_param));
+
+ // Replace impl trait with the new type parameter
+ translated = type_path;
+ }
+
+private:
+ DesugarApitType (AST::Type *base)
+ : translated (base), implicit_generic_params ()
+ {}
+
+ AST::Type *translated;
+ std::vector<std::unique_ptr<GenericParam>> implicit_generic_params;
+};
+
+// ---------
+
+class ApitBoundProcessor
+{
+public:
+ ApitBoundProcessor (
+ WhereClause &where_clause,
+ std::vector<std::unique_ptr<GenericParam>> &generic_params)
+ : where_clause (where_clause), generic_params (generic_params)
+ {}
+
+ void go (std::vector<std::unique_ptr<GenericParam>> &implicit_generics)
+ {
+ // some desugars are more complex so imagine this case
+ //
+ // pub fn foo(_value: impl Bar<Baz = impl Foo>) -> i32 {
+ // 15
+ // }
+ //
+ // this needs to become:
+ //
+ // pub fn foo<T, U>(_value: T) -> i32
+ // where
+ // T: Bar<Baz = U>,
+ // U: Foo,
+ // {
+ // 15
+ // }
+ //
+ // so we need to walk all the implicit generics and the trait bounds paths
+ // for more generics
+
+ for (auto &implicit_generic : implicit_generics)
+ {
+ switch (implicit_generic->get_kind ())
+ {
+ case GenericParam::Kind::Type:
+ {
+ TypeParam &p
+ = *static_cast<TypeParam *> (implicit_generic.get ());
+
+ process_type_param (p);
+ generic_params.push_back (std::move (implicit_generic));
+ for (auto &synth : synthetic_params)
+ generic_params.push_back (std::move (synth));
+ synthetic_params.clear ();
+ }
+ break;
+
+ default:
+ generic_params.push_back (std::move (implicit_generic));
+ break;
+ }
+ }
+ }
+
+private:
+ void process_type_param (TypeParam &p)
+ {
+ auto &bounds = p.get_type_param_bounds ();
+ std::vector<size_t> bounds_to_remove;
+ for (size_t i = 0; i < bounds.size (); i++)
+ {
+ auto &tb = bounds[i];
+ switch (tb->get_bound_type ())
+ {
+ case TypeParamBound::TypeParamBoundType::TRAIT:
+ {
+ TraitBound &ttb = *static_cast<TraitBound *> (tb.get ());
+ TypePath &path = ttb.get_type_path ();
+ bool deusgared = process_type_path (p, ttb, path);
+ if (deusgared)
+ bounds_to_remove.push_back (i);
+ }
+
+ default:
+ break;
+ }
+ }
+ for (auto it = bounds_to_remove.rbegin (); it != bounds_to_remove.rend ();
+ ++it)
+ bounds.erase (bounds.begin () + *it);
+ }
+
+ bool process_type_path (TypeParam &p, TraitBound &parent, TypePath &path)
+ {
+ bool desugared = false;
+ for (auto &segment : path.get_segments ())
+ {
+ switch (segment->get_type ())
+ {
+ case TypePathSegment::SegmentType::GENERIC:
+ {
+ TypePathSegmentGeneric &seg
+ = *static_cast<TypePathSegmentGeneric *> (segment.get ());
+ desugared |= process_generic_segment (p, parent, path, seg);
+ }
+
+ default:
+ break;
+ }
+ }
+ return desugared;
+ }
+
+ bool process_generic_segment (TypeParam &p, TraitBound &parent,
+ TypePath &path, TypePathSegmentGeneric &seg)
+ {
+ // we need to look for any impl types as default arguments in any generics
+ // and remove this index from the generic arguments by using a where
+ // constraint instead
+
+ std::vector<std::unique_ptr<WhereClauseItem>> new_clauses;
+ GenericArgs &generic_args = seg.get_generic_args ();
+ std::vector<std::reference_wrapper<const GenericArgsBinding>>
+ bindings_desugared;
+ std::vector<GenericArgsBinding> &bindings
+ = generic_args.get_binding_args ();
+
+ for (auto &generic : bindings)
+ {
+ auto &t = generic.get_type ();
+ auto translated = DesugarApitType::Desugar (t);
+ auto tt = translated.first;
+
+ auto &implicit_generics = translated.second;
+ if (implicit_generics.empty ())
+ continue;
+
+ if (tt != &t)
+ {
+ bindings_desugared.push_back (generic);
+ generic.get_type_ptr () = std::unique_ptr<Type> (tt);
+ }
+
+ for (auto &implicit_generic : implicit_generics)
+ {
+ switch (implicit_generic->get_kind ())
+ {
+ case GenericParam::Kind::Type:
+ {
+ TypeParam &tp
+ = *static_cast<TypeParam *> (implicit_generic.get ());
+
+ std::vector<std::unique_ptr<TypeParamBound>>
+ type_param_bounds;
+ for (auto &b : tp.get_type_param_bounds ())
+ type_param_bounds.push_back (std::move (b));
+ tp.get_type_param_bounds ().clear ();
+
+ // add synthetic parameter for this
+ synthetic_params.push_back (std::move (implicit_generic));
+
+ auto bound_type_path
+ = get_type_for_identifier (tp.get_type_representation ());
+
+ auto clause = new TypeBoundWhereClauseItem (
+ {}, std::move (bound_type_path),
+ std::move (type_param_bounds), tp.get_locus ());
+ std::unique_ptr<WhereClauseItem> clause_item
+ = std::unique_ptr<WhereClauseItem> (clause);
+ new_clauses.push_back (std::move (clause_item));
+ }
+ break;
+
+ default:
+ synthetic_params.push_back (std::move (implicit_generic));
+ break;
+ }
+ }
+ }
+
+ std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds;
+ auto bound = std::unique_ptr<TypeParamBound> (new TraitBound (parent));
+ type_param_bounds.push_back (std::move (bound));
+ auto parent_type_path
+ = get_type_for_identifier (p.get_type_representation ());
+ auto clause
+ = new TypeBoundWhereClauseItem ({}, std::move (parent_type_path),
+ std::move (type_param_bounds),
+ parent.get_locus ());
+ std::unique_ptr<WhereClauseItem> clause_item
+ = std::unique_ptr<WhereClauseItem> (clause);
+ where_clause.get_items ().push_back (std::move (clause_item));
+
+ for (auto &where_item : new_clauses)
+ where_clause.get_items ().push_back (std::move (where_item));
+
+ return !bindings_desugared.empty ();
+ }
+
+ static std::unique_ptr<Type> get_type_for_identifier (const Identifier &ident)
+ {
+ auto simple_seg
+ = SimplePathSegment (ident.as_string (), ident.get_locus ());
+ std::vector<SimplePathSegment> simple_segs = {simple_seg};
+ auto simple_path = SimplePath (simple_segs, false, ident.get_locus ());
+ std::vector<std::unique_ptr<TypePathSegment>> segments;
+ segments.push_back (std::unique_ptr<TypePathSegment> (new TypePathSegment (
+ PathIdentSegment (ident.as_string (), ident.get_locus ()), false,
+ ident.get_locus ())));
+ auto type_path = new TypePath (std::move (segments), ident.get_locus ());
+ return std::unique_ptr<Type> (type_path);
+ }
+
+private:
+ WhereClause &where_clause;
+ std::vector<std::unique_ptr<GenericParam>> &generic_params;
+
+ // mutates
+ std::vector<std::unique_ptr<GenericParam>> synthetic_params;
+};
+
+// ---------
+
+DesugarApit::DesugarApit () {}
+
+void
+DesugarApit::go (AST::Crate &crate)
+{
+ DefaultASTVisitor::visit (crate);
+}
+
+void
+DesugarApit::visit (AST::Function &function)
+{
+ if (!function.has_function_params ())
+ return;
+
+ auto &fn_params = function.get_function_params ();
+ for (auto &param : fn_params)
+ {
+ if (param->is_variadic () || param->is_self ())
+ continue;
+
+ auto *p = param.get ();
+ auto &fp = *static_cast<AST::FunctionParam *> (p);
+ auto &type = fp.get_type ();
+
+ auto translated = DesugarApitType::Desugar (type);
+ auto tt = translated.first;
+
+ auto &implicit_generics = translated.second;
+ if (implicit_generics.empty ())
+ continue;
+
+ if (fp.get_type_ptr ().get () != tt)
+ {
+ fp.get_type_ptr () = std::unique_ptr<AST::Type> (tt);
+ }
+
+ ApitBoundProcessor processor (function.get_where_clause (),
+ function.get_generic_params ());
+ processor.go (implicit_generics);
+ }
+}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/ast/rust-desugar-apit.h b/gcc/rust/ast/rust-desugar-apit.h
new file mode 100644
index 0000000..07c25e2
--- /dev/null
+++ b/gcc/rust/ast/rust-desugar-apit.h
@@ -0,0 +1,42 @@
+// 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_DESUGAR_APIT_H
+#define RUST_DESUGAR_APIT_H
+
+#include "rust-ast-visitor.h"
+
+namespace Rust {
+namespace AST {
+
+class DesugarApit : public DefaultASTVisitor
+{
+ using DefaultASTVisitor::visit;
+
+public:
+ DesugarApit ();
+ void go (AST::Crate &);
+
+private:
+ void visit (AST::Function &) override;
+};
+
+} // namespace AST
+} // namespace Rust
+
+#endif // ! RUST_DESUGAR_APIT_H
diff --git a/gcc/rust/ast/rust-desugar-for-loops.cc b/gcc/rust/ast/rust-desugar-for-loops.cc
index ffc3470..5cc1c19 100644
--- a/gcc/rust/ast/rust-desugar-for-loops.cc
+++ b/gcc/rust/ast/rust-desugar-for-loops.cc
@@ -17,7 +17,6 @@
// <http://www.gnu.org/licenses/>.
#include "rust-desugar-for-loops.h"
-#include "rust-ast-visitor.h"
#include "rust-ast.h"
#include "rust-hir-map.h"
#include "rust-path.h"
@@ -31,32 +30,10 @@ namespace AST {
DesugarForLoops::DesugarForLoops () {}
-void
-DesugarForLoops::go (AST::Crate &crate)
-{
- DefaultASTVisitor::visit (crate);
-}
-
-static void
-replace_for_loop (std::unique_ptr<Expr> &for_loop,
- std::unique_ptr<Expr> &&expanded)
-{
- for_loop = std::move (expanded);
-}
-
-MatchArm
-DesugarForLoops::DesugarCtx::make_match_arm (std::unique_ptr<Pattern> &&path)
-{
- auto patterns = std::vector<std::unique_ptr<Pattern>> ();
- patterns.emplace_back (std::move (path));
-
- return MatchArm (std::move (patterns), loc);
-}
-
MatchCase
DesugarForLoops::DesugarCtx::make_break_arm ()
{
- auto arm = make_match_arm (std::unique_ptr<Pattern> (new PathInExpression (
+ auto arm = builder.match_arm (std::unique_ptr<Pattern> (new PathInExpression (
builder.path_in_expression (LangItem::Kind::OPTION_NONE))));
auto break_expr
@@ -79,7 +56,7 @@ DesugarForLoops::DesugarCtx::make_continue_arm ()
builder.path_in_expression (LangItem::Kind::OPTION_SOME),
std::move (pattern_item)));
- auto val_arm = make_match_arm (std::move (pattern));
+ auto val_arm = builder.match_arm (std::move (pattern));
auto next = builder.identifier (DesugarCtx::next_value_id);
@@ -91,14 +68,8 @@ DesugarForLoops::DesugarCtx::make_continue_arm ()
return MatchCase (std::move (val_arm), std::move (assignment));
}
-std::unique_ptr<Stmt>
-DesugarForLoops::DesugarCtx::statementify (std::unique_ptr<Expr> &&expr)
-{
- return std::unique_ptr<Stmt> (new ExprStmt (std::move (expr), loc, true));
-}
-
std::unique_ptr<Expr>
-DesugarForLoops::desugar (AST::ForLoopExpr &expr)
+DesugarForLoops::desugar (ForLoopExpr &expr)
{
auto ctx = DesugarCtx (expr.get_locus ());
@@ -140,10 +111,10 @@ DesugarForLoops::desugar (AST::ForLoopExpr &expr)
auto loop_stmts = std::vector<std::unique_ptr<Stmt>> ();
loop_stmts.emplace_back (std::move (let_next));
- loop_stmts.emplace_back (ctx.statementify (std::move (match_next)));
+ loop_stmts.emplace_back (ctx.builder.statementify (std::move (match_next)));
loop_stmts.emplace_back (std::move (let_pat));
loop_stmts.emplace_back (
- ctx.statementify (expr.get_loop_block ().clone_expr ()));
+ ctx.builder.statementify (expr.get_loop_block ().clone_expr ()));
// loop {
// <let_next>;
@@ -170,34 +141,18 @@ DesugarForLoops::desugar (AST::ForLoopExpr &expr)
}
void
-DesugarForLoops::maybe_desugar_expr (std::unique_ptr<Expr> &expr)
+DesugarForLoops::go (std::unique_ptr<Expr> &ptr)
{
- if (expr->get_expr_kind () == AST::Expr::Kind::Loop)
- {
- auto &loop = static_cast<AST::BaseLoopExpr &> (*expr);
+ rust_assert (ptr->get_expr_kind () == Expr::Kind::Loop);
- if (loop.get_loop_kind () == AST::BaseLoopExpr::Kind::For)
- {
- auto &for_loop = static_cast<AST::ForLoopExpr &> (loop);
+ auto &loop = static_cast<BaseLoopExpr &> (*ptr);
- auto desugared = desugar (for_loop);
-
- replace_for_loop (expr, std::move (desugared));
- }
- }
-}
-
-void
-DesugarForLoops::visit (AST::BlockExpr &block)
-{
- for (auto &stmt : block.get_statements ())
- if (stmt->get_stmt_kind () == AST::Stmt::Kind::Expr)
- maybe_desugar_expr (static_cast<AST::ExprStmt &> (*stmt).get_expr_ptr ());
+ rust_assert (loop.get_loop_kind () == BaseLoopExpr::Kind::For);
- if (block.has_tail_expr ())
- maybe_desugar_expr (block.get_tail_expr_ptr ());
+ auto &for_loop = static_cast<ForLoopExpr &> (loop);
+ auto desugared = DesugarForLoops ().desugar (for_loop);
- DefaultASTVisitor::visit (block);
+ ptr = std::move (desugared);
}
} // namespace AST
diff --git a/gcc/rust/ast/rust-desugar-for-loops.h b/gcc/rust/ast/rust-desugar-for-loops.h
index 7beb692..96b63ff 100644
--- a/gcc/rust/ast/rust-desugar-for-loops.h
+++ b/gcc/rust/ast/rust-desugar-for-loops.h
@@ -20,7 +20,6 @@
#define RUST_DESUGAR_FOR_LOOPS_H
#include "rust-ast-builder.h"
-#include "rust-ast-visitor.h"
#include "rust-expr.h"
namespace Rust {
@@ -69,15 +68,14 @@ namespace AST {
// of the way the typechecker is currently structured, where it will fetch name
// resolution information in order to typecheck paths - which technically isn't
// necessary.
-class DesugarForLoops : public DefaultASTVisitor
+class DesugarForLoops
{
- using DefaultASTVisitor::visit;
-
public:
- DesugarForLoops ();
- void go (AST::Crate &);
+ static void go (std::unique_ptr<Expr> &ptr);
private:
+ DesugarForLoops ();
+
struct DesugarCtx
{
DesugarCtx (location_t loc) : builder (Builder (loc)), loc (loc) {}
@@ -85,10 +83,8 @@ private:
Builder builder;
location_t loc;
- MatchArm make_match_arm (std::unique_ptr<Pattern> &&pattern);
MatchCase make_break_arm ();
MatchCase make_continue_arm ();
- std::unique_ptr<Stmt> statementify (std::unique_ptr<Expr> &&expr);
constexpr static const char *continue_pattern_id = "#val";
constexpr static const char *next_value_id = "#__next";
@@ -96,10 +92,7 @@ private:
constexpr static const char *result_id = "#result";
};
- std::unique_ptr<Expr> desugar (AST::ForLoopExpr &expr);
- void maybe_desugar_expr (std::unique_ptr<Expr> &expr);
-
- void visit (AST::BlockExpr &) override;
+ std::unique_ptr<Expr> desugar (ForLoopExpr &expr);
};
} // namespace AST
diff --git a/gcc/rust/ast/rust-desugar-question-mark.cc b/gcc/rust/ast/rust-desugar-question-mark.cc
index 4d2933b..01400d8 100644
--- a/gcc/rust/ast/rust-desugar-question-mark.cc
+++ b/gcc/rust/ast/rust-desugar-question-mark.cc
@@ -18,7 +18,6 @@
#include "rust-desugar-question-mark.h"
#include "rust-ast-builder.h"
-#include "rust-ast-visitor.h"
namespace Rust {
namespace AST {
@@ -26,42 +25,14 @@ namespace AST {
DesugarQuestionMark::DesugarQuestionMark () {}
void
-DesugarQuestionMark::go (AST::Crate &crate)
+DesugarQuestionMark::go (std::unique_ptr<Expr> &ptr)
{
- DesugarQuestionMark::visit (crate);
-}
-
-void
-DesugarQuestionMark::visit (ExprStmt &stmt)
-{
- if (stmt.get_expr ().get_expr_kind () == Expr::Kind::ErrorPropagation)
- desugar_and_replace (stmt.get_expr_ptr ());
-
- DefaultASTVisitor::visit (stmt);
-}
-
-void
-DesugarQuestionMark::visit (CallExpr &call)
-{
- if (call.get_function_expr ().get_expr_kind ()
- == Expr::Kind::ErrorPropagation)
- desugar_and_replace (call.get_function_expr_ptr ());
-
- for (auto &arg : call.get_params ())
- if (arg->get_expr_kind () == Expr::Kind::ErrorPropagation)
- desugar_and_replace (arg);
-
- DefaultASTVisitor::visit (call);
-}
+ rust_assert (ptr->get_expr_kind () == Expr::Kind::ErrorPropagation);
-void
-DesugarQuestionMark::visit (LetStmt &stmt)
-{
- if (stmt.has_init_expr ()
- && stmt.get_init_expr ().get_expr_kind () == Expr::Kind::ErrorPropagation)
- desugar_and_replace (stmt.get_init_expr_ptr ());
+ auto original = static_cast<ErrorPropagationExpr &> (*ptr);
+ auto desugared = DesugarQuestionMark ().desugar (original);
- DefaultASTVisitor::visit (stmt);
+ ptr = std::move (desugared);
}
MatchArm
@@ -99,6 +70,12 @@ ok_case (Builder &builder)
MatchCase
err_case (Builder &builder)
{
+ // TODO: We need to handle the case where there is an enclosing `try {}`
+ // block, as that will create an additional block label that we can break to.
+ // This allows try blocks to use the question mark operator without having the
+ // offending statement early return from the enclosing function
+ // FIXME: How to mark that there is an enclosing block label?
+
auto val = builder.identifier_pattern ("err");
auto patterns = std::vector<std::unique_ptr<Pattern>> ();
@@ -154,14 +131,5 @@ DesugarQuestionMark::desugar (ErrorPropagationExpr &expr)
expr.get_locus ()));
}
-void
-DesugarQuestionMark::desugar_and_replace (std::unique_ptr<Expr> &ptr)
-{
- auto original = static_cast<ErrorPropagationExpr &> (*ptr);
- auto desugared = desugar (original);
-
- ptr = std::move (desugared);
-}
-
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/ast/rust-desugar-question-mark.h b/gcc/rust/ast/rust-desugar-question-mark.h
index e4c513f..542c52b 100644
--- a/gcc/rust/ast/rust-desugar-question-mark.h
+++ b/gcc/rust/ast/rust-desugar-question-mark.h
@@ -19,9 +19,7 @@
#ifndef RUST_DESUGAR_QUESTION_MARK
#define RUST_DESUGAR_QUESTION_MARK
-#include "rust-ast-visitor.h"
#include "rust-expr.h"
-#include "rust-stmt.h"
namespace Rust {
namespace AST {
@@ -56,21 +54,15 @@ namespace AST {
// }
// }
// ```
-class DesugarQuestionMark : public DefaultASTVisitor
+class DesugarQuestionMark
{
- using DefaultASTVisitor::visit;
-
public:
- DesugarQuestionMark ();
- void go (AST::Crate &);
+ static void go (std::unique_ptr<Expr> &ptr);
private:
- void desugar_and_replace (std::unique_ptr<Expr> &ptr);
- std::unique_ptr<Expr> desugar (ErrorPropagationExpr &);
+ DesugarQuestionMark ();
- void visit (AST::ExprStmt &) override;
- void visit (AST::CallExpr &) override;
- void visit (AST::LetStmt &) override;
+ std::unique_ptr<Expr> desugar (ErrorPropagationExpr &);
};
} // namespace AST
diff --git a/gcc/rust/ast/rust-desugar-try-block.cc b/gcc/rust/ast/rust-desugar-try-block.cc
new file mode 100644
index 0000000..07f06aa
--- /dev/null
+++ b/gcc/rust/ast/rust-desugar-try-block.cc
@@ -0,0 +1,62 @@
+// 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-desugar-try-block.h"
+#include "rust-ast-builder.h"
+#include "rust-expr.h"
+
+namespace Rust {
+namespace AST {
+
+DesugarTryBlock::DesugarTryBlock () {}
+
+void
+DesugarTryBlock::go (std::unique_ptr<Expr> &ptr)
+{
+ rust_assert (ptr->get_expr_kind () == Expr::Kind::Try);
+
+ auto original = static_cast<TryExpr &> (*ptr);
+ auto desugared = DesugarTryBlock ().desugar (original);
+
+ ptr = std::move (desugared);
+}
+
+std::unique_ptr<Expr>
+DesugarTryBlock::desugar (TryExpr &expr)
+{
+ auto builder = Builder (expr.get_locus ());
+ auto &block = expr.get_block_expr ();
+
+ if (block.has_statements ())
+ rust_sorry_at (expr.get_locus (),
+ "cannot desugar try-blocks with statements");
+
+ auto tail_expr = builder.tuple ();
+
+ if (block.has_tail_expr ())
+ tail_expr = block.get_tail_expr ().clone_expr ();
+
+ // Wrap in Try::from_ok call
+ auto from_ok = builder.path_in_expression (LangItem::Kind::TRY_FROM_OK);
+ auto call = builder.call (ptrify (from_ok), std::move (tail_expr));
+
+ return builder.block (std::move (call));
+}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/ast/rust-desugar-try-block.h b/gcc/rust/ast/rust-desugar-try-block.h
new file mode 100644
index 0000000..bfd0463
--- /dev/null
+++ b/gcc/rust/ast/rust-desugar-try-block.h
@@ -0,0 +1,42 @@
+// 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_DESUGAR_TRY_BLOCK
+#define RUST_DESUGAR_TRY_BLOCK
+
+#include "rust-expr.h"
+
+namespace Rust {
+namespace AST {
+
+// FIXME: Add documentation
+class DesugarTryBlock
+{
+public:
+ static void go (std::unique_ptr<Expr> &ptr);
+
+private:
+ DesugarTryBlock ();
+
+ std::unique_ptr<Expr> desugar (TryExpr &);
+};
+
+} // namespace AST
+} // namespace Rust
+
+#endif // ! RUST_DESUGAR_TRY_BLOCK
diff --git a/gcc/rust/ast/rust-desugar-while-let.cc b/gcc/rust/ast/rust-desugar-while-let.cc
new file mode 100644
index 0000000..5eadc59
--- /dev/null
+++ b/gcc/rust/ast/rust-desugar-while-let.cc
@@ -0,0 +1,104 @@
+// 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-desugar-while-let.h"
+#include "rust-ast.h"
+#include "rust-hir-map.h"
+#include "rust-path.h"
+#include "rust-pattern.h"
+#include "rust-stmt.h"
+#include "rust-expr.h"
+#include "rust-ast-builder.h"
+
+namespace Rust {
+namespace AST {
+
+DesugarWhileLet::DesugarWhileLet () {}
+
+MatchCase
+DesugarWhileLet::DesugarCtx::make_break_arm ()
+{
+ auto arm = builder.match_arm (builder.wildcard ());
+
+ auto break_expr
+ = std::unique_ptr<Expr> (new BreakExpr (tl::nullopt, nullptr, {}, loc));
+
+ return MatchCase (std::move (arm), std::move (break_expr));
+}
+
+MatchCase
+DesugarWhileLet::DesugarCtx::make_continue_arm (
+ std::unique_ptr<Pattern> &&pattern, std::unique_ptr<BlockExpr> &&body)
+{
+ auto arm = builder.match_arm (std::move (pattern));
+
+ return MatchCase (std::move (arm), std::move (body));
+}
+
+std::unique_ptr<Expr>
+DesugarWhileLet::desugar (WhileLetLoopExpr &expr)
+{
+ rust_assert (expr.get_patterns ().size () == 1);
+
+ auto pattern = expr.get_patterns ()[0]->clone_pattern ();
+ auto body = expr.get_loop_block ().clone_block_expr ();
+ auto scrutinee = expr.get_scrutinee_expr ().clone_expr ();
+
+ auto ctx = DesugarCtx (expr.get_locus ());
+
+ // _ => break,
+ auto break_arm = ctx.make_break_arm ();
+
+ // <pattern> => <body>,
+ auto continue_arm
+ = ctx.make_continue_arm (std::move (pattern), std::move (body));
+
+ // match <scrutinee> {
+ // <continue_arm>
+ // <break_arm>
+ // }
+ auto match_expr
+ = ctx.builder.match (std::move (scrutinee),
+ {std::move (continue_arm), std::move (break_arm)});
+
+ auto loop_stmts = std::vector<std::unique_ptr<Stmt>> ();
+ loop_stmts.emplace_back (ctx.builder.statementify (std::move (match_expr)));
+
+ // loop {
+ // <match_expr>
+ // }
+ return ctx.builder.loop (std::move (loop_stmts));
+}
+
+void
+DesugarWhileLet::go (std::unique_ptr<Expr> &ptr)
+{
+ rust_assert (ptr->get_expr_kind () == Expr::Kind::Loop);
+
+ auto &loop = static_cast<BaseLoopExpr &> (*ptr);
+
+ rust_assert (loop.get_loop_kind () == BaseLoopExpr::Kind::WhileLet);
+
+ auto &while_let = static_cast<WhileLetLoopExpr &> (loop);
+ auto desugared = DesugarWhileLet ().desugar (while_let);
+
+ ptr = std::move (desugared);
+}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/ast/rust-desugar-while-let.h b/gcc/rust/ast/rust-desugar-while-let.h
new file mode 100644
index 0000000..60e0693
--- /dev/null
+++ b/gcc/rust/ast/rust-desugar-while-let.h
@@ -0,0 +1,71 @@
+// 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_DESUGAR_WHILE_LET_H
+#define RUST_DESUGAR_WHILE_LET_H
+
+#include "rust-ast-builder.h"
+#include "rust-expr.h"
+
+namespace Rust {
+namespace AST {
+
+// Desugar while-let into a set of other AST nodes. The desugar is of the
+// following form:
+//
+// ```
+// whilet let <pat> = <expr> <body>
+// ```
+//
+// becomes:
+//
+// ```
+// loop {
+// match <expr> {
+// <pat> => <body>,
+// _ => break
+// }
+// }
+// ```
+class DesugarWhileLet
+{
+public:
+ static void go (std::unique_ptr<Expr> &ptr);
+
+private:
+ DesugarWhileLet ();
+
+ struct DesugarCtx
+ {
+ DesugarCtx (location_t loc) : builder (Builder (loc)), loc (loc) {}
+
+ Builder builder;
+ location_t loc;
+
+ MatchCase make_break_arm ();
+ MatchCase make_continue_arm (std::unique_ptr<Pattern> &&pattern,
+ std::unique_ptr<BlockExpr> &&body);
+ };
+
+ std::unique_ptr<Expr> desugar (WhileLetLoopExpr &expr);
+};
+
+} // namespace AST
+} // namespace Rust
+
+#endif // ! RUST_DESUGAR_WHILE_LET_H
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h
index fdb6360..7b0df25 100644
--- a/gcc/rust/ast/rust-expr.h
+++ b/gcc/rust/ast/rust-expr.h
@@ -1,6 +1,7 @@
#ifndef RUST_AST_EXPR_H
#define RUST_AST_EXPR_H
+#include "optional.h"
#include "rust-ast.h"
#include "rust-common.h"
#include "rust-path.h"
@@ -182,9 +183,13 @@ public:
AttrInputMacro (AttrInputMacro &&oth) : macro (std::move (oth.macro)) {}
- void operator= (const AttrInputMacro &oth);
+ AttrInputMacro &operator= (const AttrInputMacro &oth);
- void operator= (AttrInputMacro &&oth) { macro = std::move (oth.macro); }
+ AttrInputMacro &operator= (AttrInputMacro &&oth)
+ {
+ macro = std::move (oth.macro);
+ return *this;
+ }
std::string as_string () const override;
@@ -244,36 +249,50 @@ protected:
}
};
-// more generic meta item "path = lit" form
-class MetaItemPathLit : public MetaItem
+// more generic meta item "path = expr" form
+class MetaItemPathExpr : public MetaItem
{
SimplePath path;
- LiteralExpr lit;
+ std::unique_ptr<Expr> expr;
public:
- MetaItemPathLit (SimplePath path, LiteralExpr lit_expr)
- : path (std::move (path)), lit (std::move (lit_expr))
+ MetaItemPathExpr (SimplePath path, std::unique_ptr<Expr> expr)
+ : path (std::move (path)), expr (std::move (expr))
{}
+ MetaItemPathExpr (const MetaItemPathExpr &other)
+ : MetaItem (other), path (other.path), expr (other.expr->clone_expr ())
+ {}
+
+ MetaItemPathExpr (MetaItemPathExpr &&) = default;
+
+ MetaItemPathExpr &operator= (MetaItemPathExpr &&) = default;
+
+ MetaItemPathExpr operator= (const MetaItemPathExpr &other)
+ {
+ MetaItem::operator= (other);
+ path = other.path;
+ expr = other.expr->clone_expr ();
+ return *this;
+ }
+
SimplePath get_path () const { return path; }
SimplePath &get_path () { return path; }
- LiteralExpr get_literal () const { return lit; }
-
- LiteralExpr &get_literal () { return lit; }
+ Expr &get_expr () { return *expr; }
std::string as_string () const override
{
- return path.as_string () + " = " + lit.as_string ();
+ return path.as_string () + " = " + expr->as_string ();
}
MetaItem::ItemKind get_item_kind () const override
{
- return MetaItem::ItemKind::PathLit;
+ return MetaItem::ItemKind::PathExpr;
}
- // There are two Locations in MetaItemPathLit (path and lit_expr),
+ // There are two Locations in MetaItemPathExpr (path and expr),
// we have no idea use which of them, just simply return UNKNOWN_LOCATION
// now.
// Maybe we will figure out when we really need the location in the future.
@@ -289,9 +308,9 @@ public:
protected:
// Use covariance to implement clone function as returning this type
- MetaItemPathLit *clone_meta_item_inner_impl () const override
+ MetaItemPathExpr *clone_meta_item_inner_impl () const override
{
- return new MetaItemPathLit (*this);
+ return new MetaItemPathExpr (*this);
}
};
@@ -395,6 +414,8 @@ public:
return *main_or_left_expr;
}
+ bool has_borrow_expr () const { return main_or_left_expr != nullptr; }
+
bool get_is_mut () const { return mutability == Mutability::Mut; }
Mutability get_mutability () const { return mutability; }
@@ -1160,11 +1181,11 @@ protected:
// Value array elements
class ArrayElemsValues : public ArrayElems
{
- std::vector<std::unique_ptr<Expr> > values;
+ std::vector<std::unique_ptr<Expr>> values;
location_t locus;
public:
- ArrayElemsValues (std::vector<std::unique_ptr<Expr> > elems, location_t locus)
+ ArrayElemsValues (std::vector<std::unique_ptr<Expr>> elems, location_t locus)
: ArrayElems (), values (std::move (elems)), locus (locus)
{}
@@ -1192,14 +1213,16 @@ public:
std::string as_string () const override;
+ location_t get_locus () const { return locus; }
+
void accept_vis (ASTVisitor &vis) override;
// TODO: this mutable getter seems really dodgy. Think up better way.
- const std::vector<std::unique_ptr<Expr> > &get_values () const
+ const std::vector<std::unique_ptr<Expr>> &get_values () const
{
return values;
}
- std::vector<std::unique_ptr<Expr> > &get_values () { return values; }
+ std::vector<std::unique_ptr<Expr>> &get_values () { return values; }
size_t get_num_values () const { return values.size (); }
@@ -1214,6 +1237,8 @@ protected:
class ArrayElemsCopied : public ArrayElems
{
std::unique_ptr<Expr> elem_to_copy;
+
+ // TODO: This should be replaced by a ConstExpr
std::unique_ptr<Expr> num_copies;
location_t locus;
@@ -1246,6 +1271,8 @@ public:
std::string as_string () const override;
+ location_t get_locus () const { return locus; }
+
void accept_vis (ASTVisitor &vis) override;
// TODO: is this better? Or is a "vis_block" better?
@@ -1472,7 +1499,7 @@ class TupleExpr : public ExprWithoutBlock
{
std::vector<Attribute> outer_attrs;
std::vector<Attribute> inner_attrs;
- std::vector<std::unique_ptr<Expr> > tuple_elems;
+ std::vector<std::unique_ptr<Expr>> tuple_elems;
location_t locus;
// TODO: find another way to store this to save memory?
@@ -1492,7 +1519,7 @@ public:
outer_attrs = std::move (new_attrs);
}
- TupleExpr (std::vector<std::unique_ptr<Expr> > tuple_elements,
+ TupleExpr (std::vector<std::unique_ptr<Expr>> tuple_elements,
std::vector<Attribute> inner_attribs,
std::vector<Attribute> outer_attribs, location_t locus)
: outer_attrs (std::move (outer_attribs)),
@@ -1543,14 +1570,11 @@ public:
bool is_marked_for_strip () const override { return marked_for_strip; }
// TODO: this mutable getter seems really dodgy. Think up better way.
- const std::vector<std::unique_ptr<Expr> > &get_tuple_elems () const
- {
- return tuple_elems;
- }
- std::vector<std::unique_ptr<Expr> > &get_tuple_elems ()
+ const std::vector<std::unique_ptr<Expr>> &get_tuple_elems () const
{
return tuple_elems;
}
+ std::vector<std::unique_ptr<Expr>> &get_tuple_elems () { return tuple_elems; }
bool is_unit () const { return tuple_elems.size () == 0; }
@@ -1775,6 +1799,8 @@ public:
std::string as_string () const;
+ location_t get_locus () const { return locus; }
+
// TODO: is this better? Or is a "vis_block" better?
Expr &get_base_struct ()
{
@@ -1972,7 +1998,7 @@ protected:
class StructExprStructFields : public StructExprStruct
{
// std::vector<StructExprField> fields;
- std::vector<std::unique_ptr<StructExprField> > fields;
+ std::vector<std::unique_ptr<StructExprField>> fields;
// bool has_struct_base;
StructBase struct_base;
@@ -1985,8 +2011,8 @@ public:
// Constructor for StructExprStructFields when no struct base is used
StructExprStructFields (
PathInExpression struct_path,
- std::vector<std::unique_ptr<StructExprField> > expr_fields,
- location_t locus, StructBase base_struct = StructBase::error (),
+ std::vector<std::unique_ptr<StructExprField>> expr_fields, location_t locus,
+ StructBase base_struct = StructBase::error (),
std::vector<Attribute> inner_attribs = std::vector<Attribute> (),
std::vector<Attribute> outer_attribs = std::vector<Attribute> ())
: StructExprStruct (std::move (struct_path), std::move (inner_attribs),
@@ -2023,11 +2049,11 @@ public:
void accept_vis (ASTVisitor &vis) override;
// TODO: this mutable getter seems really dodgy. Think up better way.
- std::vector<std::unique_ptr<StructExprField> > &get_fields ()
+ std::vector<std::unique_ptr<StructExprField>> &get_fields ()
{
return fields;
}
- const std::vector<std::unique_ptr<StructExprField> > &get_fields () const
+ const std::vector<std::unique_ptr<StructExprField>> &get_fields () const
{
return fields;
}
@@ -2084,7 +2110,7 @@ class CallExpr : public ExprWithoutBlock
{
std::vector<Attribute> outer_attrs;
std::unique_ptr<Expr> function;
- std::vector<std::unique_ptr<Expr> > params;
+ std::vector<std::unique_ptr<Expr>> params;
location_t locus;
public:
@@ -2093,7 +2119,7 @@ public:
std::string as_string () const override;
CallExpr (std::unique_ptr<Expr> function_expr,
- std::vector<std::unique_ptr<Expr> > function_params,
+ std::vector<std::unique_ptr<Expr>> function_params,
std::vector<Attribute> outer_attribs, location_t locus)
: outer_attrs (std::move (outer_attribs)),
function (std::move (function_expr)),
@@ -2150,11 +2176,11 @@ public:
bool is_marked_for_strip () const override { return function == nullptr; }
// TODO: this mutable getter seems really dodgy. Think up better way.
- const std::vector<std::unique_ptr<Expr> > &get_params () const
+ const std::vector<std::unique_ptr<Expr>> &get_params () const
{
return params;
}
- std::vector<std::unique_ptr<Expr> > &get_params () { return params; }
+ std::vector<std::unique_ptr<Expr>> &get_params () { return params; }
// TODO: is this better? Or is a "vis_block" better?
Expr &get_function_expr ()
@@ -2190,7 +2216,7 @@ class MethodCallExpr : public ExprWithoutBlock
std::vector<Attribute> outer_attrs;
std::unique_ptr<Expr> receiver;
PathExprSegment method_name;
- std::vector<std::unique_ptr<Expr> > params;
+ std::vector<std::unique_ptr<Expr>> params;
location_t locus;
public:
@@ -2198,7 +2224,7 @@ public:
MethodCallExpr (std::unique_ptr<Expr> call_receiver,
PathExprSegment method_path,
- std::vector<std::unique_ptr<Expr> > method_params,
+ std::vector<std::unique_ptr<Expr>> method_params,
std::vector<Attribute> outer_attribs, location_t locus)
: outer_attrs (std::move (outer_attribs)),
receiver (std::move (call_receiver)),
@@ -2254,11 +2280,11 @@ public:
bool is_marked_for_strip () const override { return receiver == nullptr; }
// TODO: this mutable getter seems really dodgy. Think up better way.
- const std::vector<std::unique_ptr<Expr> > &get_params () const
+ const std::vector<std::unique_ptr<Expr>> &get_params () const
{
return params;
}
- std::vector<std::unique_ptr<Expr> > &get_params () { return params; }
+ std::vector<std::unique_ptr<Expr>> &get_params () { return params; }
// TODO: is this better? Or is a "vis_block" better?
Expr &get_receiver_expr ()
@@ -2504,6 +2530,8 @@ public:
bool get_has_move () const { return has_move; }
Expr::Kind get_expr_kind () const override { return Expr::Kind::Closure; }
+
+ virtual Expr &get_definition_expr () = 0;
};
// Represents a non-type-specified closure expression AST node
@@ -2563,7 +2591,7 @@ public:
return closure_inner == nullptr;
}
- Expr &get_definition_expr ()
+ Expr &get_definition_expr () override
{
rust_assert (closure_inner != nullptr);
return *closure_inner;
@@ -2583,7 +2611,7 @@ class BlockExpr : public ExprWithBlock
{
std::vector<Attribute> outer_attrs;
std::vector<Attribute> inner_attrs;
- std::vector<std::unique_ptr<Stmt> > statements;
+ std::vector<std::unique_ptr<Stmt>> statements;
std::unique_ptr<Expr> expr;
tl::optional<LoopLabel> label;
location_t start_locus;
@@ -2599,7 +2627,7 @@ public:
// Returns whether the block contains a final expression.
bool has_tail_expr () const { return expr != nullptr; }
- BlockExpr (std::vector<std::unique_ptr<Stmt> > block_statements,
+ 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,
@@ -2678,11 +2706,11 @@ public:
const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
- const std::vector<std::unique_ptr<Stmt> > &get_statements () const
+ const std::vector<std::unique_ptr<Stmt>> &get_statements () const
{
return statements;
}
- std::vector<std::unique_ptr<Stmt> > &get_statements () { return statements; }
+ std::vector<std::unique_ptr<Stmt>> &get_statements () { return statements; }
// TODO: is this better? Or is a "vis_block" better?
Expr &get_tail_expr ()
@@ -2744,6 +2772,151 @@ protected:
}
};
+class AnonConst : public ExprWithBlock
+{
+public:
+ enum class Kind
+ {
+ Explicit,
+ DeferredInference,
+ };
+
+ AnonConst (std::unique_ptr<Expr> &&expr, location_t locus = UNKNOWN_LOCATION)
+ : ExprWithBlock (), locus (locus), kind (Kind::Explicit),
+ expr (std::move (expr))
+ {
+ rust_assert (this->expr.value ());
+ }
+
+ AnonConst (location_t locus = UNKNOWN_LOCATION)
+ : ExprWithBlock (), locus (locus), kind (Kind::DeferredInference),
+ expr (tl::nullopt)
+ {}
+
+ AnonConst (const AnonConst &other)
+ {
+ node_id = other.node_id;
+ locus = other.locus;
+ kind = other.kind;
+
+ if (other.expr)
+ expr = other.expr.value ()->clone_expr ();
+ }
+
+ AnonConst operator= (const AnonConst &other)
+ {
+ node_id = other.node_id;
+ locus = other.locus;
+ kind = other.kind;
+
+ if (other.expr)
+ expr = other.expr.value ()->clone_expr ();
+
+ return *this;
+ }
+
+ std::string as_string () const override;
+
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::ConstExpr; }
+
+ location_t get_locus () const override { return locus; }
+
+ Expr &get_inner_expr ()
+ {
+ rust_assert (expr.has_value ());
+ return *expr.value ();
+ }
+
+ NodeId get_node_id () const override { return node_id; }
+
+ /* FIXME: AnonConst are always "internal" and should not have outer attributes
+ * - is that true? Or should we instead call
+ * expr->get_outer_attrs()/expr->set_outer_attrs() */
+
+ std::vector<Attribute> &get_outer_attrs () override
+ {
+ static auto attrs = std::vector<Attribute> ();
+ return attrs;
+ }
+
+ void set_outer_attrs (std::vector<Attribute>) override {}
+
+ /* FIXME: Likewise for mark_for_strip() ? */
+ void mark_for_strip () override {}
+ bool is_marked_for_strip () const override { return false; }
+
+ void accept_vis (ASTVisitor &vis) override;
+
+ bool is_deferred () const { return kind == Kind::DeferredInference; }
+
+private:
+ location_t locus;
+ Kind kind;
+ tl::optional<std::unique_ptr<Expr>> expr;
+
+ AnonConst *clone_expr_with_block_impl () const override
+ {
+ return new AnonConst (*this);
+ }
+};
+
+class ConstBlock : public ExprWithBlock
+{
+public:
+ ConstBlock (AnonConst &&expr, location_t locus = UNKNOWN_LOCATION,
+ std::vector<Attribute> &&outer_attrs = {})
+ : ExprWithBlock (), expr (std::move (expr)),
+ outer_attrs (std::move (outer_attrs)), locus (locus)
+ {}
+
+ ConstBlock (const ConstBlock &other)
+ : ExprWithBlock (other), expr (other.expr), outer_attrs (other.outer_attrs),
+ locus (other.locus)
+ {}
+
+ ConstBlock operator= (const ConstBlock &other)
+ {
+ expr = other.expr;
+ node_id = other.node_id;
+ outer_attrs = other.outer_attrs;
+ locus = other.locus;
+
+ return *this;
+ }
+
+ std::string as_string () const override;
+
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::ConstBlock; }
+
+ AnonConst &get_const_expr () { return expr; }
+
+ void accept_vis (ASTVisitor &vis) override;
+
+ std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
+
+ void set_outer_attrs (std::vector<Attribute> new_attrs) override
+ {
+ outer_attrs = std::move (new_attrs);
+ }
+
+ location_t get_locus () const override { return locus; }
+
+ bool is_marked_for_strip () const override { return marked_for_strip; }
+ void mark_for_strip () override { marked_for_strip = true; }
+
+private:
+ AnonConst expr;
+
+ std::vector<Attribute> outer_attrs;
+ location_t locus;
+ bool marked_for_strip = false;
+
+ ConstBlock *clone_expr_with_block_impl () const override
+ {
+ return new ConstBlock (*this);
+ }
+};
+
// Represents a type-specified closure expression AST node
class ClosureExprInnerTyped : public ClosureExpr
{
@@ -2812,7 +2985,7 @@ public:
bool is_marked_for_strip () const override { return expr == nullptr; }
// TODO: is this better? Or is a "vis_block" better?
- BlockExpr &get_definition_block ()
+ BlockExpr &get_definition_expr () override
{
rust_assert (expr != nullptr);
return *expr;
@@ -3572,6 +3745,82 @@ protected:
}
};
+// Try expression AST node representation
+class TryExpr : public ExprWithBlock
+{
+ std::vector<Attribute> outer_attrs;
+ std::unique_ptr<BlockExpr> block_expr;
+ location_t locus;
+
+ // TODO: find another way to store this to save memory?
+ bool marked_for_strip = false;
+
+public:
+ std::string as_string () const override;
+
+ // Constructor for ReturnExpr.
+ TryExpr (std::unique_ptr<BlockExpr> block_expr,
+ std::vector<Attribute> outer_attribs, location_t locus)
+ : outer_attrs (std::move (outer_attribs)),
+ block_expr (std::move (block_expr)), locus (locus)
+ {
+ rust_assert (this->block_expr);
+ }
+
+ // Copy constructor with clone
+ TryExpr (TryExpr const &other)
+ : ExprWithBlock (other), outer_attrs (other.outer_attrs),
+ block_expr (other.block_expr->clone_block_expr ()), locus (other.locus),
+ marked_for_strip (other.marked_for_strip)
+ {}
+
+ // Overloaded assignment operator to clone return_expr pointer
+ TryExpr &operator= (TryExpr const &other)
+ {
+ ExprWithBlock::operator= (other);
+ locus = other.locus;
+ marked_for_strip = other.marked_for_strip;
+ outer_attrs = other.outer_attrs;
+
+ block_expr = other.block_expr->clone_block_expr ();
+
+ return *this;
+ }
+
+ // move constructors
+ TryExpr (TryExpr &&other) = default;
+ TryExpr &operator= (TryExpr &&other) = default;
+
+ location_t get_locus () const override final { return locus; }
+
+ void accept_vis (ASTVisitor &vis) override;
+
+ // Can't think of any invalid invariants, so store boolean.
+ void mark_for_strip () override { marked_for_strip = true; }
+ bool is_marked_for_strip () const override { return marked_for_strip; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ BlockExpr &get_block_expr () { return *block_expr; }
+
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+ std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
+
+ void set_outer_attrs (std::vector<Attribute> new_attrs) override
+ {
+ outer_attrs = std::move (new_attrs);
+ }
+
+ Expr::Kind get_expr_kind () const override { return Expr::Kind::Try; }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ TryExpr *clone_expr_with_block_impl () const override
+ {
+ return new TryExpr (*this);
+ }
+};
+
// Forward decl - defined in rust-macro.h
class MacroInvocation;
@@ -3847,14 +4096,14 @@ protected:
class WhileLetLoopExpr : public BaseLoopExpr
{
// MatchArmPatterns patterns;
- std::vector<std::unique_ptr<Pattern> > match_arm_patterns; // inlined
+ std::vector<std::unique_ptr<Pattern>> match_arm_patterns; // inlined
std::unique_ptr<Expr> scrutinee;
public:
std::string as_string () const override;
// Constructor with a loop label
- WhileLetLoopExpr (std::vector<std::unique_ptr<Pattern> > match_arm_patterns,
+ WhileLetLoopExpr (std::vector<std::unique_ptr<Pattern>> match_arm_patterns,
std::unique_ptr<Expr> scrutinee,
std::unique_ptr<BlockExpr> loop_block, location_t locus,
tl::optional<LoopLabel> loop_label = tl::nullopt,
@@ -3908,11 +4157,11 @@ public:
}
// TODO: this mutable getter seems really dodgy. Think up better way.
- const std::vector<std::unique_ptr<Pattern> > &get_patterns () const
+ const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
{
return match_arm_patterns;
}
- std::vector<std::unique_ptr<Pattern> > &get_patterns ()
+ std::vector<std::unique_ptr<Pattern>> &get_patterns ()
{
return match_arm_patterns;
}
@@ -4195,7 +4444,7 @@ protected:
class IfLetExpr : public ExprWithBlock
{
std::vector<Attribute> outer_attrs;
- std::vector<std::unique_ptr<Pattern> > match_arm_patterns; // inlined
+ std::vector<std::unique_ptr<Pattern>> match_arm_patterns; // inlined
std::unique_ptr<Expr> value;
std::unique_ptr<BlockExpr> if_block;
location_t locus;
@@ -4203,7 +4452,7 @@ class IfLetExpr : public ExprWithBlock
public:
std::string as_string () const override;
- IfLetExpr (std::vector<std::unique_ptr<Pattern> > match_arm_patterns,
+ IfLetExpr (std::vector<std::unique_ptr<Pattern>> match_arm_patterns,
std::unique_ptr<Expr> value, std::unique_ptr<BlockExpr> if_block,
std::vector<Attribute> outer_attrs, location_t locus)
: outer_attrs (std::move (outer_attrs)),
@@ -4297,11 +4546,11 @@ public:
}
// TODO: this mutable getter seems really dodgy. Think up better way.
- const std::vector<std::unique_ptr<Pattern> > &get_patterns () const
+ const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
{
return match_arm_patterns;
}
- std::vector<std::unique_ptr<Pattern> > &get_patterns ()
+ std::vector<std::unique_ptr<Pattern>> &get_patterns ()
{
return match_arm_patterns;
}
@@ -4341,11 +4590,11 @@ class IfLetExprConseqElse : public IfLetExpr
public:
std::string as_string () const override;
- IfLetExprConseqElse (
- std::vector<std::unique_ptr<Pattern> > match_arm_patterns,
- std::unique_ptr<Expr> value, std::unique_ptr<BlockExpr> if_block,
- std::unique_ptr<ExprWithBlock> else_block,
- std::vector<Attribute> outer_attrs, location_t locus)
+ IfLetExprConseqElse (std::vector<std::unique_ptr<Pattern>> match_arm_patterns,
+ std::unique_ptr<Expr> value,
+ std::unique_ptr<BlockExpr> if_block,
+ std::unique_ptr<ExprWithBlock> else_block,
+ std::vector<Attribute> outer_attrs, location_t locus)
: IfLetExpr (std::move (match_arm_patterns), std::move (value),
std::move (if_block), std::move (outer_attrs), locus),
else_block (std::move (else_block))
@@ -4398,7 +4647,7 @@ struct MatchArm
private:
std::vector<Attribute> outer_attrs;
// MatchArmPatterns patterns;
- std::vector<std::unique_ptr<Pattern> > match_arm_patterns; // inlined
+ std::vector<std::unique_ptr<Pattern>> match_arm_patterns; // inlined
// bool has_match_arm_guard;
// inlined from MatchArmGuard
@@ -4411,7 +4660,7 @@ public:
bool has_match_arm_guard () const { return guard_expr != nullptr; }
// Constructor for match arm with a guard expression
- MatchArm (std::vector<std::unique_ptr<Pattern> > match_arm_patterns,
+ MatchArm (std::vector<std::unique_ptr<Pattern>> match_arm_patterns,
location_t locus, std::unique_ptr<Expr> guard_expr = nullptr,
std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
: outer_attrs (std::move (outer_attrs)),
@@ -4463,7 +4712,7 @@ public:
static MatchArm create_error ()
{
location_t locus = UNDEF_LOCATION;
- return MatchArm (std::vector<std::unique_ptr<Pattern> > (), locus);
+ return MatchArm (std::vector<std::unique_ptr<Pattern>> (), locus);
}
std::string as_string () const;
@@ -4485,11 +4734,11 @@ public:
const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
- const std::vector<std::unique_ptr<Pattern> > &get_patterns () const
+ const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
{
return match_arm_patterns;
}
- std::vector<std::unique_ptr<Pattern> > &get_patterns ()
+ std::vector<std::unique_ptr<Pattern>> &get_patterns ()
{
return match_arm_patterns;
}
@@ -4836,29 +5085,6 @@ enum class InlineAsmOption
MAY_UNWIND = 1 << 8,
};
-struct AnonConst
-{
- NodeId id;
- std::unique_ptr<Expr> expr;
- AnonConst (NodeId id, std::unique_ptr<Expr> expr)
- : id (id), expr (std::move (expr))
- {
- rust_assert (this->expr != nullptr);
- }
- AnonConst (const AnonConst &other)
- {
- id = other.id;
- expr = other.expr->clone_expr ();
- }
-
- AnonConst operator= (const AnonConst &other)
- {
- id = other.id;
- expr = other.expr->clone_expr ();
- return *this;
- }
-};
-
struct InlineAsmRegOrRegClass
{
enum Type
@@ -5288,6 +5514,20 @@ struct TupleTemplateStr
// Inline Assembly Node
class InlineAsm : public ExprWithoutBlock
{
+public:
+ enum class Option
+ {
+ PURE = 1 << 0,
+ NOMEM = 1 << 1,
+ READONLY = 1 << 2,
+ PRESERVES_FLAGS = 1 << 3,
+ NORETURN = 1 << 4,
+ NOSTACK = 1 << 5,
+ ATT_SYNTAX = 1 << 6,
+ RAW = 1 << 7,
+ MAY_UNWIND = 1 << 8,
+ };
+
private:
location_t locus;
// TODO: Not sure how outer_attrs plays with InlineAsm, I put it here in order
@@ -5311,7 +5551,7 @@ public:
std::map<std::string, int> named_args;
std::set<int> reg_args;
std::vector<TupleClobber> clobber_abi;
- std::set<InlineAsmOption> options;
+ std::set<InlineAsm::Option> options;
std::vector<location_t> line_spans;
@@ -5342,7 +5582,7 @@ public:
std::vector<TupleClobber> get_clobber_abi () { return clobber_abi; }
- std::set<InlineAsmOption> get_options () { return options; }
+ std::set<InlineAsm::Option> get_options () { return options; }
InlineAsm *clone_expr_without_block_impl () const override
{
@@ -5350,6 +5590,33 @@ public:
}
Expr::Kind get_expr_kind () const override { return Expr::Kind::InlineAsm; }
+
+ static std::string option_to_string (Option option)
+ {
+ switch (option)
+ {
+ case Option::PURE:
+ return "pure";
+ case Option::NOMEM:
+ return "nomem";
+ case Option::READONLY:
+ return "readonly";
+ case Option::PRESERVES_FLAGS:
+ return "preserves_flags";
+ case Option::NORETURN:
+ return "noreturn";
+ case Option::NOSTACK:
+ return "nostack";
+ case Option::ATT_SYNTAX:
+ return "att_syntax";
+ case Option::RAW:
+ return "raw";
+ case Option::MAY_UNWIND:
+ return "may_unwind";
+ default:
+ rust_unreachable ();
+ }
+ }
};
class LlvmInlineAsm : public ExprWithoutBlock
diff --git a/gcc/rust/ast/rust-expression-yeast.cc b/gcc/rust/ast/rust-expression-yeast.cc
new file mode 100644
index 0000000..9f6a62f
--- /dev/null
+++ b/gcc/rust/ast/rust-expression-yeast.cc
@@ -0,0 +1,118 @@
+// 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-expression-yeast.h"
+#include "rust-ast-visitor.h"
+#include "rust-desugar-question-mark.h"
+#include "rust-desugar-try-block.h"
+#include "rust-desugar-for-loops.h"
+#include "rust-ast-full.h"
+#include "rust-desugar-while-let.h"
+#include "rust-expr.h"
+#include "rust-stmt.h"
+
+namespace Rust {
+namespace AST {
+
+void
+ExpressionYeast::go (AST::Crate &crate)
+{
+ DefaultASTVisitor::visit (crate);
+}
+
+void
+ExpressionYeast::dispatch_loops (std::unique_ptr<Expr> &loop_expr)
+{
+ auto &loop = static_cast<BaseLoopExpr &> (*loop_expr.get ());
+
+ switch (loop.get_loop_kind ())
+ {
+ case BaseLoopExpr::Kind::For:
+ DesugarForLoops::go (loop_expr);
+ break;
+ case BaseLoopExpr::Kind::WhileLet:
+ DesugarWhileLet::go (loop_expr);
+ break;
+ default:
+ break;
+ }
+}
+
+void
+ExpressionYeast::dispatch (std::unique_ptr<Expr> &expr)
+{
+ switch (expr->get_expr_kind ())
+ {
+ case Expr::Kind::ErrorPropagation:
+ DesugarQuestionMark::go (expr);
+ break;
+ case Expr::Kind::Try:
+ DesugarTryBlock::go (expr);
+ break;
+ case Expr::Kind::Loop:
+ dispatch_loops (expr);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void
+ExpressionYeast::visit (ExprStmt &stmt)
+{
+ dispatch (stmt.get_expr_ptr ());
+
+ DefaultASTVisitor::visit (stmt);
+}
+
+void
+ExpressionYeast::visit (CallExpr &call)
+{
+ dispatch (call.get_function_expr_ptr ());
+
+ for (auto &arg : call.get_params ())
+ dispatch (arg);
+
+ DefaultASTVisitor::visit (call);
+}
+
+void
+ExpressionYeast::visit (BlockExpr &block)
+{
+ for (auto &stmt : block.get_statements ())
+ if (stmt->get_stmt_kind () == Stmt::Kind::Expr)
+ dispatch (static_cast<ExprStmt &> (*stmt).get_expr_ptr ());
+
+ if (block.has_tail_expr ())
+ dispatch (block.get_tail_expr_ptr ());
+
+ DefaultASTVisitor::visit (block);
+}
+
+void
+ExpressionYeast::visit (LetStmt &stmt)
+{
+ if (stmt.has_init_expr ())
+ dispatch (stmt.get_init_expr_ptr ());
+
+ DefaultASTVisitor::visit (stmt);
+}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/ast/rust-expression-yeast.h b/gcc/rust/ast/rust-expression-yeast.h
new file mode 100644
index 0000000..855918f
--- /dev/null
+++ b/gcc/rust/ast/rust-expression-yeast.h
@@ -0,0 +1,52 @@
+// 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_EXPRESSION_YEAST
+#define RUST_EXPRESSION_YEAST
+
+#include "rust-ast-visitor.h"
+#include "rust-ast.h"
+#include "rust-desugar-question-mark.h"
+
+namespace Rust {
+namespace AST {
+
+// This visitor takes care of all the expression desugars: try-blocks,
+// error-propagation, etc.
+class ExpressionYeast : public AST::DefaultASTVisitor
+{
+ using AST::DefaultASTVisitor::visit;
+
+public:
+ void go (AST::Crate &);
+
+private:
+ // Dispatch to the proper desugar
+ void dispatch (std::unique_ptr<Expr> &expr);
+ void dispatch_loops (std::unique_ptr<Expr> &loop_expr);
+
+ void visit (AST::ExprStmt &) override;
+ void visit (AST::CallExpr &) override;
+ void visit (AST::LetStmt &) override;
+ void visit (AST::BlockExpr &) override;
+};
+
+} // namespace AST
+} // namespace Rust
+
+#endif // ! RUST_EXPRESSION_YEAST
diff --git a/gcc/rust/ast/rust-fmt.h b/gcc/rust/ast/rust-fmt.h
index a54faec..3722db2 100644
--- a/gcc/rust/ast/rust-fmt.h
+++ b/gcc/rust/ast/rust-fmt.h
@@ -266,11 +266,10 @@ enum ParseMode
extern "C" {
-FormatArgsHandle
-collect_pieces (const char *input, bool append_newline, ParseMode parse_mode);
+FormatArgsHandle collect_pieces (const char *input, bool append_newline,
+ ParseMode parse_mode);
-FormatArgsHandle
-clone_pieces (const FormatArgsHandle &);
+FormatArgsHandle clone_pieces (const FormatArgsHandle &);
void destroy_pieces (FormatArgsHandle);
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 062f85d..d11eed7 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -51,21 +51,12 @@ class TypePath;
// A type generic parameter (as opposed to a lifetime generic parameter)
class TypeParam : public GenericParam
{
- // bool has_outer_attribute;
- // std::unique_ptr<Attribute> outer_attr;
AST::AttrVec outer_attrs;
-
Identifier type_representation;
-
- // bool has_type_param_bounds;
- // TypeParamBounds type_param_bounds;
- std::vector<std::unique_ptr<TypeParamBound>>
- type_param_bounds; // inlined form
-
- // bool has_type;
+ std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds;
std::unique_ptr<Type> type;
-
location_t locus;
+ bool was_impl_trait;
public:
Identifier get_type_representation () const { return type_representation; }
@@ -85,18 +76,19 @@ public:
std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds
= std::vector<std::unique_ptr<TypeParamBound>> (),
std::unique_ptr<Type> type = nullptr,
- AST::AttrVec outer_attrs = {})
+ AST::AttrVec outer_attrs = {}, bool was_impl_trait = false)
: GenericParam (Analysis::Mappings::get ().get_next_node_id ()),
outer_attrs (std::move (outer_attrs)),
type_representation (std::move (type_representation)),
type_param_bounds (std::move (type_param_bounds)),
- type (std::move (type)), locus (locus)
+ type (std::move (type)), locus (locus), was_impl_trait (was_impl_trait)
{}
// Copy constructor uses clone
TypeParam (TypeParam const &other)
: GenericParam (other.node_id), outer_attrs (other.outer_attrs),
- type_representation (other.type_representation), locus (other.locus)
+ type_representation (other.type_representation), locus (other.locus),
+ was_impl_trait (other.was_impl_trait)
{
// guard to prevent null pointer dereference
if (other.type != nullptr)
@@ -114,6 +106,7 @@ public:
outer_attrs = other.outer_attrs;
locus = other.locus;
node_id = other.node_id;
+ was_impl_trait = other.was_impl_trait;
// guard to prevent null pointer dereference
if (other.type != nullptr)
@@ -153,17 +146,19 @@ public:
return type;
}
- // TODO: mutable getter seems kinda dodgy
std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ()
{
return type_param_bounds;
}
+
const std::vector<std::unique_ptr<TypeParamBound>> &
get_type_param_bounds () const
{
return type_param_bounds;
}
+ bool from_impl_trait () const { return was_impl_trait; }
+
protected:
// Clone function implementation as virtual method
TypeParam *clone_generic_param_impl () const override
@@ -2455,7 +2450,7 @@ class ConstantItem : public VisItem, public AssociatedItem
// either has an identifier or "_" - maybe handle in identifier?
// bool identifier_is_underscore;
// if no identifier declared, identifier will be "_"
- std::string identifier;
+ Identifier identifier;
std::unique_ptr<Type> type;
std::unique_ptr<Expr> const_expr;
@@ -2465,7 +2460,7 @@ class ConstantItem : public VisItem, public AssociatedItem
public:
std::string as_string () const override;
- ConstantItem (std::string ident, Visibility vis, std::unique_ptr<Type> type,
+ ConstantItem (Identifier ident, Visibility vis, std::unique_ptr<Type> type,
std::unique_ptr<Expr> const_expr,
std::vector<Attribute> outer_attrs, location_t locus)
: VisItem (std::move (vis), std::move (outer_attrs)),
@@ -2473,7 +2468,7 @@ public:
const_expr (std::move (const_expr)), locus (locus)
{}
- ConstantItem (std::string ident, Visibility vis, std::unique_ptr<Type> type,
+ ConstantItem (Identifier ident, Visibility vis, std::unique_ptr<Type> type,
std::vector<Attribute> outer_attrs, location_t locus)
: VisItem (std::move (vis), std::move (outer_attrs)),
identifier (std::move (ident)), type (std::move (type)),
@@ -2516,7 +2511,7 @@ public:
/* Returns whether constant item is an "unnamed" (wildcard underscore used
* as identifier) constant. */
- bool is_unnamed () const { return identifier == "_"; }
+ bool is_unnamed () const { return identifier.as_string () == "_"; }
location_t get_locus () const override final { return locus; }
@@ -2561,7 +2556,7 @@ public:
return type;
}
- std::string get_identifier () const { return identifier; }
+ const Identifier &get_identifier () const { return identifier; }
Item::Kind get_item_kind () const override
{
diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h
index fc01e57..4165075 100644
--- a/gcc/rust/ast/rust-macro.h
+++ b/gcc/rust/ast/rust-macro.h
@@ -27,6 +27,11 @@
#include "rust-macro-builtins.h"
namespace Rust {
+
+// forward declarations for AttributeParser
+class MacroInvocLexer;
+template <typename ManagedTokenSource> class Parser;
+
namespace AST {
class MacroFragSpec
@@ -756,22 +761,16 @@ private:
std::vector<std::unique_ptr<MacroInvocation>> pending_eager_invocs;
protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
MacroInvocation *clone_pattern_impl () const final override
{
return clone_macro_invocation_impl ();
}
- /* Use covariance to implement clone function as returning this object rather
- * than base */
MacroInvocation *clone_expr_without_block_impl () const final override
{
return clone_macro_invocation_impl ();
}
- /* Use covariance to implement clone function as returning this object rather
- * than base */
MacroInvocation *clone_type_no_bounds_impl () const final override
{
return clone_macro_invocation_impl ();
@@ -788,6 +787,20 @@ public:
return new MacroInvocation (*this);
}
+ std::unique_ptr<MacroInvocation> reconstruct_macro_invocation () const
+ {
+ return nullptr;
+ // return reconstruct (this,
+ // &MacroInvocation::reconstruct_macro_invocation_impl);
+ }
+
+ MacroInvocation *reconstruct_impl () const override
+ {
+ return new MacroInvocation (kind, builtin_kind, invoc_data, outer_attrs,
+ locus, is_semi_coloned,
+ reconstruct_vec (pending_eager_invocs));
+ }
+
void add_semicolon () override { is_semi_coloned = true; }
Pattern::Kind get_pattern_kind () override
@@ -1108,16 +1121,14 @@ struct AttributeParser
{
private:
// TODO: might as well rewrite to use lexer tokens
- std::vector<std::unique_ptr<Token>> token_stream;
- int stream_pos;
+ std::unique_ptr<MacroInvocLexer> lexer;
+ std::unique_ptr<Parser<MacroInvocLexer>> parser;
public:
AttributeParser (std::vector<std::unique_ptr<Token>> token_stream,
- int stream_start_pos = 0)
- : token_stream (std::move (token_stream)), stream_pos (stream_start_pos)
- {}
+ int stream_start_pos = 0);
- ~AttributeParser () = default;
+ ~AttributeParser ();
std::vector<std::unique_ptr<MetaItemInner>> parse_meta_item_seq ();
@@ -1126,24 +1137,10 @@ private:
std::unique_ptr<MetaItemInner> parse_meta_item_inner ();
// Returns whether token can end a meta item.
bool is_end_meta_item_tok (TokenId id) const;
- // Parses a simple path.
- SimplePath parse_simple_path ();
- // Parses a segment of a simple path (but not scope resolution operator).
- SimplePathSegment parse_simple_path_segment ();
// Parses a MetaItemLitExpr.
std::unique_ptr<MetaItemLitExpr> parse_meta_item_lit ();
- // Parses a literal.
- Literal parse_literal ();
// Parses a meta item that begins with a simple path.
std::unique_ptr<MetaItem> parse_path_meta_item ();
-
- // TODO: should this be const?
- std::unique_ptr<Token> &peek_token (int i = 0)
- {
- return token_stream[stream_pos + i];
- }
-
- void skip_token (int i = 0) { stream_pos += 1 + i; }
};
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/ast/rust-path.cc b/gcc/rust/ast/rust-path.cc
index 8e43ddf..793423a 100644
--- a/gcc/rust/ast/rust-path.cc
+++ b/gcc/rust/ast/rust-path.cc
@@ -266,6 +266,27 @@ TypePath::as_simple_path () const
locus);
}
+std::string
+TypePath::make_debug_string () const
+{
+ rust_assert (!segments.empty ());
+
+ std::string output;
+
+ for (const auto &segment : segments)
+ {
+ if (segment != nullptr && !segment->is_lang_item ()
+ && !segment->is_error ())
+ {
+ if (!output.empty () || has_opening_scope_resolution_op ())
+ output.append ("::");
+ output.append (segment->get_ident_segment ().as_string ());
+ }
+ }
+
+ return output;
+}
+
// hopefully definition here will prevent circular dependency issue
TraitBound *
TypePath::to_trait_bound (bool in_parens) const
diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h
index a4ba93b..a1b19d5 100644
--- a/gcc/rust/ast/rust-path.h
+++ b/gcc/rust/ast/rust-path.h
@@ -391,6 +391,13 @@ public:
return default_value.value ();
}
+ tl::optional<GenericArg> &get_default_value () { return default_value; }
+
+ const tl::optional<GenericArg> &get_default_value () const
+ {
+ return default_value;
+ }
+
std::string as_string () const override;
void accept_vis (ASTVisitor &vis) override;
@@ -779,6 +786,11 @@ public:
{
return new TypePathSegment (*this);
}
+ virtual TypePathSegment *reconstruct_impl () const
+ {
+ return new TypePathSegment (lang_item, ident_segment,
+ has_separating_scope_resolution, locus);
+ }
public:
virtual ~TypePathSegment () {}
@@ -790,6 +802,11 @@ public:
{
return std::unique_ptr<TypePathSegment> (clone_type_path_segment_impl ());
}
+ // Unique pointer custom reconstruct function
+ std::unique_ptr<TypePathSegment> reconstruct () const
+ {
+ return reconstruct_base (this);
+ }
TypePathSegment (PathIdentSegment ident_segment,
bool has_separating_scope_resolution, location_t locus)
@@ -814,6 +831,15 @@ public:
node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
+ // General constructor
+ TypePathSegment (tl::optional<LangItem::Kind> lang_item,
+ tl::optional<PathIdentSegment> ident_segment,
+ bool has_separating_scope_resolution, location_t locus)
+ : lang_item (lang_item), ident_segment (ident_segment), locus (locus),
+ has_separating_scope_resolution (has_separating_scope_resolution),
+ node_id (Analysis::Mappings::get ().get_next_node_id ())
+ {}
+
TypePathSegment (TypePathSegment const &other)
: lang_item (other.lang_item), ident_segment (other.ident_segment),
locus (other.locus),
@@ -968,11 +994,7 @@ public:
void accept_vis (ASTVisitor &vis) override;
// TODO: is this better? Or is a "vis_pattern" better?
- GenericArgs &get_generic_args ()
- {
- rust_assert (has_generic_args ());
- return generic_args;
- }
+ GenericArgs &get_generic_args () { return generic_args; }
// Use covariance to override base class method
TypePathSegmentGeneric *clone_type_path_segment_impl () const override
@@ -1149,6 +1171,11 @@ protected:
{
return new TypePath (*this);
}
+ TypePath *reconstruct_impl () const override
+ {
+ return new TypePath (reconstruct_vec (segments), locus,
+ has_opening_scope_resolution);
+ }
public:
/* Returns whether the TypePath has an opening scope resolution operator
@@ -1215,6 +1242,8 @@ public:
std::string as_string () const override;
+ std::string make_debug_string () const;
+
/* Converts TypePath to SimplePath if possible (i.e. no generic or function
* arguments). Otherwise returns an empty SimplePath. */
SimplePath as_simple_path () const;
@@ -1438,6 +1467,12 @@ protected:
{
return new QualifiedPathInType (*this);
}
+ QualifiedPathInType *reconstruct_impl () const override
+ {
+ return new QualifiedPathInType (path_type,
+ associated_segment->reconstruct (),
+ reconstruct_vec (segments), locus);
+ }
public:
QualifiedPathInType (
diff --git a/gcc/rust/ast/rust-pattern.cc b/gcc/rust/ast/rust-pattern.cc
index fc7b610..15ab0b7 100644
--- a/gcc/rust/ast/rust-pattern.cc
+++ b/gcc/rust/ast/rust-pattern.cc
@@ -65,8 +65,8 @@ IdentifierPattern::as_string () const
str += variable_ident.as_string ();
- if (has_pattern_to_bind ())
- str += " @ " + to_bind->as_string ();
+ if (has_subpattern ())
+ str += " @ " + subpattern->as_string ();
return str;
}
@@ -327,17 +327,53 @@ GroupedExpr::as_string () const
}
std::string
-SlicePattern::as_string () const
+SlicePatternItemsNoRest::as_string () const
{
- std::string str ("SlicePattern: ");
+ std::string str;
- for (const auto &pattern : items)
+ for (const auto &pattern : patterns)
str += "\n " + pattern->as_string ();
return str;
}
std::string
+SlicePatternItemsHasRest::as_string () const
+{
+ std::string str;
+
+ str += "\n Lower patterns: ";
+ if (lower_patterns.empty ())
+ {
+ str += "none";
+ }
+ else
+ {
+ for (const auto &lower : lower_patterns)
+ str += "\n " + lower->as_string ();
+ }
+
+ str += "\n Upper patterns: ";
+ if (upper_patterns.empty ())
+ {
+ str += "none";
+ }
+ else
+ {
+ for (const auto &upper : upper_patterns)
+ str += "\n " + upper->as_string ();
+ }
+
+ return str;
+}
+
+std::string
+SlicePattern::as_string () const
+{
+ return "SlicePattern: " + items->as_string ();
+}
+
+std::string
AltPattern::as_string () const
{
std::string str ("AltPattern: ");
@@ -367,6 +403,18 @@ GroupedExpr::accept_vis (ASTVisitor &vis)
}
void
+SlicePatternItemsNoRest::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
+SlicePatternItemsHasRest::accept_vis (ASTVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
SlicePattern::accept_vis (ASTVisitor &vis)
{
vis.visit (*this);
diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h
index 69dbd98..4945ec4 100644
--- a/gcc/rust/ast/rust-pattern.h
+++ b/gcc/rust/ast/rust-pattern.h
@@ -74,7 +74,7 @@ class IdentifierPattern : public Pattern
bool is_mut;
// bool has_pattern;
- std::unique_ptr<Pattern> to_bind;
+ std::unique_ptr<Pattern> subpattern;
location_t locus;
NodeId node_id;
@@ -82,22 +82,22 @@ public:
std::string as_string () const override;
// Returns whether the IdentifierPattern has a pattern to bind.
- bool has_pattern_to_bind () const { return to_bind != nullptr; }
+ bool has_subpattern () const { return subpattern != nullptr; }
// Constructor
IdentifierPattern (Identifier ident, location_t locus, bool is_ref = false,
bool is_mut = false,
- std::unique_ptr<Pattern> to_bind = nullptr)
+ std::unique_ptr<Pattern> subpattern = nullptr)
: Pattern (), variable_ident (std::move (ident)), is_ref (is_ref),
- is_mut (is_mut), to_bind (std::move (to_bind)), locus (locus),
+ is_mut (is_mut), subpattern (std::move (subpattern)), locus (locus),
node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
IdentifierPattern (NodeId node_id, Identifier ident, location_t locus,
bool is_ref = false, bool is_mut = false,
- std::unique_ptr<Pattern> to_bind = nullptr)
+ std::unique_ptr<Pattern> subpattern = nullptr)
: Pattern (), variable_ident (std::move (ident)), is_ref (is_ref),
- is_mut (is_mut), to_bind (std::move (to_bind)), locus (locus),
+ is_mut (is_mut), subpattern (std::move (subpattern)), locus (locus),
node_id (node_id)
{}
@@ -107,8 +107,8 @@ public:
is_mut (other.is_mut), locus (other.locus), node_id (other.node_id)
{
// fix to get prevent null pointer dereference
- if (other.to_bind != nullptr)
- to_bind = other.to_bind->clone_pattern ();
+ if (other.subpattern != nullptr)
+ subpattern = other.subpattern->clone_pattern ();
}
// Overload assignment operator to use clone
@@ -121,10 +121,10 @@ public:
node_id = other.node_id;
// fix to prevent null pointer dereference
- if (other.to_bind != nullptr)
- to_bind = other.to_bind->clone_pattern ();
+ if (other.subpattern != nullptr)
+ subpattern = other.subpattern->clone_pattern ();
else
- to_bind = nullptr;
+ subpattern = nullptr;
return *this;
}
@@ -137,11 +137,10 @@ public:
void accept_vis (ASTVisitor &vis) override;
- // TODO: is this better? Or is a "vis_pattern" better?
- Pattern &get_pattern_to_bind ()
+ Pattern &get_subpattern ()
{
- rust_assert (has_pattern_to_bind ());
- return *to_bind;
+ rust_assert (has_subpattern ());
+ return *subpattern;
}
Identifier get_ident () const { return variable_ident; }
@@ -375,8 +374,7 @@ enum class RangeKind
EXCLUDED,
};
-RangeKind
-tokenid_to_rangekind (TokenId id);
+RangeKind tokenid_to_rangekind (TokenId id);
// AST node for matching within a certain range (range pattern)
class RangePattern : public Pattern
{
@@ -950,7 +948,7 @@ public:
* is empty). */
bool has_struct_pattern_elems () const { return !elems.is_empty (); }
- location_t get_locus () const override { return path.get_locus (); }
+ location_t get_locus () const override { return locus; }
void accept_vis (ASTVisitor &vis) override;
@@ -1523,41 +1521,217 @@ protected:
}
};
+// Base abstract class representing patterns in a SlicePattern
+class SlicePatternItems
+{
+public:
+ enum SlicePatternItemType
+ {
+ NO_REST,
+ HAS_REST,
+ };
+
+ virtual ~SlicePatternItems () {}
+
+ // TODO: should this store location data?
+
+ // Unique pointer custom clone function
+ std::unique_ptr<SlicePatternItems> clone_slice_pattern_items () const
+ {
+ return std::unique_ptr<SlicePatternItems> (
+ clone_slice_pattern_items_impl ());
+ }
+
+ virtual std::string as_string () const = 0;
+
+ virtual void accept_vis (ASTVisitor &vis) = 0;
+
+ virtual SlicePatternItemType get_pattern_type () const = 0;
+
+protected:
+ // pure virtual clone implementation
+ virtual SlicePatternItems *clone_slice_pattern_items_impl () const = 0;
+};
+
+// Class representing the patterns in a SlicePattern without `..`
+class SlicePatternItemsNoRest : public SlicePatternItems
+{
+ std::vector<std::unique_ptr<Pattern>> patterns;
+
+public:
+ SlicePatternItemsNoRest (std::vector<std::unique_ptr<Pattern>> patterns)
+ : patterns (std::move (patterns))
+ {}
+
+ // Copy constructor with vector clone
+ SlicePatternItemsNoRest (SlicePatternItemsNoRest const &other)
+ {
+ patterns.reserve (other.patterns.size ());
+ for (const auto &e : other.patterns)
+ patterns.push_back (e->clone_pattern ());
+ }
+
+ // Overloaded assignment operator to vector clone
+ SlicePatternItemsNoRest &operator= (SlicePatternItemsNoRest const &other)
+ {
+ patterns.clear ();
+ patterns.reserve (other.patterns.size ());
+ for (const auto &e : other.patterns)
+ patterns.push_back (e->clone_pattern ());
+
+ return *this;
+ }
+
+ // move constructors
+ SlicePatternItemsNoRest (SlicePatternItemsNoRest &&other) = default;
+ SlicePatternItemsNoRest &operator= (SlicePatternItemsNoRest &&other)
+ = default;
+
+ std::string as_string () const override;
+
+ void accept_vis (ASTVisitor &vis) override;
+
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<std::unique_ptr<Pattern>> &get_patterns () { return patterns; }
+ const std::vector<std::unique_ptr<Pattern>> &get_patterns () const
+ {
+ return patterns;
+ }
+
+ SlicePatternItemType get_pattern_type () const override
+ {
+ return SlicePatternItemType::NO_REST;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ SlicePatternItemsNoRest *clone_slice_pattern_items_impl () const override
+ {
+ return new SlicePatternItemsNoRest (*this);
+ }
+};
+
+// Class representing the patterns in a SlicePattern that contains a `..`
+class SlicePatternItemsHasRest : public SlicePatternItems
+{
+ std::vector<std::unique_ptr<Pattern>> lower_patterns;
+ std::vector<std::unique_ptr<Pattern>> upper_patterns;
+
+public:
+ SlicePatternItemsHasRest (
+ std::vector<std::unique_ptr<Pattern>> lower_patterns,
+ std::vector<std::unique_ptr<Pattern>> upper_patterns)
+ : lower_patterns (std::move (lower_patterns)),
+ upper_patterns (std::move (upper_patterns))
+ {}
+
+ // Copy constructor with vector clone
+ SlicePatternItemsHasRest (SlicePatternItemsHasRest const &other)
+ {
+ lower_patterns.reserve (other.lower_patterns.size ());
+ for (const auto &e : other.lower_patterns)
+ lower_patterns.push_back (e->clone_pattern ());
+
+ upper_patterns.reserve (other.upper_patterns.size ());
+ for (const auto &e : other.upper_patterns)
+ upper_patterns.push_back (e->clone_pattern ());
+ }
+
+ // Overloaded assignment operator to clone
+ SlicePatternItemsHasRest &operator= (SlicePatternItemsHasRest const &other)
+ {
+ lower_patterns.clear ();
+ lower_patterns.reserve (other.lower_patterns.size ());
+ for (const auto &e : other.lower_patterns)
+ lower_patterns.push_back (e->clone_pattern ());
+
+ upper_patterns.clear ();
+ upper_patterns.reserve (other.upper_patterns.size ());
+ for (const auto &e : other.upper_patterns)
+ upper_patterns.push_back (e->clone_pattern ());
+
+ return *this;
+ }
+
+ // move constructors
+ SlicePatternItemsHasRest (SlicePatternItemsHasRest &&other) = default;
+ SlicePatternItemsHasRest &operator= (SlicePatternItemsHasRest &&other)
+ = default;
+
+ std::string as_string () const override;
+
+ void accept_vis (ASTVisitor &vis) override;
+
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<std::unique_ptr<Pattern>> &get_lower_patterns ()
+ {
+ return lower_patterns;
+ }
+ const std::vector<std::unique_ptr<Pattern>> &get_lower_patterns () const
+ {
+ return lower_patterns;
+ }
+
+ // TODO: seems kinda dodgy. Think of better way.
+ std::vector<std::unique_ptr<Pattern>> &get_upper_patterns ()
+ {
+ return upper_patterns;
+ }
+ const std::vector<std::unique_ptr<Pattern>> &get_upper_patterns () const
+ {
+ return upper_patterns;
+ }
+
+ SlicePatternItemType get_pattern_type () const override
+ {
+ return SlicePatternItemType::HAS_REST;
+ }
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ SlicePatternItemsHasRest *clone_slice_pattern_items_impl () const override
+ {
+ return new SlicePatternItemsHasRest (*this);
+ }
+};
+
// AST node representing patterns that can match slices and arrays
class SlicePattern : public Pattern
{
- std::vector<std::unique_ptr<Pattern>> items;
+ std::unique_ptr<SlicePatternItems> items;
location_t locus;
NodeId node_id;
public:
std::string as_string () const override;
- SlicePattern (std::vector<std::unique_ptr<Pattern>> items, location_t locus)
+ SlicePattern (std::unique_ptr<SlicePatternItems> items, location_t locus)
: items (std::move (items)), locus (locus),
node_id (Analysis::Mappings::get ().get_next_node_id ())
{}
- // Copy constructor with vector clone
+ // Copy constructor requires clone
SlicePattern (SlicePattern const &other) : locus (other.locus)
{
+ // guard to prevent null dereference
+ rust_assert (other.items != nullptr);
+
node_id = other.node_id;
- items.reserve (other.items.size ());
- for (const auto &e : other.items)
- items.push_back (e->clone_pattern ());
+ items = other.items->clone_slice_pattern_items ();
}
- // Overloaded assignment operator to vector clone
+ // Overloaded assignment operator to clone
SlicePattern &operator= (SlicePattern const &other)
{
locus = other.locus;
node_id = other.node_id;
- items.clear ();
- items.reserve (other.items.size ());
- for (const auto &e : other.items)
- items.push_back (e->clone_pattern ());
+ // guard to prevent null dereference
+ rust_assert (other.items != nullptr);
+ items = other.items->clone_slice_pattern_items ();
return *this;
}
@@ -1570,10 +1744,10 @@ public:
void accept_vis (ASTVisitor &vis) override;
// TODO: seems kinda dodgy. Think of better way.
- std::vector<std::unique_ptr<Pattern>> &get_items () { return items; }
- const std::vector<std::unique_ptr<Pattern>> &get_items () const
+ SlicePatternItems &get_items ()
{
- return items;
+ rust_assert (items != nullptr);
+ return *items;
}
NodeId get_node_id () const override { return node_id; }
diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h
index 1bb521d..2a3496b 100644
--- a/gcc/rust/ast/rust-type.h
+++ b/gcc/rust/ast/rust-type.h
@@ -19,7 +19,9 @@
#ifndef RUST_AST_TYPE_H
#define RUST_AST_TYPE_H
+#include "optional.h"
#include "rust-ast.h"
+#include "rust-expr.h"
#include "rust-path.h"
namespace Rust {
@@ -73,6 +75,13 @@ public:
type_path (std::move (type_path)), locus (locus)
{}
+ TraitBound (TraitBound const &other)
+ : TypeParamBound (other.get_node_id ()), in_parens (other.in_parens),
+ opening_question_mark (other.opening_question_mark),
+ for_lifetimes (other.for_lifetimes), type_path (other.type_path),
+ locus (other.locus)
+ {}
+
std::string as_string () const override;
location_t get_locus () const override final { return locus; }
@@ -99,6 +108,11 @@ protected:
return new TraitBound (node_id, type_path, locus, in_parens,
opening_question_mark, for_lifetimes);
}
+ TraitBound *reconstruct_impl () const override
+ {
+ return new TraitBound (type_path, locus, in_parens, opening_question_mark,
+ for_lifetimes);
+ }
};
// definition moved to rust-ast.h
@@ -120,6 +134,10 @@ protected:
{
return new ImplTraitType (*this);
}
+ ImplTraitType *reconstruct_impl () const override
+ {
+ return new ImplTraitType (reconstruct_vec (type_param_bounds), locus);
+ }
public:
ImplTraitType (
@@ -129,7 +147,8 @@ public:
{}
// copy constructor with vector clone
- ImplTraitType (ImplTraitType const &other) : locus (other.locus)
+ ImplTraitType (ImplTraitType const &other)
+ : Type (other.node_id), locus (other.locus)
{
type_param_bounds.reserve (other.type_param_bounds.size ());
for (const auto &e : other.type_param_bounds)
@@ -184,6 +203,11 @@ protected:
{
return new TraitObjectType (*this);
}
+ TraitObjectType *reconstruct_impl () const override
+ {
+ return new TraitObjectType (reconstruct_vec (type_param_bounds), locus,
+ has_dyn);
+ }
public:
TraitObjectType (
@@ -195,7 +219,7 @@ public:
// copy constructor with vector clone
TraitObjectType (TraitObjectType const &other)
- : has_dyn (other.has_dyn), locus (other.locus)
+ : Type (other.node_id), has_dyn (other.has_dyn), locus (other.locus)
{
type_param_bounds.reserve (other.type_param_bounds.size ());
for (const auto &e : other.type_param_bounds)
@@ -251,6 +275,10 @@ protected:
{
return new ParenthesisedType (*this);
}
+ ParenthesisedType *reconstruct_impl () const override
+ {
+ return new ParenthesisedType (type_in_parens->reconstruct (), locus);
+ }
public:
// Constructor uses Type pointer for polymorphism
@@ -305,33 +333,35 @@ public:
// Impl trait with a single bound? Poor reference material here.
class ImplTraitTypeOneBound : public TypeNoBounds
{
- TraitBound trait_bound;
+ std::unique_ptr<TypeParamBound> trait_bound;
location_t locus;
-protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
- ImplTraitTypeOneBound *clone_type_no_bounds_impl () const override
- {
- return new ImplTraitTypeOneBound (*this);
- }
-
public:
- ImplTraitTypeOneBound (TraitBound trait_bound, location_t locus)
+ ImplTraitTypeOneBound (std::unique_ptr<TypeParamBound> trait_bound,
+ location_t locus)
: trait_bound (std::move (trait_bound)), locus (locus)
{}
+ ImplTraitTypeOneBound (ImplTraitTypeOneBound const &other)
+ : trait_bound (other.trait_bound->clone_type_param_bound ()),
+ locus (other.locus)
+ {}
+
std::string as_string () const override;
location_t get_locus () const override final { return locus; }
void accept_vis (ASTVisitor &vis) override;
- // TODO: would a "vis_type" be better?
- TraitBound &get_trait_bound ()
+ std::unique_ptr<TypeParamBound> &get_trait_bound () { return trait_bound; }
+
+ TypeNoBounds *clone_type_no_bounds_impl () const override
{
- // TODO: check to ensure invariants are met?
- return trait_bound;
+ return new ImplTraitTypeOneBound (*this);
+ }
+ TypeNoBounds *reconstruct_impl () const override
+ {
+ return new ImplTraitTypeOneBound (trait_bound->reconstruct (), locus);
}
};
@@ -350,6 +380,10 @@ protected:
{
return new TraitObjectTypeOneBound (*this);
}
+ TraitObjectTypeOneBound *reconstruct_impl () const override
+ {
+ return new TraitObjectTypeOneBound (trait_bound, locus, has_dyn);
+ }
public:
TraitObjectTypeOneBound (TraitBound trait_bound, location_t locus,
@@ -443,6 +477,10 @@ protected:
{
return new TupleType (*this);
}
+ TupleType *reconstruct_impl () const override
+ {
+ return new TupleType (reconstruct_vec (elems), locus);
+ }
};
/* A type with no values, representing the result of computations that never
@@ -459,6 +497,10 @@ protected:
{
return new NeverType (*this);
}
+ NeverType *reconstruct_impl () const override
+ {
+ return new NeverType (locus);
+ }
public:
NeverType (location_t locus) : locus (locus) {}
@@ -529,6 +571,9 @@ public:
return *type;
}
+ // Getter for direct access to the type unique_ptr
+ std::unique_ptr<TypeNoBounds> &get_type_ptr () { return type; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -536,6 +581,10 @@ protected:
{
return new RawPointerType (*this);
}
+ RawPointerType *reconstruct_impl () const override
+ {
+ return new RawPointerType (pointer_type, type->reconstruct (), locus);
+ }
};
// A type pointing to memory owned by another value
@@ -604,6 +653,9 @@ public:
TypeNoBounds &get_base_type () { return *type; }
+ // Getter for direct access to the type unique_ptr
+ std::unique_ptr<TypeNoBounds> &get_type_ptr () { return type; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -611,33 +663,42 @@ protected:
{
return new ReferenceType (*this);
}
+ ReferenceType *reconstruct_impl () const override
+ {
+ return new ReferenceType (has_mut, type->reconstruct (), locus,
+ // TODO: Improve this - it's ugly!
+ has_lifetime () ? tl::make_optional<Lifetime> (
+ lifetime->get_lifetime_type (),
+ lifetime->get_lifetime_name (),
+ lifetime->get_locus ())
+ : tl::nullopt);
+ }
};
// A fixed-size sequence of elements of a specified type
class ArrayType : public TypeNoBounds
{
std::unique_ptr<Type> elem_type;
- std::unique_ptr<Expr> size;
+ AnonConst size;
location_t locus;
public:
// Constructor requires pointers for polymorphism
- ArrayType (std::unique_ptr<Type> type, std::unique_ptr<Expr> array_size,
- location_t locus)
+ ArrayType (std::unique_ptr<Type> type, AnonConst array_size, location_t locus)
: elem_type (std::move (type)), size (std::move (array_size)), locus (locus)
{}
// Copy constructor requires deep copies of both unique pointers
ArrayType (ArrayType const &other)
- : elem_type (other.elem_type->clone_type ()),
- size (other.size->clone_expr ()), locus (other.locus)
+ : elem_type (other.elem_type->clone_type ()), size (other.size),
+ locus (other.locus)
{}
// Overload assignment operator to deep copy pointers
ArrayType &operator= (ArrayType const &other)
{
elem_type = other.elem_type->clone_type ();
- size = other.size->clone_expr ();
+ size = other.size;
locus = other.locus;
return *this;
}
@@ -660,12 +721,15 @@ public:
}
// TODO: would a "vis_expr" be better?
- Expr &get_size_expr ()
+ AnonConst &get_size_expr ()
{
- rust_assert (size != nullptr);
- return *size;
+ // rust_assert (size != nullptr);
+
+ return size;
}
+ std::unique_ptr<Type> &get_element_type () { return elem_type; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -673,6 +737,12 @@ protected:
{
return new ArrayType (*this);
}
+ ArrayType *reconstruct_impl () const override
+ {
+ return new ArrayType (elem_type->reconstruct (),
+ size /* FIXME: This should be `reconstruct_expr()` */,
+ locus);
+ }
};
/* A dynamically-sized type representing a "view" into a sequence of elements of
@@ -719,13 +789,20 @@ public:
return *elem_type;
}
+ // Getter for direct access to the elem_type unique_ptr
+ std::unique_ptr<Type> &get_elem_type_ptr () { return elem_type; }
+
protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
+ /* Use covariance to implement clone function as returning this object
+ * rather than base */
SliceType *clone_type_no_bounds_impl () const override
{
return new SliceType (*this);
}
+ SliceType *reconstruct_impl () const override
+ {
+ return new SliceType (elem_type->reconstruct (), locus);
+ }
};
/* Type used in generic arguments to explicitly request type inference (wildcard
@@ -736,13 +813,21 @@ class InferredType : public TypeNoBounds
// e.g. Vec<_> = whatever
protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
+ /* Use covariance to implement clone function as returning this object
+ * rather than base */
InferredType *clone_type_no_bounds_impl () const override
{
+ // This goes through the copy constructor
return new InferredType (*this);
}
+ InferredType *reconstruct_impl () const override
+ {
+ // This goes through the base constructor which calls the base
+ // TypeNoBounds constructor, which allocates a new NodeId
+ return new InferredType (locus);
+ }
+
public:
InferredType (location_t locus) : locus (locus) {}
@@ -961,9 +1046,17 @@ public:
FunctionQualifiers &get_function_qualifiers () { return function_qualifiers; }
+ BareFunctionType *reconstruct_impl () const override
+ {
+ return new BareFunctionType (
+ for_lifetimes, function_qualifiers, params,
+ /* FIXME: Should params be reconstruct() as well? */
+ _is_variadic, variadic_attrs, return_type->reconstruct (), locus);
+ }
+
protected:
- /* Use covariance to implement clone function as returning this object rather
- * than base */
+ /* Use covariance to implement clone function as returning this object
+ * rather than base */
BareFunctionType *clone_type_no_bounds_impl () const override
{
return new BareFunctionType (*this);
@@ -980,13 +1073,13 @@ class MacroInvocation;
* function item type?
* closure expression types?
* primitive types (bool, int, float, char, str (the slice))
- * Although supposedly TypePaths are used to reference these types (including
- * primitives) */
+ * Although supposedly TypePaths are used to reference these types
+ * (including primitives) */
/* FIXME: Incomplete spec references:
- * anonymous type parameters, aka "impl Trait in argument position" - impl then
- * trait bounds abstract return types, aka "impl Trait in return position" -
- * impl then trait bounds */
+ * anonymous type parameters, aka "impl Trait in argument position" - impl
+ * then trait bounds abstract return types, aka "impl Trait in return
+ * position" - impl then trait bounds */
} // namespace AST
} // namespace Rust
diff --git a/gcc/rust/backend/rust-compile-asm.cc b/gcc/rust/backend/rust-compile-asm.cc
index 7351cf0..b7143a8 100644
--- a/gcc/rust/backend/rust-compile-asm.cc
+++ b/gcc/rust/backend/rust-compile-asm.cc
@@ -74,57 +74,94 @@ CompileAsm::asm_construct_string_tree (HIR::InlineAsm &expr)
return Backend::string_constant_expression (result);
}
+tl::optional<std::reference_wrapper<HIR::Expr>>
+get_out_expr (HIR::InlineAsmOperand &operand)
+{
+ switch (operand.get_register_type ())
+ {
+ case HIR::InlineAsmOperand::RegisterType::Out:
+ return *operand.get_out ().expr;
+ case HIR::InlineAsmOperand::RegisterType::InOut:
+ return *operand.get_in_out ().expr;
+ case HIR::InlineAsmOperand::RegisterType::SplitInOut:
+ return *operand.get_split_in_out ().out_expr;
+ case HIR::InlineAsmOperand::RegisterType::Const:
+ case HIR::InlineAsmOperand::RegisterType::Sym:
+ case HIR::InlineAsmOperand::RegisterType::Label:
+ case HIR::InlineAsmOperand::RegisterType::In:
+ break;
+ }
+ return tl::nullopt;
+}
+
tree
CompileAsm::asm_construct_outputs (HIR::InlineAsm &expr)
{
// TODO: Do i need to do this?
tree head = NULL_TREE;
- for (auto &output : expr.get_operands ())
+ for (auto &operand : expr.get_operands ())
{
- if (output.get_register_type ()
- == AST::InlineAsmOperand::RegisterType::Out)
- {
- auto out = output.get_out ();
-
- tree out_tree = CompileExpr::Compile (*out.expr, this->ctx);
- // expects a tree list
- // TODO: This assumes that the output is a register
- std::string expr_name = "=r";
- auto name = build_string (expr_name.size () + 1, expr_name.c_str ());
- head
- = chainon (head, build_tree_list (build_tree_list (NULL_TREE, name),
- out_tree));
-
- /*Backend::debug (head);*/
- /*head = chainon (head, out_tree);*/
- }
+ tl::optional<std::reference_wrapper<HIR::Expr>> out_expr
+ = get_out_expr (operand);
+ if (!out_expr.has_value ())
+ continue;
+
+ tree out_tree = CompileExpr::Compile (*out_expr, this->ctx);
+ // expects a tree list
+ // TODO: This assumes that the output is a register
+ std::string expr_name = "=r";
+ auto name = build_string (expr_name.size () + 1, expr_name.c_str ());
+ head = chainon (head, build_tree_list (build_tree_list (NULL_TREE, name),
+ out_tree));
+
+ /*Backend::debug (head);*/
+ /*head = chainon (head, out_tree);*/
}
return head;
}
+tl::optional<std::reference_wrapper<HIR::Expr>>
+get_in_expr (HIR::InlineAsmOperand &operand)
+{
+ switch (operand.get_register_type ())
+ {
+ case HIR::InlineAsmOperand::RegisterType::In:
+ return *operand.get_in ().expr;
+ case HIR::InlineAsmOperand::RegisterType::InOut:
+ return *operand.get_in_out ().expr;
+ case HIR::InlineAsmOperand::RegisterType::SplitInOut:
+ return *operand.get_split_in_out ().in_expr;
+ case HIR::InlineAsmOperand::RegisterType::Const:
+ case HIR::InlineAsmOperand::RegisterType::Sym:
+ case HIR::InlineAsmOperand::RegisterType::Label:
+ case HIR::InlineAsmOperand::RegisterType::Out:
+ break;
+ }
+ return tl::nullopt;
+}
+
tree
CompileAsm::asm_construct_inputs (HIR::InlineAsm &expr)
{
// TODO: Do i need to do this?
tree head = NULL_TREE;
- for (auto &input : expr.get_operands ())
+ for (auto &operand : expr.get_operands ())
{
- if (input.get_register_type () == AST::InlineAsmOperand::RegisterType::In)
- {
- auto in = input.get_in ();
-
- tree in_tree = CompileExpr::Compile (*in.expr, this->ctx);
- // expects a tree list
- // TODO: This assumes that the input is a register
- std::string expr_name = "r";
- auto name = build_string (expr_name.size () + 1, expr_name.c_str ());
- head
- = chainon (head, build_tree_list (build_tree_list (NULL_TREE, name),
- in_tree));
-
- /*head = chainon (head, out_tree);*/
- }
+ tl::optional<std::reference_wrapper<HIR::Expr>> in_expr
+ = get_in_expr (operand);
+ if (!in_expr.has_value ())
+ continue;
+
+ tree in_tree = CompileExpr::Compile (*in_expr, this->ctx);
+ // expects a tree list
+ // TODO: This assumes that the input is a register
+ std::string expr_name = "r";
+ auto name = build_string (expr_name.size () + 1, expr_name.c_str ());
+ head = chainon (head, build_tree_list (build_tree_list (NULL_TREE, name),
+ in_tree));
+
+ /*head = chainon (head, out_tree);*/
}
return head;
}
diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc
index 12b9561..73c34b2 100644
--- a/gcc/rust/backend/rust-compile-base.cc
+++ b/gcc/rust/backend/rust-compile-base.cc
@@ -576,6 +576,25 @@ HIRCompileBase::compile_constant_expr (
}
tree
+HIRCompileBase::query_compile_const_expr (Context *ctx, TyTy::BaseType *expr_ty,
+ HIR::Expr &const_value_expr)
+{
+ HIRCompileBase c (ctx);
+
+ ctx->push_const_context ();
+
+ HirId expr_id = const_value_expr.get_mappings ().get_hirid ();
+ location_t locus = const_value_expr.get_locus ();
+ tree capacity_expr = HIRCompileBase::compile_constant_expr (
+ ctx, expr_id, expr_ty, expr_ty, Resolver::CanonicalPath::create_empty (),
+ const_value_expr, locus, locus);
+
+ ctx->pop_const_context ();
+
+ return fold_expr (capacity_expr);
+}
+
+tree
HIRCompileBase::indirect_expression (tree expr, location_t locus)
{
if (expr == error_mark_node)
@@ -677,8 +696,12 @@ HIRCompileBase::compile_function (
std::string ir_symbol_name
= canonical_path.get () + fntype->subst_as_string ();
+ rust_debug_loc (locus, "--> Compiling [%s] - %s", ir_symbol_name.c_str (),
+ fntype->get_name ().c_str ());
+
// we don't mangle the main fn since we haven't implemented the main shim
- bool is_main_fn = fn_name.compare ("main") == 0 && is_root_item;
+ bool is_main_fn = fn_name.compare ("main") == 0 && is_root_item
+ && canonical_path.size () <= 2;
if (is_main_fn)
{
rust_assert (!main_identifier_node);
@@ -687,14 +710,9 @@ HIRCompileBase::compile_function (
}
std::string asm_name = fn_name;
- auto &mappings = Analysis::Mappings::get ();
-
- if (flag_name_resolution_2_0)
- ir_symbol_name = mappings.get_current_crate_name () + "::" + ir_symbol_name;
-
unsigned int flags = 0;
tree fndecl = Backend::function (compiled_fn_type, ir_symbol_name,
- "" /* asm_name */, flags, locus);
+ tl::nullopt /* asm_name */, flags, locus);
setup_fndecl (fndecl, is_main_fn, fntype->has_substitutions_defined (),
visibility, qualifiers, outer_attrs);
@@ -812,11 +830,12 @@ HIRCompileBase::compile_constant_item (
// machineary that we already have. This means the best approach is to
// make a _fake_ function with a block so it can hold onto temps then
// use our constexpr code to fold it completely or error_mark_node
- Backend::typed_identifier receiver;
+ Backend::typed_identifier receiver ("", NULL_TREE, UNKNOWN_LOCATION);
tree compiled_fn_type = Backend::function_type (
receiver, {}, {Backend::typed_identifier ("_", const_type, locus)}, NULL,
locus);
- tree fndecl = Backend::function (compiled_fn_type, ident, "", 0, locus);
+ tree fndecl
+ = Backend::function (compiled_fn_type, ident, tl::nullopt, 0, locus);
TREE_READONLY (fndecl) = 1;
tree enclosing_scope = NULL_TREE;
diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h
index 6814abc..e9b8596 100644
--- a/gcc/rust/backend/rust-compile-base.h
+++ b/gcc/rust/backend/rust-compile-base.h
@@ -38,6 +38,9 @@ public:
const Resolver::CanonicalPath &canonical_path, HIR::Expr &const_value_expr,
location_t locus, location_t expr_locus);
+ static tree query_compile_const_expr (Context *ctx, TyTy::BaseType *expr_ty,
+ HIR::Expr &const_value_expr);
+
protected:
HIRCompileBase (Context *ctx) : ctx (ctx) {}
diff --git a/gcc/rust/backend/rust-compile-block.cc b/gcc/rust/backend/rust-compile-block.cc
index f844a27..03c36d2 100644
--- a/gcc/rust/backend/rust-compile-block.cc
+++ b/gcc/rust/backend/rust-compile-block.cc
@@ -19,6 +19,7 @@
#include "rust-compile-block.h"
#include "rust-compile-stmt.h"
#include "rust-compile-expr.h"
+#include "rust-hir-expr.h"
namespace Rust {
namespace Compile {
diff --git a/gcc/rust/backend/rust-compile-block.h b/gcc/rust/backend/rust-compile-block.h
index 3f38d08..f84bace 100644
--- a/gcc/rust/backend/rust-compile-block.h
+++ b/gcc/rust/backend/rust-compile-block.h
@@ -20,6 +20,7 @@
#define RUST_COMPILE_BLOCK
#include "rust-compile-base.h"
+#include "rust-hir-expr.h"
#include "rust-hir-visitor.h"
namespace Rust {
@@ -83,6 +84,8 @@ public:
void visit (HIR::MethodCallExpr &) override {}
void visit (HIR::FieldAccessExpr &) override {}
void visit (HIR::BlockExpr &) override {}
+ void visit (HIR::AnonConst &) override {}
+ void visit (HIR::ConstBlock &) override {}
void visit (HIR::ContinueExpr &) override {}
void visit (HIR::BreakExpr &) override {}
void visit (HIR::RangeFromToExpr &) override {}
@@ -101,6 +104,7 @@ public:
void visit (HIR::AsyncBlockExpr &) override {}
void visit (HIR::InlineAsm &) override {}
void visit (HIR::LlvmInlineAsm &) override {}
+ void visit (HIR::OffsetOf &) override {}
private:
CompileConditionalBlocks (Context *ctx, Bvariable *result)
@@ -138,6 +142,12 @@ public:
translated = CompileBlock::compile (expr, ctx, result);
}
+ void visit (HIR::ConstBlock &expr) override
+ {
+ rust_unreachable ();
+ // translated = CompileExpr::compile (expr, ctx, result);
+ }
+
// Empty visit for unused Expression HIR nodes.
void visit (HIR::PathInExpression &) override {}
void visit (HIR::QualifiedPathInExpression &) override {}
@@ -184,6 +194,8 @@ public:
void visit (HIR::AsyncBlockExpr &) override {}
void visit (HIR::InlineAsm &) override {}
void visit (HIR::LlvmInlineAsm &) override {}
+ void visit (HIR::OffsetOf &) override {}
+ void visit (HIR::AnonConst &) override {}
private:
CompileExprWithBlock (Context *ctx, Bvariable *result)
diff --git a/gcc/rust/backend/rust-compile-context.cc b/gcc/rust/backend/rust-compile-context.cc
index 86f0894..349d492 100644
--- a/gcc/rust/backend/rust-compile-context.cc
+++ b/gcc/rust/backend/rust-compile-context.cc
@@ -22,9 +22,18 @@
namespace Rust {
namespace Compile {
+Context *
+Context::get ()
+{
+ static Context *instance;
+ if (instance == nullptr)
+ instance = new Context ();
+
+ return instance;
+}
+
Context::Context ()
- : resolver (Resolver::Resolver::get ()),
- tyctx (Resolver::TypeCheckContext::get ()),
+ : tyctx (Resolver::TypeCheckContext::get ()),
mappings (Analysis::Mappings::get ()), mangler (Mangler ())
{
setup_builtins ();
@@ -70,7 +79,8 @@ Context::type_hasher (tree type)
hstate.add_object (TYPE_HASH (TYPE_OFFSET_BASETYPE (type)));
break;
- case ARRAY_TYPE: {
+ case ARRAY_TYPE:
+ {
if (TYPE_DOMAIN (type))
hstate.add_object (TYPE_HASH (TYPE_DOMAIN (type)));
if (!AGGREGATE_TYPE_P (TREE_TYPE (type)))
@@ -81,7 +91,8 @@ Context::type_hasher (tree type)
}
break;
- case INTEGER_TYPE: {
+ case INTEGER_TYPE:
+ {
tree t = TYPE_MAX_VALUE (type);
if (!t)
t = TYPE_MIN_VALUE (type);
@@ -91,7 +102,8 @@ Context::type_hasher (tree type)
}
case REAL_TYPE:
- case FIXED_POINT_TYPE: {
+ case FIXED_POINT_TYPE:
+ {
unsigned prec = TYPE_PRECISION (type);
hstate.add_object (prec);
break;
@@ -103,7 +115,8 @@ Context::type_hasher (tree type)
case RECORD_TYPE:
case UNION_TYPE:
- case QUAL_UNION_TYPE: {
+ case QUAL_UNION_TYPE:
+ {
for (tree t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t))
{
hashval_t name_hash = IDENTIFIER_HASH_VALUE (DECL_NAME (t));
@@ -118,7 +131,8 @@ Context::type_hasher (tree type)
break;
case REFERENCE_TYPE:
- case POINTER_TYPE: {
+ case POINTER_TYPE:
+ {
hashval_t type_hash = type_hasher (TREE_TYPE (type));
hstate.add_object (type_hash);
}
diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h
index ce81a1d..d4a642b 100644
--- a/gcc/rust/backend/rust-compile-context.h
+++ b/gcc/rust/backend/rust-compile-context.h
@@ -49,7 +49,7 @@ struct CustomDeriveInfo
class Context
{
public:
- Context ();
+ static Context *get ();
void setup_builtins ();
@@ -90,7 +90,6 @@ public:
return type;
}
- Resolver::Resolver *get_resolver () { return resolver; }
Resolver::TypeCheckContext *get_tyctx () { return tyctx; }
Analysis::Mappings &get_mappings () { return mappings; }
@@ -391,7 +390,8 @@ public:
}
private:
- Resolver::Resolver *resolver;
+ Context ();
+
Resolver::TypeCheckContext *tyctx;
Analysis::Mappings &mappings;
Mangler mangler;
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index dd3420f..6433923 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -17,6 +17,8 @@
// <http://www.gnu.org/licenses/>.
#include "rust-compile-expr.h"
+#include "rust-backend.h"
+#include "rust-compile-type.h"
#include "rust-compile-struct-field-expr.h"
#include "rust-compile-pattern.h"
#include "rust-compile-resolve-path.h"
@@ -30,8 +32,11 @@
#include "realmpfr.h"
#include "convert.h"
#include "print-tree.h"
+#include "rust-hir-expr.h"
#include "rust-system.h"
+#include "rust-tree.h"
#include "rust-tyty.h"
+#include "tree-core.h"
namespace Rust {
namespace Compile {
@@ -375,6 +380,31 @@ CompileExpr::visit (HIR::LlvmInlineAsm &expr)
}
void
+CompileExpr::visit (HIR::OffsetOf &expr)
+{
+ TyTy::BaseType *type = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (
+ expr.get_type ().get_mappings ().get_hirid (), &type))
+ {
+ translated = error_mark_node;
+ return;
+ }
+
+ auto compiled_ty = TyTyResolveCompile::compile (ctx, type);
+
+ rust_assert (TREE_CODE (compiled_ty) == RECORD_TYPE);
+
+ // Create an identifier node for the field
+ auto field_id = Backend::get_identifier_node (expr.get_field ().as_string ());
+
+ // And now look it up and get its value for `byte_position`
+ auto field = Backend::lookup_field (compiled_ty, field_id);
+ auto field_value = TREE_VALUE (field);
+
+ translated = byte_position (field_value);
+}
+
+void
CompileExpr::visit (HIR::IfExprConseqElse &expr)
{
TyTy::BaseType *if_type = nullptr;
@@ -441,6 +471,18 @@ CompileExpr::visit (HIR::BlockExpr &expr)
}
void
+CompileExpr::visit (HIR::AnonConst &expr)
+{
+ expr.get_inner_expr ().accept_vis (*this);
+}
+
+void
+CompileExpr::visit (HIR::ConstBlock &expr)
+{
+ expr.get_const_expr ().accept_vis (*this);
+}
+
+void
CompileExpr::visit (HIR::UnsafeBlockExpr &expr)
{
expr.get_block_expr ().accept_vis (*this);
@@ -471,6 +513,8 @@ CompileExpr::visit (HIR::StructExprStructFields &struct_expr)
rust_error_at (struct_expr.get_locus (), "unknown type");
return;
}
+ if (!tyty->is<TyTy::ADTType> ())
+ return;
// it must be an ADT
rust_assert (tyty->get_kind () == TyTy::TypeKind::ADT);
@@ -669,6 +713,15 @@ void
CompileExpr::visit (HIR::LoopExpr &expr)
{
TyTy::BaseType *block_tyty = nullptr;
+ fncontext fnctx = ctx->peek_fn ();
+ if (ctx->const_context_p () && !DECL_DECLARED_CONSTEXPR_P (fnctx.fndecl))
+ {
+ rich_location r (line_table, expr.get_locus ());
+ rust_error_at (r, ErrorCode::E0658,
+ "%<loop%> is not allowed in const context");
+ return;
+ }
+
if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
&block_tyty))
{
@@ -676,7 +729,6 @@ CompileExpr::visit (HIR::LoopExpr &expr)
return;
}
- fncontext fnctx = ctx->peek_fn ();
tree enclosing_scope = ctx->peek_enclosing_scope ();
tree block_type = TyTyResolveCompile::compile (ctx, block_tyty);
@@ -701,7 +753,8 @@ CompileExpr::visit (HIR::LoopExpr &expr)
loop_label.get_lifetime ().get_mappings ().get_hirid (), label);
}
- tree loop_begin_label = Backend::label (fnctx.fndecl, "", expr.get_locus ());
+ tree loop_begin_label
+ = Backend::label (fnctx.fndecl, tl::nullopt, expr.get_locus ());
tree loop_begin_label_decl
= Backend::label_definition_statement (loop_begin_label);
ctx->add_statement (loop_begin_label_decl);
@@ -743,7 +796,8 @@ CompileExpr::visit (HIR::WhileLoopExpr &expr)
start_location, end_location);
ctx->push_block (loop_block);
- tree loop_begin_label = Backend::label (fnctx.fndecl, "", expr.get_locus ());
+ tree loop_begin_label
+ = Backend::label (fnctx.fndecl, tl::nullopt, expr.get_locus ());
tree loop_begin_label_decl
= Backend::label_definition_statement (loop_begin_label);
ctx->add_statement (loop_begin_label_decl);
@@ -787,25 +841,16 @@ CompileExpr::visit (HIR::BreakExpr &expr)
if (expr.has_label ())
{
- NodeId resolved_node_id = UNKNOWN_NODEID;
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- if (auto id
- = nr_ctx.lookup (expr.get_label ().get_mappings ().get_nodeid ()))
- resolved_node_id = *id;
- }
- else
+ NodeId resolved_node_id;
+ if (auto id
+ = nr_ctx.lookup (expr.get_label ().get_mappings ().get_nodeid ()))
{
- NodeId tmp = UNKNOWN_NODEID;
- if (ctx->get_resolver ()->lookup_resolved_label (
- expr.get_label ().get_mappings ().get_nodeid (), &tmp))
- resolved_node_id = tmp;
+ resolved_node_id = *id;
}
-
- if (resolved_node_id == UNKNOWN_NODEID)
+ else
{
rust_error_at (
expr.get_label ().get_locus (),
@@ -849,26 +894,16 @@ CompileExpr::visit (HIR::ContinueExpr &expr)
tree label = ctx->peek_loop_begin_label ();
if (expr.has_label ())
{
- NodeId resolved_node_id = UNKNOWN_NODEID;
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- if (auto id
- = nr_ctx.lookup (expr.get_label ().get_mappings ().get_nodeid ()))
- resolved_node_id = *id;
- }
- else
+ NodeId resolved_node_id;
+ if (auto id
+ = nr_ctx.lookup (expr.get_label ().get_mappings ().get_nodeid ()))
{
- NodeId tmp = UNKNOWN_NODEID;
-
- if (ctx->get_resolver ()->lookup_resolved_label (
- expr.get_label ().get_mappings ().get_nodeid (), &tmp))
- resolved_node_id = tmp;
+ resolved_node_id = *id;
}
-
- if (resolved_node_id == UNKNOWN_NODEID)
+ else
{
rust_error_at (
expr.get_label ().get_locus (),
@@ -1130,9 +1165,8 @@ CompileExpr::visit (HIR::MatchExpr &expr)
// setup the end label so the cases can exit properly
tree fndecl = fnctx.fndecl;
location_t end_label_locus = expr.get_locus (); // FIXME
- tree end_label
- = Backend::label (fndecl, "" /* empty creates an artificial label */,
- end_label_locus);
+ // tl::nullopt creates an artificial label
+ tree end_label = Backend::label (fndecl, tl::nullopt, end_label_locus);
tree end_label_decl_statement
= Backend::label_definition_statement (end_label);
@@ -1325,6 +1359,28 @@ CompileExpr::visit (HIR::CallExpr &expr)
};
auto fn_address = CompileExpr::Compile (expr.get_fnexpr (), ctx);
+ if (ctx->const_context_p ())
+ {
+ if (!FUNCTION_POINTER_TYPE_P (TREE_TYPE (fn_address)))
+ {
+ rust_error_at (expr.get_locus (),
+ "calls in constants are limited to constant "
+ "functions, tuple structs and tuple variants");
+ return;
+ }
+
+ if (TREE_CODE (fn_address) == ADDR_EXPR)
+ {
+ tree fndecl = TREE_OPERAND (fn_address, 0);
+ if (!DECL_DECLARED_CONSTEXPR_P (fndecl))
+ {
+ rust_error_at (expr.get_locus (),
+ "calls in constants are limited to constant "
+ "functions, tuple structs and tuple variants");
+ return;
+ }
+ }
+ }
// is this a closure call?
bool possible_trait_call
@@ -1883,7 +1939,8 @@ CompileExpr::visit (HIR::ArrayExpr &expr)
HIR::ArrayElems &elements = expr.get_internal_elements ();
switch (elements.get_array_expr_type ())
{
- case HIR::ArrayElems::ArrayExprType::VALUES: {
+ case HIR::ArrayElems::ArrayExprType::VALUES:
+ {
HIR::ArrayElemsValues &elems
= static_cast<HIR::ArrayElemsValues &> (elements);
translated
@@ -2032,7 +2089,8 @@ HIRCompileBase::resolve_adjustements (
return error_mark_node;
case Resolver::Adjustment::AdjustmentType::IMM_REF:
- case Resolver::Adjustment::AdjustmentType::MUT_REF: {
+ case Resolver::Adjustment::AdjustmentType::MUT_REF:
+ {
if (!RS_DST_FLAG (TREE_TYPE (e)))
{
e = address_expression (e, locus);
@@ -2474,23 +2532,12 @@ CompileExpr::generate_closure_function (HIR::ClosureExpr &expr,
if (is_block_expr)
{
auto body_mappings = function_body.get_mappings ();
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- auto candidate = nr_ctx.values.to_rib (body_mappings.get_nodeid ());
+ auto candidate = nr_ctx.values.to_rib (body_mappings.get_nodeid ());
- rust_assert (candidate.has_value ());
- }
- else
- {
- Resolver::Rib *rib = nullptr;
- bool ok
- = ctx->get_resolver ()->find_name_rib (body_mappings.get_nodeid (),
- &rib);
- rust_assert (ok);
- }
+ rust_assert (candidate.has_value ());
}
tree enclosing_scope = NULL_TREE;
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h
index 65ed4b3..b8b4e8d 100644
--- a/gcc/rust/backend/rust-compile-expr.h
+++ b/gcc/rust/backend/rust-compile-expr.h
@@ -48,6 +48,8 @@ public:
void visit (HIR::IfExpr &expr) override;
void visit (HIR::IfExprConseqElse &expr) override;
void visit (HIR::BlockExpr &expr) override;
+ void visit (HIR::AnonConst &expr) override;
+ void visit (HIR::ConstBlock &expr) override;
void visit (HIR::UnsafeBlockExpr &expr) override;
void visit (HIR::StructExprStruct &struct_expr) override;
void visit (HIR::StructExprStructFields &struct_expr) override;
@@ -70,6 +72,7 @@ public:
void visit (HIR::ClosureExpr &expr) override;
void visit (HIR::InlineAsm &expr) override;
void visit (HIR::LlvmInlineAsm &expr) override;
+ void visit (HIR::OffsetOf &expr) override;
// TODO
void visit (HIR::ErrorPropagationExpr &) override {}
diff --git a/gcc/rust/backend/rust-compile-implitem.cc b/gcc/rust/backend/rust-compile-implitem.cc
index 1230c85..63df2f5 100644
--- a/gcc/rust/backend/rust-compile-implitem.cc
+++ b/gcc/rust/backend/rust-compile-implitem.cc
@@ -27,22 +27,11 @@ CompileTraitItem::visit (HIR::TraitItemConst &constant)
rust_assert (concrete != nullptr);
TyTy::BaseType *resolved_type = concrete;
- tl::optional<Resolver::CanonicalPath> canonical_path;
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- canonical_path = nr_ctx.values.to_canonical_path (
- constant.get_mappings ().get_nodeid ());
- }
- else
- {
- canonical_path = ctx->get_mappings ().lookup_canonical_path (
- constant.get_mappings ().get_nodeid ());
- }
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- rust_assert (canonical_path);
+ Resolver::CanonicalPath canonical_path
+ = nr_ctx.to_canonical_path (constant.get_mappings ().get_nodeid ());
HIR::Expr &const_value_expr = constant.get_expr ();
TyTy::BaseType *expr_type = nullptr;
@@ -52,7 +41,7 @@ CompileTraitItem::visit (HIR::TraitItemConst &constant)
tree const_expr
= compile_constant_item (constant.get_mappings ().get_hirid (), expr_type,
- resolved_type, *canonical_path, const_value_expr,
+ resolved_type, canonical_path, const_value_expr,
constant.get_locus (),
const_value_expr.get_locus ());
ctx->push_const (const_expr);
@@ -96,22 +85,11 @@ CompileTraitItem::visit (HIR::TraitItemFunc &func)
fntype->override_context ();
}
- tl::optional<Resolver::CanonicalPath> canonical_path;
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- canonical_path
- = nr_ctx.values.to_canonical_path (func.get_mappings ().get_nodeid ());
- }
- else
- {
- canonical_path = ctx->get_mappings ().lookup_canonical_path (
- func.get_mappings ().get_nodeid ());
- }
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- rust_assert (canonical_path);
+ Resolver::CanonicalPath canonical_path
+ = nr_ctx.to_canonical_path (func.get_mappings ().get_nodeid ());
// FIXME: How do we get the proper visibility here?
auto vis = HIR::Visibility (HIR::Visibility::VisType::PUBLIC);
@@ -121,7 +99,7 @@ CompileTraitItem::visit (HIR::TraitItemFunc &func)
function.get_self (), function.get_function_params (),
function.get_qualifiers (), vis,
func.get_outer_attrs (), func.get_locus (),
- &func.get_block_expr (), *canonical_path, fntype);
+ &func.get_block_expr (), canonical_path, fntype);
reference = address_expression (fndecl, ref_locus);
}
diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc
index 4888e23..450a869 100644
--- a/gcc/rust/backend/rust-compile-intrinsic.cc
+++ b/gcc/rust/backend/rust-compile-intrinsic.cc
@@ -32,8 +32,7 @@
// declaration taken from "stringpool.h"
// the get_identifier macro causes compilation issues
-extern tree
-get_identifier (const char *);
+extern tree get_identifier (const char *);
namespace Rust {
namespace Compile {
@@ -70,28 +69,19 @@ check_for_basic_integer_type (const std::string &intrinsic_str,
return is_basic_integer;
}
-static tree
-offset_handler (Context *ctx, TyTy::FnType *fntype);
-static tree
-sizeof_handler (Context *ctx, TyTy::FnType *fntype);
-static tree
-transmute_handler (Context *ctx, TyTy::FnType *fntype);
-static tree
-rotate_handler (Context *ctx, TyTy::FnType *fntype, tree_code op);
-static tree
-wrapping_op_handler_inner (Context *ctx, TyTy::FnType *fntype, tree_code op);
-static tree
-op_with_overflow_inner (Context *ctx, TyTy::FnType *fntype, tree_code op);
-static tree
-uninit_handler (Context *ctx, TyTy::FnType *fntype);
-static tree
-move_val_init_handler (Context *ctx, TyTy::FnType *fntype);
-static tree
-assume_handler (Context *ctx, TyTy::FnType *fntype);
-static tree
-discriminant_value_handler (Context *ctx, TyTy::FnType *fntype);
-static tree
-variant_count_handler (Context *ctx, TyTy::FnType *fntype);
+static tree offset_handler (Context *ctx, TyTy::FnType *fntype);
+static tree sizeof_handler (Context *ctx, TyTy::FnType *fntype);
+static tree transmute_handler (Context *ctx, TyTy::FnType *fntype);
+static tree rotate_handler (Context *ctx, TyTy::FnType *fntype, tree_code op);
+static tree wrapping_op_handler_inner (Context *ctx, TyTy::FnType *fntype,
+ tree_code op);
+static tree op_with_overflow_inner (Context *ctx, TyTy::FnType *fntype,
+ tree_code op);
+static tree uninit_handler (Context *ctx, TyTy::FnType *fntype);
+static tree move_val_init_handler (Context *ctx, TyTy::FnType *fntype);
+static tree assume_handler (Context *ctx, TyTy::FnType *fntype);
+static tree discriminant_value_handler (Context *ctx, TyTy::FnType *fntype);
+static tree variant_count_handler (Context *ctx, TyTy::FnType *fntype);
enum class Prefetch
{
@@ -99,8 +89,8 @@ enum class Prefetch
Write
};
-static tree
-prefetch_data_handler (Context *ctx, TyTy::FnType *fntype, Prefetch kind);
+static tree prefetch_data_handler (Context *ctx, TyTy::FnType *fntype,
+ Prefetch kind);
static inline tree
rotate_left_handler (Context *ctx, TyTy::FnType *fntype)
@@ -140,10 +130,10 @@ prefetch_write_data (Context *ctx, TyTy::FnType *fntype)
return prefetch_data_handler (ctx, fntype, Prefetch::Write);
}
-static tree
-atomic_store_handler_inner (Context *ctx, TyTy::FnType *fntype, int ordering);
-static tree
-atomic_load_handler_inner (Context *ctx, TyTy::FnType *fntype, int ordering);
+static tree atomic_store_handler_inner (Context *ctx, TyTy::FnType *fntype,
+ int ordering);
+static tree atomic_load_handler_inner (Context *ctx, TyTy::FnType *fntype,
+ int ordering);
static inline std::function<tree (Context *, TyTy::FnType *)>
atomic_store_handler (int ordering)
@@ -161,8 +151,8 @@ atomic_load_handler (int ordering)
};
}
-static inline tree
-unchecked_op_inner (Context *ctx, TyTy::FnType *fntype, tree_code op);
+static inline tree unchecked_op_inner (Context *ctx, TyTy::FnType *fntype,
+ tree_code op);
const static std::function<tree (Context *, TyTy::FnType *)>
unchecked_op_handler (tree_code op)
@@ -172,8 +162,8 @@ unchecked_op_handler (tree_code op)
};
}
-static inline tree
-copy_handler_inner (Context *ctx, TyTy::FnType *fntype, bool overlaps);
+static inline tree copy_handler_inner (Context *ctx, TyTy::FnType *fntype,
+ bool overlaps);
const static std::function<tree (Context *, TyTy::FnType *)>
copy_handler (bool overlaps)
@@ -183,8 +173,8 @@ copy_handler (bool overlaps)
};
}
-static inline tree
-expect_handler_inner (Context *ctx, TyTy::FnType *fntype, bool likely);
+static inline tree expect_handler_inner (Context *ctx, TyTy::FnType *fntype,
+ bool likely);
const static std::function<tree (Context *, TyTy::FnType *)>
expect_handler (bool likely)
@@ -194,8 +184,8 @@ expect_handler (bool likely)
};
}
-static tree
-try_handler_inner (Context *ctx, TyTy::FnType *fntype, bool is_new_api);
+static tree try_handler_inner (Context *ctx, TyTy::FnType *fntype,
+ bool is_new_api);
const static std::function<tree (Context *, TyTy::FnType *)>
try_handler (bool is_new_api)
@@ -447,8 +437,8 @@ sizeof_handler (Context *ctx, TyTy::FnType *fntype)
// get the template parameter type tree fn size_of<T>();
rust_assert (fntype->get_num_substitutions () == 1);
auto &param_mapping = fntype->get_substs ().at (0);
- const TyTy::ParamType *param_tyty = param_mapping.get_param_ty ();
- TyTy::BaseType *resolved_tyty = param_tyty->resolve ();
+ const auto param_tyty = param_mapping.get_param_ty ();
+ auto resolved_tyty = param_tyty->resolve ();
tree template_parameter_type
= TyTyResolveCompile::compile (ctx, resolved_tyty);
@@ -653,8 +643,8 @@ op_with_overflow_inner (Context *ctx, TyTy::FnType *fntype, tree_code op)
rust_assert (fntype->get_num_substitutions () == 1);
auto &param_mapping = fntype->get_substs ().at (0);
- const TyTy::ParamType *param_tyty = param_mapping.get_param_ty ();
- TyTy::BaseType *resolved_tyty = param_tyty->resolve ();
+ const auto param_tyty = param_mapping.get_param_ty ();
+ auto resolved_tyty = param_tyty->resolve ();
tree template_parameter_type
= TyTyResolveCompile::compile (ctx, resolved_tyty);
@@ -1089,8 +1079,8 @@ uninit_handler (Context *ctx, TyTy::FnType *fntype)
// get the template parameter type tree fn uninit<T>();
rust_assert (fntype->get_num_substitutions () == 1);
auto &param_mapping = fntype->get_substs ().at (0);
- const TyTy::ParamType *param_tyty = param_mapping.get_param_ty ();
- TyTy::BaseType *resolved_tyty = param_tyty->resolve ();
+ const auto param_tyty = param_mapping.get_param_ty ();
+ auto resolved_tyty = param_tyty->resolve ();
tree template_parameter_type
= TyTyResolveCompile::compile (ctx, resolved_tyty);
@@ -1154,8 +1144,8 @@ move_val_init_handler (Context *ctx, TyTy::FnType *fntype)
// get the template parameter type tree fn size_of<T>();
rust_assert (fntype->get_num_substitutions () == 1);
auto &param_mapping = fntype->get_substs ().at (0);
- const TyTy::ParamType *param_tyty = param_mapping.get_param_ty ();
- TyTy::BaseType *resolved_tyty = param_tyty->resolve ();
+ auto param_tyty = param_mapping.get_param_ty ();
+ auto resolved_tyty = param_tyty->resolve ();
tree template_parameter_type
= TyTyResolveCompile::compile (ctx, resolved_tyty);
diff --git a/gcc/rust/backend/rust-compile-item.cc b/gcc/rust/backend/rust-compile-item.cc
index 9666990..b72e70d 100644
--- a/gcc/rust/backend/rust-compile-item.cc
+++ b/gcc/rust/backend/rust-compile-item.cc
@@ -50,33 +50,21 @@ CompileItem::visit (HIR::StaticItem &var)
tree type = TyTyResolveCompile::compile (ctx, resolved_type);
- tl::optional<Resolver::CanonicalPath> canonical_path;
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- canonical_path
- = nr_ctx.values.to_canonical_path (var.get_mappings ().get_nodeid ());
- }
- else
- {
- canonical_path = ctx->get_mappings ().lookup_canonical_path (
- var.get_mappings ().get_nodeid ());
- }
-
- rust_assert (canonical_path.has_value ());
+ Resolver::CanonicalPath canonical_path
+ = nr_ctx.to_canonical_path (var.get_mappings ().get_nodeid ());
ctx->push_const_context ();
tree value
= compile_constant_item (var.get_mappings ().get_hirid (), expr_type,
- resolved_type, *canonical_path, const_value_expr,
+ resolved_type, canonical_path, const_value_expr,
var.get_locus (), const_value_expr.get_locus ());
ctx->pop_const_context ();
- std::string name = canonical_path->get ();
- std::string asm_name = ctx->mangle_item (resolved_type, *canonical_path);
+ std::string name = canonical_path.get ();
+ std::string asm_name = ctx->mangle_item (resolved_type, canonical_path);
bool is_external = false;
bool is_hidden = false;
@@ -115,24 +103,12 @@ CompileItem::visit (HIR::ConstantItem &constant)
const_value_expr.get_mappings ().get_hirid (), &expr_type);
rust_assert (ok);
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
+
// canonical path
Resolver::CanonicalPath canonical_path
- = Resolver::CanonicalPath::create_empty ();
-
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- canonical_path
- = nr_ctx.values.to_canonical_path (mappings.get_nodeid ()).value ();
- }
- else
- {
- canonical_path = ctx->get_mappings ()
- .lookup_canonical_path (mappings.get_nodeid ())
- .value ();
- }
+ = nr_ctx.to_canonical_path (mappings.get_nodeid ());
ctx->push_const_context ();
tree const_expr
@@ -210,26 +186,11 @@ CompileItem::visit (HIR::Function &function)
}
}
- Resolver::CanonicalPath canonical_path
- = Resolver::CanonicalPath::create_empty ();
-
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- auto path = nr_ctx.values.to_canonical_path (
- function.get_mappings ().get_nodeid ());
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- canonical_path = path.value ();
- }
- else
- {
- auto path = ctx->get_mappings ().lookup_canonical_path (
- function.get_mappings ().get_nodeid ());
-
- canonical_path = *path;
- }
+ Resolver::CanonicalPath canonical_path
+ = nr_ctx.to_canonical_path (function.get_mappings ().get_nodeid ());
const std::string asm_name = ctx->mangle_item (fntype, canonical_path);
@@ -300,5 +261,65 @@ CompileItem::visit (HIR::Module &module)
CompileItem::compile (item.get (), ctx);
}
+void
+CompileItem::visit (HIR::TupleStruct &tuple_struct_decl)
+{
+ TyTy::BaseType *lookup = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (
+ tuple_struct_decl.get_mappings ().get_hirid (), &lookup))
+ {
+ rust_error_at (tuple_struct_decl.get_locus (), "failed to resolve type");
+ return;
+ }
+
+ if (lookup->is_concrete ())
+ TyTyResolveCompile::compile (ctx, lookup);
+}
+
+void
+CompileItem::visit (HIR::Enum &enum_decl)
+{
+ TyTy::BaseType *lookup = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (enum_decl.get_mappings ().get_hirid (),
+ &lookup))
+ {
+ rust_error_at (enum_decl.get_locus (), "failed to resolve type");
+ return;
+ }
+
+ if (lookup->is_concrete ())
+ TyTyResolveCompile::compile (ctx, lookup);
+}
+
+void
+CompileItem::visit (HIR::Union &union_decl)
+{
+ TyTy::BaseType *lookup = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (union_decl.get_mappings ().get_hirid (),
+ &lookup))
+ {
+ rust_error_at (union_decl.get_locus (), "failed to resolve type");
+ return;
+ }
+
+ if (lookup->is_concrete ())
+ TyTyResolveCompile::compile (ctx, lookup);
+}
+
+void
+CompileItem::visit (HIR::StructStruct &struct_decl)
+{
+ TyTy::BaseType *lookup = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (struct_decl.get_mappings ().get_hirid (),
+ &lookup))
+ {
+ rust_error_at (struct_decl.get_locus (), "failed to resolve type");
+ return;
+ }
+
+ if (lookup->is_concrete ())
+ TyTyResolveCompile::compile (ctx, lookup);
+}
+
} // namespace Compile
} // namespace Rust
diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h
index d9d946d..56baaab 100644
--- a/gcc/rust/backend/rust-compile-item.h
+++ b/gcc/rust/backend/rust-compile-item.h
@@ -44,9 +44,12 @@ public:
void visit (HIR::ImplBlock &impl_block) override;
void visit (HIR::ExternBlock &extern_block) override;
void visit (HIR::Module &module) override;
+ void visit (HIR::TupleStruct &tuple_struct) override;
+ void visit (HIR::Enum &enum_decl) override;
+ void visit (HIR::Union &union_decl) override;
+ void visit (HIR::StructStruct &struct_decl) override;
// Empty visit for unused Stmt HIR nodes.
- void visit (HIR::TupleStruct &) override {}
void visit (HIR::EnumItem &) override {}
void visit (HIR::EnumItemTuple &) override {}
void visit (HIR::EnumItemStruct &) override {}
@@ -57,9 +60,6 @@ public:
void visit (HIR::ExternCrate &) override {}
void visit (HIR::UseDeclaration &) override {}
void visit (HIR::TypeAlias &) override {}
- void visit (HIR::StructStruct &) override {}
- void visit (HIR::Enum &) override {}
- void visit (HIR::Union &) override {}
void visit (HIR::Trait &) override {}
void visit (HIR::EmptyStmt &) override {}
void visit (HIR::LetStmt &) override {}
diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc
index e83717b..fe65921 100644
--- a/gcc/rust/backend/rust-compile-pattern.cc
+++ b/gcc/rust/backend/rust-compile-pattern.cc
@@ -22,6 +22,11 @@
#include "rust-constexpr.h"
#include "rust-compile-type.h"
#include "print-tree.h"
+#include "rust-diagnostics.h"
+#include "rust-hir-pattern-abstract.h"
+#include "rust-hir-pattern.h"
+#include "rust-system.h"
+#include "rust-tyty.h"
namespace Rust {
namespace Compile {
@@ -107,7 +112,8 @@ compile_range_pattern_bound (HIR::RangePatternBound &bound,
tree result = NULL_TREE;
switch (bound.get_bound_type ())
{
- case HIR::RangePatternBound::RangePatternBoundType::LITERAL: {
+ case HIR::RangePatternBound::RangePatternBoundType::LITERAL:
+ {
auto &ref = static_cast<HIR::RangePatternBoundLiteral &> (bound);
HIR::LiteralExpr litexpr (mappings, ref.get_literal (), locus,
@@ -117,7 +123,8 @@ compile_range_pattern_bound (HIR::RangePatternBound &bound,
}
break;
- case HIR::RangePatternBound::RangePatternBoundType::PATH: {
+ case HIR::RangePatternBound::RangePatternBoundType::PATH:
+ {
auto &ref = static_cast<HIR::RangePatternBoundPath &> (bound);
result = ResolvePathRef::Compile (ref.get_path (), ctx);
@@ -127,7 +134,8 @@ compile_range_pattern_bound (HIR::RangePatternBound &bound,
}
break;
- case HIR::RangePatternBound::RangePatternBoundType::QUALPATH: {
+ case HIR::RangePatternBound::RangePatternBoundType::QUALPATH:
+ {
auto &ref = static_cast<HIR::RangePatternBoundQualPath &> (bound);
result = ResolvePathRef::Compile (ref.get_qualified_path (), ctx);
@@ -204,6 +212,7 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern)
rust_assert (adt->number_of_variants () > 0);
TyTy::VariantDef *variant = nullptr;
+ tree variant_accesser_expr = nullptr;
if (adt->is_enum ())
{
// lookup the variant
@@ -218,9 +227,7 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern)
// find expected discriminant
// // need to access qualifier the field, if we use QUAL_UNION_TYPE this
- // // would be DECL_QUALIFIER i think. For now this will just access the
- // // first record field and its respective qualifier because it will
- // // always be set because this is all a big special union
+ // // would be DECL_QUALIFIER i think.
HIR::Expr &discrim_expr = variant->get_discriminant ();
tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx);
@@ -229,6 +236,14 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern)
= Backend::struct_field_expression (match_scrutinee_expr, 0,
pattern.get_path ().get_locus ());
+ // access variant data
+ tree scrutinee_union_expr
+ = Backend::struct_field_expression (match_scrutinee_expr, 1,
+ pattern.get_path ().get_locus ());
+ variant_accesser_expr
+ = Backend::struct_field_expression (scrutinee_union_expr, variant_index,
+ pattern.get_path ().get_locus ());
+
check_expr
= Backend::comparison_expression (ComparisonOperator::EQUAL,
scrutinee_expr_qualifier_expr,
@@ -240,6 +255,7 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern)
else
{
variant = adt->get_variants ().at (0);
+ variant_accesser_expr = match_scrutinee_expr;
check_expr = boolean_true_node;
}
@@ -248,13 +264,15 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern)
{
switch (field->get_item_type ())
{
- case HIR::StructPatternField::ItemType::TUPLE_PAT: {
+ case HIR::StructPatternField::ItemType::TUPLE_PAT:
+ {
// TODO
rust_unreachable ();
}
break;
- case HIR::StructPatternField::ItemType::IDENT_PAT: {
+ case HIR::StructPatternField::ItemType::IDENT_PAT:
+ {
HIR::StructPatternFieldIdentPat &ident
= static_cast<HIR::StructPatternFieldIdentPat &> (*field.get ());
@@ -263,11 +281,8 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern)
nullptr, &offs);
rust_assert (ok);
- // we may be offsetting by + 1 here since the first field in the
- // record is always the discriminator
- offs += adt->is_enum ();
tree field_expr
- = Backend::struct_field_expression (match_scrutinee_expr, offs,
+ = Backend::struct_field_expression (variant_accesser_expr, offs,
ident.get_locus ());
tree check_expr_sub
@@ -279,7 +294,8 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern)
}
break;
- case HIR::StructPatternField::ItemType::IDENT: {
+ case HIR::StructPatternField::ItemType::IDENT:
+ {
// ident pattern always matches - do nothing
}
break;
@@ -338,44 +354,70 @@ CompilePatternCheckExpr::visit (HIR::TupleStructPattern &pattern)
HIR::TupleStructItems &items = pattern.get_items ();
switch (items.get_item_type ())
{
- case HIR::TupleStructItems::RANGED: {
+ case HIR::TupleStructItems::RANGED:
+ {
// TODO
rust_unreachable ();
}
break;
- case HIR::TupleStructItems::MULTIPLE: {
+ case HIR::TupleStructItems::MULTIPLE:
+ {
HIR::TupleStructItemsNoRange &items_no_range
= static_cast<HIR::TupleStructItemsNoRange &> (items);
rust_assert (items_no_range.get_patterns ().size ()
== variant->num_fields ());
- size_t tuple_field_index = 0;
- for (auto &pattern : items_no_range.get_patterns ())
+ if (adt->is_enum ())
{
- // find payload union field of scrutinee
- tree payload_ref
- = Backend::struct_field_expression (match_scrutinee_expr, 1,
- pattern->get_locus ());
+ size_t tuple_field_index = 0;
+ for (auto &pattern : items_no_range.get_patterns ())
+ {
+ // find payload union field of scrutinee
+ tree payload_ref
+ = Backend::struct_field_expression (match_scrutinee_expr, 1,
+ pattern->get_locus ());
- tree variant_ref
- = Backend::struct_field_expression (payload_ref, variant_index,
- pattern->get_locus ());
+ tree variant_ref
+ = Backend::struct_field_expression (payload_ref,
+ variant_index,
+ pattern->get_locus ());
- tree field_expr
- = Backend::struct_field_expression (variant_ref,
- tuple_field_index++,
- pattern->get_locus ());
+ tree field_expr
+ = Backend::struct_field_expression (variant_ref,
+ tuple_field_index++,
+ pattern->get_locus ());
- tree check_expr_sub
- = CompilePatternCheckExpr::Compile (*pattern, field_expr, ctx);
- check_expr = Backend::arithmetic_or_logical_expression (
- ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
- check_expr_sub, pattern->get_locus ());
+ tree check_expr_sub
+ = CompilePatternCheckExpr::Compile (*pattern, field_expr,
+ ctx);
+ check_expr = Backend::arithmetic_or_logical_expression (
+ ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
+ check_expr_sub, pattern->get_locus ());
+ }
}
+ else
+ {
+ // For non-enum TupleStructPatterns
+ size_t tuple_field_index = 0;
+ for (auto &pattern : items_no_range.get_patterns ())
+ {
+ tree field_expr
+ = Backend::struct_field_expression (match_scrutinee_expr,
+ tuple_field_index++,
+ pattern->get_locus ());
+
+ tree check_expr_sub
+ = CompilePatternCheckExpr::Compile (*pattern, field_expr,
+ ctx);
+ check_expr = Backend::arithmetic_or_logical_expression (
+ ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
+ check_expr_sub, pattern->get_locus ());
+ }
+ }
+ break;
}
- break;
}
}
@@ -386,13 +428,57 @@ CompilePatternCheckExpr::visit (HIR::TuplePattern &pattern)
switch (pattern.get_items ().get_item_type ())
{
- case HIR::TuplePatternItems::RANGED: {
- // TODO
- gcc_unreachable ();
+ case HIR::TuplePatternItems::RANGED:
+ {
+ auto &items
+ = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ());
+ size_t tuple_field_index = 0;
+
+ // lookup the type to find out number of fields
+ TyTy::BaseType *ty = nullptr;
+ bool ok = ctx->get_tyctx ()->lookup_type (
+ pattern.get_mappings ().get_hirid (), &ty);
+ rust_assert (ok);
+ rust_assert (ty->get_kind () == TyTy::TypeKind::TUPLE);
+
+ // compile check expr for lower patterns
+ for (auto &pat : items.get_lower_patterns ())
+ {
+ tree field_expr
+ = Backend::struct_field_expression (match_scrutinee_expr,
+ tuple_field_index++,
+ pat->get_locus ());
+
+ tree check_expr_sub
+ = CompilePatternCheckExpr::Compile (*pat, field_expr, ctx);
+ check_expr = Backend::arithmetic_or_logical_expression (
+ ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
+ check_expr_sub, pat->get_locus ());
+ }
+
+ // skip the fields that are not checked
+ tuple_field_index = static_cast<TyTy::TupleType &> (*ty).num_fields ()
+ - items.get_upper_patterns ().size ();
+
+ // compile check expr for upper patterns
+ for (auto &pat : items.get_upper_patterns ())
+ {
+ tree field_expr
+ = Backend::struct_field_expression (match_scrutinee_expr,
+ tuple_field_index++,
+ pat->get_locus ());
+
+ tree check_expr_sub
+ = CompilePatternCheckExpr::Compile (*pat, field_expr, ctx);
+ check_expr = Backend::arithmetic_or_logical_expression (
+ ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
+ check_expr_sub, pat->get_locus ());
+ }
}
break;
- case HIR::TuplePatternItems::MULTIPLE: {
+ case HIR::TuplePatternItems::MULTIPLE:
+ {
auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
pattern.get_items ());
size_t tuple_field_index = 0;
@@ -414,6 +500,99 @@ CompilePatternCheckExpr::visit (HIR::TuplePattern &pattern)
}
}
+void
+CompilePatternCheckExpr::visit (HIR::IdentifierPattern &pattern)
+{
+ if (pattern.has_subpattern ())
+ {
+ check_expr = CompilePatternCheckExpr::Compile (pattern.get_subpattern (),
+ match_scrutinee_expr, ctx);
+ }
+ else
+ {
+ check_expr = boolean_true_node;
+ }
+}
+
+void
+CompilePatternCheckExpr::visit (HIR::SlicePattern &pattern)
+{
+ check_expr = boolean_true_node;
+
+ // lookup the type
+ TyTy::BaseType *lookup = nullptr;
+ bool ok
+ = ctx->get_tyctx ()->lookup_type (pattern.get_mappings ().get_hirid (),
+ &lookup);
+ rust_assert (ok);
+
+ // pattern must either be ArrayType or SliceType, should be already confirmed
+ // by type checking
+ rust_assert (lookup->get_kind () == TyTy::TypeKind::ARRAY
+ || lookup->get_kind () == TyTy::TypeKind::SLICE
+ || lookup->get_kind () == TyTy::REF);
+
+ size_t array_element_index = 0;
+ switch (lookup->get_kind ())
+ {
+ case TyTy::TypeKind::ARRAY:
+ for (auto &pattern_member : pattern.get_items ())
+ {
+ tree array_index_tree
+ = Backend::size_constant_expression (array_element_index++);
+ tree element_expr
+ = Backend::array_index_expression (match_scrutinee_expr,
+ array_index_tree,
+ pattern.get_locus ());
+ tree check_expr_sub
+ = CompilePatternCheckExpr::Compile (*pattern_member, element_expr,
+ ctx);
+ check_expr = Backend::arithmetic_or_logical_expression (
+ ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
+ check_expr_sub, pattern.get_locus ());
+ }
+ break;
+ case TyTy::TypeKind::SLICE:
+ rust_sorry_at (
+ pattern.get_locus (),
+ "SlicePattern matching against non-ref slices are not yet supported");
+ break;
+ case TyTy::TypeKind::REF:
+ {
+ rust_assert (RS_DST_FLAG_P (TREE_TYPE (match_scrutinee_expr)));
+ tree size_field
+ = Backend::struct_field_expression (match_scrutinee_expr, 1,
+ pattern.get_locus ());
+
+ // First compare the size
+ check_expr = Backend::comparison_expression (
+ ComparisonOperator::EQUAL, size_field,
+ build_int_cst (size_type_node, pattern.get_items ().size ()),
+ pattern.get_locus ());
+
+ // Then compare each element in the slice pattern
+ for (auto &pattern_member : pattern.get_items ())
+ {
+ tree slice_index_tree
+ = Backend::size_constant_expression (array_element_index++);
+ tree element_expr
+ = Backend::slice_index_expression (match_scrutinee_expr,
+ slice_index_tree,
+ pattern.get_locus ());
+ tree check_expr_sub
+ = CompilePatternCheckExpr::Compile (*pattern_member, element_expr,
+ ctx);
+ check_expr = Backend::arithmetic_or_logical_expression (
+ ArithmeticOrLogicalOperator::BITWISE_AND, check_expr,
+ check_expr_sub, pattern.get_locus ());
+ }
+ }
+ break;
+ default:
+ rust_unreachable ();
+ }
+}
+
// setup the bindings
void
@@ -449,13 +628,15 @@ CompilePatternBindings::visit (HIR::TupleStructPattern &pattern)
HIR::TupleStructItems &items = pattern.get_items ();
switch (items.get_item_type ())
{
- case HIR::TupleStructItems::RANGED: {
+ case HIR::TupleStructItems::RANGED:
+ {
// TODO
rust_unreachable ();
}
break;
- case HIR::TupleStructItems::MULTIPLE: {
+ case HIR::TupleStructItems::MULTIPLE:
+ {
HIR::TupleStructItemsNoRange &items_no_range
= static_cast<HIR::TupleStructItemsNoRange &> (items);
@@ -504,6 +685,71 @@ CompilePatternBindings::visit (HIR::TupleStructPattern &pattern)
}
}
+tree
+CompilePatternBindings::make_struct_access (TyTy::ADTType *adt,
+ TyTy::VariantDef *variant,
+ const Identifier &ident,
+ int variant_index)
+{
+ size_t offs = 0;
+ auto ok = variant->lookup_field (ident.as_string (), nullptr, &offs);
+ rust_assert (ok);
+
+ if (adt->is_enum ())
+ {
+ tree payload_accessor_union
+ = Backend::struct_field_expression (match_scrutinee_expr, 1,
+ ident.get_locus ());
+
+ tree variant_accessor
+ = Backend::struct_field_expression (payload_accessor_union,
+ variant_index, ident.get_locus ());
+
+ return Backend::struct_field_expression (variant_accessor, offs,
+ ident.get_locus ());
+ }
+ else
+ {
+ tree variant_accessor = match_scrutinee_expr;
+
+ return Backend::struct_field_expression (variant_accessor, offs,
+ ident.get_locus ());
+ }
+}
+
+void
+CompilePatternBindings::handle_struct_pattern_ident (
+ HIR::StructPatternField &pat, TyTy::ADTType *adt, TyTy::VariantDef *variant,
+ int variant_index)
+{
+ HIR::StructPatternFieldIdent &ident
+ = static_cast<HIR::StructPatternFieldIdent &> (pat);
+
+ auto identifier = ident.get_identifier ();
+ tree binding = make_struct_access (adt, variant, identifier, variant_index);
+
+ ctx->insert_pattern_binding (ident.get_mappings ().get_hirid (), binding);
+}
+
+void
+CompilePatternBindings::handle_struct_pattern_ident_pat (
+ HIR::StructPatternField &pat, TyTy::ADTType *adt, TyTy::VariantDef *variant,
+ int variant_index)
+{
+ auto &pattern = static_cast<HIR::StructPatternFieldIdentPat &> (pat);
+
+ tree binding = make_struct_access (adt, variant, pattern.get_identifier (),
+ variant_index);
+ CompilePatternBindings::Compile (pattern.get_pattern (), binding, ctx);
+}
+
+void
+CompilePatternBindings::handle_struct_pattern_tuple_pat (
+ HIR::StructPatternField &pat)
+{
+ rust_unreachable ();
+}
+
void
CompilePatternBindings::visit (HIR::StructPattern &pattern)
{
@@ -539,54 +785,14 @@ CompilePatternBindings::visit (HIR::StructPattern &pattern)
{
switch (field->get_item_type ())
{
- case HIR::StructPatternField::ItemType::TUPLE_PAT: {
- // TODO
- rust_unreachable ();
- }
+ case HIR::StructPatternField::ItemType::TUPLE_PAT:
+ handle_struct_pattern_tuple_pat (*field);
break;
-
- case HIR::StructPatternField::ItemType::IDENT_PAT: {
- // TODO
- rust_unreachable ();
- }
+ case HIR::StructPatternField::ItemType::IDENT_PAT:
+ handle_struct_pattern_ident_pat (*field, adt, variant, variant_index);
break;
-
- case HIR::StructPatternField::ItemType::IDENT: {
- HIR::StructPatternFieldIdent &ident
- = static_cast<HIR::StructPatternFieldIdent &> (*field.get ());
-
- size_t offs = 0;
- ok = variant->lookup_field (ident.get_identifier ().as_string (),
- nullptr, &offs);
- rust_assert (ok);
-
- tree binding = error_mark_node;
- if (adt->is_enum ())
- {
- tree payload_accessor_union
- = Backend::struct_field_expression (match_scrutinee_expr, 1,
- ident.get_locus ());
-
- tree variant_accessor
- = Backend::struct_field_expression (payload_accessor_union,
- variant_index,
- ident.get_locus ());
-
- binding
- = Backend::struct_field_expression (variant_accessor, offs,
- ident.get_locus ());
- }
- else
- {
- tree variant_accessor = match_scrutinee_expr;
- binding
- = Backend::struct_field_expression (variant_accessor, offs,
- ident.get_locus ());
- }
-
- ctx->insert_pattern_binding (ident.get_mappings ().get_hirid (),
- binding);
- }
+ case HIR::StructPatternField::ItemType::IDENT:
+ handle_struct_pattern_ident (*field, adt, variant, variant_index);
break;
}
}
@@ -605,6 +811,12 @@ CompilePatternBindings::visit (HIR::ReferencePattern &pattern)
void
CompilePatternBindings::visit (HIR::IdentifierPattern &pattern)
{
+ if (pattern.has_subpattern ())
+ {
+ CompilePatternBindings::Compile (pattern.get_subpattern (),
+ match_scrutinee_expr, ctx);
+ }
+
if (!pattern.get_is_ref ())
{
ctx->insert_pattern_binding (pattern.get_mappings ().get_hirid (),
@@ -631,7 +843,8 @@ CompilePatternBindings::visit (HIR::TuplePattern &pattern)
switch (pattern.get_items ().get_item_type ())
{
- case HIR::TuplePatternItems::ItemType::RANGED: {
+ case HIR::TuplePatternItems::ItemType::RANGED:
+ {
size_t tuple_idx = 0;
auto &items
= static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ());
@@ -674,7 +887,8 @@ CompilePatternBindings::visit (HIR::TuplePattern &pattern)
return;
}
- case HIR::TuplePatternItems::ItemType::MULTIPLE: {
+ case HIR::TuplePatternItems::ItemType::MULTIPLE:
+ {
size_t tuple_idx = 0;
auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
pattern.get_items ());
@@ -695,12 +909,67 @@ CompilePatternBindings::visit (HIR::TuplePattern &pattern)
return;
}
- default: {
+ default:
+ {
rust_unreachable ();
}
}
}
+void
+CompilePatternBindings::visit (HIR::SlicePattern &pattern)
+{
+ // lookup the type
+ TyTy::BaseType *lookup = nullptr;
+ bool ok
+ = ctx->get_tyctx ()->lookup_type (pattern.get_mappings ().get_hirid (),
+ &lookup);
+ rust_assert (ok);
+
+ rust_assert (lookup->get_kind () == TyTy::TypeKind::ARRAY
+ || lookup->get_kind () == TyTy::TypeKind::SLICE
+ || lookup->get_kind () == TyTy::REF);
+
+ size_t array_element_index = 0;
+ switch (lookup->get_kind ())
+ {
+ case TyTy::TypeKind::ARRAY:
+ for (auto &pattern_member : pattern.get_items ())
+ {
+ tree array_index_tree
+ = Backend::size_constant_expression (array_element_index++);
+ tree element_expr
+ = Backend::array_index_expression (match_scrutinee_expr,
+ array_index_tree,
+ pattern.get_locus ());
+ CompilePatternBindings::Compile (*pattern_member, element_expr, ctx);
+ }
+ break;
+ case TyTy::TypeKind::SLICE:
+ rust_sorry_at (
+ pattern.get_locus (),
+ "SlicePattern matching against non-ref slices are not yet supported");
+ break;
+ case TyTy::TypeKind::REF:
+ {
+ for (auto &pattern_member : pattern.get_items ())
+ {
+ tree slice_index_tree
+ = Backend::size_constant_expression (array_element_index++);
+ tree element_expr
+ = Backend::slice_index_expression (match_scrutinee_expr,
+ slice_index_tree,
+ pattern.get_locus ());
+ CompilePatternBindings::Compile (*pattern_member, element_expr,
+ ctx);
+ }
+ break;
+ }
+ default:
+ rust_unreachable ();
+ }
+}
+
//
void
@@ -755,7 +1024,8 @@ CompilePatternLet::visit (HIR::TuplePattern &pattern)
switch (pattern.get_items ().get_item_type ())
{
- case HIR::TuplePatternItems::ItemType::RANGED: {
+ case HIR::TuplePatternItems::ItemType::RANGED:
+ {
size_t tuple_idx = 0;
auto &items
= static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ());
@@ -799,7 +1069,8 @@ CompilePatternLet::visit (HIR::TuplePattern &pattern)
return;
}
- case HIR::TuplePatternItems::ItemType::MULTIPLE: {
+ case HIR::TuplePatternItems::ItemType::MULTIPLE:
+ {
size_t tuple_idx = 0;
auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
pattern.get_items ());
@@ -821,7 +1092,8 @@ CompilePatternLet::visit (HIR::TuplePattern &pattern)
return;
}
- default: {
+ default:
+ {
rust_unreachable ();
}
}
diff --git a/gcc/rust/backend/rust-compile-pattern.h b/gcc/rust/backend/rust-compile-pattern.h
index c7a62fc..233799e 100644
--- a/gcc/rust/backend/rust-compile-pattern.h
+++ b/gcc/rust/backend/rust-compile-pattern.h
@@ -17,7 +17,9 @@
// <http://www.gnu.org/licenses/>.
#include "rust-compile-base.h"
+#include "rust-hir-pattern.h"
#include "rust-hir-visitor.h"
+#include "rust-tyty.h"
namespace Rust {
namespace Compile {
@@ -43,12 +45,10 @@ public:
void visit (HIR::StructPattern &) override;
void visit (HIR::TupleStructPattern &) override;
void visit (HIR::TuplePattern &) override;
+ void visit (HIR::IdentifierPattern &) override;
+ void visit (HIR::SlicePattern &) override;
// Always succeeds
- void visit (HIR::IdentifierPattern &) override
- {
- check_expr = boolean_true_node;
- }
void visit (HIR::WildcardPattern &) override
{
check_expr = boolean_true_node;
@@ -56,7 +56,6 @@ public:
// Empty visit for unused Pattern HIR nodes.
void visit (HIR::QualifiedPathInExpression &) override {}
- void visit (HIR::SlicePattern &) override {}
CompilePatternCheckExpr (Context *ctx, tree match_scrutinee_expr)
: HIRCompileBase (ctx), match_scrutinee_expr (match_scrutinee_expr),
@@ -78,11 +77,25 @@ public:
pattern.accept_vis (compiler);
}
+ tree make_struct_access (TyTy::ADTType *adt, TyTy::VariantDef *variant,
+ const Identifier &ident, int variant_index);
+
+ void handle_struct_pattern_ident (HIR::StructPatternField &pat,
+ TyTy::ADTType *adt,
+ TyTy::VariantDef *variant,
+ int variant_index);
+ void handle_struct_pattern_ident_pat (HIR::StructPatternField &pat,
+ TyTy::ADTType *adt,
+ TyTy::VariantDef *variant,
+ int variant_index);
+ void handle_struct_pattern_tuple_pat (HIR::StructPatternField &pat);
+
void visit (HIR::StructPattern &pattern) override;
void visit (HIR::TupleStructPattern &pattern) override;
void visit (HIR::ReferencePattern &pattern) override;
void visit (HIR::IdentifierPattern &) override;
void visit (HIR::TuplePattern &pattern) override;
+ void visit (HIR::SlicePattern &) override;
// Empty visit for unused Pattern HIR nodes.
void visit (HIR::AltPattern &) override {}
@@ -90,7 +103,6 @@ public:
void visit (HIR::PathInExpression &) override {}
void visit (HIR::QualifiedPathInExpression &) override {}
void visit (HIR::RangePattern &) override {}
- void visit (HIR::SlicePattern &) override {}
void visit (HIR::WildcardPattern &) override {}
protected:
diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc
index 81d2dbb..f3b9dc2 100644
--- a/gcc/rust/backend/rust-compile-resolve-path.cc
+++ b/gcc/rust/backend/rust-compile-resolve-path.cc
@@ -187,13 +187,18 @@ ResolvePathRef::resolve_with_node_id (
}
// Handle unit struct
+ tree resolved_item = error_mark_node;
if (lookup->get_kind () == TyTy::TypeKind::ADT)
- return attempt_constructor_expression_lookup (lookup, ctx, mappings,
- expr_locus);
+ resolved_item
+ = attempt_constructor_expression_lookup (lookup, ctx, mappings,
+ expr_locus);
+
+ if (!error_operand_p (resolved_item))
+ return resolved_item;
// let the query system figure it out
- tree resolved_item = query_compile (ref, lookup, final_segment, mappings,
- expr_locus, is_qualified_path);
+ resolved_item = query_compile (ref, lookup, final_segment, mappings,
+ expr_locus, is_qualified_path);
if (resolved_item != error_mark_node)
{
TREE_USED (resolved_item) = 1;
@@ -209,36 +214,24 @@ ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment,
{
TyTy::BaseType *lookup = nullptr;
bool ok = ctx->get_tyctx ()->lookup_type (mappings.get_hirid (), &lookup);
- rust_assert (ok);
+ if (!ok)
+ return error_mark_node;
// need to look up the reference for this identifier
// this can fail because it might be a Constructor for something
// in that case the caller should attempt ResolvePathType::Compile
- NodeId ref_node_id = UNKNOWN_NODEID;
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- auto resolved = nr_ctx.lookup (mappings.get_nodeid ());
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- if (!resolved)
- return attempt_constructor_expression_lookup (lookup, ctx, mappings,
- expr_locus);
+ auto resolved = nr_ctx.lookup (mappings.get_nodeid ());
- ref_node_id = *resolved;
- }
- else
- {
- if (!ctx->get_resolver ()->lookup_resolved_name (mappings.get_nodeid (),
- &ref_node_id))
- return attempt_constructor_expression_lookup (lookup, ctx, mappings,
- expr_locus);
- }
+ if (!resolved)
+ return attempt_constructor_expression_lookup (lookup, ctx, mappings,
+ expr_locus);
return resolve_with_node_id (final_segment, mappings, expr_locus,
- is_qualified_path, ref_node_id);
+ is_qualified_path, *resolved);
}
tree
@@ -336,11 +329,18 @@ HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup,
rust_assert (lookup->is<TyTy::FnType> ());
auto fn = lookup->as<TyTy::FnType> ();
rust_assert (fn->get_num_type_params () > 0);
- auto &self = fn->get_substs ().at (0);
- auto receiver = self.get_param_ty ();
+ TyTy::SubstitutionParamMapping &self = fn->get_substs ().at (0);
+ TyTy::BaseGeneric *receiver = self.get_param_ty ();
+ TyTy::BaseType *r = receiver;
+ if (!receiver->can_resolve ())
+ {
+ bool ok
+ = ctx->get_tyctx ()->lookup_type (receiver->get_ref (), &r);
+ rust_assert (ok);
+ }
+
auto candidates
- = Resolver::PathProbeImplTrait::Probe (receiver, final_segment,
- trait_ref);
+ = Resolver::PathProbeImplTrait::Probe (r, final_segment, trait_ref);
if (candidates.size () == 0)
{
// this means we are defaulting back to the trait_item if
diff --git a/gcc/rust/backend/rust-compile-stmt.cc b/gcc/rust/backend/rust-compile-stmt.cc
index a4b5a98..b520baf 100644
--- a/gcc/rust/backend/rust-compile-stmt.cc
+++ b/gcc/rust/backend/rust-compile-stmt.cc
@@ -58,6 +58,9 @@ CompileStmt::visit (HIR::LetStmt &stmt)
return;
}
+ rust_debug_loc (stmt.get_locus (), " -> LetStmt %s",
+ ty->as_string ().c_str ());
+
// setup var decl nodes
fncontext fnctx = ctx->peek_fn ();
tree fndecl = fnctx.fndecl;
diff --git a/gcc/rust/backend/rust-compile-type.cc b/gcc/rust/backend/rust-compile-type.cc
index 83e5756..0622954 100644
--- a/gcc/rust/backend/rust-compile-type.cc
+++ b/gcc/rust/backend/rust-compile-type.cc
@@ -17,11 +17,11 @@
// <http://www.gnu.org/licenses/>.
#include "rust-compile-type.h"
-#include "rust-compile-expr.h"
#include "rust-constexpr.h"
-#include "rust-gcc.h"
+#include "rust-compile-base.h"
#include "tree.h"
+#include "fold-const.h"
#include "stor-layout.h"
namespace Rust {
@@ -121,6 +121,13 @@ TyTyResolveCompile::visit (const TyTy::InferType &type)
if (orig == lookup)
{
+ TyTy::BaseType *def = nullptr;
+ if (type.default_type (&def))
+ {
+ translated = TyTyResolveCompile::compile (ctx, def);
+ return;
+ }
+
translated = error_mark_node;
return;
}
@@ -135,6 +142,12 @@ TyTyResolveCompile::visit (const TyTy::ParamType &)
}
void
+TyTyResolveCompile::visit (const TyTy::ConstType &)
+{
+ translated = error_mark_node;
+}
+
+void
TyTyResolveCompile::visit (const TyTy::ProjectionType &type)
{
translated = error_mark_node;
@@ -189,7 +202,7 @@ TyTyResolveCompile::visit (const TyTy::ClosureType &type)
void
TyTyResolveCompile::visit (const TyTy::FnType &type)
{
- Backend::typed_identifier receiver;
+ Backend::typed_identifier receiver ("", NULL_TREE, UNKNOWN_LOCATION);
std::vector<Backend::typed_identifier> parameters;
std::vector<Backend::typed_identifier> results;
@@ -454,7 +467,7 @@ TyTyResolveCompile::visit (const TyTy::TupleType &type)
}
tree struct_type_record = Backend::struct_type (fields);
- translated = Backend::named_type (type.as_string (), struct_type_record,
+ translated = Backend::named_type (type.get_name (), struct_type_record,
type.get_ident ().locus);
}
@@ -463,26 +476,15 @@ TyTyResolveCompile::visit (const TyTy::ArrayType &type)
{
tree element_type
= TyTyResolveCompile::compile (ctx, type.get_element_type ());
+ TyTy::ConstType *const_capacity = type.get_capacity ();
+ tree folded_capacity_expr = const_capacity->get_value ();
- ctx->push_const_context ();
-
- 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);
+ // build_index_type takes the maximum index, which is one less than
+ // the length.
+ tree index_type_tree = build_index_type (
+ fold_build2 (MINUS_EXPR, sizetype, folded_capacity_expr, size_one_node));
- translated = Backend::array_type (element_type, folded_capacity_expr);
- if (translated != error_mark_node)
- translated = ctx->insert_compiled_type (translated);
+ translated = build_array_type (element_type, index_type_tree, false);
}
void
@@ -755,7 +757,9 @@ TyTyResolveCompile::visit (const TyTy::DynamicObjectType &type)
void
TyTyResolveCompile::visit (const TyTy::OpaqueType &type)
{
- translated = error_mark_node;
+ rust_assert (type.can_resolve ());
+ auto underlying = type.resolve ();
+ translated = TyTyResolveCompile::compile (ctx, underlying, trait_object_mode);
}
tree
diff --git a/gcc/rust/backend/rust-compile-type.h b/gcc/rust/backend/rust-compile-type.h
index 7ebc4a6..0675343 100644
--- a/gcc/rust/backend/rust-compile-type.h
+++ b/gcc/rust/backend/rust-compile-type.h
@@ -50,6 +50,7 @@ public:
void visit (const TyTy::ReferenceType &) override;
void visit (const TyTy::PointerType &) override;
void visit (const TyTy::ParamType &) override;
+ void visit (const TyTy::ConstType &) override;
void visit (const TyTy::StrType &) override;
void visit (const TyTy::NeverType &) override;
void visit (const TyTy::PlaceholderType &) override;
diff --git a/gcc/rust/backend/rust-compile-var-decl.h b/gcc/rust/backend/rust-compile-var-decl.h
index 4c46a7b..5c6d145 100644
--- a/gcc/rust/backend/rust-compile-var-decl.h
+++ b/gcc/rust/backend/rust-compile-var-decl.h
@@ -70,7 +70,8 @@ public:
{
switch (pattern.get_items ().get_item_type ())
{
- case HIR::TuplePatternItems::ItemType::MULTIPLE: {
+ case HIR::TuplePatternItems::ItemType::MULTIPLE:
+ {
rust_assert (TREE_CODE (translated_type) == RECORD_TYPE);
auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
pattern.get_items ());
diff --git a/gcc/rust/backend/rust-constexpr.cc b/gcc/rust/backend/rust-constexpr.cc
index dc2d6b1..d524d09 100644
--- a/gcc/rust/backend/rust-constexpr.cc
+++ b/gcc/rust/backend/rust-constexpr.cc
@@ -68,32 +68,24 @@ literal_type_p (tree t)
return false;
}
-static bool
-verify_constant (tree, bool, bool *, bool *);
-
-static HOST_WIDE_INT
-find_array_ctor_elt (tree ary, tree dindex, bool insert = false);
-static int
-array_index_cmp (tree key, tree index);
-static bool
-potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
- tsubst_flags_t flags, tree *jump_target);
-bool
-potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
- tsubst_flags_t flags);
-tree
-unshare_constructor (tree t MEM_STAT_DECL);
-void
-maybe_save_constexpr_fundef (tree fun);
-
-static bool
-returns (tree *jump_target);
-static bool
-breaks (tree *jump_target);
-static bool
-continues (tree *jump_target);
-static bool
-switches (tree *jump_target);
+static bool verify_constant (tree, bool, bool *, bool *);
+
+static HOST_WIDE_INT find_array_ctor_elt (tree ary, tree dindex,
+ bool insert = false);
+static int array_index_cmp (tree key, tree index);
+static bool potential_constant_expression_1 (tree t, bool want_rval,
+ bool strict, bool now,
+ tsubst_flags_t flags,
+ tree *jump_target);
+bool potential_constant_expression_1 (tree t, bool want_rval, bool strict,
+ bool now, tsubst_flags_t flags);
+tree unshare_constructor (tree t MEM_STAT_DECL);
+void maybe_save_constexpr_fundef (tree fun);
+
+static bool returns (tree *jump_target);
+static bool breaks (tree *jump_target);
+static bool continues (tree *jump_target);
+static bool switches (tree *jump_target);
struct constexpr_global_ctx
{
@@ -463,60 +455,52 @@ save_fundef_copy (tree fun, tree copy)
*slot = copy;
}
-static tree
-constant_value_1 (tree decl, bool strict_p, bool return_aggregate_cst_ok_p,
- bool unshare_p);
-tree
-decl_constant_value (tree decl, bool unshare_p);
+static tree constant_value_1 (tree decl, bool strict_p,
+ bool return_aggregate_cst_ok_p, bool unshare_p);
+tree decl_constant_value (tree decl, bool unshare_p);
-static void
-non_const_var_error (location_t loc, tree r);
+static void non_const_var_error (location_t loc, tree r);
-static tree
-eval_constant_expression (const constexpr_ctx *ctx, tree, bool, bool *, bool *,
- tree * = NULL);
+static tree eval_constant_expression (const constexpr_ctx *ctx, tree, bool,
+ bool *, bool *, tree * = NULL);
-static tree
-constexpr_fn_retval (const constexpr_ctx *ctx, tree r);
+static tree constexpr_fn_retval (const constexpr_ctx *ctx, tree r);
-static tree
-eval_store_expression (const constexpr_ctx *ctx, tree r, bool, bool *, bool *);
+static tree eval_store_expression (const constexpr_ctx *ctx, tree r, bool,
+ bool *, bool *);
-static tree
-eval_call_expression (const constexpr_ctx *ctx, tree r, bool, bool *, bool *);
+static tree eval_call_expression (const constexpr_ctx *ctx, tree r, bool,
+ bool *, bool *);
-static tree
-eval_binary_expression (const constexpr_ctx *ctx, tree r, bool, bool *, bool *);
+static tree eval_binary_expression (const constexpr_ctx *ctx, tree r, bool,
+ bool *, bool *);
-static tree
-get_function_named_in_call (tree t);
+static tree get_function_named_in_call (tree t);
-static tree
-eval_statement_list (const constexpr_ctx *ctx, tree t, bool *non_constant_p,
- bool *overflow_p, tree *jump_target);
-static tree
-extract_string_elt (tree string, unsigned chars_per_elt, unsigned index);
+static tree eval_statement_list (const constexpr_ctx *ctx, tree t,
+ bool *non_constant_p, bool *overflow_p,
+ tree *jump_target);
+static tree extract_string_elt (tree string, unsigned chars_per_elt,
+ unsigned index);
-static tree
-eval_conditional_expression (const constexpr_ctx *ctx, tree t, bool lval,
- bool *non_constant_p, bool *overflow_p,
- tree *jump_target);
+static tree eval_conditional_expression (const constexpr_ctx *ctx, tree t,
+ bool lval, bool *non_constant_p,
+ bool *overflow_p, tree *jump_target);
-static tree
-eval_bit_field_ref (const constexpr_ctx *ctx, tree t, bool lval,
- bool *non_constant_p, bool *overflow_p);
+static tree eval_bit_field_ref (const constexpr_ctx *ctx, tree t, bool lval,
+ bool *non_constant_p, bool *overflow_p);
-static tree
-eval_loop_expr (const constexpr_ctx *ctx, tree t, bool *non_constant_p,
- bool *overflow_p, tree *jump_target);
+static tree eval_loop_expr (const constexpr_ctx *ctx, tree t,
+ bool *non_constant_p, bool *overflow_p,
+ tree *jump_target);
-static tree
-eval_switch_expr (const constexpr_ctx *ctx, tree t, bool *non_constant_p,
- bool *overflow_p, tree *jump_target);
+static tree eval_switch_expr (const constexpr_ctx *ctx, tree t,
+ bool *non_constant_p, bool *overflow_p,
+ tree *jump_target);
-static tree
-eval_unary_expression (const constexpr_ctx *ctx, tree t, bool /*lval*/,
- bool *non_constant_p, bool *overflow_p);
+static tree eval_unary_expression (const constexpr_ctx *ctx, tree t,
+ bool /*lval*/, bool *non_constant_p,
+ bool *overflow_p);
/* Variables and functions to manage constexpr call expansion context.
These do not need to be marked for PCH or GC. */
@@ -1235,7 +1219,8 @@ get_or_insert_ctor_field (tree ctor, tree index, int pos_hint = -1)
/* We fell off the end of the CONSTRUCTOR, so insert a new
entry at the end. */
- insert : {
+ insert:
+ {
constructor_elt ce = {index, NULL_TREE};
vec_safe_insert (CONSTRUCTOR_ELTS (ctor), idx, ce);
@@ -1568,10 +1553,9 @@ free_constructor (tree t)
}
}
-static tree
-eval_and_check_array_index (const constexpr_ctx *ctx, tree t,
- bool allow_one_past, bool *non_constant_p,
- bool *overflow_p);
+static tree eval_and_check_array_index (const constexpr_ctx *ctx, tree t,
+ bool allow_one_past,
+ bool *non_constant_p, bool *overflow_p);
// forked from gcc/cp/constexpr.cc cxx_eval_array_reference
@@ -1901,6 +1885,9 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
location_t loc = EXPR_LOCATION (t);
+ if (t == NULL_TREE)
+ return NULL_TREE;
+
if (CONSTANT_CLASS_P (t))
{
if (TREE_OVERFLOW (t))
@@ -1936,8 +1923,9 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
return eval_constant_expression (ctx, r, lval, non_constant_p,
overflow_p);
}
- /* fall through */
- case CONST_DECL: {
+ /* fall through */
+ case CONST_DECL:
+ {
/* We used to not check lval for CONST_DECL, but darwin.cc uses
CONST_DECL for aggregate constants. */
if (lval)
@@ -2045,7 +2033,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
overflow_p);
break;
- case TARGET_EXPR: {
+ case TARGET_EXPR:
+ {
tree type = TREE_TYPE (t);
if (!literal_type_p (type))
@@ -2129,7 +2118,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
}
break;
- case DECL_EXPR: {
+ case DECL_EXPR:
+ {
r = DECL_EXPR_DECL (t);
if (AGGREGATE_TYPE_P (TREE_TYPE (r)) || VECTOR_TYPE_P (TREE_TYPE (r)))
@@ -2201,7 +2191,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
return eval_constant_expression (ctx, OBJ_TYPE_REF_EXPR (t), lval,
non_constant_p, overflow_p);
- case EXIT_EXPR: {
+ case EXIT_EXPR:
+ {
tree cond = TREE_OPERAND (t, 0);
cond = eval_constant_expression (ctx, cond, /*lval*/ false,
non_constant_p, overflow_p);
@@ -2243,7 +2234,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
}
break;
- case ADDR_EXPR: {
+ case ADDR_EXPR:
+ {
tree oldop = TREE_OPERAND (t, 0);
tree op = eval_constant_expression (ctx, oldop,
/*lval*/ true, non_constant_p,
@@ -2261,7 +2253,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
break;
}
- case COMPOUND_EXPR: {
+ case COMPOUND_EXPR:
+ {
/* check_return_expr sometimes wraps a TARGET_EXPR in a
COMPOUND_EXPR; don't get confused. Also handle EMPTY_CLASS_EXPR
introduced by build_call_a. */
@@ -2401,7 +2394,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
non_constant_p, overflow_p, jump_target);
break;
- case CLEANUP_POINT_EXPR: {
+ case CLEANUP_POINT_EXPR:
+ {
auto_vec<tree, 2> cleanups;
vec<tree> *prev_cleanups = ctx->global->cleanups;
ctx->global->cleanups = &cleanups;
@@ -2441,7 +2435,8 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
/* FALLTHROUGH. */
case NOP_EXPR:
case CONVERT_EXPR:
- case VIEW_CONVERT_EXPR: {
+ case VIEW_CONVERT_EXPR:
+ {
tree oldop = TREE_OPERAND (t, 0);
tree op = eval_constant_expression (ctx, oldop, lval, non_constant_p,
@@ -2688,7 +2683,8 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval,
{
case BIT_FIELD_REF:
case COMPONENT_REF:
- case ARRAY_REF: {
+ case ARRAY_REF:
+ {
tree ob = TREE_OPERAND (probe, 0);
tree elt = TREE_OPERAND (probe, 1);
if (TREE_CODE (elt) == FIELD_DECL /*&& DECL_MUTABLE_P (elt)*/)
@@ -3940,7 +3936,8 @@ constexpr_fn_retval (const constexpr_ctx *ctx, tree body)
{
switch (TREE_CODE (body))
{
- case STATEMENT_LIST: {
+ case STATEMENT_LIST:
+ {
tree expr = NULL_TREE;
for (tree stmt : tsi_range (body))
{
@@ -3958,13 +3955,15 @@ constexpr_fn_retval (const constexpr_ctx *ctx, tree body)
return expr;
}
- case RETURN_EXPR: {
+ case RETURN_EXPR:
+ {
bool non_constant_p = false;
bool overflow_p = false;
return eval_constant_expression (ctx, body, false, &non_constant_p,
&overflow_p);
}
- case DECL_EXPR: {
+ case DECL_EXPR:
+ {
tree decl = DECL_EXPR_DECL (body);
if (TREE_CODE (decl) == USING_DECL
/* Accept __func__, __FUNCTION__, and __PRETTY_FUNCTION__. */
@@ -3976,7 +3975,8 @@ constexpr_fn_retval (const constexpr_ctx *ctx, tree body)
case CLEANUP_POINT_EXPR:
return constexpr_fn_retval (ctx, TREE_OPERAND (body, 0));
- case BIND_EXPR: {
+ case BIND_EXPR:
+ {
tree b = BIND_EXPR_BODY (body);
return constexpr_fn_retval (ctx, b);
}
@@ -4136,7 +4136,8 @@ array_index_cmp (tree key, tree index)
{
case INTEGER_CST:
return tree_int_cst_compare (key, index);
- case RANGE_EXPR: {
+ case RANGE_EXPR:
+ {
tree lo = TREE_OPERAND (index, 0);
tree hi = TREE_OPERAND (index, 1);
if (tree_int_cst_lt (key, lo))
@@ -5943,7 +5944,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
case BIT_FIELD_REF:
return RECUR (TREE_OPERAND (t, 0), want_rval);
- case INDIRECT_REF: {
+ case INDIRECT_REF:
+ {
tree x = TREE_OPERAND (t, 0);
STRIP_NOPS (x);
return RECUR (x, rval);
@@ -6214,7 +6216,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
case INIT_EXPR:
return RECUR (TREE_OPERAND (t, 1), rval);
- case CONSTRUCTOR: {
+ case CONSTRUCTOR:
+ {
vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (t);
constructor_elt *ce;
for (i = 0; vec_safe_iterate (v, i, &ce); ++i)
@@ -6223,7 +6226,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
return true;
}
- case TREE_LIST: {
+ case TREE_LIST:
+ {
gcc_assert (TREE_PURPOSE (t) == NULL_TREE || DECL_P (TREE_PURPOSE (t)));
if (!RECUR (TREE_VALUE (t), want_rval))
return false;
@@ -6238,7 +6242,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
case ROUND_DIV_EXPR:
case TRUNC_MOD_EXPR:
case CEIL_MOD_EXPR:
- case ROUND_MOD_EXPR: {
+ case ROUND_MOD_EXPR:
+ {
tree denom = TREE_OPERAND (t, 1);
if (!RECUR (denom, rval))
return false;
@@ -6258,7 +6263,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
}
}
- case COMPOUND_EXPR: {
+ case COMPOUND_EXPR:
+ {
/* check_return_expr sometimes wraps a TARGET_EXPR in a
COMPOUND_EXPR; don't get confused. */
tree op0 = TREE_OPERAND (t, 0);
@@ -6280,7 +6286,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
case TRUTH_OR_EXPR:
case TRUTH_ORIF_EXPR:
tmp = boolean_false_node;
- truth : {
+ truth:
+ {
tree op0 = TREE_OPERAND (t, 0);
tree op1 = TREE_OPERAND (t, 1);
if (!RECUR (op0, rval))
diff --git a/gcc/rust/backend/rust-constexpr.h b/gcc/rust/backend/rust-constexpr.h
index 77a0797..27f0a2e 100644
--- a/gcc/rust/backend/rust-constexpr.h
+++ b/gcc/rust/backend/rust-constexpr.h
@@ -24,8 +24,7 @@ namespace Rust {
namespace Compile {
extern tree fold_expr (tree);
-extern void
-maybe_save_constexpr_fundef (tree fun);
+extern void maybe_save_constexpr_fundef (tree fun);
} // namespace Compile
} // namespace Rust
diff --git a/gcc/rust/backend/rust-mangle-v0.cc b/gcc/rust/backend/rust-mangle-v0.cc
index d0df4ab..f6b1a4c 100644
--- a/gcc/rust/backend/rust-mangle-v0.cc
+++ b/gcc/rust/backend/rust-mangle-v0.cc
@@ -62,9 +62,9 @@ struct V0Path
}
};
-static std::string
-v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty,
- const Resolver::CanonicalPath &path);
+static std::string v0_path (Rust::Compile::Context *ctx,
+ const TyTy::BaseType *ty,
+ const Resolver::CanonicalPath &path);
static std::string
v0_tuple_prefix (const TyTy::BaseType *ty)
@@ -148,7 +148,8 @@ v0_complex_type_prefix (Context *ctx, const TyTy::BaseType *ty)
// TODO: generics
switch (ty->get_kind ())
{
- case TyTy::TypeKind::ADT: {
+ case TyTy::TypeKind::ADT:
+ {
const TyTy::ADTType *adt = static_cast<const TyTy::ADTType *> (ty);
return v0_path (ctx, ty, adt->get_ident ().path);
}
@@ -387,7 +388,8 @@ v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty,
{
switch (impl_item->first->get_impl_item_type ())
{
- case HIR::ImplItem::FUNCTION: {
+ case HIR::ImplItem::FUNCTION:
+ {
HIR::Function *fn
= static_cast<HIR::Function *> (impl_item->first);
v0path
@@ -408,7 +410,8 @@ v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty,
{
switch (trait_item.value ()->get_item_kind ())
{
- case HIR::TraitItem::FUNC: {
+ case HIR::TraitItem::FUNC:
+ {
auto fn = static_cast<HIR::TraitItemFunc *> (*trait_item);
rust_unreachable ();
v0path = v0_function_path (v0path, ctx, ty,
@@ -428,7 +431,8 @@ v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty,
else if (auto item = mappings.lookup_hir_item (hir_id))
switch (item.value ()->get_item_kind ())
{
- case HIR::Item::ItemKind::Function: {
+ case HIR::Item::ItemKind::Function:
+ {
HIR::Function *fn = static_cast<HIR::Function *> (*item);
v0path
= v0_function_path (v0path, ctx, ty, fn->get_generic_params (),
diff --git a/gcc/rust/backend/rust-mangle.h b/gcc/rust/backend/rust-mangle.h
index 2a84b6b..418f2bd 100644
--- a/gcc/rust/backend/rust-mangle.h
+++ b/gcc/rust/backend/rust-mangle.h
@@ -49,13 +49,12 @@ private:
static enum MangleVersion version;
};
-std::string
-legacy_mangle_item (const TyTy::BaseType *ty,
- const Resolver::CanonicalPath &path);
+std::string legacy_mangle_item (const TyTy::BaseType *ty,
+ const Resolver::CanonicalPath &path);
-std::string
-v0_mangle_item (Rust::Compile::Context *ctx, const TyTy::BaseType *ty,
- const Resolver::CanonicalPath &path);
+std::string v0_mangle_item (Rust::Compile::Context *ctx,
+ const TyTy::BaseType *ty,
+ const Resolver::CanonicalPath &path);
} // namespace Compile
} // namespace Rust
diff --git a/gcc/rust/backend/rust-tree.cc b/gcc/rust/backend/rust-tree.cc
index 2302ffb..b86c3c8 100644
--- a/gcc/rust/backend/rust-tree.cc
+++ b/gcc/rust/backend/rust-tree.cc
@@ -268,7 +268,8 @@ convert_to_void (tree expr, impl_conv_void implicit)
return expr;
switch (TREE_CODE (expr))
{
- case COND_EXPR: {
+ case COND_EXPR:
+ {
/* The two parts of a cond expr might be separate lvalues. */
tree op1 = TREE_OPERAND (expr, 1);
tree op2 = TREE_OPERAND (expr, 2);
@@ -294,7 +295,8 @@ convert_to_void (tree expr, impl_conv_void implicit)
break;
}
- case COMPOUND_EXPR: {
+ case COMPOUND_EXPR:
+ {
/* The second part of a compound expr contains the value. */
tree op1 = TREE_OPERAND (expr, 1);
tree new_op1;
@@ -323,7 +325,8 @@ convert_to_void (tree expr, impl_conv_void implicit)
maybe_warn_nodiscard (expr, implicit);
break;
- case INDIRECT_REF: {
+ case INDIRECT_REF:
+ {
tree type = TREE_TYPE (expr);
int is_reference = TYPE_REF_P (TREE_TYPE (TREE_OPERAND (expr, 0)));
int is_volatile = TYPE_VOLATILE (type);
@@ -518,7 +521,8 @@ convert_to_void (tree expr, impl_conv_void implicit)
break;
}
- case VAR_DECL: {
+ case VAR_DECL:
+ {
/* External variables might be incomplete. */
tree type = TREE_TYPE (expr);
int is_complete = COMPLETE_TYPE_P (type);
@@ -1485,7 +1489,8 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void *data)
parameter pack. ??? Should some of these be in cp_walk_subtrees? */
switch (TREE_CODE (t))
{
- case DECL_EXPR: {
+ case DECL_EXPR:
+ {
tree decl = DECL_EXPR_DECL (t);
if (is_typedef_decl (decl))
/* Since we stop at typedefs above, we need to look through them at
@@ -1506,7 +1511,8 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void *data)
*walk_subtrees = 0;
return NULL_TREE;
- case DECLTYPE_TYPE: {
+ case DECLTYPE_TYPE:
+ {
/* When traversing a DECLTYPE_TYPE_EXPR, we need to set
type_pack_expansion_p to false so that any placeholders
within the expression don't get marked as parameter packs. */
@@ -1970,7 +1976,8 @@ rs_tree_equal (tree t1, tree t2)
case SAVE_EXPR:
return rs_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
- case CALL_EXPR: {
+ case CALL_EXPR:
+ {
if (KOENIG_LOOKUP_P (t1) != KOENIG_LOOKUP_P (t2))
return false;
@@ -1996,7 +2003,8 @@ rs_tree_equal (tree t1, tree t2)
return true;
}
- case TARGET_EXPR: {
+ case TARGET_EXPR:
+ {
tree o1 = TREE_OPERAND (t1, 0);
tree o2 = TREE_OPERAND (t2, 0);
@@ -2067,7 +2075,8 @@ rs_tree_equal (tree t1, tree t2)
case tcc_expression:
case tcc_vl_exp:
case tcc_reference:
- case tcc_statement: {
+ case tcc_statement:
+ {
int n = rs_tree_operand_length (t1);
if (TREE_CODE_CLASS (code1) == tcc_vl_exp
&& n != TREE_OPERAND_LENGTH (t2))
@@ -2095,7 +2104,11 @@ rs_tree_equal (tree t1, tree t2)
/* TRUE iff TYPE is publicly & uniquely derived from PARENT. */
-bool publicly_uniquely_derived_p (tree, tree) { return false; }
+bool
+publicly_uniquely_derived_p (tree, tree)
+{
+ return false;
+}
// forked from gcc/cp/typeck.cc comp_except_types
@@ -3375,7 +3388,11 @@ release_tree_vector (vec<tree, va_gc> *vec)
/* As above, but also check value-dependence of the expression as a whole. */
-bool instantiation_dependent_expression_p (tree) { return false; }
+bool
+instantiation_dependent_expression_p (tree)
+{
+ return false;
+}
// forked from gcc/cp/cvt.cc cp_get_callee
@@ -3425,7 +3442,11 @@ scalarish_type_p (const_tree t)
constructors are deleted. This function implements the ABI notion of
non-trivial copy, which has diverged from the one in the standard. */
-bool type_has_nontrivial_copy_init (const_tree) { return false; }
+bool
+type_has_nontrivial_copy_init (const_tree)
+{
+ return false;
+}
// forked from gcc/cp/tree.cc build_local_temp
@@ -3448,7 +3469,11 @@ build_local_temp (tree type)
/* Returns true iff DECL is a capture proxy for a normal capture
(i.e. without explicit initializer). */
-bool is_normal_capture_proxy (tree) { return false; }
+bool
+is_normal_capture_proxy (tree)
+{
+ return false;
+}
// forked from gcc/cp/c-common.cc reject_gcc_builtin
@@ -3522,7 +3547,8 @@ is_bitfield_expr_with_lowered_type (const_tree exp)
case BIT_NOT_EXPR:
return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 0));
- case COMPONENT_REF: {
+ case COMPONENT_REF:
+ {
tree field;
field = TREE_OPERAND (exp, 1);
@@ -3909,7 +3935,8 @@ retry:
break;
case OFFSET_TYPE:
- bad_member : {
+ bad_member:
+ {
tree member = TREE_OPERAND (value, 1);
if (is_overloaded_fn (member))
member = get_first_fn (member);
@@ -3994,13 +4021,21 @@ decl_constant_var_p (tree decl)
/* Returns true iff DECL is a variable or function declared with an auto type
that has not yet been deduced to a real type. */
-bool undeduced_auto_decl (tree) { return false; }
+bool
+undeduced_auto_decl (tree)
+{
+ return false;
+}
// forked from gcc/cp/decl.cc require_deduced_type
/* Complain if DECL has an undeduced return type. */
-bool require_deduced_type (tree, tsubst_flags_t) { return true; }
+bool
+require_deduced_type (tree, tsubst_flags_t)
+{
+ return true;
+}
/* Return the location of a tree passed to %+ formats. */
@@ -4290,10 +4325,9 @@ struct GTY ((for_user)) source_location_table_entry
} // namespace Rust
-extern void
-gt_pch_nx (Rust::source_location_table_entry &);
-extern void
-gt_pch_nx (Rust::source_location_table_entry *, gt_pointer_operator, void *);
+extern void gt_pch_nx (Rust::source_location_table_entry &);
+extern void gt_pch_nx (Rust::source_location_table_entry *, gt_pointer_operator,
+ void *);
namespace Rust {
@@ -4421,7 +4455,8 @@ lvalue_kind (const_tree ref)
case VIEW_CONVERT_EXPR:
return lvalue_kind (TREE_OPERAND (ref, 0));
- case ARRAY_REF: {
+ case ARRAY_REF:
+ {
tree op1 = TREE_OPERAND (ref, 0);
if (TREE_CODE (TREE_TYPE (op1)) == ARRAY_TYPE)
{
@@ -4518,7 +4553,8 @@ lvalue_kind (const_tree ref)
op2_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 1));
break;
- case COND_EXPR: {
+ case COND_EXPR:
+ {
tree op1 = TREE_OPERAND (ref, 1);
if (!op1)
op1 = TREE_OPERAND (ref, 0);
diff --git a/gcc/rust/backend/rust-tree.h b/gcc/rust/backend/rust-tree.h
index 3630b0e..9e859d4 100644
--- a/gcc/rust/backend/rust-tree.h
+++ b/gcc/rust/backend/rust-tree.h
@@ -1543,7 +1543,7 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX];
#if defined ENABLE_TREE_CHECKING
#define LANG_DECL_MIN_CHECK(NODE) \
- __extension__({ \
+ __extension__ ({ \
struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \
if (!LANG_DECL_HAS_MIN (NODE)) \
lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \
@@ -1554,7 +1554,7 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX];
template, not just on a FUNCTION_DECL. So when looking for things in
lang_decl_fn, look down through a TEMPLATE_DECL into its result. */
#define LANG_DECL_FN_CHECK(NODE) \
- __extension__({ \
+ __extension__ ({ \
struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \
if (!DECL_DECLARES_FUNCTION_P (NODE) || lt->u.base.selector != lds_fn) \
lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \
@@ -1562,7 +1562,7 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX];
})
#define LANG_DECL_NS_CHECK(NODE) \
- __extension__({ \
+ __extension__ ({ \
struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \
if (TREE_CODE (NODE) != NAMESPACE_DECL || lt->u.base.selector != lds_ns) \
lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \
@@ -1570,7 +1570,7 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX];
})
#define LANG_DECL_PARM_CHECK(NODE) \
- __extension__({ \
+ __extension__ ({ \
struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \
if (TREE_CODE (NODE) != PARM_DECL || lt->u.base.selector != lds_parm) \
lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \
@@ -1578,7 +1578,7 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX];
})
#define LANG_DECL_DECOMP_CHECK(NODE) \
- __extension__({ \
+ __extension__ ({ \
struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \
if (!VAR_P (NODE) || lt->u.base.selector != lds_decomp) \
lang_check_failed (__FILE__, __LINE__, __FUNCTION__); \
@@ -2060,8 +2060,8 @@ struct GTY (()) rust_cxx_saved_binding
// forked from gcc/cp/name-lookup.h resort_type_member_vec
/* needed for GTY annotation */
-extern void
-resort_type_member_vec (void *, void *, gt_pointer_operator, void *);
+extern void resort_type_member_vec (void *, void *, gt_pointer_operator,
+ void *);
// forked from gcc/cp/cp-tree.h saved_scope
@@ -2895,8 +2895,7 @@ enum compare_bounds_t
bounds_first
};
-extern tree
-convert_to_void (tree expr, impl_conv_void implicit);
+extern tree convert_to_void (tree expr, impl_conv_void implicit);
// The lvalue-to-rvalue conversion (7.1) is applied if and only if the
// expression is a glvalue of volatile-qualified type and it is one of the
@@ -2911,63 +2910,52 @@ convert_to_void (tree expr, impl_conv_void implicit);
// operands are one of these expressions, or
// * comma expression (8.19) where the right operand is one of these
// expressions.
-extern tree
-mark_discarded_use (tree expr);
+extern tree mark_discarded_use (tree expr);
// Mark EXP as read, not just set, for set but not used -Wunused warning
// purposes.
-extern void
-mark_exp_read (tree exp);
+extern void mark_exp_read (tree exp);
// We've seen an actual use of EXPR. Possibly replace an outer variable
// reference inside with its constant value or a lambda capture.
-extern tree
-mark_use (tree expr, bool rvalue_p, bool read_p, location_t loc,
- bool reject_builtin);
+extern tree mark_use (tree expr, bool rvalue_p, bool read_p, location_t loc,
+ bool reject_builtin);
// Called whenever the expression EXPR is used in an rvalue context.
// When REJECT_BUILTIN is true the expression is checked to make sure
// it doesn't make it possible to obtain the address of a GCC built-in
// function with no library fallback (or any of its bits, such as in
// a conversion to bool).
-extern tree
-mark_rvalue_use (tree, location_t = UNKNOWN_LOCATION,
- bool reject_builtin = true);
+extern tree mark_rvalue_use (tree, location_t = UNKNOWN_LOCATION,
+ bool reject_builtin = true);
// Called whenever an expression is used in an lvalue context.
-extern tree
-mark_lvalue_use (tree expr);
+extern tree mark_lvalue_use (tree expr);
// As above, but don't consider this use a read.
-extern tree
-mark_lvalue_use_nonread (tree expr);
+extern tree mark_lvalue_use_nonread (tree expr);
// We are using a reference VAL for its value. Bash that reference all the way
// down to its lowest form.
-extern tree
-convert_from_reference (tree val);
+extern tree convert_from_reference (tree val);
// Subroutine of convert_to_void. Warn if we're discarding something with
// attribute [[nodiscard]].
-extern void
-maybe_warn_nodiscard (tree expr, impl_conv_void implicit);
+extern void maybe_warn_nodiscard (tree expr, impl_conv_void implicit);
-extern location_t
-expr_loc_or_loc (const_tree t, location_t or_loc);
+extern location_t expr_loc_or_loc (const_tree t, location_t or_loc);
-extern location_t
-expr_loc_or_input_loc (const_tree t);
+extern location_t expr_loc_or_input_loc (const_tree t);
// FN is the callee of a CALL_EXPR or AGGR_INIT_EXPR; return the FUNCTION_DECL
// if we can.
-extern tree
-get_fndecl_from_callee (tree fn);
+extern tree get_fndecl_from_callee (tree fn);
// FIXME some helpers from HIRCompileBase could probably be moved here over time
// Return an expression for the address of BASE[INDEX], used in offset intrinsic
-extern tree
-pointer_offset_expression (tree base_tree, tree index_tree, location_t locus);
+extern tree pointer_offset_expression (tree base_tree, tree index_tree,
+ location_t locus);
/* A tree node, together with a location, so that we can track locations
(and ranges) during parsing.
@@ -2978,11 +2966,9 @@ pointer_offset_expression (tree base_tree, tree index_tree, location_t locus);
extern location_t rs_expr_location (const_tree);
-extern int
-is_empty_class (tree type);
+extern int is_empty_class (tree type);
-extern bool
-is_really_empty_class (tree, bool);
+extern bool is_really_empty_class (tree, bool);
extern bool builtin_valid_in_constant_expr_p (const_tree);
@@ -2990,15 +2976,13 @@ extern bool maybe_constexpr_fn (tree);
extern bool var_in_maybe_constexpr_fn (tree);
-extern int
-rs_type_quals (const_tree type);
+extern int rs_type_quals (const_tree type);
inline bool type_unknown_p (const_tree);
extern bool decl_maybe_constant_var_p (tree);
-extern void
-init_modules ();
+extern void init_modules ();
extern bool var_in_constexpr_fn (tree);
@@ -3006,11 +2990,9 @@ inline tree ovl_first (tree) ATTRIBUTE_PURE;
inline bool type_unknown_p (const_tree);
-extern tree
-lookup_add (tree fns, tree lookup);
+extern tree lookup_add (tree fns, tree lookup);
-extern tree
-ovl_make (tree fn, tree next = NULL_TREE);
+extern tree ovl_make (tree fn, tree next = NULL_TREE);
extern int is_overloaded_fn (tree) ATTRIBUTE_PURE;
@@ -3024,19 +3006,15 @@ extern tree make_conv_op_name (tree);
extern int type_memfn_quals (const_tree);
-struct c_fileinfo *
-get_fileinfo (const char *);
+struct c_fileinfo *get_fileinfo (const char *);
-extern tree
-cxx_make_type (enum tree_code CXX_MEM_STAT_INFO);
+extern tree cxx_make_type (enum tree_code CXX_MEM_STAT_INFO);
-extern tree
-build_cplus_array_type (tree, tree, int is_dep = -1);
+extern tree build_cplus_array_type (tree, tree, int is_dep = -1);
extern bool is_byte_access_type (tree);
-extern bool
-comptypes (tree, tree, int);
+extern bool comptypes (tree, tree, int);
extern tree canonical_eh_spec (tree);
@@ -3046,8 +3024,7 @@ extern bool rs_tree_equal (tree, tree);
extern bool compparms (const_tree, const_tree);
-extern tree
-rs_build_qualified_type_real (tree, int, tsubst_flags_t);
+extern tree rs_build_qualified_type_real (tree, int, tsubst_flags_t);
#define rs_build_qualified_type(TYPE, QUALS) \
rs_build_qualified_type_real ((TYPE), (QUALS), tf_warning_or_error)
extern bool cv_qualified_p (const_tree);
@@ -3056,21 +3033,18 @@ extern bool similar_type_p (tree, tree);
extern bool rs_tree_equal (tree, tree);
-extern bool
-vector_targets_convertible_p (const_tree t1, const_tree t2);
+extern bool vector_targets_convertible_p (const_tree t1, const_tree t2);
extern bool same_type_ignoring_top_level_qualifiers_p (tree, tree);
extern bool comp_ptr_ttypes_const (tree, tree, compare_bounds_t);
-extern tree
-get_class_binding_direct (tree, tree, bool want_type = false);
+extern tree get_class_binding_direct (tree, tree, bool want_type = false);
extern tree skip_artificial_parms_for (const_tree, tree);
-extern void
-lang_check_failed (const char *, int,
- const char *) ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+extern void lang_check_failed (const char *, int,
+ const char *) ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
extern tree default_init_uninitialized_part (tree);
@@ -3088,8 +3062,7 @@ extern tree in_class_defaulted_default_constructor (tree);
extern bool is_instantiation_of_constexpr (tree);
-extern bool
-check_for_uninitialized_const_var (tree, bool, tsubst_flags_t);
+extern bool check_for_uninitialized_const_var (tree, bool, tsubst_flags_t);
extern bool reduced_constant_expression_p (tree);
@@ -3108,19 +3081,17 @@ extern tree is_bitfield_expr_with_lowered_type (const_tree);
extern tree convert_bitfield_to_declared_type (tree);
-extern tree
-cp_fold_maybe_rvalue (tree, bool);
+extern tree cp_fold_maybe_rvalue (tree, bool);
extern tree maybe_undo_parenthesized_ref (tree);
-extern tree
-fold_offsetof (tree, tree = size_type_node, tree_code ctx = ERROR_MARK);
+extern tree fold_offsetof (tree, tree = size_type_node,
+ tree_code ctx = ERROR_MARK);
extern tree cp_truthvalue_conversion (tree, tsubst_flags_t);
-extern tree
-fold_non_dependent_expr (tree, tsubst_flags_t = tf_warning_or_error,
- bool = false, tree = NULL_TREE);
+extern tree fold_non_dependent_expr (tree, tsubst_flags_t = tf_warning_or_error,
+ bool = false, tree = NULL_TREE);
extern int char_type_p (tree);
@@ -3163,13 +3134,11 @@ extern tree build_new_constexpr_heap_type (tree, tree, tree);
extern bool is_empty_field (tree);
-extern bool
-in_immediate_context ();
+extern bool in_immediate_context ();
extern tree cp_get_callee_fndecl_nofold (tree);
-extern bool
-cxx_mark_addressable (tree, bool = false);
+extern bool cxx_mark_addressable (tree, bool = false);
extern tree fold_builtin_source_location (location_t);
@@ -3183,25 +3152,22 @@ extern bool glvalue_p (const_tree);
extern cp_lvalue_kind lvalue_kind (const_tree);
-extern tree
-decl_constant_value (tree, bool);
+extern tree decl_constant_value (tree, bool);
extern tree lookup_enumerator (tree, tree);
-extern int
-is_class_type (tree, int);
+extern int is_class_type (tree, int);
extern tree braced_lists_to_strings (tree, tree);
-extern tree
-fold_builtin_is_pointer_inverconvertible_with_class (location_t, int, tree *);
+extern tree fold_builtin_is_pointer_inverconvertible_with_class (location_t,
+ int, tree *);
extern bool layout_compatible_type_p (tree, tree);
extern tree finish_underlying_type (tree);
-extern tree
-c_common_type_for_mode (machine_mode, int);
+extern tree c_common_type_for_mode (machine_mode, int);
extern bool std_layout_type_p (const_tree);
@@ -3213,25 +3179,21 @@ extern void note_failed_type_completion_for_satisfaction (tree);
extern tree complete_type_or_maybe_complain (tree, tree, tsubst_flags_t);
-extern bool
-next_common_initial_seqence (tree &, tree &);
+extern bool next_common_initial_seqence (tree &, tree &);
extern bool null_member_pointer_value_p (tree);
-extern tree
-fold_builtin_is_corresponding_member (location_t, int, tree *);
+extern tree fold_builtin_is_corresponding_member (location_t, int, tree *);
extern tree cp_fold_rvalue (tree);
-extern tree
-maybe_constant_value (tree, tree = NULL_TREE, bool = false);
+extern tree maybe_constant_value (tree, tree = NULL_TREE, bool = false);
extern tree lvalue_type (tree);
extern void lvalue_error (location_t, enum lvalue_use);
-extern tree
-cp_fold_maybe_rvalue (tree, bool);
+extern tree cp_fold_maybe_rvalue (tree, bool);
extern tree get_first_fn (tree) ATTRIBUTE_PURE;
@@ -3253,13 +3215,12 @@ enum
ce_exact
};
-extern tree
-rs_build_qualified_type_real (tree, int, tsubst_flags_t);
+extern tree rs_build_qualified_type_real (tree, int, tsubst_flags_t);
#define rs_build_qualified_type(TYPE, QUALS) \
rs_build_qualified_type_real ((TYPE), (QUALS), tf_warning_or_error)
-extern tree
-rs_walk_subtrees (tree *, int *, walk_tree_fn, void *, hash_set<tree> *);
+extern tree rs_walk_subtrees (tree *, int *, walk_tree_fn, void *,
+ hash_set<tree> *);
#define rs_walk_tree(tp, func, data, pset) \
walk_tree_1 (tp, func, data, pset, rs_walk_subtrees)
#define rs_walk_tree_without_duplicates(tp, func, data) \
@@ -3351,11 +3312,9 @@ gnu_vector_type_p (const_tree type)
return TREE_CODE (type) == VECTOR_TYPE && !TYPE_INDIVISIBLE_P (type);
}
-extern vec<tree, va_gc> *
-make_tree_vector (void);
+extern vec<tree, va_gc> *make_tree_vector (void);
-extern void
-release_tree_vector (vec<tree, va_gc> *);
+extern void release_tree_vector (vec<tree, va_gc> *);
/* Simplified unique_ptr clone to release a tree vec on exit. */
@@ -3373,7 +3332,7 @@ public:
releasing_vec &operator= (const releasing_vec &);
vec_t &operator* () const { return *v; }
- vec_t *operator-> () const { return v; }
+ vec_t *operator->() const { return v; }
vec_t *get () const { return v; }
operator vec_t * () const { return v; }
vec_t **operator& () { return &v; }
@@ -3442,8 +3401,7 @@ cxx_incomplete_type_error (const_tree value, const_tree type)
cxx_incomplete_type_diagnostic (value, type, diagnostics::kind::error);
}
-extern location_t
-location_of (tree t);
+extern location_t location_of (tree t);
/* Helpers for IMPLICIT_RVALUE_P to look through automatic dereference. */
@@ -3465,23 +3423,18 @@ set_implicit_rvalue_p (tree ot)
}
namespace Compile {
-extern tree
-maybe_constant_init (tree, tree = NULL_TREE, bool = false);
+extern tree maybe_constant_init (tree, tree = NULL_TREE, bool = false);
-extern void
-explain_invalid_constexpr_fn (tree fun);
+extern void explain_invalid_constexpr_fn (tree fun);
extern bool potential_constant_expression (tree);
-extern bool
-literal_type_p (tree t);
+extern bool literal_type_p (tree t);
-extern bool
-maybe_constexpr_fn (tree t);
+extern bool maybe_constexpr_fn (tree t);
-extern tree
-fold_non_dependent_init (tree, tsubst_flags_t = tf_warning_or_error,
- bool = false, tree = NULL_TREE);
+extern tree fold_non_dependent_init (tree, tsubst_flags_t = tf_warning_or_error,
+ bool = false, tree = NULL_TREE);
} // namespace Compile
} // namespace Rust
diff --git a/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h b/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h
index 0ce2142..0434bcf 100644
--- a/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h
+++ b/gcc/rust/checks/errors/borrowck/polonius/rust-polonius.h
@@ -239,31 +239,25 @@ struct Facts
*
* Output is not yet implemented and is only dumped to stdout.
*/
-extern "C" FFI::Output
-polonius_run (FFI::FactsView input, bool dump_enabled);
+extern "C" FFI::Output polonius_run (FFI::FactsView input, bool dump_enabled);
// Helper functions for FFIVector to be used on Rust side
extern "C" {
-FFI::FFIVector<size_t> *
-FFIVector__new ();
+FFI::FFIVector<size_t> *FFIVector__new ();
-FFI::FFIVectorPair *
-FFIVector__new_vec_pair ();
+FFI::FFIVectorPair *FFIVector__new_vec_pair ();
-FFI::FFIVectorTriple *
-FFIVector__new_vec_triple ();
+FFI::FFIVectorTriple *FFIVector__new_vec_triple ();
-void
-FFIVector__push (FFI::FFIVector<size_t> *vector, size_t element);
+void FFIVector__push (FFI::FFIVector<size_t> *vector, size_t element);
void
FFIVector__push_vec_pair (FFI::FFIVectorPair *vector,
FFI::Pair<size_t, FFI::FFIVector<size_t> *> element);
-void
-FFIVector__push_vec_triple (FFI::FFIVectorTriple *vector,
- FFI::Triple<size_t, size_t, size_t> element);
+void FFIVector__push_vec_triple (FFI::FFIVectorTriple *vector,
+ FFI::Triple<size_t, size_t, size_t> element);
}
} // namespace Polonius
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 6b8b2e9..5b22c1a 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
@@ -240,7 +240,8 @@ ExprStmtBuilder::visit (HIR::ArrayExpr &expr)
auto &elems = expr.get_internal_elements ();
switch (elems.get_array_expr_type ())
{
- case HIR::ArrayElems::VALUES: {
+ case HIR::ArrayElems::VALUES:
+ {
auto &elem_vals = (static_cast<HIR::ArrayElemsValues &> (elems));
auto init_values = visit_list (elem_vals.get_values ());
// collect locations
@@ -254,7 +255,8 @@ ExprStmtBuilder::visit (HIR::ArrayExpr &expr)
lookup_type (expr), expr.get_locus ());
break;
}
- case HIR::ArrayElems::COPIED: {
+ case HIR::ArrayElems::COPIED:
+ {
auto &elem_copied = (static_cast<HIR::ArrayElemsCopied &> (elems));
auto init = visit_expr (elem_copied.get_elem_to_copy ());
return_expr (new InitializerExpr ({init}), lookup_type (expr),
@@ -329,6 +331,10 @@ ExprStmtBuilder::visit (HIR::LlvmInlineAsm &expr)
{}
void
+ExprStmtBuilder::visit (HIR::OffsetOf &expr)
+{}
+
+void
ExprStmtBuilder::visit (HIR::MethodCallExpr &expr)
{}
@@ -415,6 +421,18 @@ ExprStmtBuilder::visit (HIR::BlockExpr &block)
}
void
+ExprStmtBuilder::visit (HIR::AnonConst &block)
+{
+ rust_unreachable ();
+}
+
+void
+ExprStmtBuilder::visit (HIR::ConstBlock &block)
+{
+ rust_unreachable ();
+}
+
+void
ExprStmtBuilder::visit (HIR::ContinueExpr &cont)
{
LoopAndLabelCtx info = cont.has_label () ? get_label_ctx (cont.get_label ())
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 5cab3c4..ba5db8b 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
@@ -19,6 +19,7 @@
#ifndef RUST_BIR_BUILDER_EXPR_H
#define RUST_BIR_BUILDER_EXPR_H
+#include "rust-hir-expr.h"
#include "rust-hir-visitor.h"
#include "rust-bir-builder-internal.h"
@@ -84,6 +85,8 @@ protected: // Expr
void visit (HIR::MethodCallExpr &expr) override;
void visit (HIR::FieldAccessExpr &expr) override;
void visit (HIR::BlockExpr &block) override;
+ void visit (HIR::AnonConst &block) override;
+ void visit (HIR::ConstBlock &block) override;
void visit (HIR::ContinueExpr &cont) override;
void visit (HIR::BreakExpr &brk) override;
void visit (HIR::RangeFromToExpr &range) override;
@@ -101,6 +104,7 @@ protected: // Expr
void visit (HIR::IfExprConseqElse &expr) override;
void visit (HIR::InlineAsm &expr) override;
void visit (HIR::LlvmInlineAsm &expr) override;
+ void visit (HIR::OffsetOf &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-internal.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h
index 4df0e14..e2cc2dd 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h
@@ -27,6 +27,8 @@
#include "rust-name-resolver.h"
#include "rust-bir.h"
#include "rust-bir-free-region.h"
+#include "rust-immutable-name-resolution-context.h"
+#include "options.h"
namespace Rust {
@@ -402,19 +404,40 @@ protected: // HIR resolution helpers
template <typename T> NodeId resolve_label (T &expr)
{
NodeId resolved_label;
- bool ok
- = ctx.resolver.lookup_resolved_label (expr.get_mappings ().get_nodeid (),
- &resolved_label);
- rust_assert (ok);
+ if (flag_name_resolution_2_0)
+ {
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
+ auto res = nr_ctx.lookup (expr.get_mappings ().get_nodeid ());
+ rust_assert (res.has_value ());
+ resolved_label = res.value ();
+ }
+ else
+ {
+ bool ok = ctx.resolver.lookup_resolved_label (
+ expr.get_mappings ().get_nodeid (), &resolved_label);
+ rust_assert (ok);
+ }
return resolved_label;
}
template <typename T> PlaceId resolve_variable (T &variable)
{
NodeId variable_id;
- bool ok = ctx.resolver.lookup_resolved_name (
- variable.get_mappings ().get_nodeid (), &variable_id);
- rust_assert (ok);
+ if (flag_name_resolution_2_0)
+ {
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
+ auto res = nr_ctx.lookup (variable.get_mappings ().get_nodeid ());
+ rust_assert (res.has_value ());
+ variable_id = res.value ();
+ }
+ else
+ {
+ bool ok = ctx.resolver.lookup_resolved_name (
+ variable.get_mappings ().get_nodeid (), &variable_id);
+ rust_assert (ok);
+ }
return ctx.place_db.lookup_variable (variable_id);
}
@@ -425,9 +448,20 @@ protected: // HIR resolution helpers
// Unlike variables,
// functions do not have to be declared in PlaceDB before use.
NodeId variable_id;
- bool ok = ctx.resolver.lookup_resolved_name (
- variable.get_mappings ().get_nodeid (), &variable_id);
- rust_assert (ok);
+ if (flag_name_resolution_2_0)
+ {
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
+ auto res = nr_ctx.lookup (variable.get_mappings ().get_nodeid ());
+ rust_assert (res.has_value ());
+ variable_id = res.value ();
+ }
+ else
+ {
+ bool ok = ctx.resolver.lookup_resolved_name (
+ variable.get_mappings ().get_nodeid (), &variable_id);
+ rust_assert (ok);
+ }
if (ty->is<TyTy::FnType> ())
return ctx.place_db.get_constant (ty);
else
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 b7a1555..9108009 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h
@@ -169,6 +169,14 @@ public:
{
return_place (ExprStmtBuilder (ctx).build (expr), expr.get_locus ());
}
+ void visit (HIR::AnonConst &expr) override
+ {
+ return_place (ExprStmtBuilder (ctx).build (expr), expr.get_locus ());
+ }
+ void visit (HIR::ConstBlock &expr) override
+ {
+ return_place (ExprStmtBuilder (ctx).build (expr), expr.get_locus ());
+ }
void visit (HIR::UnsafeBlockExpr &expr) override
{
return_place (ExprStmtBuilder (ctx).build (expr), expr.get_locus ());
@@ -208,6 +216,7 @@ public:
void visit (HIR::InlineAsm &expr) override {}
void visit (HIR::LlvmInlineAsm &expr) override {}
+ void visit (HIR::OffsetOf &expr) override {}
protected: // Illegal at this position.
void visit (HIR::StructExprFieldIdentifier &field) override
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc b/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc
index ee37bb0..2d655f9 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-pattern.cc
@@ -101,7 +101,8 @@ PatternBindingBuilder::visit (HIR::StructPattern &pattern)
{
switch (field->get_item_type ())
{
- case HIR::StructPatternField::TUPLE_PAT: {
+ case HIR::StructPatternField::TUPLE_PAT:
+ {
auto tuple
= static_cast<HIR::StructPatternFieldTuplePat *> (field.get ());
@@ -123,7 +124,8 @@ PatternBindingBuilder::visit (HIR::StructPattern &pattern)
tuple->get_tuple_pattern ().accept_vis (*this);
break;
}
- case HIR::StructPatternField::IDENT_PAT: {
+ case HIR::StructPatternField::IDENT_PAT:
+ {
auto ident_field
= static_cast<HIR::StructPatternFieldIdentPat *> (field.get ());
TyTy::StructFieldType *field_ty = nullptr;
@@ -139,7 +141,8 @@ PatternBindingBuilder::visit (HIR::StructPattern &pattern)
ident_field->get_pattern ().accept_vis (*this);
break;
}
- case HIR::StructPatternField::IDENT: {
+ case HIR::StructPatternField::IDENT:
+ {
auto ident_field
= static_cast<HIR::StructPatternFieldIdent *> (field.get ());
TyTy::StructFieldType *field_ty = nullptr;
@@ -199,13 +202,15 @@ PatternBindingBuilder::visit (HIR::TuplePattern &pattern)
size_t index = 0;
switch (pattern.get_items ().get_item_type ())
{
- case HIR::TuplePatternItems::MULTIPLE: {
+ case HIR::TuplePatternItems::MULTIPLE:
+ {
auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
pattern.get_items ());
visit_tuple_fields (items.get_patterns (), saved, index);
break;
}
- case HIR::TuplePatternItems::RANGED: {
+ case HIR::TuplePatternItems::RANGED:
+ {
auto &items
= static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ());
@@ -244,7 +249,8 @@ PatternBindingBuilder::visit (HIR::TupleStructPattern &pattern)
size_t index = 0;
switch (pattern.get_items ().get_item_type ())
{
- case HIR::TupleStructItems::RANGED: {
+ case HIR::TupleStructItems::RANGED:
+ {
auto &items
= static_cast<HIR::TupleStructItemsRange &> (pattern.get_items ());
@@ -261,7 +267,8 @@ PatternBindingBuilder::visit (HIR::TupleStructPattern &pattern)
visit_tuple_fields (items.get_upper_patterns (), saved, index);
break;
}
- case HIR::TupleStructItems::MULTIPLE: {
+ case HIR::TupleStructItems::MULTIPLE:
+ {
auto &items
= static_cast<HIR::TupleStructItemsNoRange &> (pattern.get_items ());
visit_tuple_fields (items.get_patterns (), saved, index);
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 84311cc..d87ff8c 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h
@@ -21,6 +21,7 @@
#include "rust-bir-builder-internal.h"
#include "rust-bir-builder-expr-stmt.h"
+#include "rust-hir-expr.h"
namespace Rust {
namespace BIR {
@@ -133,6 +134,8 @@ protected:
void visit (HIR::MethodCallExpr &expr) override { rust_unreachable (); }
void visit (HIR::FieldAccessExpr &expr) override { rust_unreachable (); }
void visit (HIR::BlockExpr &expr) override { rust_unreachable (); }
+ void visit (HIR::AnonConst &expr) override { rust_unreachable (); }
+ void visit (HIR::ConstBlock &expr) override { rust_unreachable (); }
void visit (HIR::ClosureExpr &expr) override { rust_unreachable (); }
void visit (HIR::ContinueExpr &expr) override { rust_unreachable (); }
void visit (HIR::BreakExpr &expr) override { rust_unreachable (); }
@@ -154,6 +157,7 @@ protected:
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::OffsetOf &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-dump.cc b/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc
index 3864b81..9a7bb20 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc
@@ -182,7 +182,8 @@ Dump::visit (const Statement &stmt)
statement_place = stmt.get_place ();
switch (stmt.get_kind ())
{
- case Statement::Kind::ASSIGNMENT: {
+ case Statement::Kind::ASSIGNMENT:
+ {
visit_place (stmt.get_place ());
stream << " = ";
stmt.get_expr ().accept_vis (*this);
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h b/gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h
index 32a4cd7..4462d77 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h
@@ -232,42 +232,50 @@ protected: // Main collection entry points (for different categories).
{
switch (stmt.get_kind ())
{
- case Statement::Kind::ASSIGNMENT: {
+ case Statement::Kind::ASSIGNMENT:
+ {
// TODO: for unwind, must had hadning for non-panic-only assignements
issue_write_deep (stmt.get_place ());
visit_assignment_expr (stmt.get_place (), stmt.get_expr ());
break;
}
- case Statement::Kind::SWITCH: {
+ case Statement::Kind::SWITCH:
+ {
issue_read_move (stmt.get_place ());
issue_jumps ();
}
break;
- case Statement::Kind::GOTO: {
+ case Statement::Kind::GOTO:
+ {
issue_jumps ();
}
break;
- case Statement::Kind::RETURN: {
+ case Statement::Kind::RETURN:
+ {
issue_place_access (RETURN_VALUE_PLACE);
issue_locals_dealloc ();
break;
}
- case Statement::Kind::STORAGE_DEAD: {
+ case Statement::Kind::STORAGE_DEAD:
+ {
facts.path_moved_at_base.emplace_back (stmt.get_place ().value,
get_current_point_mid ());
facts.var_defined_at.emplace_back (stmt.get_place ().value,
get_current_point_mid ());
break;
}
- case Statement::Kind::STORAGE_LIVE: {
+ case Statement::Kind::STORAGE_LIVE:
+ {
issue_write_deep (stmt.get_place (), true);
break;
}
- case Statement::Kind::USER_TYPE_ASCRIPTION: {
+ case Statement::Kind::USER_TYPE_ASCRIPTION:
+ {
issue_user_type_constraints (stmt.get_place (), stmt.get_type ());
break;
}
- case Statement::Kind::FAKE_READ: {
+ case Statement::Kind::FAKE_READ:
+ {
issue_place_access (stmt.get_place ());
break;
}
@@ -791,7 +799,8 @@ protected: // Subset helpers.
type->as<const TyTy::SliceType> ()->get_element_type (), region_start,
regions);
case TyTy::FNDEF:
- case TyTy::TUPLE: {
+ case TyTy::TUPLE:
+ {
for (auto &field : type->as<const TyTy::TupleType> ()->get_fields ())
sanitize_constraints (field.get_tyty (), region_start, regions);
}
@@ -815,6 +824,7 @@ protected: // Subset helpers.
case TyTy::PLACEHOLDER:
case TyTy::INFER:
case TyTy::PARAM:
+ case TyTy::CONST:
case TyTy::OPAQUE:
rust_unreachable ();
}
@@ -874,7 +884,7 @@ protected: // Subset helpers.
return region_end;
}
-}; // namespace BIR
+};
} // namespace BIR
} // namespace Rust
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-place.h b/gcc/rust/checks/errors/borrowck/rust-bir-place.h
index dd9e672..2e9103f 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-place.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-place.h
@@ -53,7 +53,7 @@ using Variance = TyTy::VarianceAnalysis::Variance;
/** A unique identifier for a loan in the BIR. */
struct LoanId
{
- uint32_t value;
+ size_t value;
// some overloads for comparision
bool operator== (const LoanId &rhs) const { return value == rhs.value; }
bool operator!= (const LoanId &rhs) const { return !(operator== (rhs)); }
@@ -217,7 +217,7 @@ public:
const T &operator[] (I pid) const { return internal_vector[pid.value]; }
void push_back (T &&param) { internal_vector.push_back (std::move (param)); }
- template <typename... Args> void emplace_back (Args &&... args)
+ template <typename... Args> void emplace_back (Args &&...args)
{
internal_vector.emplace_back (std::forward<Args> (args)...);
}
@@ -471,14 +471,16 @@ private:
case TyTy::FNDEF:
case TyTy::NEVER:
return true;
- case TyTy::TUPLE: {
+ case TyTy::TUPLE:
+ {
auto &fields = ty->as<TyTy::TupleType> ()->get_fields ();
return std::all_of (fields.begin (), fields.end (),
[] (const TyTy::TyVar &field) {
return is_type_copy (field.get_tyty ());
});
}
- case TyTy::ARRAY: {
+ case TyTy::ARRAY:
+ {
return is_type_copy (ty->as<TyTy::ArrayType> ()->get_element_type ());
}
case TyTy::INFER:
@@ -491,6 +493,7 @@ private:
case TyTy::PROJECTION: // TODO: DUNNO
case TyTy::CLOSURE: // TODO: DUNNO
case TyTy::DYNAMIC: // TODO: dunno
+ case TyTy::CONST:
case TyTy::OPAQUE:
return false;
}
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-visitor.h b/gcc/rust/checks/errors/borrowck/rust-bir-visitor.h
index 5dac89e..d405569 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-visitor.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-visitor.h
@@ -51,7 +51,7 @@ template <typename BASE, typename T> class VisitableImpl : public BASE
{
public:
template <typename... Args>
- explicit VisitableImpl (Args &&... args) : BASE (std::forward<Args> (args)...)
+ explicit VisitableImpl (Args &&...args) : BASE (std::forward<Args> (args)...)
{}
void accept_vis (Visitor &visitor) override
diff --git a/gcc/rust/checks/errors/borrowck/rust-function-collector.h b/gcc/rust/checks/errors/borrowck/rust-function-collector.h
index 7cf0952..86f96c1 100644
--- a/gcc/rust/checks/errors/borrowck/rust-function-collector.h
+++ b/gcc/rust/checks/errors/borrowck/rust-function-collector.h
@@ -19,6 +19,7 @@
#ifndef RUST_HIR_FUNCTION_COLLECTOR_H
#define RUST_HIR_FUNCTION_COLLECTOR_H
+#include "rust-hir-expr.h"
#include "rust-hir-item.h"
#include "rust-hir-visitor.h"
#include "rust-hir.h"
@@ -104,6 +105,8 @@ public:
void visit (HIR::MethodCallExpr &expr) override {}
void visit (HIR::FieldAccessExpr &expr) override {}
void visit (HIR::BlockExpr &expr) override {}
+ void visit (HIR::AnonConst &expr) override {}
+ void visit (HIR::ConstBlock &expr) override {}
void visit (HIR::ContinueExpr &expr) override {}
void visit (HIR::BreakExpr &expr) override {}
void visit (HIR::RangeFromToExpr &expr) override {}
@@ -124,6 +127,7 @@ public:
void visit (HIR::AsyncBlockExpr &expr) override {}
void visit (HIR::InlineAsm &expr) override {}
void visit (HIR::LlvmInlineAsm &expr) override {}
+ void visit (HIR::OffsetOf &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-check.cc b/gcc/rust/checks/errors/privacy/rust-privacy-check.cc
index 3d25459..5291276 100644
--- a/gcc/rust/checks/errors/privacy/rust-privacy-check.cc
+++ b/gcc/rust/checks/errors/privacy/rust-privacy-check.cc
@@ -25,8 +25,7 @@
#include "rust-pub-restricted-visitor.h"
#include "rust-privacy-reporter.h"
-extern bool
-saw_errors (void);
+extern bool saw_errors (void);
namespace Rust {
namespace Privacy {
diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-ctx.h b/gcc/rust/checks/errors/privacy/rust-privacy-ctx.h
index a506613f..9699ac4 100644
--- a/gcc/rust/checks/errors/privacy/rust-privacy-ctx.h
+++ b/gcc/rust/checks/errors/privacy/rust-privacy-ctx.h
@@ -71,8 +71,7 @@ private:
#if CHECKING_P
namespace selftest {
-void
-rust_privacy_ctx_test (void);
+void rust_privacy_ctx_test (void);
}
#endif // !CHECKING_P
diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
index 2a10053..4af9639 100644
--- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
+++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
@@ -157,7 +157,8 @@ PrivacyReporter::check_for_privacy_violation (const NodeId &use_id,
{
case ModuleVisibility::Public:
break;
- case ModuleVisibility::Restricted: {
+ case ModuleVisibility::Restricted:
+ {
// If we are in the crate, everything is restricted correctly, but we
// can't get a module for it
if (!current_module.has_value ())
@@ -215,12 +216,14 @@ PrivacyReporter::check_base_type_privacy (Analysis::NodeMapping &node_mappings,
case TyTy::USIZE:
case TyTy::ISIZE:
case TyTy::ADT:
- case TyTy::STR: {
+ case TyTy::STR:
+ {
auto ref_id = ty->get_ref ();
if (auto lookup_id = mappings.lookup_hir_to_node (ref_id))
return check_for_privacy_violation (*lookup_id, locus);
- rust_unreachable ();
}
+ break;
+
case TyTy::REF:
return recursive_check (
static_cast<const TyTy::ReferenceType *> (ty)->get_base ());
@@ -243,7 +246,8 @@ PrivacyReporter::check_base_type_privacy (Analysis::NodeMapping &node_mappings,
static_cast<const TyTy::TupleType *> (ty)->get_fields ())
recursive_check (param.get_tyty ());
return;
- case TyTy::PLACEHOLDER: {
+ case TyTy::PLACEHOLDER:
+ {
const auto p = static_cast<const TyTy::PlaceholderType *> (ty);
if (!p->can_resolve ())
return;
@@ -273,6 +277,8 @@ PrivacyReporter::check_base_type_privacy (Analysis::NodeMapping &node_mappings,
return;
case TyTy::OPAQUE:
return;
+ case TyTy::CONST:
+ return;
case TyTy::ERROR:
return;
}
@@ -310,6 +316,12 @@ PrivacyReporter::visit (HIR::LlvmInlineAsm &)
{}
void
+PrivacyReporter::visit (HIR::OffsetOf &expr)
+{
+ // TODO: Do we have to do anything?
+}
+
+void
PrivacyReporter::visit (HIR::TypePath &path)
{
check_for_privacy_violation (path.get_mappings ().get_nodeid (),
@@ -413,7 +425,8 @@ PrivacyReporter::visit (HIR::ArrayExpr &expr)
HIR::ArrayElems &elements = expr.get_internal_elements ();
switch (elements.get_array_expr_type ())
{
- case HIR::ArrayElems::ArrayExprType::VALUES: {
+ case HIR::ArrayElems::ArrayExprType::VALUES:
+ {
auto &elems = static_cast<HIR::ArrayElemsValues &> (elements);
for (auto &value : elems.get_values ())
value->accept_vis (*this);
@@ -518,6 +531,18 @@ PrivacyReporter::visit (HIR::BlockExpr &expr)
}
void
+PrivacyReporter::visit (HIR::AnonConst &expr)
+{
+ expr.get_inner_expr ().accept_vis (*this);
+}
+
+void
+PrivacyReporter::visit (HIR::ConstBlock &expr)
+{
+ expr.get_const_expr ().accept_vis (*this);
+}
+
+void
PrivacyReporter::visit (HIR::ContinueExpr &)
{}
diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
index 7df2cf4..72716a6 100644
--- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
+++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
@@ -19,6 +19,7 @@
#ifndef RUST_PRIVACY_REPORTER_H
#define RUST_PRIVACY_REPORTER_H
+#include "rust-hir-expr.h"
#include "rust-hir-map.h"
#include "rust-hir-visitor.h"
#include "rust-mapping-common.h"
@@ -106,6 +107,8 @@ types
virtual void visit (HIR::MethodCallExpr &expr);
virtual void visit (HIR::FieldAccessExpr &expr);
virtual void visit (HIR::BlockExpr &expr);
+ virtual void visit (HIR::AnonConst &expr);
+ virtual void visit (HIR::ConstBlock &expr);
virtual void visit (HIR::ContinueExpr &expr);
virtual void visit (HIR::BreakExpr &expr);
virtual void visit (HIR::RangeFromToExpr &expr);
@@ -126,6 +129,7 @@ types
virtual void visit (HIR::AsyncBlockExpr &expr);
virtual void visit (HIR::InlineAsm &expr);
virtual void visit (HIR::LlvmInlineAsm &expr);
+ virtual void visit (HIR::OffsetOf &expr);
virtual void visit (HIR::EnumItemTuple &);
virtual void visit (HIR::EnumItemStruct &);
diff --git a/gcc/rust/checks/errors/privacy/rust-reachability.cc b/gcc/rust/checks/errors/privacy/rust-reachability.cc
index 1e57674..223c77b 100644
--- a/gcc/rust/checks/errors/privacy/rust-reachability.cc
+++ b/gcc/rust/checks/errors/privacy/rust-reachability.cc
@@ -158,7 +158,8 @@ ReachabilityVisitor::visit (HIR::Enum &enum_item)
switch (variant->get_enum_item_kind ())
{
- case HIR::EnumItem::Tuple: {
+ case HIR::EnumItem::Tuple:
+ {
// Should we update the fields only if they are public? Similarly to
// what we do in the ReachabilityVisitor for HIR::TupleStruct?
auto tuple_variant
@@ -167,7 +168,8 @@ ReachabilityVisitor::visit (HIR::Enum &enum_item)
ctx.update_reachability (field.get_mappings (), variant_reach);
break;
}
- case HIR::EnumItem::Struct: {
+ case HIR::EnumItem::Struct:
+ {
// Should we update the fields only if they are public? Similarly to
// what we do in the ReachabilityVisitor for HIR::StructStruct?
auto struct_variant
diff --git a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc
index f0da745..c59763d 100644
--- a/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc
+++ b/gcc/rust/checks/errors/privacy/rust-visibility-resolver.cc
@@ -127,7 +127,8 @@ VisibilityResolver::resolve_visibility (const HIR::Visibility &visibility,
case HIR::Visibility::PUBLIC:
to_resolve = ModuleVisibility::create_public ();
return true;
- case HIR::Visibility::RESTRICTED: {
+ case HIR::Visibility::RESTRICTED:
+ {
// FIXME: We also need to handle 2015 vs 2018 edition conflicts
auto id = UNKNOWN_DEFID;
auto result = resolve_module_path (visibility.get_path (), id);
diff --git a/gcc/rust/checks/errors/rust-const-checker.cc b/gcc/rust/checks/errors/rust-const-checker.cc
index 3716ea5..c40f9db 100644
--- a/gcc/rust/checks/errors/rust-const-checker.cc
+++ b/gcc/rust/checks/errors/rust-const-checker.cc
@@ -417,6 +417,26 @@ ConstChecker::visit (BlockExpr &expr)
}
void
+ConstChecker::visit (AnonConst &expr)
+{
+ const_context.enter (expr.get_mappings ().get_hirid ());
+
+ expr.get_inner_expr ().accept_vis (*this);
+
+ const_context.exit ();
+}
+
+void
+ConstChecker::visit (ConstBlock &expr)
+{
+ const_context.enter (expr.get_mappings ().get_hirid ());
+
+ expr.get_const_expr ().accept_vis (*this);
+
+ const_context.exit ();
+}
+
+void
ConstChecker::visit (ContinueExpr &)
{}
@@ -541,6 +561,10 @@ ConstChecker::visit (LlvmInlineAsm &)
{}
void
+ConstChecker::visit (OffsetOf &)
+{}
+
+void
ConstChecker::visit (TypeParam &)
{}
diff --git a/gcc/rust/checks/errors/rust-const-checker.h b/gcc/rust/checks/errors/rust-const-checker.h
index b954330..eb63095 100644
--- a/gcc/rust/checks/errors/rust-const-checker.h
+++ b/gcc/rust/checks/errors/rust-const-checker.h
@@ -113,6 +113,8 @@ private:
virtual void visit (FieldAccessExpr &expr) override;
virtual void visit (ClosureExpr &expr) override;
virtual void visit (BlockExpr &expr) override;
+ virtual void visit (AnonConst &expr) override;
+ virtual void visit (ConstBlock &expr) override;
virtual void visit (ContinueExpr &expr) override;
virtual void visit (BreakExpr &expr) override;
virtual void visit (RangeFromToExpr &expr) override;
@@ -133,6 +135,7 @@ private:
virtual void visit (AsyncBlockExpr &expr) override;
virtual void visit (InlineAsm &expr) override;
virtual void visit (LlvmInlineAsm &expr) override;
+ virtual void visit (OffsetOf &expr) override;
virtual void visit (TypeParam &param) override;
virtual void visit (ConstGenericParam &param) override;
diff --git a/gcc/rust/checks/errors/rust-feature.cc b/gcc/rust/checks/errors/rust-feature.cc
index 441a1b2..071d3f8 100644
--- a/gcc/rust/checks/errors/rust-feature.cc
+++ b/gcc/rust/checks/errors/rust-feature.cc
@@ -84,7 +84,7 @@ const std::map<std::string, Feature::Name> Feature::name_hash_map = {
{"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>
Feature::as_name (const std::string &name)
diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
index 648bc07..2566971 100644
--- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
+++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
@@ -295,6 +295,18 @@ PatternChecker::visit (BlockExpr &expr)
}
void
+PatternChecker::visit (AnonConst &expr)
+{
+ expr.get_inner_expr ().accept_vis (*this);
+}
+
+void
+PatternChecker::visit (ConstBlock &expr)
+{
+ expr.get_const_expr ().accept_vis (*this);
+}
+
+void
PatternChecker::visit (ContinueExpr &)
{}
@@ -427,6 +439,10 @@ PatternChecker::visit (LlvmInlineAsm &expr)
{}
void
+PatternChecker::visit (OffsetOf &expr)
+{}
+
+void
PatternChecker::visit (TypeParam &)
{}
@@ -728,23 +744,27 @@ Constructor::is_covered_by (const Constructor &o) const
switch (kind)
{
- case ConstructorKind::VARIANT: {
+ case ConstructorKind::VARIANT:
+ {
rust_assert (kind == ConstructorKind::VARIANT);
return variant_idx == o.variant_idx;
}
break;
- case ConstructorKind::INT_RANGE: {
+ case ConstructorKind::INT_RANGE:
+ {
rust_assert (kind == ConstructorKind::INT_RANGE);
return int_range.lo >= o.int_range.lo && int_range.hi <= o.int_range.hi;
}
break;
- case ConstructorKind::WILDCARD: {
+ case ConstructorKind::WILDCARD:
+ {
// TODO: wildcard is covered by a variant of enum with a single
// variant
return false;
}
break;
- case ConstructorKind::STRUCT: {
+ case ConstructorKind::STRUCT:
+ {
// Struct pattern is always covered by a other struct constructor.
return true;
}
@@ -900,19 +920,22 @@ PlaceInfo::specialize (const Constructor &c) const
switch (c.get_kind ())
{
case Constructor::ConstructorKind::WILDCARD:
- case Constructor::ConstructorKind::INT_RANGE: {
+ case Constructor::ConstructorKind::INT_RANGE:
+ {
return {};
}
break;
case Constructor::ConstructorKind::STRUCT:
- case Constructor::ConstructorKind::VARIANT: {
+ case Constructor::ConstructorKind::VARIANT:
+ {
rust_assert (ty->get_kind () == TyTy::TypeKind::ADT);
TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (ty);
switch (adt->get_adt_kind ())
{
case TyTy::ADTType::ADTKind::ENUM:
case TyTy::ADTType::ADTKind::STRUCT_STRUCT:
- case TyTy::ADTType::ADTKind::TUPLE_STRUCT: {
+ case TyTy::ADTType::ADTKind::TUPLE_STRUCT:
+ {
TyTy::VariantDef *variant
= adt->get_variants ().at (c.get_variant_index ());
if (variant->get_variant_type ()
@@ -926,14 +949,16 @@ PlaceInfo::specialize (const Constructor &c) const
return new_place_infos;
}
break;
- case TyTy::ADTType::ADTKind::UNION: {
+ case TyTy::ADTType::ADTKind::UNION:
+ {
// TODO: support unions
rust_unreachable ();
}
}
}
break;
- default: {
+ default:
+ {
rust_unreachable ();
}
break;
@@ -991,7 +1016,8 @@ WitnessPat::to_string () const
{
switch (ctor.get_kind ())
{
- case Constructor::ConstructorKind::STRUCT: {
+ case Constructor::ConstructorKind::STRUCT:
+ {
TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (ty);
TyTy::VariantDef *variant
= adt->get_variants ().at (ctor.get_variant_index ());
@@ -1016,7 +1042,8 @@ WitnessPat::to_string () const
return buf;
}
break;
- case Constructor::ConstructorKind::VARIANT: {
+ case Constructor::ConstructorKind::VARIANT:
+ {
std::string buf;
TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (ty);
buf += adt->get_identifier ();
@@ -1026,11 +1053,13 @@ WitnessPat::to_string () const
switch (variant->get_variant_type ())
{
- case TyTy::VariantDef::VariantType::NUM: {
+ case TyTy::VariantDef::VariantType::NUM:
+ {
return buf;
}
break;
- case TyTy::VariantDef::VariantType::TUPLE: {
+ case TyTy::VariantDef::VariantType::TUPLE:
+ {
buf += "(";
for (size_t i = 0; i < fields.size (); i++)
{
@@ -1042,7 +1071,8 @@ WitnessPat::to_string () const
return buf;
}
break;
- case TyTy::VariantDef::VariantType::STRUCT: {
+ case TyTy::VariantDef::VariantType::STRUCT:
+ {
buf += " {";
if (!fields.empty ())
buf += " ";
@@ -1061,7 +1091,8 @@ WitnessPat::to_string () const
buf += "}";
}
break;
- default: {
+ default:
+ {
rust_unreachable ();
}
break;
@@ -1069,21 +1100,25 @@ WitnessPat::to_string () const
return buf;
}
break;
- case Constructor::ConstructorKind::INT_RANGE: {
+ case Constructor::ConstructorKind::INT_RANGE:
+ {
// TODO: implement
rust_unreachable ();
}
break;
- case Constructor::ConstructorKind::WILDCARD: {
+ case Constructor::ConstructorKind::WILDCARD:
+ {
return "_";
}
break;
- case Constructor::ConstructorKind::REFERENCE: {
+ case Constructor::ConstructorKind::REFERENCE:
+ {
// TODO: implement
rust_unreachable ();
}
break;
- default: {
+ default:
+ {
rust_unreachable ();
}
break;
@@ -1100,12 +1135,14 @@ WitnessMatrix::apply_constructor (const Constructor &ctor,
// TODO: only support struct and variant ctor for now.
switch (ctor.get_kind ())
{
- case Constructor::ConstructorKind::WILDCARD: {
+ case Constructor::ConstructorKind::WILDCARD:
+ {
arity = 0;
}
break;
case Constructor::ConstructorKind::STRUCT:
- case Constructor::ConstructorKind::VARIANT: {
+ case Constructor::ConstructorKind::VARIANT:
+ {
if (ty->get_kind () == TyTy::TypeKind::ADT)
{
TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (ty);
@@ -1118,7 +1155,8 @@ WitnessMatrix::apply_constructor (const Constructor &ctor,
}
}
break;
- default: {
+ default:
+ {
rust_unreachable ();
}
}
@@ -1160,9 +1198,9 @@ WitnessMatrix::extend (const WitnessMatrix &other)
}
// forward declarations
-static DeconstructedPat
-lower_pattern (Resolver::TypeCheckContext *ctx, HIR::Pattern &pattern,
- TyTy::BaseType *scrutinee_ty);
+static DeconstructedPat lower_pattern (Resolver::TypeCheckContext *ctx,
+ HIR::Pattern &pattern,
+ TyTy::BaseType *scrutinee_ty);
static DeconstructedPat
lower_tuple_pattern (Resolver::TypeCheckContext *ctx,
@@ -1175,7 +1213,8 @@ lower_tuple_pattern (Resolver::TypeCheckContext *ctx,
std::vector<DeconstructedPat> fields;
switch (elems.get_item_type ())
{
- case HIR::TupleStructItems::ItemType::MULTIPLE: {
+ case HIR::TupleStructItems::ItemType::MULTIPLE:
+ {
HIR::TupleStructItemsNoRange &multiple
= static_cast<HIR::TupleStructItemsNoRange &> (elems);
@@ -1191,12 +1230,14 @@ lower_tuple_pattern (Resolver::TypeCheckContext *ctx,
return DeconstructedPat (ctor, arity, fields, pattern.get_locus ());
}
break;
- case HIR::TupleStructItems::ItemType::RANGED: {
+ case HIR::TupleStructItems::ItemType::RANGED:
+ {
// TODO: ranged tuple struct items
rust_unreachable ();
}
break;
- default: {
+ default:
+ {
rust_unreachable ();
}
}
@@ -1227,7 +1268,8 @@ lower_struct_pattern (Resolver::TypeCheckContext *ctx,
{
switch (elem->get_item_type ())
{
- case HIR::StructPatternField::ItemType::IDENT: {
+ case HIR::StructPatternField::ItemType::IDENT:
+ {
HIR::StructPatternFieldIdent *ident
= static_cast<HIR::StructPatternFieldIdent *> (elem.get ());
int field_idx
@@ -1236,7 +1278,8 @@ lower_struct_pattern (Resolver::TypeCheckContext *ctx,
= DeconstructedPat::make_wildcard (pattern.get_locus ());
}
break;
- case HIR::StructPatternField::ItemType::IDENT_PAT: {
+ case HIR::StructPatternField::ItemType::IDENT_PAT:
+ {
HIR::StructPatternFieldIdentPat *ident_pat
= static_cast<HIR::StructPatternFieldIdentPat *> (elem.get ());
int field_idx
@@ -1246,12 +1289,14 @@ lower_struct_pattern (Resolver::TypeCheckContext *ctx,
variant->get_fields ().at (field_idx)->get_field_type ());
}
break;
- case HIR::StructPatternField::ItemType::TUPLE_PAT: {
+ case HIR::StructPatternField::ItemType::TUPLE_PAT:
+ {
// TODO: tuple: pat
rust_unreachable ();
}
break;
- default: {
+ default:
+ {
rust_unreachable ();
}
}
@@ -1268,11 +1313,13 @@ lower_pattern (Resolver::TypeCheckContext *ctx, HIR::Pattern &pattern,
switch (pat_type)
{
case HIR::Pattern::PatternType::WILDCARD:
- case HIR::Pattern::PatternType::IDENTIFIER: {
+ case HIR::Pattern::PatternType::IDENTIFIER:
+ {
return DeconstructedPat::make_wildcard (pattern.get_locus ());
}
break;
- case HIR::Pattern::PatternType::PATH: {
+ case HIR::Pattern::PatternType::PATH:
+ {
// TODO: support constants, associated constants, enum variants and
// structs
// https://doc.rust-lang.org/reference/patterns.html#path-patterns
@@ -1280,13 +1327,15 @@ lower_pattern (Resolver::TypeCheckContext *ctx, HIR::Pattern &pattern,
return DeconstructedPat::make_wildcard (pattern.get_locus ());
}
break;
- case HIR::Pattern::PatternType::REFERENCE: {
+ case HIR::Pattern::PatternType::REFERENCE:
+ {
// TODO: unimplemented. Treat this pattern as wildcard for now.
return DeconstructedPat::make_wildcard (pattern.get_locus ());
}
break;
case HIR::Pattern::PatternType::STRUCT:
- case HIR::Pattern::PatternType::TUPLE_STRUCT: {
+ case HIR::Pattern::PatternType::TUPLE_STRUCT:
+ {
HirId path_id = UNKNOWN_HIRID;
if (pat_type == HIR::Pattern::PatternType::STRUCT)
{
@@ -1343,37 +1392,44 @@ lower_pattern (Resolver::TypeCheckContext *ctx, HIR::Pattern &pattern,
}
}
break;
- case HIR::Pattern::PatternType::TUPLE: {
+ case HIR::Pattern::PatternType::TUPLE:
+ {
// TODO: unimplemented. Treat this pattern as wildcard for now.
return DeconstructedPat::make_wildcard (pattern.get_locus ());
}
break;
- case HIR::Pattern::PatternType::SLICE: {
+ case HIR::Pattern::PatternType::SLICE:
+ {
// TODO: unimplemented. Treat this pattern as wildcard for now.
return DeconstructedPat::make_wildcard (pattern.get_locus ());
}
break;
- case HIR::Pattern::PatternType::ALT: {
+ case HIR::Pattern::PatternType::ALT:
+ {
// TODO: unimplemented. Treat this pattern as wildcard for now.
return DeconstructedPat::make_wildcard (pattern.get_locus ());
}
break;
- case HIR::Pattern::PatternType::LITERAL: {
+ case HIR::Pattern::PatternType::LITERAL:
+ {
// TODO: unimplemented. Treat this pattern as wildcard for now.
return DeconstructedPat::make_wildcard (pattern.get_locus ());
}
break;
- case HIR::Pattern::PatternType::RANGE: {
+ case HIR::Pattern::PatternType::RANGE:
+ {
// TODO: unimplemented. Treat this pattern as wildcard for now.
return DeconstructedPat::make_wildcard (pattern.get_locus ());
}
break;
- case HIR::Pattern::PatternType::GROUPED: {
+ case HIR::Pattern::PatternType::GROUPED:
+ {
// TODO: unimplemented. Treat this pattern as wildcard for now.
return DeconstructedPat::make_wildcard (pattern.get_locus ());
}
break;
- default: {
+ default:
+ {
rust_unreachable ();
}
}
diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h
index 6d60ced..dd44abc 100644
--- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h
+++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h
@@ -33,9 +33,9 @@ namespace Analysis {
using namespace HIR;
-void
-check_match_usefulness (Resolver::TypeCheckContext *ctx,
- TyTy::BaseType *scrutinee_ty, HIR::MatchExpr &expr);
+void check_match_usefulness (Resolver::TypeCheckContext *ctx,
+ TyTy::BaseType *scrutinee_ty,
+ HIR::MatchExpr &expr);
class PatternChecker : public HIR::HIRFullVisitor
{
@@ -86,6 +86,8 @@ private:
virtual void visit (MethodCallExpr &expr) override;
virtual void visit (FieldAccessExpr &expr) override;
virtual void visit (BlockExpr &expr) override;
+ virtual void visit (AnonConst &expr) override;
+ virtual void visit (ConstBlock &expr) override;
virtual void visit (ClosureExpr &expr) override;
virtual void visit (ContinueExpr &expr) override;
virtual void visit (BreakExpr &expr) override;
@@ -107,6 +109,7 @@ private:
virtual void visit (AsyncBlockExpr &expr) override;
virtual void visit (InlineAsm &expr) override;
virtual void visit (LlvmInlineAsm &expr) override;
+ virtual void visit (OffsetOf &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-readonly-check2.cc b/gcc/rust/checks/errors/rust-readonly-check2.cc
new file mode 100644
index 0000000..2fa92ae
--- /dev/null
+++ b/gcc/rust/checks/errors/rust-readonly-check2.cc
@@ -0,0 +1,253 @@
+// 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-readonly-check2.h"
+#include "rust-hir-expr.h"
+#include "rust-hir-node.h"
+#include "rust-hir-path.h"
+#include "rust-hir-map.h"
+#include "rust-hir-pattern.h"
+#include "rust-mapping-common.h"
+#include "rust-system.h"
+#include "rust-immutable-name-resolution-context.h"
+#include "rust-tyty.h"
+
+namespace Rust {
+namespace HIR {
+
+static std::set<HirId> already_assigned_variables = {};
+
+ReadonlyChecker::ReadonlyChecker ()
+ : resolver (*Resolver::Resolver::get ()),
+ mappings (Analysis::Mappings::get ()),
+ context (*Resolver::TypeCheckContext::get ())
+{}
+
+void
+ReadonlyChecker::go (Crate &crate)
+{
+ for (auto &item : crate.get_items ())
+ item->accept_vis (*this);
+}
+
+void
+ReadonlyChecker::visit (AssignmentExpr &expr)
+{
+ Expr &lhs = expr.get_lhs ();
+ mutable_context.enter (expr.get_mappings ().get_hirid ());
+ lhs.accept_vis (*this);
+ mutable_context.exit ();
+}
+
+void
+ReadonlyChecker::visit (PathInExpression &expr)
+{
+ if (!mutable_context.is_in_context ())
+ return;
+
+ NodeId ast_node_id = expr.get_mappings ().get_nodeid ();
+ NodeId def_id;
+
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
+ if (auto id = nr_ctx.lookup (ast_node_id))
+ def_id = *id;
+ else
+ return;
+
+ auto hir_id = mappings.lookup_node_to_hir (def_id);
+ if (!hir_id)
+ return;
+
+ // Check if the local variable is mutable.
+ auto maybe_pattern = mappings.lookup_hir_pattern (*hir_id);
+ if (maybe_pattern
+ && maybe_pattern.value ()->get_pattern_type ()
+ == HIR::Pattern::PatternType::IDENTIFIER)
+ check_variable (static_cast<IdentifierPattern *> (maybe_pattern.value ()),
+ expr.get_locus ());
+
+ // Check if the static item is mutable.
+ auto maybe_item = mappings.lookup_hir_item (*hir_id);
+ if (maybe_item
+ && maybe_item.value ()->get_item_kind () == HIR::Item::ItemKind::Static)
+ {
+ auto static_item = static_cast<HIR::StaticItem *> (*maybe_item);
+ if (!static_item->is_mut ())
+ rust_error_at (expr.get_locus (),
+ "assignment of read-only location '%s'",
+ static_item->get_identifier ().as_string ().c_str ());
+ }
+
+ // Check if the constant item is mutable.
+ if (maybe_item
+ && maybe_item.value ()->get_item_kind () == HIR::Item::ItemKind::Constant)
+ {
+ auto const_item = static_cast<HIR::ConstantItem *> (*maybe_item);
+ rust_error_at (expr.get_locus (), "assignment of read-only location '%s'",
+ const_item->get_identifier ().as_string ().c_str ());
+ }
+}
+
+void
+ReadonlyChecker::check_variable (IdentifierPattern *pattern,
+ location_t assigned_loc)
+{
+ if (!mutable_context.is_in_context ())
+ return;
+ if (pattern->is_mut ())
+ return;
+
+ auto hir_id = pattern->get_mappings ().get_hirid ();
+ if (already_assigned_variables.count (hir_id) > 0)
+ rust_error_at (assigned_loc, "assignment of read-only variable '%s'",
+ pattern->as_string ().c_str ());
+ already_assigned_variables.insert (hir_id);
+}
+
+void
+ReadonlyChecker::collect_assignment_identifier (IdentifierPattern &pattern,
+ bool has_init_expr)
+{
+ if (has_init_expr)
+ {
+ HirId pattern_id = pattern.get_mappings ().get_hirid ();
+ already_assigned_variables.insert (pattern_id);
+ }
+}
+
+void
+ReadonlyChecker::collect_assignment_tuple (TuplePattern &tuple_pattern,
+ bool has_init_expr)
+{
+ switch (tuple_pattern.get_items ().get_item_type ())
+ {
+ case HIR::TuplePatternItems::ItemType::MULTIPLE:
+ {
+ auto &items = static_cast<HIR::TuplePatternItemsMultiple &> (
+ tuple_pattern.get_items ());
+ for (auto &sub : items.get_patterns ())
+ {
+ collect_assignment (*sub, has_init_expr);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void
+ReadonlyChecker::collect_assignment (Pattern &pattern, bool has_init_expr)
+{
+ switch (pattern.get_pattern_type ())
+ {
+ case HIR::Pattern::PatternType::IDENTIFIER:
+ {
+ collect_assignment_identifier (static_cast<IdentifierPattern &> (
+ pattern),
+ has_init_expr);
+ }
+ break;
+ case HIR::Pattern::PatternType::TUPLE:
+ {
+ auto &tuple_pattern = static_cast<HIR::TuplePattern &> (pattern);
+ collect_assignment_tuple (tuple_pattern, has_init_expr);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void
+ReadonlyChecker::visit (LetStmt &stmt)
+{
+ HIR::Pattern &pattern = stmt.get_pattern ();
+ collect_assignment (pattern, stmt.has_init_expr ());
+}
+
+void
+ReadonlyChecker::visit (FieldAccessExpr &expr)
+{
+ if (mutable_context.is_in_context ())
+ {
+ expr.get_receiver_expr ().accept_vis (*this);
+ }
+}
+
+void
+ReadonlyChecker::visit (TupleIndexExpr &expr)
+{
+ if (mutable_context.is_in_context ())
+ {
+ expr.get_tuple_expr ().accept_vis (*this);
+ }
+}
+
+void
+ReadonlyChecker::visit (ArrayIndexExpr &expr)
+{
+ if (mutable_context.is_in_context ())
+ {
+ expr.get_array_expr ().accept_vis (*this);
+ }
+}
+
+void
+ReadonlyChecker::visit (TupleExpr &expr)
+{
+ if (mutable_context.is_in_context ())
+ {
+ // TODO: Add check for tuple expression
+ }
+}
+
+void
+ReadonlyChecker::visit (LiteralExpr &expr)
+{
+ if (mutable_context.is_in_context ())
+ {
+ rust_error_at (expr.get_locus (), "assignment of read-only location");
+ }
+}
+
+void
+ReadonlyChecker::visit (DereferenceExpr &expr)
+{
+ if (!mutable_context.is_in_context ())
+ return;
+ TyTy::BaseType *to_deref_type;
+ auto to_deref = expr.get_expr ().get_mappings ().get_hirid ();
+ if (!context.lookup_type (to_deref, &to_deref_type))
+ return;
+ if (to_deref_type->get_kind () == TyTy::TypeKind::REF)
+ {
+ auto ref_type = static_cast<TyTy::ReferenceType *> (to_deref_type);
+ if (!ref_type->is_mutable ())
+ rust_error_at (expr.get_locus (), "assignment of read-only location");
+ }
+ if (to_deref_type->get_kind () == TyTy::TypeKind::POINTER)
+ {
+ auto ptr_type = static_cast<TyTy::PointerType *> (to_deref_type);
+ if (!ptr_type->is_mutable ())
+ rust_error_at (expr.get_locus (), "assignment of read-only location");
+ }
+}
+} // namespace HIR
+} // namespace Rust
diff --git a/gcc/rust/checks/errors/rust-readonly-check2.h b/gcc/rust/checks/errors/rust-readonly-check2.h
new file mode 100644
index 0000000..06af9db
--- /dev/null
+++ b/gcc/rust/checks/errors/rust-readonly-check2.h
@@ -0,0 +1,67 @@
+// 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-hir-visitor.h"
+#include "rust-name-resolver.h"
+#include "rust-stacked-contexts.h"
+#include "rust-hir-type-check.h"
+
+namespace Rust {
+namespace HIR {
+class ReadonlyChecker : public DefaultHIRVisitor
+{
+public:
+ ReadonlyChecker ();
+
+ void go (HIR::Crate &crate);
+
+private:
+ enum class lvalue_use
+ {
+ assign,
+ increment,
+ decrement,
+ };
+
+ Resolver::Resolver &resolver;
+ Analysis::Mappings &mappings;
+ Resolver::TypeCheckContext &context;
+ StackedContexts<HirId> mutable_context;
+
+ using DefaultHIRVisitor::visit;
+
+ virtual void visit (AssignmentExpr &expr) override;
+ virtual void visit (PathInExpression &expr) override;
+ virtual void visit (FieldAccessExpr &expr) override;
+ virtual void visit (ArrayIndexExpr &expr) override;
+ virtual void visit (TupleExpr &expr) override;
+ virtual void visit (TupleIndexExpr &expr) override;
+ virtual void visit (LetStmt &stmt) override;
+ virtual void visit (LiteralExpr &expr) override;
+ virtual void visit (DereferenceExpr &expr) override;
+
+ void collect_assignment (Pattern &pattern, bool has_init_expr);
+ void collect_assignment_identifier (IdentifierPattern &pattern,
+ bool has_init_expr);
+ void collect_assignment_tuple (TuplePattern &pattern, bool has_init_expr);
+
+ void check_variable (IdentifierPattern *pattern, location_t assigned_loc);
+};
+
+} // namespace HIR
+} // namespace Rust \ No newline at end of file
diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.cc b/gcc/rust/checks/errors/rust-unsafe-checker.cc
index 46eef11..405c59b 100644
--- a/gcc/rust/checks/errors/rust-unsafe-checker.cc
+++ b/gcc/rust/checks/errors/rust-unsafe-checker.cc
@@ -540,6 +540,18 @@ UnsafeChecker::visit (BlockExpr &expr)
}
void
+UnsafeChecker::visit (AnonConst &expr)
+{
+ expr.get_inner_expr ().accept_vis (*this);
+}
+
+void
+UnsafeChecker::visit (ConstBlock &expr)
+{
+ expr.get_const_expr ().accept_vis (*this);
+}
+
+void
UnsafeChecker::visit (ContinueExpr &)
{}
@@ -682,6 +694,12 @@ UnsafeChecker::visit (LlvmInlineAsm &expr)
}
void
+UnsafeChecker::visit (OffsetOf &expr)
+{
+ // nothing to do, offset_of!() is safe
+}
+
+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 9a8fb7c..dc3b482 100644
--- a/gcc/rust/checks/errors/rust-unsafe-checker.h
+++ b/gcc/rust/checks/errors/rust-unsafe-checker.h
@@ -95,6 +95,8 @@ private:
virtual void visit (FieldAccessExpr &expr) override;
virtual void visit (ClosureExpr &expr) override;
virtual void visit (BlockExpr &expr) override;
+ virtual void visit (AnonConst &expr) override;
+ virtual void visit (ConstBlock &expr) override;
virtual void visit (ContinueExpr &expr) override;
virtual void visit (BreakExpr &expr) override;
virtual void visit (RangeFromToExpr &expr) override;
@@ -115,6 +117,7 @@ private:
virtual void visit (AsyncBlockExpr &expr) override;
virtual void visit (InlineAsm &expr) override;
virtual void visit (LlvmInlineAsm &expr) override;
+ virtual void visit (OffsetOf &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/lints/rust-lint-unused-var.cc b/gcc/rust/checks/lints/rust-lint-unused-var.cc
index 896eeb0..08596f1 100644
--- a/gcc/rust/checks/lints/rust-lint-unused-var.cc
+++ b/gcc/rust/checks/lints/rust-lint-unused-var.cc
@@ -31,6 +31,7 @@ check_decl (tree *t)
tree var_name = DECL_NAME (*t);
const char *var_name_ptr = IDENTIFIER_POINTER (var_name);
bool starts_with_under_score = strncmp (var_name_ptr, "_", 1) == 0;
+ bool is_self = strcmp (var_name_ptr, "self") == 0;
bool is_constant = TREE_CODE (*t) == CONST_DECL;
// if (!is_constant)
@@ -43,7 +44,8 @@ check_decl (tree *t)
// starts_with_under_score ? "true" : "false", var_name_ptr);
// }
- if (!TREE_USED (*t) && !DECL_ARTIFICIAL (*t) && !starts_with_under_score)
+ if (!TREE_USED (*t) && !DECL_ARTIFICIAL (*t) && !starts_with_under_score
+ && !is_self)
{
warning_at (DECL_SOURCE_LOCATION (*t),
is_constant ? OPT_Wunused_const_variable_
diff --git a/gcc/rust/expand/rust-cfg-strip.cc b/gcc/rust/expand/rust-cfg-strip.cc
index a8c3ca5..58d8071 100644
--- a/gcc/rust/expand/rust-cfg-strip.cc
+++ b/gcc/rust/expand/rust-cfg-strip.cc
@@ -289,7 +289,8 @@ CfgStrip::maybe_strip_generic_args (AST::GenericArgs &args)
{
switch (arg.get_kind ())
{
- case AST::GenericArg::Kind::Type: {
+ case AST::GenericArg::Kind::Type:
+ {
auto &type = arg.get_type ();
type.accept_vis (*this);
@@ -298,7 +299,8 @@ CfgStrip::maybe_strip_generic_args (AST::GenericArgs &args)
"cannot strip type in this position");
break;
}
- case AST::GenericArg::Kind::Const: {
+ case AST::GenericArg::Kind::Const:
+ {
auto &expr = arg.get_expression ();
expr.accept_vis (*this);
@@ -1190,7 +1192,7 @@ CfgStrip::visit (AST::ClosureExprInnerTyped &expr)
rust_error_at (type.get_locus (), "cannot strip type in this position");
// can't strip expression itself, but can strip sub-expressions
- auto &definition_block = expr.get_definition_block ();
+ auto &definition_block = expr.get_definition_expr ();
definition_block.accept_vis (*this);
if (definition_block.is_marked_for_strip ())
rust_error_at (definition_block.get_locus (),
@@ -1763,16 +1765,17 @@ CfgStrip::visit (AST::Module &module)
return;
}
- // A loaded module might have inner attributes
- if (module.get_kind () == AST::Module::ModuleKind::LOADED)
+ if (module.get_kind () == AST::Module::UNLOADED)
{
- // strip test based on inner attrs
- expand_cfg_attrs (module.get_inner_attrs ());
- if (fails_cfg_with_expand (module.get_inner_attrs ()))
- {
- module.mark_for_strip ();
- return;
- }
+ module.load_items ();
+ }
+
+ // strip test based on inner attrs
+ expand_cfg_attrs (module.get_inner_attrs ());
+ if (fails_cfg_with_expand (module.get_inner_attrs ()))
+ {
+ module.mark_for_strip ();
+ return;
}
// strip items if required
@@ -2260,12 +2263,12 @@ void
CfgStrip::visit (AST::IdentifierPattern &pattern)
{
// can only strip sub-patterns of the inner pattern to bind
- if (!pattern.has_pattern_to_bind ())
+ if (!pattern.has_subpattern ())
return;
AST::DefaultASTVisitor::visit (pattern);
- auto &sub_pattern = pattern.get_pattern_to_bind ();
+ auto &sub_pattern = pattern.get_subpattern ();
if (sub_pattern.is_marked_for_strip ())
rust_error_at (sub_pattern.get_locus (),
"cannot strip pattern in this position");
@@ -2475,20 +2478,44 @@ CfgStrip::visit (AST::GroupedPattern &pattern)
}
void
-CfgStrip::visit (AST::SlicePattern &pattern)
+CfgStrip::visit (AST::SlicePatternItemsNoRest &items)
{
- AST::DefaultASTVisitor::visit (pattern);
+ AST::DefaultASTVisitor::visit (items);
// can't strip individual patterns, only sub-patterns
- for (auto &item : pattern.get_items ())
+ for (auto &pattern : items.get_patterns ())
{
- if (item->is_marked_for_strip ())
- rust_error_at (item->get_locus (),
+ if (pattern->is_marked_for_strip ())
+ rust_error_at (pattern->get_locus (),
"cannot strip pattern in this position");
- // TODO: quit stripping now? or keep going?
}
}
void
+CfgStrip::visit (AST::SlicePatternItemsHasRest &items)
+{
+ AST::DefaultASTVisitor::visit (items);
+ // can't strip individual patterns, only sub-patterns
+ for (auto &pattern : items.get_lower_patterns ())
+ {
+ if (pattern->is_marked_for_strip ())
+ rust_error_at (pattern->get_locus (),
+ "cannot strip pattern in this position");
+ }
+ for (auto &pattern : items.get_upper_patterns ())
+ {
+ if (pattern->is_marked_for_strip ())
+ rust_error_at (pattern->get_locus (),
+ "cannot strip pattern in this position");
+ }
+}
+
+void
+CfgStrip::visit (AST::SlicePattern &pattern)
+{
+ AST::DefaultASTVisitor::visit (pattern);
+}
+
+void
CfgStrip::visit (AST::AltPattern &pattern)
{
AST::DefaultASTVisitor::visit (pattern);
diff --git a/gcc/rust/expand/rust-cfg-strip.h b/gcc/rust/expand/rust-cfg-strip.h
index 4900ae8..767cf28 100644
--- a/gcc/rust/expand/rust-cfg-strip.h
+++ b/gcc/rust/expand/rust-cfg-strip.h
@@ -172,6 +172,8 @@ public:
void visit (AST::TuplePatternItemsMultiple &tuple_items) override;
void visit (AST::TuplePatternItemsRanged &tuple_items) override;
void visit (AST::GroupedPattern &pattern) override;
+ void visit (AST::SlicePatternItemsNoRest &items) override;
+ void visit (AST::SlicePatternItemsHasRest &items) override;
void visit (AST::SlicePattern &pattern) override;
void visit (AST::AltPattern &pattern) override;
diff --git a/gcc/rust/expand/rust-derive-clone.h b/gcc/rust/expand/rust-derive-clone.h
index 61224ba..a3320c7 100644
--- a/gcc/rust/expand/rust-derive-clone.h
+++ b/gcc/rust/expand/rust-derive-clone.h
@@ -29,7 +29,7 @@ class DeriveClone : DeriveVisitor
public:
DeriveClone (location_t loc);
- std::unique_ptr<AST::Item> go (Item &item);
+ std::unique_ptr<Item> go (Item &item);
private:
std::unique_ptr<Item> expanded;
@@ -80,10 +80,10 @@ private:
MatchCase clone_enum_struct (PathInExpression variant_path,
const EnumItemStruct &variant);
- virtual void visit_struct (StructStruct &item);
- virtual void visit_tuple (TupleStruct &item);
- virtual void visit_enum (Enum &item);
- virtual void visit_union (Union &item);
+ virtual void visit_struct (StructStruct &item) override;
+ virtual void visit_tuple (TupleStruct &item) override;
+ virtual void visit_enum (Enum &item) override;
+ virtual void visit_union (Union &item) override;
};
} // namespace AST
diff --git a/gcc/rust/expand/rust-derive-cmp-common.cc b/gcc/rust/expand/rust-derive-cmp-common.cc
new file mode 100644
index 0000000..22ca16f
--- /dev/null
+++ b/gcc/rust/expand/rust-derive-cmp-common.cc
@@ -0,0 +1,191 @@
+// 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-derive-cmp-common.h"
+#include "rust-ast-builder.h"
+#include "rust-item.h"
+
+namespace Rust {
+namespace AST {
+
+SelfOther
+SelfOther::index (Builder builder, int idx)
+{
+ return SelfOther{
+ builder.tuple_idx ("self", idx),
+ builder.tuple_idx ("other", idx),
+ };
+}
+
+std::vector<SelfOther>
+SelfOther::indexes (Builder builder, const std::vector<TupleField> &fields)
+{
+ std::vector<SelfOther> vec;
+
+ for (size_t i = 0; i < fields.size (); i++)
+ vec.emplace_back (SelfOther::index (builder, i));
+
+ return vec;
+}
+
+SelfOther
+SelfOther::field (Builder builder, const std::string &field_name)
+{
+ return SelfOther{
+ builder.field_access (builder.identifier ("self"), field_name),
+ builder.field_access (builder.identifier ("other"), field_name),
+ };
+}
+
+std::vector<SelfOther>
+SelfOther::fields (Builder builder, const std::vector<StructField> &fields)
+{
+ std::vector<SelfOther> vec;
+
+ for (const auto &field : fields)
+ vec.emplace_back (
+ SelfOther::field (builder, field.get_field_name ().as_string ()));
+
+ return vec;
+}
+
+MatchCase
+EnumMatchBuilder::tuple (EnumItem &variant_raw)
+{
+ auto &variant = static_cast<EnumItemTuple &> (variant_raw);
+
+ auto self_patterns = std::vector<std::unique_ptr<Pattern>> ();
+ auto other_patterns = std::vector<std::unique_ptr<Pattern>> ();
+
+ auto self_other_exprs = std::vector<SelfOther> ();
+
+ for (size_t i = 0; i < variant.get_tuple_fields ().size (); i++)
+ {
+ // The patterns we're creating for each field are `self_<i>` and
+ // `other_<i>` where `i` is the index of the field. It doesn't actually
+ // matter what we use, as long as it's ordered, unique, and that we can
+ // reuse it in the match case's return expression to check that they are
+ // equal.
+
+ auto self_pattern_str = "__self_" + std::to_string (i);
+ auto other_pattern_str = "__other_" + std::to_string (i);
+
+ self_patterns.emplace_back (
+ builder.identifier_pattern (self_pattern_str));
+ other_patterns.emplace_back (
+ builder.identifier_pattern (other_pattern_str));
+
+ self_other_exprs.emplace_back (SelfOther{
+ builder.identifier (self_pattern_str),
+ builder.identifier (other_pattern_str),
+ });
+ }
+
+ // TODO: Replace with `reconstruct()` instead of building these twice
+ auto self_variant_path = builder.variant_path (enum_path, variant_path);
+ auto other_variant_path = builder.variant_path (enum_path, variant_path);
+
+ auto self_pattern_items = std::unique_ptr<TupleStructItems> (
+ new TupleStructItemsNoRange (std::move (self_patterns)));
+ auto other_pattern_items = std::unique_ptr<TupleStructItems> (
+ new TupleStructItemsNoRange (std::move (other_patterns)));
+
+ auto self_pattern = std::unique_ptr<Pattern> (
+ new ReferencePattern (std::unique_ptr<Pattern> (new TupleStructPattern (
+ self_variant_path, std::move (self_pattern_items))),
+ false, false, builder.loc));
+ auto other_pattern = std::unique_ptr<Pattern> (new ReferencePattern (
+ std::unique_ptr<Pattern> (new TupleStructPattern (
+ other_variant_path, std::move (other_pattern_items))),
+ false, false, builder.loc));
+
+ auto tuple_items = std::make_unique<TuplePatternItemsMultiple> (
+ vec (std::move (self_pattern), std::move (other_pattern)));
+
+ auto pattern
+ = std::make_unique<TuplePattern> (std::move (tuple_items), builder.loc);
+
+ auto expr = fn (std::move (self_other_exprs));
+
+ return builder.match_case (std::move (pattern), std::move (expr));
+}
+
+MatchCase
+EnumMatchBuilder::strukt (EnumItem &variant_raw)
+{
+ auto &variant = static_cast<EnumItemStruct &> (variant_raw);
+
+ auto self_fields = std::vector<std::unique_ptr<StructPatternField>> ();
+ auto other_fields = std::vector<std::unique_ptr<StructPatternField>> ();
+
+ auto self_other_exprs = std::vector<SelfOther> ();
+
+ for (auto &field : variant.get_struct_fields ())
+ {
+ // The patterns we're creating for each field are `self_<field>` and
+ // `other_<field>` where `field` is the name of the field. It doesn't
+ // actually matter what we use, as long as it's ordered, unique, and that
+ // we can reuse it in the match case's return expression to check that
+ // they are equal.
+
+ auto field_name = field.get_field_name ().as_string ();
+
+ auto self_pattern_str = "__self_" + field_name;
+ auto other_pattern_str = "__other_" + field_name;
+
+ self_fields.emplace_back (builder.struct_pattern_ident_pattern (
+ field_name, builder.identifier_pattern (self_pattern_str)));
+ other_fields.emplace_back (builder.struct_pattern_ident_pattern (
+ field_name, builder.identifier_pattern (other_pattern_str)));
+
+ self_other_exprs.emplace_back (SelfOther{
+ builder.identifier (self_pattern_str),
+ builder.identifier (other_pattern_str),
+ });
+ }
+
+ // TODO: Replace with `reconstruct()` instead of building these twice
+ auto self_variant_path = builder.variant_path (enum_path, variant_path);
+ auto other_variant_path = builder.variant_path (enum_path, variant_path);
+
+ auto self_elts = StructPatternElements (std::move (self_fields));
+ auto other_elts = StructPatternElements (std::move (other_fields));
+
+ auto self_pattern = std::unique_ptr<Pattern> (new ReferencePattern (
+ std::unique_ptr<Pattern> (new StructPattern (self_variant_path, builder.loc,
+ std::move (self_elts))),
+ false, false, builder.loc));
+ auto other_pattern = std::unique_ptr<Pattern> (
+ new ReferencePattern (std::unique_ptr<Pattern> (
+ new StructPattern (other_variant_path, builder.loc,
+ std::move (other_elts))),
+ false, false, builder.loc));
+
+ auto tuple_items = std::make_unique<TuplePatternItemsMultiple> (
+ vec (std::move (self_pattern), std::move (other_pattern)));
+
+ auto pattern
+ = std::make_unique<TuplePattern> (std::move (tuple_items), builder.loc);
+
+ auto expr = fn (std::move (self_other_exprs));
+
+ return builder.match_case (std::move (pattern), std::move (expr));
+}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/expand/rust-derive-cmp-common.h b/gcc/rust/expand/rust-derive-cmp-common.h
new file mode 100644
index 0000000..4efbed8
--- /dev/null
+++ b/gcc/rust/expand/rust-derive-cmp-common.h
@@ -0,0 +1,99 @@
+// 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_DERIVE_CMP_COMMON_H
+#define RUST_DERIVE_CMP_COMMON_H
+
+#include "rust-ast.h"
+#include "rust-ast-builder.h"
+#include "rust-item.h"
+#include "rust-path.h"
+
+namespace Rust {
+namespace AST {
+
+/**
+ * A pair of two expressions from each instance being compared. E.g. this
+ * could be `self.0` and `other.0`, or `self.field` and `other.field`
+ */
+struct SelfOther
+{
+ std::unique_ptr<Expr> self_expr;
+ std::unique_ptr<Expr> other_expr;
+
+ /* Create a <self.i> and an <other.i> expression */
+ static SelfOther index (Builder builder, int idx);
+ static std::vector<SelfOther> indexes (Builder builder,
+ const std::vector<TupleField> &fields);
+
+ /* Create a <self.field> and an <other.field> expression */
+ static SelfOther field (Builder builder, const std::string &field_name);
+ static std::vector<SelfOther> fields (Builder builder,
+ const std::vector<StructField> &fields);
+};
+
+/**
+ * Builder for common match cases used when comparing two enum instances. This
+ * builder takes care of creating the unique patterns for the `self` instance
+ * and `other` instance, as well as the entire `MatchCase` required for building
+ * a proper comparision expression for an implementation of a comparision trait
+ * for an enum type. The functions take a lambda to use when creating the
+ * expression of the generated `MatchCase`.
+ */
+class EnumMatchBuilder
+{
+public:
+ /**
+ * The type of functions to call when creating the resulting expression in the
+ * generated `MatchCase`
+ */
+ using ExprFn
+ = std::function<std::unique_ptr<Expr> (std::vector<SelfOther> &&)>;
+
+ EnumMatchBuilder (const std::string &enum_path,
+ const std::string &variant_path, ExprFn fn,
+ Builder &builder)
+ : enum_path (enum_path), variant_path (variant_path), fn (fn),
+ builder (builder)
+ {}
+
+ /**
+ * Generate a `MatchCase` for an enum tuple variant
+ *
+ * (&Enum::Tuple(self0, self1), &Enum::Tuple(other0, other1)) => <fn>
+ */
+ MatchCase tuple (EnumItem &variant);
+
+ /**
+ * Generate a `MatchCase` for an enum struct variant
+ *
+ * (&Enum::Struct { a: self_a }, &Enum::Struct { a: other_a }) => <fn>
+ */
+ MatchCase strukt (EnumItem &variant);
+
+private:
+ const std::string &enum_path;
+ const std::string &variant_path;
+ ExprFn fn;
+ Builder &builder;
+};
+
+} // namespace AST
+} // namespace Rust
+
+#endif // ! RUST_DERIVE_CMP_COMMON_H
diff --git a/gcc/rust/expand/rust-derive-copy.h b/gcc/rust/expand/rust-derive-copy.h
index 71972eb..664a8e0 100644
--- a/gcc/rust/expand/rust-derive-copy.h
+++ b/gcc/rust/expand/rust-derive-copy.h
@@ -44,10 +44,10 @@ private:
copy_impl (std::string name,
const std::vector<std::unique_ptr<GenericParam>> &type_generics);
- virtual void visit_struct (StructStruct &item);
- virtual void visit_tuple (TupleStruct &item);
- virtual void visit_enum (Enum &item);
- virtual void visit_union (Union &item);
+ virtual void visit_struct (StructStruct &item) override;
+ virtual void visit_tuple (TupleStruct &item) override;
+ virtual void visit_enum (Enum &item) override;
+ virtual void visit_union (Union &item) override;
};
} // namespace AST
diff --git a/gcc/rust/expand/rust-derive-default.cc b/gcc/rust/expand/rust-derive-default.cc
index 2e8b456..26ee546 100644
--- a/gcc/rust/expand/rust-derive-default.cc
+++ b/gcc/rust/expand/rust-derive-default.cc
@@ -98,7 +98,8 @@ DeriveDefault::visit_struct (StructStruct &item)
for (auto &field : item.get_fields ())
{
auto name = field.get_field_name ().as_string ();
- auto expr = default_call (field.get_field_type ().clone_type ());
+ auto type = field.get_field_type ().reconstruct ();
+ auto expr = default_call (std::move (type));
cloned_fields.emplace_back (
builder.struct_expr_field (std::move (name), std::move (expr)));
@@ -119,7 +120,7 @@ DeriveDefault::visit_tuple (TupleStruct &tuple_item)
for (auto &field : tuple_item.get_fields ())
{
- auto type = field.get_field_type ().clone_type ();
+ auto type = field.get_field_type ().reconstruct ();
defaulted_fields.emplace_back (default_call (std::move (type)));
}
diff --git a/gcc/rust/expand/rust-derive-eq.cc b/gcc/rust/expand/rust-derive-eq.cc
index 5e7a894..7da137f 100644
--- a/gcc/rust/expand/rust-derive-eq.cc
+++ b/gcc/rust/expand/rust-derive-eq.cc
@@ -142,7 +142,7 @@ DeriveEq::visit_tuple (TupleStruct &item)
auto types = std::vector<std::unique_ptr<Type>> ();
for (auto &field : item.get_fields ())
- types.emplace_back (field.get_field_type ().clone_type ());
+ types.emplace_back (field.get_field_type ().reconstruct ());
expanded = eq_impls (assert_receiver_is_total_eq_fn (std::move (types)),
item.get_identifier ().as_string (),
@@ -155,7 +155,7 @@ DeriveEq::visit_struct (StructStruct &item)
auto types = std::vector<std::unique_ptr<Type>> ();
for (auto &field : item.get_fields ())
- types.emplace_back (field.get_field_type ().clone_type ());
+ types.emplace_back (field.get_field_type ().reconstruct ());
expanded = eq_impls (assert_receiver_is_total_eq_fn (std::move (types)),
item.get_identifier ().as_string (),
@@ -175,19 +175,20 @@ DeriveEq::visit_enum (Enum &item)
case EnumItem::Kind::Discriminant:
// nothing to do as they contain no inner types
continue;
- case EnumItem::Kind::Tuple: {
+ case EnumItem::Kind::Tuple:
+ {
auto &tuple = static_cast<EnumItemTuple &> (*variant);
for (auto &field : tuple.get_tuple_fields ())
- types.emplace_back (field.get_field_type ().clone_type ());
-
+ types.emplace_back (field.get_field_type ().reconstruct ());
break;
}
- case EnumItem::Kind::Struct: {
+ case EnumItem::Kind::Struct:
+ {
auto &tuple = static_cast<EnumItemStruct &> (*variant);
for (auto &field : tuple.get_struct_fields ())
- types.emplace_back (field.get_field_type ().clone_type ());
+ types.emplace_back (field.get_field_type ().reconstruct ());
break;
}
@@ -205,7 +206,7 @@ DeriveEq::visit_union (Union &item)
auto types = std::vector<std::unique_ptr<Type>> ();
for (auto &field : item.get_variants ())
- types.emplace_back (field.get_field_type ().clone_type ());
+ types.emplace_back (field.get_field_type ().reconstruct ());
expanded = eq_impls (assert_receiver_is_total_eq_fn (std::move (types)),
item.get_identifier ().as_string (),
diff --git a/gcc/rust/expand/rust-derive-eq.h b/gcc/rust/expand/rust-derive-eq.h
index 17af526..fb187cc 100644
--- a/gcc/rust/expand/rust-derive-eq.h
+++ b/gcc/rust/expand/rust-derive-eq.h
@@ -31,7 +31,7 @@ class DeriveEq : DeriveVisitor
public:
DeriveEq (location_t loc);
- std::vector<std::unique_ptr<AST::Item>> go (Item &item);
+ std::vector<std::unique_ptr<Item>> go (Item &item);
private:
std::vector<std::unique_ptr<Item>> expanded;
@@ -70,10 +70,10 @@ private:
*/
std::unique_ptr<Stmt> assert_type_is_eq (std::unique_ptr<Type> &&type);
- virtual void visit_struct (StructStruct &item);
- virtual void visit_tuple (TupleStruct &item);
- virtual void visit_enum (Enum &item);
- virtual void visit_union (Union &item);
+ virtual void visit_struct (StructStruct &item) override;
+ virtual void visit_tuple (TupleStruct &item) override;
+ virtual void visit_enum (Enum &item) override;
+ virtual void visit_union (Union &item) override;
};
} // namespace AST
diff --git a/gcc/rust/expand/rust-derive-hash.cc b/gcc/rust/expand/rust-derive-hash.cc
index 0c9b0f7..94aede2 100644
--- a/gcc/rust/expand/rust-derive-hash.cc
+++ b/gcc/rust/expand/rust-derive-hash.cc
@@ -231,14 +231,7 @@ DeriveHash::visit_enum (Enum &item)
auto cases = std::vector<MatchCase> ();
auto type_name = item.get_identifier ().as_string ();
- auto intrinsic = ptrify (
- builder.path_in_expression ({"core", "intrinsics", "discriminant_value"},
- true));
-
- auto let_discr
- = builder.let (builder.identifier_pattern (DeriveHash::discr), nullptr,
- builder.call (std::move (intrinsic),
- builder.identifier ("self")));
+ auto let_discr = builder.discriminant_value (DeriveHash::discr);
auto discr_hash = builder.statementify (
hash_call (builder.ref (builder.identifier (DeriveHash::discr))));
diff --git a/gcc/rust/expand/rust-derive-hash.h b/gcc/rust/expand/rust-derive-hash.h
index 02b0bee..67170d0 100644
--- a/gcc/rust/expand/rust-derive-hash.h
+++ b/gcc/rust/expand/rust-derive-hash.h
@@ -29,7 +29,7 @@ class DeriveHash : DeriveVisitor
public:
DeriveHash (location_t loc);
- std::unique_ptr<AST::Item> go (Item &item);
+ std::unique_ptr<Item> go (Item &item);
private:
std::unique_ptr<Item> expanded;
@@ -49,10 +49,10 @@ private:
MatchCase match_enum_struct (PathInExpression variant_path,
const EnumItemStruct &variant);
- virtual void visit_struct (StructStruct &item);
- virtual void visit_tuple (TupleStruct &item);
- virtual void visit_enum (Enum &item);
- virtual void visit_union (Union &item);
+ virtual void visit_struct (StructStruct &item) override;
+ virtual void visit_tuple (TupleStruct &item) override;
+ virtual void visit_enum (Enum &item) override;
+ virtual void visit_union (Union &item) override;
};
} // namespace AST
diff --git a/gcc/rust/expand/rust-derive-ord.cc b/gcc/rust/expand/rust-derive-ord.cc
new file mode 100644
index 0000000..afc4b71
--- /dev/null
+++ b/gcc/rust/expand/rust-derive-ord.cc
@@ -0,0 +1,323 @@
+// 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-derive-ord.h"
+#include "rust-ast.h"
+#include "rust-derive-cmp-common.h"
+#include "rust-derive.h"
+#include "rust-item.h"
+#include "rust-system.h"
+
+namespace Rust {
+namespace AST {
+
+DeriveOrd::DeriveOrd (Ordering ordering, location_t loc)
+ : DeriveVisitor (loc), ordering (ordering)
+{}
+
+std::unique_ptr<Item>
+DeriveOrd::go (Item &item)
+{
+ item.accept_vis (*this);
+
+ return std::move (expanded);
+}
+
+std::unique_ptr<Expr>
+DeriveOrd::cmp_call (std::unique_ptr<Expr> &&self_expr,
+ std::unique_ptr<Expr> &&other_expr)
+{
+ auto cmp_fn_path = builder.path_in_expression (
+ {"core", "cmp", trait (ordering), fn (ordering)}, true);
+
+ return builder.call (ptrify (cmp_fn_path),
+ vec (builder.ref (std::move (self_expr)),
+ builder.ref (std::move (other_expr))));
+}
+
+std::unique_ptr<Item>
+DeriveOrd::cmp_impl (
+ std::unique_ptr<BlockExpr> &&fn_block, Identifier type_name,
+ const std::vector<std::unique_ptr<GenericParam>> &type_generics)
+{
+ auto fn = cmp_fn (std::move (fn_block), type_name);
+
+ auto trait = ordering == Ordering::Partial ? "PartialOrd" : "Ord";
+ auto trait_path = builder.type_path ({"core", "cmp", trait}, true);
+
+ auto trait_bound
+ = builder.trait_bound (builder.type_path ({"core", "cmp", trait}, true));
+
+ auto trait_items = vec (std::move (fn));
+
+ auto cmp_generics
+ = setup_impl_generics (type_name.as_string (), type_generics,
+ std::move (trait_bound));
+
+ return builder.trait_impl (trait_path, std::move (cmp_generics.self_type),
+ std::move (trait_items),
+ std::move (cmp_generics.impl));
+}
+
+std::unique_ptr<AssociatedItem>
+DeriveOrd::cmp_fn (std::unique_ptr<BlockExpr> &&block, Identifier type_name)
+{
+ // Ordering
+ auto return_type = builder.type_path ({"core", "cmp", "Ordering"}, true);
+
+ // In the case of PartialOrd, we return an Option<Ordering>
+ if (ordering == Ordering::Partial)
+ {
+ auto generic = GenericArg::create_type (ptrify (return_type));
+
+ auto generic_seg = builder.type_path_segment_generic (
+ "Option", GenericArgs ({}, {generic}, {}, loc));
+ auto core = builder.type_path_segment ("core");
+ auto option = builder.type_path_segment ("option");
+
+ return_type
+ = builder.type_path (vec (std::move (core), std::move (option),
+ std::move (generic_seg)),
+ true);
+ }
+
+ // &self, other: &Self
+ auto params = vec (
+ builder.self_ref_param (),
+ builder.function_param (builder.identifier_pattern ("other"),
+ builder.reference_type (ptrify (
+ builder.type_path (type_name.as_string ())))));
+
+ auto function_name = fn (ordering);
+
+ return builder.function (function_name, std::move (params),
+ ptrify (return_type), std::move (block));
+}
+
+std::unique_ptr<Pattern>
+DeriveOrd::make_equal ()
+{
+ std::unique_ptr<Pattern> equal = ptrify (
+ builder.path_in_expression ({"core", "cmp", "Ordering", "Equal"}, true));
+
+ // We need to wrap the pattern in Option::Some if we are doing partial
+ // ordering
+ if (ordering == Ordering::Partial)
+ {
+ auto pattern_items = std::unique_ptr<TupleStructItems> (
+ new TupleStructItemsNoRange (vec (std::move (equal))));
+
+ equal
+ = std::make_unique<TupleStructPattern> (builder.path_in_expression (
+ LangItem::Kind::OPTION_SOME),
+ std::move (pattern_items));
+ }
+
+ return equal;
+}
+
+std::pair<MatchArm, MatchArm>
+DeriveOrd::make_cmp_arms ()
+{
+ // All comparison results other than Ordering::Equal
+ auto non_equal = builder.identifier_pattern (DeriveOrd::not_equal);
+ auto equal = make_equal ();
+
+ return {builder.match_arm (std::move (equal)),
+ builder.match_arm (std::move (non_equal))};
+}
+
+std::unique_ptr<Expr>
+DeriveOrd::recursive_match (std::vector<SelfOther> &&members)
+{
+ if (members.empty ())
+ {
+ std::unique_ptr<Expr> value = ptrify (
+ builder.path_in_expression ({"core", "cmp", "Ordering", "Equal"},
+ true));
+
+ if (ordering == Ordering::Partial)
+ value = builder.call (ptrify (builder.path_in_expression (
+ LangItem::Kind::OPTION_SOME)),
+ std::move (value));
+
+ return value;
+ }
+
+ std::unique_ptr<Expr> final_expr = nullptr;
+
+ for (auto it = members.rbegin (); it != members.rend (); it++)
+ {
+ auto &member = *it;
+
+ auto call = cmp_call (std::move (member.self_expr),
+ std::move (member.other_expr));
+
+ // For the last member (so the first iterator), we just create a call
+ // expression
+ if (it == members.rbegin ())
+ {
+ final_expr = std::move (call);
+ continue;
+ }
+
+ // If we aren't dealing with the last member, then we need to wrap all of
+ // that in a big match expression and keep going
+ auto match_arms = make_cmp_arms ();
+
+ auto match_cases
+ = {builder.match_case (std::move (match_arms.first),
+ std::move (final_expr)),
+ builder.match_case (std::move (match_arms.second),
+ builder.identifier (DeriveOrd::not_equal))};
+
+ final_expr = builder.match (std::move (call), std::move (match_cases));
+ }
+
+ return final_expr;
+}
+
+// we need to do a recursive match expression for all of the fields used in a
+// struct so for something like struct Foo { a: i32, b: i32, c: i32 } we must
+// first compare each `a` field, then `b`, then `c`, like this:
+//
+// match cmp_fn(self.<field>, other.<field>) {
+// Ordering::Equal => <recurse>,
+// cmp => cmp,
+// }
+//
+// and the recurse will be the exact same expression, on the next field. so that
+// our result looks like this:
+//
+// match cmp_fn(self.a, other.a) {
+// Ordering::Equal => match cmp_fn(self.b, other.b) {
+// Ordering::Equal =>cmp_fn(self.c, other.c),
+// cmp => cmp,
+// }
+// cmp => cmp,
+// }
+//
+// the last field comparison needs not to be a match but just the function call.
+// this is going to be annoying lol
+void
+DeriveOrd::visit_struct (StructStruct &item)
+{
+ auto fields = SelfOther::fields (builder, item.get_fields ());
+
+ auto match_expr = recursive_match (std::move (fields));
+
+ expanded = cmp_impl (builder.block (std::move (match_expr)),
+ item.get_identifier (), item.get_generic_params ());
+}
+
+// same as structs, but for each field index instead of each field name -
+// straightforward once we have `visit_struct` working
+void
+DeriveOrd::visit_tuple (TupleStruct &item)
+{
+ auto fields = SelfOther::indexes (builder, item.get_fields ());
+
+ auto match_expr = recursive_match (std::move (fields));
+
+ expanded = cmp_impl (builder.block (std::move (match_expr)),
+ item.get_identifier (), item.get_generic_params ());
+}
+
+// for enums, we need to generate a match for each of the enum's variant that
+// contains data and then do the same thing as visit_struct or visit_enum. if
+// the two aren't the same variant, then compare the two discriminant values for
+// all the dataless enum variants and in the general case.
+//
+// so for enum Foo { A(i32, i32), B, C } we need to do the following
+//
+// match (self, other) {
+// (A(self_0, self_1), A(other_0, other_1)) => {
+// match cmp_fn(self_0, other_0) {
+// Ordering::Equal => cmp_fn(self_1, other_1),
+// cmp => cmp,
+// },
+// _ => cmp_fn(discr_value(self), discr_value(other))
+// }
+void
+DeriveOrd::visit_enum (Enum &item)
+{
+ // NOTE: We can factor this even further with DerivePartialEq, but this is
+ // getting out of scope for this PR surely
+
+ auto cases = std::vector<MatchCase> ();
+ auto type_name = item.get_identifier ().as_string ();
+
+ auto let_sd = builder.discriminant_value (DeriveOrd::self_discr, "self");
+ auto let_od = builder.discriminant_value (DeriveOrd::other_discr, "other");
+
+ auto discr_cmp = cmp_call (builder.identifier (DeriveOrd::self_discr),
+ builder.identifier (DeriveOrd::other_discr));
+
+ auto recursive_match_fn = [this] (std::vector<SelfOther> &&fields) {
+ return recursive_match (std::move (fields));
+ };
+
+ for (auto &variant : item.get_variants ())
+ {
+ auto enum_builder
+ = EnumMatchBuilder (type_name, variant->get_identifier ().as_string (),
+ recursive_match_fn, builder);
+
+ switch (variant->get_enum_item_kind ())
+ {
+ case EnumItem::Kind::Struct:
+ cases.emplace_back (enum_builder.strukt (*variant));
+ break;
+ case EnumItem::Kind::Tuple:
+ cases.emplace_back (enum_builder.tuple (*variant));
+ break;
+ case EnumItem::Kind::Identifier:
+ case EnumItem::Kind::Discriminant:
+ // We don't need to do anything for these, as they are handled by the
+ // discriminant value comparison
+ break;
+ }
+ }
+
+ // Add the last case which compares the discriminant values in case `self` and
+ // `other` are actually different variants of the enum
+ cases.emplace_back (
+ builder.match_case (builder.wildcard (), std::move (discr_cmp)));
+
+ auto match
+ = builder.match (builder.tuple (vec (builder.identifier ("self"),
+ builder.identifier ("other"))),
+ std::move (cases));
+
+ expanded
+ = cmp_impl (builder.block (vec (std::move (let_sd), std::move (let_od)),
+ std::move (match)),
+ type_name, item.get_generic_params ());
+}
+
+void
+DeriveOrd::visit_union (Union &item)
+{
+ auto trait_name = trait (ordering);
+
+ rust_error_at (item.get_locus (), "derive(%s) cannot be used on unions",
+ trait_name.c_str ());
+}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/expand/rust-derive-ord.h b/gcc/rust/expand/rust-derive-ord.h
new file mode 100644
index 0000000..90ce9c8
--- /dev/null
+++ b/gcc/rust/expand/rust-derive-ord.h
@@ -0,0 +1,122 @@
+// 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_DERIVE_ORD_H
+#define RUST_DERIVE_ORD_H
+
+#include "rust-ast.h"
+#include "rust-derive-cmp-common.h"
+#include "rust-derive.h"
+
+namespace Rust {
+namespace AST {
+
+/**
+ * DeriveOrd is a bit special as the expansion of both `PartialOrd` and `Ord`
+ * is extremely similar. The only difference is that `PartialOrd` concerns
+ * partial-ordering, and thus its main method returns an `Option<Ordering>`,
+ * while `Ord` concerns total-ordering, and its main method returns an
+ * `Ordering`. Otherwise, the expansion logic is the same, so we factor both
+ * derives into one.
+ */
+class DeriveOrd : public DeriveVisitor
+{
+public:
+ enum class Ordering
+ {
+ Total,
+ Partial
+ };
+
+ std::string fn (Ordering ordering)
+ {
+ if (ordering == Ordering::Total)
+ return "cmp";
+ else
+ return "partial_cmp";
+ }
+
+ std::string trait (Ordering ordering)
+ {
+ if (ordering == Ordering::Total)
+ return "Ord";
+ else
+ return "PartialOrd";
+ }
+
+ DeriveOrd (Ordering ordering, location_t loc);
+
+ std::unique_ptr<Item> go (Item &item);
+
+private:
+ std::unique_ptr<Item> expanded;
+
+ Ordering ordering;
+
+ /* Identifier patterns for the non-equal match arms */
+ constexpr static const char *not_equal = "#non_eq";
+ constexpr static const char *self_discr = "#self_discr";
+ constexpr static const char *other_discr = "#other_discr";
+
+ /**
+ * Create the recursive matching structure used when implementing the
+ * comparison function on multiple sub items (fields, tuple indexes...)
+ */
+ std::unique_ptr<Expr> recursive_match (std::vector<SelfOther> &&members);
+
+ /**
+ * Create a pattern for the `Ordering::Equal` case. In the case of partial
+ * ordering, `Option::Some(Ordering::Equal)`.
+ */
+ std::unique_ptr<Pattern> make_equal ();
+
+ /**
+ * Make the match arms for one inner match in a comparison function block.
+ * This returns the "equal" match arm and the "rest" match arm, so something
+ * like `Ordering::Equal` and `non_eq` in the following match expression:
+ *
+ * match cmp(...) {
+ * Ordering::Equal => match cmp(...) { ... }
+ * non_eq => non_eq,
+ * }
+ */
+ std::pair<MatchArm, MatchArm> make_cmp_arms ();
+
+ /**
+ * Generate a call to the proper trait function, based on the ordering, in
+ * order to compare two given expressions
+ */
+ std::unique_ptr<Expr> cmp_call (std::unique_ptr<Expr> &&self_expr,
+ std::unique_ptr<Expr> &&other_expr);
+
+ std::unique_ptr<Item>
+ cmp_impl (std::unique_ptr<BlockExpr> &&fn_block, Identifier type_name,
+ const std::vector<std::unique_ptr<GenericParam>> &type_generics);
+ std::unique_ptr<AssociatedItem> cmp_fn (std::unique_ptr<BlockExpr> &&block,
+ Identifier type_name);
+
+ virtual void visit_struct (StructStruct &item) override;
+ virtual void visit_tuple (TupleStruct &item) override;
+ virtual void visit_enum (Enum &item) override;
+ virtual void visit_union (Union &item) override;
+};
+
+} // namespace AST
+} // namespace Rust
+
+#endif // ! RUST_DERIVE_ORD_H
diff --git a/gcc/rust/expand/rust-derive-partial-eq.cc b/gcc/rust/expand/rust-derive-partial-eq.cc
index ff66faa..a0bf87a 100644
--- a/gcc/rust/expand/rust-derive-partial-eq.cc
+++ b/gcc/rust/expand/rust-derive-partial-eq.cc
@@ -64,11 +64,9 @@ DerivePartialEq::partialeq_impls (
}
std::unique_ptr<AssociatedItem>
-DerivePartialEq::eq_fn (std::unique_ptr<Expr> &&cmp_expression,
+DerivePartialEq::eq_fn (std::unique_ptr<BlockExpr> &&block,
std::string type_name)
{
- auto block = builder.block (tl::nullopt, std::move (cmp_expression));
-
auto self_type
= std::unique_ptr<TypeNoBounds> (new TypePath (builder.type_path ("Self")));
@@ -83,24 +81,6 @@ DerivePartialEq::eq_fn (std::unique_ptr<Expr> &&cmp_expression,
std::move (block));
}
-DerivePartialEq::SelfOther
-DerivePartialEq::tuple_indexes (int idx)
-{
- return SelfOther{
- builder.tuple_idx ("self", idx),
- builder.tuple_idx ("other", idx),
- };
-}
-
-DerivePartialEq::SelfOther
-DerivePartialEq::field_acccesses (const std::string &field_name)
-{
- return SelfOther{
- builder.field_access (builder.identifier ("self"), field_name),
- builder.field_access (builder.identifier ("other"), field_name),
- };
-}
-
std::unique_ptr<Expr>
DerivePartialEq::build_eq_expression (
std::vector<SelfOther> &&field_expressions)
@@ -134,12 +114,10 @@ void
DerivePartialEq::visit_tuple (TupleStruct &item)
{
auto type_name = item.get_struct_name ().as_string ();
- auto fields = std::vector<SelfOther> ();
-
- for (size_t idx = 0; idx < item.get_fields ().size (); idx++)
- fields.emplace_back (tuple_indexes (idx));
+ auto fields = SelfOther::indexes (builder, item.get_fields ());
- auto fn = eq_fn (build_eq_expression (std::move (fields)), type_name);
+ auto fn = eq_fn (builder.block (build_eq_expression (std::move (fields))),
+ type_name);
expanded
= partialeq_impls (std::move (fn), type_name, item.get_generic_params ());
@@ -149,13 +127,10 @@ void
DerivePartialEq::visit_struct (StructStruct &item)
{
auto type_name = item.get_struct_name ().as_string ();
- auto fields = std::vector<SelfOther> ();
+ auto fields = SelfOther::fields (builder, item.get_fields ());
- for (auto &field : item.get_fields ())
- fields.emplace_back (
- field_acccesses (field.get_field_name ().as_string ()));
-
- auto fn = eq_fn (build_eq_expression (std::move (fields)), type_name);
+ auto fn = eq_fn (builder.block (build_eq_expression (std::move (fields))),
+ type_name);
expanded
= partialeq_impls (std::move (fn), type_name, item.get_generic_params ());
@@ -199,8 +174,6 @@ DerivePartialEq::match_enum_tuple (PathInExpression variant_path,
auto self_pattern_str = "__self_" + std::to_string (i);
auto other_pattern_str = "__other_" + std::to_string (i);
- rust_debug ("]ARTHUR[ %s", self_pattern_str.c_str ());
-
self_patterns.emplace_back (
builder.identifier_pattern (self_pattern_str));
other_patterns.emplace_back (
@@ -240,15 +213,55 @@ MatchCase
DerivePartialEq::match_enum_struct (PathInExpression variant_path,
const EnumItemStruct &variant)
{
- // NOTE: We currently do not support compiling struct patterns where an
- // identifier is assigned a new pattern, e.g. Bloop { f0: x }
- // This is what we should be using to compile PartialEq for enum struct
- // variants, as we need to be comparing the field of each instance meaning we
- // need to give two different names to two different instances of the same
- // field. We cannot just use the field's name like we do when deriving
- // `Clone`.
-
- rust_unreachable ();
+ auto self_fields = std::vector<std::unique_ptr<StructPatternField>> ();
+ auto other_fields = std::vector<std::unique_ptr<StructPatternField>> ();
+
+ auto self_other_exprs = std::vector<SelfOther> ();
+
+ for (auto &field : variant.get_struct_fields ())
+ {
+ // The patterns we're creating for each field are `self_<field>` and
+ // `other_<field>` where `field` is the name of the field. It doesn't
+ // actually matter what we use, as long as it's ordered, unique, and that
+ // we can reuse it in the match case's return expression to check that
+ // they are equal.
+
+ auto field_name = field.get_field_name ().as_string ();
+
+ auto self_pattern_str = "__self_" + field_name;
+ auto other_pattern_str = "__other_" + field_name;
+
+ self_fields.emplace_back (builder.struct_pattern_ident_pattern (
+ field_name, builder.identifier_pattern (self_pattern_str)));
+ other_fields.emplace_back (builder.struct_pattern_ident_pattern (
+ field_name, builder.identifier_pattern (other_pattern_str)));
+
+ self_other_exprs.emplace_back (SelfOther{
+ builder.identifier (self_pattern_str),
+ builder.identifier (other_pattern_str),
+ });
+ }
+
+ auto self_elts = StructPatternElements (std::move (self_fields));
+ auto other_elts = StructPatternElements (std::move (other_fields));
+
+ auto self_pattern = std::unique_ptr<Pattern> (
+ new ReferencePattern (std::unique_ptr<Pattern> (new StructPattern (
+ variant_path, loc, std::move (self_elts))),
+ false, false, loc));
+ auto other_pattern = std::unique_ptr<Pattern> (
+ new ReferencePattern (std::unique_ptr<Pattern> (new StructPattern (
+ variant_path, loc, std::move (other_elts))),
+ false, false, loc));
+
+ auto tuple_items = std::make_unique<TuplePatternItemsMultiple> (
+ vec (std::move (self_pattern), std::move (other_pattern)));
+
+ auto pattern = std::make_unique<TuplePattern> (std::move (tuple_items), loc);
+
+ auto expr = build_eq_expression (std::move (self_other_exprs));
+
+ return builder.match_case (std::move (pattern), std::move (expr));
}
void
@@ -257,46 +270,56 @@ DerivePartialEq::visit_enum (Enum &item)
auto cases = std::vector<MatchCase> ();
auto type_name = item.get_identifier ().as_string ();
+ auto eq_expr_fn = [this] (std::vector<SelfOther> &&fields) {
+ return build_eq_expression (std::move (fields));
+ };
+
+ auto let_sd
+ = builder.discriminant_value (DerivePartialEq::self_discr, "self");
+ auto let_od
+ = builder.discriminant_value (DerivePartialEq::other_discr, "other");
+
+ auto discr_cmp
+ = builder.comparison_expr (builder.identifier (DerivePartialEq::self_discr),
+ builder.identifier (
+ DerivePartialEq::other_discr),
+ ComparisonOperator::EQUAL);
+
for (auto &variant : item.get_variants ())
{
- auto variant_path
- = builder.variant_path (type_name,
- variant->get_identifier ().as_string ());
+ auto enum_builder
+ = EnumMatchBuilder (type_name, variant->get_identifier ().as_string (),
+ eq_expr_fn, builder);
switch (variant->get_enum_item_kind ())
{
- case EnumItem::Kind::Identifier:
- case EnumItem::Kind::Discriminant:
- cases.emplace_back (match_enum_identifier (variant_path, variant));
- break;
case EnumItem::Kind::Tuple:
- cases.emplace_back (
- match_enum_tuple (variant_path,
- static_cast<EnumItemTuple &> (*variant)));
+ cases.emplace_back (enum_builder.tuple (*variant));
break;
case EnumItem::Kind::Struct:
- rust_sorry_at (
- item.get_locus (),
- "cannot derive(PartialEq) for enum struct variants yet");
+ cases.emplace_back (enum_builder.strukt (*variant));
+ break;
+ case EnumItem::Kind::Identifier:
+ case EnumItem::Kind::Discriminant:
+ // We don't need to do anything for these, as they are handled by the
+ // discriminant value comparison
break;
}
}
- // NOTE: Mention using discriminant_value and skipping that last case, and
- // instead skipping all identifiers/discriminant enum items and returning
- // `true` in the wildcard case
-
// In case the two instances of `Self` don't have the same discriminant,
// automatically return false.
cases.emplace_back (
- builder.match_case (builder.wildcard (), builder.literal_bool (false)));
+ builder.match_case (builder.wildcard (), std::move (discr_cmp)));
auto match
= builder.match (builder.tuple (vec (builder.identifier ("self"),
builder.identifier ("other"))),
std::move (cases));
- auto fn = eq_fn (std::move (match), type_name);
+ auto fn = eq_fn (builder.block (vec (std::move (let_sd), std::move (let_od)),
+ std::move (match)),
+ type_name);
expanded
= partialeq_impls (std::move (fn), type_name, item.get_generic_params ());
diff --git a/gcc/rust/expand/rust-derive-partial-eq.h b/gcc/rust/expand/rust-derive-partial-eq.h
index ac963a6..7985414 100644
--- a/gcc/rust/expand/rust-derive-partial-eq.h
+++ b/gcc/rust/expand/rust-derive-partial-eq.h
@@ -21,6 +21,7 @@
#include "rust-derive.h"
#include "rust-path.h"
+#include "rust-derive-cmp-common.h"
namespace Rust {
namespace AST {
@@ -30,7 +31,7 @@ class DerivePartialEq : DeriveVisitor
public:
DerivePartialEq (location_t loc);
- std::vector<std::unique_ptr<AST::Item>> go (Item &item);
+ std::vector<std::unique_ptr<Item>> go (Item &item);
private:
std::vector<std::unique_ptr<Item>> expanded;
@@ -43,23 +44,10 @@ private:
std::unique_ptr<AssociatedItem> &&eq_fn, std::string name,
const std::vector<std::unique_ptr<GenericParam>> &type_generics);
- std::unique_ptr<AssociatedItem> eq_fn (std::unique_ptr<Expr> &&cmp_expression,
+ std::unique_ptr<AssociatedItem> eq_fn (std::unique_ptr<BlockExpr> &&block,
std::string type_name);
/**
- * A pair of two expressions from each instance being compared. E.g. this
- * could be `self.0` and `other.0`, or `self.field` and `other.field`
- */
- struct SelfOther
- {
- std::unique_ptr<Expr> self_expr;
- std::unique_ptr<Expr> other_expr;
- };
-
- SelfOther tuple_indexes (int idx);
- SelfOther field_acccesses (const std::string &field_name);
-
- /**
* Build a suite of equality arithmetic expressions chained together by a
* boolean AND operator
*/
@@ -73,10 +61,13 @@ private:
MatchCase match_enum_struct (PathInExpression variant_path,
const EnumItemStruct &variant);
- virtual void visit_struct (StructStruct &item);
- virtual void visit_tuple (TupleStruct &item);
- virtual void visit_enum (Enum &item);
- virtual void visit_union (Union &item);
+ constexpr static const char *self_discr = "#self_discr";
+ constexpr static const char *other_discr = "#other_discr";
+
+ virtual void visit_struct (StructStruct &item) override;
+ virtual void visit_tuple (TupleStruct &item) override;
+ virtual void visit_enum (Enum &item) override;
+ virtual void visit_union (Union &item) override;
};
} // namespace AST
diff --git a/gcc/rust/expand/rust-derive.cc b/gcc/rust/expand/rust-derive.cc
index 015b81e..55147df 100644
--- a/gcc/rust/expand/rust-derive.cc
+++ b/gcc/rust/expand/rust-derive.cc
@@ -22,6 +22,7 @@
#include "rust-derive-debug.h"
#include "rust-derive-default.h"
#include "rust-derive-eq.h"
+#include "rust-derive-ord.h"
#include "rust-derive-partial-eq.h"
#include "rust-derive-hash.h"
@@ -59,10 +60,11 @@ DeriveVisitor::derive (Item &item, const Attribute &attr,
case BuiltinMacro::Hash:
return vec (DeriveHash (loc).go (item));
case BuiltinMacro::Ord:
+ return vec (DeriveOrd (DeriveOrd::Ordering::Total, loc).go (item));
case BuiltinMacro::PartialOrd:
+ return vec (DeriveOrd (DeriveOrd::Ordering::Partial, loc).go (item));
default:
- rust_sorry_at (loc, "unimplemented builtin derive macro");
- return {};
+ rust_unreachable ();
};
}
@@ -79,7 +81,8 @@ DeriveVisitor::setup_impl_generics (
{
switch (generic->get_kind ())
{
- case GenericParam::Kind::Lifetime: {
+ case GenericParam::Kind::Lifetime:
+ {
LifetimeParam &lifetime_param = (LifetimeParam &) *generic.get ();
Lifetime l = builder.new_lifetime (lifetime_param.get_lifetime ());
@@ -91,7 +94,8 @@ DeriveVisitor::setup_impl_generics (
}
break;
- case GenericParam::Kind::Type: {
+ case GenericParam::Kind::Type:
+ {
TypeParam &type_param = (TypeParam &) *generic.get ();
std::unique_ptr<Type> associated_type = builder.single_type_path (
@@ -104,7 +108,8 @@ DeriveVisitor::setup_impl_generics (
std::vector<std::unique_ptr<TypeParamBound>> extra_bounds;
if (extra_bound)
- extra_bounds.emplace_back (std::move (*extra_bound));
+ extra_bounds.emplace_back (
+ extra_bound.value ()->clone_type_param_bound ());
auto impl_type_param
= builder.new_type_param (type_param, std::move (extra_bounds));
@@ -113,17 +118,20 @@ DeriveVisitor::setup_impl_generics (
}
break;
- case GenericParam::Kind::Const: {
- rust_unreachable ();
+ case GenericParam::Kind::Const:
+ {
+ ConstGenericParam &const_param
+ = (ConstGenericParam &) *generic.get ();
- // TODO
- // const ConstGenericParam *const_param
- // = (const ConstGenericParam *) generic.get ();
- // std::unique_ptr<Expr> const_expr = nullptr;
+ std::unique_ptr<Type> associated_type
+ = builder.single_type_path (const_param.get_name ().as_string ());
- // GenericArg type_arg
- // = GenericArg::create_const (std::move (const_expr));
- // generic_args.push_back (std::move (type_arg));
+ GenericArg type_arg
+ = GenericArg::create_type (std::move (associated_type));
+ generic_args.push_back (std::move (type_arg));
+
+ auto impl_const_param = builder.new_const_param (const_param);
+ impl_generics.push_back (std::move (impl_const_param));
}
break;
}
diff --git a/gcc/rust/expand/rust-derive.h b/gcc/rust/expand/rust-derive.h
index 5fca49c..10c146c 100644
--- a/gcc/rust/expand/rust-derive.h
+++ b/gcc/rust/expand/rust-derive.h
@@ -118,7 +118,7 @@ private:
virtual void visit (LiteralExpr &expr) override final{};
virtual void visit (AttrInputLiteral &attr_input) override final{};
virtual void visit (MetaItemLitExpr &meta_item) override final{};
- virtual void visit (MetaItemPathLit &meta_item) override final{};
+ virtual void visit (MetaItemPathExpr &meta_item) override final{};
virtual void visit (BorrowExpr &expr) override final{};
virtual void visit (DereferenceExpr &expr) override final{};
virtual void visit (ErrorPropagationExpr &expr) override final{};
@@ -147,6 +147,8 @@ private:
virtual void visit (FieldAccessExpr &expr) override final{};
virtual void visit (ClosureExprInner &expr) override final{};
virtual void visit (BlockExpr &expr) override final{};
+ virtual void visit (AnonConst &expr) override final{};
+ virtual void visit (ConstBlock &expr) override final{};
virtual void visit (ClosureExprInnerTyped &expr) override final{};
virtual void visit (ContinueExpr &expr) override final{};
virtual void visit (BreakExpr &expr) override final{};
@@ -157,6 +159,7 @@ private:
virtual void visit (RangeFromToInclExpr &expr) override final{};
virtual void visit (RangeToInclExpr &expr) override final{};
virtual void visit (ReturnExpr &expr) override final{};
+ virtual void visit (TryExpr &expr) override final{};
virtual void visit (BoxExpr &expr) override final{};
virtual void visit (UnsafeBlockExpr &expr) override final{};
virtual void visit (LoopExpr &expr) override final{};
@@ -228,6 +231,8 @@ private:
virtual void visit (TuplePatternItemsRanged &tuple_items) override final{};
virtual void visit (TuplePattern &pattern) override final{};
virtual void visit (GroupedPattern &pattern) override final{};
+ virtual void visit (SlicePatternItemsNoRest &items) override final{};
+ virtual void visit (SlicePatternItemsHasRest &items) override final{};
virtual void visit (SlicePattern &pattern) override final{};
virtual void visit (AltPattern &pattern) override final{};
virtual void visit (EmptyStmt &stmt) override final{};
@@ -251,6 +256,7 @@ private:
virtual void visit (FunctionParam &param) override final{};
virtual void visit (VariadicParam &param) override final{};
virtual void visit (FormatArgs &param) override final{};
+ virtual void visit (OffsetOf &param) override final{};
};
} // namespace AST
diff --git a/gcc/rust/expand/rust-expand-format-args.cc b/gcc/rust/expand/rust-expand-format-args.cc
index af6182f..bda28dd 100644
--- a/gcc/rust/expand/rust-expand-format-args.cc
+++ b/gcc/rust/expand/rust-expand-format-args.cc
@@ -85,11 +85,13 @@ expand_format_args (AST::FormatArgs &fmt,
static_pieces.emplace_back (
builder.literal_string (node.string._0.to_string ()));
break;
- case ffi::Piece::Tag::NextArgument: {
+ case ffi::Piece::Tag::NextArgument:
+ {
auto next_argument = node.next_argument._0;
switch (node.next_argument._0.position.tag)
{
- case ffi::Position::Tag::ArgumentImplicitlyIs: {
+ case ffi::Position::Tag::ArgumentImplicitlyIs:
+ {
auto idx = next_argument.position.argument_implicitly_is._0;
auto trait = next_argument.format;
auto arg = arguments.at (idx);
diff --git a/gcc/rust/expand/rust-expand-visitor.cc b/gcc/rust/expand/rust-expand-visitor.cc
index 42df5e1..8f6e7fa 100644
--- a/gcc/rust/expand/rust-expand-visitor.cc
+++ b/gcc/rust/expand/rust-expand-visitor.cc
@@ -233,10 +233,7 @@ ExpandVisitor::expand_inner_items (
}
}
- std::function<std::unique_ptr<AST::Item> (AST::SingleASTNode)> extractor
- = [] (AST::SingleASTNode node) { return node.take_item (); };
-
- expand_macro_children (items, extractor);
+ expand_macro_children (items, &AST::SingleASTNode::take_item);
expander.pop_context ();
}
@@ -324,10 +321,7 @@ ExpandVisitor::expand_inner_stmts (AST::BlockExpr &expr)
if (!expr.has_tail_expr ())
expr.normalize_tail_expr ();
- std::function<std::unique_ptr<AST::Stmt> (AST::SingleASTNode)> extractor
- = [] (AST::SingleASTNode node) { return node.take_stmt (); };
-
- expand_macro_children (stmts, extractor);
+ expand_macro_children (stmts, &AST::SingleASTNode::take_stmt);
expander.pop_context ();
}
@@ -544,7 +538,7 @@ ExpandVisitor::visit (AST::MetaItemLitExpr &)
{}
void
-ExpandVisitor::visit (AST::MetaItemPathLit &)
+ExpandVisitor::visit (AST::MetaItemPathExpr &)
{}
void
@@ -641,7 +635,7 @@ ExpandVisitor::visit (AST::ClosureExprInnerTyped &expr)
maybe_expand_type (expr.get_return_type_ptr ());
- visit (expr.get_definition_block ());
+ visit (expr.get_definition_expr ());
}
void
@@ -866,12 +860,9 @@ ExpandVisitor::visit (AST::Trait &trait)
expander.push_context (MacroExpander::ContextType::TRAIT);
- std::function<std::unique_ptr<AST::AssociatedItem> (AST::SingleASTNode)>
- extractor
- = [] (AST::SingleASTNode node) { return node.take_assoc_item (); };
-
expand_macro_children (MacroExpander::ContextType::TRAIT,
- trait.get_trait_items (), extractor);
+ trait.get_trait_items (),
+ &AST::SingleASTNode::take_assoc_item);
expander.pop_context ();
}
@@ -894,12 +885,9 @@ ExpandVisitor::visit (AST::InherentImpl &impl)
if (impl.has_where_clause ())
expand_where_clause (impl.get_where_clause ());
- std::function<std::unique_ptr<AST::AssociatedItem> (AST::SingleASTNode)>
- extractor
- = [] (AST::SingleASTNode node) { return node.take_assoc_item (); };
-
expand_macro_children (MacroExpander::ContextType::IMPL,
- impl.get_impl_items (), extractor);
+ impl.get_impl_items (),
+ &AST::SingleASTNode::take_assoc_item);
}
void
@@ -922,12 +910,9 @@ ExpandVisitor::visit (AST::TraitImpl &impl)
if (impl.has_where_clause ())
expand_where_clause (impl.get_where_clause ());
- std::function<std::unique_ptr<AST::AssociatedItem> (AST::SingleASTNode)>
- extractor
- = [] (AST::SingleASTNode node) { return node.take_assoc_item (); };
-
expand_macro_children (MacroExpander::ContextType::TRAIT_IMPL,
- impl.get_impl_items (), extractor);
+ impl.get_impl_items (),
+ &AST::SingleASTNode::take_assoc_item);
}
void
@@ -944,12 +929,10 @@ void
ExpandVisitor::visit (AST::ExternBlock &block)
{
visit_inner_attrs (block);
- std::function<std::unique_ptr<AST::ExternalItem> (AST::SingleASTNode)>
- extractor
- = [] (AST::SingleASTNode node) { return node.take_external_item (); };
expand_macro_children (MacroExpander::ContextType::EXTERN,
- block.get_extern_items (), extractor);
+ block.get_extern_items (),
+ &AST::SingleASTNode::take_external_item);
}
void
diff --git a/gcc/rust/expand/rust-expand-visitor.h b/gcc/rust/expand/rust-expand-visitor.h
index ad237c0..845e10c 100644
--- a/gcc/rust/expand/rust-expand-visitor.h
+++ b/gcc/rust/expand/rust-expand-visitor.h
@@ -28,14 +28,12 @@ namespace Rust {
/**
* Whether or not an attribute is a derive attribute
*/
-bool
-is_derive (AST::Attribute &attr);
+bool is_derive (AST::Attribute &attr);
/**
* Whether or not an attribute is builtin
*/
-bool
-is_builtin (AST::Attribute &attr);
+bool is_builtin (AST::Attribute &attr);
class ExpandVisitor : public AST::DefaultASTVisitor
{
@@ -107,7 +105,7 @@ public:
*/
template <typename T, typename U>
void expand_macro_children (MacroExpander::ContextType ctx, T &values,
- std::function<U (AST::SingleASTNode)> extractor)
+ U (AST::SingleASTNode::*extractor) (void))
{
expander.push_context (ctx);
@@ -123,7 +121,7 @@ public:
*/
template <typename T, typename U>
void expand_macro_children (T &values,
- std::function<U (AST::SingleASTNode)> extractor)
+ U (AST::SingleASTNode::*extractor) (void))
{
for (auto it = values.begin (); it != values.end ();)
{
@@ -140,7 +138,7 @@ public:
it = values.erase (it);
for (auto &node : final_fragment.get_nodes ())
{
- U new_node = extractor (node);
+ U new_node = (node.*extractor) ();
if (new_node != nullptr)
{
it = values.insert (it, std::move (new_node));
@@ -211,7 +209,7 @@ public:
void visit (AST::AttrInputLiteral &) override;
void visit (AST::AttrInputMacro &) override;
void visit (AST::MetaItemLitExpr &) override;
- void visit (AST::MetaItemPathLit &) override;
+ void visit (AST::MetaItemPathExpr &) override;
void visit (AST::ErrorPropagationExpr &expr) override;
void visit (AST::ArithmeticOrLogicalExpr &expr) override;
void visit (AST::ComparisonExpr &expr) override;
diff --git a/gcc/rust/expand/rust-macro-builtins-asm.cc b/gcc/rust/expand/rust-macro-builtins-asm.cc
index e255729..61222db 100644
--- a/gcc/rust/expand/rust-macro-builtins-asm.cc
+++ b/gcc/rust/expand/rust-macro-builtins-asm.cc
@@ -25,18 +25,6 @@
#include "rust-parse.h"
namespace Rust {
-std::map<AST::InlineAsmOption, std::string> InlineAsmOptionMap{
- {AST::InlineAsmOption::PURE, "pure"},
- {AST::InlineAsmOption::NOMEM, "nomem"},
- {AST::InlineAsmOption::READONLY, "readonly"},
- {AST::InlineAsmOption::PRESERVES_FLAGS, "preserves_flags"},
- {AST::InlineAsmOption::NORETURN, "noreturn"},
- {AST::InlineAsmOption::NOSTACK, "nostack"},
- {AST::InlineAsmOption::MAY_UNWIND, "may_unwind"},
- {AST::InlineAsmOption::ATT_SYNTAX, "att_syntax"},
- {AST::InlineAsmOption::RAW, "raw"},
-};
-
std::set<std::string> potentially_nonpromoted_keywords
= {"in", "out", "lateout", "inout", "inlateout", "const", "sym", "label"};
@@ -396,6 +384,7 @@ parse_reg_operand_inout (InlineAsmContext inline_asm_ctx)
{
auto &parser = inline_asm_ctx.parser;
auto token = parser.peek_current_token ();
+ location_t locus = token->get_locus ();
if (!inline_asm_ctx.is_global_asm () && check_identifier (parser, "inout"))
{
@@ -413,10 +402,8 @@ parse_reg_operand_inout (InlineAsmContext inline_asm_ctx)
// TODO: Is error propogation our top priority, the ? in rust's asm.rs is
// doing a lot of work.
- // TODO: Not sure how to use parse_expr
- if (!check_identifier (parser, ""))
- rust_unreachable ();
- // auto expr = parse_format_string (inline_asm_ctx);
+ std::unique_ptr<AST::Expr> in_expr = parser.parse_expr ();
+ rust_assert (in_expr != nullptr);
std::unique_ptr<AST::Expr> out_expr;
@@ -426,11 +413,19 @@ parse_reg_operand_inout (InlineAsmContext inline_asm_ctx)
{
// auto result = parse_format_string (inline_asm_ctx);
- if (!check_identifier (parser, ""))
- rust_unreachable ();
- // out_expr = parser.parse_expr();
+ out_expr = parser.parse_expr ();
+
+ AST::InlineAsmOperand::SplitInOut splitinout (
+ reg, false, std::move (in_expr), std::move (out_expr));
+
+ inline_asm_ctx.inline_asm.operands.emplace_back (splitinout,
+ locus);
+
+ return inline_asm_ctx;
}
+ rust_unreachable ();
+
// TODO: Rembmer to pass in clone_expr() instead of nullptr
// https://github.com/rust-lang/rust/blob/a3167859f2fd8ff2241295469876a2b687280bdc/compiler/rustc_builtin_macros/src/asm.rs#L135
// RUST VERSION: ast::InlineAsmOperand::SplitInOut { reg, in_expr:
@@ -444,6 +439,8 @@ parse_reg_operand_inout (InlineAsmContext inline_asm_ctx)
}
else
{
+ AST::InlineAsmOperand::InOut inout (reg, false, std::move (in_expr));
+ inline_asm_ctx.inline_asm.operands.emplace_back (inout, locus);
// https://github.com/rust-lang/rust/blob/a3167859f2fd8ff2241295469876a2b687280bdc/compiler/rustc_builtin_macros/src/asm.rs#L137
// RUST VERSION: ast::InlineAsmOperand::InOut { reg, expr, late: false
// }
@@ -500,7 +497,7 @@ parse_reg_operand_unexpected (InlineAsmContext inline_asm_ctx)
}
void
-check_and_set (InlineAsmContext &inline_asm_ctx, AST::InlineAsmOption option)
+check_and_set (InlineAsmContext &inline_asm_ctx, AST::InlineAsm::Option option)
{
auto &parser = inline_asm_ctx.parser;
auto &inline_asm = inline_asm_ctx.inline_asm;
@@ -509,7 +506,7 @@ check_and_set (InlineAsmContext &inline_asm_ctx, AST::InlineAsmOption option)
// TODO: report an error of duplication
rust_error_at (parser.peek_current_token ()->get_locus (),
"the %qs option was already provided",
- InlineAsmOptionMap[option].c_str ());
+ AST::InlineAsm::option_to_string (option).c_str ());
return;
}
else
@@ -536,39 +533,40 @@ parse_options (InlineAsmContext &inline_asm_ctx)
{
if (!is_global_asm && check_identifier (parser, "pure"))
{
- check_and_set (inline_asm_ctx, AST::InlineAsmOption::PURE);
+ check_and_set (inline_asm_ctx, AST::InlineAsm::Option::PURE);
}
else if (!is_global_asm && check_identifier (parser, "nomem"))
{
- check_and_set (inline_asm_ctx, AST::InlineAsmOption::NOMEM);
+ check_and_set (inline_asm_ctx, AST::InlineAsm::Option::NOMEM);
}
else if (!is_global_asm && check_identifier (parser, "readonly"))
{
- check_and_set (inline_asm_ctx, AST::InlineAsmOption::READONLY);
+ check_and_set (inline_asm_ctx, AST::InlineAsm::Option::READONLY);
}
else if (!is_global_asm && check_identifier (parser, "preserves_flags"))
{
- check_and_set (inline_asm_ctx, AST::InlineAsmOption::PRESERVES_FLAGS);
+ check_and_set (inline_asm_ctx,
+ AST::InlineAsm::Option::PRESERVES_FLAGS);
}
else if (!is_global_asm && check_identifier (parser, "noreturn"))
{
- check_and_set (inline_asm_ctx, AST::InlineAsmOption::NORETURN);
+ check_and_set (inline_asm_ctx, AST::InlineAsm::Option::NORETURN);
}
else if (!is_global_asm && check_identifier (parser, "nostack"))
{
- check_and_set (inline_asm_ctx, AST::InlineAsmOption::NOSTACK);
+ check_and_set (inline_asm_ctx, AST::InlineAsm::Option::NOSTACK);
}
else if (!is_global_asm && check_identifier (parser, "may_unwind"))
{
- check_and_set (inline_asm_ctx, AST::InlineAsmOption::MAY_UNWIND);
+ check_and_set (inline_asm_ctx, AST::InlineAsm::Option::MAY_UNWIND);
}
else if (check_identifier (parser, "att_syntax"))
{
- check_and_set (inline_asm_ctx, AST::InlineAsmOption::ATT_SYNTAX);
+ check_and_set (inline_asm_ctx, AST::InlineAsm::Option::ATT_SYNTAX);
}
else if (check_identifier (parser, "raw"))
{
- check_and_set (inline_asm_ctx, AST::InlineAsmOption::RAW);
+ check_and_set (inline_asm_ctx, AST::InlineAsm::Option::RAW);
}
else
{
@@ -807,7 +805,8 @@ expand_inline_asm_strings (InlineAsmContext inline_asm_ctx)
auto next_argument = piece.next_argument._0;
switch (piece.next_argument._0.position.tag)
{
- case Fmt::ffi::Position::Tag::ArgumentImplicitlyIs: {
+ case Fmt::ffi::Position::Tag::ArgumentImplicitlyIs:
+ {
auto idx = next_argument.position.argument_implicitly_is._0;
/*auto trait = next_argument.format;*/
/*auto arg = arguments.at (idx);*/
@@ -829,6 +828,11 @@ expand_inline_asm_strings (InlineAsmContext inline_asm_ctx)
}
break;
case Fmt::ffi::Position::Tag::ArgumentIs:
+ {
+ auto idx = next_argument.position.argument_is._0;
+ transformed_template_str += "%" + std::to_string (idx);
+ break;
+ }
case Fmt::ffi::Position::Tag::ArgumentNamed:
rust_sorry_at (inline_asm.get_locus (),
"unhandled argument position specifier");
@@ -933,7 +937,9 @@ parse_format_strings (InlineAsmContext inline_asm_ctx)
{
if (!parser.skip_token (COMMA))
{
- break;
+ rust_error_at (parser.peek_current_token ()->get_locus (),
+ "expected token %qs", ";");
+ return tl::unexpected<InlineAsmParseError> (COMMITTED);
}
// Ok after the comma is good, we better be parsing correctly
// everything in here, which is formatted string in ABNF
diff --git a/gcc/rust/expand/rust-macro-builtins-asm.h b/gcc/rust/expand/rust-macro-builtins-asm.h
index bd64a7f..3196a5a 100644
--- a/gcc/rust/expand/rust-macro-builtins-asm.h
+++ b/gcc/rust/expand/rust-macro-builtins-asm.h
@@ -142,16 +142,16 @@ tl::expected<InlineAsmContext, InlineAsmParseError>
parse_reg_operand_unexpected (InlineAsmContext inline_asm_ctx);
WARN_UNUSED_RESULT
-tl::optional<AST::Fragment>
-parse_asm (location_t invoc_locus, AST::MacroInvocData &invoc,
- AST::InvocKind semicolon, AST::AsmKind is_global_asm);
+tl::optional<AST::Fragment> parse_asm (location_t invoc_locus,
+ AST::MacroInvocData &invoc,
+ AST::InvocKind semicolon,
+ AST::AsmKind is_global_asm);
WARN_UNUSED_RESULT
-bool
-check_identifier (Parser<MacroInvocLexer> &parser, std::string ident);
+bool check_identifier (Parser<MacroInvocLexer> &parser, std::string ident);
-void
-check_and_set (InlineAsmContext &inline_asm_ctx, AST::InlineAsmOption option);
+void check_and_set (InlineAsmContext &inline_asm_ctx,
+ AST::InlineAsm::Option option);
// From rustc
WARN_UNUSED_RESULT
@@ -168,9 +168,9 @@ tl::optional<std::string>
parse_format_string (InlineAsmContext &inline_asm_ctx);
WARN_UNUSED_RESULT
-tl::optional<std::string>
-parse_label (Parser<MacroInvocLexer> &parser, TokenId last_token_id,
- InlineAsmContext &inline_asm_ctx);
+tl::optional<std::string> parse_label (Parser<MacroInvocLexer> &parser,
+ TokenId last_token_id,
+ InlineAsmContext &inline_asm_ctx);
// LLVM ASM bits
@@ -188,17 +188,13 @@ public:
{}
};
-void
-parse_llvm_outputs (LlvmAsmContext &ctx);
+void parse_llvm_outputs (LlvmAsmContext &ctx);
-void
-parse_llvm_inputs (LlvmAsmContext &ctx);
+void parse_llvm_inputs (LlvmAsmContext &ctx);
-void
-parse_llvm_clobbers (LlvmAsmContext &ctx);
+void parse_llvm_clobbers (LlvmAsmContext &ctx);
-void
-parse_llvm_options (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,
diff --git a/gcc/rust/expand/rust-macro-builtins-format-args.cc b/gcc/rust/expand/rust-macro-builtins-format-args.cc
index 3e1249d..b20c849 100644
--- a/gcc/rust/expand/rust-macro-builtins-format-args.cc
+++ b/gcc/rust/expand/rust-macro-builtins-format-args.cc
@@ -52,8 +52,15 @@ format_args_parse_arguments (AST::MacroInvocData &invoc)
// TODO: Handle the case where we're not parsing a string literal (macro
// invocation for e.g.)
- if (parser.peek_current_token ()->get_id () == STRING_LITERAL)
- format_expr = parser.parse_literal_expr ();
+ switch (parser.peek_current_token ()->get_id ())
+ {
+ case STRING_LITERAL:
+ case RAW_STRING_LITERAL:
+ format_expr = parser.parse_literal_expr ();
+ default:
+ // do nothing
+ ;
+ }
rust_assert (format_expr);
diff --git a/gcc/rust/expand/rust-macro-builtins-helpers.cc b/gcc/rust/expand/rust-macro-builtins-helpers.cc
index 864379a..ee01f65 100644
--- a/gcc/rust/expand/rust-macro-builtins-helpers.cc
+++ b/gcc/rust/expand/rust-macro-builtins-helpers.cc
@@ -68,6 +68,7 @@ make_eager_builtin_invocation (
{
auto path_str = make_macro_path_str (kind);
+ auto token_stream = arguments.to_token_stream ();
std::unique_ptr<AST::Expr> node = AST::MacroInvocation::Builtin (
kind,
AST::MacroInvocData (AST::SimplePath (
@@ -76,7 +77,7 @@ make_eager_builtin_invocation (
{}, locus, std::move (pending_invocations));
return AST::Fragment ({AST::SingleASTNode (std::move (node))},
- arguments.to_token_stream ());
+ std::move (token_stream));
}
/* Match the end token of a macro given the start delimiter of the macro */
@@ -110,9 +111,9 @@ std::unique_ptr<AST::LiteralExpr>
try_extract_string_literal_from_fragment (const location_t &parent_locus,
std::unique_ptr<AST::Expr> &node)
{
- auto maybe_lit = static_cast<AST::LiteralExpr *> (node.get ());
if (!node || !node->is_literal ()
- || maybe_lit->get_lit_type () != AST::Literal::STRING)
+ || static_cast<AST::LiteralExpr &> (*node).get_lit_type ()
+ != AST::Literal::STRING)
{
rust_error_at (parent_locus, "argument must be a string literal");
if (node)
diff --git a/gcc/rust/expand/rust-macro-builtins-helpers.h b/gcc/rust/expand/rust-macro-builtins-helpers.h
index 429537e..32cf58f 100644
--- a/gcc/rust/expand/rust-macro-builtins-helpers.h
+++ b/gcc/rust/expand/rust-macro-builtins-helpers.h
@@ -33,29 +33,23 @@
#include "rust-token.h"
namespace Rust {
-std::string
-make_macro_path_str (BuiltinMacro kind);
+std::string make_macro_path_str (BuiltinMacro kind);
-std::vector<std::unique_ptr<AST::MacroInvocation>>
-check_for_eager_invocations (
+std::vector<std::unique_ptr<AST::MacroInvocation>> check_for_eager_invocations (
std::vector<std::unique_ptr<AST::Expr>> &expressions);
// Shorthand function for creating unique_ptr tokens
-std::unique_ptr<AST::Token>
-make_token (const TokenPtr tok);
+std::unique_ptr<AST::Token> make_token (const TokenPtr tok);
-std::unique_ptr<AST::Expr>
-make_string (location_t locus, std::string value);
+std::unique_ptr<AST::Expr> make_string (location_t locus, std::string value);
// TODO: Is this correct?
-AST::Fragment
-make_eager_builtin_invocation (
+AST::Fragment make_eager_builtin_invocation (
BuiltinMacro kind, location_t locus, AST::DelimTokenTree arguments,
std::vector<std::unique_ptr<AST::MacroInvocation>> &&pending_invocations);
// Match the end token of a macro given the start delimiter of the macro
-TokenId
-macro_end_token (AST::DelimTokenTree &invoc_token_tree,
- Parser<MacroInvocLexer> &parser);
+TokenId macro_end_token (AST::DelimTokenTree &invoc_token_tree,
+ Parser<MacroInvocLexer> &parser);
// Expand and then extract a string literal from the macro
std::unique_ptr<AST::LiteralExpr>
try_extract_string_literal_from_fragment (const location_t &parent_locus,
@@ -70,21 +64,18 @@ try_expand_many_expr (Parser<MacroInvocLexer> &parser,
// and return the LiteralExpr for it. Allow for an optional trailing comma,
// but otherwise enforce that these are the only tokens.
-std::unique_ptr<AST::Expr>
-parse_single_string_literal (BuiltinMacro kind,
- AST::DelimTokenTree &invoc_token_tree,
- location_t invoc_locus, MacroExpander *expander,
- bool is_semicoloned = false);
+std::unique_ptr<AST::Expr> parse_single_string_literal (
+ BuiltinMacro kind, AST::DelimTokenTree &invoc_token_tree,
+ location_t invoc_locus, MacroExpander *expander, bool is_semicoloned = false);
// Treat PATH as a path relative to the source file currently being
// compiled, and return the absolute path for it.
-std::string
-source_relative_path (std::string path, location_t locus);
+std::string source_relative_path (std::string path, location_t locus);
// Read the full contents of the file FILENAME and return them in a vector.
// FIXME: platform specific.
-tl::optional<std::vector<uint8_t>>
-load_file_bytes (location_t invoc_locus, const char *filename);
+tl::optional<std::vector<uint8_t>> load_file_bytes (location_t invoc_locus,
+ const char *filename);
} // namespace Rust
#endif // GCCRS_RUST_MACRO_BUILTINS_HELPERS_H
diff --git a/gcc/rust/expand/rust-macro-builtins-offset-of.cc b/gcc/rust/expand/rust-macro-builtins-offset-of.cc
new file mode 100644
index 0000000..53efe74
--- /dev/null
+++ b/gcc/rust/expand/rust-macro-builtins-offset-of.cc
@@ -0,0 +1,78 @@
+// Copyright (C) 2020-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 "optional.h"
+#include "rust-ast-fragment.h"
+#include "rust-ast.h"
+#include "rust-builtin-ast-nodes.h"
+#include "rust-diagnostics.h"
+#include "rust-macro-builtins-helpers.h"
+#include "rust-macro-builtins.h"
+#include "rust-macro-invoc-lexer.h"
+#include "rust-parse.h"
+
+namespace Rust {
+
+tl::optional<AST::Fragment>
+MacroBuiltin::offset_of_handler (location_t invoc_locus,
+ AST::MacroInvocData &invoc,
+ AST::InvocKind semicolon)
+{
+ MacroInvocLexer lex (invoc.get_delim_tok_tree ().to_token_stream ());
+ Parser<MacroInvocLexer> parser (lex);
+
+ auto last_token = macro_end_token (invoc.get_delim_tok_tree (), parser);
+
+ auto type = parser.parse_type ();
+
+ // if we don't see a type, there might be an eager macro expansion missing
+ // FIXME: handle that
+ if (!type)
+ {
+ rust_error_at (invoc_locus, "could not parse type argument for %qs",
+ "offset_of");
+
+ // we skip so we can still parse the field arg and check if it is correct
+ while (parser.peek_current_token ()->get_id () != COMMA
+ && parser.peek_current_token ()->get_id () != last_token)
+ parser.skip_token ();
+ }
+
+ parser.skip_token (COMMA);
+
+ auto field_tok = parser.parse_identifier_or_keyword_token ();
+ auto invalid_field = !field_tok || !field_tok->has_str ();
+
+ if (invalid_field)
+ rust_error_at (invoc_locus, "could not parse field argument for %qs",
+ "offset_of");
+
+ if (!type || invalid_field)
+ return tl::nullopt;
+
+ auto field = Identifier (field_tok->get_str ());
+
+ // FIXME: Do we need to do anything to handle the optional comma at the end?
+ parser.maybe_skip_token (COMMA);
+
+ return AST::Fragment ({AST::SingleASTNode (std::make_unique<AST::OffsetOf> (
+ std::move (type), field, invoc_locus))},
+ invoc.get_delim_tok_tree ().to_token_stream ());
+}
+
+} // namespace Rust
diff --git a/gcc/rust/expand/rust-macro-builtins.cc b/gcc/rust/expand/rust-macro-builtins.cc
index b58ed71..a7ae220 100644
--- a/gcc/rust/expand/rust-macro-builtins.cc
+++ b/gcc/rust/expand/rust-macro-builtins.cc
@@ -162,6 +162,9 @@ std::unordered_map<std::string, AST::MacroTranscriberFunc>
{"Ord", MacroBuiltin::proc_macro_builtin},
{"PartialOrd", MacroBuiltin::proc_macro_builtin},
{"Hash", MacroBuiltin::proc_macro_builtin},
+ /* offset_of is not declared in Rust 1.49 but still needed for
+ Rust-for-Linux, so we still create a transcriber and warn the user */
+ {"offset_of", MacroBuiltin::offset_of_handler},
};
tl::optional<BuiltinMacro>
diff --git a/gcc/rust/expand/rust-macro-builtins.h b/gcc/rust/expand/rust-macro-builtins.h
index 541e956..b6c2907 100644
--- a/gcc/rust/expand/rust-macro-builtins.h
+++ b/gcc/rust/expand/rust-macro-builtins.h
@@ -19,6 +19,7 @@
#ifndef RUST_MACRO_BUILTINS_H
#define RUST_MACRO_BUILTINS_H
+#include "optional.h"
#include "rust-ast.h"
#include "rust-builtin-ast-nodes.h"
#include "rust-ast-fragment.h"
@@ -188,6 +189,9 @@ public:
format_args_handler (location_t invoc_locus, AST::MacroInvocData &invoc,
AST::InvocKind semicolon, AST::FormatArgs::Newline nl);
+ static tl::optional<AST::Fragment>
+ offset_of_handler (location_t, AST::MacroInvocData &, AST::InvocKind);
+
static tl::optional<AST::Fragment> sorry (location_t invoc_locus,
AST::MacroInvocData &invoc,
AST::InvocKind semicolon);
diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc
index 673b8fb..4c54cef 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -19,6 +19,7 @@
#include "rust-macro-expand.h"
#include "optional.h"
#include "rust-ast-fragment.h"
+#include "rust-macro-builtins.h"
#include "rust-macro-substitute-ctx.h"
#include "rust-ast-full.h"
#include "rust-ast-visitor.h"
@@ -287,6 +288,26 @@ MacroExpander::expand_invoc (AST::MacroInvocation &invoc,
// lookup the rules
auto rules_def = mappings.lookup_macro_invocation (invoc);
+ // We special case the `offset_of!()` macro if the flag is here and manually
+ // resolve to the builtin transcriber we have specified
+ auto assume_builtin_offset_of
+ = flag_assume_builtin_offset_of
+ && (invoc.get_invoc_data ().get_path ().as_string () == "offset_of")
+ && !rules_def;
+
+ // TODO: This is *massive hack* which should be removed as we progress to
+ // Rust 1.71 when offset_of gets added to core
+ if (assume_builtin_offset_of)
+ {
+ fragment = MacroBuiltin::offset_of_handler (invoc.get_locus (),
+ invoc_data, semicolon)
+ .value_or (AST::Fragment::create_empty ());
+
+ set_expanded_fragment (std::move (fragment));
+
+ return;
+ }
+
// If there's no rule associated with the invocation, we can simply return
// early. The early name resolver will have already emitted an error.
if (!rules_def)
@@ -430,7 +451,8 @@ MacroExpander::match_fragment (Parser<MacroInvocLexer> &parser,
parser.parse_visibility ();
break;
- case AST::MacroFragSpec::STMT: {
+ case AST::MacroFragSpec::STMT:
+ {
auto restrictions = ParseRestrictions ();
restrictions.consume_semi = false;
parser.parse_stmt (restrictions);
@@ -480,19 +502,22 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer> &parser,
// this is used so we can check that we delimit the stream correctly.
switch (delimiter->get_id ())
{
- case LEFT_PAREN: {
+ case LEFT_PAREN:
+ {
if (!check_delim (AST::DelimType::PARENS))
return false;
}
break;
- case LEFT_SQUARE: {
+ case LEFT_SQUARE:
+ {
if (!check_delim (AST::DelimType::SQUARE))
return false;
}
break;
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
if (!check_delim (AST::DelimType::CURLY))
return false;
}
@@ -510,7 +535,8 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer> &parser,
switch (match->get_macro_match_type ())
{
- case AST::MacroMatch::MacroMatchType::Fragment: {
+ case AST::MacroMatch::MacroMatchType::Fragment:
+ {
AST::MacroMatchFragment *fragment
= static_cast<AST::MacroMatchFragment *> (match.get ());
if (!match_fragment (parser, *fragment))
@@ -524,14 +550,16 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer> &parser,
}
break;
- case AST::MacroMatch::MacroMatchType::Tok: {
+ case AST::MacroMatch::MacroMatchType::Tok:
+ {
AST::Token *tok = static_cast<AST::Token *> (match.get ());
if (!match_token (parser, *tok))
return false;
}
break;
- case AST::MacroMatch::MacroMatchType::Repetition: {
+ case AST::MacroMatch::MacroMatchType::Repetition:
+ {
AST::MacroMatchRepetition *rep
= static_cast<AST::MacroMatchRepetition *> (match.get ());
if (!match_repetition (parser, *rep))
@@ -539,7 +567,8 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer> &parser,
}
break;
- case AST::MacroMatch::MacroMatchType::Matcher: {
+ case AST::MacroMatch::MacroMatchType::Matcher:
+ {
AST::MacroMatcher *m
= static_cast<AST::MacroMatcher *> (match.get ());
expansion_depth++;
@@ -556,19 +585,22 @@ MacroExpander::match_matcher (Parser<MacroInvocLexer> &parser,
switch (delimiter->get_id ())
{
- case LEFT_PAREN: {
+ case LEFT_PAREN:
+ {
if (!parser.skip_token (RIGHT_PAREN))
return false;
}
break;
- case LEFT_SQUARE: {
+ case LEFT_SQUARE:
+ {
if (!parser.skip_token (RIGHT_SQUARE))
return false;
}
break;
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
if (!parser.skip_token (RIGHT_CURLY))
return false;
}
@@ -617,7 +649,8 @@ MacroExpander::match_n_matches (Parser<MacroInvocLexer> &parser,
size_t offs_begin = source.get_offs ();
switch (match->get_macro_match_type ())
{
- case AST::MacroMatch::MacroMatchType::Fragment: {
+ case AST::MacroMatch::MacroMatchType::Fragment:
+ {
AST::MacroMatchFragment *fragment
= static_cast<AST::MacroMatchFragment *> (match.get ());
valid_current_match = match_fragment (parser, *fragment);
@@ -632,20 +665,23 @@ MacroExpander::match_n_matches (Parser<MacroInvocLexer> &parser,
}
break;
- case AST::MacroMatch::MacroMatchType::Tok: {
+ case AST::MacroMatch::MacroMatchType::Tok:
+ {
AST::Token *tok = static_cast<AST::Token *> (match.get ());
valid_current_match = match_token (parser, *tok);
}
break;
- case AST::MacroMatch::MacroMatchType::Repetition: {
+ case AST::MacroMatch::MacroMatchType::Repetition:
+ {
AST::MacroMatchRepetition *rep
= static_cast<AST::MacroMatchRepetition *> (match.get ());
valid_current_match = match_repetition (parser, *rep);
}
break;
- case AST::MacroMatch::MacroMatchType::Matcher: {
+ case AST::MacroMatch::MacroMatchType::Matcher:
+ {
AST::MacroMatcher *m
= static_cast<AST::MacroMatcher *> (match.get ());
valid_current_match = match_matcher (parser, *m, true);
diff --git a/gcc/rust/expand/rust-macro-substitute-ctx.cc b/gcc/rust/expand/rust-macro-substitute-ctx.cc
index 02e4e3b..ac36ed8 100644
--- a/gcc/rust/expand/rust-macro-substitute-ctx.cc
+++ b/gcc/rust/expand/rust-macro-substitute-ctx.cc
@@ -273,7 +273,8 @@ SubstituteCtx::substitute_token (size_t token_idx)
// don't substitute, dollar sign is alone/metavar is unknown
return {std::vector<std::unique_ptr<AST::Token>> (), 0};
- case LEFT_PAREN: {
+ case LEFT_PAREN:
+ {
// We need to parse up until the closing delimiter and expand this
// fragment->n times.
rust_debug ("expanding repetition");
diff --git a/gcc/rust/expand/rust-proc-macro.h b/gcc/rust/expand/rust-proc-macro.h
index 6ffaaf6..058c93a 100644
--- a/gcc/rust/expand/rust-proc-macro.h
+++ b/gcc/rust/expand/rust-proc-macro.h
@@ -82,11 +82,9 @@ public:
*
* @param The path to the shared object file to load.
*/
-const std::vector<ProcMacro::Procmacro>
-load_macros (std::string path);
+const std::vector<ProcMacro::Procmacro> load_macros (std::string path);
-std::string
-generate_proc_macro_decls_symbol (std::uint32_t stable_crate_id);
+std::string generate_proc_macro_decls_symbol (std::uint32_t stable_crate_id);
} // namespace Rust
diff --git a/gcc/rust/expand/rust-token-tree-desugar.cc b/gcc/rust/expand/rust-token-tree-desugar.cc
index 3b47180..aa20d50 100644
--- a/gcc/rust/expand/rust-token-tree-desugar.cc
+++ b/gcc/rust/expand/rust-token-tree-desugar.cc
@@ -68,5 +68,5 @@ TokenTreeDesugar::visit (Token &tts)
}
}
-}; // namespace AST
-}; // namespace Rust
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/expand/rust-token-tree-desugar.h b/gcc/rust/expand/rust-token-tree-desugar.h
index ccba53b..da9d732 100644
--- a/gcc/rust/expand/rust-token-tree-desugar.h
+++ b/gcc/rust/expand/rust-token-tree-desugar.h
@@ -49,7 +49,7 @@ private:
virtual void visit (Token &tts) override;
};
-}; // namespace AST
-}; // namespace Rust
+} // 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 2d9a445..b723f59 100644
--- a/gcc/rust/hir/rust-ast-lower-base.cc
+++ b/gcc/rust/hir/rust-ast-lower-base.cc
@@ -47,6 +47,27 @@ ASTLoweringBase::visit (AST::ErrorPropagationExpr &expr)
}
void
+ASTLoweringBase::visit (AST::TryExpr &expr)
+{
+ rust_fatal_error (expr.get_locus (), "missing desugar for try-blocks");
+ rust_unreachable ();
+}
+
+void
+ASTLoweringBase::visit (AST::ForLoopExpr &expr)
+{
+ rust_fatal_error (expr.get_locus (), "missing desugar for for-loops");
+ rust_unreachable ();
+}
+
+void
+ASTLoweringBase::visit (AST::WhileLetLoopExpr &expr)
+{
+ rust_fatal_error (expr.get_locus (), "missing desugar for while-let loops");
+ rust_unreachable ();
+}
+
+void
ASTLoweringBase::visit (AST::Token &)
{}
void
@@ -115,7 +136,7 @@ void
ASTLoweringBase::visit (AST::MetaItemLitExpr &)
{}
void
-ASTLoweringBase::visit (AST::MetaItemPathLit &)
+ASTLoweringBase::visit (AST::MetaItemPathExpr &)
{}
void
ASTLoweringBase::visit (AST::BorrowExpr &)
@@ -201,6 +222,12 @@ void
ASTLoweringBase::visit (AST::BlockExpr &)
{}
void
+ASTLoweringBase::visit (AST::AnonConst &)
+{}
+void
+ASTLoweringBase::visit (AST::ConstBlock &)
+{}
+void
ASTLoweringBase::visit (AST::ClosureExprInnerTyped &)
{}
void
@@ -245,12 +272,6 @@ void
ASTLoweringBase::visit (AST::WhileLoopExpr &)
{}
void
-ASTLoweringBase::visit (AST::WhileLetLoopExpr &)
-{}
-void
-ASTLoweringBase::visit (AST::ForLoopExpr &)
-{}
-void
ASTLoweringBase::visit (AST::IfExpr &)
{}
void
@@ -474,6 +495,12 @@ void
ASTLoweringBase::visit (AST::GroupedPattern &)
{}
void
+ASTLoweringBase::visit (AST::SlicePatternItemsNoRest &)
+{}
+void
+ASTLoweringBase::visit (AST::SlicePatternItemsHasRest &)
+{}
+void
ASTLoweringBase::visit (AST::SlicePattern &)
{}
void
@@ -551,6 +578,10 @@ void
ASTLoweringBase::visit (AST::FormatArgs &fmt)
{}
+void
+ASTLoweringBase::visit (AST::OffsetOf &offset_of)
+{}
+
HIR::Lifetime
ASTLoweringBase::lower_lifetime (AST::Lifetime &lifetime,
bool default_to_static_lifetime)
@@ -648,12 +679,14 @@ ASTLoweringBase::lower_generic_args (AST::GenericArgs &args)
{
switch (arg.get_kind ())
{
- case AST::GenericArg::Kind::Type: {
+ case AST::GenericArg::Kind::Type:
+ {
auto type = ASTLoweringType::translate (arg.get_type ());
type_args.emplace_back (std::unique_ptr<HIR::Type> (type));
break;
}
- case AST::GenericArg::Kind::Const: {
+ case AST::GenericArg::Kind::Const:
+ {
auto expr = ASTLoweringExpr::translate (arg.get_expression ());
const_args.emplace_back (
HIR::ConstGenericArg (std::unique_ptr<HIR::Expr> (expr),
@@ -887,7 +920,8 @@ ASTLoweringBase::lower_range_pattern_bound (AST::RangePatternBound &bound)
std::unique_ptr<HIR::RangePatternBound> hir_bound = nullptr;
switch (bound.get_bound_type ())
{
- case AST::RangePatternBound::RangePatternBoundType::LITERAL: {
+ case AST::RangePatternBound::RangePatternBoundType::LITERAL:
+ {
AST::RangePatternBoundLiteral &ref
= static_cast<AST::RangePatternBoundLiteral &> (bound);
@@ -898,7 +932,8 @@ ASTLoweringBase::lower_range_pattern_bound (AST::RangePatternBound &bound)
ref.get_has_minus ()));
}
break;
- case AST::RangePatternBound::RangePatternBoundType::PATH: {
+ case AST::RangePatternBound::RangePatternBoundType::PATH:
+ {
auto &ref = static_cast<AST::RangePatternBoundPath &> (bound);
HIR::PathInExpression *path
@@ -908,7 +943,8 @@ ASTLoweringBase::lower_range_pattern_bound (AST::RangePatternBound &bound)
new HIR::RangePatternBoundPath (*path));
}
break;
- case AST::RangePatternBound::RangePatternBoundType::QUALPATH: {
+ case AST::RangePatternBound::RangePatternBoundType::QUALPATH:
+ {
auto &ref = static_cast<AST::RangePatternBoundQualPath &> (bound);
HIR::QualifiedPathInExpression *qualpath
diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h
index 3116181..e86aacb 100644
--- a/gcc/rust/hir/rust-ast-lower-base.h
+++ b/gcc/rust/hir/rust-ast-lower-base.h
@@ -20,6 +20,8 @@
#define RUST_AST_LOWER_BASE
#include "rust-ast.h"
+#include "rust-builtin-ast-nodes.h"
+#include "rust-expr.h"
#include "rust-system.h"
#include "rust-ast-full.h"
#include "rust-ast-visitor.h"
@@ -63,6 +65,9 @@ public:
// Special casing nodes that should never reach the HIR lowering stage
virtual void visit (AST::MacroInvocation &) override final;
virtual void visit (AST::ErrorPropagationExpr &) override final;
+ virtual void visit (AST::ForLoopExpr &) override final;
+ virtual void visit (AST::TryExpr &) override final;
+ virtual void visit (AST::WhileLetLoopExpr &) override final;
// visitor impl
// rust-ast.h
@@ -101,7 +106,7 @@ public:
virtual void visit (AST::AttrInputLiteral &attr_input) override;
virtual void visit (AST::AttrInputMacro &attr_input) override;
virtual void visit (AST::MetaItemLitExpr &meta_item) override;
- virtual void visit (AST::MetaItemPathLit &meta_item) override;
+ virtual void visit (AST::MetaItemPathExpr &meta_item) override;
virtual void visit (AST::BorrowExpr &expr) override;
virtual void visit (AST::DereferenceExpr &expr) override;
virtual void visit (AST::NegationExpr &expr) override;
@@ -131,6 +136,8 @@ public:
virtual void visit (AST::FieldAccessExpr &expr) override;
virtual void visit (AST::ClosureExprInner &expr) override;
virtual void visit (AST::BlockExpr &expr) override;
+ virtual void visit (AST::AnonConst &expr) override;
+ virtual void visit (AST::ConstBlock &expr) override;
virtual void visit (AST::ClosureExprInnerTyped &expr) override;
virtual void visit (AST::ContinueExpr &expr) override;
virtual void visit (AST::BreakExpr &expr) override;
@@ -145,8 +152,6 @@ public:
virtual void visit (AST::UnsafeBlockExpr &expr) override;
virtual void visit (AST::LoopExpr &expr) override;
virtual void visit (AST::WhileLoopExpr &expr) override;
- virtual void visit (AST::WhileLetLoopExpr &expr) override;
- virtual void visit (AST::ForLoopExpr &expr) override;
virtual void visit (AST::IfExpr &expr) override;
virtual void visit (AST::IfExprConseqElse &expr) override;
virtual void visit (AST::IfLetExpr &expr) override;
@@ -231,6 +236,8 @@ public:
virtual void visit (AST::TuplePatternItemsRanged &tuple_items) override;
virtual void visit (AST::TuplePattern &pattern) override;
virtual void visit (AST::GroupedPattern &pattern) override;
+ virtual void visit (AST::SlicePatternItemsNoRest &items) override;
+ virtual void visit (AST::SlicePatternItemsHasRest &items) override;
virtual void visit (AST::SlicePattern &pattern) override;
virtual void visit (AST::AltPattern &pattern) override;
@@ -259,6 +266,7 @@ public:
virtual void visit (AST::SelfParam &param) override;
virtual void visit (AST::FormatArgs &fmt) override;
+ virtual void visit (AST::OffsetOf &offset_of) override;
protected:
ASTLoweringBase ()
diff --git a/gcc/rust/hir/rust-ast-lower-block.h b/gcc/rust/hir/rust-ast-lower-block.h
index 93cd443..f10039b 100644
--- a/gcc/rust/hir/rust-ast-lower-block.h
+++ b/gcc/rust/hir/rust-ast-lower-block.h
@@ -213,8 +213,6 @@ public:
void visit (AST::WhileLoopExpr &expr) override;
- void visit (AST::ForLoopExpr &expr) override;
-
void visit (AST::MatchExpr &expr) override;
private:
diff --git a/gcc/rust/hir/rust-ast-lower-expr.cc b/gcc/rust/hir/rust-ast-lower-expr.cc
index 07d0c835..4ed51d9 100644
--- a/gcc/rust/hir/rust-ast-lower-expr.cc
+++ b/gcc/rust/hir/rust-ast-lower-expr.cc
@@ -24,7 +24,9 @@
#include "rust-ast-lower-pattern.h"
#include "rust-ast-lower-type.h"
#include "rust-ast.h"
+#include "rust-builtin-ast-nodes.h"
#include "rust-diagnostics.h"
+#include "rust-hir-map.h"
#include "rust-system.h"
#include "tree/rust-hir-expr.h"
@@ -127,6 +129,50 @@ ASTLoweringExpr::visit (AST::BlockExpr &expr)
}
void
+ASTLoweringExpr::visit (AST::AnonConst &expr)
+{
+ auto &mappings = Analysis::Mappings::get ();
+ auto crate_num = mappings.get_current_crate ();
+ auto mapping = Analysis::NodeMapping (crate_num, expr.get_node_id (),
+ mappings.get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ if (expr.is_deferred ())
+ {
+ translated = new HIR::AnonConst (std::move (mapping), expr.get_locus ());
+ }
+ else
+ {
+ auto inner_expr = ASTLoweringExpr::translate (expr.get_inner_expr ());
+
+ translated = new HIR::AnonConst (std::move (mapping),
+ std::unique_ptr<Expr> (inner_expr),
+ expr.get_locus ());
+ }
+}
+
+void
+ASTLoweringExpr::visit (AST::ConstBlock &expr)
+{
+ auto inner_expr = ASTLoweringExpr::translate (expr.get_const_expr ());
+
+ // we know this will always be an `AnonConst`, or we have an issue. Let's
+ // assert just to be sure.
+ rust_assert (inner_expr->get_expression_type () == Expr::ExprType::AnonConst);
+ auto anon_const = static_cast<AnonConst *> (inner_expr);
+
+ auto &mappings = Analysis::Mappings::get ();
+ auto crate_num = mappings.get_current_crate ();
+ auto mapping = Analysis::NodeMapping (crate_num, expr.get_node_id (),
+ mappings.get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated
+ = new HIR::ConstBlock (std::move (mapping), std::move (*anon_const),
+ expr.get_locus (), expr.get_outer_attrs ());
+}
+
+void
ASTLoweringExpr::visit (AST::UnsafeBlockExpr &expr)
{
translated = ASTLoweringBlock::translate (expr, &terminated);
@@ -589,12 +635,6 @@ ASTLoweringExpr::visit (AST::WhileLoopExpr &expr)
}
void
-ASTLoweringExpr::visit (AST::ForLoopExpr &expr)
-{
- rust_unreachable ();
-}
-
-void
ASTLoweringExpr::visit (AST::BreakExpr &expr)
{
tl::optional<HIR::Lifetime> break_label = tl::nullopt;
@@ -798,7 +838,7 @@ ASTLoweringExpr::visit (AST::ClosureExprInnerTyped &expr)
{
HIR::Type *closure_return_type = nullptr;
HIR::Expr *closure_expr
- = ASTLoweringExpr::translate (expr.get_definition_block ());
+ = ASTLoweringExpr::translate (expr.get_definition_expr ());
std::vector<HIR::ClosureParam> closure_params;
for (auto &param : expr.get_params ())
@@ -841,6 +881,7 @@ translate_operand_out (const AST::InlineAsmOperand &operand)
*out_value.expr.get ())));
return out;
}
+
HIR::InlineAsmOperand
translate_operand_inout (const AST::InlineAsmOperand &operand)
{
@@ -851,6 +892,7 @@ translate_operand_inout (const AST::InlineAsmOperand &operand)
*inout_value.expr.get ())));
return inout;
}
+
HIR::InlineAsmOperand
translate_operand_split_in_out (const AST::InlineAsmOperand &operand)
{
@@ -863,19 +905,21 @@ translate_operand_split_in_out (const AST::InlineAsmOperand &operand)
ASTLoweringExpr::translate (*split_in_out_value.out_expr.get ())));
return split_in_out;
}
+
HIR::InlineAsmOperand
translate_operand_const (const AST::InlineAsmOperand &operand)
{
auto const_value = operand.get_const ();
- struct HIR::AnonConst anon_const (const_value.anon_const.id,
- std::unique_ptr<Expr> (
- ASTLoweringExpr::translate (
- *const_value.anon_const.expr.get ())));
- struct HIR::InlineAsmOperand::Const cnst
- {
- anon_const
- };
- return cnst;
+
+ auto inner_expr = ASTLoweringExpr::translate (const_value.anon_const);
+
+ // Like `ConstBlock`, we know this should only be an `AnonConst` - let's
+ // assert to make sure and static cast
+ rust_assert (inner_expr->get_expression_type () == Expr::ExprType::AnonConst);
+
+ auto anon_const = static_cast<AnonConst *> (inner_expr);
+
+ return HIR::InlineAsmOperand::Const{*anon_const};
}
HIR::InlineAsmOperand
@@ -1006,5 +1050,20 @@ ASTLoweringExpr::visit (AST::FormatArgs &fmt)
"FormatArgs lowering is not implemented yet");
}
+void
+ASTLoweringExpr::visit (AST::OffsetOf &offset_of)
+{
+ auto type = std::unique_ptr<Type> (
+ ASTLoweringType::translate (offset_of.get_type ()));
+
+ auto crate_num = mappings.get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, offset_of.get_node_id (),
+ mappings.get_next_hir_id (crate_num),
+ mappings.get_next_localdef_id (crate_num));
+
+ translated = new HIR::OffsetOf (std::move (type), offset_of.get_field (),
+ mapping, offset_of.get_locus ());
+}
+
} // namespace HIR
} // namespace Rust
diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h
index adedeb3..4eed4ec 100644
--- a/gcc/rust/hir/rust-ast-lower-expr.h
+++ b/gcc/rust/hir/rust-ast-lower-expr.h
@@ -21,6 +21,7 @@
#include "rust-ast-lower-base.h"
#include "rust-ast.h"
+#include "rust-expr.h"
namespace Rust {
namespace HIR {
@@ -82,6 +83,8 @@ public:
void visit (AST::IfLetExpr &expr) override;
void visit (AST::IfLetExprConseqElse &expr) override;
void visit (AST::BlockExpr &expr) override;
+ void visit (AST::AnonConst &expr) override;
+ void visit (AST::ConstBlock &expr) override;
void visit (AST::UnsafeBlockExpr &expr) override;
void visit (AST::PathInExpression &expr) override;
void visit (AST::QualifiedPathInExpression &expr) override;
@@ -108,7 +111,6 @@ public:
void visit (AST::FieldAccessExpr &expr) override;
void visit (AST::LoopExpr &expr) override;
void visit (AST::WhileLoopExpr &expr) override;
- void visit (AST::ForLoopExpr &expr) override;
void visit (AST::BreakExpr &expr) override;
void visit (AST::ContinueExpr &expr) override;
void visit (AST::BorrowExpr &expr) override;
@@ -124,8 +126,9 @@ public:
void visit (AST::InlineAsm &expr) override;
void visit (AST::LlvmInlineAsm &expr) override;
- // Extra visitor for FormatArgs nodes
+ // Extra visitor for builtin macro nodes
void visit (AST::FormatArgs &fmt) override;
+ void visit (AST::OffsetOf &offset_of) override;
private:
ASTLoweringExpr ();
diff --git a/gcc/rust/hir/rust-ast-lower-extern.h b/gcc/rust/hir/rust-ast-lower-extern.h
index 0105e38..3dca1b6 100644
--- a/gcc/rust/hir/rust-ast-lower-extern.h
+++ b/gcc/rust/hir/rust-ast-lower-extern.h
@@ -99,7 +99,7 @@ public:
= static_cast<AST::IdentifierPattern &> (param.get_pattern ());
Identifier param_name = param_kind == AST::Pattern::Kind::Identifier
? param_ident.get_ident ()
- : std::string ("_");
+ : Identifier ("_", param.get_locus ());
HIR::Type *param_type = ASTLoweringType::translate (param.get_type ());
diff --git a/gcc/rust/hir/rust-ast-lower-implitem.cc b/gcc/rust/hir/rust-ast-lower-implitem.cc
index d815a71..5db11cb 100644
--- a/gcc/rust/hir/rust-ast-lower-implitem.cc
+++ b/gcc/rust/hir/rust-ast-lower-implitem.cc
@@ -138,7 +138,8 @@ ASTLowerImplItem::visit (AST::Function &function)
std::unique_ptr<HIR::Type> return_type
= function.has_return_type () ? std::unique_ptr<HIR::Type> (
- ASTLoweringType::translate (function.get_return_type ()))
+ ASTLoweringType::translate (function.get_return_type (), false,
+ true /* impl trait is allowed here*/))
: nullptr;
Defaultness defaultness
@@ -274,7 +275,16 @@ ASTLowerTraitItem::visit (AST::Function &func)
auto hir_param
= HIR::FunctionParam (mapping, std::move (translated_pattern),
std::move (translated_type), param.get_locus ());
- function_params.push_back (hir_param);
+ function_params.push_back (std::move (hir_param));
+ }
+
+ if (func.has_self_param ())
+ {
+ // insert mappings for self
+ // 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 ());
}
HIR::TraitFunctionDecl decl (func.get_function_name (),
@@ -300,14 +310,6 @@ ASTLowerTraitItem::visit (AST::Function &func)
= new HIR::TraitItemFunc (mapping, std::move (decl), std::move (block_expr),
func.get_outer_attrs (), func.get_locus ());
translated = trait_item;
- if (func.has_self_param ())
- {
- // insert mappings for self
- // 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
for (auto &param : trait_item->get_decl ().get_function_params ())
diff --git a/gcc/rust/hir/rust-ast-lower-item.cc b/gcc/rust/hir/rust-ast-lower-item.cc
index f4396b5..4e5a747 100644
--- a/gcc/rust/hir/rust-ast-lower-item.cc
+++ b/gcc/rust/hir/rust-ast-lower-item.cc
@@ -217,7 +217,7 @@ ASTLoweringItem::visit (AST::StructStruct &struct_decl)
field.get_outer_attrs ());
if (struct_field_name_exists (fields, translated_field))
- break;
+ continue;
fields.push_back (std::move (translated_field));
}
@@ -367,7 +367,9 @@ ASTLoweringItem::visit (AST::ConstantItem &constant)
HIR::Visibility vis = translate_visibility (constant.get_visibility ());
HIR::Type *type = ASTLoweringType::translate (constant.get_type (), true);
- HIR::Expr *expr = ASTLoweringExpr::translate (constant.get_expr ());
+ HIR::Expr *expr = nullptr;
+ if (constant.has_expr ())
+ expr = ASTLoweringExpr::translate (constant.get_expr ());
auto crate_num = mappings.get_current_crate ();
Analysis::NodeMapping mapping (crate_num, constant.get_node_id (),
@@ -411,7 +413,8 @@ ASTLoweringItem::visit (AST::Function &function)
std::unique_ptr<HIR::Type> return_type
= function.has_return_type () ? std::unique_ptr<HIR::Type> (
- ASTLoweringType::translate (function.get_return_type ()))
+ ASTLoweringType::translate (function.get_return_type (), false,
+ true /* impl trait is allowed here*/))
: nullptr;
std::vector<HIR::FunctionParam> function_params;
@@ -494,7 +497,8 @@ ASTLoweringItem::visit (AST::InherentImpl &impl_block)
{
switch (generic_param->get_kind ())
{
- case HIR::GenericParam::GenericKind::TYPE: {
+ case HIR::GenericParam::GenericKind::TYPE:
+ {
const HIR::TypeParam &t
= static_cast<const HIR::TypeParam &> (*generic_param);
@@ -651,7 +655,8 @@ ASTLoweringItem::visit (AST::TraitImpl &impl_block)
{
switch (generic_param->get_kind ())
{
- case HIR::GenericParam::GenericKind::TYPE: {
+ case HIR::GenericParam::GenericKind::TYPE:
+ {
const HIR::TypeParam &t
= static_cast<const HIR::TypeParam &> (*generic_param);
@@ -729,6 +734,25 @@ ASTLoweringItem::visit (AST::MacroRulesDefinition &def)
lower_macro_definition (def);
}
+void
+ASTLoweringItem::visit (AST::ExternCrate &extern_crate)
+{
+ if (extern_crate.references_self ())
+ return;
+
+ auto &mappings = Analysis::Mappings::get ();
+ CrateNum num
+ = mappings.lookup_crate_name (extern_crate.get_referenced_crate ())
+ .value ();
+ AST::Crate &crate = mappings.get_ast_crate (num);
+
+ auto saved_crate_num = mappings.get_current_crate ();
+ mappings.set_current_crate (num);
+ auto lowered = ASTLowering::Resolve (crate);
+ mappings.insert_hir_crate (std::move (lowered));
+ mappings.set_current_crate (saved_crate_num);
+}
+
HIR::SimplePath
ASTLoweringSimplePath::translate (const AST::SimplePath &path)
{
diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h
index 4e142ed..dc75057 100644
--- a/gcc/rust/hir/rust-ast-lower-item.h
+++ b/gcc/rust/hir/rust-ast-lower-item.h
@@ -45,6 +45,7 @@ public:
void visit (AST::TraitImpl &impl_block) override;
void visit (AST::ExternBlock &extern_block) override;
void visit (AST::MacroRulesDefinition &rules_def) override;
+ void visit (AST::ExternCrate &extern_crate) override;
private:
ASTLoweringItem () : translated (nullptr) {}
diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc b/gcc/rust/hir/rust-ast-lower-pattern.cc
index b7a4c56..8aabcd8 100644
--- a/gcc/rust/hir/rust-ast-lower-pattern.cc
+++ b/gcc/rust/hir/rust-ast-lower-pattern.cc
@@ -23,7 +23,9 @@
namespace Rust {
namespace HIR {
-ASTLoweringPattern::ASTLoweringPattern () : translated (nullptr) {}
+ASTLoweringPattern::ASTLoweringPattern ()
+ : translated (nullptr), is_let_top_level (false)
+{}
HIR::Pattern *
ASTLoweringPattern::translate (AST::Pattern &pattern, bool is_let_top_level)
@@ -49,13 +51,18 @@ ASTLoweringPattern::visit (AST::IdentifierPattern &pattern)
mappings.get_next_hir_id (crate_num),
UNKNOWN_LOCAL_DEFID);
- std::unique_ptr<Pattern> to_bind;
+ std::unique_ptr<Pattern> subpattern;
+ if (pattern.has_subpattern ())
+ {
+ subpattern = std::unique_ptr<Pattern> (
+ ASTLoweringPattern::translate (pattern.get_subpattern ()));
+ }
translated
= new HIR::IdentifierPattern (mapping, pattern.get_ident (),
pattern.get_locus (), pattern.get_is_ref (),
pattern.get_is_mut () ? Mutability::Mut
: Mutability::Imm,
- std::move (to_bind));
+ std::move (subpattern));
}
void
@@ -74,13 +81,15 @@ ASTLoweringPattern::visit (AST::TupleStructPattern &pattern)
auto &items = pattern.get_items ();
switch (items.get_item_type ())
{
- case AST::TupleStructItems::RANGE: {
+ case AST::TupleStructItems::RANGE:
+ {
// TODO
rust_unreachable ();
}
break;
- case AST::TupleStructItems::NO_RANGE: {
+ case AST::TupleStructItems::NO_RANGE:
+ {
AST::TupleStructItemsNoRange &items_no_range
= static_cast<AST::TupleStructItemsNoRange &> (items);
@@ -120,7 +129,8 @@ ASTLoweringPattern::visit (AST::StructPattern &pattern)
HIR::StructPatternField *f = nullptr;
switch (field->get_item_type ())
{
- case AST::StructPatternField::ItemType::TUPLE_PAT: {
+ case AST::StructPatternField::ItemType::TUPLE_PAT:
+ {
auto &tuple
= static_cast<AST::StructPatternFieldTuplePat &> (*field);
@@ -140,7 +150,8 @@ ASTLoweringPattern::visit (AST::StructPattern &pattern)
}
break;
- case AST::StructPatternField::ItemType::IDENT_PAT: {
+ case AST::StructPatternField::ItemType::IDENT_PAT:
+ {
AST::StructPatternFieldIdentPat &ident
= static_cast<AST::StructPatternFieldIdentPat &> (*field);
@@ -160,7 +171,8 @@ ASTLoweringPattern::visit (AST::StructPattern &pattern)
}
break;
- case AST::StructPatternField::ItemType::IDENT: {
+ case AST::StructPatternField::ItemType::IDENT:
+ {
AST::StructPatternFieldIdent &ident
= static_cast<AST::StructPatternFieldIdent &> (*field.get ());
@@ -213,7 +225,8 @@ ASTLoweringPattern::visit (AST::TuplePattern &pattern)
std::unique_ptr<HIR::TuplePatternItems> items;
switch (pattern.get_items ().get_pattern_type ())
{
- case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE: {
+ case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE:
+ {
AST::TuplePatternItemsMultiple &ref
= static_cast<AST::TuplePatternItemsMultiple &> (
pattern.get_items ());
@@ -221,7 +234,8 @@ ASTLoweringPattern::visit (AST::TuplePattern &pattern)
}
break;
- case AST::TuplePatternItems::TuplePatternItemType::RANGED: {
+ case AST::TuplePatternItems::TuplePatternItemType::RANGED:
+ {
AST::TuplePatternItemsRanged &ref
= static_cast<AST::TuplePatternItemsRanged &> (pattern.get_items ());
items = lower_tuple_pattern_ranged (ref);
@@ -309,10 +323,27 @@ void
ASTLoweringPattern::visit (AST::SlicePattern &pattern)
{
std::vector<std::unique_ptr<HIR::Pattern>> items;
- for (auto &p : pattern.get_items ())
+
+ switch (pattern.get_items ().get_pattern_type ())
{
- HIR::Pattern *item = ASTLoweringPattern::translate (*p);
- items.push_back (std::unique_ptr<HIR::Pattern> (item));
+ case AST::SlicePatternItems::SlicePatternItemType::NO_REST:
+ {
+ AST::SlicePatternItemsNoRest &ref
+ = static_cast<AST::SlicePatternItemsNoRest &> (pattern.get_items ());
+ for (auto &p : ref.get_patterns ())
+ {
+ HIR::Pattern *item = ASTLoweringPattern::translate (*p);
+ items.push_back (std::unique_ptr<HIR::Pattern> (item));
+ }
+ }
+ break;
+ case AST::SlicePatternItems::SlicePatternItemType::HAS_REST:
+ {
+ rust_error_at (pattern.get_locus (),
+ "lowering of slice patterns with rest elements are not "
+ "supported yet");
+ }
+ break;
}
auto crate_num = mappings.get_current_crate ();
diff --git a/gcc/rust/hir/rust-ast-lower-type.cc b/gcc/rust/hir/rust-ast-lower-type.cc
index a678f18..1841576 100644
--- a/gcc/rust/hir/rust-ast-lower-type.cc
+++ b/gcc/rust/hir/rust-ast-lower-type.cc
@@ -209,10 +209,17 @@ ASTLowerQualifiedPathInType::visit (AST::QualifiedPathInType &path)
path.get_locus ());
}
+ASTLoweringType::ASTLoweringType (bool default_to_static_lifetime,
+ bool impl_trait_allowed)
+ : ASTLoweringBase (), default_to_static_lifetime (default_to_static_lifetime),
+ impl_trait_allowed (impl_trait_allowed), translated (nullptr)
+{}
+
HIR::Type *
-ASTLoweringType::translate (AST::Type &type, bool default_to_static_lifetime)
+ASTLoweringType::translate (AST::Type &type, bool default_to_static_lifetime,
+ bool impl_trait_allowed)
{
- ASTLoweringType resolver (default_to_static_lifetime);
+ ASTLoweringType resolver (default_to_static_lifetime, impl_trait_allowed);
type.accept_vis (resolver);
rust_assert (resolver.translated != nullptr);
@@ -260,7 +267,8 @@ ASTLoweringType::visit (AST::BareFunctionType &fntype)
HIR::Type *param_type
= ASTLoweringType::translate (param.get_type (),
- default_to_static_lifetime);
+ default_to_static_lifetime,
+ impl_trait_allowed);
HIR::MaybeNamedParam p (param.get_name (), kind,
std::unique_ptr<HIR::Type> (param_type),
@@ -272,7 +280,8 @@ ASTLoweringType::visit (AST::BareFunctionType &fntype)
if (fntype.has_return_type ())
{
return_type = ASTLoweringType::translate (fntype.get_return_type (),
- default_to_static_lifetime);
+ default_to_static_lifetime,
+ impl_trait_allowed);
}
auto crate_num = mappings.get_current_crate ();
@@ -292,8 +301,8 @@ ASTLoweringType::visit (AST::TupleType &tuple)
std::vector<std::unique_ptr<HIR::Type>> elems;
for (auto &e : tuple.get_elems ())
{
- HIR::Type *t
- = ASTLoweringType::translate (*e, default_to_static_lifetime);
+ HIR::Type *t = ASTLoweringType::translate (*e, default_to_static_lifetime,
+ impl_trait_allowed);
elems.push_back (std::unique_ptr<HIR::Type> (t));
}
@@ -323,7 +332,8 @@ ASTLoweringType::visit (AST::ArrayType &type)
{
HIR::Type *translated_type
= ASTLoweringType::translate (type.get_elem_type (),
- default_to_static_lifetime);
+ default_to_static_lifetime,
+ impl_trait_allowed);
HIR::Expr *array_size = ASTLoweringExpr::translate (type.get_size_expr ());
auto crate_num = mappings.get_current_crate ();
@@ -343,9 +353,9 @@ ASTLoweringType::visit (AST::ReferenceType &type)
HIR::Lifetime lifetime
= lower_lifetime (type.get_lifetime (), default_to_static_lifetime);
- HIR::Type *base_type
- = ASTLoweringType::translate (type.get_base_type (),
- default_to_static_lifetime);
+ HIR::Type *base_type = ASTLoweringType::translate (type.get_base_type (),
+ default_to_static_lifetime,
+ impl_trait_allowed);
auto crate_num = mappings.get_current_crate ();
Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
@@ -364,7 +374,8 @@ ASTLoweringType::visit (AST::RawPointerType &type)
{
HIR::Type *base_type
= ASTLoweringType::translate (type.get_type_pointed_to (),
- default_to_static_lifetime);
+ default_to_static_lifetime,
+ impl_trait_allowed);
auto crate_num = mappings.get_current_crate ();
Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
@@ -384,9 +395,9 @@ ASTLoweringType::visit (AST::RawPointerType &type)
void
ASTLoweringType::visit (AST::SliceType &type)
{
- HIR::Type *base_type
- = ASTLoweringType::translate (type.get_elem_type (),
- default_to_static_lifetime);
+ HIR::Type *base_type = ASTLoweringType::translate (type.get_elem_type (),
+ default_to_static_lifetime,
+ impl_trait_allowed);
auto crate_num = mappings.get_current_crate ();
Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
@@ -463,7 +474,8 @@ void
ASTLoweringType::visit (AST::ParenthesisedType &type)
{
auto *inner = ASTLoweringType::translate (*type.get_type_in_parens (),
- default_to_static_lifetime);
+ default_to_static_lifetime,
+ impl_trait_allowed);
auto crate_num = mappings.get_current_crate ();
Analysis::NodeMapping mapping (crate_num, type.get_node_id (),
@@ -480,6 +492,9 @@ ASTLoweringType::visit (AST::ParenthesisedType &type)
void
ASTLoweringType::visit (AST::ImplTraitType &type)
{
+ if (!impl_trait_allowed)
+ emit_impl_trait_error (type.get_locus ());
+
std::vector<std::unique_ptr<HIR::TypeParamBound>> bounds;
for (auto &bound : type.get_type_param_bounds ())
{
@@ -499,9 +514,12 @@ ASTLoweringType::visit (AST::ImplTraitType &type)
void
ASTLoweringType::visit (AST::ImplTraitTypeOneBound &type)
{
+ if (!impl_trait_allowed)
+ emit_impl_trait_error (type.get_locus ());
+
std::vector<std::unique_ptr<HIR::TypeParamBound>> bounds;
- auto b = ASTLoweringTypeBounds::translate (type.get_trait_bound ());
+ auto b = ASTLoweringTypeBounds::translate (*type.get_trait_bound ().get ());
bounds.push_back (std::unique_ptr<HIR::TypeParamBound> (b));
auto crate_num = mappings.get_current_crate ();
@@ -513,6 +531,15 @@ ASTLoweringType::visit (AST::ImplTraitTypeOneBound &type)
= new HIR::ImplTraitType (mapping, std::move (bounds), type.get_locus ());
}
+void
+ASTLoweringType::emit_impl_trait_error (location_t locus)
+{
+ rich_location r (line_table, locus);
+ rust_error_at (r, ErrorCode::E0562,
+ "%<impl Trait%> not allowed outside of function and inherent "
+ "method return types");
+}
+
HIR::GenericParam *
ASTLowerGenericParam::translate (AST::GenericParam &param)
{
@@ -593,7 +620,8 @@ ASTLowerGenericParam::visit (AST::TypeParam &param)
translated
= new HIR::TypeParam (mapping, param.get_type_representation (),
param.get_locus (), std::move (type_param_bounds),
- std::move (type), param.get_outer_attrs ());
+ std::move (type), param.get_outer_attrs (),
+ param.from_impl_trait ());
}
HIR::TypeParamBound *
diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h
index 4efaeee..50f543a 100644
--- a/gcc/rust/hir/rust-ast-lower-type.h
+++ b/gcc/rust/hir/rust-ast-lower-type.h
@@ -66,7 +66,8 @@ class ASTLoweringType : public ASTLoweringBase
public:
static HIR::Type *translate (AST::Type &type,
- bool default_to_static_lifetime = false);
+ bool default_to_static_lifetime = false,
+ bool impl_trait_allowed = false);
void visit (AST::BareFunctionType &fntype) override;
void visit (AST::TupleType &tuple) override;
@@ -81,19 +82,17 @@ public:
void visit (AST::TraitObjectTypeOneBound &type) override;
void visit (AST::TraitObjectType &type) override;
void visit (AST::ParenthesisedType &type) override;
-
void visit (AST::ImplTraitType &type) override;
void visit (AST::ImplTraitTypeOneBound &type) override;
+ void emit_impl_trait_error (location_t locus);
+
private:
- ASTLoweringType (bool default_to_static_lifetime)
- : ASTLoweringBase (),
- default_to_static_lifetime (default_to_static_lifetime),
- translated (nullptr)
- {}
+ ASTLoweringType (bool default_to_static_lifetime, bool impl_trait_allowed);
/** Used when compiling const and static items. */
bool default_to_static_lifetime;
+ bool impl_trait_allowed;
HIR::Type *translated;
};
diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc
index 76bd135..e6e327f 100644
--- a/gcc/rust/hir/rust-ast-lower.cc
+++ b/gcc/rust/hir/rust-ast-lower.cc
@@ -423,12 +423,6 @@ ASTLoweringExprWithBlock::visit (AST::WhileLoopExpr &expr)
}
void
-ASTLoweringExprWithBlock::visit (AST::ForLoopExpr &expr)
-{
- rust_unreachable ();
-}
-
-void
ASTLoweringExprWithBlock::visit (AST::MatchExpr &expr)
{
HIR::Expr *branch_value
diff --git a/gcc/rust/hir/rust-ast-lower.h b/gcc/rust/hir/rust-ast-lower.h
index cc74082..0787ddf 100644
--- a/gcc/rust/hir/rust-ast-lower.h
+++ b/gcc/rust/hir/rust-ast-lower.h
@@ -28,16 +28,14 @@ namespace HIR {
/* Checks whether the name of a field already exists. Returns true
and produces an error if so. */
-bool
-struct_field_name_exists (std::vector<HIR::StructField> &fields,
- HIR::StructField &new_field);
+bool struct_field_name_exists (std::vector<HIR::StructField> &fields,
+ HIR::StructField &new_field);
/**
* Lowers a Visibility from the AST into an HIR Visibility, desugaring it in
* the process
*/
-Visibility
-translate_visibility (const AST::Visibility &vis);
+Visibility translate_visibility (const AST::Visibility &vis);
/**
* Main base class used for lowering AST to HIR.
diff --git a/gcc/rust/hir/rust-hir-dump.cc b/gcc/rust/hir/rust-hir-dump.cc
index cb32f68..a0cdcb2 100644
--- a/gcc/rust/hir/rust-hir-dump.cc
+++ b/gcc/rust/hir/rust-hir-dump.cc
@@ -92,7 +92,7 @@ Dump::go (HIR::Crate &e)
end ("Crate");
}
-Dump::Dump (std::ostream &stream) : stream (stream) {}
+Dump::Dump (std::ostream &stream) : beg_of_line (false), stream (stream) {}
/**
* Writes TEXT with a final newline if ENDLINE is true.
@@ -1297,6 +1297,31 @@ Dump::visit (BlockExpr &e)
}
void
+Dump::visit (AnonConst &e)
+{
+ begin ("AnonConst");
+ do_expr (e);
+
+ if (e.is_deferred ())
+ put_field ("inner", "_");
+ else
+ visit_field ("inner", e.get_inner_expr ());
+
+ end ("AnonConst");
+}
+
+void
+Dump::visit (ConstBlock &e)
+{
+ begin ("ConstBlock");
+ do_expr (e);
+
+ visit_field ("inner", e.get_const_expr ());
+
+ end ("ConstBlock");
+}
+
+void
Dump::visit (ContinueExpr &e)
{
begin ("ContinueExpr");
@@ -1507,13 +1532,91 @@ Dump::visit (AsyncBlockExpr &e)
void
Dump::visit (InlineAsm &e)
-{}
+{
+ begin ("InlineAsm");
+ do_expr (e);
+ for (auto &temp : e.get_template_ ())
+ {
+ put_field ("template", temp.string);
+ }
+
+ for (auto &temp_str : e.get_template_strs ())
+ {
+ put_field ("template_str", temp_str.symbol);
+ }
+
+ for (auto &operand : e.get_operands ())
+ {
+ switch (operand.get_register_type ())
+ {
+ case HIR::InlineAsmOperand::RegisterType::In:
+ {
+ const auto &in = operand.get_in ();
+ visit_field ("in expr", *in.expr);
+ break;
+ }
+ case HIR::InlineAsmOperand::RegisterType::Out:
+ {
+ const auto &out = operand.get_out ();
+ visit_field ("out expr", *out.expr);
+ break;
+ }
+ case HIR::InlineAsmOperand::RegisterType::InOut:
+ {
+ const auto &inout = operand.get_in_out ();
+ visit_field ("inout expr", *inout.expr);
+ break;
+ }
+ case HIR::InlineAsmOperand::RegisterType::SplitInOut:
+ {
+ const auto &inout = operand.get_split_in_out ();
+ begin ("Split in out");
+ visit_field ("in expr", *inout.in_expr);
+ visit_field ("out expr", *inout.out_expr);
+ end ("Split in out");
+
+ break;
+ }
+ case HIR::InlineAsmOperand::RegisterType::Const:
+ {
+ auto &cnst = operand.get_const ();
+ visit_field ("const expr", cnst.anon_const.get_inner_expr ());
+ break;
+ }
+ case HIR::InlineAsmOperand::RegisterType::Sym:
+ {
+ auto &sym = operand.get_sym ();
+ visit_field ("sym expr", *sym.expr);
+ break;
+ }
+ case HIR::InlineAsmOperand::RegisterType::Label:
+ {
+ auto &label = operand.get_label ();
+ put_field ("label name", label.label_name);
+ do_expr (*label.expr);
+ break;
+ }
+ }
+ }
+ end ("InlineAsm");
+}
void
Dump::visit (LlvmInlineAsm &e)
{}
void
+Dump::visit (OffsetOf &e)
+{
+ begin ("OffsetOf");
+
+ put_field ("type", e.get_type ().as_string ());
+ put_field ("field", e.get_field ());
+
+ end ("OffsetOf");
+}
+
+void
Dump::visit (TypeParam &e)
{
begin ("TypeParam");
@@ -1602,7 +1705,8 @@ Dump::visit (UseTreeGlob &e)
case UseTreeGlob::PathType::GLOBAL:
glob = "::*";
break;
- case UseTreeGlob::PathType::PATH_PREFIXED: {
+ case UseTreeGlob::PathType::PATH_PREFIXED:
+ {
path = e.get_path ().as_string ();
glob = "::*";
break;
@@ -1630,7 +1734,8 @@ Dump::visit (UseTreeList &e)
case UseTreeList::PathType::GLOBAL:
path_type = "::*";
break;
- case UseTreeList::PathType::PATH_PREFIXED: {
+ case UseTreeList::PathType::PATH_PREFIXED:
+ {
path = e.get_path ().as_string ();
path_type = "::*";
break;
@@ -1902,7 +2007,8 @@ Dump::visit (ConstantItem &e)
do_vis_item (e);
put_field ("identifier", e.get_identifier ().as_string ());
visit_field ("type", e.get_type ());
- visit_field ("const_expr", e.get_expr ());
+ if (e.has_expr ())
+ visit_field ("const_expr", e.get_expr ());
end ("ConstantItem");
}
@@ -2091,10 +2197,10 @@ Dump::visit (IdentifierPattern &e)
put_field ("is_ref", std::to_string (e.get_is_ref ()));
put_field ("mut", std::to_string (e.is_mut ()));
- if (e.has_pattern_to_bind ())
- put_field ("to_bind", e.get_to_bind ().as_string ());
+ if (e.has_subpattern ())
+ visit_field ("subpattern", e.get_subpattern ());
else
- put_field ("to_bind", "none");
+ put_field ("subpattern", "none");
end ("IdentifierPattern");
}
@@ -2172,7 +2278,7 @@ Dump::visit (StructPatternFieldIdentPat &e)
auto oa = e.get_outer_attrs ();
do_outer_attrs (oa);
put_field ("ident", e.get_identifier ().as_string ());
- put_field ("ident_pattern", e.get_pattern ().as_string ());
+ visit_field ("ident_pattern", e.get_pattern ());
end ("StructPatternFieldIdentPat");
}
@@ -2290,7 +2396,7 @@ Dump::visit (LetStmt &e)
auto oa = e.get_outer_attrs ();
do_outer_attrs (oa);
- put_field ("variable_pattern", e.get_pattern ().as_string ());
+ visit_field ("variable_pattern", e.get_pattern ());
if (e.has_type ())
visit_field ("type", e.get_type ());
diff --git a/gcc/rust/hir/rust-hir-dump.h b/gcc/rust/hir/rust-hir-dump.h
index 45b1708..3e6ae30 100644
--- a/gcc/rust/hir/rust-hir-dump.h
+++ b/gcc/rust/hir/rust-hir-dump.h
@@ -146,6 +146,8 @@ private:
virtual void visit (FieldAccessExpr &) override;
virtual void visit (ClosureExpr &) override;
virtual void visit (BlockExpr &) override;
+ virtual void visit (AnonConst &) override;
+ virtual void visit (ConstBlock &) override;
virtual void visit (ContinueExpr &) override;
virtual void visit (BreakExpr &) override;
virtual void visit (RangeFromToExpr &) override;
@@ -167,6 +169,7 @@ private:
virtual void visit (AsyncBlockExpr &) override;
virtual void visit (InlineAsm &) override;
virtual void visit (LlvmInlineAsm &) override;
+ virtual void visit (OffsetOf &) override;
virtual void visit (TypeParam &) override;
virtual void visit (ConstGenericParam &) override;
@@ -252,7 +255,6 @@ private:
} // namespace Rust
// In the global namespace to make it easier to call from debugger
-void
-debug (Rust::HIR::FullVisitable &v);
+void debug (Rust::HIR::FullVisitable &v);
#endif // !RUST_HIR_DUMP_H
diff --git a/gcc/rust/hir/tree/rust-hir-expr-abstract.h b/gcc/rust/hir/tree/rust-hir-expr-abstract.h
index 5bc5d89..371daa8 100644
--- a/gcc/rust/hir/tree/rust-hir-expr-abstract.h
+++ b/gcc/rust/hir/tree/rust-hir-expr-abstract.h
@@ -43,7 +43,7 @@ public:
WITHOUT_BLOCK,
};
- enum ExprType
+ enum class ExprType
{
Lit,
Operator,
@@ -58,6 +58,8 @@ public:
FieldAccess,
Closure,
Block,
+ AnonConst,
+ ConstBlock,
Continue,
Break,
Range,
@@ -72,6 +74,7 @@ public:
Path,
InlineAsm,
LlvmInlineAsm,
+ OffsetOf,
};
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 266c79c..14786ad 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.cc
+++ b/gcc/rust/hir/tree/rust-hir-expr.cc
@@ -17,6 +17,8 @@
// <http://www.gnu.org/licenses/>.
#include "rust-hir-expr.h"
+#include "rust-hir-map.h"
+#include "optional.h"
#include "rust-operators.h"
#include "rust-hir-stmt.h"
@@ -790,6 +792,61 @@ BlockExpr::operator= (BlockExpr const &other)
return *this;
}
+AnonConst::AnonConst (Analysis::NodeMapping mappings,
+ std::unique_ptr<Expr> &&expr, location_t locus)
+ : ExprWithBlock (std::move (mappings), {}), locus (locus),
+ kind (Kind::Explicit), expr (std::move (expr))
+{
+ rust_assert (this->expr.value ());
+}
+
+AnonConst::AnonConst (Analysis::NodeMapping mappings, location_t locus)
+ : ExprWithBlock (std::move (mappings), {}), locus (locus),
+ kind (Kind::DeferredInference), expr (tl::nullopt)
+{}
+
+AnonConst::AnonConst (const AnonConst &other)
+ : ExprWithBlock (other), locus (other.locus), kind (other.kind)
+{
+ if (other.expr)
+ expr = other.expr.value ()->clone_expr ();
+}
+
+AnonConst
+AnonConst::operator= (const AnonConst &other)
+{
+ ExprWithBlock::operator= (other);
+
+ locus = other.locus;
+ kind = other.kind;
+
+ if (other.expr)
+ expr = other.expr.value ()->clone_expr ();
+
+ return *this;
+}
+
+ConstBlock::ConstBlock (Analysis::NodeMapping mappings, AnonConst &&expr,
+ location_t locus, AST::AttrVec outer_attrs)
+ : ExprWithBlock (std::move (mappings), std::move (outer_attrs)),
+ expr (std::move (expr)), locus (locus)
+{}
+
+ConstBlock::ConstBlock (const ConstBlock &other)
+ : ExprWithBlock (other), expr (other.expr), locus (other.locus)
+{}
+
+ConstBlock
+ConstBlock::operator= (const ConstBlock &other)
+{
+ ExprWithBlock::operator= (other);
+
+ expr = other.expr;
+ locus = other.locus;
+
+ return *this;
+}
+
ContinueExpr::ContinueExpr (Analysis::NodeMapping mappings, location_t locus,
tl::optional<Lifetime> label,
AST::AttrVec outer_attribs)
@@ -1277,59 +1334,42 @@ AsyncBlockExpr::operator= (AsyncBlockExpr const &other)
OperatorExprMeta::OperatorExprMeta (HIR::CompoundAssignmentExpr &expr)
: node_mappings (expr.get_mappings ()),
lvalue_mappings (expr.get_expr ().get_mappings ()),
- locus (expr.get_locus ())
+ rvalue_mappings (expr.get_rhs ().get_mappings ()), locus (expr.get_locus ())
{}
OperatorExprMeta::OperatorExprMeta (HIR::ArithmeticOrLogicalExpr &expr)
: node_mappings (expr.get_mappings ()),
lvalue_mappings (expr.get_expr ().get_mappings ()),
- locus (expr.get_locus ())
+ rvalue_mappings (expr.get_rhs ().get_mappings ()), locus (expr.get_locus ())
{}
OperatorExprMeta::OperatorExprMeta (HIR::NegationExpr &expr)
: node_mappings (expr.get_mappings ()),
lvalue_mappings (expr.get_expr ().get_mappings ()),
+ rvalue_mappings (Analysis::NodeMapping::get_error ()),
locus (expr.get_locus ())
{}
OperatorExprMeta::OperatorExprMeta (HIR::DereferenceExpr &expr)
: node_mappings (expr.get_mappings ()),
lvalue_mappings (expr.get_expr ().get_mappings ()),
+ rvalue_mappings (Analysis::NodeMapping::get_error ()),
locus (expr.get_locus ())
{}
OperatorExprMeta::OperatorExprMeta (HIR::ArrayIndexExpr &expr)
: node_mappings (expr.get_mappings ()),
lvalue_mappings (expr.get_array_expr ().get_mappings ()),
+ rvalue_mappings (expr.get_index_expr ().get_mappings ()),
locus (expr.get_locus ())
{}
OperatorExprMeta::OperatorExprMeta (HIR::ComparisonExpr &expr)
: node_mappings (expr.get_mappings ()),
lvalue_mappings (expr.get_expr ().get_mappings ()),
- locus (expr.get_locus ())
+ rvalue_mappings (expr.get_rhs ().get_mappings ()), locus (expr.get_locus ())
{}
-AnonConst::AnonConst (NodeId id, std::unique_ptr<Expr> expr)
- : id (id), expr (std::move (expr))
-{
- rust_assert (this->expr != nullptr);
-}
-
-AnonConst::AnonConst (const AnonConst &other)
-{
- id = other.id;
- expr = other.expr->clone_expr ();
-}
-
-AnonConst
-AnonConst::operator= (const AnonConst &other)
-{
- id = other.id;
- expr = other.expr->clone_expr ();
- return *this;
-}
-
InlineAsmOperand::In::In (
const tl::optional<struct AST::InlineAsmRegOrRegClass> &reg,
std::unique_ptr<Expr> expr)
@@ -1476,7 +1516,7 @@ InlineAsm::InlineAsm (location_t locus, bool is_global_asm,
std::vector<AST::TupleTemplateStr> template_strs,
std::vector<HIR::InlineAsmOperand> operands,
std::vector<AST::TupleClobber> clobber_abi,
- std::set<AST::InlineAsmOption> options,
+ std::set<AST::InlineAsm::Option> options,
Analysis::NodeMapping mappings,
AST::AttrVec outer_attribs)
: ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
@@ -1486,5 +1526,41 @@ InlineAsm::InlineAsm (location_t locus, bool is_global_asm,
clobber_abi (std::move (clobber_abi)), options (std::move (options))
{}
+OffsetOf &
+OffsetOf::operator= (const OffsetOf &other)
+{
+ ExprWithoutBlock::operator= (other);
+
+ type = other.type->clone_type ();
+ field = other.field;
+ loc = other.loc;
+
+ return *this;
+}
+
+ExprWithoutBlock *
+OffsetOf::clone_expr_without_block_impl () const
+{
+ return new OffsetOf (*this);
+}
+
+std::string
+OffsetOf::as_string () const
+{
+ return "OffsetOf(" + type->as_string () + ", " + field.as_string () + ")";
+}
+
+void
+OffsetOf::accept_vis (HIRExpressionVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
+OffsetOf::accept_vis (HIRFullVisitor &vis)
+{
+ vis.visit (*this);
+}
+
} // namespace HIR
} // namespace Rust
diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h
index 375f474..61e3590 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.h
+++ b/gcc/rust/hir/tree/rust-hir-expr.h
@@ -19,12 +19,15 @@
#ifndef RUST_HIR_EXPR_H
#define RUST_HIR_EXPR_H
+#include "rust-ast.h"
#include "rust-hir-expr-abstract.h"
#include "rust-hir-literal.h"
#include "rust-common.h"
#include "rust-hir-bound.h"
#include "rust-hir-attrs.h"
#include "rust-expr.h"
+#include "rust-hir-map.h"
+#include "rust-mapping-common.h"
namespace Rust {
namespace HIR {
@@ -1800,6 +1803,92 @@ protected:
}
};
+class AnonConst : public ExprWithBlock
+{
+public:
+ enum class Kind
+ {
+ Explicit,
+ DeferredInference
+ };
+
+ AnonConst (Analysis::NodeMapping mappings, std::unique_ptr<Expr> &&expr,
+ location_t locus = UNKNOWN_LOCATION);
+ AnonConst (Analysis::NodeMapping mappings,
+ location_t locus = UNKNOWN_LOCATION);
+ AnonConst (const AnonConst &other);
+ AnonConst operator= (const AnonConst &other);
+
+ std::string as_string () const override;
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ ExprType get_expression_type () const final override
+ {
+ return ExprType::AnonConst;
+ }
+
+ location_t get_locus () const override { return locus; }
+
+ Expr &get_inner_expr ()
+ {
+ rust_assert (kind == Kind::Explicit);
+ return *expr.value ();
+ }
+
+ const Expr &get_inner_expr () const
+ {
+ rust_assert (kind == Kind::Explicit);
+ return *expr.value ();
+ }
+
+ bool is_deferred () const { return kind == Kind::DeferredInference; }
+
+private:
+ location_t locus;
+ Kind kind;
+ tl::optional<std::unique_ptr<Expr>> expr;
+
+ AnonConst *clone_expr_with_block_impl () const override
+ {
+ return new AnonConst (*this);
+ }
+};
+
+class ConstBlock : public ExprWithBlock
+{
+public:
+ ConstBlock (Analysis::NodeMapping mappings, AnonConst &&expr,
+ location_t locus = UNKNOWN_LOCATION,
+ AST::AttrVec outer_attrs = {});
+ ConstBlock (const ConstBlock &other);
+ ConstBlock operator= (const ConstBlock &other);
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ std::string as_string () const override;
+
+ ExprType get_expression_type () const final override
+ {
+ return ExprType::ConstBlock;
+ }
+
+ location_t get_locus () const override { return locus; }
+ AnonConst &get_const_expr () { return expr; }
+ const AnonConst &get_const_expr () const { return expr; }
+
+private:
+ AnonConst expr;
+ location_t locus;
+
+ ConstBlock *clone_expr_with_block_impl () const override
+ {
+ return new ConstBlock (*this);
+ }
+};
+
// HIR node representing continue expression within loops
class ContinueExpr : public ExprWithoutBlock
{
@@ -2631,6 +2720,8 @@ public:
Expr &get_guard_expr () { return *guard_expr; }
location_t get_locus () const { return locus; }
+
+ AST::AttrVec &get_outer_attrs () { return outer_attrs; }
};
/* A "match case" - a correlated match arm and resulting expression. Not
@@ -2823,6 +2914,22 @@ public:
OperatorExprMeta (HIR::ComparisonExpr &expr);
+ OperatorExprMeta (const OperatorExprMeta &other)
+ : node_mappings (other.node_mappings),
+ lvalue_mappings (other.lvalue_mappings),
+ rvalue_mappings (other.rvalue_mappings), locus (other.locus)
+ {}
+
+ OperatorExprMeta &operator= (const OperatorExprMeta &other)
+ {
+ node_mappings = other.node_mappings;
+ lvalue_mappings = other.lvalue_mappings;
+ rvalue_mappings = other.rvalue_mappings;
+ locus = other.locus;
+
+ return *this;
+ }
+
const Analysis::NodeMapping &get_mappings () const { return node_mappings; }
const Analysis::NodeMapping &get_lvalue_mappings () const
@@ -2830,11 +2937,22 @@ public:
return lvalue_mappings;
}
+ const Analysis::NodeMapping &get_rvalue_mappings () const
+ {
+ return rvalue_mappings;
+ }
+
+ bool has_rvalue_mappings () const
+ {
+ return rvalue_mappings.get_hirid () != UNKNOWN_HIRID;
+ }
+
location_t get_locus () const { return locus; }
private:
- const Analysis::NodeMapping node_mappings;
- const Analysis::NodeMapping lvalue_mappings;
+ Analysis::NodeMapping node_mappings;
+ Analysis::NodeMapping lvalue_mappings;
+ Analysis::NodeMapping rvalue_mappings;
location_t locus;
};
@@ -2892,18 +3010,6 @@ class InlineAsmRegClass
std::string placeholder;
};
-struct AnonConst
-{
- NodeId id;
- std::unique_ptr<Expr> expr;
-
- AnonConst (NodeId id, std::unique_ptr<Expr> expr);
-
- AnonConst (const AnonConst &other);
-
- AnonConst operator= (const AnonConst &other);
-};
-
class InlineAsmOperand
{
public:
@@ -2992,8 +3098,9 @@ public:
Label operator= (const struct Label &other);
};
-private:
using RegisterType = AST::InlineAsmOperand::RegisterType;
+
+private:
AST::InlineAsmOperand::RegisterType register_type;
tl::optional<struct In> in;
@@ -3037,13 +3144,24 @@ public:
RegisterType get_register_type () const { return register_type; }
// Potentially unsafe without get_register_type() check
- struct In get_in () const { return in.value (); }
- struct Out get_out () const { return out.value (); }
- struct InOut get_in_out () const { return in_out.value (); }
- struct SplitInOut get_split_in_out () const { return split_in_out.value (); }
- struct Const get_const () const { return cnst.value (); }
- struct Sym get_sym () const { return sym.value (); }
- struct Label get_label () const { return label.value (); }
+ const struct In &get_in () const { return in.value (); }
+ const struct Out &get_out () const { return out.value (); }
+ const struct InOut &get_in_out () const { return in_out.value (); }
+ const struct SplitInOut &get_split_in_out () const
+ {
+ return split_in_out.value ();
+ }
+ const struct Const &get_const () const { return cnst.value (); }
+ const struct Sym &get_sym () const { return sym.value (); }
+ const struct Label &get_label () const { return label.value (); }
+
+ struct In &get_in () { return in.value (); }
+ struct Out &get_out () { return out.value (); }
+ struct InOut &get_in_out () { return in_out.value (); }
+ struct SplitInOut &get_split_in_out () { return split_in_out.value (); }
+ struct Const &get_const () { return cnst.value (); }
+ struct Sym &get_sym () { return sym.value (); }
+ struct Label &get_label () { return label.value (); }
};
// Inline Assembly Node
@@ -3059,7 +3177,7 @@ public:
std::vector<AST::TupleTemplateStr> template_strs;
std::vector<HIR::InlineAsmOperand> operands;
std::vector<AST::TupleClobber> clobber_abi;
- std::set<AST::InlineAsmOption> options;
+ std::set<AST::InlineAsm::Option> options;
std::vector<location_t> line_spans;
@@ -3090,11 +3208,11 @@ public:
return template_strs;
}
- std::vector<HIR::InlineAsmOperand> get_operands () { return operands; }
+ std::vector<HIR::InlineAsmOperand> &get_operands () { return operands; }
std::vector<AST::TupleClobber> get_clobber_abi () { return clobber_abi; }
- std::set<AST::InlineAsmOption> get_options () { return options; }
+ std::set<AST::InlineAsm::Option> get_options () { return options; }
bool is_simple_asm ()
{
@@ -3113,11 +3231,47 @@ public:
std::vector<AST::TupleTemplateStr> template_strs,
std::vector<HIR::InlineAsmOperand> operands,
std::vector<AST::TupleClobber> clobber_abi,
- std::set<AST::InlineAsmOption> options,
+ std::set<AST::InlineAsm::Option> options,
Analysis::NodeMapping mappings,
AST::AttrVec outer_attribs = AST::AttrVec ());
};
+class OffsetOf : public ExprWithoutBlock
+{
+public:
+ OffsetOf (std::unique_ptr<Type> &&type, Identifier field,
+ Analysis::NodeMapping mappings, location_t loc)
+ : ExprWithoutBlock (mappings), type (std::move (type)), field (field),
+ loc (loc)
+ {}
+
+ OffsetOf (const OffsetOf &other)
+ : ExprWithoutBlock (other), type (other.type->clone_type ()),
+ field (other.field), loc (other.loc)
+ {}
+
+ OffsetOf &operator= (const OffsetOf &other);
+
+ ExprWithoutBlock *clone_expr_without_block_impl () const override;
+ std::string as_string () const override;
+
+ void accept_vis (HIRExpressionVisitor &vis) override;
+ void accept_vis (HIRFullVisitor &vis) override;
+
+ ExprType get_expression_type () const override { return ExprType::OffsetOf; }
+
+ location_t get_locus () const override { return loc; }
+
+ Type &get_type () { return *type; }
+ const Type &get_type () const { return *type; }
+ const Identifier &get_field () const { return field; }
+
+private:
+ std::unique_ptr<Type> type;
+ Identifier field;
+ location_t loc;
+};
+
struct LlvmOperand
{
std::string constraint;
diff --git a/gcc/rust/hir/tree/rust-hir-full-decls.h b/gcc/rust/hir/tree/rust-hir-full-decls.h
index 1e313ec..57b3a4d 100644
--- a/gcc/rust/hir/tree/rust-hir-full-decls.h
+++ b/gcc/rust/hir/tree/rust-hir-full-decls.h
@@ -95,6 +95,8 @@ class FieldAccessExpr;
struct ClosureParam;
class ClosureExpr;
class BlockExpr;
+class AnonConst;
+class ConstBlock;
class ContinueExpr;
class BreakExpr;
class RangeExpr;
@@ -123,10 +125,10 @@ class AwaitExpr;
class AsyncBlockExpr;
class InlineAsmReg;
class InlineAsmRegClass;
-struct AnonConst;
class InlineAsmOperand;
class InlineAsm;
class LlvmInlineAsm;
+class OffsetOf;
// 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 960de56..340b5c6 100644
--- a/gcc/rust/hir/tree/rust-hir-generic-param.h
+++ b/gcc/rust/hir/tree/rust-hir-generic-param.h
@@ -150,7 +150,7 @@ public:
location_t get_locus () const override final { return locus; };
- bool has_default_expression () { return default_expression != nullptr; }
+ bool has_default_expression () const { return default_expression != nullptr; }
std::string get_name () { return name; }
Type &get_type ()
@@ -160,6 +160,8 @@ public:
}
Expr &get_default_expression () { return *default_expression; }
+ const Expr &get_default_expression () const { return *default_expression; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
diff --git a/gcc/rust/hir/tree/rust-hir-item.cc b/gcc/rust/hir/tree/rust-hir-item.cc
index 160f710..1406e7a 100644
--- a/gcc/rust/hir/tree/rust-hir-item.cc
+++ b/gcc/rust/hir/tree/rust-hir-item.cc
@@ -26,16 +26,18 @@ TypeParam::TypeParam (
Analysis::NodeMapping mappings, Identifier type_representation,
location_t locus,
std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
- tl::optional<std::unique_ptr<Type>> type, AST::AttrVec outer_attrs)
+ tl::optional<std::unique_ptr<Type>> type, AST::AttrVec outer_attrs,
+ bool was_impl_trait)
: GenericParam (mappings), outer_attrs (std::move (outer_attrs)),
type_representation (std::move (type_representation)),
type_param_bounds (std::move (type_param_bounds)), type (std::move (type)),
- locus (locus)
+ locus (locus), was_impl_trait (was_impl_trait)
{}
TypeParam::TypeParam (TypeParam const &other)
: GenericParam (other.mappings), outer_attrs (other.outer_attrs),
- type_representation (other.type_representation), locus (other.locus)
+ type_representation (other.type_representation), locus (other.locus),
+ was_impl_trait (other.was_impl_trait)
{
// guard to prevent null pointer dereference
if (other.has_type ())
@@ -55,6 +57,7 @@ TypeParam::operator= (TypeParam const &other)
outer_attrs = other.outer_attrs;
locus = other.locus;
mappings = other.mappings;
+ was_impl_trait = other.was_impl_trait;
// guard to prevent null pointer dereference
if (other.has_type ())
diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h
index 37f599c..d9df602 100644
--- a/gcc/rust/hir/tree/rust-hir-item.h
+++ b/gcc/rust/hir/tree/rust-hir-item.h
@@ -95,17 +95,11 @@ protected:
class TypeParam : public GenericParam
{
AST::AttrVec outer_attrs;
-
Identifier type_representation;
-
- // bool has_type_param_bounds;
- // TypeParamBounds type_param_bounds;
- std::vector<std::unique_ptr<TypeParamBound>>
- type_param_bounds; // inlined form
-
+ std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds;
tl::optional<std::unique_ptr<Type>> type;
-
location_t locus;
+ bool was_impl_trait;
public:
// Returns whether the type of the type param has been specified.
@@ -121,9 +115,9 @@ public:
TypeParam (Analysis::NodeMapping mappings, Identifier type_representation,
location_t locus = UNDEF_LOCATION,
std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds
- = std::vector<std::unique_ptr<TypeParamBound>> (),
+ = {},
tl::optional<std::unique_ptr<Type>> type = tl::nullopt,
- AST::AttrVec outer_attrs = std::vector<AST::Attribute> ());
+ AST::AttrVec outer_attrs = {}, bool was_impl_trait = false);
// Copy constructor uses clone
TypeParam (TypeParam const &other);
@@ -154,6 +148,8 @@ public:
std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ();
+ bool from_impl_trait () const { return was_impl_trait; }
+
protected:
// Clone function implementation as (not pure) virtual method
TypeParam *clone_generic_param_impl () const override
@@ -213,6 +209,8 @@ public:
std::string as_string () const override;
+ location_t get_locus () const { return locus; }
+
void accept_vis (HIRFullVisitor &vis) override;
Lifetime &get_lifetime () { return lifetime; }
@@ -406,6 +404,8 @@ public:
const Lifetime &get_lifetime () const { return lifetime.value (); }
+ Lifetime &get_lifetime () { return lifetime.value (); }
+
std::string as_string () const;
location_t get_locus () const { return locus; }
@@ -1801,6 +1801,8 @@ public:
return *type;
}
+ bool has_expr () const { return const_expr != nullptr; }
+
Expr &get_expr () { return *const_expr; }
Identifier get_identifier () const { return identifier; }
diff --git a/gcc/rust/hir/tree/rust-hir-path.h b/gcc/rust/hir/tree/rust-hir-path.h
index 3ce2662..4f296d8 100644
--- a/gcc/rust/hir/tree/rust-hir-path.h
+++ b/gcc/rust/hir/tree/rust-hir-path.h
@@ -41,11 +41,15 @@ public:
: segment_name (std::move (segment_name))
{}
- /* TODO: insert check in constructor for this? Or is this a semantic error
- * best handled then? */
+ PathIdentSegment (const PathIdentSegment &other)
+ : segment_name (other.segment_name)
+ {}
- /* TODO: does this require visitor? pretty sure this isn't polymorphic, but
- * not entirely sure */
+ PathIdentSegment &operator= (PathIdentSegment const &other)
+ {
+ segment_name = other.segment_name;
+ return *this;
+ }
// Creates an error PathIdentSegment.
static PathIdentSegment create_error () { return PathIdentSegment (""); }
@@ -128,6 +132,8 @@ public:
std::unique_ptr<Expr> &get_expression () { return expression; }
+ location_t get_locus () const { return locus; }
+
private:
std::unique_ptr<Expr> expression;
location_t locus;
@@ -146,7 +152,7 @@ public:
bool has_generic_args () const
{
return !(lifetime_args.empty () && type_args.empty ()
- && binding_args.empty ());
+ && binding_args.empty () && const_args.empty ());
}
GenericArgs (std::vector<Lifetime> lifetime_args,
diff --git a/gcc/rust/hir/tree/rust-hir-pattern.h b/gcc/rust/hir/tree/rust-hir-pattern.h
index 5cc5c95..9c636ca 100644
--- a/gcc/rust/hir/tree/rust-hir-pattern.h
+++ b/gcc/rust/hir/tree/rust-hir-pattern.h
@@ -80,7 +80,7 @@ class IdentifierPattern : public Pattern
Identifier variable_ident;
bool is_ref;
Mutability mut;
- std::unique_ptr<Pattern> to_bind;
+ std::unique_ptr<Pattern> subpattern;
location_t locus;
Analysis::NodeMapping mappings;
@@ -88,15 +88,15 @@ public:
std::string as_string () const override;
// Returns whether the IdentifierPattern has a pattern to bind.
- bool has_pattern_to_bind () const { return to_bind != nullptr; }
+ bool has_subpattern () const { return subpattern != nullptr; }
// Constructor
IdentifierPattern (Analysis::NodeMapping mappings, Identifier ident,
location_t locus, bool is_ref = false,
Mutability mut = Mutability::Imm,
- std::unique_ptr<Pattern> to_bind = nullptr)
+ std::unique_ptr<Pattern> subpattern = nullptr)
: variable_ident (std::move (ident)), is_ref (is_ref), mut (mut),
- to_bind (std::move (to_bind)), locus (locus), mappings (mappings)
+ subpattern (std::move (subpattern)), locus (locus), mappings (mappings)
{}
// Copy constructor with clone
@@ -105,8 +105,8 @@ public:
mut (other.mut), locus (other.locus), mappings (other.mappings)
{
// fix to get prevent null pointer dereference
- if (other.to_bind != nullptr)
- to_bind = other.to_bind->clone_pattern ();
+ if (other.subpattern != nullptr)
+ subpattern = other.subpattern->clone_pattern ();
}
// Overload assignment operator to use clone
@@ -119,8 +119,8 @@ public:
mappings = other.mappings;
// fix to get prevent null pointer dereference
- if (other.to_bind != nullptr)
- to_bind = other.to_bind->clone_pattern ();
+ if (other.subpattern != nullptr)
+ subpattern = other.subpattern->clone_pattern ();
return *this;
}
@@ -133,7 +133,7 @@ public:
bool is_mut () const { return mut == Mutability::Mut; }
bool get_is_ref () const { return is_ref; }
- Pattern &get_to_bind () { return *to_bind; }
+ Pattern &get_subpattern () { return *subpattern; }
void accept_vis (HIRFullVisitor &vis) override;
void accept_vis (HIRPatternVisitor &vis) override;
diff --git a/gcc/rust/hir/tree/rust-hir-visibility.h b/gcc/rust/hir/tree/rust-hir-visibility.h
index a750d88..9dd6ff2 100644
--- a/gcc/rust/hir/tree/rust-hir-visibility.h
+++ b/gcc/rust/hir/tree/rust-hir-visibility.h
@@ -73,6 +73,8 @@ public:
}
std::string as_string () const;
+
+ location_t get_locus () const { return locus; }
};
} // namespace HIR
} // namespace Rust
diff --git a/gcc/rust/hir/tree/rust-hir-visitor.cc b/gcc/rust/hir/tree/rust-hir-visitor.cc
new file mode 100644
index 0000000..58c1e1a
--- /dev/null
+++ b/gcc/rust/hir/tree/rust-hir-visitor.cc
@@ -0,0 +1,1187 @@
+// Copyright (C) 2021-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-expr.h"
+#include "rust-hir-full-decls.h"
+#include "rust-hir-visitor.h"
+#include "rust-hir-full.h"
+#include "rust-system.h"
+
+namespace Rust {
+namespace HIR {
+
+void
+DefaultHIRVisitor::walk (Lifetime &)
+{}
+
+void
+DefaultHIRVisitor::walk (LifetimeParam &lifetime_param)
+{
+ visit_outer_attrs (lifetime_param);
+ lifetime_param.get_lifetime ().accept_vis (*this);
+ for (Lifetime &lifetime_bound : lifetime_param.get_lifetime_bounds ())
+ lifetime_bound.accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::visit_generic_args (GenericArgs &generic_args)
+{
+ for (auto &lifetime : generic_args.get_lifetime_args ())
+ lifetime.accept_vis (*this);
+ for (auto &type : generic_args.get_type_args ())
+ type->accept_vis (*this);
+ for (auto &binding : generic_args.get_binding_args ())
+ binding.get_type ().accept_vis (*this);
+ for (auto &const_arg : generic_args.get_const_args ())
+ const_arg.get_expression ()->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (PathInExpression &path_in_expr)
+{
+ visit_outer_attrs (path_in_expr);
+ if (!path_in_expr.is_lang_item ())
+ for (auto &segment : path_in_expr.get_segments ())
+ visit_path_expr_segment (segment);
+}
+
+void
+DefaultHIRVisitor::walk (TypePathSegment &)
+{}
+
+void
+DefaultHIRVisitor::walk (TypePathSegmentFunction &segment_function)
+{
+ TypePathFunction &function_path = segment_function.get_function_path ();
+ if (function_path.has_inputs ())
+ for (auto &param : function_path.get_params ())
+ param->accept_vis (*this);
+ if (function_path.has_return_type ())
+ function_path.get_return_type ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TypePathSegmentGeneric &segment_generic)
+{
+ if (segment_generic.has_generic_args ())
+ visit_generic_args (segment_generic.get_generic_args ());
+}
+
+void
+DefaultHIRVisitor::walk (TypePath &type_path)
+{
+ for (auto &segment : type_path.get_segments ())
+ segment->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::visit_qualified_path_type (QualifiedPathType &path)
+{
+ path.get_type ().accept_vis (*this);
+ if (path.has_as_clause ())
+ path.get_trait ().accept_vis (*this);
+}
+
+// TODO: Implement visit_path_expr_segment
+void
+DefaultHIRVisitor::visit_path_expr_segment (PathExprSegment &segment)
+{
+ if (segment.has_generic_args ())
+ visit_generic_args (segment.get_generic_args ());
+}
+
+void
+DefaultHIRVisitor::walk (QualifiedPathInExpression &path_in_expr)
+{
+ visit_outer_attrs (path_in_expr);
+ visit_qualified_path_type (path_in_expr.get_path_type ());
+ for (auto &segment : path_in_expr.get_segments ())
+ visit_path_expr_segment (segment);
+}
+
+void
+DefaultHIRVisitor::walk (QualifiedPathInType &path_in_type)
+{
+ visit_qualified_path_type (path_in_type.get_path_type ());
+ path_in_type.get_associated_segment ().accept_vis (*this);
+ for (auto &segment : path_in_type.get_segments ())
+ segment->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (LiteralExpr &expr)
+{
+ visit_outer_attrs (expr);
+}
+
+void
+DefaultHIRVisitor::walk (BorrowExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (DereferenceExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ErrorPropagationExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (NegationExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ArithmeticOrLogicalExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_lhs ().accept_vis (*this);
+ expr.get_rhs ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ComparisonExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_lhs ().accept_vis (*this);
+ expr.get_rhs ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (LazyBooleanExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_lhs ().accept_vis (*this);
+ expr.get_rhs ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TypeCastExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_expr ().accept_vis (*this);
+ expr.get_type_to_convert_to ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (AssignmentExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_lhs ().accept_vis (*this);
+ expr.get_rhs ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (CompoundAssignmentExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_lhs ().accept_vis (*this);
+ expr.get_rhs ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (GroupedExpr &expr)
+{
+ visit_outer_attrs (expr);
+ visit_inner_attrs (expr);
+ expr.get_expr_in_parens ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ArrayElemsValues &elems)
+{
+ for (auto &elem : elems.get_values ())
+ elem->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ArrayElemsCopied &elems)
+{
+ elems.get_elem_to_copy ().accept_vis (*this);
+ elems.get_num_copies_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ArrayExpr &expr)
+{
+ visit_outer_attrs (expr);
+ visit_inner_attrs (expr);
+ expr.get_internal_elements ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ArrayIndexExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_array_expr ().accept_vis (*this);
+ expr.get_index_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TupleExpr &expr)
+{
+ visit_outer_attrs (expr);
+ visit_inner_attrs (expr);
+ for (auto &elem : expr.get_tuple_elems ())
+ elem->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TupleIndexExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_tuple_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (StructExprStruct &expr)
+{
+ visit_outer_attrs (expr);
+ visit_inner_attrs (expr);
+ expr.get_struct_name ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (StructExprFieldIdentifier &)
+{}
+
+void
+DefaultHIRVisitor::walk (StructExprFieldIdentifierValue &field)
+{
+ field.get_value ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (StructExprFieldIndexValue &field)
+{
+ field.get_value ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (StructExprStructFields &expr)
+{
+ visit_outer_attrs (expr);
+ visit_inner_attrs (expr);
+ expr.get_struct_name ().accept_vis (*this);
+ if (expr.has_struct_base ())
+ {
+ StructBase &base = expr.get_struct_base ();
+ base.get_base ().accept_vis (*this);
+ }
+ for (auto &field : expr.get_fields ())
+ field->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (StructExprStructBase &expr)
+{
+ visit_outer_attrs (expr);
+ visit_inner_attrs (expr);
+ expr.get_struct_name ().accept_vis (*this);
+ StructBase &base = expr.get_struct_base ();
+ base.get_base ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (CallExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_fnexpr ().accept_vis (*this);
+ for (auto &arg : expr.get_arguments ())
+ arg->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (MethodCallExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_receiver ().accept_vis (*this);
+ visit_path_expr_segment (expr.get_method_name ());
+ for (auto &arg : expr.get_arguments ())
+ arg->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (FieldAccessExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_receiver_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::visit_closure_param (ClosureParam &param)
+{
+ visit_outer_attrs (param);
+ param.get_pattern ().accept_vis (*this);
+ if (param.has_type_given ())
+ {
+ param.get_type ().accept_vis (*this);
+ }
+}
+
+void
+DefaultHIRVisitor::walk (ClosureExpr &expr)
+{
+ visit_outer_attrs (expr);
+ for (auto &param : expr.get_params ())
+ visit_closure_param (param);
+ if (expr.has_return_type ())
+ expr.get_return_type ().accept_vis (*this);
+ expr.get_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (BlockExpr &expr)
+{
+ visit_outer_attrs (expr);
+ visit_inner_attrs (expr);
+ for (auto &stmt : expr.get_statements ())
+ stmt->accept_vis (*this);
+ if (expr.has_expr ())
+ expr.get_final_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (AnonConst &expr)
+{
+ if (!expr.is_deferred ())
+ expr.get_inner_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ConstBlock &expr)
+{
+ expr.get_const_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ContinueExpr &expr)
+{
+ visit_outer_attrs (expr);
+ if (expr.has_label ())
+ expr.get_label ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (BreakExpr &expr)
+{
+ visit_outer_attrs (expr);
+ if (expr.has_label ())
+ expr.get_label ().accept_vis (*this);
+
+ if (expr.has_break_expr ())
+ expr.get_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (RangeFromToExpr &expr)
+{
+ expr.get_from_expr ().accept_vis (*this);
+ expr.get_to_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (RangeFromExpr &expr)
+{
+ expr.get_from_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (RangeToExpr &expr)
+{
+ expr.get_to_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (RangeFullExpr &)
+{}
+
+void
+DefaultHIRVisitor::walk (RangeFromToInclExpr &expr)
+{
+ expr.get_from_expr ().accept_vis (*this);
+ expr.get_to_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (RangeToInclExpr &expr)
+{
+ expr.get_to_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ReturnExpr &expr)
+{
+ visit_outer_attrs (expr);
+ if (expr.has_return_expr ())
+ expr.get_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (UnsafeBlockExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_block_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::visit_loop_label (LoopLabel &label)
+{
+ label.get_lifetime ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (LoopExpr &expr)
+{
+ visit_outer_attrs (expr);
+ if (expr.has_loop_label ())
+ visit_loop_label (expr.get_loop_label ());
+ expr.get_loop_block ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (WhileLoopExpr &expr)
+{
+ visit_outer_attrs (expr);
+ if (expr.has_loop_label ())
+ visit_loop_label (expr.get_loop_label ());
+ expr.get_predicate_expr ().accept_vis (*this);
+ expr.get_loop_block ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (WhileLetLoopExpr &expr)
+{
+ visit_outer_attrs (expr);
+ for (auto &pattern : expr.get_patterns ())
+ pattern->accept_vis (*this);
+ if (expr.has_loop_label ())
+ visit_loop_label (expr.get_loop_label ());
+ expr.get_cond ().accept_vis (*this);
+ expr.get_loop_block ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (IfExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_if_condition ().accept_vis (*this);
+ expr.get_if_block ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (IfExprConseqElse &expr)
+{
+ expr.IfExpr::accept_vis (*this);
+ expr.get_else_block ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::visit_match_arm (MatchArm &arm)
+{
+ // visit_outer_attrs (arm);
+ for (auto &pattern : arm.get_patterns ())
+ pattern->accept_vis (*this);
+ if (arm.has_match_arm_guard ())
+ arm.get_guard_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::visit_match_case (MatchCase &arm)
+{
+ visit_match_arm (arm.get_arm ());
+ arm.get_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (MatchExpr &expr)
+{
+ visit_outer_attrs (expr);
+ visit_inner_attrs (expr);
+ expr.get_scrutinee_expr ().accept_vis (*this);
+ for (auto &arm : expr.get_match_cases ())
+ visit_match_case (arm);
+}
+
+void
+DefaultHIRVisitor::walk (AwaitExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_awaited_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (AsyncBlockExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_block_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (InlineAsm &expr)
+{
+ visit_outer_attrs (expr);
+ auto &operands = expr.get_operands ();
+ using RegisterType = AST::InlineAsmOperand::RegisterType;
+ for (auto &operand : operands)
+ {
+ switch (operand.get_register_type ())
+ {
+ case RegisterType::In:
+ {
+ operand.get_in ().expr->accept_vis (*this);
+ break;
+ }
+ case RegisterType::Out:
+ {
+ operand.get_out ().expr->accept_vis (*this);
+ break;
+ }
+ case RegisterType::InOut:
+ {
+ operand.get_in_out ().expr->accept_vis (*this);
+ break;
+ }
+ case RegisterType::SplitInOut:
+ {
+ operand.get_split_in_out ().in_expr->accept_vis (*this);
+ operand.get_split_in_out ().out_expr->accept_vis (*this);
+ break;
+ }
+ case RegisterType::Const:
+ {
+ operand.get_const ().anon_const.get_inner_expr ().accept_vis (
+ *this);
+ break;
+ }
+ case RegisterType::Sym:
+ {
+ operand.get_sym ().expr->accept_vis (*this);
+ break;
+ }
+ case RegisterType::Label:
+ {
+ operand.get_label ().expr->accept_vis (*this);
+ break;
+ }
+ }
+ }
+}
+
+void
+DefaultHIRVisitor::walk (LlvmInlineAsm &expr)
+{
+ for (auto &output : expr.outputs)
+ output.expr->accept_vis (*this);
+ for (auto &input : expr.inputs)
+ input.expr->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (OffsetOf &expr)
+{
+ expr.get_type ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TypeParam &param)
+{
+ visit_outer_attrs (param);
+ for (auto &bounds : param.get_type_param_bounds ())
+ bounds->accept_vis (*this);
+ if (param.has_type ())
+ param.get_type ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ConstGenericParam &const_param)
+{
+ visit_outer_attrs (const_param);
+ const_param.get_type ().accept_vis (*this);
+ if (const_param.has_default_expression ())
+ const_param.get_default_expression ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (LifetimeWhereClauseItem &item)
+{
+ item.get_lifetime ().accept_vis (*this);
+ for (auto &bound : item.get_lifetime_bounds ())
+ bound.accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TypeBoundWhereClauseItem &item)
+{
+ for (auto &lifetime : item.get_for_lifetimes ())
+ lifetime.accept_vis (*this);
+ item.get_bound_type ().accept_vis (*this);
+ for (auto &param : item.get_type_param_bounds ())
+ param->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (Module &module)
+{
+ visit_outer_attrs (module);
+ visit_inner_attrs (module);
+ for (auto &item : module.get_items ())
+ item->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ExternCrate &crate)
+{
+ visit_outer_attrs (crate);
+}
+
+void
+DefaultHIRVisitor::walk (UseTreeGlob &)
+{}
+
+void
+DefaultHIRVisitor::walk (UseTreeList &)
+{}
+
+void
+DefaultHIRVisitor::walk (UseTreeRebind &)
+{}
+
+void
+DefaultHIRVisitor::walk (UseDeclaration &)
+{}
+
+void
+DefaultHIRVisitor::visit_function_param (FunctionParam &param)
+{
+ param.get_param_name ().accept_vis (*this);
+ param.get_type ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (Function &function)
+{
+ visit_outer_attrs (function);
+ for (auto &generic : function.get_generic_params ())
+ generic->accept_vis (*this);
+ for (auto &param : function.get_function_params ())
+ visit_function_param (param);
+ if (function.has_return_type ())
+ function.get_return_type ().accept_vis (*this);
+ if (function.has_where_clause ())
+ visit_where_clause (function.get_where_clause ());
+ function.get_definition ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TypeAlias &type_alias)
+{
+ visit_outer_attrs (type_alias);
+ for (auto &generic : type_alias.get_generic_params ())
+ generic->accept_vis (*this);
+ if (type_alias.has_where_clause ())
+ visit_where_clause (type_alias.get_where_clause ());
+ type_alias.get_type_aliased ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::visit_struct_field (StructField &field)
+{
+ field.get_field_type ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (StructStruct &struct_item)
+{
+ visit_outer_attrs (struct_item);
+ for (auto &generic : struct_item.get_generic_params ())
+ generic->accept_vis (*this);
+ if (struct_item.has_where_clause ())
+ visit_where_clause (struct_item.get_where_clause ());
+ for (auto &field : struct_item.get_fields ())
+ visit_struct_field (field);
+}
+
+void
+DefaultHIRVisitor::walk (TupleStruct &tuple_struct)
+{
+ visit_outer_attrs (tuple_struct);
+ for (auto &generic : tuple_struct.get_generic_params ())
+ generic->accept_vis (*this);
+ if (tuple_struct.has_where_clause ())
+ visit_where_clause (tuple_struct.get_where_clause ());
+ for (auto &field : tuple_struct.get_fields ())
+ field.get_field_type ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (EnumItem &item)
+{
+ visit_outer_attrs (item);
+}
+
+void
+DefaultHIRVisitor::walk (EnumItemTuple &item_tuple)
+{
+ item_tuple.EnumItem::accept_vis (*this);
+ for (auto &field : item_tuple.get_tuple_fields ())
+ field.get_field_type ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (EnumItemStruct &item_struct)
+{
+ item_struct.EnumItem::accept_vis (*this);
+ for (auto &field : item_struct.get_struct_fields ())
+ field.get_field_type ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (EnumItemDiscriminant &item)
+{
+ item.EnumItem::accept_vis (*this);
+ item.get_discriminant_expression ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (Enum &enum_item)
+{
+ visit_outer_attrs (enum_item);
+ for (auto &generic : enum_item.get_generic_params ())
+ generic->accept_vis (*this);
+ if (enum_item.has_where_clause ())
+ visit_where_clause (enum_item.get_where_clause ());
+ for (auto &item : enum_item.get_variants ())
+ item->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (Union &union_item)
+{
+ visit_outer_attrs (union_item);
+ for (auto &generic : union_item.get_generic_params ())
+ generic->accept_vis (*this);
+ if (union_item.has_where_clause ())
+ visit_where_clause (union_item.get_where_clause ());
+ for (auto &variant : union_item.get_variants ())
+ visit_struct_field (variant);
+}
+
+void
+DefaultHIRVisitor::walk (ConstantItem &const_item)
+{
+ visit_outer_attrs (const_item);
+ const_item.get_type ().accept_vis (*this);
+ const_item.get_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (StaticItem &static_item)
+{
+ visit_outer_attrs (static_item);
+ static_item.get_type ().accept_vis (*this);
+ static_item.get_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::visit_self_param (SelfParam &self_param)
+{
+ if (self_param.has_lifetime ())
+ {
+ Lifetime lifetime = self_param.get_lifetime ();
+ lifetime.accept_vis (*this);
+ }
+ if (self_param.has_type ())
+ self_param.get_type ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TraitItemFunc &item)
+{
+ visit_outer_attrs (item);
+ TraitFunctionDecl &decl = item.get_decl ();
+ for (auto &generic : decl.get_generic_params ())
+ generic->accept_vis (*this);
+ if (decl.get_self ().has_value ())
+ visit_self_param (decl.get_self ().value ());
+ for (auto &param : decl.get_function_params ())
+ visit_function_param (param);
+ if (decl.has_return_type ())
+ decl.get_return_type ().accept_vis (*this);
+ if (decl.has_where_clause ())
+ visit_where_clause (decl.get_where_clause ());
+ if (item.has_definition ())
+ item.get_block_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TraitItemConst &item)
+{
+ visit_outer_attrs (item);
+ item.get_type ().accept_vis (*this);
+ if (item.has_expr ())
+ item.get_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TraitItemType &item)
+{
+ visit_outer_attrs (item);
+ for (auto &bound : item.get_type_param_bounds ())
+ bound->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::visit_where_clause (const WhereClause &where_clause)
+{
+ for (auto &item : where_clause.get_items ())
+ item->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::visit_where_clause (WhereClause &where_clause)
+{
+ for (auto &item : where_clause.get_items ())
+ {
+ item->accept_vis (*this);
+ }
+}
+
+void
+DefaultHIRVisitor::walk (WhereClauseItem &node)
+{}
+
+void
+DefaultHIRVisitor::walk (Trait &trait)
+{
+ visit_outer_attrs (trait);
+ for (auto &generic : trait.get_generic_params ())
+ generic->accept_vis (*this);
+ if (trait.has_where_clause ())
+ visit_where_clause (trait.get_where_clause ());
+ for (auto &bound : trait.get_type_param_bounds ())
+ bound->accept_vis (*this);
+ for (auto &item : trait.get_trait_items ())
+ item->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ImplBlock &impl)
+{
+ visit_outer_attrs (impl);
+ for (auto &generic : impl.get_generic_params ())
+ generic->accept_vis (*this);
+ if (impl.has_trait_ref ())
+ impl.get_trait_ref ().accept_vis (*this);
+ impl.get_type ().accept_vis (*this);
+ if (impl.has_where_clause ())
+ visit_where_clause (impl.get_where_clause ());
+ visit_inner_attrs (impl);
+ for (auto &item : impl.get_impl_items ())
+ item->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ExternalStaticItem &item)
+{
+ visit_outer_attrs (item);
+ item.get_item_type ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::visit_named_function_param (NamedFunctionParam &param)
+{
+ param.get_type ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ExternalFunctionItem &item)
+{
+ visit_outer_attrs (item);
+ for (auto &generic : item.get_generic_params ())
+ generic->accept_vis (*this);
+ for (auto &param : item.get_function_params ())
+ visit_named_function_param (param);
+ if (item.has_return_type ())
+ item.get_return_type ().accept_vis (*this);
+ if (item.has_where_clause ())
+ visit_where_clause (item.get_where_clause ());
+}
+
+void
+DefaultHIRVisitor::walk (ExternalTypeItem &item)
+{
+ visit_outer_attrs (item);
+}
+
+void
+DefaultHIRVisitor::walk (ExternBlock &block)
+{
+ visit_outer_attrs (block);
+ visit_inner_attrs (block);
+ for (auto &item : block.get_extern_items ())
+ item->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (LiteralPattern &)
+{}
+
+void
+DefaultHIRVisitor::walk (IdentifierPattern &pattern)
+{
+ if (pattern.has_subpattern ())
+ pattern.get_subpattern ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (WildcardPattern &)
+{}
+
+void
+DefaultHIRVisitor::walk (RangePatternBoundLiteral &)
+{}
+
+void
+DefaultHIRVisitor::walk (RangePatternBoundPath &bound)
+{
+ bound.get_path ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (RangePatternBoundQualPath &bound)
+{
+ bound.get_qualified_path ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (RangePattern &pattern)
+{
+ pattern.get_lower_bound ().accept_vis (*this);
+ pattern.get_upper_bound ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ReferencePattern &pattern)
+{
+ pattern.get_referenced_pattern ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (StructPatternFieldTuplePat &field)
+{
+ visit_outer_attrs (field);
+ field.get_tuple_pattern ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (StructPatternFieldIdentPat &field)
+{
+ visit_outer_attrs (field);
+ field.get_pattern ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (StructPatternFieldIdent &field)
+{
+ visit_outer_attrs (field);
+}
+
+void
+DefaultHIRVisitor::walk (StructPattern &pattern)
+{
+ pattern.get_path ().accept_vis (*this);
+ StructPatternElements &elements = pattern.get_struct_pattern_elems ();
+ for (auto &field : elements.get_struct_pattern_fields ())
+ field->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TupleStructItemsNoRange &tuple_items)
+{
+ for (auto &item : tuple_items.get_patterns ())
+ item->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TupleStructItemsRange &tuple_items)
+{
+ for (auto &lower : tuple_items.get_lower_patterns ())
+ lower->accept_vis (*this);
+ for (auto &upper : tuple_items.get_upper_patterns ())
+ upper->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TupleStructPattern &pattern)
+{
+ pattern.get_path ().accept_vis (*this);
+ pattern.get_items ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TuplePatternItemsMultiple &tuple_items)
+{
+ for (auto &pattern : tuple_items.get_patterns ())
+ pattern->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TuplePatternItemsRanged &tuple_items)
+{
+ for (auto &lower : tuple_items.get_lower_patterns ())
+ lower->accept_vis (*this);
+ for (auto &upper : tuple_items.get_upper_patterns ())
+ upper->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TuplePattern &pattern)
+{
+ pattern.get_items ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (SlicePattern &pattern)
+{
+ for (auto &item : pattern.get_items ())
+ item->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (AltPattern &pattern)
+{
+ for (auto &item : pattern.get_alts ())
+ item->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (EmptyStmt &stmt)
+{}
+
+void
+DefaultHIRVisitor::walk (LetStmt &stmt)
+{
+ visit_outer_attrs (stmt);
+ stmt.get_pattern ().accept_vis (*this);
+ if (stmt.has_type ())
+ stmt.get_type ().accept_vis (*this);
+ if (stmt.has_init_expr ())
+ stmt.get_init_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ExprStmt &stmt)
+{
+ stmt.get_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TraitBound &bound)
+{
+ for (auto &lifetime : bound.get_for_lifetimes ())
+ lifetime.accept_vis (*this);
+ bound.get_path ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ImplTraitType &type)
+{
+ for (auto &bound : type.get_type_param_bounds ())
+ bound->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TraitObjectType &type)
+{
+ for (auto &bound : type.get_type_param_bounds ())
+ bound->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ParenthesisedType &type)
+{
+ type.get_type_in_parens ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (TupleType &type)
+{
+ for (auto &elem : type.get_elems ())
+ elem->accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (NeverType &type)
+{}
+
+void
+DefaultHIRVisitor::walk (RawPointerType &type)
+{
+ type.get_type ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ReferenceType &type)
+{
+ if (type.has_lifetime ())
+ type.get_lifetime ().accept_vis (*this);
+ type.get_base_type ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (ArrayType &type)
+{
+ type.get_element_type ().accept_vis (*this);
+ type.get_size_expr ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (SliceType &type)
+{
+ type.get_element_type ().accept_vis (*this);
+}
+
+void
+DefaultHIRVisitor::walk (InferredType &type)
+{}
+
+void
+DefaultHIRVisitor::walk (BareFunctionType &type)
+{
+ for (auto &lifetime : type.get_for_lifetimes ())
+ lifetime.accept_vis (*this);
+ for (auto &param : type.get_function_params ())
+ param.get_type ().accept_vis (*this);
+ if (type.has_return_type ())
+ type.get_return_type ().accept_vis (*this);
+}
+
+} // namespace HIR
+} // namespace Rust
diff --git a/gcc/rust/hir/tree/rust-hir-visitor.h b/gcc/rust/hir/tree/rust-hir-visitor.h
index 283cc34..7996260 100644
--- a/gcc/rust/hir/tree/rust-hir-visitor.h
+++ b/gcc/rust/hir/tree/rust-hir-visitor.h
@@ -20,6 +20,7 @@
#define RUST_HIR_VISITOR_H
#include "rust-hir-full-decls.h"
+#include "rust-ast.h"
namespace Rust {
namespace HIR {
@@ -64,6 +65,8 @@ public:
virtual void visit (MethodCallExpr &expr) = 0;
virtual void visit (FieldAccessExpr &expr) = 0;
virtual void visit (BlockExpr &expr) = 0;
+ virtual void visit (AnonConst &expr) = 0;
+ virtual void visit (ConstBlock &expr) = 0;
virtual void visit (ClosureExpr &expr) = 0;
virtual void visit (ContinueExpr &expr) = 0;
virtual void visit (BreakExpr &expr) = 0;
@@ -85,6 +88,7 @@ public:
virtual void visit (AsyncBlockExpr &expr) = 0;
virtual void visit (InlineAsm &expr) = 0;
virtual void visit (LlvmInlineAsm &expr) = 0;
+ virtual void visit (OffsetOf &expr) = 0;
virtual void visit (TypeParam &param) = 0;
virtual void visit (ConstGenericParam &param) = 0;
virtual void visit (LifetimeWhereClauseItem &item) = 0;
@@ -153,6 +157,312 @@ public:
virtual void visit (BareFunctionType &type) = 0;
};
+class DefaultHIRVisitor : public HIRFullVisitor
+{
+public:
+ virtual void visit_where_clause (WhereClause &);
+ virtual void visit_where_clause (const WhereClause &);
+ virtual void visit_named_function_param (NamedFunctionParam &param);
+ virtual void visit_function_param (FunctionParam &param);
+ virtual void visit_self_param (SelfParam &param);
+ virtual void visit_match_arm (MatchArm &arm);
+ virtual void visit_match_case (MatchCase &);
+ virtual void visit_struct_field (StructField &field);
+ virtual void visit_generic_args (GenericArgs &args);
+ virtual void visit_qualified_path_type (QualifiedPathType &);
+ virtual void visit_path_expr_segment (PathExprSegment &segment);
+ virtual void visit_closure_param (ClosureParam &param);
+ virtual void visit_loop_label (LoopLabel &);
+
+ virtual void visit_attribute (AST::Attribute &attr)
+ {
+ visit_attribute (static_cast<const AST::Attribute &> (attr));
+ }
+ virtual void visit_attribute (const AST::Attribute &attr) {}
+ template <typename T> void visit_outer_attrs (T &node)
+ {
+ for (auto &attr : node.get_outer_attrs ())
+ visit_attribute (attr);
+ }
+ template <typename T> void visit_inner_attrs (T &node)
+ {
+ for (auto &attr : node.get_inner_attrs ())
+ visit_attribute (attr);
+ }
+
+ virtual void visit (WhereClauseItem &node) { walk (node); }
+
+ virtual void visit (Lifetime &node) override { walk (node); }
+ virtual void visit (LifetimeParam &node) override { walk (node); }
+ virtual void visit (PathInExpression &node) override { walk (node); }
+ virtual void visit (TypePathSegment &node) override { walk (node); }
+ virtual void visit (TypePathSegmentGeneric &node) override { walk (node); }
+ virtual void visit (TypePathSegmentFunction &node) override { walk (node); }
+ virtual void visit (TypePath &node) override { walk (node); }
+ virtual void visit (QualifiedPathInExpression &node) override { walk (node); }
+ virtual void visit (QualifiedPathInType &node) override { walk (node); }
+ virtual void visit (LiteralExpr &node) override { walk (node); }
+ virtual void visit (BorrowExpr &node) override { walk (node); }
+ virtual void visit (DereferenceExpr &node) override { walk (node); }
+ virtual void visit (ErrorPropagationExpr &node) override { walk (node); }
+ virtual void visit (NegationExpr &node) override { walk (node); }
+ virtual void visit (ArithmeticOrLogicalExpr &node) override { walk (node); }
+ virtual void visit (ComparisonExpr &node) override { walk (node); }
+ virtual void visit (LazyBooleanExpr &node) override { walk (node); }
+ virtual void visit (TypeCastExpr &node) override { walk (node); }
+ virtual void visit (AssignmentExpr &node) override { walk (node); }
+ virtual void visit (CompoundAssignmentExpr &node) override { walk (node); }
+ virtual void visit (GroupedExpr &node) override { walk (node); }
+ virtual void visit (ArrayElemsValues &node) override { walk (node); }
+ virtual void visit (ArrayElemsCopied &node) override { walk (node); }
+ virtual void visit (ArrayExpr &node) override { walk (node); }
+ virtual void visit (ArrayIndexExpr &node) override { walk (node); }
+ virtual void visit (TupleExpr &node) override { walk (node); }
+ virtual void visit (TupleIndexExpr &node) override { walk (node); }
+ virtual void visit (StructExprStruct &node) override { walk (node); }
+ virtual void visit (StructExprFieldIdentifier &node) override { walk (node); }
+ virtual void visit (StructExprFieldIdentifierValue &node) override
+ {
+ walk (node);
+ }
+ virtual void visit (StructExprFieldIndexValue &node) override { walk (node); }
+ virtual void visit (StructExprStructFields &node) override { walk (node); }
+ virtual void visit (StructExprStructBase &node) override { walk (node); }
+ virtual void visit (CallExpr &node) override { walk (node); }
+ virtual void visit (MethodCallExpr &node) override { walk (node); }
+ virtual void visit (FieldAccessExpr &node) override { walk (node); }
+ virtual void visit (ClosureExpr &node) override { walk (node); }
+ virtual void visit (BlockExpr &node) override { walk (node); }
+ virtual void visit (AnonConst &node) override { walk (node); }
+ virtual void visit (ConstBlock &node) override { walk (node); }
+ virtual void visit (ContinueExpr &node) override { walk (node); }
+ virtual void visit (BreakExpr &node) override { walk (node); }
+ virtual void visit (RangeFromToExpr &node) override { walk (node); }
+ virtual void visit (RangeFromExpr &node) override { walk (node); }
+ virtual void visit (RangeToExpr &node) override { walk (node); }
+ virtual void visit (RangeFullExpr &node) override { walk (node); }
+ virtual void visit (RangeFromToInclExpr &node) override { walk (node); }
+ virtual void visit (RangeToInclExpr &node) override { walk (node); }
+ virtual void visit (ReturnExpr &node) override { walk (node); }
+ virtual void visit (UnsafeBlockExpr &node) override { walk (node); }
+ virtual void visit (LoopExpr &node) override { walk (node); }
+ virtual void visit (WhileLoopExpr &node) override { walk (node); }
+ virtual void visit (WhileLetLoopExpr &node) override { walk (node); }
+ virtual void visit (IfExpr &node) override { walk (node); }
+ virtual void visit (IfExprConseqElse &node) override { walk (node); }
+ virtual void visit (MatchExpr &node) override { walk (node); }
+ virtual void visit (AwaitExpr &node) override { walk (node); }
+ virtual void visit (AsyncBlockExpr &node) override { walk (node); }
+ virtual void visit (InlineAsm &node) override { walk (node); }
+ virtual void visit (LlvmInlineAsm &node) override { walk (node); }
+ virtual void visit (OffsetOf &node) override { walk (node); }
+ virtual void visit (TypeParam &node) override { walk (node); }
+ virtual void visit (ConstGenericParam &node) override { walk (node); }
+ virtual void visit (LifetimeWhereClauseItem &node) override { walk (node); }
+ virtual void visit (TypeBoundWhereClauseItem &node) override { walk (node); }
+ virtual void visit (Module &node) override { walk (node); }
+ virtual void visit (ExternCrate &node) override { walk (node); }
+ virtual void visit (UseTreeGlob &node) override { walk (node); }
+ virtual void visit (UseTreeList &node) override { walk (node); }
+ virtual void visit (UseTreeRebind &node) override { walk (node); }
+ virtual void visit (UseDeclaration &node) override { walk (node); }
+ virtual void visit (Function &node) override { walk (node); }
+ virtual void visit (TypeAlias &node) override { walk (node); }
+ virtual void visit (StructStruct &node) override { walk (node); }
+ virtual void visit (TupleStruct &node) override { walk (node); }
+ virtual void visit (EnumItem &node) override { walk (node); }
+ virtual void visit (EnumItemTuple &node) override { walk (node); }
+ virtual void visit (EnumItemStruct &node) override { walk (node); }
+ virtual void visit (EnumItemDiscriminant &node) override { walk (node); }
+ virtual void visit (Enum &node) override { walk (node); }
+ virtual void visit (Union &node) override { walk (node); }
+ virtual void visit (ConstantItem &node) override { walk (node); }
+ virtual void visit (StaticItem &node) override { walk (node); }
+ virtual void visit (TraitItemFunc &node) override { walk (node); }
+ virtual void visit (TraitItemConst &node) override { walk (node); }
+ virtual void visit (TraitItemType &node) override { walk (node); }
+ virtual void visit (Trait &node) override { walk (node); }
+ virtual void visit (ImplBlock &node) override { walk (node); }
+ virtual void visit (ExternalStaticItem &node) override { walk (node); }
+ virtual void visit (ExternalFunctionItem &node) override { walk (node); }
+ virtual void visit (ExternalTypeItem &node) override { walk (node); }
+ virtual void visit (ExternBlock &node) override { walk (node); }
+ virtual void visit (LiteralPattern &node) override { walk (node); }
+ virtual void visit (IdentifierPattern &node) override { walk (node); }
+ virtual void visit (WildcardPattern &node) override { walk (node); }
+ virtual void visit (RangePatternBoundLiteral &node) override { walk (node); }
+ virtual void visit (RangePatternBoundPath &node) override { walk (node); }
+ virtual void visit (RangePatternBoundQualPath &node) override { walk (node); }
+ virtual void visit (RangePattern &node) override { walk (node); }
+ virtual void visit (ReferencePattern &node) override { walk (node); }
+ virtual void visit (StructPatternFieldTuplePat &node) override
+ {
+ walk (node);
+ }
+ virtual void visit (StructPatternFieldIdentPat &node) override
+ {
+ walk (node);
+ }
+ virtual void visit (StructPatternFieldIdent &node) override { walk (node); }
+ virtual void visit (StructPattern &node) override { walk (node); }
+ virtual void visit (TupleStructItemsNoRange &node) override { walk (node); }
+ virtual void visit (TupleStructItemsRange &node) override { walk (node); }
+ virtual void visit (TupleStructPattern &node) override { walk (node); }
+ virtual void visit (TuplePatternItemsMultiple &node) override { walk (node); }
+ virtual void visit (TuplePatternItemsRanged &node) override { walk (node); }
+ virtual void visit (TuplePattern &node) override { walk (node); }
+ virtual void visit (SlicePattern &node) override { walk (node); }
+ virtual void visit (AltPattern &node) override { walk (node); }
+ virtual void visit (EmptyStmt &node) override { walk (node); }
+ virtual void visit (LetStmt &node) override { walk (node); }
+ virtual void visit (ExprStmt &node) override { walk (node); }
+ virtual void visit (TraitBound &node) override { walk (node); }
+ virtual void visit (ImplTraitType &node) override { walk (node); }
+ virtual void visit (TraitObjectType &node) override { walk (node); }
+ virtual void visit (ParenthesisedType &node) override { walk (node); }
+ virtual void visit (TupleType &node) override { walk (node); }
+ virtual void visit (NeverType &node) override { walk (node); }
+ virtual void visit (RawPointerType &node) override { walk (node); }
+ virtual void visit (ReferenceType &node) override { walk (node); }
+ virtual void visit (ArrayType &node) override { walk (node); }
+ virtual void visit (SliceType &node) override { walk (node); }
+ virtual void visit (InferredType &node) override { walk (node); }
+ virtual void visit (BareFunctionType &node) override { walk (node); }
+
+protected:
+ virtual void walk (WhereClauseItem &) final;
+
+ virtual void walk (Lifetime &) final;
+ virtual void walk (LifetimeParam &) final;
+ virtual void walk (PathInExpression &) final;
+ virtual void walk (TypePathSegment &) final;
+ virtual void walk (TypePathSegmentGeneric &) final;
+ virtual void walk (TypePathSegmentFunction &) final;
+ virtual void walk (TypePath &) final;
+ virtual void walk (QualifiedPathInExpression &) final;
+ virtual void walk (QualifiedPathInType &) final;
+
+ virtual void walk (LiteralExpr &) final;
+ virtual void walk (BorrowExpr &) final;
+ virtual void walk (DereferenceExpr &) final;
+ virtual void walk (ErrorPropagationExpr &) final;
+ virtual void walk (NegationExpr &) final;
+ virtual void walk (ArithmeticOrLogicalExpr &) final;
+ virtual void walk (ComparisonExpr &) final;
+ virtual void walk (LazyBooleanExpr &) final;
+ virtual void walk (TypeCastExpr &) final;
+ virtual void walk (AssignmentExpr &) final;
+ virtual void walk (CompoundAssignmentExpr &) final;
+ virtual void walk (GroupedExpr &) final;
+
+ virtual void walk (ArrayElemsValues &) final;
+ virtual void walk (ArrayElemsCopied &) final;
+ virtual void walk (ArrayExpr &) final;
+ virtual void walk (ArrayIndexExpr &) final;
+ virtual void walk (TupleExpr &) final;
+ virtual void walk (TupleIndexExpr &) final;
+ virtual void walk (StructExprStruct &) final;
+ virtual void walk (StructExprFieldIdentifier &) final;
+ virtual void walk (StructExprFieldIdentifierValue &) final;
+ virtual void walk (StructExprFieldIndexValue &) final;
+ virtual void walk (StructExprStructFields &) final;
+ virtual void walk (StructExprStructBase &) final;
+ virtual void walk (CallExpr &) final;
+ virtual void walk (MethodCallExpr &) final;
+ virtual void walk (FieldAccessExpr &) final;
+ virtual void walk (ClosureExpr &) final;
+ virtual void walk (BlockExpr &) final;
+ virtual void walk (AnonConst &) final;
+ virtual void walk (ConstBlock &) final;
+ virtual void walk (ContinueExpr &) final;
+ virtual void walk (BreakExpr &) final;
+ virtual void walk (RangeFromToExpr &) final;
+ virtual void walk (RangeFromExpr &) final;
+ virtual void walk (RangeToExpr &) final;
+ virtual void walk (RangeFullExpr &) final;
+ virtual void walk (RangeFromToInclExpr &) final;
+ virtual void walk (RangeToInclExpr &) final;
+ virtual void walk (ReturnExpr &) final;
+ virtual void walk (UnsafeBlockExpr &) final;
+ virtual void walk (LoopExpr &) final;
+ virtual void walk (WhileLoopExpr &) final;
+ virtual void walk (WhileLetLoopExpr &) final;
+ virtual void walk (IfExpr &) final;
+ virtual void walk (IfExprConseqElse &) final;
+ virtual void walk (MatchExpr &) final;
+ virtual void walk (AwaitExpr &) final;
+ virtual void walk (AsyncBlockExpr &) final;
+ virtual void walk (InlineAsm &) final;
+ virtual void walk (LlvmInlineAsm &) final;
+ virtual void walk (OffsetOf &) final;
+ virtual void walk (TypeParam &) final;
+ virtual void walk (ConstGenericParam &) final;
+ virtual void walk (LifetimeWhereClauseItem &) final;
+ virtual void walk (TypeBoundWhereClauseItem &) final;
+ virtual void walk (Module &) final;
+ virtual void walk (ExternCrate &) final;
+ virtual void walk (UseTreeGlob &) final;
+ virtual void walk (UseTreeList &) final;
+ virtual void walk (UseTreeRebind &) final;
+ virtual void walk (UseDeclaration &) final;
+ virtual void walk (Function &) final;
+ virtual void walk (TypeAlias &) final;
+ virtual void walk (StructStruct &) final;
+ virtual void walk (TupleStruct &) final;
+ virtual void walk (EnumItem &) final;
+ virtual void walk (EnumItemTuple &) final;
+ virtual void walk (EnumItemStruct &) final;
+ virtual void walk (EnumItemDiscriminant &) final;
+ virtual void walk (Enum &) final;
+ virtual void walk (Union &) final;
+ virtual void walk (ConstantItem &) final;
+ virtual void walk (StaticItem &) final;
+ virtual void walk (TraitItemFunc &) final;
+ virtual void walk (TraitItemConst &) final;
+ virtual void walk (TraitItemType &) final;
+ virtual void walk (Trait &) final;
+ virtual void walk (ImplBlock &) final;
+ virtual void walk (ExternalStaticItem &) final;
+ virtual void walk (ExternalFunctionItem &) final;
+ virtual void walk (ExternalTypeItem &) final;
+ virtual void walk (ExternBlock &) final;
+ virtual void walk (LiteralPattern &) final;
+ virtual void walk (IdentifierPattern &) final;
+ virtual void walk (WildcardPattern &) final;
+ virtual void walk (RangePatternBoundLiteral &) final;
+ virtual void walk (RangePatternBoundPath &) final;
+ virtual void walk (RangePatternBoundQualPath &) final;
+ virtual void walk (RangePattern &) final;
+ virtual void walk (ReferencePattern &) final;
+ virtual void walk (StructPatternFieldTuplePat &) final;
+ virtual void walk (StructPatternFieldIdentPat &) final;
+ virtual void walk (StructPatternFieldIdent &) final;
+ virtual void walk (StructPattern &) final;
+ virtual void walk (TupleStructItemsNoRange &) final;
+ virtual void walk (TupleStructItemsRange &) final;
+ virtual void walk (TupleStructPattern &) final;
+ virtual void walk (TuplePatternItemsMultiple &) final;
+ virtual void walk (TuplePatternItemsRanged &) final;
+ virtual void walk (TuplePattern &) final;
+ virtual void walk (SlicePattern &) final;
+ virtual void walk (AltPattern &) final;
+ virtual void walk (EmptyStmt &) final;
+ virtual void walk (LetStmt &) final;
+ virtual void walk (ExprStmt &) final;
+ virtual void walk (TraitBound &) final;
+ virtual void walk (ImplTraitType &) final;
+ virtual void walk (TraitObjectType &) final;
+ virtual void walk (ParenthesisedType &) final;
+ virtual void walk (TupleType &) final;
+ virtual void walk (NeverType &) final;
+ virtual void walk (RawPointerType &) final;
+ virtual void walk (ReferenceType &) final;
+ virtual void walk (ArrayType &) final;
+ virtual void walk (SliceType &) final;
+ virtual void walk (InferredType &) final;
+ virtual void walk (BareFunctionType &) final;
+};
+
class HIRFullVisitorBase : public HIRFullVisitor
{
public:
@@ -201,6 +511,8 @@ public:
virtual void visit (FieldAccessExpr &) override {}
virtual void visit (ClosureExpr &) override {}
virtual void visit (BlockExpr &) override {}
+ virtual void visit (AnonConst &) override {}
+ virtual void visit (ConstBlock &) override {}
virtual void visit (ContinueExpr &) override {}
virtual void visit (BreakExpr &) override {}
virtual void visit (RangeFromToExpr &) override {}
@@ -222,6 +534,7 @@ public:
virtual void visit (AsyncBlockExpr &) override {}
virtual void visit (InlineAsm &) override {}
virtual void visit (LlvmInlineAsm &) override {}
+ virtual void visit (OffsetOf &) override {}
virtual void visit (TypeParam &) override {}
virtual void visit (ConstGenericParam &) override {}
@@ -427,6 +740,8 @@ public:
virtual void visit (MethodCallExpr &expr) = 0;
virtual void visit (FieldAccessExpr &expr) = 0;
virtual void visit (BlockExpr &expr) = 0;
+ virtual void visit (AnonConst &expr) = 0;
+ virtual void visit (ConstBlock &expr) = 0;
virtual void visit (ContinueExpr &expr) = 0;
virtual void visit (BreakExpr &expr) = 0;
virtual void visit (RangeFromToExpr &expr) = 0;
@@ -443,6 +758,7 @@ public:
virtual void visit (IfExpr &expr) = 0;
virtual void visit (IfExprConseqElse &expr) = 0;
virtual void visit (InlineAsm &expr) = 0;
+ virtual void visit (OffsetOf &expr) = 0;
virtual void visit (LlvmInlineAsm &expr) = 0;
virtual void visit (MatchExpr &expr) = 0;
virtual void visit (AwaitExpr &expr) = 0;
diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc
index 093d8d5..a802e8c 100644
--- a/gcc/rust/hir/tree/rust-hir.cc
+++ b/gcc/rust/hir/tree/rust-hir.cc
@@ -577,7 +577,8 @@ UseTreeGlob::as_string () const
return "*";
case GLOBAL:
return "::*";
- case PATH_PREFIXED: {
+ case PATH_PREFIXED:
+ {
std::string path_str = path.as_string ();
return path_str + "::*";
}
@@ -600,7 +601,8 @@ UseTreeList::as_string () const
case GLOBAL:
path_str = "::{";
break;
- case PATH_PREFIXED: {
+ case PATH_PREFIXED:
+ {
path_str = path.as_string () + "::{";
break;
}
@@ -1048,6 +1050,36 @@ BlockExpr::as_string () const
}
std::string
+AnonConst::as_string () const
+{
+ std::string istr = indent_spaces (enter);
+ std::string str = istr + "AnonConst:\n" + istr;
+
+ if (expr.has_value ())
+ str += get_inner_expr ().as_string ();
+ else
+ str += "_";
+
+ str += "\n" + indent_spaces (out);
+
+ return str;
+}
+
+std::string
+ConstBlock::as_string () const
+{
+ std::string istr = indent_spaces (enter);
+
+ std::string str = istr + "ConstBlock:\n" + istr;
+
+ str += get_const_expr ().as_string ();
+
+ str += "\n" + indent_spaces (out);
+
+ return str;
+}
+
+std::string
TypeAlias::as_string () const
{
std::string str = VisItem::as_string ();
@@ -2579,9 +2611,9 @@ IdentifierPattern::as_string () const
str += variable_ident.as_string ();
- if (has_pattern_to_bind ())
+ if (has_subpattern ())
{
- str += " @ " + to_bind->as_string ();
+ str += " @ " + subpattern->as_string ();
}
return str;
@@ -4055,6 +4087,18 @@ BlockExpr::accept_vis (HIRFullVisitor &vis)
}
void
+AnonConst::accept_vis (HIRFullVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
+ConstBlock::accept_vis (HIRFullVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
ContinueExpr::accept_vis (HIRFullVisitor &vis)
{
vis.visit (*this);
@@ -5027,6 +5071,18 @@ BlockExpr::accept_vis (HIRExpressionVisitor &vis)
}
void
+AnonConst::accept_vis (HIRExpressionVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
+ConstBlock::accept_vis (HIRExpressionVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
Function::accept_vis (HIRStmtVisitor &vis)
{
vis.visit (*this);
diff --git a/gcc/rust/lang.opt b/gcc/rust/lang.opt
index 9cdbce2..d9824f1 100644
--- a/gcc/rust/lang.opt
+++ b/gcc/rust/lang.opt
@@ -205,7 +205,7 @@ EnumValue
Enum(frust_compile_until) String(end) Value(13)
frust-name-resolution-2.0
-Rust Var(flag_name_resolution_2_0)
+Rust Var(flag_name_resolution_2_0) Init(1)
Use the temporary and experimental name resolution pipeline instead of the stable one
frust-borrowcheck
@@ -229,4 +229,8 @@ frust-overflow-checks
Rust Var(flag_overflow_checks) Init(1)
Enable the overflow checks in code generation
+frust-assume-builtin-offset-of
+Rust Var(flag_assume_builtin_offset_of)
+Define a built-in offset_of macro in the compiler and assume it is present
+
; This comment is to ensure we retain the blank line above.
diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc
index b143e70..76ff15c 100644
--- a/gcc/rust/lex/rust-lex.cc
+++ b/gcc/rust/lex/rust-lex.cc
@@ -1317,7 +1317,8 @@ Lexer::parse_escape (char opening_char)
switch (current_char.value)
{
- case 'x': {
+ case 'x':
+ {
auto hex_escape_pair = parse_partial_hex_escape ();
long hexLong = hex_escape_pair.first;
additional_length_offset += hex_escape_pair.second;
@@ -1400,7 +1401,8 @@ Lexer::parse_utf8_escape ()
switch (current_char.value)
{
- case 'x': {
+ case 'x':
+ {
auto hex_escape_pair = parse_partial_hex_escape ();
long hexLong = hex_escape_pair.first;
additional_length_offset += hex_escape_pair.second;
@@ -1438,7 +1440,8 @@ Lexer::parse_utf8_escape ()
case '"':
output_char = '"';
break;
- case 'u': {
+ case 'u':
+ {
auto unicode_escape_pair = parse_partial_unicode_escape ();
output_char = unicode_escape_pair.first;
additional_length_offset += unicode_escape_pair.second;
@@ -1894,6 +1897,11 @@ Lexer::parse_raw_byte_string (location_t loc)
break;
}
}
+ else if (current_char.is_eof ())
+ {
+ rust_error_at (string_begin_locus, "unended raw byte string literal");
+ return Token::make (END_OF_FILE, get_current_location ());
+ }
else if (current_char.value > 127)
{
rust_error_at (get_current_location (),
@@ -1901,11 +1909,6 @@ Lexer::parse_raw_byte_string (location_t loc)
current_char.as_string ().c_str ());
current_char = 0;
}
- else if (current_char.is_eof ())
- {
- rust_error_at (string_begin_locus, "unended raw byte string literal");
- return Token::make (END_OF_FILE, get_current_location ());
- }
length++;
current_column++;
diff --git a/gcc/rust/lex/rust-lex.h b/gcc/rust/lex/rust-lex.h
index 10293e0..383ffac 100644
--- a/gcc/rust/lex/rust-lex.h
+++ b/gcc/rust/lex/rust-lex.h
@@ -263,8 +263,7 @@ private:
#if CHECKING_P
namespace selftest {
-void
-rust_input_source_test ();
+void rust_input_source_test ();
} // namespace selftest
diff --git a/gcc/rust/lex/rust-token.cc b/gcc/rust/lex/rust-token.cc
index 8493889..c396e10 100644
--- a/gcc/rust/lex/rust-token.cc
+++ b/gcc/rust/lex/rust-token.cc
@@ -20,6 +20,7 @@
#include "rust-token.h"
#include "rust-diagnostics.h"
#include "rust-unicode.h"
+#include "rust-ast.h"
namespace Rust {
// Hackily defined way to get token description for enum value using x-macros
@@ -88,7 +89,8 @@ token_id_keyword_string (TokenId id)
switch (id)
{
#define RS_TOKEN_KEYWORD_2015(id, str_ptr) \
- case id: { \
+ case id: \
+ { \
static const std::string str (str_ptr); \
return str; \
} \
@@ -234,6 +236,13 @@ escape_special_chars (const std::string &source, Context ctx)
} // namespace
+TokenPtr
+Token::make_identifier (const Identifier &ident)
+{
+ std::string str = ident;
+ return make_identifier (ident.get_locus (), std::move (str));
+}
+
std::string
Token::as_string () const
{
diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h
index c683ecd..2021aec 100644
--- a/gcc/rust/lex/rust-token.h
+++ b/gcc/rust/lex/rust-token.h
@@ -24,6 +24,10 @@
#include "rust-unicode.h"
namespace Rust {
+
+// used by Rust::Token::make_identifier
+class Identifier;
+
// "Primitive core types" in Rust - the different int and float types, as well
// as some others
enum PrimitiveCoreType
@@ -221,25 +225,20 @@ typedef std::shared_ptr<Token> TokenPtr;
typedef std::shared_ptr<const Token> const_TokenPtr;
// Hackily defined way to get token description for enum value using x-macros
-const char *
-get_token_description (TokenId id);
+const char *get_token_description (TokenId id);
/* Hackily defined way to get token description as a string for enum value using
* x-macros */
-const char *
-token_id_to_str (TokenId id);
+const char *token_id_to_str (TokenId id);
/* checks if a token is a keyword */
-bool
-token_id_is_keyword (TokenId id);
+bool token_id_is_keyword (TokenId id);
/* gets the string associated with a keyword */
-const std::string &
-token_id_keyword_string (TokenId id);
+const std::string &token_id_keyword_string (TokenId id);
// Get type hint description as a string.
-const char *
-get_type_hint_string (PrimitiveCoreType type);
+const char *get_type_hint_string (PrimitiveCoreType type);
/* Normalize string if a token is a identifier */
-std::string
-nfc_normalize_token_string (location_t loc, TokenId id, const std::string &str);
+std::string nfc_normalize_token_string (location_t loc, TokenId id,
+ const std::string &str);
// Represents a single token. Create using factory static methods.
class Token
@@ -329,6 +328,8 @@ public:
return TokenPtr (new Token (IDENTIFIER, locus, std::move (str)));
}
+ static TokenPtr make_identifier (const Identifier &ident);
+
// Makes and returns a new TokenPtr of type INT_LITERAL.
static TokenPtr make_int (location_t locus, std::string &&str,
PrimitiveCoreType type_hint = CORETYPE_UNKNOWN)
diff --git a/gcc/rust/metadata/rust-export-metadata.cc b/gcc/rust/metadata/rust-export-metadata.cc
index 771bec6..1829a85 100644
--- a/gcc/rust/metadata/rust-export-metadata.cc
+++ b/gcc/rust/metadata/rust-export-metadata.cc
@@ -263,8 +263,7 @@ PublicInterface::write_to_path (const std::string &path) const
FILE *nfd = fopen (path.c_str (), "wb");
if (nfd == NULL)
{
- rust_error_at (UNDEF_LOCATION,
- "failed to open file %qs for writing: %s",
+ rust_error_at (UNDEF_LOCATION, "failed to open file %qs for writing: %s",
path.c_str (), xstrerror (errno));
return;
}
diff --git a/gcc/rust/metadata/rust-import-archive.cc b/gcc/rust/metadata/rust-import-archive.cc
index cf24607..f64de4e 100644
--- a/gcc/rust/metadata/rust-import-archive.cc
+++ b/gcc/rust/metadata/rust-import-archive.cc
@@ -683,7 +683,7 @@ public:
const Header &operator* () const { return this->header_; }
- const Header *operator-> () const { return &this->header_; }
+ const Header *operator->() const { return &this->header_; }
Archive_iterator &operator++ ()
{
diff --git a/gcc/rust/metadata/rust-imports.h b/gcc/rust/metadata/rust-imports.h
index a497c67..65a2af1 100644
--- a/gcc/rust/metadata/rust-imports.h
+++ b/gcc/rust/metadata/rust-imports.h
@@ -11,8 +11,7 @@
namespace Rust {
-extern void
-add_search_path (const std::string &path);
+extern void add_search_path (const std::string &path);
class Import
{
diff --git a/gcc/rust/parse/rust-cfg-parser.h b/gcc/rust/parse/rust-cfg-parser.h
index 0d64016..61db240 100644
--- a/gcc/rust/parse/rust-cfg-parser.h
+++ b/gcc/rust/parse/rust-cfg-parser.h
@@ -36,15 +36,14 @@ namespace Rust {
*
* @return false if the given input was invalid, true otherwise
*/
-bool
-parse_cfg_option (std::string &input, std::string &key, std::string &value);
+bool parse_cfg_option (std::string &input, std::string &key,
+ std::string &value);
} // namespace Rust
#if CHECKING_P
namespace selftest {
-extern void
-rust_cfg_parser_test (void);
+extern void rust_cfg_parser_test (void);
} // namespace selftest
#endif // CHECKING_P
diff --git a/gcc/rust/ast/rust-macro.cc b/gcc/rust/parse/rust-parse-impl-lexer.cc
index 2703438..fec91e8 100644
--- a/gcc/rust/ast/rust-macro.cc
+++ b/gcc/rust/parse/rust-parse-impl-lexer.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2020-2025 Free Software Foundation, Inc.
+// Copyright (C) 2025 Free Software Foundation, Inc.
// This file is part of GCC.
@@ -16,10 +16,10 @@
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-#include "rust-macro.h"
+#include "rust-parse-impl.h"
namespace Rust {
-namespace AST {
-} // namespace AST
+template class Parser<Lexer>;
+
} // namespace Rust
diff --git a/gcc/rust/parse/rust-parse-impl-macro.cc b/gcc/rust/parse/rust-parse-impl-macro.cc
new file mode 100644
index 0000000..e632887
--- /dev/null
+++ b/gcc/rust/parse/rust-parse-impl-macro.cc
@@ -0,0 +1,26 @@
+// 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-parse-impl.h"
+#include "rust-macro-invoc-lexer.h"
+
+namespace Rust {
+
+template class Parser<MacroInvocLexer>;
+
+} // namespace Rust
diff --git a/gcc/rust/parse/rust-parse-impl-proc-macro.cc b/gcc/rust/parse/rust-parse-impl-proc-macro.cc
new file mode 100644
index 0000000..edc484f
--- /dev/null
+++ b/gcc/rust/parse/rust-parse-impl-proc-macro.cc
@@ -0,0 +1,34 @@
+// 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-parse-impl.h"
+#include "rust-proc-macro-invoc-lexer.h"
+
+namespace Rust {
+
+template std::unique_ptr<AST::Item>
+Parser<ProcMacroInvocLexer>::parse_item (bool);
+
+template std::unique_ptr<AST::Stmt>
+ Parser<ProcMacroInvocLexer>::parse_stmt (ParseRestrictions);
+
+// instantiate entire class (or just more functions) if necessary
+
+// template class Parser<ProcMacroInvocLexer>;
+
+} // namespace Rust
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 9dda231..14bccbd 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -19,13 +19,17 @@
/* Template implementation for Rust::Parser. Previously in rust-parse.cc (before
* Parser was template). Separated from rust-parse.h for readability. */
-/* DO NOT INCLUDE ANYWHERE - this is automatically included with rust-parse.h
+/* DO NOT INCLUDE ANYWHERE - this is automatically included
+ * by rust-parse-impl-*.cc
* This is also the reason why there are no include guards. */
+#include "expected.h"
+#include "rust-ast.h"
#include "rust-common.h"
#include "rust-expr.h"
#include "rust-item.h"
#include "rust-common.h"
+#include "rust-parse.h"
#include "rust-token.h"
#define INCLUDE_ALGORITHM
#include "rust-diagnostics.h"
@@ -227,19 +231,22 @@ Parser<ManagedTokenSource>::skip_generics_right_angle ()
// this is good - skip token
lexer.skip_token ();
return true;
- case RIGHT_SHIFT: {
+ case RIGHT_SHIFT:
+ {
// new implementation that should be better
lexer.split_current_token (RIGHT_ANGLE, RIGHT_ANGLE);
lexer.skip_token ();
return true;
}
- case GREATER_OR_EQUAL: {
+ case GREATER_OR_EQUAL:
+ {
// new implementation that should be better
lexer.split_current_token (RIGHT_ANGLE, EQUAL);
lexer.skip_token ();
return true;
}
- case RIGHT_SHIFT_EQ: {
+ case RIGHT_SHIFT_EQ:
+ {
// new implementation that should be better
lexer.split_current_token (RIGHT_ANGLE, GREATER_OR_EQUAL);
lexer.skip_token ();
@@ -651,10 +658,7 @@ Parser<ManagedTokenSource>::parse_simple_path ()
// Parse all other simple path segments
while (lexer.peek_token ()->get_id () == SCOPE_RESOLUTION)
{
- // Skip scope resolution operator
- lexer.skip_token ();
-
- AST::SimplePathSegment new_segment = parse_simple_path_segment ();
+ AST::SimplePathSegment new_segment = parse_simple_path_segment (1);
// Return path as currently constructed if segment in error state.
if (new_segment.is_error ())
@@ -682,35 +686,36 @@ Parser<ManagedTokenSource>::parse_simple_path ()
}
/* Parses a single SimplePathSegment (does not handle the scope resolution
- * operators) */
+ * operators)
+ * Starts parsing at an offset of base_peek */
template <typename ManagedTokenSource>
AST::SimplePathSegment
-Parser<ManagedTokenSource>::parse_simple_path_segment ()
+Parser<ManagedTokenSource>::parse_simple_path_segment (int base_peek)
{
using namespace Values;
- const_TokenPtr t = lexer.peek_token ();
+ const_TokenPtr t = lexer.peek_token (base_peek);
switch (t->get_id ())
{
case IDENTIFIER:
- lexer.skip_token ();
+ lexer.skip_token (base_peek);
return AST::SimplePathSegment (t->get_str (), t->get_locus ());
case SUPER:
- lexer.skip_token ();
+ lexer.skip_token (base_peek);
return AST::SimplePathSegment (Keywords::SUPER, t->get_locus ());
case SELF:
- lexer.skip_token ();
+ lexer.skip_token (base_peek);
return AST::SimplePathSegment (Keywords::SELF, t->get_locus ());
case CRATE:
- lexer.skip_token ();
+ lexer.skip_token (base_peek);
return AST::SimplePathSegment (Keywords::CRATE, t->get_locus ());
case DOLLAR_SIGN:
- if (lexer.peek_token (1)->get_id () == CRATE)
+ if (lexer.peek_token (base_peek + 1)->get_id () == CRATE)
{
- lexer.skip_token (1);
+ lexer.skip_token (base_peek + 1);
return AST::SimplePathSegment ("$crate", t->get_locus ());
}
@@ -790,7 +795,8 @@ Parser<ManagedTokenSource>::parse_attr_input ()
{
case LEFT_PAREN:
case LEFT_SQUARE:
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// must be a delimited token tree, so parse that
std::unique_ptr<AST::AttrInput> input_tree (
new AST::DelimTokenTree (parse_delim_token_tree ()));
@@ -799,7 +805,8 @@ Parser<ManagedTokenSource>::parse_attr_input ()
return input_tree;
}
- case EQUAL: {
+ case EQUAL:
+ {
// = LiteralExpr
lexer.skip_token ();
@@ -877,7 +884,10 @@ Parser<ManagedTokenSource>::parse_attr_input ()
return attr_input_lit;
}
break;
+ case RIGHT_PAREN:
case RIGHT_SQUARE:
+ case RIGHT_CURLY:
+ case END_OF_FILE:
// means AttrInput is missing, which is allowed
return nullptr;
default:
@@ -2117,7 +2127,8 @@ Parser<ManagedTokenSource>::parse_macro_match ()
{
case LEFT_PAREN:
case LEFT_SQUARE:
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// must be macro matcher as delimited
AST::MacroMatcher matcher = parse_macro_matcher ();
if (matcher.is_error ())
@@ -2131,7 +2142,8 @@ Parser<ManagedTokenSource>::parse_macro_match ()
return std::unique_ptr<AST::MacroMatcher> (
new AST::MacroMatcher (std::move (matcher)));
}
- case DOLLAR_SIGN: {
+ case DOLLAR_SIGN:
+ {
// have to do more lookahead to determine if fragment or repetition
const_TokenPtr t2 = lexer.peek_token (1);
switch (t2->get_id ())
@@ -2402,7 +2414,8 @@ Parser<ManagedTokenSource>::parse_visibility ()
skip_token (RIGHT_PAREN);
return AST::Visibility::create_super (path_loc, vis_loc);
- case IN: {
+ case IN:
+ {
lexer.skip_token ();
// parse the "in" path as well
@@ -2466,7 +2479,8 @@ Parser<ManagedTokenSource>::parse_module (AST::Visibility vis,
new AST::Module (std::move (name), std::move (vis),
std::move (outer_attrs), locus, safety,
lexer.get_filename (), inline_module_stack));
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
lexer.skip_token ();
// parse inner attributes
@@ -2730,7 +2744,8 @@ Parser<ManagedTokenSource>::parse_use_tree ()
return std::unique_ptr<AST::UseTreeGlob> (
new AST::UseTreeGlob (AST::UseTreeGlob::NO_PATH,
AST::SimplePath::create_empty (), locus));
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// nested tree UseTree type
lexer.skip_token ();
@@ -2794,58 +2809,12 @@ Parser<ManagedTokenSource>::parse_use_tree ()
}
else
{
- /* Due to aforementioned implementation issues, the trailing :: token is
- * consumed by the path, so it can not be used as a disambiguator.
- * NOPE, not true anymore - TODO what are the consequences of this? */
-
const_TokenPtr t = lexer.peek_token ();
+
switch (t->get_id ())
{
- case ASTERISK:
- // glob UseTree type
- lexer.skip_token ();
-
- return std::unique_ptr<AST::UseTreeGlob> (
- new AST::UseTreeGlob (AST::UseTreeGlob::PATH_PREFIXED,
- std::move (path), locus));
- case LEFT_CURLY: {
- // nested tree UseTree type
- lexer.skip_token ();
-
- std::vector<std::unique_ptr<AST::UseTree>> use_trees;
-
- // TODO: think of better control structure
- const_TokenPtr t = lexer.peek_token ();
- while (t->get_id () != RIGHT_CURLY)
- {
- std::unique_ptr<AST::UseTree> use_tree = parse_use_tree ();
- if (use_tree == nullptr)
- {
- break;
- }
-
- use_trees.push_back (std::move (use_tree));
-
- if (lexer.peek_token ()->get_id () != COMMA)
- break;
-
- lexer.skip_token ();
- t = lexer.peek_token ();
- }
-
- // skip end curly delimiter
- if (!skip_token (RIGHT_CURLY))
- {
- // skip after somewhere?
- return nullptr;
- }
-
- return std::unique_ptr<AST::UseTreeList> (
- new AST::UseTreeList (AST::UseTreeList::PATH_PREFIXED,
- std::move (path), std::move (use_trees),
- locus));
- }
- case AS: {
+ case AS:
+ {
// rebind UseTree type
lexer.skip_token ();
@@ -2884,16 +2853,72 @@ Parser<ManagedTokenSource>::parse_use_tree ()
// don't skip semicolon - handled in parse_use_tree
// lexer.skip_token();
-
- return std::unique_ptr<AST::UseTreeRebind> (
- new AST::UseTreeRebind (AST::UseTreeRebind::NONE, std::move (path),
- locus));
case COMMA:
case RIGHT_CURLY:
// this may occur in recursive calls - assume it is ok and ignore it
return std::unique_ptr<AST::UseTreeRebind> (
new AST::UseTreeRebind (AST::UseTreeRebind::NONE, std::move (path),
locus));
+ case SCOPE_RESOLUTION:
+ // keep going
+ break;
+ default:
+ add_error (Error (t->get_locus (),
+ "unexpected token %qs in use tree with valid path",
+ t->get_token_description ()));
+ return nullptr;
+ }
+
+ skip_token ();
+ t = lexer.peek_token ();
+
+ switch (t->get_id ())
+ {
+ case ASTERISK:
+ // glob UseTree type
+ lexer.skip_token ();
+
+ return std::unique_ptr<AST::UseTreeGlob> (
+ new AST::UseTreeGlob (AST::UseTreeGlob::PATH_PREFIXED,
+ std::move (path), locus));
+ case LEFT_CURLY:
+ {
+ // nested tree UseTree type
+ lexer.skip_token ();
+
+ std::vector<std::unique_ptr<AST::UseTree>> use_trees;
+
+ // TODO: think of better control structure
+ const_TokenPtr t = lexer.peek_token ();
+ while (t->get_id () != RIGHT_CURLY)
+ {
+ std::unique_ptr<AST::UseTree> use_tree = parse_use_tree ();
+ if (use_tree == nullptr)
+ {
+ break;
+ }
+
+ use_trees.push_back (std::move (use_tree));
+
+ if (lexer.peek_token ()->get_id () != COMMA)
+ break;
+
+ lexer.skip_token ();
+ t = lexer.peek_token ();
+ }
+
+ // skip end curly delimiter
+ if (!skip_token (RIGHT_CURLY))
+ {
+ // skip after somewhere?
+ return nullptr;
+ }
+
+ return std::unique_ptr<AST::UseTreeList> (
+ new AST::UseTreeList (AST::UseTreeList::PATH_PREFIXED,
+ std::move (path), std::move (use_trees),
+ locus));
+ }
default:
add_error (Error (t->get_locus (),
"unexpected token %qs in use tree with valid path",
@@ -3100,7 +3125,8 @@ Parser<ManagedTokenSource>::parse_generic_param (EndTokenPred is_end_token)
switch (token->get_id ())
{
- case LIFETIME: {
+ case LIFETIME:
+ {
auto lifetime = parse_lifetime (false);
if (!lifetime)
{
@@ -3126,7 +3152,8 @@ Parser<ManagedTokenSource>::parse_generic_param (EndTokenPred is_end_token)
std::move (outer_attrs), token->get_locus ()));
break;
}
- case IDENTIFIER: {
+ case IDENTIFIER:
+ {
auto type_ident = token->get_str ();
lexer.skip_token ();
@@ -3161,7 +3188,8 @@ Parser<ManagedTokenSource>::parse_generic_param (EndTokenPred is_end_token)
std::move (outer_attrs)));
break;
}
- case CONST: {
+ case CONST:
+ {
lexer.skip_token ();
auto name_token = expect_token (IDENTIFIER);
@@ -3345,7 +3373,8 @@ Parser<ManagedTokenSource>::parse_lifetime_params (EndTokenPred is_end_token)
/* Parses lifetime generic parameters (objects). Will also consume any
* trailing comma. No extra checks for end token.
- * TODO: is this best solution? implements most of the same algorithm. */
+ * TODO: is this best solution? implements most of the same algorithm.
+ * TODO: seems to be unused, remove? */
template <typename ManagedTokenSource>
std::vector<AST::LifetimeParam>
Parser<ManagedTokenSource>::parse_lifetime_params_objs ()
@@ -3363,7 +3392,7 @@ Parser<ManagedTokenSource>::parse_lifetime_params_objs ()
break;
}
- 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;
@@ -4356,7 +4385,8 @@ Parser<ManagedTokenSource>::parse_struct (AST::Visibility vis,
const_TokenPtr t = lexer.peek_token ();
switch (t->get_id ())
{
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// struct with body
// skip curly bracket
@@ -4759,7 +4789,8 @@ Parser<ManagedTokenSource>::parse_enum_item ()
const_TokenPtr t = lexer.peek_token ();
switch (t->get_id ())
{
- case LEFT_PAREN: {
+ case LEFT_PAREN:
+ {
// tuple enum item
lexer.skip_token ();
@@ -4780,7 +4811,8 @@ Parser<ManagedTokenSource>::parse_enum_item ()
std::move (item_name), std::move (vis), std::move (tuple_fields),
std::move (outer_attrs), item_name_tok->get_locus ()));
}
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// struct enum item
lexer.skip_token ();
@@ -4797,7 +4829,8 @@ Parser<ManagedTokenSource>::parse_enum_item ()
std::move (item_name), std::move (vis), std::move (struct_fields),
std::move (outer_attrs), item_name_tok->get_locus ()));
}
- case EQUAL: {
+ case EQUAL:
+ {
// discriminant enum item
lexer.skip_token ();
@@ -5450,7 +5483,8 @@ Parser<ManagedTokenSource>::parse_inherent_impl_item ()
case SUPER:
case SELF:
case CRATE:
- case PUB: {
+ case PUB:
+ {
// visibility, so not a macro invocation semi - must be constant,
// function, or method
AST::Visibility vis = parse_visibility ();
@@ -5581,7 +5615,8 @@ Parser<ManagedTokenSource>::parse_inherent_impl_function_or_method (
// param
auto initial_param = parse_self_param ();
- if (!initial_param.has_value () && initial_param.error () != NOT_SELF)
+ if (!initial_param.has_value ()
+ && initial_param.error () != ParseSelfError::NOT_SELF)
return nullptr;
/* FIXME: ensure that self param doesn't accidently consume tokens for a
@@ -5780,7 +5815,8 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method (
// param
auto initial_param = parse_self_param ();
- if (!initial_param.has_value () && initial_param.error () != NOT_SELF)
+ if (!initial_param.has_value ()
+ && initial_param.error () != ParseSelfError::NOT_SELF)
return nullptr;
// FIXME: ensure that self param doesn't accidently consume tokens for a
@@ -5964,7 +6000,8 @@ Parser<ManagedTokenSource>::parse_external_item ()
{
case IDENTIFIER:
return parse_macro_invocation_semi (outer_attrs);
- case STATIC_KW: {
+ case STATIC_KW:
+ {
// parse extern static item
lexer.skip_token ();
@@ -6261,7 +6298,8 @@ Parser<ManagedTokenSource>::parse_generic_arg ()
switch (tok->get_id ())
{
- case IDENTIFIER: {
+ case IDENTIFIER:
+ {
// This is a bit of a weird situation: With an identifier token, we
// could either have a valid type or a macro (FIXME: anything else?). So
// we need one bit of lookahead to differentiate if this is really
@@ -6309,9 +6347,10 @@ Parser<ManagedTokenSource>::parse_generic_arg ()
case FALSE_LITERAL:
expr = parse_literal_expr ();
break;
- // FIXME: Because of this, error reporting is garbage for const generic
- // parameter's default values
- default: {
+ // FIXME: Because of this, error reporting is garbage for const generic
+ // parameter's default values
+ default:
+ {
auto type = parse_type ();
// FIXME: Find a better way to do this?
if (type)
@@ -6510,7 +6549,8 @@ Parser<ManagedTokenSource>::parse_type_path_segment ()
switch (t->get_id ())
{
case LEFT_SHIFT:
- case LEFT_ANGLE: {
+ case LEFT_ANGLE:
+ {
// parse generic args
AST::GenericArgs generic_args = parse_path_generic_args ();
@@ -6519,7 +6559,8 @@ Parser<ManagedTokenSource>::parse_type_path_segment ()
has_separating_scope_resolution,
std::move (generic_args), locus));
}
- case LEFT_PAREN: {
+ case LEFT_PAREN:
+ {
// parse type path function
AST::TypePathFunction type_path_function
= parse_type_path_function (locus);
@@ -7068,16 +7109,14 @@ Parser<ManagedTokenSource>::parse_expr_stmt (AST::AttrVec outer_attrs,
case SELF:
case SELF_ALIAS:
case DOLLAR_SIGN:
- case SCOPE_RESOLUTION: {
+ case SCOPE_RESOLUTION:
+ {
AST::PathInExpression path = parse_path_in_expression ();
std::unique_ptr<AST::Expr> null_denotation;
if (lexer.peek_token ()->get_id () == EXCLAM)
{
- // Bind a reference to avoid -Wredundant-move on post-P1825R0
- // compilers. Change to non-reference type and remove the moves
- // below once C++20 is required to build gcc.
- std::unique_ptr<AST::MacroInvocation> &&invoc
+ std::unique_ptr<AST::MacroInvocation> invoc
= parse_macro_invocation_partial (std::move (path),
std::move (outer_attrs));
@@ -7085,7 +7124,7 @@ Parser<ManagedTokenSource>::parse_expr_stmt (AST::AttrVec outer_attrs,
{
invoc->add_semicolon ();
// Macro invocation with semicolon.
- return std::move (invoc);
+ return invoc;
}
TokenId after_macro = lexer.peek_token ()->get_id ();
@@ -7093,14 +7132,14 @@ Parser<ManagedTokenSource>::parse_expr_stmt (AST::AttrVec outer_attrs,
if (restrictions.allow_close_after_expr_stmt
&& (after_macro == RIGHT_PAREN || after_macro == RIGHT_CURLY
|| after_macro == RIGHT_SQUARE))
- return std::move (invoc);
+ return invoc;
if (invoc->get_invoc_data ().get_delim_tok_tree ().get_delim_type ()
== AST::CURLY
&& after_macro != DOT && after_macro != QUESTION_MARK)
{
rust_debug ("braced macro statement");
- return std::move (invoc);
+ return invoc;
}
null_denotation = std::move (invoc);
@@ -7238,6 +7277,51 @@ Parser<ManagedTokenSource>::parse_block_expr (
std::move (label), locus, end_locus));
}
+/* Parse an anonymous const expression. This can be a regular const expression
+ * or an underscore for deferred const inference */
+template <typename ManagedTokenSource>
+tl::expected<AST::AnonConst, AnonConstError>
+Parser<ManagedTokenSource>::parse_anon_const ()
+{
+ auto current = lexer.peek_token ();
+ auto locus = current->get_locus ();
+
+ // Special case deferred inference constants
+ if (maybe_skip_token (UNDERSCORE))
+ return AST::AnonConst (locus);
+
+ auto expr = parse_expr ();
+
+ if (!expr)
+ return tl::make_unexpected (AnonConstError::InvalidSizeExpr);
+
+ return AST::AnonConst (std::move (expr), locus);
+}
+
+/* Parse a "const block", a block preceded by the `const` keyword whose
+ * statements can be const evaluated and used in constant contexts */
+template <typename ManagedTokenSource>
+std::unique_ptr<AST::ConstBlock>
+Parser<ManagedTokenSource>::parse_const_block_expr (AST::AttrVec outer_attrs,
+ location_t locus)
+{
+ auto block = parse_block_expr ();
+
+ if (!block)
+ {
+ add_error (Error (locus, "failed to parse inner block in const block"));
+ skip_after_end_block ();
+
+ return nullptr;
+ }
+
+ auto block_locus = block->get_locus ();
+
+ return std::make_unique<AST::ConstBlock> (AST::AnonConst (std::move (block),
+ block_locus),
+ locus, std::move (outer_attrs));
+}
+
/* Parses a "grouped" expression (expression in parentheses), used to control
* precedence. */
template <typename ManagedTokenSource>
@@ -7518,6 +7602,34 @@ Parser<ManagedTokenSource>::parse_return_expr (AST::AttrVec outer_attrs,
locus));
}
+// Parses a try expression.
+template <typename ManagedTokenSource>
+std::unique_ptr<AST::TryExpr>
+Parser<ManagedTokenSource>::parse_try_expr (AST::AttrVec outer_attrs,
+ location_t pratt_parsed_loc)
+{
+ location_t locus = pratt_parsed_loc;
+ if (locus == UNKNOWN_LOCATION)
+ {
+ locus = lexer.peek_token ()->get_locus ();
+ skip_token (TRY);
+ }
+
+ std::unique_ptr<AST::BlockExpr> block_expr = parse_block_expr ();
+
+ if (!block_expr)
+ {
+ Error error (lexer.peek_token ()->get_locus (),
+ "failed to parse try block expression");
+ add_error (std::move (error));
+
+ return nullptr;
+ }
+
+ return std::unique_ptr<AST::TryExpr> (
+ new AST::TryExpr (std::move (block_expr), std::move (outer_attrs), locus));
+}
+
/* Parses a break expression (including any label to break to AND any return
* expression). */
template <typename ManagedTokenSource>
@@ -7675,7 +7787,8 @@ Parser<ManagedTokenSource>::parse_if_expr (AST::AttrVec outer_attrs,
const_TokenPtr t = lexer.peek_token ();
switch (t->get_id ())
{
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// double selection - else
// parse else block expr (required)
std::unique_ptr<AST::BlockExpr> else_body = parse_block_expr ();
@@ -7696,7 +7809,8 @@ Parser<ManagedTokenSource>::parse_if_expr (AST::AttrVec outer_attrs,
std::move (else_body),
std::move (outer_attrs), locus));
}
- case IF: {
+ case IF:
+ {
// multiple selection - else if or else if let
// branch on whether next token is 'let' or not
if (lexer.peek_token (1)->get_id () == LET)
@@ -7857,7 +7971,8 @@ Parser<ManagedTokenSource>::parse_if_let_expr (AST::AttrVec outer_attrs,
const_TokenPtr t = lexer.peek_token ();
switch (t->get_id ())
{
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// double selection - else
// parse else block expr (required)
std::unique_ptr<AST::BlockExpr> else_body = parse_block_expr ();
@@ -7879,7 +7994,8 @@ Parser<ManagedTokenSource>::parse_if_let_expr (AST::AttrVec outer_attrs,
std::move (else_body),
std::move (outer_attrs), locus));
}
- case IF: {
+ case IF:
+ {
// multiple selection - else if or else if let
// branch on whether next token is 'let' or not
if (lexer.peek_token (1)->get_id () == LET)
@@ -8931,7 +9047,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors)
// slice type or array type - requires further disambiguation
return parse_slice_or_array_type ();
case LEFT_SHIFT:
- case LEFT_ANGLE: {
+ case LEFT_ANGLE:
+ {
// qualified path in type
AST::QualifiedPathInType path = parse_qualified_path_in_type ();
if (path.is_error ())
@@ -8960,7 +9077,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors)
case LOGICAL_AND:
// reference type
return parse_reference_type ();
- case LIFETIME: {
+ case LIFETIME:
+ {
/* probably a lifetime bound, so probably type param bounds in
* TraitObjectType */
std::vector<std::unique_ptr<AST::TypeParamBound>> bounds
@@ -8976,7 +9094,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors)
case SELF_ALIAS:
case CRATE:
case DOLLAR_SIGN:
- case SCOPE_RESOLUTION: {
+ case SCOPE_RESOLUTION:
+ {
// macro invocation or type path - requires further disambiguation.
/* for parsing path component of each rule, perhaps parse it as a
* typepath and attempt conversion to simplepath if a trailing '!' is
@@ -9006,7 +9125,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors)
t = lexer.peek_token ();
switch (t->get_id ())
{
- case EXCLAM: {
+ case EXCLAM:
+ {
// macro invocation
// convert to simple path
AST::SimplePath macro_path = path.as_simple_path ();
@@ -9032,7 +9152,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors)
std::move (tok_tree)),
{}, locus);
}
- case PLUS: {
+ case PLUS:
+ {
// type param bounds
std::vector<std::unique_ptr<AST::TypeParamBound>> bounds;
@@ -9117,14 +9238,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors)
t = lexer.peek_token ();
if (t->get_id () != PLUS)
{
- // convert trait bound to value object
- AST::TraitBound value_bound (*initial_bound);
-
- // DEBUG: removed as unique ptr, so should auto-delete
- // delete initial_bound;
-
return std::unique_ptr<AST::ImplTraitTypeOneBound> (
- new AST::ImplTraitTypeOneBound (std::move (value_bound),
+ new AST::ImplTraitTypeOneBound (std::move (initial_bound),
locus));
}
@@ -9152,7 +9267,8 @@ Parser<ManagedTokenSource>::parse_type (bool save_errors)
new AST::ImplTraitType (std::move (bounds), locus));
}
case DYN:
- case QUESTION_MARK: {
+ case QUESTION_MARK:
+ {
// either TraitObjectType or TraitObjectTypeOneBound
bool has_dyn = false;
if (t->get_id () == DYN)
@@ -9405,7 +9521,8 @@ Parser<ManagedTokenSource>::parse_for_prefixed_type ()
case SELF:
case SELF_ALIAS:
case CRATE:
- case DOLLAR_SIGN: {
+ case DOLLAR_SIGN:
+ {
// path, so trait type
// parse type path to finish parsing trait bound
@@ -9751,13 +9868,15 @@ Parser<ManagedTokenSource>::parse_slice_or_array_type ()
return std::unique_ptr<AST::SliceType> (
new AST::SliceType (std::move (inner_type), locus));
- case SEMICOLON: {
+ case SEMICOLON:
+ {
// array type
lexer.skip_token ();
// parse required array size expression
- std::unique_ptr<AST::Expr> size = parse_expr ();
- if (size == nullptr)
+ auto size = parse_anon_const ();
+
+ if (!size)
{
Error error (lexer.peek_token ()->get_locus (),
"failed to parse size expression in array type");
@@ -9772,7 +9891,8 @@ Parser<ManagedTokenSource>::parse_slice_or_array_type ()
}
return std::unique_ptr<AST::ArrayType> (
- new AST::ArrayType (std::move (inner_type), std::move (size), locus));
+ new AST::ArrayType (std::move (inner_type), std::move (*size),
+ locus));
}
default:
// error
@@ -9802,7 +9922,8 @@ Parser<ManagedTokenSource>::parse_type_no_bounds ()
// slice type or array type - requires further disambiguation
return parse_slice_or_array_type ();
case LEFT_SHIFT:
- case LEFT_ANGLE: {
+ case LEFT_ANGLE:
+ {
// qualified path in type
AST::QualifiedPathInType path = parse_qualified_path_in_type ();
if (path.is_error ())
@@ -9843,7 +9964,8 @@ Parser<ManagedTokenSource>::parse_type_no_bounds ()
case SELF_ALIAS:
case CRATE:
case DOLLAR_SIGN:
- case SCOPE_RESOLUTION: {
+ case SCOPE_RESOLUTION:
+ {
// macro invocation or type path - requires further disambiguation.
/* for parsing path component of each rule, perhaps parse it as a
* typepath and attempt conversion to simplepath if a trailing '!' is
@@ -9871,7 +9993,8 @@ Parser<ManagedTokenSource>::parse_type_no_bounds ()
t = lexer.peek_token ();
switch (t->get_id ())
{
- case EXCLAM: {
+ case EXCLAM:
+ {
// macro invocation
// convert to simple path
AST::SimplePath macro_path = path.as_simple_path ();
@@ -9955,14 +10078,12 @@ Parser<ManagedTokenSource>::parse_type_no_bounds ()
return nullptr;
}
- // convert trait bound to value object
- AST::TraitBound value_bound (*initial_bound);
-
return std::unique_ptr<AST::ImplTraitTypeOneBound> (
- new AST::ImplTraitTypeOneBound (std::move (value_bound), locus));
+ new AST::ImplTraitTypeOneBound (std::move (initial_bound), locus));
}
case DYN:
- case QUESTION_MARK: {
+ case QUESTION_MARK:
+ {
// either TraitObjectTypeOneBound
bool has_dyn = false;
if (t->get_id () == DYN)
@@ -10303,7 +10424,8 @@ Parser<ManagedTokenSource>::parse_range_pattern_bound ()
case SELF_ALIAS:
case CRATE:
case SCOPE_RESOLUTION:
- case DOLLAR_SIGN: {
+ case DOLLAR_SIGN:
+ {
// path in expression
AST::PathInExpression path = parse_path_in_expression ();
if (path.is_error ())
@@ -10319,7 +10441,8 @@ Parser<ManagedTokenSource>::parse_range_pattern_bound ()
new AST::RangePatternBoundPath (std::move (path)));
}
case LEFT_SHIFT:
- case LEFT_ANGLE: {
+ case LEFT_ANGLE:
+ {
// qualified path in expression
AST::QualifiedPathInExpression path
= parse_qualified_path_in_expression ();
@@ -10464,7 +10587,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt ()
// slice pattern
return parse_slice_pattern ();
case LEFT_SHIFT:
- case LEFT_ANGLE: {
+ case LEFT_ANGLE:
+ {
// qualified path in expression or qualified range pattern bound
AST::QualifiedPathInExpression path
= parse_qualified_path_in_expression ();
@@ -10500,7 +10624,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt ()
case SELF_ALIAS:
case CRATE:
case SCOPE_RESOLUTION:
- case DOLLAR_SIGN: {
+ case DOLLAR_SIGN:
+ {
// path in expression or range pattern bound
AST::PathInExpression path = parse_path_in_expression ();
@@ -10509,7 +10634,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt ()
{
case DOT_DOT_EQ:
case DOT_DOT:
- case ELLIPSIS: {
+ case ELLIPSIS:
+ {
// qualified range pattern bound, so parse rest of range pattern
AST::RangeKind kind = AST::tokenid_to_rangekind (next->get_id ());
lexer.skip_token ();
@@ -10527,7 +10653,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt ()
case EXCLAM:
return parse_macro_invocation_partial (std::move (path),
AST::AttrVec ());
- case LEFT_PAREN: {
+ case LEFT_PAREN:
+ {
// tuple struct
lexer.skip_token ();
@@ -10552,7 +10679,8 @@ Parser<ManagedTokenSource>::parse_pattern_no_alt ()
new AST::TupleStructPattern (std::move (path),
std::move (items)));
}
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// struct
lexer.skip_token ();
@@ -10722,7 +10850,8 @@ Parser<ManagedTokenSource>::parse_grouped_or_tuple_pattern ()
return std::unique_ptr<AST::GroupedPattern> (
new AST::GroupedPattern (std::move (initial_pattern), paren_locus));
- case COMMA: {
+ case COMMA:
+ {
// tuple pattern
lexer.skip_token ();
@@ -10835,27 +10964,47 @@ Parser<ManagedTokenSource>::parse_slice_pattern ()
{
location_t square_locus = lexer.peek_token ()->get_locus ();
std::vector<std::unique_ptr<AST::Pattern>> patterns;
+ tl::optional<std::vector<std::unique_ptr<AST::Pattern>>> upper_patterns
+ = tl::nullopt;
+
+ // lambda function to determine which vector to push new patterns into
+ auto get_pattern_ref
+ = [&] () -> std::vector<std::unique_ptr<AST::Pattern>> & {
+ return upper_patterns.has_value () ? upper_patterns.value () : patterns;
+ };
+
skip_token (LEFT_SQUARE);
if (lexer.peek_token ()->get_id () == RIGHT_SQUARE)
{
skip_token (RIGHT_SQUARE);
+ std::unique_ptr<AST::SlicePatternItemsNoRest> items (
+ new AST::SlicePatternItemsNoRest (std::move (patterns)));
return std::unique_ptr<AST::SlicePattern> (
- new AST::SlicePattern (std::move (patterns), square_locus));
+ new AST::SlicePattern (std::move (items), square_locus));
}
// parse initial pattern (required)
- std::unique_ptr<AST::Pattern> initial_pattern = parse_pattern ();
- if (initial_pattern == nullptr)
+ if (lexer.peek_token ()->get_id () == DOT_DOT)
{
- Error error (lexer.peek_token ()->get_locus (),
- "failed to parse initial pattern in slice pattern");
- add_error (std::move (error));
-
- return nullptr;
+ lexer.skip_token ();
+ upper_patterns = std::vector<std::unique_ptr<AST::Pattern>> ();
}
+ else
+ {
+ // Not a rest pattern `..`, parse normally
+ std::unique_ptr<AST::Pattern> initial_pattern = parse_pattern ();
+ if (initial_pattern == nullptr)
+ {
+ Error error (lexer.peek_token ()->get_locus (),
+ "failed to parse initial pattern in slice pattern");
+ add_error (std::move (error));
- patterns.push_back (std::move (initial_pattern));
+ return nullptr;
+ }
+
+ patterns.push_back (std::move (initial_pattern));
+ }
const_TokenPtr t = lexer.peek_token ();
while (t->get_id () == COMMA)
@@ -10866,6 +11015,23 @@ Parser<ManagedTokenSource>::parse_slice_pattern ()
if (lexer.peek_token ()->get_id () == RIGHT_SQUARE)
break;
+ if (lexer.peek_token ()->get_id () == DOT_DOT)
+ {
+ if (upper_patterns.has_value ())
+ {
+ // DOT_DOT has been parsed before
+ Error error (lexer.peek_token ()->get_locus (), "%s",
+ "`..` can only be used once per slice pattern");
+ add_error (std::move (error));
+
+ return nullptr;
+ }
+ upper_patterns = std::vector<std::unique_ptr<AST::Pattern>> ();
+ lexer.skip_token ();
+ t = lexer.peek_token ();
+ continue;
+ }
+
// parse pattern (required)
std::unique_ptr<AST::Pattern> pattern = parse_pattern ();
if (pattern == nullptr)
@@ -10876,7 +11042,7 @@ Parser<ManagedTokenSource>::parse_slice_pattern ()
return nullptr;
}
- patterns.push_back (std::move (pattern));
+ get_pattern_ref ().push_back (std::move (pattern));
t = lexer.peek_token ();
}
@@ -10886,8 +11052,21 @@ Parser<ManagedTokenSource>::parse_slice_pattern ()
return nullptr;
}
+ if (upper_patterns.has_value ())
+ {
+ // Slice pattern with rest
+ std::unique_ptr<AST::SlicePatternItemsHasRest> items (
+ new AST::SlicePatternItemsHasRest (
+ std::move (patterns), std::move (upper_patterns.value ())));
+ return std::unique_ptr<AST::SlicePattern> (
+ new AST::SlicePattern (std::move (items), square_locus));
+ }
+
+ // Rest-less slice pattern
+ std::unique_ptr<AST::SlicePatternItemsNoRest> items (
+ new AST::SlicePatternItemsNoRest (std::move (patterns)));
return std::unique_ptr<AST::SlicePattern> (
- new AST::SlicePattern (std::move (patterns), square_locus));
+ new AST::SlicePattern (std::move (items), square_locus));
}
/* Parses an identifier pattern (pattern that binds a value matched to a
@@ -10979,7 +11158,8 @@ Parser<ManagedTokenSource>::parse_ident_leading_pattern ()
{
case EXCLAM:
return parse_macro_invocation_partial (std::move (path), AST::AttrVec ());
- case LEFT_PAREN: {
+ case LEFT_PAREN:
+ {
// tuple struct
lexer.skip_token ();
@@ -11012,7 +11192,8 @@ Parser<ManagedTokenSource>::parse_ident_leading_pattern ()
return std::unique_ptr<AST::TupleStructPattern> (
new AST::TupleStructPattern (std::move (path), std::move (items)));
}
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// struct
lexer.skip_token ();
@@ -11033,7 +11214,8 @@ Parser<ManagedTokenSource>::parse_ident_leading_pattern ()
}
case DOT_DOT_EQ:
case DOT_DOT:
- case ELLIPSIS: {
+ case ELLIPSIS:
+ {
// range
AST::RangeKind kind
= AST::tokenid_to_rangekind (lexer.peek_token ()->get_id ());
@@ -11050,7 +11232,8 @@ Parser<ManagedTokenSource>::parse_ident_leading_pattern ()
std::move (upper_bound), kind,
t->get_locus ()));
}
- case PATTERN_BIND: {
+ case PATTERN_BIND:
+ {
// only allow on single-segment paths
if (path.is_single_segment ())
{
@@ -11188,7 +11371,8 @@ Parser<ManagedTokenSource>::parse_tuple_struct_items ()
case RIGHT_PAREN:
return std::unique_ptr<AST::TupleStructItemsNoRange> (
new AST::TupleStructItemsNoRange (std::move (lower_patterns)));
- case DOT_DOT: {
+ case DOT_DOT:
+ {
// has an upper range that must be parsed separately
lexer.skip_token ();
@@ -11308,7 +11492,8 @@ Parser<ManagedTokenSource>::parse_struct_pattern_field_partial (
const_TokenPtr t = lexer.peek_token ();
switch (t->get_id ())
{
- case INT_LITERAL: {
+ case INT_LITERAL:
+ {
// tuple index
std::string index_str = t->get_str ();
int index = atoi (index_str.c_str ());
@@ -11342,7 +11527,8 @@ Parser<ManagedTokenSource>::parse_struct_pattern_field_partial (
// branch on next token
switch (lexer.peek_token (1)->get_id ())
{
- case COLON: {
+ case COLON:
+ {
// identifier-pattern
Identifier ident{t};
lexer.skip_token ();
@@ -11367,7 +11553,8 @@ Parser<ManagedTokenSource>::parse_struct_pattern_field_partial (
t->get_locus ()));
}
case COMMA:
- case RIGHT_CURLY: {
+ case RIGHT_CURLY:
+ {
// identifier only
Identifier ident = {t};
lexer.skip_token ();
@@ -11386,7 +11573,8 @@ Parser<ManagedTokenSource>::parse_struct_pattern_field_partial (
return nullptr;
}
case REF:
- case MUT: {
+ case MUT:
+ {
// only identifier
bool has_ref = false;
if (t->get_id () == REF)
@@ -11458,7 +11646,8 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr ()
t = lexer.peek_token ();
switch (t->get_id ())
{
- case LET: {
+ case LET:
+ {
// let statement
std::unique_ptr<AST::LetStmt> stmt (
parse_let_stmt (std::move (outer_attrs)));
@@ -11476,42 +11665,48 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr ()
case STATIC_KW:
case AUTO:
case TRAIT:
- case IMPL: {
+ case IMPL:
+ {
std::unique_ptr<AST::VisItem> item (
parse_vis_item (std::move (outer_attrs)));
return ExprOrStmt (std::move (item));
}
- /* TODO: implement union keyword but not really because of
- * context-dependence crappy hack way to parse a union written below to
- * separate it from the good code. */
- // case UNION:
- case UNSAFE: { // maybe - unsafe traits are a thing
+ /* TODO: implement union keyword but not really because of
+ * context-dependence crappy hack way to parse a union written below to
+ * separate it from the good code. */
+ // case UNION:
+ case UNSAFE:
+ { // maybe - unsafe traits are a thing
/* if any of these (should be all possible VisItem prefixes), parse a
* VisItem - can't parse item because would require reparsing outer
* attributes */
const_TokenPtr t2 = lexer.peek_token (1);
switch (t2->get_id ())
{
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
// unsafe block: parse as expression
expr = parse_expr (std::move (outer_attrs), restrictions);
break;
}
case AUTO:
- case TRAIT: {
+ case TRAIT:
+ {
// unsafe trait
std::unique_ptr<AST::VisItem> item (
parse_vis_item (std::move (outer_attrs)));
return ExprOrStmt (std::move (item));
}
case EXTERN_KW:
- case FN_KW: {
+ case FN_KW:
+ {
// unsafe function
std::unique_ptr<AST::VisItem> item (
parse_vis_item (std::move (outer_attrs)));
return ExprOrStmt (std::move (item));
}
- case IMPL: {
+ case IMPL:
+ {
// unsafe trait impl
std::unique_ptr<AST::VisItem> item (
parse_vis_item (std::move (outer_attrs)));
@@ -11556,7 +11751,8 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr ()
case SELF_ALIAS:
case CRATE:
case SCOPE_RESOLUTION:
- case DOLLAR_SIGN: {
+ case DOLLAR_SIGN:
+ {
AST::PathInExpression path = parse_path_in_expression ();
std::unique_ptr<AST::Expr> null_denotation;
@@ -11680,7 +11876,8 @@ Parser<ManagedTokenSource>::parse_struct_expr_field ()
std::move (outer_attrs),
t->get_locus ()));
}
- case INT_LITERAL: {
+ case INT_LITERAL:
+ {
// parse tuple index field
int index = atoi (t->get_str ().c_str ());
lexer.skip_token ();
@@ -11725,11 +11922,12 @@ Parser<ManagedTokenSource>::parse_struct_expr_field ()
}
// "Unexpected token" panic mode - flags gcc error at unexpected token
+// TODO: seems to be unused, remove?
template <typename ManagedTokenSource>
void
Parser<ManagedTokenSource>::unexpected_token (const_TokenPtr t)
{
- Error error (t->get_locus (), "unexpected token %qs\n",
+ Error error (t->get_locus (), "unexpected token %qs",
t->get_token_description ());
add_error (std::move (error));
}
@@ -11920,7 +12118,7 @@ Parser<ManagedTokenSource>::skip_after_end_attribute ()
{
const_TokenPtr t = lexer.peek_token ();
- while (t->get_id () != RIGHT_SQUARE)
+ while (t->get_id () != RIGHT_SQUARE && t->get_id () != END_OF_FILE)
{
lexer.skip_token ();
t = lexer.peek_token ();
@@ -12050,7 +12248,8 @@ Parser<ManagedTokenSource>::null_denotation (const_TokenPtr tok,
case SELF_ALIAS:
case DOLLAR_SIGN:
case CRATE:
- case SUPER: {
+ case SUPER:
+ {
// DEBUG
rust_debug ("beginning null denotation identifier handling");
@@ -12061,7 +12260,8 @@ Parser<ManagedTokenSource>::null_denotation (const_TokenPtr tok,
return null_denotation_path (std::move (path), std::move (outer_attrs),
restrictions);
}
- case SCOPE_RESOLUTION: {
+ case SCOPE_RESOLUTION:
+ {
// TODO: fix: this is for global paths, i.e. std::string::whatever
Error error (tok->get_locus (),
"found null denotation scope resolution operator, and "
@@ -12103,7 +12303,8 @@ Parser<ManagedTokenSource>::null_denotation_path (
// macro
return parse_macro_invocation_partial (std::move (path),
std::move (outer_attrs));
- case LEFT_CURLY: {
+ case LEFT_CURLY:
+ {
bool not_a_block = lexer.peek_token (1)->get_id () == IDENTIFIER
&& (lexer.peek_token (2)->get_id () == COMMA
|| (lexer.peek_token (2)->get_id () == COLON
@@ -12179,7 +12380,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
{
// FIXME: Handle in null_denotation_path?
case LEFT_SHIFT:
- case LEFT_ANGLE: {
+ case LEFT_ANGLE:
+ {
// qualified path
// HACK: add outer attrs to path
AST::QualifiedPathInExpression path
@@ -12237,23 +12439,24 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
return parse_grouped_or_tuple_expr (std::move (outer_attrs),
tok->get_locus ());
- /*case PLUS: { // unary plus operator
- // invoke parse_expr recursively with appropriate priority, etc. for
- below AST::Expr* expr = parse_expr(LBP_UNARY_PLUS);
+ /*case PLUS: { // unary plus operator
+ // invoke parse_expr recursively with appropriate priority, etc. for
+ below AST::Expr* expr = parse_expr(LBP_UNARY_PLUS);
- if (expr == nullptr)
- return nullptr;
- // can only apply to integer and float expressions
- if (expr->get_type() != integer_type_node || expr->get_type() !=
- float_type_node) { rust_error_at(tok->get_locus(), "operand of unary
- plus must be int or float but it is %s", print_type(expr->get_type()));
- return nullptr;
- }
+ if (expr == nullptr)
+ return nullptr;
+ // can only apply to integer and float expressions
+ if (expr->get_type() != integer_type_node || expr->get_type() !=
+ float_type_node) { rust_error_at(tok->get_locus(), "operand of unary
+ plus must be int or float but it is %s", print_type(expr->get_type()));
+ return nullptr;
+ }
- return Tree(expr, tok->get_locus());
- }*/
- // Rust has no unary plus operator
- case MINUS: { // unary minus
+ return Tree(expr, tok->get_locus());
+ }*/
+ // Rust has no unary plus operator
+ case MINUS:
+ { // unary minus
ParseRestrictions entered_from_unary;
entered_from_unary.entered_from_unary = true;
if (!restrictions.can_be_struct_expr)
@@ -12280,7 +12483,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
new AST::NegationExpr (std::move (expr), NegationOperator::NEGATE,
std::move (outer_attrs), tok->get_locus ()));
}
- case EXCLAM: { // logical or bitwise not
+ case EXCLAM:
+ { // logical or bitwise not
ParseRestrictions entered_from_unary;
entered_from_unary.entered_from_unary = true;
if (!restrictions.can_be_struct_expr)
@@ -12305,7 +12509,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
new AST::NegationExpr (std::move (expr), NegationOperator::NOT,
std::move (outer_attrs), tok->get_locus ()));
}
- case ASTERISK: {
+ case ASTERISK:
+ {
/* pointer dereference only - HACK: as struct expressions should
* always be value expressions, cannot be dereferenced */
ParseRestrictions entered_from_unary;
@@ -12318,7 +12523,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
new AST::DereferenceExpr (std::move (expr), std::move (outer_attrs),
tok->get_locus ()));
}
- case AMP: {
+ case AMP:
+ {
// (single) "borrow" expression - shared (mutable) or immutable
std::unique_ptr<AST::Expr> expr = nullptr;
Mutability mutability = Mutability::Imm;
@@ -12375,7 +12581,8 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
new AST::BorrowExpr (std::move (expr), mutability, raw_borrow, false,
std::move (outer_attrs), tok->get_locus ()));
}
- case LOGICAL_AND: {
+ case LOGICAL_AND:
+ {
// (double) "borrow" expression - shared (mutable) or immutable
std::unique_ptr<AST::Expr> expr = nullptr;
Mutability mutability = Mutability::Imm;
@@ -12414,6 +12621,9 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
case RETURN_KW:
// FIXME: is this really a null denotation expression?
return parse_return_expr (std::move (outer_attrs), tok->get_locus ());
+ case TRY:
+ // FIXME: is this really a null denotation expression?
+ return parse_try_expr (std::move (outer_attrs), tok->get_locus ());
case BREAK:
// FIXME: is this really a null denotation expression?
return parse_break_expr (std::move (outer_attrs), tok->get_locus ());
@@ -12469,6 +12679,9 @@ Parser<ManagedTokenSource>::null_denotation_not_path (
"use of %qs is not allowed on the right-side of an assignment",
tok->get_token_description ()));
return nullptr;
+ case CONST:
+ return parse_const_block_expr (std::move (outer_attrs),
+ tok->get_locus ());
default:
if (!restrictions.expr_can_be_null)
add_error (Error (tok->get_locus (),
@@ -12491,8 +12704,9 @@ Parser<ManagedTokenSource>::left_denotation (const_TokenPtr tok,
// Token passed in has already been skipped, so peek gives "next" token
switch (tok->get_id ())
{
- // FIXME: allow for outer attributes to be applied
- case QUESTION_MARK: {
+ // FIXME: allow for outer attributes to be applied
+ case QUESTION_MARK:
+ {
location_t left_locus = left->get_locus ();
// error propagation expression - unary postfix
return std::unique_ptr<AST::ErrorPropagationExpr> (
@@ -12746,7 +12960,8 @@ Parser<ManagedTokenSource>::left_denotation (const_TokenPtr tok,
"function - this should probably be handled elsewhere"));
return nullptr;
- case DOT: {
+ case DOT:
+ {
/* field expression or method call - relies on parentheses after next
* identifier or await if token after is "await" (unary postfix) or
* tuple index if token after is a decimal int literal */
@@ -14062,7 +14277,8 @@ Parser<ManagedTokenSource>::parse_struct_expr_struct_partial (
* algorithm should work too. As such, AST type not happening. */
case IDENTIFIER:
case HASH:
- case INT_LITERAL: {
+ case INT_LITERAL:
+ {
// struct with struct expr fields
// parse struct expr fields
@@ -14359,7 +14575,8 @@ Parser<ManagedTokenSource>::parse_closure_expr_pratt (const_TokenPtr tok,
case OR:
// no parameters, don't skip token
break;
- case PIPE: {
+ case PIPE:
+ {
// actually may have parameters
// don't skip token
const_TokenPtr t = lexer.peek_token ();
diff --git a/gcc/rust/parse/rust-parse.cc b/gcc/rust/parse/rust-parse.cc
index 43d15aa..860fd11 100644
--- a/gcc/rust/parse/rust-parse.cc
+++ b/gcc/rust/parse/rust-parse.cc
@@ -42,8 +42,7 @@ extract_module_path (const AST::AttrVec &inner_attrs,
{
rust_error_at (
path_attr.get_locus (),
- // Split the format string so that -Wformat-diag does not complain...
- "path attributes must contain a filename: '%s'", "#![path = \"file\"]");
+ "path attributes must contain a filename: %<#[path = \"file\"]%>");
return name;
}
@@ -67,8 +66,7 @@ extract_module_path (const AST::AttrVec &inner_attrs,
{
rust_error_at (
path_attr.get_locus (),
- // Split the format string so that -Wformat-diag does not complain...
- "path attributes must contain a filename: '%s'", "#[path = \"file\"]");
+ "path attributes must contain a filename: %<#[path = \"file\"]%>");
return name;
}
@@ -80,6 +78,15 @@ extract_module_path (const AST::AttrVec &inner_attrs,
// a character that is not an equal sign or whitespace
auto filename_begin = path_value.find_first_not_of ("=\t ");
+ // If the path consists of only whitespace, then we have an error
+ if (filename_begin == std::string::npos)
+ {
+ rust_error_at (
+ path_attr.get_locus (),
+ "path attributes must contain a filename: %<#[path = \"file\"]%>");
+ return name;
+ }
+
auto path = path_value.substr (filename_begin);
// On windows, the path might mix '/' and '\' separators. Replace the
@@ -144,10 +151,9 @@ peculiar_fragment_match_compatible_fragment (
= contains (fragment_follow_set[last_spec.get_kind ()], spec.get_kind ());
if (!is_valid)
- rust_error_at (
- match_locus,
- "fragment specifier %qs is not allowed after %qs fragments",
- spec.as_string ().c_str (), last_spec.as_string ().c_str ());
+ rust_error_at (match_locus,
+ "fragment specifier %qs is not allowed after %qs fragments",
+ spec.as_string ().c_str (), last_spec.as_string ().c_str ());
return is_valid;
}
@@ -244,7 +250,8 @@ peculiar_fragment_match_compatible (const AST::MacroMatchFragment &last_match,
// the error.
switch (match.get_macro_match_type ())
{
- case AST::MacroMatch::Tok: {
+ case AST::MacroMatch::Tok:
+ {
auto tok = static_cast<const AST::Token *> (&match);
if (contains (allowed_toks, tok->get_id ()))
return true;
@@ -254,7 +261,8 @@ peculiar_fragment_match_compatible (const AST::MacroMatchFragment &last_match,
break;
}
break;
- case AST::MacroMatch::Repetition: {
+ case AST::MacroMatch::Repetition:
+ {
auto repetition
= static_cast<const AST::MacroMatchRepetition *> (&match);
auto &matches = repetition->get_matches ();
@@ -263,7 +271,8 @@ peculiar_fragment_match_compatible (const AST::MacroMatchFragment &last_match,
return peculiar_fragment_match_compatible (last_match, *first_frag);
break;
}
- case AST::MacroMatch::Matcher: {
+ case AST::MacroMatch::Matcher:
+ {
auto matcher = static_cast<const AST::MacroMatcher *> (&match);
auto first_token = matcher->get_delim_type ();
TokenId delim_id;
@@ -289,7 +298,8 @@ peculiar_fragment_match_compatible (const AST::MacroMatchFragment &last_match,
error_locus = matcher->get_match_locus ();
break;
}
- case AST::MacroMatch::Fragment: {
+ case AST::MacroMatch::Fragment:
+ {
auto last_spec = last_match.get_frag_spec ();
auto fragment = static_cast<const AST::MacroMatchFragment *> (&match);
if (last_spec.has_follow_set_fragment_restrictions ())
@@ -328,10 +338,11 @@ is_match_compatible (const AST::MacroMatch &last_match,
switch (last_match.get_macro_match_type ())
{
- // This is our main stop condition: When we are finally looking at the
- // last match (or its actual last component), and it is a fragment, it
- // may contain some follow up restrictions.
- case AST::MacroMatch::Fragment: {
+ // This is our main stop condition: When we are finally looking at the
+ // last match (or its actual last component), and it is a fragment, it
+ // may contain some follow up restrictions.
+ case AST::MacroMatch::Fragment:
+ {
auto fragment
= static_cast<const AST::MacroMatchFragment *> (&last_match);
if (fragment->get_frag_spec ().has_follow_set_restrictions ())
@@ -339,7 +350,8 @@ is_match_compatible (const AST::MacroMatch &last_match,
else
return true;
}
- case AST::MacroMatch::Repetition: {
+ case AST::MacroMatch::Repetition:
+ {
// A repetition on the left hand side means we want to make sure the
// last match of the repetition is compatible with the new match
auto repetition
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index 827d91d..8253885 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -17,6 +17,7 @@ along with GCC; see the file COPYING3. If not see
#ifndef RUST_PARSE_H
#define RUST_PARSE_H
+#include "rust-ast.h"
#include "rust-item.h"
#include "rust-lex.h"
#include "rust-ast-full.h"
@@ -33,12 +34,19 @@ class ParseLifetimeParamError
class ParseLifetimeError
{
};
+
+enum class AnonConstError
+{
+ InvalidSizeExpr,
+};
+
enum class ParseLoopLabelError
{
NOT_LOOP_LABEL,
MISSING_COLON,
};
-enum ParseSelfError
+
+enum class ParseSelfError
{
SELF_PTR,
PARSING,
@@ -165,6 +173,12 @@ public:
tl::optional<AST::LoopLabel> = tl::nullopt,
location_t pratt_parsed_loc = UNKNOWN_LOCATION);
+ tl::expected<AST::AnonConst, AnonConstError> parse_anon_const ();
+
+ std::unique_ptr<AST::ConstBlock>
+ parse_const_block_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
+ location_t loc = UNKNOWN_LOCATION);
+
bool is_macro_rules_def (const_TokenPtr t);
std::unique_ptr<AST::Item> parse_item (bool called_from_statement);
std::unique_ptr<AST::Pattern> parse_pattern ();
@@ -222,7 +236,7 @@ private:
// Path-related
AST::SimplePath parse_simple_path ();
- AST::SimplePathSegment parse_simple_path_segment ();
+ AST::SimplePathSegment parse_simple_path_segment (int base_peek = 0);
AST::TypePath parse_type_path ();
std::unique_ptr<AST::TypePathSegment> parse_type_path_segment ();
AST::PathIdentSegment parse_path_ident_segment ();
@@ -644,6 +658,9 @@ private:
std::unique_ptr<AST::ReturnExpr>
parse_return_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
location_t pratt_parsed_loc = UNKNOWN_LOCATION);
+ std::unique_ptr<AST::TryExpr>
+ parse_try_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
+ location_t pratt_parsed_loc = UNKNOWN_LOCATION);
std::unique_ptr<AST::BreakExpr>
parse_break_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
location_t pratt_parsed_loc = UNKNOWN_LOCATION);
@@ -762,11 +779,15 @@ private:
}
~InlineModuleStackScope () { parser.inline_module_stack.pop_back (); }
};
+
+ // don't want to make things *only* AttributeParser uses public
+ // TODO: fold more of AttributeParser into Parser?
+ friend class ::Rust::AST::AttributeParser;
};
-std::string
-extract_module_path (const AST::AttrVec &inner_attrs,
- const AST::AttrVec &outer_attrs, const std::string &name);
+std::string extract_module_path (const AST::AttrVec &inner_attrs,
+ const AST::AttrVec &outer_attrs,
+ const std::string &name);
/**
* Check if a MacroMatch is allowed to follow the last parsed MacroMatch.
@@ -776,12 +797,8 @@ extract_module_path (const AST::AttrVec &inner_attrs,
*
* @return true if the follow-up is valid, false otherwise
*/
-bool
-is_match_compatible (const AST::MacroMatch &last_match,
- const AST::MacroMatch &current_match);
+bool is_match_compatible (const AST::MacroMatch &last_match,
+ const AST::MacroMatch &current_match);
} // namespace Rust
-// as now template, include implementations of all methods
-#include "rust-parse-impl.h"
-
#endif // RUST_PARSE_H
diff --git a/gcc/rust/resolve/rust-ast-resolve-base.cc b/gcc/rust/resolve/rust-ast-resolve-base.cc
index b781ce33..3c7b425 100644
--- a/gcc/rust/resolve/rust-ast-resolve-base.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-base.cc
@@ -116,7 +116,7 @@ ResolverBase::visit (AST::MetaItemLitExpr &)
{}
void
-ResolverBase::visit (AST::MetaItemPathLit &)
+ResolverBase::visit (AST::MetaItemPathExpr &)
{}
void
@@ -232,6 +232,14 @@ ResolverBase::visit (AST::BlockExpr &)
{}
void
+ResolverBase::visit (AST::AnonConst &)
+{}
+
+void
+ResolverBase::visit (AST::ConstBlock &)
+{}
+
+void
ResolverBase::visit (AST::ClosureExprInnerTyped &)
{}
@@ -276,6 +284,10 @@ ResolverBase::visit (AST::ReturnExpr &)
{}
void
+ResolverBase::visit (AST::TryExpr &)
+{}
+
+void
ResolverBase::visit (AST::UnsafeBlockExpr &)
{}
@@ -572,6 +584,14 @@ ResolverBase::visit (AST::GroupedPattern &)
{}
void
+ResolverBase::visit (AST::SlicePatternItemsNoRest &)
+{}
+
+void
+ResolverBase::visit (AST::SlicePatternItemsHasRest &)
+{}
+
+void
ResolverBase::visit (AST::SlicePattern &)
{}
@@ -663,5 +683,9 @@ void
ResolverBase::visit (AST::FormatArgs &fmt)
{}
+void
+ResolverBase::visit (AST::OffsetOf &offset_of)
+{}
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h b/gcc/rust/resolve/rust-ast-resolve-base.h
index 5bb9e4f..89c5c35 100644
--- a/gcc/rust/resolve/rust-ast-resolve-base.h
+++ b/gcc/rust/resolve/rust-ast-resolve-base.h
@@ -21,6 +21,8 @@
#include "rust-ast-visitor.h"
#include "rust-ast.h"
+#include "rust-builtin-ast-nodes.h"
+#include "rust-expr.h"
#include "rust-name-resolver.h"
#include "rust-diagnostics.h"
#include "rust-location.h"
@@ -56,7 +58,7 @@ public:
void visit (AST::AttrInputLiteral &);
void visit (AST::AttrInputMacro &);
void visit (AST::MetaItemLitExpr &);
- void visit (AST::MetaItemPathLit &);
+ void visit (AST::MetaItemPathExpr &);
void visit (AST::BorrowExpr &);
void visit (AST::DereferenceExpr &);
void visit (AST::ErrorPropagationExpr &);
@@ -85,6 +87,8 @@ public:
void visit (AST::FieldAccessExpr &);
void visit (AST::ClosureExprInner &);
void visit (AST::BlockExpr &);
+ void visit (AST::AnonConst &);
+ void visit (AST::ConstBlock &);
void visit (AST::ClosureExprInnerTyped &);
void visit (AST::ContinueExpr &);
void visit (AST::BreakExpr &);
@@ -96,6 +100,7 @@ public:
void visit (AST::RangeToInclExpr &);
void visit (AST::BoxExpr &);
void visit (AST::ReturnExpr &);
+ void visit (AST::TryExpr &);
void visit (AST::UnsafeBlockExpr &);
void visit (AST::LoopExpr &);
void visit (AST::WhileLoopExpr &);
@@ -181,6 +186,8 @@ public:
void visit (AST::TuplePatternItemsRanged &);
void visit (AST::TuplePattern &);
void visit (AST::GroupedPattern &);
+ void visit (AST::SlicePatternItemsNoRest &);
+ void visit (AST::SlicePatternItemsHasRest &);
void visit (AST::SlicePattern &);
void visit (AST::AltPattern &);
@@ -207,6 +214,7 @@ public:
void visit (AST::SelfParam &param);
void visit (AST::FormatArgs &fmt);
+ void visit (AST::OffsetOf &offset_of);
protected:
ResolverBase ()
diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.cc b/gcc/rust/resolve/rust-ast-resolve-expr.cc
index 5524e18..a410193 100644
--- a/gcc/rust/resolve/rust-ast-resolve-expr.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-expr.cc
@@ -315,6 +315,18 @@ ResolveExpr::visit (AST::BlockExpr &expr)
}
void
+ResolveExpr::visit (AST::AnonConst &expr)
+{
+ ResolveExpr::go (expr.get_inner_expr (), prefix, canonical_prefix);
+}
+
+void
+ResolveExpr::visit (AST::ConstBlock &expr)
+{
+ ResolveExpr::go (expr.get_const_expr (), prefix, canonical_prefix);
+}
+
+void
translate_operand (AST::InlineAsm &expr, const CanonicalPath &prefix,
const CanonicalPath &canonical_prefix)
{
@@ -324,38 +336,46 @@ translate_operand (AST::InlineAsm &expr, const CanonicalPath &prefix,
{
switch (operand.get_register_type ())
{
- case RegisterType::In: {
+ case RegisterType::In:
+ {
auto in = operand.get_in ();
ResolveExpr::go (*in.expr, prefix, canonical_prefix);
break;
}
- case RegisterType::Out: {
+ case RegisterType::Out:
+ {
auto out = operand.get_out ();
ResolveExpr::go (*out.expr, prefix, canonical_prefix);
break;
}
- case RegisterType::InOut: {
+ case RegisterType::InOut:
+ {
auto in_out = operand.get_in_out ();
ResolveExpr::go (*in_out.expr, prefix, canonical_prefix);
break;
}
- case RegisterType::SplitInOut: {
+ case RegisterType::SplitInOut:
+ {
auto split_in_out = operand.get_split_in_out ();
ResolveExpr::go (*split_in_out.in_expr, prefix, canonical_prefix);
ResolveExpr::go (*split_in_out.out_expr, prefix, canonical_prefix);
break;
}
- case RegisterType::Const: {
+ case RegisterType::Const:
+ {
auto anon_const = operand.get_const ().anon_const;
- ResolveExpr::go (*anon_const.expr, prefix, canonical_prefix);
+ ResolveExpr::go (anon_const.get_inner_expr (), prefix,
+ canonical_prefix);
break;
}
- case RegisterType::Sym: {
+ case RegisterType::Sym:
+ {
auto sym = operand.get_sym ();
ResolveExpr::go (*sym.expr, prefix, canonical_prefix);
break;
}
- case RegisterType::Label: {
+ case RegisterType::Label:
+ {
auto label = operand.get_label ();
ResolveExpr::go (*label.expr, prefix, canonical_prefix);
break;
@@ -766,7 +786,7 @@ ResolveExpr::visit (AST::ClosureExprInnerTyped &expr)
resolver->push_closure_context (expr.get_node_id ());
- ResolveExpr::go (expr.get_definition_block (), prefix, canonical_prefix);
+ ResolveExpr::go (expr.get_definition_expr (), prefix, canonical_prefix);
resolver->pop_closure_context ();
diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h
index b296d66..aad1605 100644
--- a/gcc/rust/resolve/rust-ast-resolve-expr.h
+++ b/gcc/rust/resolve/rust-ast-resolve-expr.h
@@ -56,6 +56,8 @@ public:
void visit (AST::IfLetExpr &expr) override;
void visit (AST::IfLetExprConseqElse &expr) override;
void visit (AST::BlockExpr &expr) override;
+ void visit (AST::AnonConst &expr) override;
+ void visit (AST::ConstBlock &expr) override;
void visit (AST::InlineAsm &expr) override;
void visit (AST::LlvmInlineAsm &expr) override;
void visit (AST::UnsafeBlockExpr &expr) override;
diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc
index 30f6d43..1d5ebed 100644
--- a/gcc/rust/resolve/rust-ast-resolve-item.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-item.cc
@@ -453,7 +453,8 @@ ResolveItem::visit (AST::ConstantItem &constant)
resolve_visibility (constant.get_visibility ());
ResolveType::go (constant.get_type ());
- ResolveExpr::go (constant.get_expr (), path, cpath);
+ if (constant.has_expr ())
+ ResolveExpr::go (constant.get_expr (), path, cpath);
}
void
@@ -608,10 +609,7 @@ ResolveItem::visit (AST::InherentImpl &impl_block)
}
else
{
- std::string seg_buf = "<impl " + self_cpath.get () + ">";
- CanonicalPath seg
- = CanonicalPath::new_seg (impl_block.get_node_id (), seg_buf);
- cpath = canonical_prefix.append (seg);
+ cpath = canonical_prefix.append (impl_type_seg);
}
// done setup paths
@@ -732,13 +730,7 @@ ResolveItem::visit (AST::TraitImpl &impl_block)
}
else
{
- std::string projection_str = canonical_projection.get ();
- std::string seg_buf
- = "<impl " + projection_str.substr (1, projection_str.size () - 2)
- + ">";
- CanonicalPath seg
- = CanonicalPath::new_seg (impl_block.get_node_id (), seg_buf);
- cpath = canonical_prefix.append (seg);
+ cpath = canonical_prefix.append (canonical_projection);
}
// DONE setup canonical-path
@@ -838,29 +830,32 @@ ResolveItem::resolve_extern_item (AST::ExternalItem &item)
ResolveExternItem::go (item, prefix, canonical_prefix);
}
-static void
-flatten_glob (const AST::UseTreeGlob &glob, std::vector<Import> &imports);
-static void
-flatten_rebind (const AST::UseTreeRebind &glob, std::vector<Import> &imports);
-static void
-flatten_list (const AST::UseTreeList &glob, std::vector<Import> &imports);
+static void flatten_glob (const AST::UseTreeGlob &glob,
+ std::vector<Import> &imports);
+static void flatten_rebind (const AST::UseTreeRebind &glob,
+ std::vector<Import> &imports);
+static void flatten_list (const AST::UseTreeList &glob,
+ std::vector<Import> &imports);
static void
flatten (const AST::UseTree *tree, std::vector<Import> &imports)
{
switch (tree->get_kind ())
{
- case AST::UseTree::Glob: {
+ case AST::UseTree::Glob:
+ {
auto glob = static_cast<const AST::UseTreeGlob *> (tree);
flatten_glob (*glob, imports);
break;
}
- case AST::UseTree::Rebind: {
+ case AST::UseTree::Rebind:
+ {
auto rebind = static_cast<const AST::UseTreeRebind *> (tree);
flatten_rebind (*rebind, imports);
break;
}
- case AST::UseTree::List: {
+ case AST::UseTree::List:
+ {
auto list = static_cast<const AST::UseTreeList *> (tree);
flatten_list (*list, imports);
break;
diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h
index 776dd53..d31f910 100644
--- a/gcc/rust/resolve/rust-ast-resolve-item.h
+++ b/gcc/rust/resolve/rust-ast-resolve-item.h
@@ -153,8 +153,7 @@ private:
#if CHECKING_P
namespace selftest {
-extern void
-rust_simple_path_resolve_test (void);
+extern void rust_simple_path_resolve_test (void);
} // namespace selftest
#endif // CHECKING_P
diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.cc b/gcc/rust/resolve/rust-ast-resolve-pattern.cc
index ee84be8..3b80f9f 100644
--- a/gcc/rust/resolve/rust-ast-resolve-pattern.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-pattern.cc
@@ -62,6 +62,11 @@ PatternDeclaration::go (AST::Pattern &pattern, Rib::ItemType type,
void
PatternDeclaration::visit (AST::IdentifierPattern &pattern)
{
+ if (pattern.has_subpattern ())
+ {
+ pattern.get_subpattern ().accept_vis (*this);
+ }
+
Mutability mut = pattern.get_is_mut () ? Mutability::Mut : Mutability::Imm;
add_new_binding (pattern.get_ident (), pattern.get_node_id (),
BindingTypeInfo (mut, pattern.get_is_ref (),
@@ -94,13 +99,15 @@ PatternDeclaration::visit (AST::TupleStructPattern &pattern)
AST::TupleStructItems &items = pattern.get_items ();
switch (items.get_item_type ())
{
- case AST::TupleStructItems::RANGE: {
+ case AST::TupleStructItems::RANGE:
+ {
// TODO
rust_unreachable ();
}
break;
- case AST::TupleStructItems::NO_RANGE: {
+ case AST::TupleStructItems::NO_RANGE:
+ {
auto &items_no_range
= static_cast<AST::TupleStructItemsNoRange &> (items);
@@ -123,7 +130,8 @@ PatternDeclaration::visit (AST::StructPattern &pattern)
{
switch (field->get_item_type ())
{
- case AST::StructPatternField::ItemType::TUPLE_PAT: {
+ case AST::StructPatternField::ItemType::TUPLE_PAT:
+ {
AST::StructPatternFieldTuplePat &tuple
= static_cast<AST::StructPatternFieldTuplePat &> (*field);
@@ -131,7 +139,8 @@ PatternDeclaration::visit (AST::StructPattern &pattern)
}
break;
- case AST::StructPatternField::ItemType::IDENT_PAT: {
+ case AST::StructPatternField::ItemType::IDENT_PAT:
+ {
AST::StructPatternFieldIdentPat &ident
= static_cast<AST::StructPatternFieldIdentPat &> (*field);
@@ -139,7 +148,8 @@ PatternDeclaration::visit (AST::StructPattern &pattern)
}
break;
- case AST::StructPatternField::ItemType::IDENT: {
+ case AST::StructPatternField::ItemType::IDENT:
+ {
auto &ident = static_cast<AST::StructPatternFieldIdent &> (*field);
Mutability mut
@@ -160,7 +170,8 @@ PatternDeclaration::visit (AST::TuplePattern &pattern)
auto &items = pattern.get_items ();
switch (items.get_pattern_type ())
{
- case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE: {
+ case AST::TuplePatternItems::TuplePatternItemType::MULTIPLE:
+ {
auto &ref = static_cast<AST::TuplePatternItemsMultiple &> (
pattern.get_items ());
@@ -169,7 +180,8 @@ PatternDeclaration::visit (AST::TuplePattern &pattern)
}
break;
- case AST::TuplePatternItems::TuplePatternItemType::RANGED: {
+ case AST::TuplePatternItems::TuplePatternItemType::RANGED:
+ {
auto &ref
= static_cast<AST::TuplePatternItemsRanged &> (pattern.get_items ());
@@ -348,14 +360,16 @@ resolve_range_pattern_bound (AST::RangePatternBound &bound)
// Nothing to resolve for a literal.
break;
- case AST::RangePatternBound::RangePatternBoundType::PATH: {
+ case AST::RangePatternBound::RangePatternBoundType::PATH:
+ {
auto &ref = static_cast<AST::RangePatternBoundPath &> (bound);
ResolvePath::go (ref.get_path ());
}
break;
- case AST::RangePatternBound::RangePatternBoundType::QUALPATH: {
+ case AST::RangePatternBound::RangePatternBoundType::QUALPATH:
+ {
auto &ref = static_cast<AST::RangePatternBoundQualPath &> (bound);
ResolvePath::go (ref.get_qualified_path ());
@@ -374,9 +388,30 @@ PatternDeclaration::visit (AST::RangePattern &pattern)
void
PatternDeclaration::visit (AST::SlicePattern &pattern)
{
- for (auto &p : pattern.get_items ())
+ auto &items = pattern.get_items ();
+ switch (items.get_pattern_type ())
{
- p->accept_vis (*this);
+ case AST::SlicePatternItems::SlicePatternItemType::NO_REST:
+ {
+ auto &ref
+ = static_cast<AST::SlicePatternItemsNoRest &> (pattern.get_items ());
+
+ for (auto &p : ref.get_patterns ())
+ p->accept_vis (*this);
+ }
+ break;
+
+ case AST::SlicePatternItems::SlicePatternItemType::HAS_REST:
+ {
+ auto &ref
+ = static_cast<AST::SlicePatternItemsHasRest &> (pattern.get_items ());
+
+ for (auto &p : ref.get_lower_patterns ())
+ p->accept_vis (*this);
+ for (auto &p : ref.get_upper_patterns ())
+ p->accept_vis (*this);
+ }
+ break;
}
}
diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h
index d413a7c..d714511 100644
--- a/gcc/rust/resolve/rust-ast-resolve-stmt.h
+++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h
@@ -67,7 +67,8 @@ public:
});
ResolveType::go (constant.get_type ());
- ResolveExpr::go (constant.get_expr (), prefix, canonical_prefix);
+ if (constant.has_expr ())
+ ResolveExpr::go (constant.get_expr (), prefix, canonical_prefix);
}
void visit (AST::LetStmt &stmt) override
diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc b/gcc/rust/resolve/rust-ast-resolve-type.cc
index 8fd69c3..a040228 100644
--- a/gcc/rust/resolve/rust-ast-resolve-type.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-type.cc
@@ -140,7 +140,7 @@ ResolveType::visit (AST::ImplTraitType &type)
void
ResolveType::visit (AST::ImplTraitTypeOneBound &type)
{
- ResolveTypeBound::go (type.get_trait_bound ());
+ ResolveTypeBound::go (*type.get_trait_bound ().get ());
}
// resolve relative type-paths
@@ -210,7 +210,8 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId &resolved_node_id)
switch (segment->get_type ())
{
- case AST::TypePathSegment::SegmentType::GENERIC: {
+ case AST::TypePathSegment::SegmentType::GENERIC:
+ {
AST::TypePathSegmentGeneric *s
= static_cast<AST::TypePathSegmentGeneric *> (segment.get ());
if (s->has_generic_args ())
@@ -509,7 +510,8 @@ ResolveTypeToCanonicalPath::visit (AST::TypePath &path)
auto &final_seg = path.get_segments ().back ();
switch (final_seg->get_type ())
{
- case AST::TypePathSegment::SegmentType::GENERIC: {
+ case AST::TypePathSegment::SegmentType::GENERIC:
+ {
AST::TypePathSegmentGeneric *s
= static_cast<AST::TypePathSegmentGeneric *> (final_seg.get ());
@@ -651,7 +653,8 @@ ResolveTypeToCanonicalPath::visit (AST::TraitObjectType &type)
switch (additional_bound->get_bound_type ())
{
- case AST::TypeParamBound::TRAIT: {
+ case AST::TypeParamBound::TRAIT:
+ {
auto bound_path = CanonicalPath::create_empty ();
auto &bound_type_path
diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc
index 3e3c992..2208f70 100644
--- a/gcc/rust/resolve/rust-ast-resolve.cc
+++ b/gcc/rust/resolve/rust-ast-resolve.cc
@@ -24,8 +24,7 @@
#include "rust-ast-resolve-expr.h"
#include "rust-ast-resolve-struct-expr-field.h"
-extern bool
-saw_errors (void);
+extern bool saw_errors (void);
namespace Rust {
namespace Resolver {
diff --git a/gcc/rust/resolve/rust-default-resolver.cc b/gcc/rust/resolve/rust-default-resolver.cc
index 480034c..f1c0e5c 100644
--- a/gcc/rust/resolve/rust-default-resolver.cc
+++ b/gcc/rust/resolve/rust-default-resolver.cc
@@ -25,6 +25,21 @@ namespace Rust {
namespace Resolver2_0 {
void
+DefaultResolver::visit (AST::Crate &crate)
+{
+ auto inner_fn = [this, &crate] () { AST::DefaultASTVisitor::visit (crate); };
+
+ auto &mappings = Analysis::Mappings::get ();
+
+ auto crate_num = mappings.lookup_crate_num (crate.get_node_id ());
+ rust_assert (crate_num.has_value ());
+ auto crate_name = mappings.get_crate_name (*crate_num);
+ rust_assert (crate_name.has_value ());
+
+ ctx.canonical_ctx.scope_crate (crate.get_node_id (), *crate_name, inner_fn);
+}
+
+void
DefaultResolver::visit (AST::BlockExpr &expr)
{
// extracting the lambda from the `scoped` call otherwise the code looks like
@@ -38,19 +53,32 @@ DefaultResolver::visit (AST::BlockExpr &expr)
void
DefaultResolver::visit (AST::Module &module)
{
- auto item_fn = [this, &module] () { AST::DefaultASTVisitor::visit (module); };
+ auto item_fn_1
+ = [this, &module] () { AST::DefaultASTVisitor::visit (module); };
+
+ auto item_fn_2 = [this, &module, &item_fn_1] () {
+ ctx.canonical_ctx.scope (module.get_node_id (), module.get_name (),
+ std::move (item_fn_1));
+ };
- ctx.scoped (Rib::Kind::Module, module.get_node_id (), item_fn,
+ ctx.scoped (Rib::Kind::Module, module.get_node_id (), item_fn_2,
module.get_name ());
}
void
DefaultResolver::visit (AST::Function &function)
{
- auto def_fn
+ auto def_fn_1
= [this, &function] () { AST::DefaultASTVisitor::visit (function); };
- ctx.scoped (Rib::Kind::Function, function.get_node_id (), def_fn);
+ auto def_fn_2 = [this, &function, &def_fn_1] () {
+ ctx.canonical_ctx.scope (function.get_node_id (),
+ function.get_function_name (),
+ std::move (def_fn_1));
+ };
+
+ ctx.scoped (Rib::Kind::Function, function.get_node_id (), def_fn_2,
+ function.get_function_name ());
}
void
@@ -61,73 +89,252 @@ DefaultResolver::visit (AST::ForLoopExpr &expr)
}
void
-DefaultResolver::visit (AST::Trait &trait)
+DefaultResolver::visit_if_let_patterns (AST::IfLetExpr &expr)
+{
+ for (auto &pattern : expr.get_patterns ())
+ visit (pattern);
+}
+
+void
+DefaultResolver::visit (AST::IfLetExpr &expr)
{
- auto inner_fn = [this, &trait] () { AST::DefaultASTVisitor::visit (trait); };
+ auto inner_vis = [this, &expr] () {
+ visit_if_let_patterns (expr);
+ visit (expr.get_if_block ());
+ };
+
+ visit_outer_attrs (expr);
+
+ visit (expr.get_value_expr ());
+
+ ctx.scoped (Rib::Kind::Normal, expr.get_node_id (), inner_vis);
+}
+
+void
+DefaultResolver::visit (AST::IfLetExprConseqElse &expr)
+{
+ DefaultResolver::visit (static_cast<AST::IfLetExpr &> (expr));
+ visit (expr.get_else_block ());
+}
- ctx.scoped (Rib::Kind::TraitOrImpl, trait.get_node_id (), inner_fn,
+void
+DefaultResolver::visit (AST::Trait &trait)
+{
+ visit_outer_attrs (trait);
+ visit (trait.get_visibility ());
+ visit_inner_attrs (trait);
+
+ auto inner_fn_1 = [this, &trait] () {
+ for (auto &item : trait.get_trait_items ())
+ visit (item);
+ };
+
+ auto inner_fn_2 = [this, &trait, &inner_fn_1] () {
+ visit (trait.get_implicit_self ());
+ for (auto &generic : trait.get_generic_params ())
+ visit (generic);
+ if (trait.has_where_clause ())
+ visit (trait.get_where_clause ());
+ for (auto &bound : trait.get_type_param_bounds ())
+ visit (bound);
+
+ ctx.scoped (Rib::Kind::TraitOrImpl, trait.get_node_id (), inner_fn_1);
+ };
+
+ auto inner_fn_3 = [this, &trait, &inner_fn_2] () {
+ ctx.canonical_ctx.scope (trait.get_node_id (), trait.get_identifier (),
+ std::move (inner_fn_2));
+ };
+
+ ctx.scoped (Rib::Kind::Generics, trait.get_node_id (), inner_fn_3,
trait.get_identifier () /* FIXME: Is that valid?*/);
}
void
DefaultResolver::visit (AST::InherentImpl &impl)
{
- auto inner_fn = [this, &impl] () { AST::DefaultASTVisitor::visit (impl); };
-
- ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn);
+ visit_outer_attrs (impl);
+ visit (impl.get_visibility ());
+ visit_inner_attrs (impl);
+
+ auto inner_fn_1 = [this, &impl] () {
+ for (auto &item : impl.get_impl_items ())
+ visit (item);
+ };
+
+ auto inner_fn_2 = [this, &impl, &inner_fn_1] () {
+ maybe_insert_big_self (impl);
+ for (auto &generic : impl.get_generic_params ())
+ visit (generic);
+ if (impl.has_where_clause ())
+ visit (impl.get_where_clause ());
+ visit_impl_type (impl.get_type ());
+
+ ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn_1);
+ };
+
+ auto inner_fn_3 = [this, &impl, &inner_fn_2] () {
+ ctx.canonical_ctx.scope_impl (impl, std::move (inner_fn_2));
+ };
+
+ ctx.scoped (Rib::Kind::Generics, impl.get_node_id (), inner_fn_3);
}
void
DefaultResolver::visit (AST::TraitImpl &impl)
{
- auto inner_fn = [this, &impl] () { AST::DefaultASTVisitor::visit (impl); };
-
- ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn);
+ visit_outer_attrs (impl);
+ visit (impl.get_visibility ());
+ visit_inner_attrs (impl);
+
+ auto inner_fn_1 = [this, &impl] () {
+ for (auto &item : impl.get_impl_items ())
+ visit (item);
+ };
+
+ auto inner_fn_2 = [this, &impl, &inner_fn_1] () {
+ maybe_insert_big_self (impl);
+ for (auto &generic : impl.get_generic_params ())
+ visit (generic);
+ if (impl.has_where_clause ())
+ visit (impl.get_where_clause ());
+ visit_impl_type (impl.get_type ());
+ visit (impl.get_trait_path ());
+
+ ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn_1);
+ };
+
+ auto inner_fn_3 = [this, &impl, &inner_fn_2] () {
+ ctx.canonical_ctx.scope_impl (impl, std::move (inner_fn_2));
+ };
+
+ ctx.scoped (Rib::Kind::Generics, impl.get_node_id (), inner_fn_3);
}
void
DefaultResolver::visit (AST::StructStruct &type)
{
- auto inner_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+ auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+
+ auto inner_fn_2 = [this, &type, &inner_fn_1] () {
+ ctx.canonical_ctx.scope (type.get_node_id (), type.get_struct_name (),
+ std::move (inner_fn_1));
+ };
ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (),
- inner_fn, type.get_struct_name ());
+ inner_fn_2, type.get_struct_name ());
}
void
DefaultResolver::visit (AST::TupleStruct &type)
{
- auto inner_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+ auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+
+ auto inner_fn_2 = [this, &type, &inner_fn_1] () {
+ ctx.canonical_ctx.scope (type.get_node_id (), type.get_struct_name (),
+ std::move (inner_fn_1));
+ };
ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (),
- inner_fn, type.get_struct_name ());
+ inner_fn_2, type.get_struct_name ());
+}
+
+void
+DefaultResolver::visit (AST::EnumItem &item)
+{
+ auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
+
+ ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (),
+ inner_fn);
+}
+
+void
+DefaultResolver::visit (AST::EnumItemTuple &item)
+{
+ auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
+
+ ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (),
+ inner_fn);
+}
+
+void
+DefaultResolver::visit (AST::EnumItemStruct &item)
+{
+ auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
+
+ ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (),
+ inner_fn);
+}
+
+void
+DefaultResolver::visit (AST::EnumItemDiscriminant &item)
+{
+ auto inner_fn = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
+
+ ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (),
+ inner_fn);
}
void
DefaultResolver::visit (AST::Enum &type)
{
- auto variant_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+ auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+
+ auto inner_fn_2 = [this, &type, &inner_fn_1] () {
+ ctx.canonical_ctx.scope (type.get_node_id (), type.get_identifier (),
+ std::move (inner_fn_1));
+ };
ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (),
- variant_fn, type.get_identifier ());
+ inner_fn_2, type.get_identifier ());
}
void
DefaultResolver::visit (AST::Union &type)
{
- auto inner_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+ auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+
+ auto inner_fn_2 = [this, &type, &inner_fn_1] () {
+ ctx.canonical_ctx.scope (type.get_node_id (), type.get_identifier (),
+ std::move (inner_fn_1));
+ };
ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (),
- inner_fn, type.get_identifier ());
+ inner_fn_2, type.get_identifier ());
}
void
DefaultResolver::visit (AST::TypeAlias &type)
{
- auto inner_fn = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+ auto inner_fn_1 = [this, &type] () { AST::DefaultASTVisitor::visit (type); };
+
+ auto inner_fn_2 = [this, &type, &inner_fn_1] () {
+ ctx.canonical_ctx.scope (type.get_node_id (), type.get_new_type_name (),
+ std::move (inner_fn_1));
+ };
ctx.scoped (Rib::Kind::Item /* FIXME: Correct? */, type.get_node_id (),
- inner_fn, type.get_new_type_name ());
+ inner_fn_2, type.get_new_type_name ());
+}
+
+void
+DefaultResolver::visit_closure_params (AST::ClosureExpr &expr)
+{
+ for (auto &param : expr.get_params ())
+ visit (param);
+}
+
+void
+DefaultResolver::visit (AST::ClosureExpr &expr)
+{
+ auto expr_fn = [this, &expr] () {
+ visit_closure_params (expr);
+ visit (expr.get_definition_expr ());
+ };
+
+ visit_outer_attrs (expr);
+
+ ctx.scoped (Rib::Kind::Normal, expr.get_node_id (), expr_fn);
}
void
@@ -136,7 +343,7 @@ DefaultResolver::visit (AST::ClosureExprInner &expr)
if (expr.is_marked_for_strip ())
return;
- AST::DefaultASTVisitor::visit (expr);
+ visit (static_cast<AST::ClosureExpr &> (expr));
}
void
@@ -145,7 +352,8 @@ DefaultResolver::visit (AST::ClosureExprInnerTyped &expr)
if (expr.is_marked_for_strip ())
return;
- AST::DefaultASTVisitor::visit (expr);
+ visit (static_cast<AST::ClosureExpr &> (expr));
+ visit (expr.get_return_type ());
}
void
@@ -160,23 +368,29 @@ DefaultResolver::visit (AST::MatchExpr &expr)
void
DefaultResolver::visit (AST::ConstantItem &item)
{
- if (item.has_expr ())
- {
- auto expr_vis
- = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
+ auto expr_vis_1 = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
- // FIXME: Why do we need a Rib here?
- ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis);
- }
+ auto expr_vis_2 = [this, &item, &expr_vis_1] () {
+ ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (),
+ std::move (expr_vis_1));
+ };
+
+ // FIXME: Why do we need a Rib here?
+ ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis_2);
}
void
DefaultResolver::visit (AST::StaticItem &item)
{
- auto expr_vis = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
+ auto expr_vis_1 = [this, &item] () { AST::DefaultASTVisitor::visit (item); };
+
+ auto expr_vis_2 = [this, &item, &expr_vis_1] () {
+ ctx.canonical_ctx.scope (item.get_node_id (), item.get_identifier (),
+ std::move (expr_vis_1));
+ };
// FIXME: Why do we need a Rib here?
- ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis);
+ ctx.scoped (Rib::Kind::ConstantItem, item.get_node_id (), expr_vis_2);
}
void
@@ -187,5 +401,46 @@ DefaultResolver::visit (AST::TypeParam &param)
ctx.scoped (Rib::Kind::ForwardTypeParamBan, param.get_node_id (), expr_vis);
}
+void
+DefaultResolver::visit_extern_crate (AST::ExternCrate &extern_crate,
+ AST::Crate &crate, CrateNum num)
+{
+ visit (crate);
+}
+
+void
+DefaultResolver::visit (AST::ExternCrate &crate)
+{
+ auto &mappings = Analysis::Mappings::get ();
+ auto num_opt = mappings.lookup_crate_name (crate.get_referenced_crate ());
+
+ if (!num_opt)
+ {
+ rust_error_at (crate.get_locus (), "unknown crate %qs",
+ crate.get_referenced_crate ().c_str ());
+ return;
+ }
+
+ CrateNum num = *num_opt;
+
+ AST::Crate &referenced_crate = mappings.get_ast_crate (num);
+
+ auto sub_visitor_1
+ = [&, this] () { visit_extern_crate (crate, referenced_crate, num); };
+
+ auto sub_visitor_2 = [&] () {
+ ctx.canonical_ctx.scope_crate (referenced_crate.get_node_id (),
+ crate.get_referenced_crate (),
+ std::move (sub_visitor_1));
+ };
+
+ if (crate.has_as_clause ())
+ ctx.scoped (Rib::Kind::Module, referenced_crate.get_node_id (),
+ sub_visitor_2, crate.get_as_clause ());
+ else
+ ctx.scoped (Rib::Kind::Module, referenced_crate.get_node_id (),
+ sub_visitor_2, crate.get_referenced_crate ());
+}
+
} // namespace Resolver2_0
} // namespace Rust
diff --git a/gcc/rust/resolve/rust-default-resolver.h b/gcc/rust/resolve/rust-default-resolver.h
index 2a987ef..cf0df68 100644
--- a/gcc/rust/resolve/rust-default-resolver.h
+++ b/gcc/rust/resolve/rust-default-resolver.h
@@ -39,6 +39,7 @@ public:
virtual ~DefaultResolver () {}
+ void visit (AST::Crate &) override;
// First, our lexical scope expressions - these visit their sub nodes, always
// these nodes create new scopes and ribs - they are often used to declare new
// variables, such as a for loop's iterator, or a function's arguments
@@ -46,20 +47,35 @@ public:
void visit (AST::Module &) override;
void visit (AST::Function &) override;
void visit (AST::ForLoopExpr &expr) override;
+ virtual void visit_if_let_patterns (AST::IfLetExpr &expr);
+ void visit (AST::IfLetExpr &expr) override;
+ void visit (AST::IfLetExprConseqElse &expr) override;
void visit (AST::Trait &) override;
+ // used to handle Self insertion in TopLevel
+ virtual void maybe_insert_big_self (AST::Impl &) {}
+ virtual void visit_impl_type (AST::Type &type) { visit (type); }
void visit (AST::InherentImpl &) override;
void visit (AST::TraitImpl &) override;
void visit (AST::TypeParam &) override;
+ virtual void visit_extern_crate (AST::ExternCrate &, AST::Crate &, CrateNum);
+ void visit (AST::ExternCrate &) override;
+
// type dec nodes, which visit their fields or variants by default
void visit (AST::StructStruct &) override;
void visit (AST::TupleStruct &) override;
+ void visit (AST::EnumItem &) override;
+ void visit (AST::EnumItemTuple &) override;
+ void visit (AST::EnumItemStruct &) override;
+ void visit (AST::EnumItemDiscriminant &) override;
void visit (AST::Enum &) override;
void visit (AST::Union &) override;
void visit (AST::TypeAlias &) override;
// Visitors that visit their expression node(s)
+ virtual void visit_closure_params (AST::ClosureExpr &);
+ virtual void visit (AST::ClosureExpr &);
void visit (AST::ClosureExprInner &) override;
void visit (AST::ClosureExprInnerTyped &) override;
void visit (AST::MatchExpr &) 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 3390f09..4fd1dd2 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
@@ -17,8 +17,11 @@
// <http://www.gnu.org/licenses/>.
#include "rust-early-name-resolver-2.0.h"
-#include "rust-ast-full.h"
+#include "optional.h"
+#include "options.h"
#include "rust-diagnostics.h"
+#include "rust-hir-map.h"
+#include "rust-item.h"
#include "rust-toplevel-name-resolver-2.0.h"
#include "rust-attributes.h"
#include "rust-finalize-imports-2.0.h"
@@ -62,8 +65,9 @@ Early::go (AST::Crate &crate)
// We now proceed with resolving macros, which can be nested in almost any
// items
textual_scope.push ();
- for (auto &item : crate.items)
- item->accept_vis (*this);
+
+ visit (crate);
+
textual_scope.pop ();
}
@@ -74,8 +78,9 @@ Early::resolve_glob_import (NodeId use_dec_id, TopLevel::ImportKind &&glob)
if (!resolved.has_value ())
return false;
- auto result
- = Analysis::Mappings::get ().lookup_ast_module (resolved->get_node_id ());
+ auto result = Analysis::Mappings::get ().lookup_glob_container (
+ resolved->get_node_id ());
+
if (!result)
return false;
@@ -249,7 +254,12 @@ Early::visit (AST::Module &module)
void
Early::visit (AST::MacroInvocation &invoc)
{
- auto path = invoc.get_invoc_data ().get_path ();
+ auto &path = invoc.get_invoc_data ().get_path ();
+
+ // We special case the `offset_of!()` macro if the flag is here, otherwise
+ // we accept whatever `offset_of!()` definition we resolved to.
+ auto resolve_offset_of
+ = flag_assume_builtin_offset_of && (path.as_string () == "offset_of");
if (invoc.get_kind () == AST::MacroInvocation::InvocKind::Builtin)
for (auto &pending_invoc : invoc.get_pending_eager_invocations ())
@@ -272,14 +282,16 @@ Early::visit (AST::MacroInvocation &invoc)
// we won't have changed `definition` from `nullopt` if there are more
// than one segments in our path
if (!definition.has_value ())
- definition = ctx.resolve_path (path.get_segments (), Namespace::Macros);
+ definition = ctx.resolve_path (path, Namespace::Macros);
- // if the definition still does not have a value, then it's an error
+ // if the definition still does not have a value, then it's an error - unless
+ // we should automatically resolve offset_of!() calls
if (!definition.has_value ())
{
- collect_error (Error (invoc.get_locus (), ErrorCode::E0433,
- "could not resolve macro invocation %qs",
- path.as_string ().c_str ()));
+ if (!resolve_offset_of)
+ collect_error (Error (invoc.get_locus (), ErrorCode::E0433,
+ "could not resolve macro invocation %qs",
+ path.as_string ().c_str ()));
return;
}
@@ -314,8 +326,8 @@ Early::visit_attributes (std::vector<AST::Attribute> &attrs)
auto traits = attr.get_traits_to_derive ();
for (auto &trait : traits)
{
- auto definition = ctx.resolve_path (trait.get ().get_segments (),
- Namespace::Macros);
+ auto definition
+ = ctx.resolve_path (trait.get (), Namespace::Macros);
if (!definition.has_value ())
{
// FIXME: Change to proper error message
@@ -337,8 +349,8 @@ Early::visit_attributes (std::vector<AST::Attribute> &attrs)
->lookup_builtin (name)
.is_error ()) // Do not resolve builtins
{
- auto definition = ctx.resolve_path (attr.get_path ().get_segments (),
- Namespace::Macros);
+ auto definition
+ = ctx.resolve_path (attr.get_path (), Namespace::Macros);
if (!definition.has_value ())
{
// FIXME: Change to proper error message
@@ -350,7 +362,8 @@ Early::visit_attributes (std::vector<AST::Attribute> &attrs)
auto pm_def = mappings.lookup_attribute_proc_macro_def (
definition->get_node_id ());
- rust_assert (pm_def.has_value ());
+ if (!pm_def.has_value ())
+ return;
mappings.insert_attribute_proc_macro_invocation (attr.get_path (),
pm_def.value ());
@@ -392,12 +405,12 @@ void
Early::finalize_glob_import (NameResolutionContext &ctx,
const Early::ImportPair &mapping)
{
- auto module = Analysis::Mappings::get ().lookup_ast_module (
- mapping.data.module ().get_node_id ());
- rust_assert (module);
+ auto container = Analysis::Mappings::get ().lookup_glob_container (
+ mapping.data.container ().get_node_id ());
+
+ rust_assert (container);
- GlobbingVisitor glob_visitor (ctx);
- glob_visitor.go (module.value ());
+ GlobbingVisitor (ctx).go (container.value ());
}
void
@@ -419,7 +432,8 @@ 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: {
+ 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 ())
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 e78bec0..960de0e 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.h
@@ -83,15 +83,15 @@ public:
return ImportData (Kind::Rebind, std::move (definitions));
}
- static ImportData Glob (Rib::Definition module)
+ static ImportData Glob (Rib::Definition container)
{
- return ImportData (Kind::Glob, module);
+ return ImportData (Kind::Glob, container);
}
- Rib::Definition module () const
+ Rib::Definition container () const
{
rust_assert (kind == Kind::Glob);
- return glob_module;
+ return glob_container;
}
std::vector<std::pair<Rib::Definition, Namespace>> definitions () const
@@ -107,8 +107,8 @@ public:
: kind (kind), resolved_definitions (std::move (definitions))
{}
- ImportData (Kind kind, Rib::Definition module)
- : kind (kind), glob_module (module)
+ ImportData (Kind kind, Rib::Definition container)
+ : kind (kind), glob_container (container)
{}
// TODO: Should this be a union?
@@ -117,7 +117,7 @@ public:
std::vector<std::pair<Rib::Definition, Namespace>> resolved_definitions;
// For Glob
- Rib::Definition glob_module;
+ Rib::Definition glob_container;
};
struct ImportPair
diff --git a/gcc/rust/resolve/rust-early-name-resolver.cc b/gcc/rust/resolve/rust-early-name-resolver.cc
index fc9a26c..7b365ef 100644
--- a/gcc/rust/resolve/rust-early-name-resolver.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver.cc
@@ -205,7 +205,7 @@ EarlyNameResolver::visit (AST::MetaItemLitExpr &)
{}
void
-EarlyNameResolver::visit (AST::MetaItemPathLit &)
+EarlyNameResolver::visit (AST::MetaItemPathExpr &)
{}
void
diff --git a/gcc/rust/resolve/rust-early-name-resolver.h b/gcc/rust/resolve/rust-early-name-resolver.h
index 26fc84d..d3c5225 100644
--- a/gcc/rust/resolve/rust-early-name-resolver.h
+++ b/gcc/rust/resolve/rust-early-name-resolver.h
@@ -142,7 +142,7 @@ private:
virtual void visit (AST::AttrInputLiteral &attr_input);
virtual void visit (AST::AttrInputMacro &attr_input);
virtual void visit (AST::MetaItemLitExpr &meta_item);
- virtual void visit (AST::MetaItemPathLit &meta_item);
+ virtual void visit (AST::MetaItemPathExpr &meta_item);
virtual void visit (AST::StructExprStruct &expr);
virtual void visit (AST::StructExprFieldIdentifier &field);
virtual void visit (AST::StructExprStructBase &expr);
diff --git a/gcc/rust/resolve/rust-finalize-imports-2.0.cc b/gcc/rust/resolve/rust-finalize-imports-2.0.cc
index b0e8651..317acb0 100644
--- a/gcc/rust/resolve/rust-finalize-imports-2.0.cc
+++ b/gcc/rust/resolve/rust-finalize-imports-2.0.cc
@@ -21,19 +21,44 @@
#include "rust-hir-map.h"
#include "rust-name-resolution-context.h"
#include "rust-rib.h"
+#include "rust-system.h"
#include "rust-toplevel-name-resolver-2.0.h"
namespace Rust {
namespace Resolver2_0 {
void
-GlobbingVisitor::go (AST::Module *module)
+GlobbingVisitor::go (AST::Item *container)
{
- for (auto &i : module->get_items ())
+ switch (container->get_item_kind ())
+ {
+ case AST::Item::Kind::Module:
+ visit_module_container (static_cast<AST::Module &> (*container));
+ break;
+ case AST::Item::Kind::Enum:
+ visit_enum_container (static_cast<AST::Enum &> (*container));
+ break;
+ default:
+ rust_unreachable ();
+ }
+}
+
+void
+GlobbingVisitor::visit_module_container (AST::Module &module)
+{
+ for (auto &i : module.get_items ())
visit (i);
}
void
+GlobbingVisitor::visit_enum_container (AST::Enum &item)
+{
+ for (auto &variant : item.get_variants ())
+ ctx.insert_globbed (variant->get_identifier (), variant->get_node_id (),
+ Namespace::Types);
+}
+
+void
GlobbingVisitor::visit (AST::Module &module)
{
if (module.get_visibility ().is_public ())
diff --git a/gcc/rust/resolve/rust-finalize-imports-2.0.h b/gcc/rust/resolve/rust-finalize-imports-2.0.h
index d587a5e..4ae1d6d 100644
--- a/gcc/rust/resolve/rust-finalize-imports-2.0.h
+++ b/gcc/rust/resolve/rust-finalize-imports-2.0.h
@@ -18,6 +18,7 @@
#include "rust-ast.h"
#include "rust-expr.h"
+#include "rust-item.h"
#include "rust-name-resolution-context.h"
#include "rust-toplevel-name-resolver-2.0.h"
#include "rust-early-name-resolver-2.0.h"
@@ -32,7 +33,11 @@ class GlobbingVisitor : public AST::DefaultASTVisitor
public:
GlobbingVisitor (NameResolutionContext &ctx) : ctx (ctx) {}
- void go (AST::Module *module);
+ void go (AST::Item *container);
+
+ void visit_module_container (AST::Module &module);
+ void visit_enum_container (AST::Enum &item);
+
void visit (AST::Module &module) override;
void visit (AST::MacroRulesDefinition &macro) override;
void visit (AST::Function &function) override;
diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h
index 81468e5..75dd873 100644
--- a/gcc/rust/resolve/rust-forever-stack.h
+++ b/gcc/rust/resolve/rust-forever-stack.h
@@ -543,6 +543,13 @@ private:
Node root;
};
+enum class ResolutionMode
+{
+ Normal,
+ FromRoot,
+ FromExtern, // extern prelude
+};
+
template <Namespace N> class ForeverStack
{
public:
@@ -672,14 +679,11 @@ public:
*/
template <typename S>
tl::optional<Rib::Definition> resolve_path (
- const std::vector<S> &segments, bool has_opening_scope_resolution,
+ const std::vector<S> &segments, ResolutionMode mode,
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;
-
- // FIXME: Documentation
tl::optional<Rib &> to_rib (NodeId rib_id);
tl::optional<const Rib &> to_rib (NodeId rib_id) const;
@@ -739,6 +743,9 @@ private:
tl::optional<Node &> parent; // `None` only if the node is a root
};
+ // private overload which allows specifying a starting point
+ tl::optional<Rib::Definition> get (Node &start, const Identifier &name);
+
/* Should we keep going upon seeing a Rib? */
enum class KeepGoing
{
diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx
index 069111ee..1ed87b3 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -291,12 +291,16 @@ ForeverStack<N>::update_cursor (Node &new_cursor)
template <Namespace N>
tl::optional<Rib::Definition>
-ForeverStack<N>::get (const Identifier &name)
+ForeverStack<N>::get (Node &start, const Identifier &name)
{
tl::optional<Rib::Definition> resolved_definition = tl::nullopt;
// TODO: Can we improve the API? have `reverse_iter` return an optional?
- reverse_iter ([&resolved_definition, &name] (Node &current) {
+ reverse_iter (start, [&resolved_definition, &name] (Node &current) {
+ // we can't reference associated types/functions like this
+ if (current.rib.kind == Rib::Kind::TraitOrImpl)
+ return KeepGoing::Yes;
+
auto candidate = current.rib.get (name.as_string ());
return candidate.map_or (
@@ -320,6 +324,13 @@ ForeverStack<N>::get (const Identifier &name)
template <Namespace N>
tl::optional<Rib::Definition>
+ForeverStack<N>::get (const Identifier &name)
+{
+ return get (cursor (), name);
+}
+
+template <Namespace N>
+tl::optional<Rib::Definition>
ForeverStack<N>::get_lang_prelude (const Identifier &name)
{
return lang_prelude.rib.get (name.as_string ());
@@ -542,6 +553,14 @@ ForeverStack<N>::resolve_segments (
bool searched_prelude = false;
while (true)
{
+ if (is_start (iterator, segments)
+ && current_node->rib.kind == Rib::Kind::TraitOrImpl)
+ {
+ // we can't reference associated types/functions like this
+ current_node = &current_node->parent.value ();
+ continue;
+ }
+
// may set the value of child
for (auto &kv : current_node->children)
{
@@ -625,88 +644,158 @@ template <Namespace N>
template <typename S>
tl::optional<Rib::Definition>
ForeverStack<N>::resolve_path (
- const std::vector<S> &segments, bool has_opening_scope_resolution,
+ const std::vector<S> &segments, ResolutionMode mode,
std::function<void (const S &, NodeId)> insert_segment_resolution,
std::vector<Error> &collect_errors)
{
- // TODO: What to do if segments.empty() ?
+ rust_assert (!segments.empty ());
- // handle paths with opening scopes
- std::function<void (void)> cleanup_current = [] () {};
- if (has_opening_scope_resolution)
+ std::reference_wrapper<Node> starting_point = cursor ();
+ switch (mode)
{
- 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; };
+ case ResolutionMode::Normal:
+ break; // default
+ case ResolutionMode::FromRoot:
+ starting_point = root;
+ break;
+ case ResolutionMode::FromExtern:
+ starting_point = extern_prelude;
+ break;
+ default:
+ rust_unreachable ();
}
// if there's only one segment, we just use `get`
if (segments.size () == 1)
{
- auto &seg = segments.front ();
- if (auto lang_item = unwrap_segment_get_lang_item (seg))
+ auto &outer_seg = segments.front ();
+ if (auto lang_item = unwrap_segment_get_lang_item (outer_seg))
{
NodeId seg_id = Analysis::Mappings::get ().get_lang_item_node (
lang_item.value ());
- insert_segment_resolution (seg, seg_id);
- cleanup_current ();
+ insert_segment_resolution (outer_seg, seg_id);
// TODO: does NonShadowable matter?
return Rib::Definition::NonShadowable (seg_id);
}
+ auto &seg = unwrap_type_segment (outer_seg);
+
tl::optional<Rib::Definition> res
- = get (unwrap_type_segment (segments.back ()).as_string ());
+ = get (starting_point.get (), seg.as_string ());
if (!res)
- res = get_lang_prelude (
- unwrap_type_segment (segments.back ()).as_string ());
+ res = get_lang_prelude (seg.as_string ());
+
+ if (N == Namespace::Types && !res)
+ {
+ if (seg.is_crate_path_seg ())
+ {
+ insert_segment_resolution (outer_seg, root.id);
+ // TODO: does NonShadowable matter?
+ return Rib::Definition::NonShadowable (root.id);
+ }
+ else if (seg.is_lower_self_seg ())
+ {
+ NodeId id = find_closest_module (starting_point.get ()).id;
+ insert_segment_resolution (outer_seg, id);
+ // TODO: does NonShadowable matter?
+ return Rib::Definition::NonShadowable (id);
+ }
+ else if (seg.is_super_path_seg ())
+ {
+ Node &closest_module
+ = find_closest_module (starting_point.get ());
+ if (closest_module.is_root ())
+ {
+ rust_error_at (seg.get_locus (), ErrorCode::E0433,
+ "too many leading %<super%> keywords");
+ return tl::nullopt;
+ }
+
+ NodeId id
+ = find_closest_module (closest_module.parent.value ()).id;
+ insert_segment_resolution (outer_seg, id);
+ // TODO: does NonShadowable matter?
+ return Rib::Definition::NonShadowable (id);
+ }
+ else
+ {
+ // HACK: check for a module after we check the language prelude
+ for (auto &kv :
+ find_closest_module (starting_point.get ()).children)
+ {
+ auto &link = kv.first;
+
+ if (link.path.map_or (
+ [&seg] (Identifier path) {
+ auto &path_str = path.as_string ();
+ return path_str == seg.as_string ();
+ },
+ false))
+ {
+ insert_segment_resolution (outer_seg, kv.second.id);
+ return Rib::Definition::NonShadowable (kv.second.id);
+ }
+ }
+ }
+ }
if (res && !res->is_ambiguous ())
- insert_segment_resolution (segments.back (), res->get_node_id ());
- cleanup_current ();
+ insert_segment_resolution (outer_seg, res->get_node_id ());
return res;
}
- std::reference_wrapper<Node> starting_point = cursor ();
+ return 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);
- 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;
+ if (N == Namespace::Types && !res)
+ {
+ // HACK: check for a module after we check the language prelude
+ for (auto &kv : final_node.children)
+ {
+ auto &link = kv.first;
+
+ if (link.path.map_or (
+ [&seg_name] (Identifier path) {
+ auto &path_str = path.as_string ();
+ return path_str == seg_name;
+ },
+ false))
+ {
+ insert_segment_resolution (segments.back (), kv.second.id);
+ return Rib::Definition::NonShadowable (kv.second.id);
+ }
+ }
+ }
+
+ if (res && !res->is_ambiguous ())
+ insert_segment_resolution (segments.back (), res->get_node_id ());
+
+ return res;
+ });
}
template <Namespace N>
@@ -771,67 +860,6 @@ ForeverStack<N>::dfs (const ForeverStack<N>::Node &starting_point,
}
template <Namespace N>
-tl::optional<Resolver::CanonicalPath>
-ForeverStack<N>::to_canonical_path (NodeId id) const
-{
- // find the id in the current forever stack, starting from the root,
- // performing either a BFS or DFS once the Node containing the ID is found, go
- // back up to the root (parent().parent().parent()...) accumulate link
- // segments reverse them that's your canonical path
-
- return dfs (root, id).map ([this, id] (ConstDfsResult tuple) {
- auto containing_node = tuple.first;
- auto name = tuple.second;
-
- auto segments = std::vector<Resolver::CanonicalPath> ();
-
- reverse_iter (containing_node, [&segments] (const Node &current) {
- if (current.is_root ())
- return KeepGoing::No;
-
- auto children = current.parent.value ().children;
- const Link *outer_link = nullptr;
-
- for (auto &kv : children)
- {
- auto &link = kv.first;
- auto &child = kv.second;
-
- if (current.id == child.id)
- {
- outer_link = &link;
- break;
- }
- }
-
- rust_assert (outer_link);
-
- outer_link->path.map ([&segments, outer_link] (Identifier path) {
- segments.emplace (segments.begin (),
- Resolver::CanonicalPath::new_seg (outer_link->id,
- path.as_string ()));
- });
-
- return KeepGoing::Yes;
- });
-
- auto &mappings = Analysis::Mappings::get ();
- CrateNum crate_num = mappings.lookup_crate_num (root.id).value ();
- auto path = Resolver::CanonicalPath::new_seg (
- root.id, mappings.get_crate_name (crate_num).value ());
- path.set_crate_num (crate_num);
-
- for (const auto &segment : segments)
- path = path.append (segment);
-
- // Finally, append the name
- path = path.append (Resolver::CanonicalPath::new_seg (id, name));
-
- return path;
- });
-}
-
-template <Namespace N>
tl::optional<Rib &>
ForeverStack<N>::dfs_rib (ForeverStack<N>::Node &starting_point, NodeId to_find)
{
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 a15e17f..e39ca15 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
@@ -19,6 +19,7 @@
#include "optional.h"
#include "rust-ast-full.h"
#include "rust-diagnostics.h"
+#include "rust-expr.h"
#include "rust-hir-map.h"
#include "rust-late-name-resolver-2.0.h"
#include "rust-default-resolver.h"
@@ -33,7 +34,9 @@
namespace Rust {
namespace Resolver2_0 {
-Late::Late (NameResolutionContext &ctx) : DefaultResolver (ctx) {}
+Late::Late (NameResolutionContext &ctx)
+ : DefaultResolver (ctx), funny_error (false), block_big_self (false)
+{}
static NodeId
next_node_id ()
@@ -114,8 +117,7 @@ Late::go (AST::Crate &crate)
{
setup_builtin_types ();
- for (auto &item : crate.items)
- item->accept_vis (*this);
+ visit (crate);
}
void
@@ -140,24 +142,21 @@ Late::visit (AST::ForLoopExpr &expr)
ctx.bindings.exit ();
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 ());
}
void
-Late::visit (AST::IfLetExpr &expr)
+Late::visit_if_let_patterns (AST::IfLetExpr &expr)
{
- visit_outer_attrs (expr);
+ ctx.bindings.enter (BindingSource::IfLet);
- ctx.bindings.enter (BindingSource::Let);
-
- for (auto &pattern : expr.get_patterns ())
- visit (pattern);
+ DefaultResolver::visit_if_let_patterns (expr);
ctx.bindings.exit ();
-
- visit (expr.get_value_expr ());
- visit (expr.get_if_block ());
}
void
@@ -214,45 +213,80 @@ Late::visit (AST::LetStmt &let)
}
void
-Late::visit (AST::IdentifierPattern &identifier)
+Late::visit (AST::WhileLetLoopExpr &while_let)
+{
+ DefaultASTVisitor::visit_outer_attrs (while_let);
+
+ if (while_let.has_loop_label ())
+ visit (while_let.get_loop_label ());
+
+ // visit expression before pattern
+ // this makes variable shadowing work properly
+ visit (while_let.get_scrutinee_expr ());
+
+ ctx.bindings.enter (BindingSource::WhileLet);
+
+ for (auto &pattern : while_let.get_patterns ())
+ visit (pattern);
+
+ ctx.bindings.exit ();
+
+ visit (while_let.get_loop_block ());
+}
+
+static void
+visit_identifier_as_pattern (NameResolutionContext &ctx,
+ const Identifier &ident, location_t locus,
+ NodeId node_id, bool is_ref, bool is_mut)
{
// do we insert in labels or in values
// but values does not allow shadowing... since functions cannot shadow
// do we insert functions in labels as well?
- if (ctx.bindings.peek ().is_and_bound (identifier.get_ident ()))
+ if (ctx.bindings.peek ().is_and_bound (ident))
{
if (ctx.bindings.peek ().get_source () == BindingSource::Param)
rust_error_at (
- identifier.get_locus (), ErrorCode::E0415,
+ locus, ErrorCode::E0415,
"identifier %qs is bound more than once in the same parameter list",
- identifier.as_string ().c_str ());
+ ident.as_string ().c_str ());
else
rust_error_at (
- identifier.get_locus (), ErrorCode::E0416,
+ locus, ErrorCode::E0416,
"identifier %qs is bound more than once in the same pattern",
- identifier.as_string ().c_str ());
+ ident.as_string ().c_str ());
return;
}
- ctx.bindings.peek ().insert_ident (identifier.get_ident ());
+ ctx.bindings.peek ().insert_ident (ident.as_string (), locus, is_ref, is_mut);
- if (ctx.bindings.peek ().is_or_bound (identifier.get_ident ()))
+ if (ctx.bindings.peek ().is_or_bound (ident))
{
- // FIXME: map usage instead
- std::ignore = ctx.values.insert_shadowable (identifier.get_ident (),
- identifier.get_node_id ());
+ auto res = ctx.values.get (ident);
+ rust_assert (res.has_value () && !res->is_ambiguous ());
+ ctx.map_usage (Usage (node_id), Definition (res->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 ());
+ std::ignore = ctx.values.insert_shadowable (ident, node_id);
}
}
void
+Late::visit (AST::IdentifierPattern &identifier)
+{
+ DefaultResolver::visit (identifier);
+
+ visit_identifier_as_pattern (ctx, identifier.get_ident (),
+ identifier.get_locus (),
+ identifier.get_node_id (),
+ identifier.get_is_ref (),
+ identifier.get_is_mut ());
+}
+
+void
Late::visit (AST::AltPattern &pattern)
{
ctx.bindings.peek ().push (Binding::Kind::Or);
@@ -279,9 +313,9 @@ Late::visit_function_params (AST::Function &function)
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 (field.get_identifier (),
- field.get_node_id ());
+ visit_identifier_as_pattern (ctx, field.get_identifier (), field.get_locus (),
+ field.get_node_id (), field.is_ref (),
+ field.is_mut ());
}
void
@@ -375,7 +409,8 @@ Late::visit (AST::IdentifierExpr &expr)
}
else if (funny_error)
{
- diagnostics::text_finalizer (global_dc) = Resolver::funny_ice_text_finalizer;
+ diagnostics::text_finalizer (global_dc)
+ = Resolver::funny_ice_text_finalizer;
emit_diagnostic (diagnostics::kind::ice_nobt, expr.get_locus (), -1,
"are you trying to break %s? how dare you?",
expr.as_string ().c_str ());
@@ -477,6 +512,16 @@ Late::visit (AST::PathInExpression &expr)
}
void
+Late::visit_impl_type (AST::Type &type)
+{
+ // TODO: does this have to handle reentrancy?
+ rust_assert (!block_big_self);
+ block_big_self = true;
+ visit (type);
+ block_big_self = false;
+}
+
+void
Late::visit (AST::TypePath &type)
{
// should we add type path resolution in `ForeverStack` directly? Since it's
@@ -486,6 +531,16 @@ Late::visit (AST::TypePath &type)
DefaultResolver::visit (type);
+ // prevent "impl Self {}" and similar
+ if (type.get_segments ().size () == 1
+ && !type.get_segments ().front ()->is_lang_item ()
+ && type.get_segments ().front ()->is_big_self_seg () && block_big_self)
+ {
+ rust_error_at (type.get_locus (),
+ "%<Self%> is not valid in the self type of an impl block");
+ return;
+ }
+
// this *should* mostly work
// TODO: make sure typepath-like path resolution (?) is working
auto resolved = ctx.resolve_path (type, Namespace::Types);
@@ -493,15 +548,16 @@ Late::visit (AST::TypePath &type)
if (!resolved.has_value ())
{
if (!ctx.lookup (type.get_segments ().front ()->get_node_id ()))
- rust_error_at (type.get_locus (), "could not resolve type path %qs",
- type.as_string ().c_str ());
+ rust_error_at (type.get_locus (), ErrorCode::E0412,
+ "could not resolve type path %qs",
+ type.make_debug_string ().c_str ());
return;
}
if (resolved->is_ambiguous ())
{
rust_error_at (type.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
- type.as_string ().c_str ());
+ type.make_debug_string ().c_str ());
return;
}
@@ -518,6 +574,62 @@ Late::visit (AST::TypePath &type)
}
void
+Late::visit (AST::Visibility &vis)
+{
+ if (!vis.has_path ())
+ return;
+
+ AST::SimplePath &path = vis.get_path ();
+
+ rust_assert (path.get_segments ().size ());
+ auto &first_seg = path.get_segments ()[0];
+
+ auto mode = ResolutionMode::Normal;
+
+ if (path.has_opening_scope_resolution ())
+ {
+ if (get_rust_edition () == Edition::E2015)
+ mode = ResolutionMode::FromRoot;
+ else
+ mode = ResolutionMode::FromExtern;
+ }
+ else if (!first_seg.is_crate_path_seg () && !first_seg.is_super_path_seg ()
+ && !first_seg.is_lower_self_seg ())
+ {
+ if (get_rust_edition () == Edition::E2015)
+ {
+ mode = ResolutionMode::FromRoot;
+ }
+ else
+ {
+ rust_error_at (path.get_locus (),
+ "relative paths are not supported in visibilities in "
+ "2018 edition or later");
+ return;
+ }
+ }
+
+ auto res = ctx.resolve_path (path.get_segments (), mode, Namespace::Types);
+
+ if (!res.has_value ())
+ {
+ rust_error_at (path.get_locus (), ErrorCode::E0433,
+ "could not resolve path %qs", path.as_string ().c_str ());
+ return;
+ }
+
+ // TODO: is this possible?
+ if (res->is_ambiguous ())
+ {
+ rust_error_at (path.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
+ path.as_string ().c_str ());
+ return;
+ }
+
+ ctx.map_usage (Usage (path.get_node_id ()), Definition (res->get_node_id ()));
+}
+
+void
Late::visit (AST::Trait &trait)
{
// kind of weird how this is done
@@ -531,13 +643,6 @@ Late::visit (AST::Trait &trait)
}
void
-Late::visit (AST::StructStruct &s)
-{
- auto s_vis = [this, &s] () { AST::DefaultASTVisitor::visit (s); };
- ctx.scoped (Rib::Kind::Item, s.get_node_id (), s_vis);
-}
-
-void
Late::visit (AST::StructExprStruct &s)
{
visit_outer_attrs (s);
@@ -613,51 +718,27 @@ Late::visit (AST::GenericArg &arg)
DefaultResolver::visit (arg);
}
-template <class Closure>
-static void
-add_captures (Closure &closure, NameResolutionContext &ctx)
-{
- auto vals = ctx.values.peek ().get_values ();
- for (auto &val : vals)
- {
- ctx.mappings.add_capture (closure.get_node_id (),
- val.second.get_node_id ());
- }
-}
-
void
-Late::visit (AST::ClosureExprInner &closure)
+Late::visit_closure_params (AST::ClosureExpr &closure)
{
- add_captures (closure, ctx);
-
- visit_outer_attrs (closure);
-
ctx.bindings.enter (BindingSource::Param);
- for (auto &param : closure.get_params ())
- visit (param);
+ DefaultResolver::visit_closure_params (closure);
ctx.bindings.exit ();
-
- visit (closure.get_definition_expr ());
}
void
-Late::visit (AST::ClosureExprInnerTyped &closure)
+Late::visit (AST::ClosureExpr &expr)
{
- add_captures (closure, ctx);
-
- visit_outer_attrs (closure);
-
- ctx.bindings.enter (BindingSource::Param);
-
- for (auto &param : closure.get_params ())
- visit (param);
-
- ctx.bindings.exit ();
+ // add captures
+ auto vals = ctx.values.peek ().get_values ();
+ for (auto &val : vals)
+ {
+ ctx.mappings.add_capture (expr.get_node_id (), val.second.get_node_id ());
+ }
- visit (closure.get_return_type ());
- visit (closure.get_definition_block ());
+ DefaultResolver::visit (expr);
}
} // 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 171d9bf..95540e3 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h
@@ -42,6 +42,7 @@ public:
// some more label declarations
void visit (AST::LetStmt &) override;
+ void visit (AST::WhileLetLoopExpr &) override;
// TODO: Do we need this?
// void visit (AST::Method &) override;
void visit (AST::IdentifierPattern &) override;
@@ -50,7 +51,7 @@ public:
void visit (AST::SelfParam &) override;
void visit (AST::MatchArm &) override;
void visit (AST::ForLoopExpr &) override;
- void visit (AST::IfLetExpr &) override;
+ void visit_if_let_patterns (AST::IfLetExpr &) override;
// resolutions
void visit (AST::IdentifierExpr &) override;
@@ -59,16 +60,17 @@ public:
void visit (AST::ContinueExpr &) override;
void visit (AST::LoopLabel &) override;
void visit (AST::PathInExpression &) override;
+ void visit_impl_type (AST::Type &) override;
void visit (AST::TypePath &) override;
+ void visit (AST::Visibility &) override;
void visit (AST::Trait &) override;
void visit (AST::StructExprStruct &) override;
void visit (AST::StructExprStructBase &) override;
void visit (AST::StructExprStructFields &) override;
- void visit (AST::StructStruct &) override;
void visit (AST::GenericArgs &) override;
void visit (AST::GenericArg &);
- void visit (AST::ClosureExprInner &) override;
- void visit (AST::ClosureExprInnerTyped &) override;
+ void visit_closure_params (AST::ClosureExpr &) override;
+ void visit (AST::ClosureExpr &) override;
private:
void resolve_label (AST::Lifetime &lifetime);
@@ -77,6 +79,9 @@ private:
void setup_builtin_types ();
bool funny_error;
+
+ /* used to prevent "impl Self {}", "impl (Self, i32) {}", etc */
+ bool block_big_self;
};
// TODO: Add missing mappings and data structures
diff --git a/gcc/rust/resolve/rust-name-resolution-context.cc b/gcc/rust/resolve/rust-name-resolution-context.cc
index f098e48..1b84f1d 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.cc
+++ b/gcc/rust/resolve/rust-name-resolution-context.cc
@@ -33,7 +33,8 @@ BindingLayer::bind_test (Identifier ident, Binding::Kind kind)
{
for (auto &bind : bindings)
{
- if (bind.set.find (ident) != bind.set.cend () && bind.kind == kind)
+ if (bind.idents.find (ident.as_string ()) != bind.idents.cend ()
+ && bind.kind == kind)
{
return true;
}
@@ -60,20 +61,66 @@ BindingLayer::is_or_bound (Identifier ident)
}
void
-BindingLayer::insert_ident (Identifier ident)
+BindingLayer::insert_ident (std::string ident, location_t locus, bool is_ref,
+ bool is_mut)
{
- bindings.back ().set.insert (ident);
+ bindings.back ().idents.emplace (
+ std::move (ident), std::make_pair (locus, IdentifierMode (is_ref, is_mut)));
}
void
BindingLayer::merge ()
{
- auto last_binding = bindings.back ();
+ auto last_binding = std::move (bindings.back ());
bindings.pop_back ();
- for (auto &value : last_binding.set)
+
+ if (bindings.back ().has_expected_bindings)
+ {
+ for (auto &value : bindings.back ().idents)
+ {
+ auto ident = value.first;
+ if (last_binding.idents.find (ident) == last_binding.idents.end ())
+ {
+ location_t locus = value.second.first;
+ rust_error_at (locus, ErrorCode::E0408,
+ "variable %qs is not bound in all patterns",
+ ident.c_str ());
+ }
+ }
+ }
+
+ for (auto &value : last_binding.idents)
{
- bindings.back ().set.insert (value);
+ auto res = bindings.back ().idents.emplace (value);
+ if (res.second)
+ {
+ if (bindings.back ().has_expected_bindings)
+ {
+ auto &ident = value.first;
+ location_t locus = value.second.first;
+ rust_error_at (locus, ErrorCode::E0408,
+ "variable %qs is not bound in all patterns",
+ ident.c_str ());
+ }
+ }
+ else
+ {
+ auto this_mode = value.second.second;
+ auto other_mode = res.first->second.second;
+ if (this_mode != other_mode)
+ {
+ auto &ident = value.first;
+ location_t locus = value.second.first;
+ rust_error_at (locus, ErrorCode::E0409,
+ "variable %qs is bound inconsistently across "
+ "pattern alternatives",
+ ident.c_str ());
+ }
+ }
}
+
+ if (bindings.back ().kind == Binding::Kind::Or)
+ bindings.back ().has_expected_bindings = true;
}
BindingSource
@@ -82,8 +129,63 @@ BindingLayer::get_source () const
return source;
}
+Resolver::CanonicalPath
+CanonicalPathRecordCrateRoot::as_path (const NameResolutionContext &)
+{
+ auto ret = Resolver::CanonicalPath::new_seg (node_id, seg);
+ ret.set_crate_num (crate_num);
+ return ret;
+}
+
+Resolver::CanonicalPath
+CanonicalPathRecordNormal::as_path (const NameResolutionContext &ctx)
+{
+ auto parent_path = get_parent ().as_path (ctx);
+ return parent_path.append (Resolver::CanonicalPath::new_seg (node_id, seg));
+}
+
+Resolver::CanonicalPath
+CanonicalPathRecordLookup::as_path (const NameResolutionContext &ctx)
+{
+ if (!cache)
+ {
+ auto res = ctx.lookup (lookup_id).and_then (
+ [&ctx] (NodeId id) { return ctx.canonical_ctx.get_record_opt (id); });
+
+ if (!res)
+ {
+ // HACK: use a dummy value
+ // this should bring us roughly to parity with nr1.0
+ // since nr1.0 doesn't seem to handle canonical paths for generics
+ // quite right anyways
+ return Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, "XXX");
+ }
+
+ cache = res.value ();
+ }
+ return cache->as_path (ctx);
+}
+
+Resolver::CanonicalPath
+CanonicalPathRecordImpl::as_path (const NameResolutionContext &ctx)
+{
+ auto parent_path = get_parent ().as_path (ctx);
+ return parent_path.append (
+ Resolver::CanonicalPath::inherent_impl_seg (impl_id,
+ type_record.as_path (ctx)));
+}
+
+Resolver::CanonicalPath
+CanonicalPathRecordTraitImpl::as_path (const NameResolutionContext &ctx)
+{
+ auto parent_path = get_parent ().as_path (ctx);
+ return parent_path.append (
+ Resolver::CanonicalPath::trait_impl_projection_seg (
+ impl_id, trait_path_record.as_path (ctx), type_record.as_path (ctx)));
+}
+
NameResolutionContext::NameResolutionContext ()
- : mappings (Analysis::Mappings::get ())
+ : mappings (Analysis::Mappings::get ()), canonical_ctx (*this)
{}
tl::expected<NodeId, DuplicateNameError>
diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h
index 19ba750..558b3ca 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.h
+++ b/gcc/rust/resolve/rust-name-resolution-context.h
@@ -24,6 +24,7 @@
#include "rust-hir-map.h"
#include "rust-rib.h"
#include "rust-stacked-contexts.h"
+#include "rust-item.h"
namespace Rust {
namespace Resolver2_0 {
@@ -157,6 +158,22 @@ public:
NodeId id;
};
+struct IdentifierMode
+{
+ bool is_ref;
+ bool is_mut;
+
+ IdentifierMode (bool is_ref, bool is_mut) : is_ref (is_ref), is_mut (is_mut)
+ {}
+
+ bool operator== (const IdentifierMode &other)
+ {
+ return other.is_ref == is_ref && other.is_mut == is_mut;
+ }
+
+ bool operator!= (const IdentifierMode &other) { return !(*this == other); }
+};
+
struct Binding
{
enum class Kind
@@ -165,9 +182,12 @@ struct Binding
Or,
} kind;
- std::unordered_set<Identifier> set;
+ // used to check the correctness of or-bindings
+ bool has_expected_bindings;
- Binding (Binding::Kind kind) : kind (kind) {}
+ std::unordered_map<std::string, std::pair<location_t, IdentifierMode>> idents;
+
+ Binding (Binding::Kind kind) : kind (kind), has_expected_bindings (false) {}
};
/**
@@ -177,6 +197,8 @@ enum class BindingSource
{
Match,
Let,
+ IfLet,
+ WhileLet,
For,
/* Closure param or function param */
Param
@@ -206,13 +228,256 @@ public:
*/
bool is_or_bound (Identifier ident);
- void insert_ident (Identifier ident);
+ void insert_ident (std::string ident, location_t locus, bool is_ref,
+ bool is_mut);
void merge ();
BindingSource get_source () const;
};
+class NameResolutionContext;
+/*
+ * Used to handle canonical paths
+ * Similar to ForeverStack, but namespace independent and more specialized
+ */
+class CanonicalPathRecord
+{
+public:
+ virtual Resolver::CanonicalPath as_path (const NameResolutionContext &) = 0;
+
+ virtual bool is_root () const = 0;
+
+ virtual ~CanonicalPathRecord () = default;
+};
+
+class CanonicalPathRecordWithParent : public CanonicalPathRecord
+{
+public:
+ CanonicalPathRecordWithParent (CanonicalPathRecord &parent) : parent (&parent)
+ {}
+
+ CanonicalPathRecord &get_parent () { return *parent; }
+
+ bool is_root () const override final { return false; }
+
+private:
+ CanonicalPathRecord *parent;
+};
+
+class CanonicalPathRecordCrateRoot : public CanonicalPathRecord
+{
+public:
+ CanonicalPathRecordCrateRoot (NodeId node_id, std::string seg)
+ : node_id (node_id), seg (std::move (seg))
+ {
+ rust_assert (Analysis::Mappings::get ().node_is_crate (node_id));
+ crate_num = Analysis::Mappings::get ().lookup_crate_num (node_id).value ();
+ }
+
+ Resolver::CanonicalPath as_path (const NameResolutionContext &) override;
+
+ bool is_root () const override final { return true; }
+
+private:
+ NodeId node_id;
+ CrateNum crate_num;
+ std::string seg;
+};
+
+class CanonicalPathRecordNormal : public CanonicalPathRecordWithParent
+{
+public:
+ CanonicalPathRecordNormal (CanonicalPathRecord &parent, NodeId node_id,
+ std::string seg)
+ : CanonicalPathRecordWithParent (parent), node_id (node_id),
+ seg (std::move (seg))
+ {
+ rust_assert (!Analysis::Mappings::get ().node_is_crate (node_id));
+ }
+
+ Resolver::CanonicalPath as_path (const NameResolutionContext &) override;
+
+private:
+ NodeId node_id;
+ std::string seg;
+};
+
+class CanonicalPathRecordLookup : public CanonicalPathRecord
+{
+public:
+ CanonicalPathRecordLookup (NodeId lookup_id)
+ : lookup_id (lookup_id), cache (nullptr)
+ {}
+
+ Resolver::CanonicalPath as_path (const NameResolutionContext &) override;
+
+ bool is_root () const override final { return true; }
+
+private:
+ NodeId lookup_id;
+ CanonicalPathRecord *cache;
+};
+
+class CanonicalPathRecordImpl : public CanonicalPathRecordWithParent
+{
+public:
+ CanonicalPathRecordImpl (CanonicalPathRecord &parent, NodeId impl_id,
+ NodeId type_id)
+ : CanonicalPathRecordWithParent (parent), impl_id (impl_id),
+ type_record (type_id)
+ {}
+
+ Resolver::CanonicalPath as_path (const NameResolutionContext &) override;
+
+private:
+ NodeId impl_id;
+ CanonicalPathRecordLookup type_record;
+};
+
+class CanonicalPathRecordTraitImpl : public CanonicalPathRecordWithParent
+{
+public:
+ CanonicalPathRecordTraitImpl (CanonicalPathRecord &parent, NodeId impl_id,
+ NodeId type_id, NodeId trait_path_id)
+ : CanonicalPathRecordWithParent (parent), impl_id (impl_id),
+ type_record (type_id), trait_path_record (trait_path_id)
+ {}
+
+ Resolver::CanonicalPath as_path (const NameResolutionContext &) override;
+
+private:
+ NodeId impl_id;
+ CanonicalPathRecordLookup type_record;
+ CanonicalPathRecordLookup trait_path_record;
+};
+
+class CanonicalPathCtx
+{
+public:
+ CanonicalPathCtx (const NameResolutionContext &ctx)
+ : current_record (nullptr), nr_ctx (&ctx)
+ {}
+
+ Resolver::CanonicalPath get_path (NodeId id) const
+ {
+ return get_record (id).as_path (*nr_ctx);
+ }
+
+ CanonicalPathRecord &get_record (NodeId id) const
+ {
+ auto it = records.find (id);
+ rust_assert (it != records.end ());
+ return *it->second;
+ }
+
+ tl::optional<CanonicalPathRecord *> get_record_opt (NodeId id) const
+ {
+ auto it = records.find (id);
+ if (it == records.end ())
+ return tl::nullopt;
+ else
+ return it->second.get ();
+ }
+
+ void insert_record (NodeId id, const Identifier &ident)
+ {
+ insert_record (id, ident.as_string ());
+ }
+
+ void insert_record (NodeId id, std::string seg)
+ {
+ rust_assert (current_record != nullptr);
+
+ auto it = records.find (id);
+ if (it == records.end ())
+ {
+ auto record = new CanonicalPathRecordNormal (*current_record, id,
+ std::move (seg));
+ bool ok
+ = records.emplace (id, std::unique_ptr<CanonicalPathRecord> (record))
+ .second;
+ rust_assert (ok);
+ }
+ }
+
+ template <typename F> void scope (NodeId id, const Identifier &ident, F &&f)
+ {
+ scope (id, ident.as_string (), std::forward<F> (f));
+ }
+
+ template <typename F> void scope (NodeId id, std::string seg, F &&f)
+ {
+ rust_assert (current_record != nullptr);
+
+ scope_inner (id, std::forward<F> (f), [this, id, &seg] () {
+ return new CanonicalPathRecordNormal (*current_record, id,
+ std::move (seg));
+ });
+ }
+
+ template <typename F> void scope_impl (AST::InherentImpl &impl, F &&f)
+ {
+ rust_assert (current_record != nullptr);
+
+ NodeId id = impl.get_node_id ();
+ scope_inner (id, std::forward<F> (f), [this, id, &impl] () {
+ return new CanonicalPathRecordImpl (*current_record, id,
+ impl.get_type ().get_node_id ());
+ });
+ }
+
+ template <typename F> void scope_impl (AST::TraitImpl &impl, F &&f)
+ {
+ rust_assert (current_record != nullptr);
+
+ NodeId id = impl.get_node_id ();
+ scope_inner (id, std::forward<F> (f), [this, id, &impl] () {
+ return new CanonicalPathRecordTraitImpl (
+ *current_record, id, impl.get_type ().get_node_id (),
+ impl.get_trait_path ().get_node_id ());
+ });
+ }
+
+ template <typename F>
+ void scope_crate (NodeId node_id, std::string crate_name, F &&f)
+ {
+ scope_inner (node_id, std::forward<F> (f), [node_id, &crate_name] () {
+ return new CanonicalPathRecordCrateRoot (node_id, std::move (crate_name));
+ });
+ }
+
+private:
+ template <typename FCreate, typename FCallback>
+ void scope_inner (NodeId id, FCallback &&f_callback, FCreate &&f_create)
+ {
+ auto it = records.find (id);
+ if (it == records.end ())
+ {
+ CanonicalPathRecord *record = std::forward<FCreate> (f_create) ();
+ it = records.emplace (id, std::unique_ptr<CanonicalPathRecord> (record))
+ .first;
+ }
+
+ rust_assert (it->second->is_root ()
+ || &static_cast<CanonicalPathRecordWithParent &> (*it->second)
+ .get_parent ()
+ == current_record);
+
+ CanonicalPathRecord *stash = it->second.get ();
+ std::swap (stash, current_record);
+
+ std::forward<FCallback> (f_callback) ();
+
+ std::swap (stash, current_record);
+ }
+
+ std::unordered_map<NodeId, std::unique_ptr<CanonicalPathRecord>> records;
+ CanonicalPathRecord *current_record;
+
+ const NameResolutionContext *nr_ctx;
+};
+
// Now our resolver, which keeps track of all the `ForeverStack`s we could want
class NameResolutionContext
{
@@ -271,16 +536,22 @@ public:
Analysis::Mappings &mappings;
StackedContexts<BindingLayer> bindings;
+ CanonicalPathCtx canonical_ctx;
+
// TODO: Rename
// TODO: Use newtype pattern for Usage and Definition
void map_usage (Usage usage, Definition definition);
tl::optional<NodeId> lookup (NodeId usage) const;
+ Resolver::CanonicalPath to_canonical_path (NodeId id) const
+ {
+ return canonical_ctx.get_path (id);
+ }
+
template <typename S>
tl::optional<Rib::Definition>
- resolve_path (const std::vector<S> &segments,
- bool has_opening_scope_resolution,
+ resolve_path (const std::vector<S> &segments, ResolutionMode mode,
std::vector<Error> &collect_errors, Namespace ns)
{
std::function<void (const S &, NodeId)> insert_segment_resolution
@@ -292,17 +563,17 @@ public:
switch (ns)
{
case Namespace::Values:
- return values.resolve_path (segments, has_opening_scope_resolution,
- insert_segment_resolution, collect_errors);
+ return values.resolve_path (segments, mode, insert_segment_resolution,
+ collect_errors);
case Namespace::Types:
- return types.resolve_path (segments, has_opening_scope_resolution,
- insert_segment_resolution, collect_errors);
+ return types.resolve_path (segments, mode, insert_segment_resolution,
+ collect_errors);
case Namespace::Macros:
- return macros.resolve_path (segments, has_opening_scope_resolution,
- insert_segment_resolution, collect_errors);
+ return macros.resolve_path (segments, mode, insert_segment_resolution,
+ collect_errors);
case Namespace::Labels:
- return labels.resolve_path (segments, has_opening_scope_resolution,
- insert_segment_resolution, collect_errors);
+ return labels.resolve_path (segments, mode, insert_segment_resolution,
+ collect_errors);
default:
rust_unreachable ();
}
@@ -310,8 +581,7 @@ public:
template <typename S, typename... Args>
tl::optional<Rib::Definition>
- resolve_path (const std::vector<S> &segments,
- bool has_opening_scope_resolution,
+ resolve_path (const std::vector<S> &segments, ResolutionMode mode,
tl::optional<std::vector<Error> &> collect_errors,
Namespace ns_first, Args... ns_args)
{
@@ -320,8 +590,7 @@ public:
for (auto ns : namespaces)
{
std::vector<Error> collect_errors_inner;
- if (auto ret = resolve_path (segments, has_opening_scope_resolution,
- collect_errors_inner, ns))
+ if (auto ret = resolve_path (segments, mode, collect_errors_inner, ns))
return ret;
if (!collect_errors_inner.empty ())
{
@@ -343,52 +612,68 @@ public:
return tl::nullopt;
}
- template <typename... Args>
+ template <typename S, typename... Args>
tl::optional<Rib::Definition>
- resolve_path (const AST::SimplePath &path,
+ resolve_path (const std::vector<S> &path_segments,
+ bool has_opening_scope_resolution,
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...);
+ auto mode = ResolutionMode::Normal;
+ if (has_opening_scope_resolution)
+ {
+ if (get_rust_edition () == Edition::E2015)
+ mode = ResolutionMode::FromRoot;
+ else
+ mode = ResolutionMode::FromExtern;
+ }
+ return resolve_path (path_segments, mode, collect_errors, ns_first,
+ ns_args...);
}
- template <typename... Args>
+ template <typename S, 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)
+ resolve_path (const std::vector<S> &path_segments,
+ bool has_opening_scope_resolution, Namespace ns_first,
+ Args... ns_args)
{
- return resolve_path (path.get_segments (), path.opening_scope_resolution (),
- collect_errors, ns_first, ns_args...);
+ return resolve_path (path_segments, has_opening_scope_resolution,
+ tl::nullopt, ns_first, ns_args...);
}
- template <typename... Args>
+ template <typename S, typename... Args>
tl::optional<Rib::Definition>
- resolve_path (const AST::TypePath &path,
- tl::optional<std::vector<Error> &> collect_errors,
+ resolve_path (const std::vector<S> &path_segments, ResolutionMode mode,
Namespace ns_first, Args... ns_args)
{
+ return resolve_path (path_segments, mode, tl::nullopt, ns_first,
+ ns_args...);
+ }
+
+ template <typename... Args>
+ tl::optional<Rib::Definition> resolve_path (const AST::SimplePath &path,
+ Args &&...args)
+ {
return resolve_path (path.get_segments (),
- path.has_opening_scope_resolution_op (),
- collect_errors, ns_first, ns_args...);
+ path.has_opening_scope_resolution (),
+ std::forward<Args> (args)...);
}
- template <typename P, typename... Args>
- tl::optional<Rib::Definition> resolve_path (const P &path, Namespace ns_first,
- Args... ns_args)
+ template <typename... Args>
+ tl::optional<Rib::Definition> resolve_path (const AST::PathInExpression &path,
+ Args &&...args)
{
- return resolve_path (path, tl::nullopt, ns_first, ns_args...);
+ return resolve_path (path.get_segments (), path.opening_scope_resolution (),
+ std::forward<Args> (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)
+ template <typename... Args>
+ tl::optional<Rib::Definition> resolve_path (const AST::TypePath &path,
+ Args &&...args)
{
- return resolve_path (path_segments, has_opening_scope_resolution,
- tl::nullopt, ns_first, ns_args...);
+ return resolve_path (path.get_segments (),
+ path.has_opening_scope_resolution_op (),
+ std::forward<Args> (args)...);
}
private:
diff --git a/gcc/rust/resolve/rust-rib.h b/gcc/rust/resolve/rust-rib.h
index c498328..140c991 100644
--- a/gcc/rust/resolve/rust-rib.h
+++ b/gcc/rust/resolve/rust-rib.h
@@ -188,6 +188,8 @@ public:
* restriction that you cannot `use` items from the Prelude
*/
Prelude,
+ /* Generic rib, used to store generics */
+ Generics,
} kind;
static std::string kind_to_string (Rib::Kind kind)
@@ -214,9 +216,13 @@ public:
return "Forward type param ban";
case Rib::Kind::ConstParamType:
return "Const Param Type";
- default:
- rust_unreachable ();
+ case Kind::Prelude:
+ return "Prelude";
+ case Kind::Generics:
+ return "Generics";
}
+
+ rust_unreachable ();
}
Rib (Kind kind);
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 2f036fe..0930f96 100644
--- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
@@ -95,41 +95,17 @@ TopLevel::go (AST::Crate &crate)
// times in a row in a fixed-point fashion, so it would make the code
// responsible for this ugly and perfom a lot of error checking.
- for (auto &item : crate.items)
- item->accept_vis (*this);
+ visit (crate);
}
void
TopLevel::visit (AST::Module &module)
{
- insert_or_error_out (module.get_name (), module, Namespace::Types);
-
- // Parse the module's items if they haven't been expanded and the file
- // should be parsed (i.e isn't hidden behind an untrue or impossible cfg
- // directive
- // TODO: make sure this is right
- // TODO: avoid loading items if cfg attributes are present?
- // might not be needed if this runs after early resolution?
- // This was copied from the old early resolver method
- // 'accumulate_escaped_macros'
- if (module.get_kind () == AST::Module::UNLOADED)
- {
- 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);
- if (Analysis::Mappings::get ().lookup_ast_module (module.get_node_id ())
+ if (Analysis::Mappings::get ().lookup_glob_container (module.get_node_id ())
== tl::nullopt)
- Analysis::Mappings::get ().insert_ast_module (&module);
+ Analysis::Mappings::get ().insert_glob_container (&module);
}
void
@@ -141,33 +117,10 @@ TopLevel::visit (AST::Trait &trait)
}
void
-TopLevel::visit (AST::InherentImpl &impl)
-{
- auto inner_fn = [this, &impl] () {
- insert_or_error_out (Identifier ("Self", impl.get_type ().get_locus ()),
- impl.get_type (), Namespace::Types);
-
- // We do want to visit with the default visitor instead of default resolver
- // because we don't want to insert the scope twice.
- AST::DefaultASTVisitor::visit (impl);
- };
-
- ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn);
-}
-
-void
-TopLevel::visit (AST::TraitImpl &impl)
+TopLevel::maybe_insert_big_self (AST::Impl &impl)
{
- auto inner_fn = [this, &impl] () {
- insert_or_error_out (Identifier ("Self", impl.get_type ().get_locus ()),
- impl.get_type (), Namespace::Types);
-
- // We do want to visit using the default visitor instead of default resolver
- // because we don't want to insert the scope twice.
- AST::DefaultASTVisitor::visit (impl);
- };
-
- ctx.scoped (Rib::Kind::TraitOrImpl, impl.get_node_id (), inner_fn);
+ insert_or_error_out (Identifier ("Self", impl.get_type ().get_locus ()),
+ impl.get_type (), Namespace::Types);
}
void
@@ -197,19 +150,10 @@ insert_macros (std::vector<PROC_MACRO> &macros, NameResolutionContext &ctx)
}
void
-TopLevel::visit (AST::ExternCrate &crate)
+TopLevel::visit_extern_crate (AST::ExternCrate &extern_crate, AST::Crate &crate,
+ CrateNum num)
{
auto &mappings = Analysis::Mappings::get ();
- auto num_opt = mappings.lookup_crate_name (crate.get_referenced_crate ());
-
- if (!num_opt)
- {
- rust_error_at (crate.get_locus (), "unknown crate %qs",
- crate.get_referenced_crate ().c_str ());
- return;
- }
-
- CrateNum num = *num_opt;
auto attribute_macros = mappings.lookup_attribute_proc_macros (num);
@@ -217,34 +161,27 @@ TopLevel::visit (AST::ExternCrate &crate)
auto derive_macros = mappings.lookup_derive_proc_macros (num);
- auto sub_visitor = [&] () {
- // TODO: Find a way to keep this part clean without the double dispatch.
- if (derive_macros.has_value ())
- {
- insert_macros (derive_macros.value (), ctx);
- for (auto &macro : derive_macros.value ())
- mappings.insert_derive_proc_macro_def (macro);
- }
- if (attribute_macros.has_value ())
- {
- insert_macros (attribute_macros.value (), ctx);
- for (auto &macro : attribute_macros.value ())
- mappings.insert_attribute_proc_macro_def (macro);
- }
- if (bang_macros.has_value ())
- {
- insert_macros (bang_macros.value (), ctx);
- for (auto &macro : bang_macros.value ())
- mappings.insert_bang_proc_macro_def (macro);
- }
- };
+ // TODO: Find a way to keep this part clean without the double dispatch.
+ if (derive_macros.has_value ())
+ {
+ insert_macros (derive_macros.value (), ctx);
+ for (auto &macro : derive_macros.value ())
+ mappings.insert_derive_proc_macro_def (macro);
+ }
+ if (attribute_macros.has_value ())
+ {
+ insert_macros (attribute_macros.value (), ctx);
+ for (auto &macro : attribute_macros.value ())
+ mappings.insert_attribute_proc_macro_def (macro);
+ }
+ if (bang_macros.has_value ())
+ {
+ insert_macros (bang_macros.value (), ctx);
+ for (auto &macro : bang_macros.value ())
+ mappings.insert_bang_proc_macro_def (macro);
+ }
- if (crate.has_as_clause ())
- ctx.scoped (Rib::Kind::Module, crate.get_node_id (), sub_visitor,
- crate.get_as_clause ());
- else
- ctx.scoped (Rib::Kind::Module, crate.get_node_id (), sub_visitor,
- crate.get_referenced_crate ());
+ visit (crate);
}
static bool
@@ -321,14 +258,7 @@ TopLevel::visit (AST::ExternalStaticItem &static_item)
void
TopLevel::visit (AST::StructStruct &struct_item)
{
- auto generic_vis = [this, &struct_item] () {
- for (auto &g : struct_item.get_generic_params ())
- {
- g->accept_vis (*this);
- }
- };
-
- ctx.scoped (Rib::Kind::Item, struct_item.get_node_id (), generic_vis);
+ DefaultResolver::visit (struct_item);
insert_or_error_out (struct_item.get_struct_name (), struct_item,
Namespace::Types);
@@ -374,24 +304,32 @@ void
TopLevel::visit (AST::EnumItem &variant)
{
insert_enum_variant_or_error_out (variant.get_identifier (), variant);
+
+ DefaultResolver::visit (variant);
}
void
TopLevel::visit (AST::EnumItemTuple &variant)
{
insert_enum_variant_or_error_out (variant.get_identifier (), variant);
+
+ DefaultResolver::visit (variant);
}
void
TopLevel::visit (AST::EnumItemStruct &variant)
{
insert_enum_variant_or_error_out (variant.get_identifier (), variant);
+
+ DefaultResolver::visit (variant);
}
void
TopLevel::visit (AST::EnumItemDiscriminant &variant)
{
insert_or_error_out (variant.get_identifier (), variant, Namespace::Types);
+
+ DefaultResolver::visit (variant);
}
void
@@ -401,6 +339,13 @@ TopLevel::visit (AST::Enum &enum_item)
Namespace::Types);
DefaultResolver::visit (enum_item);
+
+ // Since enums can be containers for imports, we need to insert them like we
+ // do for modules
+ if (Analysis::Mappings::get ().lookup_glob_container (
+ enum_item.get_node_id ())
+ == tl::nullopt)
+ Analysis::Mappings::get ().insert_glob_container (&enum_item);
}
void
@@ -430,21 +375,18 @@ TopLevel::visit (AST::TypeAlias &type_item)
DefaultResolver::visit (type_item);
}
-static void
-flatten_rebind (
+static void flatten_rebind (
const AST::UseTreeRebind &glob,
std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths);
-static void
-flatten_list (
+static void flatten_list (
const AST::UseTreeList &glob, std::vector<AST::SimplePath> &paths,
std::vector<AST::SimplePath> &glob_paths,
std::vector<std::pair<AST::SimplePath, AST::UseTreeRebind>> &rebind_paths,
NameResolutionContext &ctx);
-static void
-flatten_glob (const AST::UseTreeGlob &glob,
- std::vector<AST::SimplePath> &glob_paths,
- NameResolutionContext &ctx);
+static void flatten_glob (const AST::UseTreeGlob &glob,
+ std::vector<AST::SimplePath> &glob_paths,
+ NameResolutionContext &ctx);
static void
flatten (
@@ -455,17 +397,20 @@ flatten (
{
switch (tree->get_kind ())
{
- case AST::UseTree::Rebind: {
+ case AST::UseTree::Rebind:
+ {
auto rebind = static_cast<const AST::UseTreeRebind *> (tree);
flatten_rebind (*rebind, rebind_paths);
break;
}
- case AST::UseTree::List: {
+ case AST::UseTree::List:
+ {
auto list = static_cast<const AST::UseTreeList *> (tree);
flatten_list (*list, paths, glob_paths, rebind_paths, ctx);
break;
}
- case AST::UseTree::Glob: {
+ case AST::UseTree::Glob:
+ {
auto glob = static_cast<const AST::UseTreeGlob *> (tree);
flatten_glob (*glob, glob_paths, ctx);
break;
diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
index 3ff37ed..8d3da92 100644
--- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
@@ -160,8 +160,7 @@ private:
void visit (AST::Module &module) override;
void visit (AST::Trait &trait) override;
- void visit (AST::InherentImpl &impl) override;
- void visit (AST::TraitImpl &impl) override;
+ void maybe_insert_big_self (AST::Impl &impl) override;
void visit (AST::TraitItemType &trait_item) override;
void visit (AST::MacroRulesDefinition &macro) override;
void visit (AST::Function &function) override;
@@ -177,7 +176,7 @@ private:
void visit (AST::Union &union_item) override;
void visit (AST::ConstantItem &const_item) override;
void visit (AST::TypeAlias &type_item) override;
- void visit (AST::ExternCrate &crate) override;
+ void visit_extern_crate (AST::ExternCrate &, AST::Crate &, CrateNum) override;
void visit (AST::TypeParam &type_param) override;
void visit (AST::ConstGenericParam &const_param) override;
diff --git a/gcc/rust/rust-attribs.cc b/gcc/rust/rust-attribs.cc
index 74cb2af..a98c1fa 100644
--- a/gcc/rust/rust-attribs.cc
+++ b/gcc/rust/rust-attribs.cc
@@ -38,35 +38,27 @@ along with GCC; see the file COPYING3. If not see
* future.
*/
-extern const attribute_spec grs_langhook_common_attribute_table[];
+extern const struct scoped_attribute_specs grs_langhook_gnu_attribute_table;
+extern const struct scoped_attribute_specs grs_langhook_common_attribute_table;
/* Internal attribute handlers for built-in functions. */
-static tree
-handle_noreturn_attribute (tree *, tree, tree, int, bool *);
-static tree
-handle_leaf_attribute (tree *, tree, tree, int, bool *);
-static tree
-handle_const_attribute (tree *, tree, tree, int, bool *);
-static tree
-handle_malloc_attribute (tree *, tree, tree, int, bool *);
-static tree
-handle_pure_attribute (tree *, tree, tree, int, bool *);
-static tree
-handle_novops_attribute (tree *, tree, tree, int, bool *);
-static tree
-handle_nonnull_attribute (tree *, tree, tree, int, bool *);
-static tree
-handle_nothrow_attribute (tree *, tree, tree, int, bool *);
-static tree
-handle_type_generic_attribute (tree *, tree, tree, int, bool *);
-static tree
-handle_transaction_pure_attribute (tree *, tree, tree, int, bool *);
-static tree
-handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
-static tree
-handle_fnspec_attribute (tree *, tree, tree, int, bool *);
-static tree
-handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *);
+static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
+static tree handle_leaf_attribute (tree *, tree, tree, int, bool *);
+static tree handle_const_attribute (tree *, tree, tree, int, bool *);
+static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
+static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
+static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
+static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
+static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
+static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
+static tree handle_transaction_pure_attribute (tree *, tree, tree, int, bool *);
+static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
+static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
+static tree handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *);
+
+/* Rust attribute handlers for user defined attributes. */
+static tree handle_cold_attribute (tree *, tree, tree, int, bool *);
+static tree handle_hot_attribute (tree *, tree, tree, int, bool *);
/* Helper to define attribute exclusions. */
#define ATTR_EXCL(name, function, type, variable) \
@@ -74,6 +66,10 @@ handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *);
name, function, type, variable \
}
+// clang-format off
+// Disabling clang-format because it insists in having several ATTR_EXCL() on a
+// single line.
+
static const struct attribute_spec::exclusions attr_noreturn_exclusions[] = {
// ATTR_EXCL ("alloc_size", true, true, true),
ATTR_EXCL ("const", true, true, true),
@@ -89,11 +85,22 @@ static const struct attribute_spec::exclusions attr_returns_twice_exclusions[]
ATTR_EXCL (NULL, false, false, false),
};
+extern const struct attribute_spec::exclusions attr_cold_hot_exclusions[] = {
+
+ ATTR_EXCL ("cold", true, true, true),
+ ATTR_EXCL ("hot", true, true, true),
+ ATTR_EXCL (NULL, false, false, false)
+};
+
static const struct attribute_spec::exclusions attr_const_pure_exclusions[] = {
// ATTR_EXCL ("alloc_size", true, true, true),
ATTR_EXCL ("const", true, true, true),
ATTR_EXCL ("noreturn", true, true, true),
- ATTR_EXCL ("pure", true, true, true), ATTR_EXCL (NULL, false, false, false)};
+ ATTR_EXCL ("pure", true, true, true),
+ ATTR_EXCL (NULL, false, false, false)
+};
+
+// clang-format on
/* Helper to define an attribute. */
#define ATTR_SPEC(name, min_len, max_len, decl_req, type_req, fn_type_req, \
@@ -105,7 +112,7 @@ static const struct attribute_spec::exclusions attr_const_pure_exclusions[] = {
/* Table of machine-independent attributes.
For internal use (marking of built-ins) only. */
-const attribute_spec grs_langhook_common_attribute_table[] = {
+static const attribute_spec grs_langhook_common_attributes[] = {
ATTR_SPEC ("noreturn", 0, 0, true, false, false, false,
handle_noreturn_attribute, attr_noreturn_exclusions),
ATTR_SPEC ("leaf", 0, 0, true, false, false, false, handle_leaf_attribute,
@@ -132,9 +139,21 @@ const attribute_spec grs_langhook_common_attribute_table[] = {
NULL),
ATTR_SPEC ("omp declare simd", 0, -1, true, false, false, false,
handle_omp_declare_simd_attribute, NULL),
- ATTR_SPEC (NULL, 0, 0, false, false, false, false, NULL, NULL),
};
+const scoped_attribute_specs grs_langhook_common_attribute_table
+ = {"gnu", {grs_langhook_common_attributes}};
+
+static const attribute_spec grs_langhook_gnu_attributes[] = {
+ ATTR_SPEC ("cold", 0, 0, true, false, false, false, handle_cold_attribute,
+ attr_cold_hot_exclusions),
+ ATTR_SPEC ("hot", 0, 0, true, false, false, false, handle_hot_attribute,
+ attr_cold_hot_exclusions),
+};
+
+const scoped_attribute_specs grs_langhook_gnu_attribute_table
+ = {"gnu", {grs_langhook_gnu_attributes}};
+
/* Built-in attribute handlers.
These functions take the arguments:
(tree *node, tree name, tree args, int flags, bool *no_add_attrs) */
@@ -204,7 +223,7 @@ handle_const_attribute (tree *node, tree, tree, int, bool *)
/* Handle a "malloc" attribute; arguments as in
struct attribute_spec.handler. */
-tree
+static tree
handle_malloc_attribute (tree *node, tree, tree, int, bool *)
{
gcc_assert (TREE_CODE (*node) == FUNCTION_DECL
@@ -217,9 +236,14 @@ handle_malloc_attribute (tree *node, tree, tree, int, bool *)
struct attribute_spec.handler. */
static tree
-handle_pure_attribute (tree *node, tree, tree, int, bool *)
+handle_pure_attribute (tree *node, tree name, tree, int, bool *no_add_attrs)
{
- gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
DECL_PURE_P (*node) = 1;
return NULL_TREE;
}
@@ -228,9 +252,14 @@ handle_pure_attribute (tree *node, tree, tree, int, bool *)
struct attribute_spec.handler. */
static tree
-handle_novops_attribute (tree *node, tree, tree, int, bool *)
+handle_novops_attribute (tree *node, tree name, tree, int, bool *no_add_attrs)
{
- gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
DECL_IS_NOVOPS (*node) = 1;
return NULL_TREE;
}
@@ -301,9 +330,14 @@ handle_nonnull_attribute (tree *node, tree, tree args, int, bool *)
struct attribute_spec.handler. */
static tree
-handle_nothrow_attribute (tree *node, tree, tree, int, bool *)
+handle_nothrow_attribute (tree *node, tree name, tree, int, bool *no_add_attrs)
{
- gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
TREE_NOTHROW (*node) = 1;
return NULL_TREE;
}
@@ -339,9 +373,14 @@ handle_transaction_pure_attribute (tree *node, tree, tree, int, bool *)
struct attribute_spec.handler. */
static tree
-handle_returns_twice_attribute (tree *node, tree, tree, int, bool *)
+handle_returns_twice_attribute (tree *node, tree name, tree, int,
+ bool *no_add_attrs)
{
- gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
DECL_IS_RETURNS_TWICE (*node) = 1;
@@ -351,7 +390,7 @@ handle_returns_twice_attribute (tree *node, tree, tree, int, bool *)
/* Handle a "fn spec" attribute; arguments as in
struct attribute_spec.handler. */
-tree
+static tree
handle_fnspec_attribute (tree *, tree, tree args, int, bool *)
{
gcc_assert (args && TREE_CODE (TREE_VALUE (args)) == STRING_CST
@@ -362,9 +401,46 @@ handle_fnspec_attribute (tree *, tree, tree args, int, bool *)
/* Handle an "omp declare simd" attribute; arguments as in
struct attribute_spec.handler. */
-tree
-handle_omp_declare_simd_attribute (tree *node, tree, tree, int, bool *)
+static tree
+handle_omp_declare_simd_attribute (tree *node, tree name, tree, int,
+ bool *no_add_attrs)
{
- gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Language specific attribute handlers.
+ These functions take the arguments:
+ (tree *node, tree name, tree args, int flags, bool *no_add_attrs) */
+
+/* Handle a "cold" and attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_cold_attribute (tree *node, tree name, tree, int, bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+static tree
+handle_hot_attribute (tree *node, tree name, tree, int, bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
return NULL_TREE;
}
diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h
index 414799e..95ca7a9 100644
--- a/gcc/rust/rust-backend.h
+++ b/gcc/rust/rust-backend.h
@@ -27,6 +27,8 @@
#include "rust-linemap.h"
#include "rust-diagnostics.h"
#include "util/rust-operators.h"
+#include "util/rust-ggc.h"
+#include "util/optional.h"
#include "tree.h"
#include "rust-gcc.h"
@@ -42,69 +44,60 @@ class Bvariable;
namespace Backend {
-void
-init ();
+namespace GGC {
+
+using Rust::GGC::Ident;
+
+} // namespace GGC
+
+void init ();
// Name/type/location. Used for function parameters, struct fields,
// interface methods.
struct typed_identifier
{
- std::string name;
+ GGC::Ident name;
tree type;
location_t location;
- typed_identifier () : name (), type (NULL_TREE), location (UNKNOWN_LOCATION)
- {}
-
- typed_identifier (const std::string &a_name, tree a_type,
- location_t a_location)
+ typed_identifier (GGC::Ident a_name, tree a_type, location_t a_location)
: name (a_name), type (a_type), location (a_location)
{}
};
// debug
void debug (tree);
-void
-debug (Bvariable *);
+void debug (Bvariable *);
-tree
-get_identifier_node (const std::string &str);
+tree get_identifier_node (const std::string &str);
// Types.
// Get the wchar type
-tree
-wchar_type ();
+tree wchar_type ();
// Get the Host pointer size in bits
-int
-get_pointer_size ();
+int get_pointer_size ();
// Get the raw str type const char*
-tree
-raw_str_type ();
+tree raw_str_type ();
// Get an unnamed integer type with the given signedness and number
// of bits.
-tree
-integer_type (bool is_unsigned, int bits);
+tree integer_type (bool is_unsigned, int bits);
// Get an unnamed floating point type with the given number of bits
// (32 or 64).
-tree
-float_type (int bits);
+tree float_type (int bits);
// Get a pointer type.
-tree
-pointer_type (tree to_type);
+tree pointer_type (tree to_type);
// Get a reference type.
-tree
-reference_type (tree to_type);
+tree reference_type (tree to_type);
// make type immutable
-tree
-immutable_type (tree base);
+tree immutable_type (tree base);
// Get a function type. The receiver, parameter, and results are
// generated from the types in the Function_type. The Function_type
@@ -115,41 +108,36 @@ immutable_type (tree base);
// one result, RESULT_STRUCT is a struct type to hold the results,
// and RESULTS may be ignored; if there are zero or one results,
// RESULT_STRUCT is NULL.
-tree
-function_type (const typed_identifier &receiver,
- const std::vector<typed_identifier> &parameters,
- const std::vector<typed_identifier> &results, tree result_struct,
- location_t location);
-
-tree
-function_type_variadic (const typed_identifier &receiver,
- const std::vector<typed_identifier> &parameters,
- const std::vector<typed_identifier> &results,
- tree result_struct, location_t location);
-
-tree
-function_ptr_type (tree result, const std::vector<tree> &praameters,
- location_t location);
+tree function_type (const typed_identifier &receiver,
+ const std::vector<typed_identifier> &parameters,
+ const std::vector<typed_identifier> &results,
+ tree result_struct, location_t location);
+
+tree function_type_variadic (const typed_identifier &receiver,
+ const std::vector<typed_identifier> &parameters,
+ const std::vector<typed_identifier> &results,
+ tree result_struct, location_t location);
+
+tree function_ptr_type (tree result, const std::vector<tree> &praameters,
+ location_t location);
// Get a struct type.
-tree
-struct_type (const std::vector<typed_identifier> &fields, bool layout = true);
+tree struct_type (const std::vector<typed_identifier> &fields,
+ bool layout = true);
// Get a union type.
-tree
-union_type (const std::vector<typed_identifier> &fields, bool layout = true);
+tree union_type (const std::vector<typed_identifier> &fields,
+ bool layout = true);
// Get an array type.
-tree
-array_type (tree element_type, tree length);
+tree array_type (tree element_type, tree length);
// Return a named version of a type. The location is the location
// of the type definition. This will not be called for a type
// created via placeholder_pointer_type, placeholder_struct_type, or
// placeholder_array_type.. (It may be called for a pointer,
// struct, or array type in a case like "type P *byte; type Q P".)
-tree
-named_type (const std::string &name, tree, location_t);
+tree named_type (GGC::Ident name, tree, location_t);
// Return the size of a type.
int64_t type_size (tree);
@@ -164,8 +152,7 @@ int64_t type_field_alignment (tree);
// Return the offset of field INDEX in a struct type. INDEX is the
// entry in the FIELDS std::vector parameter of struct_type or
// set_placeholder_struct_type.
-int64_t
-type_field_offset (tree, size_t index);
+int64_t type_field_offset (tree, size_t index);
// Expressions.
@@ -175,155 +162,135 @@ type_field_offset (tree, size_t index);
tree zero_expression (tree);
// Create a reference to a variable.
-tree
-var_expression (Bvariable *var, location_t);
+tree var_expression (Bvariable *var, location_t);
// Return an expression for the floating point value VAL in BTYPE.
-tree
-float_constant_expression (tree btype, mpfr_t val);
+tree float_constant_expression (tree btype, mpfr_t val);
// Return an expression for the string value VAL.
-tree
-string_constant_expression (const std::string &val);
+tree string_constant_expression (const std::string &val);
// Get a char literal
-tree
-char_constant_expression (char c);
+tree char_constant_expression (char c);
// Get a char literal
-tree
-wchar_constant_expression (wchar_t c);
+tree wchar_constant_expression (wchar_t c);
+
+// Get a size literal
+tree size_constant_expression (size_t val);
// Return an expression for the boolean value VAL.
-tree
-boolean_constant_expression (bool val);
+tree boolean_constant_expression (bool val);
// Return an expression that converts EXPR to TYPE.
-tree
-convert_expression (tree type, tree expr, location_t);
+tree convert_expression (tree type, tree expr, location_t);
// Return an expression for the field at INDEX in BSTRUCT.
-tree
-struct_field_expression (tree bstruct, size_t index, location_t);
+tree struct_field_expression (tree bstruct, size_t index, location_t);
// Create an expression that executes BSTAT before BEXPR.
-tree
-compound_expression (tree bstat, tree bexpr, location_t);
+tree compound_expression (tree bstat, tree bexpr, location_t);
// Return an expression that executes THEN_EXPR if CONDITION is true, or
// ELSE_EXPR otherwise and returns the result as type BTYPE, within the
// specified function FUNCTION. ELSE_EXPR may be NULL. BTYPE may be NULL.
-tree
-conditional_expression (tree function, tree btype, tree condition,
- tree then_expr, tree else_expr, location_t);
+tree conditional_expression (tree function, tree btype, tree condition,
+ tree then_expr, tree else_expr, location_t);
// Return an expression for the negation operation OP EXPR.
// Supported values of OP are enumerated in NegationOperator.
-tree
-negation_expression (NegationOperator op, tree expr, location_t);
+tree negation_expression (NegationOperator op, tree expr, location_t);
// Return an expression for the operation LEFT OP RIGHT.
// Supported values of OP are enumerated in ArithmeticOrLogicalOperator.
-tree
-arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op, tree left,
- tree right, location_t loc);
+tree arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op,
+ tree left, tree right, location_t loc);
// Return an expression for the operation LEFT OP RIGHT.
// Supported values of OP are enumerated in ArithmeticOrLogicalOperator.
// This function adds overflow checking and returns a list of statements to
// add to the current function context. The `receiver` variable refers to the
// variable which will contain the result of that operation.
-tree
-arithmetic_or_logical_expression_checked (ArithmeticOrLogicalOperator op,
- tree left, tree right, location_t loc,
- Bvariable *receiver);
+tree arithmetic_or_logical_expression_checked (ArithmeticOrLogicalOperator op,
+ tree left, tree right,
+ location_t loc,
+ Bvariable *receiver);
// Return an expression for the operation LEFT OP RIGHT.
// Supported values of OP are enumerated in ComparisonOperator.
-tree
-comparison_expression (ComparisonOperator op, tree left, tree right,
- location_t loc);
+tree comparison_expression (ComparisonOperator op, tree left, tree right,
+ location_t loc);
// Return an expression for the operation LEFT OP RIGHT.
// Supported values of OP are enumerated in LazyBooleanOperator.
-tree
-lazy_boolean_expression (LazyBooleanOperator op, tree left, tree right,
- location_t);
+tree lazy_boolean_expression (LazyBooleanOperator op, tree left, tree right,
+ location_t);
// Return an expression that constructs BTYPE with VALS. BTYPE must be the
// backend representation a of struct. VALS must be in the same order as the
// corresponding fields in BTYPE.
-tree
-constructor_expression (tree btype, bool is_variant,
- const std::vector<tree> &vals, int, location_t);
+tree constructor_expression (tree btype, bool is_variant,
+ const std::vector<tree> &vals, int, location_t);
// Return an expression that constructs an array of BTYPE with INDEXES and
// VALS. INDEXES and VALS must have the same amount of elements. Each index
// in INDEXES must be in the same order as the corresponding value in VALS.
-tree
-array_constructor_expression (tree btype,
- const std::vector<unsigned long> &indexes,
- const std::vector<tree> &vals, location_t);
+tree array_constructor_expression (tree btype,
+ const std::vector<unsigned long> &indexes,
+ const std::vector<tree> &vals, location_t);
-tree
-array_initializer (tree, tree, tree, tree, tree, tree *, location_t);
+tree array_initializer (tree, tree, tree, tree, tree, tree *, location_t);
// Return an expression for ARRAY[INDEX] as an l-value. ARRAY is a valid
// fixed-length array, not a slice.
-tree
-array_index_expression (tree array, tree index, location_t);
+tree array_index_expression (tree array, tree index, location_t);
+
+// Return an expresison for SLICE[INDEX] as an l-value. SLICE is represented
+// with a DST.
+tree slice_index_expression (tree slice, tree index, location_t);
// Create an expression for a call to FN with ARGS, taking place within
// caller CALLER.
-tree
-call_expression (tree fn, const std::vector<tree> &args, tree static_chain,
- location_t);
+tree call_expression (tree fn, const std::vector<tree> &args, tree static_chain,
+ location_t);
// Statements.
// Create a variable initialization statement in the specified
// function. This initializes a local variable at the point in the
// program flow where it is declared.
-tree
-init_statement (tree, Bvariable *var, tree init);
+tree init_statement (tree, Bvariable *var, tree init);
// Create an assignment statement within the specified function.
-tree
-assignment_statement (tree lhs, tree rhs, location_t);
+tree assignment_statement (tree lhs, tree rhs, location_t);
// Create return statement for an decl for a value (can be NULL_TREE) at a
// location
-tree
-return_statement (tree fndecl, tree val, location_t);
+tree return_statement (tree fndecl, tree val, location_t);
// Create an if statement within a function. ELSE_BLOCK may be NULL.
-tree
-if_statement (tree, tree condition, tree then_block, tree else_block,
- location_t);
+tree if_statement (tree, tree condition, tree then_block, tree else_block,
+ location_t);
// infinite loop expressions
-tree
-loop_expression (tree body, location_t);
+tree loop_expression (tree body, location_t);
// exit expressions
-tree
-exit_expression (tree condition, location_t);
+tree exit_expression (tree condition, location_t);
// Create a single statement from two statements.
tree compound_statement (tree, tree);
// Create a single statement from a list of statements.
-tree
-statement_list (const std::vector<tree> &);
+tree statement_list (const std::vector<tree> &);
// Create a statement that attempts to execute BSTAT and calls EXCEPT_STMT if
// an exception occurs. EXCEPT_STMT may be NULL. FINALLY_STMT may be NULL and
// if not NULL, it will always be executed. This is used for handling defers
// in Go functions. In C++, the resulting code is of this form:
// try { BSTAT; } catch { EXCEPT_STMT; } finally { FINALLY_STMT; }
-tree
-exception_handler_statement (tree bstat, tree except_stmt, tree finally_stmt,
- location_t);
+tree exception_handler_statement (tree bstat, tree except_stmt,
+ tree finally_stmt, location_t);
// Blocks.
@@ -337,16 +304,14 @@ exception_handler_statement (tree bstat, tree except_stmt, tree finally_stmt,
// the initial curly brace. END_LOCATION is the location of the end
// of the block, more or less the location of the final curly brace.
// The statements will be added after the block is created.
-tree
-block (tree function, tree enclosing, const std::vector<Bvariable *> &vars,
- location_t start_location, location_t end_location);
+tree block (tree function, tree enclosing, const std::vector<Bvariable *> &vars,
+ location_t start_location, location_t end_location);
// Add the statements to a block. The block is created first. Then
// the statements are created. Then the statements are added to the
// block. This will called exactly once per block. The vector may
// be empty if there are no statements.
-void
-block_add_statements (tree, const std::vector<tree> &);
+void block_add_statements (tree, const std::vector<tree> &);
// Variables.
@@ -360,10 +325,9 @@ block_add_statements (tree, const std::vector<tree> &);
// be put into a unique section if possible; this is intended to
// permit the linker to garbage collect the variable if it is not
// referenced. LOCATION is where the variable was defined.
-Bvariable *
-global_variable (const std::string &name, const std::string &asm_name,
- tree btype, bool is_external, bool is_hidden,
- bool in_unique_section, location_t location);
+Bvariable *global_variable (GGC::Ident name, GGC::Ident asm_name, tree btype,
+ bool is_external, bool is_hidden,
+ bool in_unique_section, location_t location);
// A global variable will 1) be initialized to zero, or 2) be
// initialized to a constant value, or 3) be initialized in the init
@@ -371,8 +335,7 @@ global_variable (const std::string &name, const std::string &asm_name,
// global_variable_set_init to set the initial value. If this is
// not called, the backend should initialize a global variable to 0.
// The init function may then assign a value to it.
-void
-global_variable_set_init (Bvariable *, tree);
+void global_variable_set_init (Bvariable *, tree);
// Create a local variable. The frontend will create the local
// variables first, and then create the block which contains them.
@@ -386,21 +349,18 @@ global_variable_set_init (Bvariable *, tree);
// the function, as otherwise the variable would be on the heap).
// LOCATION is where the variable is defined. For each local variable
// the frontend will call init_statement to set the initial value.
-Bvariable *
-local_variable (tree function, const std::string &name, tree type,
- Bvariable *decl_var, location_t location);
+Bvariable *local_variable (tree function, GGC::Ident name, tree type,
+ Bvariable *decl_var, location_t location);
// Create a function parameter. This is an incoming parameter, not
// a result parameter (result parameters are treated as local
// variables). The arguments are as for local_variable.
-Bvariable *
-parameter_variable (tree function, const std::string &name, tree type,
- location_t location);
+Bvariable *parameter_variable (tree function, GGC::Ident name, tree type,
+ location_t location);
// Create a static chain parameter. This is the closure parameter.
-Bvariable *
-static_chain_variable (tree function, const std::string &name, tree type,
- location_t location);
+Bvariable *static_chain_variable (tree function, GGC::Ident name, tree type,
+ location_t location);
// Create a temporary variable. A temporary variable has no name,
// just a type. We pass in FUNCTION and BLOCK in case they are
@@ -413,18 +373,16 @@ static_chain_variable (tree function, const std::string &name, tree type,
// variable, and may not be very useful. This function should
// return a variable which can be referenced later and should set
// *PSTATEMENT to a statement which initializes the variable.
-Bvariable *
-temporary_variable (tree fndecl, tree bind_tree, tree type, tree init,
- bool address_is_taken, location_t location,
- tree *pstatement);
+Bvariable *temporary_variable (tree fndecl, tree bind_tree, tree type,
+ tree init, bool address_is_taken,
+ location_t location, tree *pstatement);
// Labels.
-// Create a new label. NAME will be empty if this is a label
+// Create a new label. NAME will be tl::nullopt if this is a label
// created by the frontend for a loop construct. The location is
// where the label is defined.
-tree
-label (tree, const std::string &name, location_t);
+tree label (tree, tl::optional<GGC::Ident> name, location_t);
// Create a statement which defines a label. This statement will be
// put into the codestream at the point where the label should be
@@ -439,6 +397,12 @@ tree goto_statement (tree, location_t);
// recover.
tree label_address (tree, location_t);
+// Lookup a field from a type given its name.
+// Build the `component` tree with `Backend::get_identifier_node`.
+//
+// Forked from the C frontend.
+tree lookup_field (const_tree, tree);
+
// Functions.
// Bit flags to pass to the function method.
@@ -460,43 +424,38 @@ static const unsigned int function_does_not_return = 1 << 2;
static const unsigned int function_in_unique_section = 1 << 3;
// Declare or define a function of FNTYPE.
-// NAME is the Go name of the function. ASM_NAME, if not the empty
-// string, is the name that should be used in the symbol table; this
+// NAME is the Go name of the function. ASM_NAME, if not tl::nullopt,
+// is the name that should be used in the symbol table; this
// will be non-empty if a magic extern comment is used. FLAGS is
// bit flags described above.
-tree
-function (tree fntype, const std::string &name, const std::string &asm_name,
- unsigned int flags, location_t);
+tree function (tree fntype, GGC::Ident name, tl::optional<GGC::Ident> asm_name,
+ unsigned int flags, location_t);
// Create a statement that runs all deferred calls for FUNCTION. This should
// be a statement that looks like this in C++:
// finish:
// try { DEFER_RETURN; } catch { CHECK_DEFER; goto finish; }
-tree
-function_defer_statement (tree function, tree undefer, tree check_defer,
- location_t);
+tree function_defer_statement (tree function, tree undefer, tree check_defer,
+ location_t);
// Record PARAM_VARS as the variables to use for the parameters of FUNCTION.
// This will only be called for a function definition. Returns true on
// success, false on failure.
-bool
-function_set_parameters (tree function,
- const std::vector<Bvariable *> &param_vars);
+bool function_set_parameters (tree function,
+ const std::vector<Bvariable *> &param_vars);
// Utility.
// Write the definitions for all TYPE_DECLS, CONSTANT_DECLS,
// FUNCTION_DECLS, and VARIABLE_DECLS declared globally.
-void
-write_global_definitions (const std::vector<tree> &type_decls,
- const std::vector<tree> &constant_decls,
- const std::vector<tree> &function_decls,
- const std::vector<Bvariable *> &variable_decls);
+void write_global_definitions (const std::vector<tree> &type_decls,
+ const std::vector<tree> &constant_decls,
+ const std::vector<tree> &function_decls,
+ const std::vector<Bvariable *> &variable_decls);
// TODO: make static
-tree
-fill_in_fields (tree, const std::vector<typed_identifier> &, bool);
+tree fill_in_fields (tree, const std::vector<typed_identifier> &, bool);
tree fill_in_array (tree, tree, tree);
diff --git a/gcc/rust/rust-diagnostics.cc b/gcc/rust/rust-diagnostics.cc
index 702da71..5965bb4 100644
--- a/gcc/rust/rust-diagnostics.cc
+++ b/gcc/rust/rust-diagnostics.cc
@@ -48,27 +48,33 @@ expand_format (const char *fmt)
c++;
switch (*c)
{
- case '\0': {
+ case '\0':
+ {
// malformed format string
rust_unreachable ();
}
- case '%': {
+ case '%':
+ {
ss << "%";
break;
}
- case 'm': {
+ case 'm':
+ {
ss << mformat_value ();
break;
}
- case '<': {
+ case '<':
+ {
ss << rust_open_quote ();
break;
}
- case '>': {
+ case '>':
+ {
ss << rust_close_quote ();
break;
}
- case 'q': {
+ case 'q':
+ {
ss << rust_open_quote ();
c++;
if (*c == 'm')
@@ -82,7 +88,8 @@ expand_format (const char *fmt)
ss << rust_close_quote ();
break;
}
- default: {
+ default:
+ {
ss << "%" << *c;
}
}
@@ -104,8 +111,8 @@ expand_format (const char *fmt)
// calling function must need to have attribute gnu_printf as well, even
// though there is already an attribute declaration for it.
-static std::string
-expand_message (const char *fmt, va_list ap) RUST_ATTRIBUTE_GCC_DIAG (1, 0);
+static std::string expand_message (const char *fmt, va_list ap)
+ RUST_ATTRIBUTE_GCC_DIAG (1, 0);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsuggest-attribute=format"
@@ -420,24 +427,24 @@ namespace Rust {
*/
// simple location
-static Error
-va_constructor (Error::Kind kind, location_t locus, const char *fmt,
- va_list args) RUST_ATTRIBUTE_GCC_DIAG (3, 0);
+static Error va_constructor (Error::Kind kind, location_t locus,
+ const char *fmt, va_list args)
+ RUST_ATTRIBUTE_GCC_DIAG (3, 0);
// simple location + error code
-static Error
-va_constructor (Error::Kind kind, location_t locus, const ErrorCode code,
- const char *fmt, va_list args) RUST_ATTRIBUTE_GCC_DIAG (4, 0);
+static Error va_constructor (Error::Kind kind, location_t locus,
+ const ErrorCode code, const char *fmt,
+ va_list args) RUST_ATTRIBUTE_GCC_DIAG (4, 0);
// rich location
-static Error
-va_constructor (Error::Kind kind, rich_location *r_locus, const char *fmt,
- va_list args) RUST_ATTRIBUTE_GCC_DIAG (3, 0);
+static Error va_constructor (Error::Kind kind, rich_location *r_locus,
+ const char *fmt, va_list args)
+ RUST_ATTRIBUTE_GCC_DIAG (3, 0);
// rich location + error code
-static Error
-va_constructor (Error::Kind kind, rich_location *r_locus, const ErrorCode code,
- const char *fmt, va_list args) RUST_ATTRIBUTE_GCC_DIAG (4, 0);
+static Error va_constructor (Error::Kind kind, rich_location *r_locus,
+ const ErrorCode code, const char *fmt,
+ va_list args) RUST_ATTRIBUTE_GCC_DIAG (4, 0);
// simple location
static Error
diff --git a/gcc/rust/rust-diagnostics.h b/gcc/rust/rust-diagnostics.h
index a13dc6a2..09d5e24 100644
--- a/gcc/rust/rust-diagnostics.h
+++ b/gcc/rust/rust-diagnostics.h
@@ -31,7 +31,7 @@
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)
#define RUST_ATTRIBUTE_GCC_DIAG(m, n) \
__attribute__ ((__format__ (__gcc_tdiag__, m, n))) \
- __attribute__ ((__nonnull__ (m)))
+ __attribute__ ((__nonnull__ (m)))
#else
#define RUST_ATTRIBUTE_GCC_DIAG(m, n)
#endif
@@ -119,10 +119,8 @@ rust_error_at(rich_location *richloc, const ErrorCode, const char *fmt, ...)
// These interfaces provide a way for the front end to ask for
// the open/close quote characters it should use when formatting
// diagnostics (warnings, errors).
-extern const char *
-rust_open_quote ();
-extern const char *
-rust_close_quote ();
+extern const char *rust_open_quote ();
+extern const char *rust_close_quote ();
// These interfaces are used by utilities above to pass warnings and
// errors (once format specifiers have been expanded) to the back end,
@@ -185,7 +183,7 @@ struct Error
Error (Kind kind, location_t locus, std::string message)
: kind (kind), locus (locus), message (std::move (message))
{
- message.shrink_to_fit ();
+ this->message.shrink_to_fit ();
}
// simple location + error code
Error (Kind kind, location_t locus, ErrorCode code, std::string message)
@@ -193,13 +191,13 @@ struct Error
message (std::move (message))
{
is_errorcode = true;
- message.shrink_to_fit ();
+ this->message.shrink_to_fit ();
}
// rich location
Error (Kind kind, rich_location *richlocus, std::string message)
: kind (kind), richlocus (richlocus), message (std::move (message))
{
- message.shrink_to_fit ();
+ this->message.shrink_to_fit ();
}
// rich location + error code
Error (Kind kind, rich_location *richlocus, ErrorCode code,
@@ -208,7 +206,7 @@ struct Error
message (std::move (message))
{
is_errorcode = true;
- message.shrink_to_fit ();
+ this->message.shrink_to_fit ();
}
// simple location
Error (location_t locus, std::string message)
@@ -306,8 +304,7 @@ struct Error
#define rust_sorry_at(location, ...) sorry_at (location, __VA_ARGS__)
-void
-rust_debug_loc (const location_t location, const char *fmt,
- ...) ATTRIBUTE_PRINTF_2;
+void rust_debug_loc (const location_t location, const char *fmt,
+ ...) ATTRIBUTE_PRINTF_2;
#endif // !defined(RUST_DIAGNOSTICS_H)
diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc
index e5319d3..398dea1 100644
--- a/gcc/rust/rust-gcc.cc
+++ b/gcc/rust/rust-gcc.cc
@@ -91,12 +91,6 @@ Bvariable::error_variable ()
// A helper function to create a GCC identifier from a C++ string.
-static inline tree
-get_identifier_from_string (const std::string &str)
-{
- return get_identifier_with_length (str.data (), str.length ());
-}
-
namespace Backend {
// Define the built-in functions that are exposed to GCCRust.
@@ -609,7 +603,7 @@ fill_in_fields (tree fill, const std::vector<typed_identifier> &fields,
tree *pp = &field_trees;
for (const auto &p : fields)
{
- tree name_tree = get_identifier_from_string (p.name);
+ tree name_tree = p.name.as_tree ();
tree type_tree = p.type;
if (error_operand_p (type_tree))
return error_mark_node;
@@ -675,7 +669,7 @@ fill_in_array (tree fill, tree element_type, tree length_tree)
// Return a named version of a type.
tree
-named_type (const std::string &name, tree type, location_t location)
+named_type (GGC::Ident name, tree type, location_t location)
{
if (error_operand_p (type))
return error_mark_node;
@@ -688,15 +682,14 @@ named_type (const std::string &name, tree type, location_t location)
|| TREE_CODE (type) == COMPLEX_TYPE
|| TREE_CODE (type) == BOOLEAN_TYPE))
{
- tree decl = build_decl (BUILTINS_LOCATION, TYPE_DECL,
- get_identifier_from_string (name), type);
+ tree decl
+ = build_decl (BUILTINS_LOCATION, TYPE_DECL, name.as_tree (), type);
TYPE_NAME (type) = decl;
return type;
}
tree copy = build_variant_type_copy (type);
- tree decl
- = build_decl (location, TYPE_DECL, get_identifier_from_string (name), copy);
+ tree decl = build_decl (location, TYPE_DECL, name.as_tree (), copy);
DECL_ORIGINAL_TYPE (decl) = type;
TYPE_NAME (copy) = decl;
return copy;
@@ -825,6 +818,12 @@ char_constant_expression (char c)
return build_int_cst (char_type_node, c);
}
+tree
+size_constant_expression (size_t val)
+{
+ return size_int (val);
+}
+
// Make a constant boolean expression.
tree
@@ -1505,6 +1504,34 @@ array_index_expression (tree array_tree, tree index_tree, location_t location)
return ret;
}
+// Return an expression representing SLICE[INDEX]
+
+tree
+slice_index_expression (tree slice_tree, tree index_tree, location_t location)
+{
+ if (error_operand_p (slice_tree) || error_operand_p (index_tree))
+ return error_mark_node;
+
+ // A slice is created in TyTyResolvecompile::create_slice_type_record
+ // For example:
+ // &[i32] is turned directly into a struct { i32* data, usize len };
+ // [i32] is also turned into struct { i32* data, usize len }
+
+ // it should have RS_DST_FLAG set to 1
+ rust_assert (RS_DST_FLAG_P (TREE_TYPE (slice_tree)));
+
+ tree data_field = struct_field_expression (slice_tree, 0, location);
+ tree data_field_deref = build_fold_indirect_ref_loc (location, data_field);
+
+ tree element_type = TREE_TYPE (data_field_deref);
+ tree data_pointer = TREE_OPERAND (data_field_deref, 0);
+ rust_assert (POINTER_TYPE_P (TREE_TYPE (data_pointer)));
+ tree data_offset_expr
+ = Rust::pointer_offset_expression (data_pointer, index_tree, location);
+
+ return build1_loc (location, INDIRECT_REF, element_type, data_offset_expr);
+}
+
// Create an expression for a call to FN_EXPR with FN_ARGS.
tree
call_expression (tree fn, const std::vector<tree> &fn_args, tree chain_expr,
@@ -1876,7 +1903,8 @@ non_zero_size_type (tree type)
}
return rust_non_zero_struct;
- case ARRAY_TYPE: {
+ case ARRAY_TYPE:
+ {
tree element_type = non_zero_size_type (TREE_TYPE (type));
return build_array_type_nelts (element_type, 1);
}
@@ -1923,9 +1951,9 @@ convert_tree (tree type_tree, tree expr_tree, location_t location)
// Make a global variable.
Bvariable *
-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)
+global_variable (GGC::Ident var_name, GGC::Ident asm_name, tree type_tree,
+ bool is_external, bool is_hidden, bool in_unique_section,
+ location_t location)
{
if (error_operand_p (type_tree))
return Bvariable::error_variable ();
@@ -1935,8 +1963,7 @@ global_variable (const std::string &var_name, const std::string &asm_name,
if ((is_external || !is_hidden) && int_size_in_bytes (type_tree) == 0)
type_tree = non_zero_size_type (type_tree);
- tree decl = build_decl (location, VAR_DECL,
- get_identifier_from_string (var_name), type_tree);
+ tree decl = build_decl (location, VAR_DECL, var_name.as_tree (), type_tree);
if (is_external)
DECL_EXTERNAL (decl) = 1;
else
@@ -1944,11 +1971,11 @@ global_variable (const std::string &var_name, const std::string &asm_name,
if (!is_hidden)
{
TREE_PUBLIC (decl) = 1;
- SET_DECL_ASSEMBLER_NAME (decl, get_identifier_from_string (asm_name));
+ SET_DECL_ASSEMBLER_NAME (decl, asm_name.as_tree ());
}
else
{
- SET_DECL_ASSEMBLER_NAME (decl, get_identifier_from_string (asm_name));
+ SET_DECL_ASSEMBLER_NAME (decl, asm_name.as_tree ());
}
TREE_USED (decl) = 1;
@@ -1988,13 +2015,12 @@ global_variable_set_init (Bvariable *var, tree expr_tree)
// Make a local variable.
Bvariable *
-local_variable (tree function, const std::string &name, tree type_tree,
+local_variable (tree function, GGC::Ident name, tree type_tree,
Bvariable *decl_var, location_t location)
{
if (error_operand_p (type_tree))
return Bvariable::error_variable ();
- tree decl = build_decl (location, VAR_DECL, get_identifier_from_string (name),
- type_tree);
+ tree decl = build_decl (location, VAR_DECL, name.as_tree (), type_tree);
DECL_CONTEXT (decl) = function;
if (decl_var != NULL)
@@ -2009,13 +2035,12 @@ local_variable (tree function, const std::string &name, tree type_tree,
// Make a function parameter variable.
Bvariable *
-parameter_variable (tree function, const std::string &name, tree type_tree,
+parameter_variable (tree function, GGC::Ident name, tree type_tree,
location_t location)
{
if (error_operand_p (type_tree))
return Bvariable::error_variable ();
- tree decl = build_decl (location, PARM_DECL,
- get_identifier_from_string (name), type_tree);
+ tree decl = build_decl (location, PARM_DECL, name.as_tree (), type_tree);
DECL_CONTEXT (decl) = function;
DECL_ARG_TYPE (decl) = type_tree;
@@ -2026,13 +2051,12 @@ parameter_variable (tree function, const std::string &name, tree type_tree,
// Make a static chain variable.
Bvariable *
-static_chain_variable (tree fndecl, const std::string &name, tree type_tree,
+static_chain_variable (tree fndecl, GGC::Ident name, tree type_tree,
location_t location)
{
if (error_operand_p (type_tree))
return Bvariable::error_variable ();
- tree decl = build_decl (location, PARM_DECL,
- get_identifier_from_string (name), type_tree);
+ tree decl = build_decl (location, PARM_DECL, name.as_tree (), type_tree);
DECL_CONTEXT (decl) = fndecl;
DECL_ARG_TYPE (decl) = type_tree;
TREE_USED (decl) = 1;
@@ -2123,10 +2147,10 @@ temporary_variable (tree fndecl, tree bind_tree, tree type_tree, tree init_tree,
// Make a label.
tree
-label (tree func_tree, const std::string &name, location_t location)
+label (tree func_tree, tl::optional<GGC::Ident> name, location_t location)
{
tree decl;
- if (name.empty ())
+ if (!name.has_value ())
{
if (DECL_STRUCT_FUNCTION (func_tree) == NULL)
push_struct_function (func_tree);
@@ -2139,7 +2163,7 @@ label (tree func_tree, const std::string &name, location_t location)
}
else
{
- tree id = get_identifier_from_string (name);
+ tree id = name->as_tree ();
decl = build_decl (location, LABEL_DECL, id, void_type_node);
DECL_CONTEXT (decl) = func_tree;
}
@@ -2178,7 +2202,7 @@ label_address (tree label, location_t location)
// Declare or define a new function.
tree
-function (tree functype, const std::string &name, const std::string &asm_name,
+function (tree functype, GGC::Ident name, tl::optional<GGC::Ident> asm_name,
unsigned int flags, location_t location)
{
if (error_operand_p (functype))
@@ -2186,13 +2210,13 @@ function (tree functype, const std::string &name, const std::string &asm_name,
gcc_assert (FUNCTION_POINTER_TYPE_P (functype));
functype = TREE_TYPE (functype);
- tree id = get_identifier_from_string (name);
+ tree id = name.as_tree ();
if (error_operand_p (id))
return error_mark_node;
tree decl = build_decl (location, FUNCTION_DECL, id, functype);
- if (!asm_name.empty ())
- SET_DECL_ASSEMBLER_NAME (decl, get_identifier_from_string (asm_name));
+ if (asm_name.has_value ())
+ SET_DECL_ASSEMBLER_NAME (decl, asm_name->as_tree ());
if ((flags & function_is_declaration) != 0)
DECL_EXTERNAL (decl) = 1;
@@ -2235,7 +2259,7 @@ function_defer_statement (tree function, tree undefer_tree, tree defer_tree,
push_cfun (DECL_STRUCT_FUNCTION (function));
tree stmt_list = NULL;
- tree label = Backend::label (function, "", location);
+ tree label = Backend::label (function, tl::nullopt, location);
tree label_def = label_definition_statement (label);
append_to_statement_list (label_def, &stmt_list);
@@ -2342,4 +2366,30 @@ write_global_definitions (const std::vector<tree> &type_decls,
delete[] defs;
}
+tree
+lookup_field (const_tree type, tree component)
+{
+ tree field;
+
+ for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+ {
+ if (DECL_NAME (field) == NULL_TREE
+ && RECORD_OR_UNION_TYPE_P (TREE_TYPE (field)))
+ {
+ tree anon = lookup_field (TREE_TYPE (field), component);
+
+ if (anon)
+ return tree_cons (NULL_TREE, field, anon);
+ }
+
+ if (DECL_NAME (field) == component)
+ break;
+ }
+
+ if (field == NULL_TREE)
+ return NULL_TREE;
+
+ return tree_cons (NULL_TREE, field, NULL_TREE);
+}
+
} // namespace Backend
diff --git a/gcc/rust/rust-lang.cc b/gcc/rust/rust-lang.cc
index f3a155d..93ce041 100644
--- a/gcc/rust/rust-lang.cc
+++ b/gcc/rust/rust-lang.cc
@@ -51,10 +51,10 @@
// FIXME: test saving intellisense
#include "options.h"
-// version check to stop compiling if c++ isn't c++11 or higher
-#if __cplusplus < 201103
+// version check to stop compiling if c++ isn't c++14 or higher
+#if __cplusplus < 201402
#error \
- "GCC Rust frontend requires C++11 or higher. You can compile the g++ frontend first and then compile the Rust frontend using that."
+ "GCC Rust frontend requires C++14 or higher. You can compile the g++ frontend first and then compile the Rust frontend using that."
#endif
// TODO: is this best way to do it? Is it allowed? (should be)
@@ -373,7 +373,13 @@ rust_localize_identifier (const char *ident)
return identifier_to_locale (ident);
}
-extern const attribute_spec grs_langhook_common_attribute_table[];
+extern const struct scoped_attribute_specs grs_langhook_gnu_attribute_table;
+extern const struct scoped_attribute_specs grs_langhook_common_attribute_table;
+
+const scoped_attribute_specs *const grs_langhook_attribute_table[] = {
+ &grs_langhook_gnu_attribute_table,
+ &grs_langhook_common_attribute_table,
+};
/* The language hooks data structure. This is the main interface between the GCC
* front-end and the GCC middle-end/back-end. A list of language hooks could be
@@ -394,8 +400,7 @@ extern const attribute_spec grs_langhook_common_attribute_table[];
#undef LANG_HOOKS_WRITE_GLOBALS
#undef LANG_HOOKS_GIMPLIFY_EXPR
#undef LANG_HOOKS_EH_PERSONALITY
-
-#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
+#undef LANG_HOOKS_ATTRIBUTE_TABLE
#define LANG_HOOKS_NAME "GNU Rust"
#define LANG_HOOKS_INIT grs_langhook_init
@@ -417,7 +422,7 @@ extern const attribute_spec grs_langhook_common_attribute_table[];
#define LANG_HOOKS_GIMPLIFY_EXPR grs_langhook_gimplify_expr
#define LANG_HOOKS_EH_PERSONALITY grs_langhook_eh_personality
-#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE grs_langhook_common_attribute_table
+#define LANG_HOOKS_ATTRIBUTE_TABLE grs_langhook_attribute_table
#if CHECKING_P
diff --git a/gcc/rust/rust-object-export.h b/gcc/rust/rust-object-export.h
index fe055c3..784fef3 100644
--- a/gcc/rust/rust-object-export.h
+++ b/gcc/rust/rust-object-export.h
@@ -21,13 +21,10 @@
#include "rust-system.h"
-extern unsigned int
-rust_field_alignment (tree t);
-
-extern const char *
-rust_read_export_data (int fd, off_t offset, char **pbuf, size_t *plen,
- int *perr);
-extern void
-rust_write_export_data (const char *bytes, unsigned int size);
+extern unsigned int rust_field_alignment (tree t);
+
+extern const char *rust_read_export_data (int fd, off_t offset, char **pbuf,
+ size_t *plen, int *perr);
+extern void rust_write_export_data (const char *bytes, unsigned int size);
#endif // RUST_OBJECT_EXPORT_H
diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc
index 48acbf34..17f9c06 100644
--- a/gcc/rust/rust-session-manager.cc
+++ b/gcc/rust/rust-session-manager.cc
@@ -20,7 +20,9 @@
#include "rust-collect-lang-items.h"
#include "rust-desugar-for-loops.h"
#include "rust-desugar-question-mark.h"
+#include "rust-desugar-apit.h"
#include "rust-diagnostics.h"
+#include "rust-expression-yeast.h"
#include "rust-hir-pattern-analysis.h"
#include "rust-immutable-name-resolution-context.h"
#include "rust-unsafe-checker.h"
@@ -61,11 +63,9 @@
#include "tm.h"
#include "rust-target.h"
-extern bool
-saw_errors (void);
+extern bool saw_errors (void);
-extern Linemap *
-rust_get_linemap ();
+extern Linemap *rust_get_linemap ();
namespace Rust {
@@ -150,9 +150,9 @@ validate_crate_name (const std::string &crate_name, Error &error)
{
if (!(is_alphabetic (c.value) || is_numeric (c.value) || c.value == '_'))
{
- error = Error (UNDEF_LOCATION,
- "invalid character %qs in crate name: %qs",
- c.as_string ().c_str (), crate_name.c_str ());
+ error
+ = Error (UNDEF_LOCATION, "invalid character %qs in crate name: %qs",
+ c.as_string ().c_str (), crate_name.c_str ());
return false;
}
}
@@ -203,14 +203,16 @@ Session::handle_option (
switch (code)
{
case OPT_I:
- case OPT_L: {
+ case OPT_L:
+ {
// TODO: add search path
const std::string p = std::string (arg);
add_search_path (p);
}
break;
- case OPT_frust_extern_: {
+ case OPT_frust_extern_:
+ {
std::string input (arg);
ret = handle_extern_option (input);
}
@@ -251,7 +253,8 @@ Session::handle_option (
Compile::Mangler::set_mangling (flag_rust_mangling);
break;
- case OPT_frust_cfg_: {
+ case OPT_frust_cfg_:
+ {
auto string_arg = std::string (arg);
ret = handle_cfg_option (string_arg);
break;
@@ -617,9 +620,6 @@ 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))
{
@@ -682,6 +682,7 @@ Session::compile_crate (const char *filename)
Resolver2_0::ImmutableNameResolutionContext::init (name_resolution_ctx);
// type resolve
+ Compile::Context *ctx = Compile::Context::get ();
Resolver::TypeResolution::Resolve (hir);
Resolver::TypeCheckContext::get ()->get_variance_analysis_ctx ().solve ();
@@ -729,16 +730,15 @@ Session::compile_crate (const char *filename)
return;
// do compile to gcc generic
- Compile::Context ctx;
- Compile::CompileCrate::Compile (hir, &ctx);
+ Compile::CompileCrate::Compile (hir, ctx);
// we can't do static analysis if there are errors to worry about
if (!saw_errors ())
{
// lints
Analysis::ScanDeadcode::Scan (hir);
- Analysis::UnusedVariables::Lint (ctx);
- Analysis::ReadonlyCheck::Lint (ctx);
+ Analysis::UnusedVariables::Lint (*ctx);
+ Analysis::ReadonlyCheck::Lint (*ctx);
// metadata
bool specified_emit_metadata
@@ -759,7 +759,7 @@ Session::compile_crate (const char *filename)
}
// pass to GCC middle-end
- ctx.write_to_backend ();
+ ctx->write_to_backend ();
}
void
@@ -983,6 +983,20 @@ Session::expansion (AST::Crate &crate, Resolver2_0::NameResolutionContext &ctx)
rust_error_at (range, "reached recursion limit");
}
+ // handle AST desugaring
+ if (!saw_errors ())
+ {
+ AST::ExpressionYeast ().go (crate);
+
+ AST::DesugarApit ().go (crate);
+
+ // HACK: we may need a final TopLevel pass
+ // however, this should not count towards the recursion limit
+ // and we don't need a full Early pass
+ if (flag_name_resolution_2_0)
+ Resolver2_0::TopLevel (ctx).go (crate);
+ }
+
// error reporting - check unused macros, get missing fragment specifiers
// build test harness
@@ -1108,8 +1122,7 @@ Session::load_extern_crate (const std::string &crate_name, location_t locus)
if (stream == NULL // No stream and
&& proc_macros.empty ()) // no proc macros
{
- rust_error_at (locus, "failed to locate crate %qs",
- import_name.c_str ());
+ rust_error_at (locus, "failed to locate crate %qs", import_name.c_str ());
return UNKNOWN_NODEID;
}
@@ -1177,16 +1190,13 @@ Session::load_extern_crate (const std::string &crate_name, location_t locus)
mappings.insert_bang_proc_macros (crate_num, bang_macros);
mappings.insert_derive_proc_macros (crate_num, derive_macros);
- // name resolve it
- Resolver::NameResolution::Resolve (parsed_crate);
-
- // perform hir lowering
- std::unique_ptr<HIR::Crate> lowered
- = HIR::ASTLowering::Resolve (parsed_crate);
- HIR::Crate &hir = mappings.insert_hir_crate (std::move (lowered));
-
- // perform type resolution
- Resolver::TypeResolution::Resolve (hir);
+ // if flag_name_resolution_2_0 is enabled
+ // then we perform resolution later
+ if (!flag_name_resolution_2_0)
+ {
+ // name resolve it
+ Resolver::NameResolution::Resolve (parsed_crate);
+ }
// always restore the crate_num
mappings.set_current_crate (saved_crate_num);
diff --git a/gcc/rust/rust-session-manager.h b/gcc/rust/rust-session-manager.h
index 83ba121..9af103c 100644
--- a/gcc/rust/rust-session-manager.h
+++ b/gcc/rust/rust-session-manager.h
@@ -441,8 +441,7 @@ private:
#if CHECKING_P
namespace selftest {
-extern void
-rust_crate_name_validation_test (void);
+extern void rust_crate_name_validation_test (void);
}
#endif // CHECKING_P
diff --git a/gcc/rust/rust-system.h b/gcc/rust/rust-system.h
index 986428b..a455123 100644
--- a/gcc/rust/rust-system.h
+++ b/gcc/rust/rust-system.h
@@ -88,10 +88,8 @@ constexpr static const char *file_separator = "/";
*/
#define rust_unreachable() (fancy_abort (__FILE__, __LINE__, __FUNCTION__))
-extern void
-rust_preserve_from_gc (tree t);
+extern void rust_preserve_from_gc (tree t);
-extern const char *
-rust_localize_identifier (const char *ident);
+extern const char *rust_localize_identifier (const char *ident);
#endif // !defined(RUST_SYSTEM_H)
diff --git a/gcc/rust/rust-target.h b/gcc/rust/rust-target.h
index dbc2baf..e61ea51 100644
--- a/gcc/rust/rust-target.h
+++ b/gcc/rust/rust-target.h
@@ -26,8 +26,7 @@
#include "rust-target.def"
/* Used by target to add target-related info. */
-extern void
-rust_add_target_info (const char *, const char *);
+extern void rust_add_target_info (const char *, const char *);
/* Each target can provide their own. */
extern struct gcc_targetrustm targetrustm;
diff --git a/gcc/rust/typecheck/rust-autoderef.cc b/gcc/rust/typecheck/rust-autoderef.cc
index 6aa20a8..10a59bd 100644
--- a/gcc/rust/typecheck/rust-autoderef.cc
+++ b/gcc/rust/typecheck/rust-autoderef.cc
@@ -26,8 +26,7 @@
namespace Rust {
namespace Resolver {
-static bool
-resolve_operator_overload_fn (
+static bool resolve_operator_overload_fn (
LangItem::Kind lang_item_type, TyTy::BaseType *ty, TyTy::FnType **resolved_fn,
Adjustment::AdjustmentType *requires_ref_adjustment);
@@ -248,7 +247,6 @@ resolve_operator_overload_fn (
const TyTy::ADTType *adt = static_cast<const TyTy::ADTType *> (lhs);
auto s = fn->get_self_type ()->get_root ();
- rust_assert (s->can_eq (adt, false));
rust_assert (s->get_kind () == TyTy::TypeKind::ADT);
const TyTy::ADTType *self_adt
= static_cast<const TyTy::ADTType *> (s);
diff --git a/gcc/rust/typecheck/rust-casts.cc b/gcc/rust/typecheck/rust-casts.cc
index 90bdef1..f06d9ed 100644
--- a/gcc/rust/typecheck/rust-casts.cc
+++ b/gcc/rust/typecheck/rust-casts.cc
@@ -17,6 +17,7 @@
// <http://www.gnu.org/licenses/>.
#include "rust-casts.h"
+#include "rust-tyty-util.h"
namespace Rust {
namespace Resolver {
@@ -28,15 +29,20 @@ TypeCastRules::TypeCastRules (location_t locus, TyTy::TyWithLocation from,
TypeCoercionRules::CoercionResult
TypeCastRules::resolve (location_t locus, TyTy::TyWithLocation from,
- TyTy::TyWithLocation to)
+ TyTy::TyWithLocation to, bool emit_error)
{
TypeCastRules cast_rules (locus, from, to);
- return cast_rules.check ();
+ return cast_rules.check (emit_error);
}
TypeCoercionRules::CoercionResult
-TypeCastRules::check ()
+TypeCastRules::check (bool emit_error)
{
+ // try the simple cast rules
+ auto simple_cast = cast_rules ();
+ if (!simple_cast.is_error ())
+ return simple_cast;
+
// https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/cast.rs#L565-L582
auto possible_coercion
= TypeCoercionRules::TryCoerce (from.get_ty (), to.get_ty (), locus,
@@ -51,13 +57,9 @@ TypeCastRules::check ()
true /*is_cast_site*/);
}
- // try the simple cast rules
- auto simple_cast = cast_rules ();
- if (!simple_cast.is_error ())
- return simple_cast;
+ if (emit_error)
+ TypeCastRules::emit_cast_error (locus, from, to);
- // failed to cast
- emit_cast_error ();
return TypeCoercionRules::CoercionResult::get_error ();
}
@@ -73,7 +75,8 @@ TypeCastRules::cast_rules ()
to.get_ty ()->debug_str ().c_str ());
switch (from_type->get_kind ())
{
- case TyTy::TypeKind::INFER: {
+ case TyTy::TypeKind::INFER:
+ {
TyTy::InferType *from_infer
= static_cast<TyTy::InferType *> (from_type);
switch (from_infer->get_infer_kind ())
@@ -85,7 +88,8 @@ TypeCastRules::cast_rules ()
case TyTy::InferType::InferTypeKind::INTEGRAL:
switch (to.get_ty ()->get_kind ())
{
- case TyTy::TypeKind::CHAR: {
+ case TyTy::TypeKind::CHAR:
+ {
// only u8 and char
bool was_uint
= from.get_ty ()->get_kind () == TyTy::TypeKind::UINT;
@@ -108,7 +112,8 @@ TypeCastRules::cast_rules ()
return TypeCoercionRules::CoercionResult{
{}, to.get_ty ()->clone ()};
- case TyTy::TypeKind::INFER: {
+ case TyTy::TypeKind::INFER:
+ {
TyTy::InferType *to_infer
= static_cast<TyTy::InferType *> (to.get_ty ());
@@ -140,7 +145,8 @@ TypeCastRules::cast_rules ()
return TypeCoercionRules::CoercionResult{
{}, to.get_ty ()->clone ()};
- case TyTy::TypeKind::INFER: {
+ case TyTy::TypeKind::INFER:
+ {
TyTy::InferType *to_infer
= static_cast<TyTy::InferType *> (to.get_ty ());
@@ -187,7 +193,8 @@ TypeCastRules::cast_rules ()
case TyTy::TypeKind::INT:
switch (to.get_ty ()->get_kind ())
{
- case TyTy::TypeKind::CHAR: {
+ case TyTy::TypeKind::CHAR:
+ {
// only u8 and char
bool was_uint = from.get_ty ()->get_kind () == TyTy::TypeKind::UINT;
bool was_u8 = was_uint
@@ -200,7 +207,8 @@ TypeCastRules::cast_rules ()
}
break;
- case TyTy::TypeKind::FLOAT: {
+ case TyTy::TypeKind::FLOAT:
+ {
// can only do this for number types not char
bool from_char
= from.get_ty ()->get_kind () == TyTy::TypeKind::CHAR;
@@ -210,7 +218,8 @@ TypeCastRules::cast_rules ()
}
break;
- case TyTy::TypeKind::POINTER: {
+ case TyTy::TypeKind::POINTER:
+ {
// char can't be casted as a ptr
bool from_char
= from.get_ty ()->get_kind () == TyTy::TypeKind::CHAR;
@@ -244,7 +253,8 @@ TypeCastRules::cast_rules ()
case TyTy::TypeKind::FLOAT:
return TypeCoercionRules::CoercionResult{{}, to.get_ty ()->clone ()};
- case TyTy::TypeKind::INFER: {
+ case TyTy::TypeKind::INFER:
+ {
TyTy::InferType *to_infer
= static_cast<TyTy::InferType *> (to.get_ty ());
@@ -273,7 +283,8 @@ TypeCastRules::cast_rules ()
case TyTy::TypeKind::USIZE:
case TyTy::TypeKind::ISIZE:
case TyTy::TypeKind::UINT:
- case TyTy::TypeKind::INT: {
+ case TyTy::TypeKind::INT:
+ {
// refs should not cast to numeric type
bool from_ptr
= from.get_ty ()->get_kind () == TyTy::TypeKind::POINTER;
@@ -320,7 +331,27 @@ TypeCastRules::check_ptr_ptr_cast ()
}
else if (from_is_ref && to_is_ref)
{
- // mutability must be coercedable
+ const auto &from_ref = *from.get_ty ()->as<TyTy::ReferenceType> ();
+ const auto &to_ref = *to.get_ty ()->as<TyTy::ReferenceType> ();
+
+ if (from_ref.is_dyn_object () != to_ref.is_dyn_object ())
+ {
+ // this needs to be handled by coercion logic
+ return TypeCoercionRules::CoercionResult::get_error ();
+ }
+
+ // are the underlying types safely simple castable?
+ const auto to_underly = to_ref.get_base ();
+ const auto from_underly = from_ref.get_base ();
+ auto res = resolve (locus, TyTy::TyWithLocation (from_underly),
+ TyTy::TyWithLocation (to_underly), false);
+ if (res.is_error ())
+ {
+ // this needs to be handled by coercion logic
+ return TypeCoercionRules::CoercionResult::get_error ();
+ }
+
+ // mutability must be coerceable
TyTy::ReferenceType &f
= static_cast<TyTy::ReferenceType &> (*from.get_ty ());
TyTy::ReferenceType &t
@@ -337,7 +368,8 @@ TypeCastRules::check_ptr_ptr_cast ()
}
void
-TypeCastRules::emit_cast_error () const
+TypeCastRules::emit_cast_error (location_t locus, TyTy::TyWithLocation from,
+ TyTy::TyWithLocation to)
{
rich_location r (line_table, locus);
r.add_range (from.get_locus ());
diff --git a/gcc/rust/typecheck/rust-casts.h b/gcc/rust/typecheck/rust-casts.h
index 0d6ed68..10bb006 100644
--- a/gcc/rust/typecheck/rust-casts.h
+++ b/gcc/rust/typecheck/rust-casts.h
@@ -30,15 +30,17 @@ class TypeCastRules
public:
static TypeCoercionRules::CoercionResult resolve (location_t locus,
TyTy::TyWithLocation from,
- TyTy::TyWithLocation to);
+ TyTy::TyWithLocation to,
+ bool emit_error = true);
+
+ static void emit_cast_error (location_t locus, TyTy::TyWithLocation from,
+ TyTy::TyWithLocation to);
protected:
- TypeCoercionRules::CoercionResult check ();
+ TypeCoercionRules::CoercionResult check (bool emit_error);
TypeCoercionRules::CoercionResult cast_rules ();
TypeCoercionRules::CoercionResult check_ptr_ptr_cast ();
- void emit_cast_error () const;
-
protected:
TypeCastRules (location_t locus, TyTy::TyWithLocation from,
TyTy::TyWithLocation to);
diff --git a/gcc/rust/typecheck/rust-coercion.cc b/gcc/rust/typecheck/rust-coercion.cc
index 5905992..fd12839 100644
--- a/gcc/rust/typecheck/rust-coercion.cc
+++ b/gcc/rust/typecheck/rust-coercion.cc
@@ -125,13 +125,15 @@ TypeCoercionRules::do_coercion (TyTy::BaseType *receiver)
// pointers
switch (expected->get_kind ())
{
- case TyTy::TypeKind::POINTER: {
+ case TyTy::TypeKind::POINTER:
+ {
TyTy::PointerType *ptr = static_cast<TyTy::PointerType *> (expected);
try_result = coerce_unsafe_ptr (receiver, ptr, ptr->mutability ());
return !try_result.is_error ();
}
- case TyTy::TypeKind::REF: {
+ case TyTy::TypeKind::REF:
+ {
TyTy::ReferenceType *ptr
= static_cast<TyTy::ReferenceType *> (expected);
try_result
@@ -147,7 +149,8 @@ TypeCoercionRules::do_coercion (TyTy::BaseType *receiver)
// https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/coercion.rs#L210
switch (receiver->get_kind ())
{
- default: {
+ default:
+ {
rust_debug (
"do_coercion default unify and infer expected: %s receiver %s",
receiver->debug_str ().c_str (), expected->debug_str ().c_str ());
@@ -182,7 +185,8 @@ TypeCoercionRules::coerce_unsafe_ptr (TyTy::BaseType *receiver,
TyTy::BaseType *element = nullptr;
switch (receiver->get_kind ())
{
- case TyTy::TypeKind::REF: {
+ case TyTy::TypeKind::REF:
+ {
TyTy::ReferenceType *ref
= static_cast<TyTy::ReferenceType *> (receiver);
from_mutbl = ref->mutability ();
@@ -190,16 +194,19 @@ TypeCoercionRules::coerce_unsafe_ptr (TyTy::BaseType *receiver,
}
break;
- case TyTy::TypeKind::POINTER: {
+ case TyTy::TypeKind::POINTER:
+ {
TyTy::PointerType *ref = static_cast<TyTy::PointerType *> (receiver);
from_mutbl = ref->mutability ();
element = ref->get_base ();
}
break;
- default: {
- // FIXME this can probably turn into a unify_and
- if (receiver->can_eq (expected, false))
+ default:
+ {
+ if (types_compatable (TyTy::TyWithLocation (receiver),
+ TyTy::TyWithLocation (expected), UNKNOWN_LOCATION,
+ false))
return CoercionResult{{}, expected->clone ()};
return CoercionResult::get_error ();
@@ -264,17 +271,16 @@ TypeCoercionRules::coerce_borrowed_pointer (TyTy::BaseType *receiver,
Mutability from_mutbl = Mutability::Imm;
switch (receiver->get_kind ())
{
- case TyTy::TypeKind::REF: {
+ case TyTy::TypeKind::REF:
+ {
TyTy::ReferenceType *from
= static_cast<TyTy::ReferenceType *> (receiver);
from_mutbl = from->mutability ();
}
break;
- default: {
- // FIXME
- // we might be able to replace this with a can_eq because we default
- // back to a final unity anyway
+ default:
+ {
rust_debug ("coerce_borrowed_pointer -- unify");
TyTy::BaseType *result
= unify_site_and (receiver->get_ref (),
@@ -393,7 +399,7 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source,
if (expect_dyn && need_unsize)
{
- bool bounds_compatible = b->bounds_compatible (*a, locus, true);
+ bool bounds_compatible = b->bounds_compatible (*a, locus, false);
if (!bounds_compatible)
{
unsafe_error = true;
diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.cc b/gcc/rust/typecheck/rust-hir-dot-operator.cc
index c1165e9..7b7944c 100644
--- a/gcc/rust/typecheck/rust-hir-dot-operator.cc
+++ b/gcc/rust/typecheck/rust-hir-dot-operator.cc
@@ -102,26 +102,16 @@ MethodResolver::try_hook (const TyTy::BaseType &r)
}
}
-bool
-MethodResolver::select (TyTy::BaseType &receiver)
+std::vector<MethodResolver::impl_item_candidate>
+MethodResolver::assemble_inherent_impl_candidates (
+ const TyTy::BaseType &receiver)
{
- rust_debug ("MethodResolver::select reciever=[%s] path=[%s]",
- receiver.debug_str ().c_str (),
- segment_name.as_string ().c_str ());
-
- struct impl_item_candidate
- {
- HIR::Function *item;
- HIR::ImplBlock *impl_block;
- TyTy::FnType *ty;
- };
-
+ std::vector<impl_item_candidate> inherent_impl_fns;
const TyTy::BaseType *raw = receiver.destructure ();
bool receiver_is_raw_ptr = raw->get_kind () == TyTy::TypeKind::POINTER;
bool receiver_is_ref = raw->get_kind () == TyTy::TypeKind::REF;
- // assemble inherent impl items
- std::vector<impl_item_candidate> inherent_impl_fns;
+ // Assemble inherent impl items (non-trait impl blocks)
mappings.iterate_impl_items (
[&] (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl) mutable -> bool {
bool is_trait_impl = impl->has_trait_ref ();
@@ -190,16 +180,19 @@ MethodResolver::select (TyTy::BaseType &receiver)
return true;
});
- struct trait_item_candidate
- {
- const HIR::TraitItemFunc *item;
- const HIR::Trait *trait;
- TyTy::FnType *ty;
- const TraitReference *reference;
- const TraitItemReference *item_ref;
- };
+ return inherent_impl_fns;
+}
+
+void
+MethodResolver::assemble_trait_impl_candidates (
+ const TyTy::BaseType &receiver,
+ std::vector<impl_item_candidate> &impl_candidates,
+ std::vector<trait_item_candidate> &trait_candidates)
+{
+ const TyTy::BaseType *raw = receiver.destructure ();
+ bool receiver_is_raw_ptr = raw->get_kind () == TyTy::TypeKind::POINTER;
+ bool receiver_is_ref = raw->get_kind () == TyTy::TypeKind::REF;
- std::vector<trait_item_candidate> trait_fns;
mappings.iterate_impl_blocks ([&] (HirId id,
HIR::ImplBlock *impl) mutable -> bool {
bool is_trait_impl = impl->has_trait_ref ();
@@ -266,7 +259,7 @@ MethodResolver::select (TyTy::BaseType &receiver)
continue;
}
- inherent_impl_fns.push_back ({func, impl, fnty});
+ impl_candidates.push_back ({func, impl, fnty});
return true;
}
@@ -293,26 +286,15 @@ MethodResolver::select (TyTy::BaseType &receiver)
TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty);
trait_item_candidate candidate{func, trait, fnty, trait_ref, item_ref};
- trait_fns.push_back (candidate);
+ trait_candidates.push_back (candidate);
return true;
});
+}
- // lookup specified bounds for an associated item
- struct precdicate_candidate
- {
- TyTy::TypeBoundPredicateItem lookup;
- TyTy::FnType *fntype;
- };
-
- // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/method/probe.rs#L580-L694
-
- rust_debug ("inherent_impl_fns found {%lu}, trait_fns found {%lu}, "
- "predicate_items found {%lu}",
- (unsigned long) inherent_impl_fns.size (),
- (unsigned long) trait_fns.size (),
- (unsigned long) predicate_items.size ());
-
+bool
+MethodResolver::try_select_predicate_candidates (TyTy::BaseType &receiver)
+{
bool found_possible_candidate = false;
for (const auto &predicate : predicate_items)
{
@@ -346,60 +328,33 @@ MethodResolver::select (TyTy::BaseType &receiver)
found_possible_candidate = true;
}
}
- if (found_possible_candidate)
- {
- return true;
- }
+ return found_possible_candidate;
+}
- for (auto &impl_item : inherent_impl_fns)
+bool
+MethodResolver::try_select_inherent_impl_candidates (
+ TyTy::BaseType &receiver, const std::vector<impl_item_candidate> &candidates,
+ bool trait_impl_blocks_only)
+{
+ bool found_possible_candidate = false;
+ for (auto &impl_item : candidates)
{
bool is_trait_impl_block = impl_item.impl_block->has_trait_ref ();
- if (is_trait_impl_block)
+ if (trait_impl_blocks_only && !is_trait_impl_block)
continue;
-
- TyTy::FnType *fn = impl_item.ty;
- rust_assert (fn->is_method ());
-
- TyTy::BaseType *fn_self = fn->get_self_type ();
- rust_debug ("dot-operator impl_item fn_self={%s} can_eq receiver={%s}",
- fn_self->debug_str ().c_str (),
- receiver.debug_str ().c_str ());
-
- auto res
- = TypeCoercionRules::TryCoerce (&receiver, fn_self, UNDEF_LOCATION,
- false /*allow-autoderef*/);
- bool ok = !res.is_error ();
- if (ok)
- {
- std::vector<Adjustment> adjs = append_adjustments (res.adjustments);
- PathProbeCandidate::ImplItemCandidate c{impl_item.item,
- impl_item.impl_block};
- auto try_result = MethodCandidate{
- PathProbeCandidate (PathProbeCandidate::CandidateType::IMPL_FUNC,
- fn, impl_item.item->get_locus (), c),
- adjs};
- result.insert (std::move (try_result));
- found_possible_candidate = true;
- }
- }
- if (found_possible_candidate)
- {
- return true;
- }
-
- for (auto &impl_item : inherent_impl_fns)
- {
- bool is_trait_impl_block = impl_item.impl_block->has_trait_ref ();
- if (!is_trait_impl_block)
+ if (!trait_impl_blocks_only && is_trait_impl_block)
continue;
TyTy::FnType *fn = impl_item.ty;
rust_assert (fn->is_method ());
TyTy::BaseType *fn_self = fn->get_self_type ();
- rust_debug (
- "dot-operator trait_impl_item fn_self={%s} can_eq receiver={%s}",
- fn_self->debug_str ().c_str (), receiver.debug_str ().c_str ());
+
+ const char *debug_prefix
+ = trait_impl_blocks_only ? "trait_impl_item" : "impl_item";
+ rust_debug ("dot-operator %s fn_self={%s} can_eq receiver={%s}",
+ debug_prefix, fn_self->debug_str ().c_str (),
+ receiver.debug_str ().c_str ());
auto res
= TypeCoercionRules::TryCoerce (&receiver, fn_self, UNDEF_LOCATION,
@@ -418,12 +373,15 @@ MethodResolver::select (TyTy::BaseType &receiver)
found_possible_candidate = true;
}
}
- if (found_possible_candidate)
- {
- return true;
- }
+ return found_possible_candidate;
+}
- for (auto trait_item : trait_fns)
+bool
+MethodResolver::try_select_trait_impl_candidates (
+ TyTy::BaseType &receiver, const std::vector<trait_item_candidate> &candidates)
+{
+ bool found_possible_candidate = false;
+ for (auto trait_item : candidates)
{
TyTy::FnType *fn = trait_item.ty;
rust_assert (fn->is_method ());
@@ -451,10 +409,53 @@ MethodResolver::select (TyTy::BaseType &receiver)
found_possible_candidate = true;
}
}
-
return found_possible_candidate;
}
+bool
+MethodResolver::select (TyTy::BaseType &receiver)
+{
+ rust_debug ("MethodResolver::select reciever=[%s] path=[%s]",
+ receiver.debug_str ().c_str (),
+ segment_name.as_string ().c_str ());
+
+ // Assemble candidates
+ std::vector<impl_item_candidate> inherent_impl_fns
+ = assemble_inherent_impl_candidates (receiver);
+ std::vector<impl_item_candidate> trait_impl_fns;
+ std::vector<trait_item_candidate> trait_fns;
+ assemble_trait_impl_candidates (receiver, trait_impl_fns, trait_fns);
+
+ // Combine inherent and trait impl functions
+ inherent_impl_fns.insert (inherent_impl_fns.end (), trait_impl_fns.begin (),
+ trait_impl_fns.end ());
+
+ // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/method/probe.rs#L580-L694
+
+ rust_debug ("inherent_impl_fns found {%lu}, trait_fns found {%lu}, "
+ "predicate_items found {%lu}",
+ (unsigned long) inherent_impl_fns.size (),
+ (unsigned long) trait_fns.size (),
+ (unsigned long) predicate_items.size ());
+
+ // Try selection in the priority order defined by Rust's method resolution:
+
+ // 1. Try predicate candidates first (highest priority)
+ if (try_select_predicate_candidates (receiver))
+ return true;
+
+ // 2. Try inherent impl functions (non-trait impl blocks)
+ if (try_select_inherent_impl_candidates (receiver, inherent_impl_fns, false))
+ return true;
+
+ // 3. Try inherent impl functions from trait impl blocks
+ if (try_select_inherent_impl_candidates (receiver, inherent_impl_fns, true))
+ return true;
+
+ // 4. Try trait functions (lowest priority)
+ return try_select_trait_impl_candidates (receiver, trait_fns);
+}
+
std::vector<MethodResolver::predicate_candidate>
MethodResolver::get_predicate_items (
const HIR::PathIdentSegment &segment_name, const TyTy::BaseType &receiver,
diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.h b/gcc/rust/typecheck/rust-hir-dot-operator.h
index ab95a5a..cc40472 100644
--- a/gcc/rust/typecheck/rust-hir-dot-operator.h
+++ b/gcc/rust/typecheck/rust-hir-dot-operator.h
@@ -65,6 +65,22 @@ public:
const HIR::PathIdentSegment &segment_name, const TyTy::BaseType &receiver,
const std::vector<TyTy::TypeBoundPredicate> &specified_bounds);
+ struct impl_item_candidate
+ {
+ HIR::Function *item;
+ HIR::ImplBlock *impl_block;
+ TyTy::FnType *ty;
+ };
+
+ struct trait_item_candidate
+ {
+ const HIR::TraitItemFunc *item;
+ const HIR::Trait *trait;
+ TyTy::FnType *ty;
+ const TraitReference *reference;
+ const TraitItemReference *item_ref;
+ };
+
protected:
MethodResolver (bool autoderef_flag,
const HIR::PathIdentSegment &segment_name);
@@ -77,6 +93,25 @@ private:
std::vector<Adjustment>
append_adjustments (const std::vector<Adjustment> &adjustments) const;
+ std::vector<impl_item_candidate>
+ assemble_inherent_impl_candidates (const TyTy::BaseType &receiver);
+
+ void assemble_trait_impl_candidates (
+ const TyTy::BaseType &receiver,
+ std::vector<impl_item_candidate> &impl_candidates,
+ std::vector<trait_item_candidate> &trait_candidates);
+
+ bool try_select_predicate_candidates (TyTy::BaseType &receiver);
+
+ bool try_select_inherent_impl_candidates (
+ TyTy::BaseType &receiver,
+ const std::vector<impl_item_candidate> &candidates,
+ bool trait_impl_blocks_only);
+
+ bool try_select_trait_impl_candidates (
+ TyTy::BaseType &receiver,
+ const std::vector<trait_item_candidate> &candidates);
+
private:
// search
const HIR::PathIdentSegment &segment_name;
diff --git a/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h b/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h
index 5537b14..a66396f 100644
--- a/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h
+++ b/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h
@@ -79,27 +79,29 @@ public:
if (query == candidate)
continue;
- if (query->can_eq (candidate, false))
+ if (!types_compatable (TyTy::TyWithLocation (query),
+ TyTy::TyWithLocation (candidate),
+ UNKNOWN_LOCATION, false))
+ continue;
+
+ // we might be in the case that we have:
+ //
+ // *const T vs *const [T]
+ //
+ // so lets use an equality check when the
+ // candidates are both generic to be sure we dont emit a false
+ // positive
+
+ bool a = query->is_concrete ();
+ bool b = candidate->is_concrete ();
+ bool both_generic = !a && !b;
+ if (both_generic)
{
- // we might be in the case that we have:
- //
- // *const T vs *const [T]
- //
- // so lets use an equality check when the
- // candidates are both generic to be sure we dont emit a false
- // positive
-
- bool a = query->is_concrete ();
- bool b = candidate->is_concrete ();
- bool both_generic = !a && !b;
- if (both_generic)
- {
- if (!query->is_equal (*candidate))
- continue;
- }
-
- possible_collision (it->second, iy->second);
+ if (!query->is_equal (*candidate))
+ continue;
}
+
+ possible_collision (it->second, iy->second);
}
}
}
diff --git a/gcc/rust/typecheck/rust-hir-path-probe.cc b/gcc/rust/typecheck/rust-hir-path-probe.cc
index 32e2399..c02702f 100644
--- a/gcc/rust/typecheck/rust-hir-path-probe.cc
+++ b/gcc/rust/typecheck/rust-hir-path-probe.cc
@@ -137,7 +137,7 @@ PathProbeCandidate::operator< (const PathProbeCandidate &c) const
// PathProbeType
-PathProbeType::PathProbeType (const TyTy::BaseType *receiver,
+PathProbeType::PathProbeType (TyTy::BaseType *receiver,
const HIR::PathIdentSegment &query,
DefId specific_trait_id)
: TypeCheckBase (), receiver (receiver), search (query),
@@ -145,7 +145,7 @@ PathProbeType::PathProbeType (const TyTy::BaseType *receiver,
{}
std::set<PathProbeCandidate>
-PathProbeType::Probe (const TyTy::BaseType *receiver,
+PathProbeType::Probe (TyTy::BaseType *receiver,
const HIR::PathIdentSegment &segment_name,
bool probe_impls, bool probe_bounds,
bool ignore_mandatory_trait_items,
@@ -443,7 +443,7 @@ PathProbeType::is_receiver_generic () const
// PathProbImplTrait
-PathProbeImplTrait::PathProbeImplTrait (const TyTy::BaseType *receiver,
+PathProbeImplTrait::PathProbeImplTrait (TyTy::BaseType *receiver,
const HIR::PathIdentSegment &query,
const TraitReference *trait_reference)
: PathProbeType (receiver, query, UNKNOWN_DEFID),
@@ -451,7 +451,7 @@ PathProbeImplTrait::PathProbeImplTrait (const TyTy::BaseType *receiver,
{}
std::set<PathProbeCandidate>
-PathProbeImplTrait::Probe (const TyTy::BaseType *receiver,
+PathProbeImplTrait::Probe (TyTy::BaseType *receiver,
const HIR::PathIdentSegment &segment_name,
const TraitReference *trait_reference)
{
diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h b/gcc/rust/typecheck/rust-hir-path-probe.h
index 59ffeb1..936bcb9 100644
--- a/gcc/rust/typecheck/rust-hir-path-probe.h
+++ b/gcc/rust/typecheck/rust-hir-path-probe.h
@@ -108,9 +108,8 @@ class PathProbeType : public TypeCheckBase, public HIR::HIRImplVisitor
{
public:
static std::set<PathProbeCandidate>
- Probe (const TyTy::BaseType *receiver,
- const HIR::PathIdentSegment &segment_name, bool probe_impls,
- bool probe_bounds, bool ignore_mandatory_trait_items,
+ Probe (TyTy::BaseType *receiver, const HIR::PathIdentSegment &segment_name,
+ bool probe_impls, bool probe_bounds, bool ignore_mandatory_trait_items,
DefId specific_trait_id = UNKNOWN_DEFID);
void visit (HIR::TypeAlias &alias) override;
@@ -135,8 +134,8 @@ protected:
bool ignore_mandatory_trait_items);
protected:
- PathProbeType (const TyTy::BaseType *receiver,
- const HIR::PathIdentSegment &query, DefId specific_trait_id);
+ PathProbeType (TyTy::BaseType *receiver, const HIR::PathIdentSegment &query,
+ DefId specific_trait_id);
std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>>
union_bounds (
@@ -147,7 +146,7 @@ protected:
bool is_receiver_generic () const;
- const TyTy::BaseType *receiver;
+ TyTy::BaseType *receiver;
const HIR::PathIdentSegment &search;
std::set<PathProbeCandidate> candidates;
HIR::ImplBlock *current_impl;
@@ -178,12 +177,11 @@ class PathProbeImplTrait : public PathProbeType
{
public:
static std::set<PathProbeCandidate>
- Probe (const TyTy::BaseType *receiver,
- const HIR::PathIdentSegment &segment_name,
+ Probe (TyTy::BaseType *receiver, const HIR::PathIdentSegment &segment_name,
const TraitReference *trait_reference);
private:
- PathProbeImplTrait (const TyTy::BaseType *receiver,
+ PathProbeImplTrait (TyTy::BaseType *receiver,
const HIR::PathIdentSegment &query,
const TraitReference *trait_reference);
diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.cc b/gcc/rust/typecheck/rust-hir-trait-reference.cc
index 83985f0..74856f0 100644
--- a/gcc/rust/typecheck/rust-hir-trait-reference.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-reference.cc
@@ -342,7 +342,15 @@ TraitReference::on_resolved ()
{
for (auto &item : item_refs)
{
- item.on_resolved ();
+ if (item.get_trait_item_type ()
+ == TraitItemReference::TraitItemType::TYPE)
+ item.on_resolved ();
+ }
+ for (auto &item : item_refs)
+ {
+ if (item.get_trait_item_type ()
+ != TraitItemReference::TraitItemType::TYPE)
+ item.on_resolved ();
}
}
@@ -424,7 +432,13 @@ TraitReference::trait_has_generics () const
return !trait_substs.empty ();
}
-std::vector<TyTy::SubstitutionParamMapping>
+std::vector<TyTy::SubstitutionParamMapping> &
+TraitReference::get_trait_substs ()
+{
+ return trait_substs;
+}
+
+const std::vector<TyTy::SubstitutionParamMapping> &
TraitReference::get_trait_substs () const
{
return trait_substs;
diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.h b/gcc/rust/typecheck/rust-hir-trait-reference.h
index 8b1ac7d..473513e 100644
--- a/gcc/rust/typecheck/rust-hir-trait-reference.h
+++ b/gcc/rust/typecheck/rust-hir-trait-reference.h
@@ -224,7 +224,9 @@ public:
bool trait_has_generics () const;
- std::vector<TyTy::SubstitutionParamMapping> get_trait_substs () const;
+ std::vector<TyTy::SubstitutionParamMapping> &get_trait_substs ();
+
+ const std::vector<TyTy::SubstitutionParamMapping> &get_trait_substs () const;
bool satisfies_bound (const TraitReference &reference) const;
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
index 032bb58..0fd0147 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
@@ -22,9 +22,6 @@
#include "rust-type-util.h"
#include "rust-immutable-name-resolution-context.h"
-// used for flag_name_resolution_2_0
-#include "options.h"
-
namespace Rust {
namespace Resolver {
@@ -123,28 +120,16 @@ bool
TraitResolver::resolve_path_to_trait (const HIR::TypePath &path,
HIR::Trait **resolved) const
{
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
+
NodeId ref;
- bool ok;
- if (flag_name_resolution_2_0)
+ if (auto ref_opt = nr_ctx.lookup (path.get_mappings ().get_nodeid ()))
{
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- auto ref_opt = nr_ctx.lookup (path.get_mappings ().get_nodeid ());
-
- if ((ok = ref_opt.has_value ()))
- ref = *ref_opt;
+ ref = *ref_opt;
}
else
{
- auto path_nodeid = path.get_mappings ().get_nodeid ();
- ok = resolver->lookup_resolved_type (path_nodeid, &ref)
- || resolver->lookup_resolved_name (path_nodeid, &ref)
- || resolver->lookup_resolved_macro (path_nodeid, &ref);
- }
-
- if (!ok)
- {
rust_error_at (path.get_locus (), "Failed to resolve path to node-id");
return false;
}
@@ -224,7 +209,8 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference)
// handling.
break;
- case HIR::GenericParam::GenericKind::TYPE: {
+ case HIR::GenericParam::GenericKind::TYPE:
+ {
auto &typaram = static_cast<HIR::TypeParam &> (*generic_param);
bool is_self
= typaram.get_type_representation ().as_string ().compare ("Self")
@@ -287,7 +273,8 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference)
auto predicate = get_predicate_from_bound (
b->get_path (),
- tl::nullopt /*this will setup a PLACEHOLDER for self*/);
+ tl::nullopt /*this will setup a PLACEHOLDER for self*/,
+ BoundPolarity::RegularBound, false, true);
if (predicate.is_error ())
return &TraitReference::error_node ();
@@ -443,11 +430,27 @@ TraitItemReference::associated_type_set (TyTy::BaseType *ty) const
{
rust_assert (get_trait_item_type () == TraitItemType::TYPE);
+ // this isnt super safe there are cases like the FnTraits where the type is
+ // set to the impls placeholder associated type. For example
+ //
+ // type Output = F::Output; -- see the fn trait impls in libcore
+ //
+ // then this projection ends up resolving back to this placeholder so it just
+ // ends up being cyclical
+
TyTy::BaseType *item_ty = get_tyty ();
rust_assert (item_ty->get_kind () == TyTy::TypeKind::PLACEHOLDER);
TyTy::PlaceholderType *placeholder
= static_cast<TyTy::PlaceholderType *> (item_ty);
+ if (ty->is<TyTy::ProjectionType> ())
+ {
+ const auto &projection = *static_cast<const TyTy::ProjectionType *> (ty);
+ const auto resolved = projection.get ();
+ if (resolved == item_ty)
+ return;
+ }
+
placeholder->set_associated_type (ty->get_ty_ref ());
}
@@ -543,7 +546,8 @@ AssociatedImplTrait::setup_associated_types (
// handling.
break;
- case HIR::GenericParam::GenericKind::TYPE: {
+ case HIR::GenericParam::GenericKind::TYPE:
+ {
TyTy::BaseType *l = nullptr;
bool ok = context->lookup_type (
generic_param->get_mappings ().get_hirid (), &l);
@@ -580,8 +584,8 @@ AssociatedImplTrait::setup_associated_types (
}
else
{
- TyTy::ParamType *param = p.get_param_ty ();
- TyTy::BaseType *resolved = param->destructure ();
+ auto param = p.get_param_ty ();
+ auto resolved = param->destructure ();
subst_args.push_back (TyTy::SubstitutionArg (&p, resolved));
param_mappings[param->get_symbol ()] = resolved->get_ref ();
}
@@ -609,8 +613,8 @@ AssociatedImplTrait::setup_associated_types (
if (i == 0)
continue;
- const TyTy::ParamType *p = arg.get_param_ty ();
- TyTy::BaseType *r = p->resolve ();
+ const auto p = arg.get_param_ty ();
+ auto r = p->resolve ();
if (!r->is_concrete ())
{
r = SubstMapperInternal::Resolve (r, infer_arguments);
@@ -626,8 +630,8 @@ AssociatedImplTrait::setup_associated_types (
if (i == 0)
continue;
- const TyTy::ParamType *p = arg.get_param_ty ();
- TyTy::BaseType *r = p->resolve ();
+ const auto p = arg.get_param_ty ();
+ auto r = p->resolve ();
if (!r->is_concrete ())
{
r = SubstMapperInternal::Resolve (r, infer_arguments);
@@ -753,7 +757,8 @@ TraitItemReference::is_object_safe () const
// https://doc.rust-lang.org/reference/items/traits.html#object-safety
switch (get_trait_item_type ())
{
- case TraitItemReference::TraitItemType::FN: {
+ case TraitItemReference::TraitItemType::FN:
+ {
// lets be boring and just check that this is indeed a method will do
// for now
const HIR::TraitItem *item = get_hir_trait_item ();
diff --git a/gcc/rust/typecheck/rust-hir-type-bounds.h b/gcc/rust/typecheck/rust-hir-type-bounds.h
index 82333f1..5384700 100644
--- a/gcc/rust/typecheck/rust-hir-type-bounds.h
+++ b/gcc/rust/typecheck/rust-hir-type-bounds.h
@@ -37,7 +37,11 @@ public:
private:
void scan ();
- void assemble_sized_builtin ();
+ bool
+ process_impl_block (HirId id, HIR::ImplBlock *impl,
+ std::vector<std::pair<HIR::TypePath *, HIR::ImplBlock *>>
+ &possible_trait_paths);
+ void assemble_marker_builtins ();
void add_trait_bound (HIR::Trait *trait);
void assemble_builtin_candidate (LangItem::Kind item);
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc
index 14b8ab8..68001bf 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc
@@ -17,28 +17,33 @@
// <http://www.gnu.org/licenses/>.
#include "rust-hir-type-check-base.h"
+#include "rust-compile-base.h"
+#include "rust-hir-item.h"
#include "rust-hir-type-check-expr.h"
#include "rust-hir-type-check-type.h"
#include "rust-hir-trait-resolve.h"
#include "rust-type-util.h"
#include "rust-attribute-values.h"
+#include "rust-tyty.h"
+#include "tree.h"
namespace Rust {
namespace Resolver {
TypeCheckBase::TypeCheckBase ()
- : mappings (Analysis::Mappings::get ()), resolver (Resolver::get ()),
- context (TypeCheckContext::get ())
+ : mappings (Analysis::Mappings::get ()), context (TypeCheckContext::get ())
{}
void
TypeCheckBase::ResolveGenericParams (
+ const HIR::Item::ItemKind item_kind, location_t item_locus,
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);
+ ctx.resolve_generic_params (item_kind, item_locus, generic_params,
+ substitutions, is_foreign, abi);
}
static void
@@ -47,10 +52,10 @@ walk_types_to_constrain (std::set<HirId> &constrained_symbols,
{
for (const auto &c : constraints.get_mappings ())
{
- const TyTy::BaseType *arg = c.get_tyty ();
+ auto arg = c.get_tyty ();
if (arg != nullptr)
{
- const TyTy::BaseType *p = arg->get_root ();
+ const auto p = arg->get_root ();
constrained_symbols.insert (p->get_ty_ref ());
if (p->has_substitutions_defined ())
{
@@ -66,7 +71,7 @@ TypeCheckBase::check_for_unconstrained (
const std::vector<TyTy::SubstitutionParamMapping> &params_to_constrain,
const TyTy::SubstitutionArgumentMappings &constraint_a,
const TyTy::SubstitutionArgumentMappings &constraint_b,
- const TyTy::BaseType *reference)
+ TyTy::BaseType *reference)
{
bool check_result = false;
bool check_completed
@@ -124,7 +129,8 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings,
TyTy::BaseType *infered = nullptr;
switch (literal.get_lit_type ())
{
- case HIR::Literal::LitType::INT: {
+ case HIR::Literal::LitType::INT:
+ {
bool ok = false;
switch (literal.get_type_hint ())
@@ -191,7 +197,8 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings,
}
break;
- case HIR::Literal::LitType::FLOAT: {
+ case HIR::Literal::LitType::FLOAT:
+ {
bool ok = false;
switch (literal.get_type_hint ())
@@ -216,25 +223,29 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings,
}
break;
- case HIR::Literal::LitType::BOOL: {
+ case HIR::Literal::LitType::BOOL:
+ {
auto ok = context->lookup_builtin ("bool", &infered);
rust_assert (ok);
}
break;
- case HIR::Literal::LitType::CHAR: {
+ case HIR::Literal::LitType::CHAR:
+ {
auto ok = context->lookup_builtin ("char", &infered);
rust_assert (ok);
}
break;
- case HIR::Literal::LitType::BYTE: {
+ case HIR::Literal::LitType::BYTE:
+ {
auto ok = context->lookup_builtin ("u8", &infered);
rust_assert (ok);
}
break;
- case HIR::Literal::LitType::STRING: {
+ case HIR::Literal::LitType::STRING:
+ {
TyTy::BaseType *base = nullptr;
auto ok = context->lookup_builtin ("str", &base);
rust_assert (ok);
@@ -246,7 +257,8 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings,
}
break;
- case HIR::Literal::LitType::BYTE_STRING: {
+ case HIR::Literal::LitType::BYTE_STRING:
+ {
/* This is an arraytype of u8 reference (&[u8;size]). It isn't in
UTF-8, but really just a byte array. Code to construct the array
reference copied from ArrayElemsValues and ArrayType. */
@@ -280,10 +292,21 @@ TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings,
crate_num),
UNKNOWN_LOCAL_DEFID);
+ auto ctx = Compile::Context::get ();
+ tree capacity = Compile::HIRCompileBase::query_compile_const_expr (
+ ctx, expected_ty, *literal_capacity);
+
+ TyTy::ConstType *capacity_expr
+ = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, "",
+ expected_ty, capacity, {},
+ literal_capacity->get_locus (),
+ literal_capacity->get_mappings ().get_hirid (),
+ literal_capacity->get_mappings ().get_hirid (),
+ {});
+
TyTy::ArrayType *array
= new TyTy::ArrayType (array_mapping.get_hirid (), locus,
- *literal_capacity,
- TyTy::TyVar (u8->get_ref ()));
+ capacity_expr, TyTy::TyVar (u8->get_ref ()));
context->insert_type (array_mapping, array);
infered = new TyTy::ReferenceType (expr_mappings.get_hirid (),
@@ -432,6 +455,7 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus)
void
TypeCheckBase::resolve_generic_params (
+ const HIR::Item::ItemKind item_kind, location_t item_locus,
const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params,
std::vector<TyTy::SubstitutionParamMapping> &substitutions, bool is_foreign,
ABI abi)
@@ -440,7 +464,8 @@ TypeCheckBase::resolve_generic_params (
{
switch (generic_param->get_kind ())
{
- case HIR::GenericParam::GenericKind::LIFETIME: {
+ case HIR::GenericParam::GenericKind::LIFETIME:
+ {
auto lifetime_param
= static_cast<HIR::LifetimeParam &> (*generic_param);
auto lifetime = lifetime_param.get_lifetime ();
@@ -449,7 +474,8 @@ TypeCheckBase::resolve_generic_params (
}
break;
- case HIR::GenericParam::GenericKind::CONST: {
+ case HIR::GenericParam::GenericKind::CONST:
+ {
if (is_foreign && abi != Rust::ABI::INTRINSIC)
{
rust_error_at (generic_param->get_locus (), ErrorCode::E0044,
@@ -462,6 +488,27 @@ TypeCheckBase::resolve_generic_params (
if (param.has_default_expression ())
{
+ switch (item_kind)
+ {
+ case HIR::Item::ItemKind::Struct:
+ case HIR::Item::ItemKind::Enum:
+ case HIR::Item::ItemKind::TypeAlias:
+ case HIR::Item::ItemKind::Trait:
+ case HIR::Item::ItemKind::Union:
+ break;
+
+ default:
+ {
+ rich_location r (line_table, item_locus);
+ r.add_fixit_remove (param.get_locus ());
+ rust_error_at (
+ r,
+ "default values for const generic parameters are not "
+ "allowed here");
+ }
+ break;
+ }
+
auto expr_type
= TypeCheckExpr::Resolve (param.get_default_expression ());
@@ -471,14 +518,39 @@ TypeCheckBase::resolve_generic_params (
expr_type,
param.get_default_expression ().get_locus ()),
param.get_locus ());
+
+ // fold the default value
+ auto ctx = Compile::Context::get ();
+ auto &expr = param.get_default_expression ();
+ tree default_value
+ = Compile::HIRCompileBase::query_compile_const_expr (
+ ctx, specified_type, expr);
+
+ TyTy::ConstType *default_const_decl
+ = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value,
+ param.get_name (), specified_type,
+ default_value, {}, param.get_locus (),
+ expr.get_mappings ().get_hirid (),
+ expr.get_mappings ().get_hirid (), {});
+
+ context->insert_type (expr.get_mappings (), default_const_decl);
}
- context->insert_type (generic_param->get_mappings (),
- specified_type);
+ TyTy::ConstType *const_decl
+ = new TyTy::ConstType (TyTy::ConstType::ConstKind::Decl,
+ param.get_name (), specified_type,
+ error_mark_node, {}, param.get_locus (),
+ param.get_mappings ().get_hirid (),
+ param.get_mappings ().get_hirid (), {});
+
+ context->insert_type (generic_param->get_mappings (), const_decl);
+ TyTy::SubstitutionParamMapping p (*generic_param, const_decl);
+ substitutions.push_back (p);
}
break;
- case HIR::GenericParam::GenericKind::TYPE: {
+ case HIR::GenericParam::GenericKind::TYPE:
+ {
if (is_foreign && abi != Rust::ABI::INTRINSIC)
{
rust_error_at (generic_param->get_locus (), ErrorCode::E0044,
@@ -489,8 +561,7 @@ TypeCheckBase::resolve_generic_params (
*generic_param, false /*resolve_trait_bounds*/);
context->insert_type (generic_param->get_mappings (), param_type);
- auto &param = static_cast<HIR::TypeParam &> (*generic_param);
- TyTy::SubstitutionParamMapping p (param, param_type);
+ TyTy::SubstitutionParamMapping p (*generic_param, param_type);
substitutions.push_back (p);
}
break;
@@ -500,9 +571,16 @@ TypeCheckBase::resolve_generic_params (
// 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);
+ auto &generic = subst.get_generic_param ();
+ if (generic.get_kind () != HIR::GenericParam::GenericKind::TYPE)
+ continue;
+
+ auto &type_param = static_cast<HIR::TypeParam &> (generic);
+ auto bpty = subst.get_param_ty ();
+ rust_assert (bpty->get_kind () == TyTy::TypeKind::PARAM);
+ auto pty = static_cast<TyTy::ParamType *> (bpty);
+
+ TypeResolveGenericParam::ApplyAnyTraitBounds (type_param, pty);
}
}
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h b/gcc/rust/typecheck/rust-hir-type-check-base.h
index 580082a..6430089 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.h
@@ -33,6 +33,7 @@ public:
virtual ~TypeCheckBase () {}
static void ResolveGenericParams (
+ const HIR::Item::ItemKind item_kind, location_t item_locus,
const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params,
std::vector<TyTy::SubstitutionParamMapping> &substitutions, bool is_foreign,
ABI abi);
@@ -46,13 +47,13 @@ protected:
HIR::TypePath &path,
tl::optional<std::reference_wrapper<HIR::Type>> associated_self,
BoundPolarity polarity = BoundPolarity::RegularBound,
- bool is_qualified_type = false);
+ bool is_qualified_type = false, bool is_super_trait = false);
bool check_for_unconstrained (
const std::vector<TyTy::SubstitutionParamMapping> &params_to_constrain,
const TyTy::SubstitutionArgumentMappings &constraint_a,
const TyTy::SubstitutionArgumentMappings &constraint_b,
- const TyTy::BaseType *reference);
+ TyTy::BaseType *reference);
TyTy::BaseType *resolve_literal (const Analysis::NodeMapping &mappings,
HIR::Literal &literal, location_t locus);
@@ -61,6 +62,7 @@ protected:
location_t locus);
void resolve_generic_params (
+ const HIR::Item::ItemKind item_kind, location_t item_locus,
const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params,
std::vector<TyTy::SubstitutionParamMapping> &substitutions,
bool is_foreign = false, ABI abi = ABI::RUST);
@@ -69,7 +71,6 @@ protected:
location_t locus);
Analysis::Mappings &mappings;
- Resolver *resolver;
TypeCheckContext *context;
};
diff --git a/gcc/rust/typecheck/rust-hir-type-check-enumitem.cc b/gcc/rust/typecheck/rust-hir-type-check-enumitem.cc
index c80a12f..23a8cca 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-enumitem.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-enumitem.cc
@@ -23,9 +23,6 @@
#include "rust-type-util.h"
#include "rust-immutable-name-resolution-context.h"
-// for flag_name_resolution_2_0
-#include "options.h"
-
namespace Rust {
namespace Resolver {
@@ -79,25 +76,13 @@ TypeCheckEnumItem::visit (HIR::EnumItem &item)
rust_assert (ok);
context->insert_type (mapping, isize);
- tl::optional<CanonicalPath> canonical_path;
-
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- canonical_path
- = nr_ctx.types.to_canonical_path (item.get_mappings ().get_nodeid ());
- }
- else
- {
- canonical_path
- = mappings.lookup_canonical_path (item.get_mappings ().get_nodeid ());
- }
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- rust_assert (canonical_path.has_value ());
+ CanonicalPath canonical_path
+ = nr_ctx.to_canonical_path (item.get_mappings ().get_nodeid ());
- RustIdent ident{*canonical_path, item.get_locus ()};
+ RustIdent ident{canonical_path, item.get_locus ()};
variant = new TyTy::VariantDef (item.get_mappings ().get_hirid (),
item.get_mappings ().get_defid (),
item.get_identifier ().as_string (), ident,
@@ -123,25 +108,13 @@ TypeCheckEnumItem::visit (HIR::EnumItemDiscriminant &item)
TyTy::TyWithLocation (expected_ty),
TyTy::TyWithLocation (capacity_type), item.get_locus ());
- tl::optional<CanonicalPath> canonical_path;
-
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- canonical_path
- = nr_ctx.types.to_canonical_path (item.get_mappings ().get_nodeid ());
- }
- else
- {
- canonical_path
- = mappings.lookup_canonical_path (item.get_mappings ().get_nodeid ());
- }
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- rust_assert (canonical_path.has_value ());
+ CanonicalPath canonical_path
+ = nr_ctx.to_canonical_path (item.get_mappings ().get_nodeid ());
- RustIdent ident{*canonical_path, item.get_locus ()};
+ RustIdent ident{canonical_path, item.get_locus ()};
variant
= new TyTy::VariantDef (item.get_mappings ().get_hirid (),
item.get_mappings ().get_defid (),
@@ -185,25 +158,13 @@ TypeCheckEnumItem::visit (HIR::EnumItemTuple &item)
rust_assert (ok);
context->insert_type (mapping, isize);
- tl::optional<CanonicalPath> canonical_path;
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- canonical_path
- = nr_ctx.types.to_canonical_path (item.get_mappings ().get_nodeid ());
- }
- else
- {
- canonical_path
- = mappings.lookup_canonical_path (item.get_mappings ().get_nodeid ());
- }
-
- rust_assert (canonical_path.has_value ());
+ CanonicalPath canonical_path
+ = nr_ctx.to_canonical_path (item.get_mappings ().get_nodeid ());
- RustIdent ident{*canonical_path, item.get_locus ()};
+ RustIdent ident{canonical_path, item.get_locus ()};
variant = new TyTy::VariantDef (item.get_mappings ().get_hirid (),
item.get_mappings ().get_defid (),
item.get_identifier ().as_string (), ident,
@@ -245,25 +206,13 @@ TypeCheckEnumItem::visit (HIR::EnumItemStruct &item)
rust_assert (ok);
context->insert_type (mapping, isize);
- tl::optional<CanonicalPath> canonical_path;
-
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- canonical_path
- = nr_ctx.types.to_canonical_path (item.get_mappings ().get_nodeid ());
- }
- else
- {
- canonical_path
- = mappings.lookup_canonical_path (item.get_mappings ().get_nodeid ());
- }
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- rust_assert (canonical_path.has_value ());
+ CanonicalPath canonical_path
+ = nr_ctx.to_canonical_path (item.get_mappings ().get_nodeid ());
- RustIdent ident{*canonical_path, item.get_locus ()};
+ RustIdent ident{canonical_path, item.get_locus ()};
variant = new TyTy::VariantDef (item.get_mappings ().get_hirid (),
item.get_mappings ().get_defid (),
item.get_identifier ().as_string (), ident,
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index cbf529a7..438200b 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -17,6 +17,7 @@
// <http://www.gnu.org/licenses/>.
#include "optional.h"
+#include "rust-common.h"
#include "rust-hir-expr.h"
#include "rust-system.h"
#include "rust-tyty-call.h"
@@ -31,9 +32,9 @@
#include "rust-hir-type-check-item.h"
#include "rust-type-util.h"
#include "rust-immutable-name-resolution-context.h"
-
-// for flag_name_resolution_2_0
-#include "options.h"
+#include "rust-compile-base.h"
+#include "rust-tyty-util.h"
+#include "tree.h"
namespace Rust {
namespace Resolver {
@@ -58,6 +59,19 @@ TypeCheckExpr::Resolve (HIR::Expr &expr)
return resolver.infered;
}
+TyTy::BaseType *
+TypeCheckExpr::ResolveOpOverload (LangItem::Kind lang_item_type,
+ HIR::OperatorExprMeta expr,
+ TyTy::BaseType *lhs, TyTy::BaseType *rhs,
+ HIR::PathIdentSegment specified_segment)
+{
+ TypeCheckExpr resolver;
+
+ resolver.resolve_operator_overload (lang_item_type, expr, lhs, rhs,
+ specified_segment);
+ return resolver.infered;
+}
+
void
TypeCheckExpr::visit (HIR::TupleIndexExpr &expr)
{
@@ -373,7 +387,8 @@ TypeCheckExpr::visit (HIR::ArithmeticOrLogicalExpr &expr)
switch (expr.get_expr_type ())
{
case ArithmeticOrLogicalOperator::LEFT_SHIFT:
- case ArithmeticOrLogicalOperator::RIGHT_SHIFT: {
+ case ArithmeticOrLogicalOperator::RIGHT_SHIFT:
+ {
TyTy::TyWithLocation from (rhs, expr.get_rhs ().get_locus ());
TyTy::TyWithLocation to (lhs, expr.get_lhs ().get_locus ());
infered = cast_site (expr.get_mappings ().get_hirid (), from, to,
@@ -381,7 +396,8 @@ TypeCheckExpr::visit (HIR::ArithmeticOrLogicalExpr &expr)
}
break;
- default: {
+ default:
+ {
infered = unify_site (
expr.get_mappings ().get_hirid (),
TyTy::TyWithLocation (lhs, expr.get_lhs ().get_locus ()),
@@ -470,7 +486,8 @@ TypeCheckExpr::visit (HIR::NegationExpr &expr)
// https://doc.rust-lang.org/reference/expressions/operator-expr.html#negation-operators
switch (expr.get_expr_type ())
{
- case NegationOperator::NEGATE: {
+ case NegationOperator::NEGATE:
+ {
bool valid
= (negated_expr_ty->get_kind () == TyTy::TypeKind::INT)
|| (negated_expr_ty->get_kind () == TyTy::TypeKind::UINT)
@@ -492,7 +509,8 @@ TypeCheckExpr::visit (HIR::NegationExpr &expr)
}
break;
- case NegationOperator::NOT: {
+ case NegationOperator::NOT:
+ {
bool valid
= (negated_expr_ty->get_kind () == TyTy::TypeKind::BOOL)
|| (negated_expr_ty->get_kind () == TyTy::TypeKind::INT)
@@ -643,6 +661,33 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr)
}
void
+TypeCheckExpr::visit (HIR::AnonConst &expr)
+{
+ if (!expr.is_deferred ())
+ {
+ infered = TypeCheckExpr::Resolve (expr.get_inner_expr ());
+ return;
+ }
+
+ auto locus = expr.get_locus ();
+ auto infer_ty_var = TyTy::TyVar::get_implicit_infer_var (locus);
+
+ HirId next = mappings.get_next_hir_id ();
+ infered = new TyTy::ConstType (TyTy::ConstType::ConstKind::Infer, "",
+ infer_ty_var.get_tyty (), error_mark_node, {},
+ locus, next, next, {});
+
+ context->insert_implicit_type (infered->get_ref (), infered);
+ mappings.insert_location (infered->get_ref (), locus);
+}
+
+void
+TypeCheckExpr::visit (HIR::ConstBlock &expr)
+{
+ infered = TypeCheckExpr::Resolve (expr.get_const_expr ());
+}
+
+void
TypeCheckExpr::visit (HIR::RangeFromToExpr &expr)
{
auto lang_item_type = LangItem::Kind::RANGE;
@@ -790,38 +835,45 @@ typecheck_inline_asm_operand (HIR::InlineAsm &expr)
{
switch (operand.get_register_type ())
{
- case RegisterType::In: {
+ case RegisterType::In:
+ {
auto in = operand.get_in ();
TypeCheckExpr::Resolve (*in.expr);
break;
}
- case RegisterType::Out: {
+ case RegisterType::Out:
+ {
auto out = operand.get_out ();
TypeCheckExpr::Resolve (*out.expr);
break;
}
- case RegisterType::InOut: {
+ case RegisterType::InOut:
+ {
auto in_out = operand.get_in_out ();
TypeCheckExpr::Resolve (*in_out.expr);
break;
}
- case RegisterType::SplitInOut: {
+ case RegisterType::SplitInOut:
+ {
auto split_in_out = operand.get_split_in_out ();
TypeCheckExpr::Resolve (*split_in_out.in_expr);
TypeCheckExpr::Resolve (*split_in_out.out_expr);
break;
}
- case RegisterType::Const: {
+ case RegisterType::Const:
+ {
auto anon_const = operand.get_const ().anon_const;
- TypeCheckExpr::Resolve (*anon_const.expr);
+ TypeCheckExpr::Resolve (anon_const.get_inner_expr ());
break;
}
- case RegisterType::Sym: {
+ case RegisterType::Sym:
+ {
auto sym = operand.get_sym ();
TypeCheckExpr::Resolve (*sym.expr);
break;
}
- case RegisterType::Label: {
+ case RegisterType::Label:
+ {
auto label = operand.get_label ();
TypeCheckExpr::Resolve (*label.expr);
break;
@@ -837,7 +889,7 @@ TypeCheckExpr::visit (HIR::InlineAsm &expr)
// NOTE: Hoise out if we have noreturn as an option
// to return a never type
// TODO : new keyword for memory seems sooooo shaky
- if (expr.options.count (AST::InlineAsmOption::NORETURN) == 1)
+ if (expr.options.count (AST::InlineAsm::Option::NORETURN) == 1)
infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ());
else
infered = TyTy::TupleType::get_unit_type ();
@@ -857,6 +909,19 @@ TypeCheckExpr::visit (HIR::LlvmInlineAsm &expr)
}
void
+TypeCheckExpr::visit (HIR::OffsetOf &expr)
+{
+ TypeCheckType::Resolve (expr.get_type ());
+
+ // FIXME: Does offset_of always return a usize?
+ TyTy::BaseType *size_ty;
+ bool ok = context->lookup_builtin ("usize", &size_ty);
+ rust_assert (ok);
+
+ infered = size_ty;
+}
+
+void
TypeCheckExpr::visit (HIR::RangeFullExpr &expr)
{
auto lang_item_type = LangItem::Kind::RANGE_FULL;
@@ -960,7 +1025,10 @@ TypeCheckExpr::visit (HIR::ArrayIndexExpr &expr)
bool ok = context->lookup_builtin ("usize", &size_ty);
rust_assert (ok);
- bool maybe_simple_array_access = index_expr_ty->can_eq (size_ty, false);
+ bool maybe_simple_array_access
+ = types_compatable (TyTy::TyWithLocation (index_expr_ty),
+ TyTy::TyWithLocation (size_ty), expr.get_locus (),
+ false);
if (maybe_simple_array_access
&& direct_array_expr_ty->get_kind () == TyTy::TypeKind::ARRAY)
{
@@ -996,8 +1064,7 @@ TypeCheckExpr::visit (HIR::ArrayIndexExpr &expr)
rich_location r (line_table, expr.get_locus ());
r.add_range (expr.get_array_expr ().get_locus ());
r.add_range (expr.get_index_expr ().get_locus ());
- rust_error_at (r, ErrorCode::E0277,
- "the type %qs cannot be indexed by %qs",
+ rust_error_at (r, ErrorCode::E0277, "the type %qs cannot be indexed by %qs",
array_expr_ty->get_name ().c_str (),
index_expr_ty->get_name ().c_str ());
}
@@ -1007,35 +1074,40 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr)
{
auto &elements = expr.get_internal_elements ();
+ TyTy::BaseType *expected_ty = nullptr;
+ bool ok = context->lookup_builtin ("usize", &expected_ty);
+ rust_assert (ok);
+
HIR::Expr *capacity_expr = nullptr;
TyTy::BaseType *element_type = nullptr;
+ TyTy::BaseType *capacity_type = nullptr;
switch (elements.get_array_expr_type ())
{
- case HIR::ArrayElems::ArrayExprType::COPIED: {
+ case HIR::ArrayElems::ArrayExprType::COPIED:
+ {
HIR::ArrayElemsCopied &elems
= static_cast<HIR::ArrayElemsCopied &> (elements);
element_type = TypeCheckExpr::Resolve (elems.get_elem_to_copy ());
- auto capacity_type
+ auto capacity_expr_ty
= TypeCheckExpr::Resolve (elems.get_num_copies_expr ());
- TyTy::BaseType *expected_ty = nullptr;
- bool ok = context->lookup_builtin ("usize", &expected_ty);
- rust_assert (ok);
context->insert_type (elems.get_num_copies_expr ().get_mappings (),
expected_ty);
- unify_site (expr.get_mappings ().get_hirid (),
- TyTy::TyWithLocation (expected_ty),
- TyTy::TyWithLocation (
- capacity_type, elems.get_num_copies_expr ().get_locus ()),
- expr.get_locus ());
+ unify_site (
+ expr.get_mappings ().get_hirid (), TyTy::TyWithLocation (expected_ty),
+ TyTy::TyWithLocation (capacity_expr_ty,
+ elems.get_num_copies_expr ().get_locus ()),
+ expr.get_locus ());
capacity_expr = &elems.get_num_copies_expr ();
+ capacity_type = expected_ty;
}
break;
- case HIR::ArrayElems::ArrayExprType::VALUES: {
+ case HIR::ArrayElems::ArrayExprType::VALUES:
+ {
HIR::ArrayElemsValues &elems
= static_cast<HIR::ArrayElemsValues &> (elements);
@@ -1068,17 +1140,26 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr)
UNDEF_LOCATION, {});
// mark the type for this implicit node
- TyTy::BaseType *expected_ty = nullptr;
- bool ok = context->lookup_builtin ("usize", &expected_ty);
- rust_assert (ok);
context->insert_type (mapping, expected_ty);
+ capacity_type = expected_ty;
}
break;
}
- infered = new TyTy::ArrayType (expr.get_mappings ().get_hirid (),
- expr.get_locus (), *capacity_expr,
- TyTy::TyVar (element_type->get_ref ()));
+ rust_assert (capacity_expr);
+ rust_assert (capacity_type);
+ auto ctx = Compile::Context::get ();
+ tree capacity_value
+ = Compile::HIRCompileBase::query_compile_const_expr (ctx, capacity_type,
+ *capacity_expr);
+ HirId size_id = capacity_expr->get_mappings ().get_hirid ();
+ TyTy::ConstType *const_type
+ = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, "", expected_ty,
+ capacity_value, {}, capacity_expr->get_locus (),
+ size_id, size_id);
+ infered
+ = new TyTy::ArrayType (expr.get_mappings ().get_hirid (), expr.get_locus (),
+ const_type, TyTy::TyVar (element_type->get_ref ()));
}
// empty struct
@@ -1408,26 +1489,11 @@ TypeCheckExpr::visit (HIR::MethodCallExpr &expr)
// store the expected fntype
context->insert_type (expr.get_method_name ().get_mappings (), lookup);
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> (
- Resolver2_0::ImmutableNameResolutionContext::get ().resolver ());
+ auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> (
+ Resolver2_0::ImmutableNameResolutionContext::get ().resolver ());
- nr_ctx.map_usage (Resolver2_0::Usage (expr.get_mappings ().get_nodeid ()),
- Resolver2_0::Definition (resolved_node_id));
- }
- // set up the resolved name on the path
- else if (resolver->get_name_scope ().decl_was_declared_here (
- resolved_node_id))
- {
- resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (),
- resolved_node_id);
- }
- else
- {
- resolver->insert_resolved_misc (expr.get_mappings ().get_nodeid (),
- resolved_node_id);
- }
+ nr_ctx.map_usage (Resolver2_0::Usage (expr.get_mappings ().get_nodeid ()),
+ Resolver2_0::Definition (resolved_node_id));
// return the result of the function back
infered = function_ret_tyty;
@@ -1702,16 +1768,22 @@ TypeCheckExpr::visit (HIR::MatchExpr &expr)
void
TypeCheckExpr::visit (HIR::ClosureExpr &expr)
{
- TypeCheckContextItem current_context = context->peek_context ();
- TyTy::FnType *current_context_fndecl = current_context.get_context_type ();
-
+ std::vector<TyTy::SubstitutionParamMapping> subst_refs;
HirId ref = expr.get_mappings ().get_hirid ();
DefId id = expr.get_mappings ().get_defid ();
- RustIdent ident{current_context_fndecl->get_ident ().path, expr.get_locus ()};
+ RustIdent ident{CanonicalPath::create_empty (), expr.get_locus ()};
- // get from parent context
- std::vector<TyTy::SubstitutionParamMapping> subst_refs
- = current_context_fndecl->clone_substs ();
+ if (context->have_function_context ())
+ {
+ TypeCheckContextItem current_context = context->peek_context ();
+ TyTy::FnType *current_context_fndecl
+ = current_context.get_context_type ();
+
+ ident = RustIdent{current_context_fndecl->get_ident ().path,
+ expr.get_locus ()};
+
+ subst_refs = current_context_fndecl->clone_substs ();
+ }
std::vector<TyTy::TyVar> parameter_types;
for (auto &p : expr.get_params ())
@@ -1763,19 +1835,12 @@ TypeCheckExpr::visit (HIR::ClosureExpr &expr)
// Resolve closure captures
std::set<NodeId> captures;
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> (
- Resolver2_0::ImmutableNameResolutionContext::get ().resolver ());
+ auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> (
+ Resolver2_0::ImmutableNameResolutionContext::get ().resolver ());
- if (auto opt_cap = nr_ctx.mappings.lookup_captures (closure_node_id))
- for (auto cap : opt_cap.value ())
- captures.insert (cap);
- }
- else
- {
- captures = resolver->get_captures (closure_node_id);
- }
+ if (auto opt_cap = nr_ctx.mappings.lookup_captures (closure_node_id))
+ for (auto cap : opt_cap.value ())
+ captures.insert (cap);
infered = new TyTy::ClosureType (ref, id, ident, closure_args, result_type,
subst_refs, captures);
@@ -1826,7 +1891,7 @@ TypeCheckExpr::visit (HIR::ClosureExpr &expr)
args.get_type_args ().push_back (std::unique_ptr<HIR::Type> (implicit_tuple));
// apply the arguments
- predicate.apply_generic_arguments (&args, false);
+ predicate.apply_generic_arguments (&args, false, false);
// finally inherit the trait bound
infered->inherit_bounds ({predicate});
@@ -1845,7 +1910,16 @@ TypeCheckExpr::resolve_operator_overload (
// probe for the lang-item
if (!lang_item_defined)
return false;
+
DefId &respective_lang_item_id = lang_item_defined.value ();
+ auto def_lookup = mappings.lookup_defid (respective_lang_item_id);
+ rust_assert (def_lookup.has_value ());
+
+ HIR::Item *def_item = def_lookup.value ();
+ rust_assert (def_item->get_item_kind () == HIR::Item::ItemKind::Trait);
+ HIR::Trait &trait = *static_cast<HIR::Trait *> (def_item);
+ TraitReference *defid_trait_reference = TraitResolver::Resolve (trait);
+ rust_assert (!defid_trait_reference->is_error ());
// we might be in a static or const context and unknown is fine
TypeCheckContextItem current_context = TypeCheckContextItem::get_error ();
@@ -1889,15 +1963,49 @@ TypeCheckExpr::resolve_operator_overload (
if (selected_candidates.size () > 1)
{
- // mutliple candidates
- rich_location r (line_table, expr.get_locus ());
- for (auto &c : resolved_candidates)
- r.add_range (c.candidate.locus);
+ auto infer
+ = TyTy::TyVar::get_implicit_infer_var (expr.get_locus ()).get_tyty ();
+ auto trait_subst = defid_trait_reference->get_trait_substs ();
+ rust_assert (trait_subst.size () > 0);
- rust_error_at (
- r, "multiple candidates found for possible operator overload");
+ TyTy::TypeBoundPredicate pred (respective_lang_item_id, trait_subst,
+ BoundPolarity::RegularBound,
+ expr.get_locus ());
- return false;
+ std::vector<TyTy::SubstitutionArg> mappings;
+ auto &self_param_mapping = trait_subst[0];
+ mappings.push_back (TyTy::SubstitutionArg (&self_param_mapping, lhs));
+
+ if (rhs != nullptr)
+ {
+ rust_assert (trait_subst.size () == 2);
+ auto &rhs_param_mapping = trait_subst[1];
+ mappings.push_back (TyTy::SubstitutionArg (&rhs_param_mapping, lhs));
+ }
+
+ std::map<std::string, TyTy::BaseType *> binding_args;
+ binding_args["Output"] = infer;
+
+ TyTy::SubstitutionArgumentMappings arg_mappings (mappings, binding_args,
+ TyTy::RegionParamList (
+ trait_subst.size ()),
+ expr.get_locus ());
+ pred.apply_argument_mappings (arg_mappings, false);
+
+ infer->inherit_bounds ({pred});
+ DeferredOpOverload defer (expr.get_mappings ().get_hirid (),
+ lang_item_type, specified_segment, pred, expr);
+ context->insert_deferred_operator_overload (std::move (defer));
+
+ if (rhs != nullptr)
+ lhs = unify_site (expr.get_mappings ().get_hirid (),
+ TyTy::TyWithLocation (lhs),
+ TyTy::TyWithLocation (rhs), expr.get_locus ());
+
+ infered = unify_site (expr.get_mappings ().get_hirid (),
+ TyTy::TyWithLocation (lhs),
+ TyTy::TyWithLocation (infer), expr.get_locus ());
+ return true;
}
// Get the adjusted self
@@ -2040,19 +2148,11 @@ TypeCheckExpr::resolve_operator_overload (
context->insert_operator_overload (expr.get_mappings ().get_hirid (), type);
// set up the resolved name on the path
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> (
- Resolver2_0::ImmutableNameResolutionContext::get ().resolver ());
+ auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> (
+ Resolver2_0::ImmutableNameResolutionContext::get ().resolver ());
- nr_ctx.map_usage (Resolver2_0::Usage (expr.get_mappings ().get_nodeid ()),
- Resolver2_0::Definition (resolved_node_id));
- }
- else
- {
- resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (),
- resolved_node_id);
- }
+ nr_ctx.map_usage (Resolver2_0::Usage (expr.get_mappings ().get_nodeid ()),
+ Resolver2_0::Definition (resolved_node_id));
// return the result of the function back
infered = function_ret_tyty;
@@ -2062,16 +2162,13 @@ TypeCheckExpr::resolve_operator_overload (
HIR::PathIdentSegment
TypeCheckExpr::resolve_possible_fn_trait_call_method_name (
- TyTy::BaseType &receiver, TyTy::TypeBoundPredicate *associated_predicate)
+ const TyTy::BaseType &receiver,
+ TyTy::TypeBoundPredicate *associated_predicate)
{
- // Question
- // do we need to probe possible bounds here? I think not, i think when we
- // support Fn traits they are explicitly specified
-
// FIXME
// the logic to map the FnTrait to their respective call trait-item is
// duplicated over in the backend/rust-compile-expr.cc
- for (auto &bound : receiver.get_specified_bounds ())
+ for (const auto &bound : receiver.get_specified_bounds ())
{
bool found_fn = bound.get_name ().compare ("Fn") == 0;
bool found_fn_mut = bound.get_name ().compare ("FnMut") == 0;
@@ -2094,6 +2191,34 @@ TypeCheckExpr::resolve_possible_fn_trait_call_method_name (
}
}
+ if (receiver.is<TyTy::ReferenceType> ())
+ {
+ const auto &ref = static_cast<const TyTy::ReferenceType &> (receiver);
+ const auto &underlying = *ref.get_base ();
+ for (const auto &bound : underlying.get_specified_bounds ())
+ {
+ bool found_fn = bound.get_name ().compare ("Fn") == 0;
+ bool found_fn_mut = bound.get_name ().compare ("FnMut") == 0;
+ bool found_fn_once = bound.get_name ().compare ("FnOnce") == 0;
+
+ if (found_fn)
+ {
+ *associated_predicate = bound;
+ return HIR::PathIdentSegment ("call");
+ }
+ else if (found_fn_mut)
+ {
+ *associated_predicate = bound;
+ return HIR::PathIdentSegment ("call_mut");
+ }
+ else if (found_fn_once)
+ {
+ *associated_predicate = bound;
+ return HIR::PathIdentSegment ("call_once");
+ }
+ }
+ }
+
// nothing
*associated_predicate = TyTy::TypeBoundPredicate::error ();
return HIR::PathIdentSegment ("");
@@ -2220,32 +2345,15 @@ TypeCheckExpr::resolve_fn_trait_call (HIR::CallExpr &expr,
context->insert_operator_overload (expr.get_mappings ().get_hirid (), fn);
// set up the resolved name on the path
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> (
- Resolver2_0::ImmutableNameResolutionContext::get ().resolver ());
+ auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> (
+ Resolver2_0::ImmutableNameResolutionContext::get ().resolver ());
- auto existing = nr_ctx.lookup (expr.get_mappings ().get_nodeid ());
- if (existing)
- rust_assert (*existing == resolved_node_id);
- else
- nr_ctx.map_usage (Resolver2_0::Usage (
- expr.get_mappings ().get_nodeid ()),
- Resolver2_0::Definition (resolved_node_id));
- }
+ auto existing = nr_ctx.lookup (expr.get_mappings ().get_nodeid ());
+ if (existing)
+ rust_assert (*existing == resolved_node_id);
else
- {
- NodeId existing = UNKNOWN_NODEID;
- bool ok
- = resolver->lookup_resolved_name (expr.get_mappings ().get_nodeid (),
- &existing);
-
- if (ok)
- rust_assert (existing == resolved_node_id);
- else
- resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (),
- resolved_node_id);
- }
+ nr_ctx.map_usage (Resolver2_0::Usage (expr.get_mappings ().get_nodeid ()),
+ Resolver2_0::Definition (resolved_node_id));
// return the result of the function back
*result = function_ret_tyty;
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index 79121b3..0343922 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -19,6 +19,7 @@
#ifndef RUST_HIR_TYPE_CHECK_EXPR
#define RUST_HIR_TYPE_CHECK_EXPR
+#include "rust-hir-expr.h"
#include "rust-hir-type-check-base.h"
#include "rust-hir-visitor.h"
#include "rust-tyty.h"
@@ -31,6 +32,11 @@ class TypeCheckExpr : private TypeCheckBase, private HIR::HIRExpressionVisitor
public:
static TyTy::BaseType *Resolve (HIR::Expr &expr);
+ static TyTy::BaseType *
+ ResolveOpOverload (LangItem::Kind lang_item_type, HIR::OperatorExprMeta expr,
+ TyTy::BaseType *lhs, TyTy::BaseType *rhs,
+ HIR::PathIdentSegment specified_segment);
+
void visit (HIR::TupleIndexExpr &expr) override;
void visit (HIR::TupleExpr &expr) override;
void visit (HIR::ReturnExpr &expr) override;
@@ -46,6 +52,8 @@ public:
void visit (HIR::IfExpr &expr) override;
void visit (HIR::IfExprConseqElse &expr) override;
void visit (HIR::BlockExpr &expr) override;
+ void visit (HIR::AnonConst &expr) override;
+ void visit (HIR::ConstBlock &expr) override;
void visit (HIR::UnsafeBlockExpr &expr) override;
void visit (HIR::ArrayIndexExpr &expr) override;
void visit (HIR::ArrayExpr &expr) override;
@@ -71,6 +79,7 @@ public:
void visit (HIR::ClosureExpr &expr) override;
void visit (HIR::InlineAsm &expr) override;
void visit (HIR::LlvmInlineAsm &expr) override;
+ void visit (HIR::OffsetOf &expr) override;
// TODO
void visit (HIR::ErrorPropagationExpr &) override {}
@@ -107,7 +116,8 @@ protected:
TyTy::BaseType **result);
HIR::PathIdentSegment resolve_possible_fn_trait_call_method_name (
- TyTy::BaseType &receiver, TyTy::TypeBoundPredicate *associated_predicate);
+ const TyTy::BaseType &receiver,
+ TyTy::TypeBoundPredicate *associated_predicate);
private:
TypeCheckExpr ();
diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
index bc7f6dc..c8544a1 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
@@ -28,9 +28,6 @@
#include "rust-tyty.h"
#include "rust-immutable-name-resolution-context.h"
-// for flag_name_resolution_2_0
-#include "options.h"
-
namespace Rust {
namespace Resolver {
@@ -73,7 +70,9 @@ TypeCheckTopLevelExternItem::visit (HIR::ExternalFunctionItem &function)
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (function.has_generics ())
{
- resolve_generic_params (function.get_generic_params (), substitutions,
+ resolve_generic_params (HIR::Item::ItemKind::Function,
+ function.get_locus (),
+ function.get_generic_params (), substitutions,
true /*is_foreign*/, parent.get_abi ());
}
@@ -203,7 +202,9 @@ TypeCheckImplItem::visit (HIR::Function &function)
auto binder_pin = context->push_lifetime_binder ();
if (function.has_generics ())
- resolve_generic_params (function.get_generic_params (), substitutions);
+ resolve_generic_params (HIR::Item::ItemKind::Function,
+ function.get_locus (),
+ function.get_generic_params (), substitutions);
TyTy::RegionConstraints region_constraints;
for (auto &where_clause_item : function.get_where_clause ().get_items ())
@@ -266,7 +267,8 @@ TypeCheckImplItem::visit (HIR::Function &function)
self_type = self->clone ();
break;
- case HIR::SelfParam::IMM_REF: {
+ case HIR::SelfParam::IMM_REF:
+ {
tl::optional<TyTy::Region> region;
if (self_param.has_lifetime ())
{
@@ -290,7 +292,8 @@ TypeCheckImplItem::visit (HIR::Function &function)
}
break;
- case HIR::SelfParam::MUT_REF: {
+ case HIR::SelfParam::MUT_REF:
+ {
tl::optional<TyTy::Region> region;
if (self_param.has_lifetime ())
{
@@ -336,25 +339,13 @@ TypeCheckImplItem::visit (HIR::Function &function)
TyTy::FnParam (param.get_param_name ().clone_pattern (), param_tyty));
}
- tl::optional<CanonicalPath> canonical_path;
-
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- canonical_path = nr_ctx.values.to_canonical_path (
- function.get_mappings ().get_nodeid ());
- }
- else
- {
- canonical_path = mappings.lookup_canonical_path (
- function.get_mappings ().get_nodeid ());
- }
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- rust_assert (canonical_path.has_value ());
+ CanonicalPath canonical_path
+ = nr_ctx.to_canonical_path (function.get_mappings ().get_nodeid ());
- RustIdent ident{*canonical_path, function.get_locus ()};
+ RustIdent ident{canonical_path, function.get_locus ()};
auto fnType = new TyTy::FnType (
function.get_mappings ().get_hirid (),
function.get_mappings ().get_defid (),
@@ -410,7 +401,8 @@ TypeCheckImplItem::visit (HIR::TypeAlias &alias)
auto binder_pin = context->push_lifetime_binder ();
if (alias.has_generics ())
- resolve_generic_params (alias.get_generic_params (), substitutions);
+ resolve_generic_params (HIR::Item::ItemKind::TypeAlias, alias.get_locus (),
+ alias.get_generic_params (), substitutions);
TyTy::BaseType *actual_type
= TypeCheckType::Resolve (alias.get_type_aliased ());
@@ -494,10 +486,9 @@ TypeCheckImplItemWithTrait::visit (HIR::ConstantItem &constant)
rich_location r (line_table, constant.get_locus ());
r.add_range (resolved_trait_item.get_locus ());
- rust_error_at (
- r, "constant %qs has an incompatible type for trait %qs",
- constant.get_identifier ().as_string ().c_str (),
- trait_reference.get_name ().c_str ());
+ rust_error_at (r, "constant %qs has an incompatible type for trait %qs",
+ constant.get_identifier ().as_string ().c_str (),
+ trait_reference.get_name ().c_str ());
}
}
@@ -545,10 +536,9 @@ TypeCheckImplItemWithTrait::visit (HIR::TypeAlias &type)
rich_location r (line_table, type.get_locus ());
r.add_range (resolved_trait_item.get_locus ());
- rust_error_at (
- r, "type alias %qs has an incompatible type for trait %qs",
- type.get_new_type_name ().as_string ().c_str (),
- trait_reference.get_name ().c_str ());
+ rust_error_at (r, "type alias %qs has an incompatible type for trait %qs",
+ type.get_new_type_name ().as_string ().c_str (),
+ trait_reference.get_name ().c_str ());
}
// its actually a projection, since we need a way to actually bind the
diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc
index aaa04af..3ba607b 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-item.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc
@@ -20,6 +20,7 @@
#include "optional.h"
#include "rust-canonical-path.h"
#include "rust-diagnostics.h"
+#include "rust-hir-item.h"
#include "rust-hir-type-check-enumitem.h"
#include "rust-hir-type-check-implitem.h"
#include "rust-hir-type-check-type.h"
@@ -33,9 +34,6 @@
#include "rust-type-util.h"
#include "rust-tyty-variance-analysis.h"
-// for flag_name_resolution_2_0
-#include "options.h"
-
namespace Rust {
namespace Resolver {
@@ -121,8 +119,8 @@ TypeCheckItem::ResolveImplBlockSelfWithInference (
}
else
{
- TyTy::ParamType *param = p.get_param_ty ();
- TyTy::BaseType *resolved = param->destructure ();
+ auto param = p.get_param_ty ();
+ auto resolved = param->destructure ();
args.push_back (TyTy::SubstitutionArg (&p, resolved));
}
}
@@ -170,7 +168,9 @@ TypeCheckItem::visit (HIR::TupleStruct &struct_decl)
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (struct_decl.has_generics ())
- resolve_generic_params (struct_decl.get_generic_params (), substitutions);
+ resolve_generic_params (HIR::Item::ItemKind::Struct,
+ struct_decl.get_locus (),
+ struct_decl.get_generic_params (), substitutions);
TyTy::RegionConstraints region_constraints;
for (auto &where_clause_item : struct_decl.get_where_clause ().get_items ())
@@ -195,25 +195,11 @@ TypeCheckItem::visit (HIR::TupleStruct &struct_decl)
// get the path
- auto path = CanonicalPath::create_empty ();
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- // FIXME: HACK: ARTHUR: Disgusting
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- path = nr_ctx.values
- .to_canonical_path (struct_decl.get_mappings ().get_nodeid ())
- .value ();
- }
- else
- {
- path
- = mappings
- .lookup_canonical_path (struct_decl.get_mappings ().get_nodeid ())
- .value ();
- }
+ CanonicalPath path
+ = nr_ctx.to_canonical_path (struct_decl.get_mappings ().get_nodeid ());
RustIdent ident{path, struct_decl.get_locus ()};
@@ -255,7 +241,9 @@ TypeCheckItem::visit (HIR::StructStruct &struct_decl)
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (struct_decl.has_generics ())
- resolve_generic_params (struct_decl.get_generic_params (), substitutions);
+ resolve_generic_params (HIR::Item::ItemKind::Struct,
+ struct_decl.get_locus (),
+ struct_decl.get_generic_params (), substitutions);
TyTy::RegionConstraints region_constraints;
for (auto &where_clause_item : struct_decl.get_where_clause ().get_items ())
@@ -276,27 +264,11 @@ TypeCheckItem::visit (HIR::StructStruct &struct_decl)
context->insert_type (field.get_mappings (), ty_field->get_field_type ());
}
- auto path = CanonicalPath::create_empty ();
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- // FIXME: HACK: ARTHUR: Disgusting
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- auto canonical_path = nr_ctx.types.to_canonical_path (
- struct_decl.get_mappings ().get_nodeid ());
-
- if (!canonical_path.has_value ())
- rust_unreachable ();
- path = canonical_path.value ();
- }
- else
- {
- path
- = mappings
- .lookup_canonical_path (struct_decl.get_mappings ().get_nodeid ())
- .value ();
- }
+ CanonicalPath path
+ = nr_ctx.to_canonical_path (struct_decl.get_mappings ().get_nodeid ());
RustIdent ident{path, struct_decl.get_locus ()};
@@ -337,7 +309,8 @@ TypeCheckItem::visit (HIR::Enum &enum_decl)
auto lifetime_pin = context->push_clean_lifetime_resolver ();
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (enum_decl.has_generics ())
- resolve_generic_params (enum_decl.get_generic_params (), substitutions);
+ resolve_generic_params (HIR::Item::ItemKind::Enum, enum_decl.get_locus (),
+ enum_decl.get_generic_params (), substitutions);
// Process #[repr(X)] attribute, if any
const AST::AttrVec &attrs = enum_decl.get_outer_attrs ();
@@ -367,26 +340,14 @@ TypeCheckItem::visit (HIR::Enum &enum_decl)
}
}
- // get the path
- tl::optional<CanonicalPath> canonical_path;
-
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- canonical_path = nr_ctx.types.to_canonical_path (
- enum_decl.get_mappings ().get_nodeid ());
- }
- else
- {
- canonical_path = mappings.lookup_canonical_path (
- enum_decl.get_mappings ().get_nodeid ());
- }
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- rust_assert (canonical_path.has_value ());
+ // get the path
+ CanonicalPath canonical_path
+ = nr_ctx.to_canonical_path (enum_decl.get_mappings ().get_nodeid ());
- RustIdent ident{*canonical_path, enum_decl.get_locus ()};
+ RustIdent ident{canonical_path, enum_decl.get_locus ()};
// multi variant ADT
auto *type
@@ -409,7 +370,8 @@ TypeCheckItem::visit (HIR::Union &union_decl)
auto lifetime_pin = context->push_clean_lifetime_resolver ();
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (union_decl.has_generics ())
- resolve_generic_params (union_decl.get_generic_params (), substitutions);
+ resolve_generic_params (HIR::Item::ItemKind::Union, union_decl.get_locus (),
+ union_decl.get_generic_params (), substitutions);
TyTy::RegionConstraints region_constraints;
for (auto &where_clause_item : union_decl.get_where_clause ().get_items ())
@@ -431,26 +393,14 @@ TypeCheckItem::visit (HIR::Union &union_decl)
ty_variant->get_field_type ());
}
- // get the path
- tl::optional<CanonicalPath> canonical_path;
-
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- canonical_path = nr_ctx.types.to_canonical_path (
- union_decl.get_mappings ().get_nodeid ());
- }
- else
- {
- canonical_path = mappings.lookup_canonical_path (
- union_decl.get_mappings ().get_nodeid ());
- }
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- rust_assert (canonical_path.has_value ());
+ // get the path
+ CanonicalPath canonical_path
+ = nr_ctx.to_canonical_path (union_decl.get_mappings ().get_nodeid ());
- RustIdent ident{*canonical_path, union_decl.get_locus ()};
+ RustIdent ident{canonical_path, union_decl.get_locus ()};
// there is only a single variant
std::vector<TyTy::VariantDef *> variants;
@@ -569,8 +519,9 @@ TypeCheckItem::visit (HIR::Function &function)
auto lifetime_pin = context->push_clean_lifetime_resolver ();
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (function.has_generics ())
- resolve_generic_params (function.get_generic_params (),
- substitutions); // TODO resolve constraints
+ resolve_generic_params (HIR::Item::ItemKind::Function,
+ function.get_locus (),
+ function.get_generic_params (), substitutions);
TyTy::RegionConstraints region_constraints;
for (auto &where_clause_item : function.get_where_clause ().get_items ())
@@ -607,24 +558,11 @@ TypeCheckItem::visit (HIR::Function &function)
TyTy::FnParam (param.get_param_name ().clone_pattern (), param_tyty));
}
- auto path = CanonicalPath::create_empty ();
-
- // FIXME: HACK: ARTHUR: Disgusting
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- auto canonical_path = nr_ctx.values.to_canonical_path (
- function.get_mappings ().get_nodeid ());
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- path = canonical_path.value ();
- }
- else
- {
- path = mappings
- .lookup_canonical_path (function.get_mappings ().get_nodeid ())
- .value ();
- }
+ CanonicalPath path
+ = nr_ctx.to_canonical_path (function.get_mappings ().get_nodeid ());
RustIdent ident{path, function.get_locus ()};
@@ -745,13 +683,33 @@ TypeCheckItem::visit (HIR::ExternBlock &extern_block)
}
}
+void
+TypeCheckItem::visit (HIR::ExternCrate &extern_crate)
+{
+ if (extern_crate.references_self ())
+ return;
+
+ auto &mappings = Analysis::Mappings::get ();
+ CrateNum num
+ = mappings.lookup_crate_name (extern_crate.get_referenced_crate ())
+ .value ();
+ HIR::Crate &crate = mappings.get_hir_crate (num);
+
+ CrateNum saved_crate_num = mappings.get_current_crate ();
+ mappings.set_current_crate (num);
+ for (auto &item : crate.get_items ())
+ TypeCheckItem::Resolve (*item);
+ mappings.set_current_crate (saved_crate_num);
+}
+
std::pair<std::vector<TyTy::SubstitutionParamMapping>, TyTy::RegionConstraints>
TypeCheckItem::resolve_impl_block_substitutions (HIR::ImplBlock &impl_block,
bool &failure_flag)
{
std::vector<TyTy::SubstitutionParamMapping> substitutions;
if (impl_block.has_generics ())
- resolve_generic_params (impl_block.get_generic_params (), substitutions);
+ resolve_generic_params (HIR::Item::ItemKind::Impl, impl_block.get_locus (),
+ impl_block.get_generic_params (), substitutions);
TyTy::RegionConstraints region_constraints;
for (auto &where_clause_item : impl_block.get_where_clause ().get_items ())
diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h
index 56832e7..414694b 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-item.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-item.h
@@ -51,9 +51,9 @@ public:
void visit (HIR::ImplBlock &impl_block) override;
void visit (HIR::ExternBlock &extern_block) override;
void visit (HIR::Trait &trait_block) override;
+ void visit (HIR::ExternCrate &extern_crate) override;
// nothing to do
- void visit (HIR::ExternCrate &) override {}
void visit (HIR::UseDeclaration &) override {}
protected:
diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc
index 5662da5..cc5c412 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-path.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc
@@ -157,20 +157,11 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr)
bool fully_resolved = expr.get_segments ().size () <= 1;
if (fully_resolved)
{
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> (
- Resolver2_0::ImmutableNameResolutionContext::get ().resolver ());
+ auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> (
+ Resolver2_0::ImmutableNameResolutionContext::get ().resolver ());
- nr_ctx.map_usage (Resolver2_0::Usage (
- expr.get_mappings ().get_nodeid ()),
- Resolver2_0::Definition (root_resolved_node_id));
- }
- else
- {
- resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (),
- root_resolved_node_id);
- }
+ nr_ctx.map_usage (Resolver2_0::Usage (expr.get_mappings ().get_nodeid ()),
+ Resolver2_0::Definition (root_resolved_node_id));
return;
}
@@ -264,24 +255,16 @@ TypeCheckExpr::resolve_root_path (HIR::PathInExpression &expr, size_t *offset,
bool is_root = *offset == 0;
NodeId ast_node_id = seg.get_mappings ().get_nodeid ();
- // then lookup the reference_node_id
- NodeId ref_node_id = UNKNOWN_NODEID;
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- if (flag_name_resolution_2_0)
+ // lookup the reference_node_id
+ NodeId ref_node_id;
+ if (auto res = nr_ctx.lookup (ast_node_id))
{
- 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;
- });
+ ref_node_id = *res;
}
- else if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id))
- resolver->lookup_resolved_type (ast_node_id, &ref_node_id);
-
- // ref_node_id is the NodeId that the segments refers to.
- if (ref_node_id == UNKNOWN_NODEID)
+ else
{
if (root_tyty != nullptr && *offset > 0)
{
@@ -561,33 +544,12 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id,
}
rust_assert (resolved_node_id != UNKNOWN_NODEID);
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> (
- Resolver2_0::ImmutableNameResolutionContext::get ().resolver ());
- nr_ctx.map_usage (Resolver2_0::Usage (expr_mappings.get_nodeid ()),
- Resolver2_0::Definition (resolved_node_id));
- }
- // name scope first
- else if (resolver->get_name_scope ().decl_was_declared_here (
- resolved_node_id))
- {
- resolver->insert_resolved_name (expr_mappings.get_nodeid (),
- resolved_node_id);
- }
- // check the type scope
- else if (resolver->get_type_scope ().decl_was_declared_here (
- resolved_node_id))
- {
- resolver->insert_resolved_type (expr_mappings.get_nodeid (),
- resolved_node_id);
- }
- else
- {
- resolver->insert_resolved_misc (expr_mappings.get_nodeid (),
- resolved_node_id);
- }
+ auto &nr_ctx = const_cast<Resolver2_0::NameResolutionContext &> (
+ Resolver2_0::ImmutableNameResolutionContext::get ().resolver ());
+
+ nr_ctx.map_usage (Resolver2_0::Usage (expr_mappings.get_nodeid ()),
+ Resolver2_0::Definition (resolved_node_id));
infered = tyseg;
}
diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
index bd13f7a..be926fc 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
@@ -22,9 +22,6 @@
#include "rust-type-util.h"
#include "rust-immutable-name-resolution-context.h"
-// for flag_name_resolution_2_0
-#include "options.h"
-
namespace Rust {
namespace Resolver {
@@ -54,23 +51,13 @@ TypeCheckPattern::visit (HIR::PathInExpression &pattern)
NodeId ref_node_id = UNKNOWN_NODEID;
bool maybe_item = false;
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- if (auto id = nr_ctx.lookup (pattern.get_mappings ().get_nodeid ()))
- {
- ref_node_id = *id;
- maybe_item = true;
- }
- }
- else
+ if (auto id = nr_ctx.lookup (pattern.get_mappings ().get_nodeid ()))
{
- maybe_item |= resolver->lookup_resolved_name (
- pattern.get_mappings ().get_nodeid (), &ref_node_id);
- maybe_item |= resolver->lookup_resolved_type (
- pattern.get_mappings ().get_nodeid (), &ref_node_id);
+ ref_node_id = *id;
+ maybe_item = true;
}
bool path_is_const_item = false;
@@ -213,13 +200,15 @@ TypeCheckPattern::visit (HIR::TupleStructPattern &pattern)
auto &items = pattern.get_items ();
switch (items.get_item_type ())
{
- case HIR::TupleStructItems::RANGED: {
+ case HIR::TupleStructItems::RANGED:
+ {
// TODO
rust_unreachable ();
}
break;
- case HIR::TupleStructItems::MULTIPLE: {
+ case HIR::TupleStructItems::MULTIPLE:
+ {
HIR::TupleStructItemsNoRange &items_no_range
= static_cast<HIR::TupleStructItemsNoRange &> (items);
@@ -333,13 +322,15 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern)
{
switch (field->get_item_type ())
{
- case HIR::StructPatternField::ItemType::TUPLE_PAT: {
+ case HIR::StructPatternField::ItemType::TUPLE_PAT:
+ {
// TODO
rust_unreachable ();
}
break;
- case HIR::StructPatternField::ItemType::IDENT_PAT: {
+ case HIR::StructPatternField::ItemType::IDENT_PAT:
+ {
HIR::StructPatternFieldIdentPat &ident
= static_cast<HIR::StructPatternFieldIdentPat &> (*field);
@@ -358,7 +349,8 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern)
}
break;
- case HIR::StructPatternField::ItemType::IDENT: {
+ case HIR::StructPatternField::ItemType::IDENT:
+ {
HIR::StructPatternFieldIdent &ident
= static_cast<HIR::StructPatternFieldIdent &> (*field);
@@ -397,7 +389,8 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern)
case HIR::StructPatternField::ItemType::IDENT:
case HIR::StructPatternField::ItemType::IDENT_PAT:
break;
- default: {
+ default:
+ {
auto first_elem
= struct_pattern_elems.get_struct_pattern_fields ()
.at (0)
@@ -457,25 +450,27 @@ void
TypeCheckPattern::visit (HIR::TuplePattern &pattern)
{
std::unique_ptr<HIR::TuplePatternItems> items;
+
+ // Check whether parent is tuple
+ auto resolved_parent = parent->destructure ();
+ if (resolved_parent->get_kind () != TyTy::TUPLE)
+ {
+ rust_error_at (pattern.get_locus (), "expected %s, found tuple",
+ parent->as_string ().c_str ());
+ return;
+ }
+ TyTy::TupleType &par = *static_cast<TyTy::TupleType *> (resolved_parent);
+
switch (pattern.get_items ().get_item_type ())
{
- case HIR::TuplePatternItems::ItemType::MULTIPLE: {
+ case HIR::TuplePatternItems::ItemType::MULTIPLE:
+ {
auto &ref = static_cast<HIR::TuplePatternItemsMultiple &> (
pattern.get_items ());
- auto resolved_parent = parent->destructure ();
- if (resolved_parent->get_kind () != TyTy::TUPLE)
- {
- rust_error_at (pattern.get_locus (), "expected %s, found tuple",
- parent->as_string ().c_str ());
- break;
- }
-
const auto &patterns = ref.get_patterns ();
size_t nitems_to_resolve = patterns.size ();
- TyTy::TupleType &par
- = *static_cast<TyTy::TupleType *> (resolved_parent);
if (patterns.size () != par.get_fields ().size ())
{
emit_pattern_size_error (pattern, par.get_fields ().size (),
@@ -498,12 +493,55 @@ TypeCheckPattern::visit (HIR::TuplePattern &pattern)
}
break;
- case HIR::TuplePatternItems::ItemType::RANGED: {
- // HIR::TuplePatternItemsRanged &ref
- // = *static_cast<HIR::TuplePatternItemsRanged *> (
- // pattern.get_items ().get ());
- // TODO
- rust_unreachable ();
+ case HIR::TuplePatternItems::ItemType::RANGED:
+ {
+ HIR::TuplePatternItemsRanged &ref
+ = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ());
+
+ const auto &lower = ref.get_lower_patterns ();
+ const auto &upper = ref.get_upper_patterns ();
+ size_t min_size_required = lower.size () + upper.size ();
+
+ // Ensure that size of lower and upper patterns <= parent size
+ if (min_size_required > par.get_fields ().size ())
+ {
+ emit_pattern_size_error (pattern, par.get_fields ().size (),
+ min_size_required);
+ // TODO attempt to continue to do typechecking even after wrong size
+ break;
+ }
+
+ // Resolve lower patterns
+ std::vector<TyTy::TyVar> pattern_elems;
+ for (size_t i = 0; i < lower.size (); i++)
+ {
+ auto &p = lower[i];
+ TyTy::BaseType *par_type = par.get_field (i);
+
+ TyTy::BaseType *elem = TypeCheckPattern::Resolve (*p, par_type);
+ pattern_elems.push_back (TyTy::TyVar (elem->get_ref ()));
+ }
+
+ // Pad pattern_elems until needing to resolve upper patterns
+ size_t rest_end = par.get_fields ().size () - upper.size ();
+ for (size_t i = lower.size (); i < rest_end; i++)
+ {
+ TyTy::BaseType *par_type = par.get_field (i);
+ pattern_elems.push_back (TyTy::TyVar (par_type->get_ref ()));
+ }
+
+ // Resolve upper patterns
+ for (size_t i = 0; i < upper.size (); i++)
+ {
+ auto &p = upper[i];
+ TyTy::BaseType *par_type = par.get_field (rest_end + i);
+
+ TyTy::BaseType *elem = TypeCheckPattern::Resolve (*p, par_type);
+ pattern_elems.push_back (TyTy::TyVar (elem->get_ref ()));
+ }
+
+ infered = new TyTy::TupleType (pattern.get_mappings ().get_hirid (),
+ pattern.get_locus (), pattern_elems);
}
break;
}
@@ -512,8 +550,18 @@ TypeCheckPattern::visit (HIR::TuplePattern &pattern)
void
TypeCheckPattern::visit (HIR::LiteralPattern &pattern)
{
- infered = resolve_literal (pattern.get_mappings (), pattern.get_literal (),
- pattern.get_locus ());
+ TyTy::BaseType *resolved
+ = resolve_literal (pattern.get_mappings (), pattern.get_literal (),
+ pattern.get_locus ());
+ if (resolved->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ infered = resolved;
+ return;
+ }
+
+ infered = unify_site (pattern.get_mappings ().get_hirid (),
+ TyTy::TyWithLocation (parent),
+ TyTy::TyWithLocation (resolved), pattern.get_locus ());
}
void
@@ -538,6 +586,11 @@ TypeCheckPattern::visit (HIR::RangePattern &pattern)
void
TypeCheckPattern::visit (HIR::IdentifierPattern &pattern)
{
+ if (pattern.has_subpattern ())
+ {
+ TypeCheckPattern::Resolve (pattern.get_subpattern (), parent);
+ }
+
if (!pattern.get_is_ref ())
{
infered = parent;
@@ -580,8 +633,72 @@ TypeCheckPattern::visit (HIR::ReferencePattern &pattern)
void
TypeCheckPattern::visit (HIR::SlicePattern &pattern)
{
- rust_sorry_at (pattern.get_locus (),
- "type checking qualified path patterns not supported");
+ auto resolved_parent = parent->destructure ();
+ TyTy::BaseType *parent_element_ty = nullptr;
+ switch (resolved_parent->get_kind ())
+ {
+ case TyTy::ARRAY:
+ {
+ auto &array_ty_ty = static_cast<TyTy::ArrayType &> (*parent);
+ parent_element_ty = array_ty_ty.get_element_type ();
+ auto capacity = array_ty_ty.get_capacity ();
+ tree cap = capacity->get_value ();
+ if (error_operand_p (cap))
+ {
+ rust_error_at (parent->get_locus (),
+ "capacity of array %qs is not known at compile time",
+ array_ty_ty.get_name ().c_str ());
+ break;
+ }
+ auto cap_wi = wi::to_wide (cap).to_uhwi ();
+ if (cap_wi != pattern.get_items ().size ())
+ {
+ rust_error_at (pattern.get_locus (), ErrorCode::E0527,
+ "pattern requires %lu elements but array has %lu",
+ (unsigned long) pattern.get_items ().size (),
+ (unsigned long) cap_wi);
+ break;
+ }
+ break;
+ }
+ case TyTy::SLICE:
+ {
+ auto &slice_ty_ty = static_cast<TyTy::SliceType &> (*parent);
+ parent_element_ty = slice_ty_ty.get_element_type ();
+ break;
+ }
+ case TyTy::REF:
+ {
+ auto &ref_ty_ty = static_cast<TyTy::ReferenceType &> (*parent);
+ const TyTy::SliceType *slice = nullptr;
+ if (!ref_ty_ty.is_dyn_slice_type (&slice))
+ {
+ rust_error_at (pattern.get_locus (), "expected %s, found slice",
+ parent->as_string ().c_str ());
+ return;
+ }
+ parent_element_ty = slice->get_element_type ();
+ break;
+ }
+ default:
+ {
+ rust_error_at (pattern.get_locus (), "expected %s, found slice",
+ parent->as_string ().c_str ());
+ return;
+ }
+ }
+
+ rust_assert (parent_element_ty != nullptr);
+ // infered inherits array/slice typing from parent
+ infered = parent->clone ();
+ infered->set_ref (pattern.get_mappings ().get_hirid ());
+
+ // Type check every item in the SlicePattern against parent's element ty
+ // TODO update this after adding support for RestPattern in SlicePattern
+ for (const auto &item : pattern.get_items ())
+ {
+ TypeCheckPattern::Resolve (*item, parent_element_ty);
+ }
}
void
@@ -608,7 +725,8 @@ TypeCheckPattern::typecheck_range_pattern_bound (
TyTy::BaseType *resolved_bound = nullptr;
switch (bound.get_bound_type ())
{
- case HIR::RangePatternBound::RangePatternBoundType::LITERAL: {
+ case HIR::RangePatternBound::RangePatternBoundType::LITERAL:
+ {
auto &ref = static_cast<HIR::RangePatternBoundLiteral &> (bound);
HIR::Literal lit = ref.get_literal ();
@@ -617,14 +735,16 @@ TypeCheckPattern::typecheck_range_pattern_bound (
}
break;
- case HIR::RangePatternBound::RangePatternBoundType::PATH: {
+ case HIR::RangePatternBound::RangePatternBoundType::PATH:
+ {
auto &ref = static_cast<HIR::RangePatternBoundPath &> (bound);
resolved_bound = TypeCheckExpr::Resolve (ref.get_path ());
}
break;
- case HIR::RangePatternBound::RangePatternBoundType::QUALPATH: {
+ case HIR::RangePatternBound::RangePatternBoundType::QUALPATH:
+ {
auto &ref = static_cast<HIR::RangePatternBoundQualPath &> (bound);
resolved_bound = TypeCheckExpr::Resolve (ref.get_qualified_path ());
diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.cc b/gcc/rust/typecheck/rust-hir-type-check-stmt.cc
index 4e53856..87141af 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-stmt.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.cc
@@ -60,6 +60,12 @@ void
TypeCheckStmt::visit (HIR::ConstantItem &constant)
{
TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ());
+ if (!constant.has_expr ())
+ {
+ infered = type;
+ return;
+ }
+
TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ());
infered = coercion_site (
diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct.cc b/gcc/rust/typecheck/rust-hir-type-check-struct.cc
index df1636a..4ef8348 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-struct.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-struct.cc
@@ -329,8 +329,7 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field)
repeat_location.add_range (prev_field_locus);
rust_error_at (repeat_location, ErrorCode::E0062,
- "field %qs specified more than once",
- field_name.c_str ());
+ "field %qs specified more than once", field_name.c_str ());
return false;
}
@@ -363,7 +362,7 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field)
if (!ok)
{
rust_error_at (field.get_locus (), "unknown field");
- return true;
+ 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 6919093..78037bd 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc
@@ -29,6 +29,7 @@
#include "rust-substitution-mapper.h"
#include "rust-type-util.h"
#include "rust-system.h"
+#include "rust-compile-base.h"
namespace Rust {
namespace Resolver {
@@ -335,19 +336,13 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset,
seg->get_lang_item ());
else
{
- // FIXME: HACK: ARTHUR: Remove this
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ()
- .resolver ();
+ 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);
+ // 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;
+ });
}
// ref_node_id is the NodeId that the segments refers to.
@@ -549,8 +544,7 @@ TypeCheckType::resolve_segments (
bool selfResolveOk = false;
if (first_segment && tySegIsBigSelf
- && context->block_context ().is_in_context ()
- && context->block_context ().peek ().is_impl_block ())
+ && context->block_context ().is_in_context ())
{
TypeCheckBlockContextItem ctx = context->block_context ().peek ();
TyTy::BaseType *lookup = nullptr;
@@ -695,6 +689,7 @@ TypeCheckType::visit (HIR::ParenthesisedType &type)
void
TypeCheckType::visit (HIR::ArrayType &type)
{
+ auto element_type = TypeCheckType::Resolve (type.get_element_type ());
auto capacity_type = TypeCheckExpr::Resolve (type.get_size_expr ());
if (capacity_type->get_kind () == TyTy::TypeKind::ERROR)
return;
@@ -704,16 +699,38 @@ TypeCheckType::visit (HIR::ArrayType &type)
rust_assert (ok);
context->insert_type (type.get_size_expr ().get_mappings (), expected_ty);
- unify_site (type.get_size_expr ().get_mappings ().get_hirid (),
- TyTy::TyWithLocation (expected_ty),
- TyTy::TyWithLocation (capacity_type,
- type.get_size_expr ().get_locus ()),
- type.get_size_expr ().get_locus ());
+ TyTy::ConstType *const_type = nullptr;
+ if (capacity_type->get_kind () == TyTy::TypeKind::CONST)
+ {
+ const_type = static_cast<TyTy::ConstType *> (capacity_type);
- TyTy::BaseType *base = TypeCheckType::Resolve (type.get_element_type ());
- translated = new TyTy::ArrayType (type.get_mappings ().get_hirid (),
- type.get_locus (), type.get_size_expr (),
- TyTy::TyVar (base->get_ref ()));
+ unify_site (type.get_size_expr ().get_mappings ().get_hirid (),
+ TyTy::TyWithLocation (expected_ty),
+ TyTy::TyWithLocation (const_type->get_ty (),
+ type.get_size_expr ().get_locus ()),
+ type.get_size_expr ().get_locus ());
+ }
+ else
+ {
+ HirId size_id = type.get_size_expr ().get_mappings ().get_hirid ();
+ unify_site (size_id, TyTy::TyWithLocation (expected_ty),
+ TyTy::TyWithLocation (capacity_type,
+ type.get_size_expr ().get_locus ()),
+ type.get_size_expr ().get_locus ());
+
+ auto ctx = Compile::Context::get ();
+ tree capacity_expr = Compile::HIRCompileBase::query_compile_const_expr (
+ ctx, capacity_type, type.get_size_expr ());
+
+ const_type = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, "",
+ expected_ty, capacity_expr, {},
+ type.get_size_expr ().get_locus (),
+ size_id, size_id);
+ }
+
+ translated
+ = new TyTy::ArrayType (type.get_mappings ().get_hirid (), type.get_locus (),
+ const_type, TyTy::TyVar (element_type->get_ref ()));
}
void
@@ -850,10 +867,9 @@ 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, {});
+ resolved = new TyTy::ParamType (param.get_type_representation ().as_string (),
+ param.get_locus (),
+ param.get_mappings ().get_hirid (), {});
if (resolve_trait_bounds)
apply_trait_bounds (param, resolved);
@@ -872,7 +888,7 @@ TypeResolveGenericParam::apply_trait_bounds (HIR::TypeParam &param,
HirId implicit_id = mappings.get_next_hir_id ();
TyTy::ParamType *p
= new TyTy::ParamType (param.get_type_representation ().as_string (),
- param.get_locus (), implicit_id, param,
+ param.get_locus (), implicit_id,
{} /*empty specified bounds*/);
context->insert_implicit_type (implicit_id, p);
@@ -908,7 +924,8 @@ TypeResolveGenericParam::apply_trait_bounds (HIR::TypeParam &param,
{
switch (bound->get_bound_type ())
{
- case HIR::TypeParamBound::BoundType::TRAITBOUND: {
+ case HIR::TypeParamBound::BoundType::TRAITBOUND:
+ {
HIR::TraitBound &b = static_cast<HIR::TraitBound &> (*bound);
TyTy::TypeBoundPredicate predicate = get_predicate_from_bound (
@@ -920,7 +937,8 @@ TypeResolveGenericParam::apply_trait_bounds (HIR::TypeParam &param,
{
switch (predicate.get_polarity ())
{
- case BoundPolarity::AntiBound: {
+ case BoundPolarity::AntiBound:
+ {
bool found = predicates.find (predicate.get_id ())
!= predicates.end ();
if (found)
@@ -937,7 +955,8 @@ TypeResolveGenericParam::apply_trait_bounds (HIR::TypeParam &param,
}
break;
- default: {
+ default:
+ {
if (predicates.find (predicate.get_id ())
== predicates.end ())
{
@@ -1033,7 +1052,8 @@ ResolveWhereClauseItem::visit (HIR::TypeBoundWhereClauseItem &item)
{
switch (bound->get_bound_type ())
{
- case HIR::TypeParamBound::BoundType::TRAITBOUND: {
+ case HIR::TypeParamBound::BoundType::TRAITBOUND:
+ {
auto *b = static_cast<HIR::TraitBound *> (bound.get ());
TyTy::TypeBoundPredicate predicate
@@ -1042,7 +1062,8 @@ ResolveWhereClauseItem::visit (HIR::TypeBoundWhereClauseItem &item)
specified_bounds.push_back (std::move (predicate));
}
break;
- case HIR::TypeParamBound::BoundType::LIFETIME: {
+ case HIR::TypeParamBound::BoundType::LIFETIME:
+ {
if (auto param = binding->try_as<TyTy::ParamType> ())
{
auto *b = static_cast<HIR::Lifetime *> (bound.get ());
@@ -1071,23 +1092,15 @@ ResolveWhereClauseItem::visit (HIR::TypeBoundWhereClauseItem &item)
// then lookup the reference_node_id
NodeId ref_node_id = UNKNOWN_NODEID;
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- if (auto id = nr_ctx.lookup (ast_node_id))
- ref_node_id = *id;
- }
- else
- {
- NodeId id = UNKNOWN_NODEID;
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- if (resolver->lookup_resolved_type (ast_node_id, &id))
- ref_node_id = id;
+ if (auto id = nr_ctx.lookup (ast_node_id))
+ {
+ ref_node_id = *id;
}
-
- if (ref_node_id == UNKNOWN_NODEID)
+ else
{
// FIXME
rust_error_at (UNDEF_LOCATION,
diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc
index fbaf323..aba4ab5 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check.cc
@@ -26,11 +26,7 @@
#include "rust-hir-type-check-struct-field.h"
#include "rust-immutable-name-resolution-context.h"
-// for flag_name_resolution_2_0
-#include "options.h"
-
-extern bool
-saw_errors (void);
+extern bool saw_errors (void);
namespace Rust {
namespace Resolver {
@@ -165,7 +161,9 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const
HIR::TraitFunctionDecl &function = fn.get_decl ();
if (function.has_generics ())
{
- TypeCheckBase::ResolveGenericParams (function.get_generic_params (),
+ TypeCheckBase::ResolveGenericParams (HIR::Item::ItemKind::Function,
+ fn.get_locus (),
+ function.get_generic_params (),
substitutions, false /*is_foreign*/,
ABI::RUST);
}
@@ -231,7 +229,8 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const
break;
case HIR::SelfParam::IMM_REF:
- case HIR::SelfParam::MUT_REF: {
+ case HIR::SelfParam::MUT_REF:
+ {
auto mutability
= self_param.get_self_kind () == HIR::SelfParam::IMM_REF
? Mutability::Imm
@@ -275,26 +274,13 @@ TraitItemReference::get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const
TyTy::FnParam (param.get_param_name ().clone_pattern (), param_tyty));
}
- auto &mappings = Analysis::Mappings::get ();
-
- tl::optional<CanonicalPath> canonical_path;
- if (flag_name_resolution_2_0)
- {
- auto &nr_ctx
- = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
-
- canonical_path
- = nr_ctx.values.to_canonical_path (fn.get_mappings ().get_nodeid ());
- }
- else
- {
- canonical_path
- = mappings.lookup_canonical_path (fn.get_mappings ().get_nodeid ());
- }
+ auto &nr_ctx
+ = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
- rust_assert (canonical_path);
+ CanonicalPath canonical_path
+ = nr_ctx.to_canonical_path (fn.get_mappings ().get_nodeid ());
- RustIdent ident{*canonical_path, fn.get_locus ()};
+ RustIdent ident{canonical_path, fn.get_locus ()};
auto resolved = new TyTy::FnType (
fn.get_mappings ().get_hirid (), fn.get_mappings ().get_defid (),
function.get_function_name ().as_string (), ident,
diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h
index 18a65fe..e5a6e9e 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.h
+++ b/gcc/rust/typecheck/rust-hir-type-check.h
@@ -20,6 +20,7 @@
#define RUST_HIR_TYPE_CHECK
#include "rust-hir-map.h"
+#include "rust-mapping-common.h"
#include "rust-tyty.h"
#include "rust-hir-trait-reference.h"
#include "rust-stacked-contexts.h"
@@ -157,6 +158,39 @@ public:
WARN_UNUSED_RESULT Lifetime next () { return Lifetime (interner_index++); }
};
+struct DeferredOpOverload
+{
+ HirId expr_id;
+ LangItem::Kind lang_item_type;
+ HIR::PathIdentSegment specified_segment;
+ TyTy::TypeBoundPredicate predicate;
+ HIR::OperatorExprMeta op;
+
+ DeferredOpOverload (HirId expr_id, LangItem::Kind lang_item_type,
+ HIR::PathIdentSegment specified_segment,
+ TyTy::TypeBoundPredicate &predicate,
+ HIR::OperatorExprMeta op)
+ : expr_id (expr_id), lang_item_type (lang_item_type),
+ specified_segment (specified_segment), predicate (predicate), op (op)
+ {}
+
+ DeferredOpOverload (const struct DeferredOpOverload &other)
+ : expr_id (other.expr_id), lang_item_type (other.lang_item_type),
+ specified_segment (other.specified_segment), predicate (other.predicate),
+ op (other.op)
+ {}
+
+ DeferredOpOverload &operator= (struct DeferredOpOverload const &other)
+ {
+ expr_id = other.expr_id;
+ lang_item_type = other.lang_item_type;
+ specified_segment = other.specified_segment;
+ op = other.op;
+
+ return *this;
+ }
+};
+
class TypeCheckContext
{
public:
@@ -215,10 +249,10 @@ public:
bool lookup_associated_type_mapping (HirId id, HirId *mapping);
void insert_associated_impl_mapping (HirId trait_id,
- const TyTy::BaseType *impl_type,
+ TyTy::BaseType *impl_type,
HirId impl_id);
bool lookup_associated_impl_mapping_for_self (HirId trait_id,
- const TyTy::BaseType *self,
+ TyTy::BaseType *self,
HirId *mapping);
void insert_autoderef_mappings (HirId id,
@@ -237,6 +271,13 @@ public:
void insert_operator_overload (HirId id, TyTy::FnType *call_site);
bool lookup_operator_overload (HirId id, TyTy::FnType **call);
+ void insert_deferred_operator_overload (DeferredOpOverload deferred);
+ bool lookup_deferred_operator_overload (HirId id,
+ DeferredOpOverload *deferred);
+
+ void iterate_deferred_operator_overloads (
+ std::function<bool (HirId, DeferredOpOverload &)> cb);
+
void insert_unconstrained_check_marker (HirId id, bool status);
bool have_checked_for_unconstrained (HirId id, bool *result);
@@ -263,13 +304,16 @@ public:
WARN_UNUSED_RESULT std::vector<TyTy::Region>
regions_from_generic_args (const HIR::GenericArgs &args) const;
- void compute_inference_variables (bool error);
+ void compute_inference_variables (bool emit_error);
TyTy::VarianceAnalysis::CrateCtx &get_variance_analysis_ctx ();
private:
TypeCheckContext ();
+ bool compute_infer_var (HirId id, TyTy::BaseType *ty, bool emit_error);
+ bool compute_ambigious_op_overload (HirId id, DeferredOpOverload &op);
+
std::map<NodeId, HirId> node_id_refs;
std::map<HirId, TyTy::BaseType *> resolved;
std::vector<std::unique_ptr<TyTy::BaseType>> builtins;
@@ -281,7 +325,7 @@ private:
std::map<HirId, AssociatedImplTrait> associated_impl_traits;
// trait-id -> list of < self-tyty:impl-id>
- std::map<HirId, std::vector<std::pair<const TyTy::BaseType *, HirId>>>
+ std::map<HirId, std::vector<std::pair<TyTy::BaseType *, HirId>>>
associated_traits_to_impls;
std::map<HirId, HirId> associated_type_mappings;
@@ -306,6 +350,9 @@ private:
std::set<HirId> querys_in_progress;
std::set<DefId> trait_queries_in_progress;
+ // deferred operator overload
+ std::map<HirId, DeferredOpOverload> deferred_operator_overloads;
+
// variance analysis
TyTy::VarianceAnalysis::CrateCtx variance_analysis_ctx;
diff --git a/gcc/rust/typecheck/rust-substitution-mapper.cc b/gcc/rust/typecheck/rust-substitution-mapper.cc
index f0bd1f8..c5b823e 100644
--- a/gcc/rust/typecheck/rust-substitution-mapper.cc
+++ b/gcc/rust/typecheck/rust-substitution-mapper.cc
@@ -268,6 +268,12 @@ SubstMapperInternal::visit (TyTy::ParamType &type)
}
void
+SubstMapperInternal::visit (TyTy::ConstType &type)
+{
+ resolved = type.handle_substitions (mappings);
+}
+
+void
SubstMapperInternal::visit (TyTy::PlaceholderType &type)
{
rust_assert (type.can_resolve ());
@@ -374,7 +380,7 @@ SubstMapperInternal::visit (TyTy::DynamicObjectType &type)
void
SubstMapperInternal::visit (TyTy::OpaqueType &type)
{
- resolved = type.handle_substitions (mappings);
+ resolved = type.clone ();
}
// SubstMapperFromExisting
diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h
index 32ab71c..2389d83 100644
--- a/gcc/rust/typecheck/rust-substitution-mapper.h
+++ b/gcc/rust/typecheck/rust-substitution-mapper.h
@@ -61,6 +61,7 @@ public:
void visit (TyTy::ReferenceType &) override { rust_unreachable (); }
void visit (TyTy::PointerType &) override { rust_unreachable (); }
void visit (TyTy::ParamType &) override { rust_unreachable (); }
+ void visit (TyTy::ConstType &) override { rust_unreachable (); }
void visit (TyTy::StrType &) override { rust_unreachable (); }
void visit (TyTy::NeverType &) override { rust_unreachable (); }
void visit (TyTy::DynamicObjectType &) override { rust_unreachable (); }
@@ -92,6 +93,7 @@ public:
void visit (TyTy::ReferenceType &type) override;
void visit (TyTy::PointerType &type) override;
void visit (TyTy::ParamType &type) override;
+ void visit (TyTy::ConstType &type) override;
void visit (TyTy::PlaceholderType &type) override;
void visit (TyTy::ProjectionType &type) override;
void visit (TyTy::ClosureType &type) override;
@@ -145,6 +147,7 @@ public:
void visit (TyTy::ReferenceType &) override { rust_unreachable (); }
void visit (TyTy::PointerType &) override { rust_unreachable (); }
void visit (TyTy::ParamType &) override { rust_unreachable (); }
+ void visit (TyTy::ConstType &) override { rust_unreachable (); }
void visit (TyTy::StrType &) override { rust_unreachable (); }
void visit (TyTy::NeverType &) override { rust_unreachable (); }
void visit (TyTy::PlaceholderType &) override { rust_unreachable (); }
@@ -185,12 +188,13 @@ public:
void visit (const TyTy::ReferenceType &) override {}
void visit (const TyTy::PointerType &) override {}
void visit (const TyTy::ParamType &) override {}
+ void visit (const TyTy::ConstType &) override {}
void visit (const TyTy::StrType &) override {}
void visit (const TyTy::NeverType &) override {}
void visit (const TyTy::PlaceholderType &) override {}
void visit (const TyTy::ProjectionType &) override {}
void visit (const TyTy::DynamicObjectType &) override {}
- void visit (const TyTy::OpaqueType &type) override {}
+ void visit (const TyTy::OpaqueType &) override {}
private:
GetUsedSubstArgs ();
diff --git a/gcc/rust/typecheck/rust-type-util.cc b/gcc/rust/typecheck/rust-type-util.cc
index c6c5b4b..2d66166 100644
--- a/gcc/rust/typecheck/rust-type-util.cc
+++ b/gcc/rust/typecheck/rust-type-util.cc
@@ -24,6 +24,7 @@
#include "rust-hir-type-check.h"
#include "rust-hir-type-check-type.h"
#include "rust-casts.h"
+#include "rust-mapping-common.h"
#include "rust-unify.h"
#include "rust-coercion.h"
#include "rust-hir-type-bounds.h"
@@ -37,15 +38,14 @@ 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))
- return false;
-
if (context->lookup_type (reference, result))
return true;
+ if (context->query_in_progress (reference))
+ return false;
+
context->insert_query (reference);
std::pair<HIR::Enum *, HIR::EnumItem *> enum_candidiate
@@ -103,18 +103,13 @@ query_type (HirId reference, TyTy::BaseType **result)
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 ();
+ 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);
+ // 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;
+ });
if (ref_node_id != UNKNOWN_NODEID)
{
@@ -192,10 +187,12 @@ unify_site_and (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
TyTy::BaseType *expected = lhs.get_ty ();
TyTy::BaseType *expr = rhs.get_ty ();
- rust_debug (
- "unify_site_and commit %s infer %s id={%u} expected={%s} expr={%s}",
- commit_if_ok ? "true" : "false", implicit_infer_vars ? "true" : "false", id,
- expected->debug_str ().c_str (), expr->debug_str ().c_str ());
+ rust_debug_loc (
+ unify_locus,
+ "begin unify_site_and commit %s infer %s id={%u} expected={%s} expr={%s}",
+ commit_if_ok ? "true" : "false", implicit_infer_vars ? "true" : "false",
+ id == UNKNOWN_HIRID ? 0 : id, expected->debug_str ().c_str (),
+ expr->debug_str ().c_str ());
std::vector<UnifyRules::CommitSite> commits;
std::vector<UnifyRules::InferenceSite> infers;
@@ -203,6 +200,15 @@ unify_site_and (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
= UnifyRules::Resolve (lhs, rhs, unify_locus, false /*commit inline*/,
emit_errors, implicit_infer_vars, commits, infers);
bool ok = result->get_kind () != TyTy::TypeKind::ERROR;
+
+ rust_debug_loc (unify_locus,
+ "unify_site_and done ok=%s commit %s infer %s id={%u} "
+ "expected={%s} expr={%s}",
+ ok ? "true" : "false", commit_if_ok ? "true" : "false",
+ implicit_infer_vars ? "true" : "false",
+ id == UNKNOWN_HIRID ? 0 : id, expected->debug_str ().c_str (),
+ expr->debug_str ().c_str ());
+
if (ok && commit_if_ok)
{
for (auto &c : commits)
diff --git a/gcc/rust/typecheck/rust-type-util.h b/gcc/rust/typecheck/rust-type-util.h
index 03874a4..dd97f1e 100644
--- a/gcc/rust/typecheck/rust-type-util.h
+++ b/gcc/rust/typecheck/rust-type-util.h
@@ -25,33 +25,30 @@
namespace Rust {
namespace Resolver {
-bool
-query_type (HirId reference, TyTy::BaseType **result);
+bool query_type (HirId reference, TyTy::BaseType **result);
-bool
-types_compatable (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
- location_t unify_locus, bool emit_errors);
+bool types_compatable (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
+ location_t unify_locus, bool emit_errors);
-TyTy::BaseType *
-unify_site (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
- location_t unify_locus);
+TyTy::BaseType *unify_site (HirId id, TyTy::TyWithLocation lhs,
+ TyTy::TyWithLocation rhs, location_t unify_locus);
-TyTy::BaseType *
-unify_site_and (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
- location_t unify_locus, bool emit_errors, bool commit_if_ok,
- bool implicit_infer_vars, bool cleanup);
+TyTy::BaseType *unify_site_and (HirId id, TyTy::TyWithLocation lhs,
+ TyTy::TyWithLocation rhs,
+ location_t unify_locus, bool emit_errors,
+ bool commit_if_ok, bool implicit_infer_vars,
+ bool cleanup);
-TyTy::BaseType *
-coercion_site (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
- location_t coercion_locus);
+TyTy::BaseType *coercion_site (HirId id, TyTy::TyWithLocation lhs,
+ TyTy::TyWithLocation rhs,
+ location_t coercion_locus);
-TyTy::BaseType *
-try_coercion (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
- location_t coercion_locus);
+TyTy::BaseType *try_coercion (HirId id, TyTy::TyWithLocation lhs,
+ TyTy::TyWithLocation rhs,
+ location_t coercion_locus);
-TyTy::BaseType *
-cast_site (HirId id, TyTy::TyWithLocation from, TyTy::TyWithLocation to,
- location_t cast_locus);
+TyTy::BaseType *cast_site (HirId id, TyTy::TyWithLocation from,
+ TyTy::TyWithLocation to, location_t cast_locus);
AssociatedImplTrait *
lookup_associated_impl_block (const TyTy::TypeBoundPredicate &bound,
diff --git a/gcc/rust/typecheck/rust-typecheck-context.cc b/gcc/rust/typecheck/rust-typecheck-context.cc
index 9112b99..c74a920 100644
--- a/gcc/rust/typecheck/rust-typecheck-context.cc
+++ b/gcc/rust/typecheck/rust-typecheck-context.cc
@@ -18,6 +18,7 @@
#include "rust-hir-type-check.h"
#include "rust-type-util.h"
+#include "rust-hir-type-check-expr.h"
namespace Rust {
namespace Resolver {
@@ -299,8 +300,9 @@ TypeCheckContext::lookup_associated_type_mapping (HirId id, HirId *mapping)
}
void
-TypeCheckContext::insert_associated_impl_mapping (
- HirId trait_id, const TyTy::BaseType *impl_type, HirId impl_id)
+TypeCheckContext::insert_associated_impl_mapping (HirId trait_id,
+ TyTy::BaseType *impl_type,
+ HirId impl_id)
{
auto it = associated_traits_to_impls.find (trait_id);
if (it == associated_traits_to_impls.end ())
@@ -312,8 +314,9 @@ TypeCheckContext::insert_associated_impl_mapping (
}
bool
-TypeCheckContext::lookup_associated_impl_mapping_for_self (
- HirId trait_id, const TyTy::BaseType *self, HirId *mapping)
+TypeCheckContext::lookup_associated_impl_mapping_for_self (HirId trait_id,
+ TyTy::BaseType *self,
+ HirId *mapping)
{
auto it = associated_traits_to_impls.find (trait_id);
if (it == associated_traits_to_impls.end ())
@@ -321,7 +324,9 @@ TypeCheckContext::lookup_associated_impl_mapping_for_self (
for (auto &item : it->second)
{
- if (item.first->can_eq (self, false))
+ if (types_compatable (TyTy::TyWithLocation (item.first),
+ TyTy::TyWithLocation (self), UNKNOWN_LOCATION,
+ false))
{
*mapping = item.second;
return true;
@@ -409,6 +414,38 @@ TypeCheckContext::lookup_operator_overload (HirId id, TyTy::FnType **call)
}
void
+TypeCheckContext::insert_deferred_operator_overload (
+ DeferredOpOverload deferred)
+{
+ HirId expr_id = deferred.expr_id;
+ deferred_operator_overloads.emplace (std::make_pair (expr_id, deferred));
+}
+
+bool
+TypeCheckContext::lookup_deferred_operator_overload (
+ HirId id, DeferredOpOverload *deferred)
+{
+ auto it = deferred_operator_overloads.find (id);
+ if (it == deferred_operator_overloads.end ())
+ return false;
+
+ *deferred = it->second;
+ return true;
+}
+
+void
+TypeCheckContext::iterate_deferred_operator_overloads (
+ std::function<bool (HirId, DeferredOpOverload &)> cb)
+{
+ for (auto it = deferred_operator_overloads.begin ();
+ it != deferred_operator_overloads.end (); it++)
+ {
+ if (!cb (it->first, it->second))
+ return;
+ }
+}
+
+void
TypeCheckContext::insert_unconstrained_check_marker (HirId id, bool status)
{
unconstrained[id] = status;
@@ -574,44 +611,77 @@ TypeCheckContext::regions_from_generic_args (const HIR::GenericArgs &args) const
return regions;
}
+bool
+TypeCheckContext::compute_ambigious_op_overload (HirId id,
+ DeferredOpOverload &op)
+{
+ rust_debug ("attempting resolution of op overload: %s",
+ op.predicate.as_string ().c_str ());
+
+ TyTy::BaseType *lhs = nullptr;
+ bool ok = lookup_type (op.op.get_lvalue_mappings ().get_hirid (), &lhs);
+ rust_assert (ok);
+
+ TyTy::BaseType *rhs = nullptr;
+ if (op.op.has_rvalue_mappings ())
+ {
+ bool ok = lookup_type (op.op.get_rvalue_mappings ().get_hirid (), &rhs);
+ rust_assert (ok);
+ }
+
+ TypeCheckExpr::ResolveOpOverload (op.lang_item_type, op.op, lhs, rhs,
+ op.specified_segment);
+
+ return true;
+}
+
void
-TypeCheckContext::compute_inference_variables (bool error)
+TypeCheckContext::compute_inference_variables (bool emit_error)
{
- auto &mappings = Analysis::Mappings::get ();
+ iterate_deferred_operator_overloads (
+ [&] (HirId id, DeferredOpOverload &op) mutable -> bool {
+ return compute_ambigious_op_overload (id, op);
+ });
- // default inference variables if possible
iterate ([&] (HirId id, TyTy::BaseType *ty) mutable -> bool {
- // nothing to do
- if (ty->get_kind () != TyTy::TypeKind::INFER)
- return true;
+ return compute_infer_var (id, ty, emit_error);
+ });
+}
- TyTy::InferType *infer_var = static_cast<TyTy::InferType *> (ty);
- TyTy::BaseType *default_type;
-
- rust_debug_loc (mappings.lookup_location (id),
- "trying to default infer-var: %s",
- infer_var->as_string ().c_str ());
- bool ok = infer_var->default_type (&default_type);
- if (!ok)
- {
- if (error)
- rust_error_at (mappings.lookup_location (id), ErrorCode::E0282,
- "type annotations needed");
- return true;
- }
-
- auto result
- = unify_site (id, TyTy::TyWithLocation (ty),
- TyTy::TyWithLocation (default_type), UNDEF_LOCATION);
- rust_assert (result);
- rust_assert (result->get_kind () != TyTy::TypeKind::ERROR);
- result->set_ref (id);
- insert_type (Analysis::NodeMapping (mappings.get_current_crate (), 0, id,
- UNKNOWN_LOCAL_DEFID),
- result);
+bool
+TypeCheckContext::compute_infer_var (HirId id, TyTy::BaseType *ty,
+ bool emit_error)
+{
+ auto &mappings = Analysis::Mappings::get ();
+ // nothing to do
+ if (ty->get_kind () != TyTy::TypeKind::INFER)
return true;
- });
+
+ TyTy::InferType *infer_var = static_cast<TyTy::InferType *> (ty);
+ TyTy::BaseType *default_type;
+
+ rust_debug_loc (mappings.lookup_location (id),
+ "trying to default infer-var: %s",
+ infer_var->as_string ().c_str ());
+ bool ok = infer_var->default_type (&default_type);
+ if (!ok)
+ {
+ if (emit_error)
+ rust_error_at (mappings.lookup_location (id), ErrorCode::E0282,
+ "type annotations needed");
+ return true;
+ }
+
+ auto result
+ = unify_site (id, TyTy::TyWithLocation (ty),
+ TyTy::TyWithLocation (default_type), UNDEF_LOCATION);
+ rust_assert (result);
+ rust_assert (result->get_kind () != TyTy::TypeKind::ERROR);
+ result->set_ref (id);
+ insert_implicit_type (id, result);
+
+ return true;
}
TyTy::VarianceAnalysis::CrateCtx &
diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc
index e028a0a..6cf9b04 100644
--- a/gcc/rust/typecheck/rust-tyty-bounds.cc
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -61,6 +61,39 @@ TypeBoundsProbe::is_bound_satisfied_for_type (TyTy::BaseType *receiver,
return false;
}
+bool
+TypeBoundsProbe::process_impl_block (
+ HirId id, HIR::ImplBlock *impl,
+ std::vector<std::pair<HIR::TypePath *, HIR::ImplBlock *>>
+ &possible_trait_paths)
+{
+ // we are filtering for trait-impl-blocks
+ if (!impl->has_trait_ref ())
+ return true;
+
+ // can be recursive trait resolution
+ HIR::Trait *t = TraitResolver::ResolveHirItem (impl->get_trait_ref ());
+ if (t == nullptr)
+ return true;
+ // DefId trait_id = t->get_mappings ().get_defid ();
+ // if (context->trait_query_in_progress (trait_id))
+ // return true;
+
+ HirId impl_ty_id = impl->get_type ().get_mappings ().get_hirid ();
+ TyTy::BaseType *impl_type = nullptr;
+ if (!query_type (impl_ty_id, &impl_type))
+ return true;
+
+ if (!receiver->can_eq (impl_type, false))
+ {
+ if (!impl_type->can_eq (receiver, false))
+ return true;
+ }
+
+ possible_trait_paths.push_back ({&impl->get_trait_ref (), impl});
+ return true;
+}
+
void
TypeBoundsProbe::scan ()
{
@@ -68,31 +101,7 @@ TypeBoundsProbe::scan ()
possible_trait_paths;
mappings.iterate_impl_blocks (
[&] (HirId id, HIR::ImplBlock *impl) mutable -> bool {
- // we are filtering for trait-impl-blocks
- if (!impl->has_trait_ref ())
- return true;
-
- // can be recursive trait resolution
- HIR::Trait *t = TraitResolver::ResolveHirItem (impl->get_trait_ref ());
- if (t == nullptr)
- return true;
- DefId trait_id = t->get_mappings ().get_defid ();
- if (context->trait_query_in_progress (trait_id))
- return true;
-
- HirId impl_ty_id = impl->get_type ().get_mappings ().get_hirid ();
- TyTy::BaseType *impl_type = nullptr;
- if (!query_type (impl_ty_id, &impl_type))
- return true;
-
- if (!receiver->can_eq (impl_type, false))
- {
- if (!impl_type->can_eq (receiver, false))
- return true;
- }
-
- possible_trait_paths.push_back ({&impl->get_trait_ref (), impl});
- return true;
+ return process_impl_block (id, impl, possible_trait_paths);
});
for (auto &path : possible_trait_paths)
@@ -105,7 +114,7 @@ TypeBoundsProbe::scan ()
}
// marker traits...
- assemble_sized_builtin ();
+ assemble_marker_builtins ();
// add auto trait bounds
for (auto *auto_trait : mappings.get_auto_traits ())
@@ -113,7 +122,7 @@ TypeBoundsProbe::scan ()
}
void
-TypeBoundsProbe::assemble_sized_builtin ()
+TypeBoundsProbe::assemble_marker_builtins ()
{
const TyTy::BaseType *raw = receiver->destructure ();
@@ -132,7 +141,6 @@ TypeBoundsProbe::assemble_sized_builtin ()
case TyTy::POINTER:
case TyTy::PARAM:
case TyTy::FNDEF:
- case TyTy::FNPTR:
case TyTy::BOOL:
case TyTy::CHAR:
case TyTy::INT:
@@ -140,7 +148,6 @@ TypeBoundsProbe::assemble_sized_builtin ()
case TyTy::FLOAT:
case TyTy::USIZE:
case TyTy::ISIZE:
- case TyTy::CLOSURE:
case TyTy::INFER:
case TyTy::NEVER:
case TyTy::PLACEHOLDER:
@@ -149,6 +156,14 @@ TypeBoundsProbe::assemble_sized_builtin ()
assemble_builtin_candidate (LangItem::Kind::SIZED);
break;
+ case TyTy::FNPTR:
+ case TyTy::CLOSURE:
+ assemble_builtin_candidate (LangItem::Kind::SIZED);
+ assemble_builtin_candidate (LangItem::Kind::FN_ONCE);
+ assemble_builtin_candidate (LangItem::Kind::FN);
+ assemble_builtin_candidate (LangItem::Kind::FN_MUT);
+ break;
+
// FIXME str and slice need to be moved and test cases updated
case TyTy::SLICE:
case TyTy::STR:
@@ -158,6 +173,7 @@ TypeBoundsProbe::assemble_sized_builtin ()
assemble_builtin_candidate (LangItem::Kind::SIZED);
break;
+ case TyTy::CONST:
case TyTy::DYNAMIC:
case TyTy::ERROR:
break;
@@ -206,7 +222,7 @@ TyTy::TypeBoundPredicate
TypeCheckBase::get_predicate_from_bound (
HIR::TypePath &type_path,
tl::optional<std::reference_wrapper<HIR::Type>> associated_self,
- BoundPolarity polarity, bool is_qualified_type_path)
+ BoundPolarity polarity, bool is_qualified_type_path, bool is_super_trait)
{
TyTy::TypeBoundPredicate lookup = TyTy::TypeBoundPredicate::error ();
bool already_resolved
@@ -226,7 +242,8 @@ TypeCheckBase::get_predicate_from_bound (
auto &final_seg = type_path.get_final_segment ();
switch (final_seg.get_type ())
{
- case HIR::TypePathSegment::SegmentType::GENERIC: {
+ case HIR::TypePathSegment::SegmentType::GENERIC:
+ {
auto &final_generic_seg
= static_cast<HIR::TypePathSegmentGeneric &> (final_seg);
if (final_generic_seg.has_generic_args ())
@@ -251,7 +268,8 @@ TypeCheckBase::get_predicate_from_bound (
}
break;
- case HIR::TypePathSegment::SegmentType::FUNCTION: {
+ case HIR::TypePathSegment::SegmentType::FUNCTION:
+ {
auto &final_function_seg
= static_cast<HIR::TypePathSegmentFunction &> (final_seg);
auto &fn = final_function_seg.get_function_path ();
@@ -327,7 +345,8 @@ TypeCheckBase::get_predicate_from_bound (
if (!args.is_empty () || predicate.requires_generic_args ())
{
// this is applying generic arguments to a trait reference
- predicate.apply_generic_arguments (&args, associated_self.has_value ());
+ predicate.apply_generic_arguments (&args, associated_self.has_value (),
+ is_super_trait);
}
context->insert_resolved_predicate (type_path.get_mappings ().get_hirid (),
@@ -508,7 +527,8 @@ TypeBoundPredicate::is_object_safe (bool emit_error, location_t locus) const
void
TypeBoundPredicate::apply_generic_arguments (HIR::GenericArgs *generic_args,
- bool has_associated_self)
+ bool has_associated_self,
+ bool is_super_trait)
{
rust_assert (!substitutions.empty ());
if (has_associated_self)
@@ -529,23 +549,26 @@ TypeBoundPredicate::apply_generic_arguments (HIR::GenericArgs *generic_args,
Resolver::TypeCheckContext::get ()->regions_from_generic_args (
*generic_args));
- apply_argument_mappings (args);
+ apply_argument_mappings (args, is_super_trait);
}
void
TypeBoundPredicate::apply_argument_mappings (
- SubstitutionArgumentMappings &arguments)
+ SubstitutionArgumentMappings &arguments, bool is_super_trait)
{
used_arguments = arguments;
error_flag |= used_arguments.is_error ();
auto &subst_mappings = used_arguments;
+
+ bool substs_need_bounds_check = !is_super_trait;
for (auto &sub : get_substs ())
{
SubstitutionArg arg = SubstitutionArg::error ();
bool ok
= subst_mappings.get_argument_for_symbol (sub.get_param_ty (), &arg);
if (ok && arg.get_tyty () != nullptr)
- sub.fill_param_ty (subst_mappings, subst_mappings.get_locus ());
+ sub.fill_param_ty (subst_mappings, subst_mappings.get_locus (),
+ substs_need_bounds_check);
}
// associated argument mappings
@@ -566,7 +589,7 @@ TypeBoundPredicate::apply_argument_mappings (
auto adjusted
= super_trait.adjust_mappings_for_this (used_arguments,
true /*trait mode*/);
- super_trait.apply_argument_mappings (adjusted);
+ super_trait.apply_argument_mappings (adjusted, is_super_trait);
}
}
@@ -699,7 +722,7 @@ TypeBoundPredicate::handle_substitions (
if (sub.get_param_ty () == nullptr)
continue;
- ParamType *p = sub.get_param_ty ();
+ auto p = sub.get_param_ty ();
BaseType *r = p->resolve ();
BaseType *s = Resolver::SubstMapperInternal::Resolve (r, subst_mappings);
@@ -746,16 +769,34 @@ size_t
TypeBoundPredicate::get_num_associated_bindings () const
{
size_t count = 0;
+
+ get_trait_hierachy ([&count] (const Resolver::TraitReference &ref) {
+ for (const auto &trait_item : ref.get_trait_items ())
+ {
+ bool is_associated_type
+ = trait_item.get_trait_item_type ()
+ == Resolver::TraitItemReference::TraitItemType::TYPE;
+ if (is_associated_type)
+ count++;
+ }
+ });
+
+ return count;
+}
+
+void
+TypeBoundPredicate::get_trait_hierachy (
+ std::function<void (const Resolver::TraitReference &)> callback) const
+{
auto trait_ref = get ();
- for (const auto &trait_item : trait_ref->get_trait_items ())
+ callback (*trait_ref);
+
+ for (auto &super : super_traits)
{
- bool is_associated_type
- = trait_item.get_trait_item_type ()
- == Resolver::TraitItemReference::TraitItemType::TYPE;
- if (is_associated_type)
- count++;
+ const auto &super_trait_ref = *super.get ();
+ callback (super_trait_ref);
+ super.get_trait_hierachy (callback);
}
- return count;
}
TypeBoundPredicateItem
@@ -808,21 +849,19 @@ TypeBoundPredicate::is_equal (const TypeBoundPredicate &other) const
// then match the generics applied
for (size_t i = 0; i < get_num_substitutions (); i++)
{
- const SubstitutionParamMapping &a = substitutions.at (i);
- const SubstitutionParamMapping &b = other.substitutions.at (i);
+ SubstitutionParamMapping a = substitutions.at (i);
+ SubstitutionParamMapping b = other.substitutions.at (i);
- const ParamType *ap = a.get_param_ty ();
- const ParamType *bp = b.get_param_ty ();
+ auto ap = a.get_param_ty ();
+ auto bp = b.get_param_ty ();
- const BaseType *apd = ap->destructure ();
- const BaseType *bpd = bp->destructure ();
+ BaseType *apd = ap->destructure ();
+ BaseType *bpd = bp->destructure ();
- // FIXME use the unify_and infer inteface or try coerce
- if (!apd->can_eq (bpd, false /*emit_errors*/))
- {
- if (!bpd->can_eq (apd, false /*emit_errors*/))
- return false;
- }
+ if (!Resolver::types_compatable (TyTy::TyWithLocation (apd),
+ TyTy::TyWithLocation (bpd),
+ UNKNOWN_LOCATION, false))
+ return false;
}
return true;
diff --git a/gcc/rust/typecheck/rust-tyty-call.cc b/gcc/rust/typecheck/rust-tyty-call.cc
index 2e0830e..63bb1ff 100644
--- a/gcc/rust/typecheck/rust-tyty-call.cc
+++ b/gcc/rust/typecheck/rust-tyty-call.cc
@@ -171,7 +171,8 @@ TypeCheckCallExpr::visit (FnType &type)
{
case TyTy::TypeKind::ERROR:
return;
- case TyTy::TypeKind::INT: {
+ case TyTy::TypeKind::INT:
+ {
auto &int_ty
= static_cast<TyTy::IntType &> (*argument_expr_tyty);
if ((int_ty.get_int_kind () == TyTy::IntType::IntKind::I8)
@@ -186,7 +187,8 @@ TypeCheckCallExpr::visit (FnType &type)
}
break;
}
- case TyTy::TypeKind::UINT: {
+ case TyTy::TypeKind::UINT:
+ {
auto &uint_ty
= static_cast<TyTy::UintType &> (*argument_expr_tyty);
if ((uint_ty.get_uint_kind () == TyTy::UintType::UintKind::U8)
@@ -202,7 +204,8 @@ TypeCheckCallExpr::visit (FnType &type)
}
break;
}
- case TyTy::TypeKind::FLOAT: {
+ case TyTy::TypeKind::FLOAT:
+ {
if (static_cast<TyTy::FloatType &> (*argument_expr_tyty)
.get_float_kind ()
== TyTy::FloatType::FloatKind::F32)
@@ -216,14 +219,16 @@ TypeCheckCallExpr::visit (FnType &type)
}
break;
}
- case TyTy::TypeKind::BOOL: {
+ case TyTy::TypeKind::BOOL:
+ {
rich_location richloc (line_table, arg_locus);
richloc.add_fixit_replace ("cast the value to c_int: as c_int");
rust_error_at (arg_locus, ErrorCode::E0617,
"expected %<c_int%> variadic argument");
return;
}
- case TyTy::TypeKind::FNDEF: {
+ case TyTy::TypeKind::FNDEF:
+ {
rust_error_at (
arg_locus, ErrorCode::E0617,
"unexpected function definition type as variadic "
@@ -246,7 +251,7 @@ TypeCheckCallExpr::visit (FnType &type)
}
type.monomorphize ();
- resolved = type.get_return_type ()->clone ();
+ resolved = type.get_return_type ()->monomorphized_clone ();
}
void
diff --git a/gcc/rust/typecheck/rust-tyty-call.h b/gcc/rust/typecheck/rust-tyty-call.h
index c42fdcd..9e4aab5 100644
--- a/gcc/rust/typecheck/rust-tyty-call.h
+++ b/gcc/rust/typecheck/rust-tyty-call.h
@@ -62,6 +62,7 @@ public:
void visit (DynamicObjectType &) override { rust_unreachable (); }
void visit (ClosureType &type) override { rust_unreachable (); }
void visit (OpaqueType &type) override { rust_unreachable (); }
+ void visit (ConstType &type) override { rust_unreachable (); }
// tuple-structs
void visit (ADTType &type) override;
diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h
index c897c13..c22dfdd 100644
--- a/gcc/rust/typecheck/rust-tyty-cmp.h
+++ b/gcc/rust/typecheck/rust-tyty-cmp.h
@@ -447,6 +447,22 @@ public:
}
}
+ virtual void visit (const ConstType &type) override
+ {
+ ok = false;
+ if (emit_error_flag)
+ {
+ location_t ref_locus = mappings.lookup_location (type.get_ref ());
+ location_t base_locus
+ = mappings.lookup_location (get_base ()->get_ref ());
+ rich_location r (line_table, ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "expected [%s] got [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+ }
+
protected:
BaseCmp (const BaseType *base, bool emit_errors)
: mappings (Analysis::Mappings::get ()),
@@ -621,7 +637,8 @@ public:
ok = true;
return;
- case InferType::InferTypeKind::INTEGRAL: {
+ case InferType::InferTypeKind::INTEGRAL:
+ {
if (type.get_infer_kind () == InferType::InferTypeKind::INTEGRAL)
{
ok = true;
@@ -635,7 +652,8 @@ public:
}
break;
- case InferType::InferTypeKind::FLOAT: {
+ case InferType::InferTypeKind::FLOAT:
+ {
if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
{
ok = true;
@@ -1604,6 +1622,23 @@ private:
const OpaqueType *base;
};
+class ConstCmp : public BaseCmp
+{
+ using Rust::TyTy::BaseCmp::visit;
+
+public:
+ ConstCmp (const ConstType *base, bool emit_errors)
+ : BaseCmp (base, emit_errors), base (base)
+ {}
+
+ // TODO
+
+private:
+ const BaseType *get_base () const override { return base; }
+
+ const ConstType *base;
+};
+
} // namespace TyTy
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc
index bdb6474..817910b 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.cc
+++ b/gcc/rust/typecheck/rust-tyty-subst.cc
@@ -18,18 +18,22 @@
#include "rust-tyty-subst.h"
+#include "rust-hir-generic-param.h"
#include "rust-system.h"
#include "rust-tyty.h"
#include "rust-hir-type-check.h"
#include "rust-substitution-mapper.h"
#include "rust-hir-type-check-type.h"
+#include "rust-hir-type-check-expr.h"
+#include "rust-compile-base.h"
#include "rust-type-util.h"
+#include "tree.h"
namespace Rust {
namespace TyTy {
-SubstitutionParamMapping::SubstitutionParamMapping (HIR::TypeParam &generic,
- ParamType *param)
+SubstitutionParamMapping::SubstitutionParamMapping (HIR::GenericParam &generic,
+ BaseGeneric *param)
: generic (generic), param (param)
{}
@@ -54,30 +58,42 @@ SubstitutionParamMapping::clone () const
static_cast<ParamType *> (param->clone ()));
}
-ParamType *
+BaseGeneric *
SubstitutionParamMapping::get_param_ty ()
{
return param;
}
-const ParamType *
+const BaseGeneric *
SubstitutionParamMapping::get_param_ty () const
{
return param;
}
-HIR::TypeParam &
+HIR::GenericParam &
SubstitutionParamMapping::get_generic_param ()
{
return generic;
}
+const HIR::GenericParam &
+SubstitutionParamMapping::get_generic_param () const
+{
+ return generic;
+}
+
bool
SubstitutionParamMapping::needs_substitution () const
{
return !(get_param_ty ()->is_concrete ());
}
+Identifier
+SubstitutionParamMapping::get_type_representation () const
+{
+ return param->get_symbol ();
+}
+
location_t
SubstitutionParamMapping::get_param_locus () const
{
@@ -87,13 +103,35 @@ SubstitutionParamMapping::get_param_locus () const
bool
SubstitutionParamMapping::param_has_default_ty () const
{
- return generic.has_type ();
+ if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
+ {
+ const auto &type_param = static_cast<const HIR::TypeParam &> (generic);
+ return type_param.has_type ();
+ }
+
+ rust_assert (generic.get_kind () == HIR::GenericParam::GenericKind::CONST);
+ const auto &const_param
+ = static_cast<const HIR::ConstGenericParam &> (generic);
+ return const_param.has_default_expression ();
}
BaseType *
SubstitutionParamMapping::get_default_ty () const
{
- TyVar var (generic.get_type_mappings ().get_hirid ());
+ if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
+ {
+ const auto &type_param = static_cast<const HIR::TypeParam &> (generic);
+ TyVar var (type_param.get_type_mappings ().get_hirid ());
+ return var.get_tyty ();
+ }
+
+ rust_assert (generic.get_kind () == HIR::GenericParam::GenericKind::CONST);
+ const auto &const_param
+ = static_cast<const HIR::ConstGenericParam &> (generic);
+ rust_assert (const_param.has_default_expression ());
+
+ const auto &expr = const_param.get_default_expression ();
+ TyVar var (expr.get_mappings ().get_hirid ());
return var.get_tyty ();
}
@@ -109,7 +147,8 @@ SubstitutionParamMapping::need_substitution () const
bool
SubstitutionParamMapping::fill_param_ty (
- SubstitutionArgumentMappings &subst_mappings, location_t locus)
+ SubstitutionArgumentMappings &subst_mappings, location_t locus,
+ bool needs_bounds_check)
{
SubstitutionArg arg = SubstitutionArg::error ();
bool ok = subst_mappings.get_argument_for_symbol (get_param_ty (), &arg);
@@ -124,17 +163,21 @@ SubstitutionParamMapping::fill_param_ty (
if (type.get_kind () == TypeKind::PARAM)
{
- // delete param;
- param = static_cast<ParamType *> (type.clone ());
+ param = static_cast<BaseGeneric *> (type.clone ());
}
- else
+ else if (type.get_kind () == TyTy::TypeKind::CONST)
{
+ param = static_cast<BaseGeneric *> (type.clone ());
+ }
+ else if (param->get_kind () == TypeKind::PARAM)
+ {
+ auto &p = *static_cast<TyTy::ParamType *> (param);
+
// check the substitution is compatible with bounds
rust_debug_loc (locus,
"fill_param_ty bounds_compatible: param %s type %s",
param->get_name ().c_str (), type.get_name ().c_str ());
-
- if (!param->is_implicit_self_trait ())
+ if (needs_bounds_check && !p.is_implicit_self_trait ())
{
if (!param->bounds_compatible (type, locus, true))
return false;
@@ -145,7 +188,7 @@ SubstitutionParamMapping::fill_param_ty (
bound.handle_substitions (subst_mappings);
param->set_ty_ref (type.get_ref ());
- subst_mappings.on_param_subst (*param, arg);
+ subst_mappings.on_param_subst (p, arg);
}
return true;
@@ -191,12 +234,6 @@ SubstitutionArg::operator= (const SubstitutionArg &other)
}
BaseType *
-SubstitutionArg::get_tyty ()
-{
- return argument;
-}
-
-const BaseType *
SubstitutionArg::get_tyty () const
{
return argument;
@@ -208,7 +245,7 @@ SubstitutionArg::get_param_mapping () const
return param;
}
-const ParamType *
+const BaseGeneric *
SubstitutionArg::get_param_ty () const
{
return original_param;
@@ -313,11 +350,11 @@ SubstitutionArgumentMappings::is_error () const
bool
SubstitutionArgumentMappings::get_argument_for_symbol (
- const ParamType *param_to_find, SubstitutionArg *argument) const
+ const BaseGeneric *param_to_find, SubstitutionArg *argument) const
{
for (const auto &mapping : mappings)
{
- const ParamType *p = mapping.get_param_ty ();
+ const auto *p = mapping.get_param_ty ();
if (p->get_symbol () == param_to_find->get_symbol ())
{
*argument = mapping;
@@ -618,7 +655,6 @@ SubstitutionRef::get_mappings_from_generic_args (
if (args.get_binding_args ().size () > get_num_associated_bindings ())
{
rich_location r (line_table, args.get_locus ());
-
rust_error_at (r,
"generic item takes at most %lu type binding "
"arguments but %lu were supplied",
@@ -666,11 +702,17 @@ SubstitutionRef::get_mappings_from_generic_args (
// for inherited arguments
size_t offs = used_arguments.size ();
- if (args.get_type_args ().size () + offs > substitutions.size ())
+ size_t total_arguments
+ = args.get_type_args ().size () + args.get_const_args ().size () + offs;
+ if (total_arguments > substitutions.size ())
{
rich_location r (line_table, args.get_locus ());
if (!substitutions.empty ())
- r.add_range (substitutions.front ().get_param_locus ());
+ {
+ const auto &subst = substitutions.front ();
+ const auto &generic = subst.get_generic_param ();
+ r.add_range (generic.get_locus ());
+ }
rust_error_at (
r,
@@ -680,10 +722,15 @@ SubstitutionRef::get_mappings_from_generic_args (
return SubstitutionArgumentMappings::error ();
}
- if (args.get_type_args ().size () + offs < min_required_substitutions ())
+ if (total_arguments < min_required_substitutions ())
{
rich_location r (line_table, args.get_locus ());
- r.add_range (substitutions.front ().get_param_locus ());
+ if (!substitutions.empty ())
+ {
+ const auto &subst = substitutions.front ();
+ const auto &generic = subst.get_generic_param ();
+ r.add_range (generic.get_locus ());
+ }
rust_error_at (
r, ErrorCode::E0107,
@@ -702,7 +749,91 @@ SubstitutionRef::get_mappings_from_generic_args (
return SubstitutionArgumentMappings::error ();
}
- SubstitutionArg subst_arg (&substitutions.at (offs), resolved);
+ const auto &param_mapping = substitutions.at (offs);
+ const auto &generic = param_mapping.get_generic_param ();
+ if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
+ {
+ const auto &type_param
+ = static_cast<const HIR::TypeParam &> (generic);
+ if (type_param.from_impl_trait ())
+ {
+ rich_location r (line_table, arg->get_locus ());
+ r.add_fixit_remove (arg->get_locus ());
+ rust_error_at (r, ErrorCode::E0632,
+ "cannot provide explicit generic arguments when "
+ "%<impl Trait%> is used in argument position");
+ return SubstitutionArgumentMappings::error ();
+ }
+ }
+ else if (generic.get_kind () == HIR::GenericParam::GenericKind::CONST)
+ {
+ if (!resolved->is<ConstType> ())
+ {
+ rich_location r (line_table, arg->get_locus ());
+ r.add_fixit_remove (arg->get_locus ());
+ rust_error_at (r, ErrorCode::E0747,
+ "type provided when a constant was expected");
+ return SubstitutionArgumentMappings::error ();
+ }
+ }
+
+ SubstitutionArg subst_arg (&param_mapping, resolved);
+ offs++;
+ mappings.push_back (std::move (subst_arg));
+ }
+
+ for (auto &arg : args.get_const_args ())
+ {
+ auto &expr = *arg.get_expression ().get ();
+ BaseType *expr_type = Resolver::TypeCheckExpr::Resolve (expr);
+ if (expr_type == nullptr || expr_type->is<ErrorType> ())
+ return SubstitutionArgumentMappings::error ();
+
+ // validate this param is really a const generic
+ const auto &param_mapping = substitutions.at (offs);
+ const auto &generic = param_mapping.get_generic_param ();
+ if (generic.get_kind () != HIR::GenericParam::GenericKind::CONST)
+ {
+ rich_location r (line_table, arg.get_locus ());
+ r.add_fixit_remove (expr.get_locus ());
+ rust_error_at (r, "invalid position for a const generic argument");
+ return SubstitutionArgumentMappings::error ();
+ }
+
+ // get the const generic specified type
+ const auto base_generic = param_mapping.get_param_ty ();
+ rust_assert (base_generic->is<ConstType> ());
+ const auto const_param
+ = static_cast<const TyTy::ConstType *> (base_generic);
+ auto specified_type = const_param->get_ty ();
+
+ // validate this const generic is of the correct type
+ auto coereced_type
+ = Resolver::coercion_site (expr.get_mappings ().get_hirid (),
+ TyTy::TyWithLocation (specified_type),
+ TyTy::TyWithLocation (expr_type,
+ expr.get_locus ()),
+ arg.get_locus ());
+ if (coereced_type->is<ErrorType> ())
+ return SubstitutionArgumentMappings::error ();
+
+ // const fold it
+ auto ctx = Compile::Context::get ();
+ tree folded
+ = Compile::HIRCompileBase::query_compile_const_expr (ctx, coereced_type,
+ expr);
+
+ if (folded == error_mark_node)
+ return SubstitutionArgumentMappings::error ();
+
+ // create const type
+ auto const_value
+ = new TyTy::ConstType (TyTy::ConstType::ConstKind::Value, "",
+ coereced_type, folded, {}, expr.get_locus (),
+ expr.get_mappings ().get_hirid (),
+ expr.get_mappings ().get_hirid (), {});
+
+ SubstitutionArg subst_arg (&param_mapping, const_value);
offs++;
mappings.push_back (std::move (subst_arg));
}
@@ -754,6 +885,7 @@ SubstitutionRef::infer_substitions (location_t locus)
{
if (p.needs_substitution ())
{
+ const HIR::GenericParam &generic = p.get_generic_param ();
const std::string &symbol = p.get_param_ty ()->get_symbol ();
auto it = argument_mappings.find (symbol);
bool have_mapping = it != argument_mappings.end ();
@@ -762,12 +894,24 @@ SubstitutionRef::infer_substitions (location_t locus)
{
args.push_back (SubstitutionArg (&p, it->second));
}
- else
+ else if (generic.get_kind () == HIR::GenericParam::GenericKind::TYPE)
{
TyVar infer_var = TyVar::get_implicit_infer_var (locus);
args.push_back (SubstitutionArg (&p, infer_var.get_tyty ()));
argument_mappings[symbol] = infer_var.get_tyty ();
}
+ else if (generic.get_kind () == HIR::GenericParam::GenericKind::CONST)
+ {
+ const auto const_param = p.get_param_ty ();
+ rust_assert (const_param->is<TyTy::ConstType> ());
+ const auto &const_type
+ = *static_cast<const TyTy::ConstType *> (const_param);
+
+ TyVar infer_var
+ = TyVar::get_implicit_const_infer_var (const_type, locus);
+ args.push_back (SubstitutionArg (&p, infer_var.get_tyty ()));
+ argument_mappings[symbol] = infer_var.get_tyty ();
+ }
}
else
{
@@ -905,7 +1049,7 @@ SubstitutionRef::prepare_higher_ranked_bounds ()
{
for (const auto &subst : get_substs ())
{
- const TyTy::ParamType *pty = subst.get_param_ty ();
+ const auto pty = subst.get_param_ty ();
for (const auto &bound : pty->get_specified_bounds ())
{
const auto ref = bound.get ();
@@ -919,8 +1063,7 @@ SubstitutionRef::monomorphize ()
{
for (const auto &subst : get_substs ())
{
- const TyTy::ParamType *pty = subst.get_param_ty ();
-
+ const auto pty = subst.get_param_ty ();
if (!pty->can_resolve ())
continue;
diff --git a/gcc/rust/typecheck/rust-tyty-subst.h b/gcc/rust/typecheck/rust-tyty-subst.h
index e6ed1fc..c1bc96a 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.h
+++ b/gcc/rust/typecheck/rust-tyty-subst.h
@@ -24,12 +24,14 @@
#include "rust-hir-full-decls.h"
#include "rust-tyty-bounds.h"
#include "rust-tyty-region.h"
+#include "rust-ast.h"
#include "optional.h"
namespace Rust {
namespace TyTy {
class ParamType;
+class BaseGeneric;
struct RegionConstraints
{
@@ -44,22 +46,24 @@ class SubstitutionArgumentMappings;
class SubstitutionParamMapping
{
public:
- SubstitutionParamMapping (HIR::TypeParam &generic, ParamType *param);
+ SubstitutionParamMapping (HIR::GenericParam &generic, BaseGeneric *param);
SubstitutionParamMapping (const SubstitutionParamMapping &other);
std::string as_string () const;
bool fill_param_ty (SubstitutionArgumentMappings &subst_mappings,
- location_t locus);
+ location_t locus, bool needs_bounds_check = true);
SubstitutionParamMapping clone () const;
- ParamType *get_param_ty ();
+ BaseGeneric *get_param_ty ();
+ const BaseGeneric *get_param_ty () const;
- const ParamType *get_param_ty () const;
+ HIR::GenericParam &get_generic_param ();
+ const HIR::GenericParam &get_generic_param () const;
- HIR::TypeParam &get_generic_param ();
+ Identifier get_type_representation () const;
// 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,8 +80,8 @@ public:
bool need_substitution () const;
private:
- HIR::TypeParam &generic;
- ParamType *param;
+ HIR::GenericParam &generic;
+ BaseGeneric *param;
};
/**
@@ -147,13 +151,11 @@ public:
SubstitutionArg &operator= (const SubstitutionArg &other);
- BaseType *get_tyty ();
-
- const BaseType *get_tyty () const;
+ BaseType *get_tyty () const;
const SubstitutionParamMapping *get_param_mapping () const;
- const ParamType *get_param_ty () const;
+ const BaseGeneric *get_param_ty () const;
static SubstitutionArg error ();
@@ -165,7 +167,7 @@ public:
private:
const SubstitutionParamMapping *param;
- const ParamType *original_param;
+ const BaseGeneric *original_param;
BaseType *argument;
};
@@ -205,7 +207,7 @@ public:
bool is_error () const;
- bool get_argument_for_symbol (const ParamType *param_to_find,
+ bool get_argument_for_symbol (const BaseGeneric *param_to_find,
SubstitutionArg *argument) const;
/** Return type parameter index for symbol */
diff --git a/gcc/rust/typecheck/rust-tyty-util.cc b/gcc/rust/typecheck/rust-tyty-util.cc
index ff210ce..4bc1723 100644
--- a/gcc/rust/typecheck/rust-tyty-util.cc
+++ b/gcc/rust/typecheck/rust-tyty-util.cc
@@ -17,6 +17,8 @@
// <http://www.gnu.org/licenses/>.
#include "rust-hir-type-check.h"
+#include "rust-mapping-common.h"
+#include "rust-system.h"
#include "rust-tyty.h"
namespace Rust {
@@ -47,14 +49,30 @@ TyVar::get_implicit_infer_var (location_t locus)
auto &mappings = Analysis::Mappings::get ();
auto context = Resolver::TypeCheckContext::get ();
- InferType *infer = new InferType (mappings.get_next_hir_id (),
- InferType::InferTypeKind::GENERAL,
- InferType::TypeHint::Default (), locus);
- context->insert_type (Analysis::NodeMapping (mappings.get_current_crate (),
- UNKNOWN_NODEID,
- infer->get_ref (),
- UNKNOWN_LOCAL_DEFID),
- infer);
+ HirId next = mappings.get_next_hir_id ();
+ auto infer = new InferType (next, InferType::InferTypeKind::GENERAL,
+ InferType::TypeHint::Default (), locus);
+
+ context->insert_implicit_type (infer->get_ref (), infer);
+ mappings.insert_location (infer->get_ref (), locus);
+
+ return TyVar (infer->get_ref ());
+}
+
+TyVar
+TyVar::get_implicit_const_infer_var (const ConstType &const_type,
+ location_t locus)
+{
+ auto &mappings = Analysis::Mappings::get ();
+ auto context = Resolver::TypeCheckContext::get ();
+
+ HirId next = mappings.get_next_hir_id ();
+ auto infer
+ = new ConstType (ConstType::ConstKind::Infer, const_type.get_symbol (),
+ const_type.get_ty (), error_mark_node,
+ const_type.get_specified_bounds (), locus, next, next, {});
+
+ context->insert_implicit_type (infer->get_ref (), infer);
mappings.insert_location (infer->get_ref (), locus);
return TyVar (infer->get_ref ());
diff --git a/gcc/rust/typecheck/rust-tyty-util.h b/gcc/rust/typecheck/rust-tyty-util.h
index cbb3e8e..1c8fd72 100644
--- a/gcc/rust/typecheck/rust-tyty-util.h
+++ b/gcc/rust/typecheck/rust-tyty-util.h
@@ -25,6 +25,7 @@ namespace Rust {
namespace TyTy {
class BaseType;
+class ConstType;
// this is a placeholder for types that can change like inference variables
class TyVar
@@ -42,6 +43,9 @@ public:
static TyVar get_implicit_infer_var (location_t locus);
+ static TyVar get_implicit_const_infer_var (const TyTy::ConstType &const_type,
+ location_t locus);
+
static TyVar subst_covariant_var (TyTy::BaseType *orig,
TyTy::BaseType *subst);
diff --git a/gcc/rust/typecheck/rust-tyty-variance-analysis-private.h b/gcc/rust/typecheck/rust-tyty-variance-analysis-private.h
index d36afc8..deb76a7 100644
--- a/gcc/rust/typecheck/rust-tyty-variance-analysis-private.h
+++ b/gcc/rust/typecheck/rust-tyty-variance-analysis-private.h
@@ -170,6 +170,8 @@ public:
}
void visit (OpaqueType &type) override {}
+
+ void visit (ConstType &type) override {}
};
/** Per crate context for generic type variance analysis. */
diff --git a/gcc/rust/typecheck/rust-tyty-variance-analysis.cc b/gcc/rust/typecheck/rust-tyty-variance-analysis.cc
index 38f9d52..7971ccf 100644
--- a/gcc/rust/typecheck/rust-tyty-variance-analysis.cc
+++ b/gcc/rust/typecheck/rust-tyty-variance-analysis.cc
@@ -199,9 +199,7 @@ GenericTyPerCrateCtx::debug_print_solutions ()
{
if (i > solution_index)
result += ", ";
- result += param.get_generic_param ()
- .get_type_representation ()
- .as_string ();
+ result += param.get_type_representation ().as_string ();
result += "=";
result += solutions[i].as_string ();
i++;
@@ -239,8 +237,7 @@ GenericTyVisitorCtx::process_type (ADTType &ty)
first_type = first_lifetime + ty.get_used_arguments ().get_regions ().size ();
for (auto &param : ty.get_substs ())
- param_names.push_back (
- param.get_generic_param ().get_type_representation ().as_string ());
+ param_names.push_back (param.get_type_representation ().as_string ());
for (const auto &variant : ty.get_variants ())
{
diff --git a/gcc/rust/typecheck/rust-tyty-variance-analysis.h b/gcc/rust/typecheck/rust-tyty-variance-analysis.h
index 9059a2f..282c6f3 100644
--- a/gcc/rust/typecheck/rust-tyty-variance-analysis.h
+++ b/gcc/rust/typecheck/rust-tyty-variance-analysis.h
@@ -41,9 +41,10 @@ private:
std::unique_ptr<GenericTyPerCrateCtx> private_ctx;
};
-std::vector<size_t>
-query_field_regions (const ADTType *parent, size_t variant_index,
- size_t field_index, const FreeRegions &parent_regions);
+std::vector<size_t> query_field_regions (const ADTType *parent,
+ size_t variant_index,
+ size_t field_index,
+ const FreeRegions &parent_regions);
/** Variance semilattice */
class Variance
diff --git a/gcc/rust/typecheck/rust-tyty-visitor.h b/gcc/rust/typecheck/rust-tyty-visitor.h
index 4f8e7856..7783075 100644
--- a/gcc/rust/typecheck/rust-tyty-visitor.h
+++ b/gcc/rust/typecheck/rust-tyty-visitor.h
@@ -45,6 +45,7 @@ public:
virtual void visit (ReferenceType &type) = 0;
virtual void visit (PointerType &type) = 0;
virtual void visit (ParamType &type) = 0;
+ virtual void visit (ConstType &type) = 0;
virtual void visit (StrType &type) = 0;
virtual void visit (NeverType &type) = 0;
virtual void visit (PlaceholderType &type) = 0;
@@ -75,6 +76,7 @@ public:
virtual void visit (const ReferenceType &type) = 0;
virtual void visit (const PointerType &type) = 0;
virtual void visit (const ParamType &type) = 0;
+ virtual void visit (const ConstType &type) = 0;
virtual void visit (const StrType &type) = 0;
virtual void visit (const NeverType &type) = 0;
virtual void visit (const PlaceholderType &type) = 0;
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index f0f4a07..db96773 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -19,6 +19,7 @@
#include "rust-tyty.h"
#include "optional.h"
+#include "rust-tyty-subst.h"
#include "rust-tyty-visitor.h"
#include "rust-hir-map.h"
#include "rust-location.h"
@@ -30,9 +31,14 @@
#include "rust-tyty-cmp.h"
#include "rust-type-util.h"
#include "rust-hir-type-bounds.h"
+#include "print-tree.h"
+#include "tree-pretty-print.h"
#include "options.h"
#include "rust-system.h"
+#include "tree.h"
+#include "fold-const.h"
+#include <string>
namespace Rust {
namespace TyTy {
@@ -114,6 +120,9 @@ TypeKindFormat::to_string (TypeKind kind)
case TypeKind::OPAQUE:
return "Opaque";
+ case TypeKind::CONST:
+ return "Const";
+
case TypeKind::ERROR:
return "ERROR";
}
@@ -223,6 +232,7 @@ BaseType::is_unit () const
case OPAQUE:
case STR:
case DYNAMIC:
+ case CONST:
case ERROR:
return false;
@@ -230,11 +240,13 @@ BaseType::is_unit () const
case NEVER:
return true;
- case TUPLE: {
+ case TUPLE:
+ {
return x->as<const TupleType> ()->num_fields () == 0;
}
- case ADT: {
+ case ADT:
+ {
auto adt = x->as<const ADTType> ();
if (adt->is_enum ())
return false;
@@ -438,11 +450,10 @@ BaseType::inherit_bounds (
}
}
-const BaseType *
-BaseType::get_root () const
+BaseType *
+BaseType::get_root ()
{
- // FIXME this needs to be it its own visitor class with a vector adjustments
- const TyTy::BaseType *root = this;
+ TyTy::BaseType *root = this;
if (const auto r = root->try_as<const ReferenceType> ())
{
@@ -546,17 +557,14 @@ BaseType::destructure () const
{
x = p->get ();
}
- // else if (auto p = x->try_as<const OpaqueType> ())
- // {
- // auto pr = p->resolve ();
-
- // rust_debug ("XXXXXX")
-
- // if (pr == x)
- // return pr;
+ else if (auto p = x->try_as<const OpaqueType> ())
+ {
+ auto pr = p->resolve ();
+ if (pr == x)
+ return pr;
- // x = pr;
- // }
+ x = pr;
+ }
else
{
return x;
@@ -575,7 +583,7 @@ BaseType::monomorphized_clone () const
{
TyVar elm = arr->get_var_element_type ().monomorphized_clone ();
return new ArrayType (arr->get_ref (), arr->get_ty_ref (), ident.locus,
- arr->get_capacity_expr (), elm,
+ arr->get_capacity (), elm,
arr->get_combined_refs ());
}
else if (auto slice = x->try_as<const SliceType> ())
@@ -824,7 +832,8 @@ BaseType::is_concrete () const
}
else if (auto arr = x->try_as<const ArrayType> ())
{
- return arr->get_element_type ()->is_concrete ();
+ return arr->get_element_type ()->is_concrete ()
+ && arr->get_capacity ()->is_concrete ();
}
else if (auto slice = x->try_as<const SliceType> ())
{
@@ -853,6 +862,10 @@ BaseType::is_concrete () const
return false;
return closure->get_result_type ().is_concrete ();
}
+ else if (auto const_type = x->try_as<const ConstType> ())
+ {
+ return const_type->get_value () != error_mark_node;
+ }
else if (x->is<InferType> () || x->is<BoolType> () || x->is<CharType> ()
|| x->is<IntType> () || x->is<UintType> () || x->is<FloatType> ()
|| x->is<USizeType> () || x->is<ISizeType> () || x->is<NeverType> ()
@@ -891,31 +904,36 @@ BaseType::has_substitutions_defined () const
case TUPLE:
case PARAM:
case PLACEHOLDER:
+ case CONST:
case OPAQUE:
return false;
- case PROJECTION: {
+ case PROJECTION:
+ {
const ProjectionType &p = *static_cast<const ProjectionType *> (x);
const SubstitutionRef &ref = static_cast<const SubstitutionRef &> (p);
return ref.has_substitutions ();
}
break;
- case FNDEF: {
+ case FNDEF:
+ {
const FnType &fn = *static_cast<const FnType *> (x);
const SubstitutionRef &ref = static_cast<const SubstitutionRef &> (fn);
return ref.has_substitutions ();
}
break;
- case ADT: {
+ case ADT:
+ {
const ADTType &adt = *static_cast<const ADTType *> (x);
const SubstitutionRef &ref = static_cast<const SubstitutionRef &> (adt);
return ref.has_substitutions ();
}
break;
- case CLOSURE: {
+ case CLOSURE:
+ {
const ClosureType &closure = *static_cast<const ClosureType *> (x);
const SubstitutionRef &ref
= static_cast<const SubstitutionRef &> (closure);
@@ -953,31 +971,36 @@ BaseType::needs_generic_substitutions () const
case TUPLE:
case PARAM:
case PLACEHOLDER:
+ case CONST:
case OPAQUE:
return false;
- case PROJECTION: {
+ case PROJECTION:
+ {
const ProjectionType &p = *static_cast<const ProjectionType *> (x);
const SubstitutionRef &ref = static_cast<const SubstitutionRef &> (p);
return ref.needs_substitution ();
}
break;
- case FNDEF: {
+ case FNDEF:
+ {
const FnType &fn = *static_cast<const FnType *> (x);
const SubstitutionRef &ref = static_cast<const SubstitutionRef &> (fn);
return ref.needs_substitution ();
}
break;
- case ADT: {
+ case ADT:
+ {
const ADTType &adt = *static_cast<const ADTType *> (x);
const SubstitutionRef &ref = static_cast<const SubstitutionRef &> (adt);
return ref.needs_substitution ();
}
break;
- case CLOSURE: {
+ case CLOSURE:
+ {
const ClosureType &closure = *static_cast<const ClosureType *> (x);
const SubstitutionRef &ref
= static_cast<const SubstitutionRef &> (closure);
@@ -996,28 +1019,32 @@ BaseType::get_subst_argument_mappings () const
const TyTy::BaseType *x = destructure ();
switch (x->get_kind ())
{
- case PROJECTION: {
+ case PROJECTION:
+ {
const auto &p = *static_cast<const ProjectionType *> (x);
const auto &ref = static_cast<const SubstitutionRef &> (p);
return ref.get_substitution_arguments ();
}
break;
- case FNDEF: {
+ case FNDEF:
+ {
const auto &fn = *static_cast<const FnType *> (x);
const auto &ref = static_cast<const SubstitutionRef &> (fn);
return ref.get_substitution_arguments ();
}
break;
- case ADT: {
+ case ADT:
+ {
const auto &adt = *static_cast<const ADTType *> (x);
const auto &ref = static_cast<const SubstitutionRef &> (adt);
return ref.get_substitution_arguments ();
}
break;
- case CLOSURE: {
+ case CLOSURE:
+ {
const auto &closure = *static_cast<const ClosureType *> (x);
const auto &ref = static_cast<const SubstitutionRef &> (closure);
return ref.get_substitution_arguments ();
@@ -1140,13 +1167,15 @@ InferType::default_type (BaseType **type) const
case GENERAL:
return false;
- case INTEGRAL: {
+ case INTEGRAL:
+ {
ok = context->lookup_builtin ("i32", type);
rust_assert (ok);
return ok;
}
- case FLOAT: {
+ case FLOAT:
+ {
ok = context->lookup_builtin ("f64", type);
rust_assert (ok);
return ok;
@@ -1269,7 +1298,8 @@ InferType::apply_primitive_type_hint (const BaseType &hint)
default_hint.kind = hint.get_kind ();
break;
- case INT: {
+ case INT:
+ {
infer_kind = INTEGRAL;
default_hint.kind = hint.get_kind ();
default_hint.shint = TypeHint::SignedHint::SIGNED;
@@ -1294,7 +1324,8 @@ InferType::apply_primitive_type_hint (const BaseType &hint)
}
break;
- case UINT: {
+ case UINT:
+ {
infer_kind = INTEGRAL;
default_hint.kind = hint.get_kind ();
default_hint.shint = TypeHint::SignedHint::UNSIGNED;
@@ -1319,7 +1350,8 @@ InferType::apply_primitive_type_hint (const BaseType &hint)
}
break;
- case TypeKind::FLOAT: {
+ case TypeKind::FLOAT:
+ {
infer_kind = FLOAT;
default_hint.shint = TypeHint::SignedHint::SIGNED;
default_hint.kind = hint.get_kind ();
@@ -1800,11 +1832,9 @@ ADTType::is_equal (const BaseType &other) const
const SubstitutionParamMapping &a = substitutions.at (i);
const SubstitutionParamMapping &b = other2->substitutions.at (i);
- const ParamType *aa = a.get_param_ty ();
- const ParamType *bb = b.get_param_ty ();
- BaseType *aaa = aa->resolve ();
- BaseType *bbb = bb->resolve ();
- if (!aaa->is_equal (*bbb))
+ const auto &aa = a.get_param_ty ();
+ const auto &bb = b.get_param_ty ();
+ if (!aa->is_equal (*bb))
return false;
}
}
@@ -1992,7 +2022,7 @@ TupleType::get_name () const
std::string fields_buffer;
for (const TyVar &field : get_fields ())
{
- fields_buffer += field.get_tyty ()->as_string ();
+ fields_buffer += field.get_tyty ()->get_name ();
bool has_next = (i + 1) < get_fields ().size ();
fields_buffer += has_next ? ", " : "";
i++;
@@ -2129,9 +2159,8 @@ FnType::is_equal (const BaseType &other) const
const SubstitutionParamMapping &a = get_substs ().at (i);
const SubstitutionParamMapping &b = ofn.get_substs ().at (i);
- const ParamType *pa = a.get_param_ty ();
- const ParamType *pb = b.get_param_ty ();
-
+ const auto *pa = a.get_param_ty ();
+ const auto *pb = b.get_param_ty ();
if (!pa->is_equal (*pb))
return false;
}
@@ -2470,7 +2499,8 @@ ArrayType::accept_vis (TyConstVisitor &vis) const
std::string
ArrayType::as_string () const
{
- return "[" + get_element_type ()->as_string () + ":" + "CAPACITY" + "]";
+ return "[" + get_element_type ()->as_string () + "; " + capacity->as_string ()
+ + "]";
}
bool
@@ -2509,7 +2539,7 @@ ArrayType::get_var_element_type () const
BaseType *
ArrayType::clone () const
{
- return new ArrayType (get_ref (), get_ty_ref (), ident.locus, capacity_expr,
+ return new ArrayType (get_ref (), get_ty_ref (), ident.locus, capacity,
element_type, get_combined_refs ());
}
@@ -2526,6 +2556,13 @@ ArrayType::handle_substitions (SubstitutionArgumentMappings &mappings)
BaseType *concrete = Resolver::SubstMapperInternal::Resolve (base, mappings);
ref->element_type = TyVar::subst_covariant_var (base, concrete);
+ // handle capacity type
+ auto cap = ref->get_capacity ();
+ BaseType *concrete_cap
+ = Resolver::SubstMapperInternal::Resolve (cap, mappings);
+ rust_assert (concrete_cap->get_kind () == TyTy::TypeKind::CONST);
+ ref->capacity = static_cast<TyTy::ConstType *> (concrete_cap);
+
return ref;
}
@@ -3382,33 +3419,26 @@ PointerType::handle_substitions (SubstitutionArgumentMappings &mappings)
// PARAM Type
ParamType::ParamType (std::string symbol, location_t locus, HirId ref,
- HIR::GenericParam &param,
std::vector<TypeBoundPredicate> specified_bounds,
std::set<HirId> refs)
- : BaseType (ref, ref, KIND,
- {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
- locus},
- specified_bounds, refs),
- is_trait_self (false), symbol (symbol), param (param)
+ : BaseGeneric (ref, ref, KIND,
+ {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
+ locus},
+ specified_bounds, refs),
+ is_trait_self (false), symbol (symbol)
{}
ParamType::ParamType (bool is_trait_self, std::string symbol, location_t locus,
- HirId ref, HirId ty_ref, HIR::GenericParam &param,
+ HirId ref, HirId ty_ref,
std::vector<TypeBoundPredicate> specified_bounds,
std::set<HirId> refs)
- : BaseType (ref, ty_ref, KIND,
- {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
- locus},
- specified_bounds, refs),
- is_trait_self (is_trait_self), symbol (symbol), param (param)
+ : BaseGeneric (ref, ty_ref, KIND,
+ {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
+ locus},
+ specified_bounds, refs),
+ is_trait_self (is_trait_self), symbol (symbol)
{}
-HIR::GenericParam &
-ParamType::get_generic_param ()
-{
- return param;
-}
-
bool
ParamType::can_resolve () const
{
@@ -3459,7 +3489,7 @@ BaseType *
ParamType::clone () const
{
return new ParamType (is_trait_self, get_symbol (), ident.locus, get_ref (),
- get_ty_ref (), param, get_specified_bounds (),
+ get_ty_ref (), get_specified_bounds (),
get_combined_refs ());
}
@@ -3529,12 +3559,12 @@ ParamType::handle_substitions (SubstitutionArgumentMappings &subst_mappings)
ParamType *p = static_cast<ParamType *> (clone ());
subst_mappings.on_param_subst (*p, arg);
- // there are two cases one where we substitute directly to a new PARAM and
- // otherwise
- if (arg.get_tyty ()->get_kind () == TyTy::TypeKind::PARAM)
+ const BaseType *resolved = arg.get_tyty ();
+ if (resolved->get_kind () == TyTy::TypeKind::PARAM)
{
- p->set_ty_ref (arg.get_tyty ()->get_ref ());
- return p;
+ const ParamType &pp = *static_cast<const ParamType *> (resolved);
+ if (pp.can_resolve ())
+ resolved = pp.resolve ();
}
// this is the new subst that this needs to pass
@@ -3556,6 +3586,157 @@ ParamType::is_implicit_self_trait () const
return is_trait_self;
}
+// ConstType
+
+ConstType::ConstType (ConstKind kind, std::string symbol, TyTy::BaseType *ty,
+ tree value,
+ std::vector<TypeBoundPredicate> specified_bounds,
+ location_t locus, HirId ref, HirId ty_ref,
+ std::set<HirId> refs)
+ : BaseGeneric (ref, ty_ref, KIND,
+ {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID,
+ symbol.empty () ? "<n/a>"
+ : symbol),
+ locus},
+ specified_bounds, refs),
+ const_kind (kind), ty (ty), value (value), symbol (symbol)
+{}
+
+void
+ConstType::accept_vis (TyVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
+ConstType::accept_vis (TyConstVisitor &vis) const
+{
+ vis.visit (*this);
+}
+
+void
+ConstType::set_value (tree v)
+{
+ value = v;
+ const_kind = ConstType::ConstKind::Value;
+}
+
+std::string
+ConstType::as_string () const
+{
+ return get_name ();
+}
+
+bool
+ConstType::can_eq (const BaseType *other, bool emit_errors) const
+{
+ ConstCmp r (this, emit_errors);
+ return r.can_eq (other);
+}
+
+BaseType *
+ConstType::clone () const
+{
+ return new ConstType (const_kind, symbol, ty, value, get_specified_bounds (),
+ ident.locus, ref, ty_ref, get_combined_refs ());
+}
+
+std::string
+ConstType::get_symbol () const
+{
+ return symbol;
+}
+
+bool
+ConstType::can_resolve () const
+{
+ return false;
+}
+
+BaseType *
+ConstType::resolve () const
+{
+ rust_unreachable ();
+ return nullptr;
+}
+
+static std::string
+generate_tree_str (tree value)
+{
+ char *buf = nullptr;
+ size_t size = 0;
+
+ FILE *stream = open_memstream (&buf, &size);
+ if (!stream)
+ return "<error>";
+
+ print_generic_stmt (stream, value, TDF_NONE);
+ fclose (stream);
+
+ std::string result = (buf ? std::string (buf, size) : "<error>");
+ free (buf);
+
+ if (!result.empty () && result.back () == '\n')
+ result.pop_back ();
+
+ return result;
+}
+
+std::string
+ConstType::get_name () const
+{
+ if (value == error_mark_node)
+ {
+ switch (get_const_kind ())
+ {
+ case Rust::TyTy::ConstType::Decl:
+ return "ConstType:<" + get_ty ()->get_name () + " " + get_symbol ()
+ + ">";
+
+ case Rust::TyTy::ConstType::Infer:
+ return "ConstType:<" + get_ty ()->get_name () + " ?" + ">";
+
+ default:
+ return "ConstType:<" + get_ty ()->get_name () + " - <error>" + ">";
+ }
+ }
+
+ return generate_tree_str (value);
+}
+
+bool
+ConstType::is_equal (const BaseType &other) const
+{
+ if (get_kind () != other.get_kind ())
+ {
+ return false;
+ }
+
+ const ConstType &rhs = static_cast<const ConstType &> (other);
+ if (!get_ty ()->is_equal (*rhs.get_ty ()))
+ return false;
+
+ tree lv = get_value ();
+ tree rv = rhs.get_value ();
+
+ return operand_equal_p (lv, rv, 0);
+}
+
+ConstType *
+ConstType::handle_substitions (SubstitutionArgumentMappings &mappings)
+{
+ SubstitutionArg arg = SubstitutionArg::error ();
+ bool found = mappings.get_argument_for_symbol (this, &arg);
+ if (found && !arg.is_error ())
+ {
+ TyTy::BaseType *subst = arg.get_tyty ();
+ rust_assert (subst->is<TyTy::ConstType> ());
+ return static_cast<TyTy::ConstType *> (subst);
+ }
+
+ return this;
+}
+
// OpaqueType
OpaqueType::OpaqueType (location_t locus, HirId ref,
@@ -3624,28 +3805,7 @@ BaseType *
OpaqueType::resolve () const
{
TyVar var (get_ty_ref ());
- BaseType *r = var.get_tyty ();
-
- while (r->get_kind () == TypeKind::OPAQUE)
- {
- OpaqueType *rr = static_cast<OpaqueType *> (r);
- if (!rr->can_resolve ())
- break;
-
- TyVar v (rr->get_ty_ref ());
- BaseType *n = v.get_tyty ();
-
- // fix infinite loop
- if (r == n)
- break;
-
- r = n;
- }
-
- if (r->get_kind () == TypeKind::OPAQUE && (r->get_ref () == r->get_ty_ref ()))
- return TyVar (r->get_ty_ref ()).get_tyty ();
-
- return r;
+ return var.get_tyty ();
}
bool
@@ -3655,41 +3815,9 @@ OpaqueType::is_equal (const BaseType &other) const
if (can_resolve () != other2.can_resolve ())
return false;
- if (can_resolve ())
- return resolve ()->can_eq (other2.resolve (), false);
-
return bounds_compatible (other, UNDEF_LOCATION, false);
}
-OpaqueType *
-OpaqueType::handle_substitions (SubstitutionArgumentMappings &subst_mappings)
-{
- // SubstitutionArg arg = SubstitutionArg::error ();
- // bool ok = subst_mappings.get_argument_for_symbol (this, &arg);
- // if (!ok || arg.is_error ())
- // return this;
-
- // OpaqueType *p = static_cast<OpaqueType *> (clone ());
- // subst_mappings.on_param_subst (*p, arg);
-
- // // there are two cases one where we substitute directly to a new PARAM and
- // // otherwise
- // if (arg.get_tyty ()->get_kind () == TyTy::TypeKind::PARAM)
- // {
- // p->set_ty_ref (arg.get_tyty ()->get_ref ());
- // return p;
- // }
-
- // // this is the new subst that this needs to pass
- // p->set_ref (mappings.get_next_hir_id ());
- // p->set_ty_ref (arg.get_tyty ()->get_ref ());
-
- // return p;
-
- rust_unreachable ();
- return nullptr;
-}
-
// StrType
StrType::StrType (HirId ref, std::set<HirId> refs)
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 1cada9a..49415ea 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -19,6 +19,7 @@
#ifndef RUST_TYTY
#define RUST_TYTY
+#include "optional.h"
#include "rust-hir-map.h"
#include "rust-common.h"
#include "rust-identifier.h"
@@ -29,6 +30,7 @@
#include "rust-tyty-region.h"
#include "rust-system.h"
#include "rust-hir.h"
+#include "tree.h"
namespace Rust {
@@ -56,6 +58,7 @@ enum TypeKind
REF,
POINTER,
PARAM,
+ CONST,
ARRAY,
SLICE,
FNDEF,
@@ -78,8 +81,7 @@ enum TypeKind
ERROR
};
-extern bool
-is_primitive_type_kind (TypeKind kind);
+extern bool is_primitive_type_kind (TypeKind kind);
class TypeKindFormat
{
@@ -165,8 +167,7 @@ public:
void debug () const;
- // FIXME this will eventually go away
- const BaseType *get_root () const;
+ BaseType *get_root ();
// This will get the monomorphized type from Params, Placeholders or
// Projections if available or error
@@ -268,8 +269,8 @@ public:
{}
WARN_UNUSED_RESULT virtual size_t get_num_params () const = 0;
- WARN_UNUSED_RESULT virtual BaseType *
- get_param_type_at (size_t index) const = 0;
+ WARN_UNUSED_RESULT virtual BaseType *get_param_type_at (size_t index) const
+ = 0;
WARN_UNUSED_RESULT virtual BaseType *get_return_type () const = 0;
};
@@ -365,18 +366,34 @@ public:
std::string get_name () const override final;
};
-class ParamType : public BaseType
+class BaseGeneric : public BaseType
+{
+public:
+ virtual std::string get_symbol () const = 0;
+
+ virtual bool can_resolve () const = 0;
+
+ virtual BaseType *resolve () const = 0;
+
+protected:
+ BaseGeneric (HirId ref, HirId ty_ref, TypeKind kind, RustIdent ident,
+ std::vector<TypeBoundPredicate> specified_bounds,
+ std::set<HirId> refs = std::set<HirId> ())
+ : BaseType (ref, ty_ref, kind, ident, specified_bounds, refs)
+ {}
+};
+
+class ParamType : public BaseGeneric
{
public:
static constexpr auto KIND = TypeKind::PARAM;
ParamType (std::string symbol, location_t locus, HirId ref,
- HIR::GenericParam &param,
std::vector<TypeBoundPredicate> specified_bounds,
std::set<HirId> refs = std::set<HirId> ());
ParamType (bool is_trait_self, std::string symbol, location_t locus,
- HirId ref, HirId ty_ref, HIR::GenericParam &param,
+ HirId ref, HirId ty_ref,
std::vector<TypeBoundPredicate> specified_bounds,
std::set<HirId> refs = std::set<HirId> ());
@@ -389,13 +406,11 @@ public:
BaseType *clone () const final override;
- std::string get_symbol () const;
-
- HIR::GenericParam &get_generic_param ();
+ std::string get_symbol () const override final;
- bool can_resolve () const;
+ bool can_resolve () const override final;
- BaseType *resolve () const;
+ BaseType *resolve () const override final;
std::string get_name () const override final;
@@ -409,7 +424,58 @@ public:
private:
bool is_trait_self;
std::string symbol;
- HIR::GenericParam &param;
+};
+
+class ConstType : public BaseGeneric
+{
+public:
+ static constexpr auto KIND = TypeKind::CONST;
+
+ enum ConstKind
+ {
+ Decl,
+ Value,
+ Infer,
+ Error
+ };
+
+ ConstType (ConstKind kind, std::string symbol, TyTy::BaseType *ty, tree value,
+ std::vector<TypeBoundPredicate> specified_bounds, location_t locus,
+ HirId ref, HirId ty_ref,
+ std::set<HirId> refs = std::set<HirId> ());
+
+ void accept_vis (TyVisitor &vis) override;
+ void accept_vis (TyConstVisitor &vis) const override;
+
+ ConstKind get_const_kind () const { return const_kind; }
+ TyTy::BaseType *get_ty () const { return ty; }
+ tree get_value () const { return value; }
+
+ void set_value (tree value);
+
+ std::string as_string () const override;
+
+ bool can_eq (const BaseType *other, bool emit_errors) const override final;
+
+ BaseType *clone () const final override;
+
+ std::string get_symbol () const override final;
+
+ bool can_resolve () const override final;
+
+ BaseType *resolve () const override final;
+
+ std::string get_name () const override final;
+
+ bool is_equal (const BaseType &other) const override;
+
+ ConstType *handle_substitions (SubstitutionArgumentMappings &mappings);
+
+private:
+ ConstKind const_kind;
+ TyTy::BaseType *ty;
+ tree value;
+ std::string symbol;
};
class OpaqueType : public BaseType
@@ -441,8 +507,6 @@ public:
std::string get_name () const override final;
bool is_equal (const BaseType &other) const override;
-
- OpaqueType *handle_substitions (SubstitutionArgumentMappings &mappings);
};
class StructFieldType
@@ -541,14 +605,15 @@ public:
std::string get_name () const;
- // check that this predicate is object-safe see:
+ // check that this is object-safe see:
// https://doc.rust-lang.org/reference/items/traits.html#object-safety
bool is_object_safe (bool emit_error, location_t locus) const;
void apply_generic_arguments (HIR::GenericArgs *generic_args,
- bool has_associated_self);
+ bool has_associated_self, bool is_super_trait);
- void apply_argument_mappings (SubstitutionArgumentMappings &arguments);
+ void apply_argument_mappings (SubstitutionArgumentMappings &arguments,
+ bool is_super_trait);
bool contains_item (const std::string &search) const;
@@ -596,6 +661,9 @@ private:
TypeBoundPredicate (mark_is_error);
+ void get_trait_hierachy (
+ std::function<void (const Resolver::TraitReference &)> callback) const;
+
DefId reference;
location_t locus;
bool error_flag;
@@ -1156,19 +1224,18 @@ class ArrayType : public BaseType
public:
static constexpr auto KIND = TypeKind::ARRAY;
- ArrayType (HirId ref, location_t locus, HIR::Expr &capacity_expr, TyVar base,
+ ArrayType (HirId ref, location_t locus, ConstType *capacity, TyVar base,
std::set<HirId> refs = std::set<HirId> ())
: BaseType (ref, ref, TypeKind::ARRAY,
{Resolver::CanonicalPath::create_empty (), locus}, refs),
- element_type (base), capacity_expr (capacity_expr)
+ element_type (base), capacity (capacity)
{}
- ArrayType (HirId ref, HirId ty_ref, location_t locus,
- HIR::Expr &capacity_expr, TyVar base,
- std::set<HirId> refs = std::set<HirId> ())
+ ArrayType (HirId ref, HirId ty_ref, location_t locus, ConstType *capacity,
+ TyVar base, std::set<HirId> refs = std::set<HirId> ())
: BaseType (ref, ty_ref, TypeKind::ARRAY,
{Resolver::CanonicalPath::create_empty (), locus}, refs),
- element_type (base), capacity_expr (capacity_expr)
+ element_type (base), capacity (capacity)
{}
void accept_vis (TyVisitor &vis) override;
@@ -1187,15 +1254,13 @@ public:
BaseType *clone () const final override;
- HIR::Expr &get_capacity_expr () const { return capacity_expr; }
+ ConstType *get_capacity () const { return capacity; }
ArrayType *handle_substitions (SubstitutionArgumentMappings &mappings);
private:
TyVar element_type;
- // FIXME: I dont think this should be in tyty - tyty should already be const
- // evaluated
- HIR::Expr &capacity_expr;
+ ConstType *capacity;
};
class SliceType : public BaseType
diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc
index 294b677..30ead5b 100644
--- a/gcc/rust/typecheck/rust-unify.cc
+++ b/gcc/rust/typecheck/rust-unify.cc
@@ -17,6 +17,9 @@
// <http://www.gnu.org/licenses/>.
#include "rust-unify.h"
+#include "fold-const.h"
+#include "rust-tyty.h"
+#include "tree.h"
namespace Rust {
namespace Resolver {
@@ -53,6 +56,22 @@ UnifyRules::Resolve (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
}
TyTy::BaseType *
+UnifyRules::resolve_subtype (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs)
+{
+ TyTy::BaseType *result
+ = UnifyRules::Resolve (lhs, rhs, locus, commit_flag, emit_error, infer_flag,
+ commits, infers);
+
+ // If the recursive call resulted in an error and would have emitted an error
+ // message, disable error emission for the current level to avoid duplicate
+ // errors
+ if (result->get_kind () == TyTy::TypeKind::ERROR && emit_error)
+ emit_error = false;
+
+ return result;
+}
+
+TyTy::BaseType *
UnifyRules::get_base ()
{
return lhs.get_ty ()->destructure ();
@@ -69,7 +88,6 @@ UnifyRules::commit (TyTy::BaseType *base, TyTy::BaseType *other,
TyTy::BaseType *resolved)
{
TypeCheckContext &context = *TypeCheckContext::get ();
- Analysis::Mappings &mappings = Analysis::Mappings::get ();
TyTy::BaseType *b = base->destructure ();
TyTy::BaseType *o = other->destructure ();
@@ -102,13 +120,8 @@ UnifyRules::commit (TyTy::BaseType *base, TyTy::BaseType *other,
continue;
// if any of the types are inference variables lets fix them
- if (ref_tyty->get_kind () == TyTy::TypeKind::INFER)
- {
- auto node = Analysis::NodeMapping (mappings.get_current_crate (),
- UNKNOWN_NODEID, ref,
- UNKNOWN_LOCAL_DEFID);
- context.insert_type (node, resolved->clone ());
- }
+ if (ref_tyty->is<TyTy::InferType> ())
+ context.insert_implicit_type (ref, resolved);
}
}
}
@@ -315,6 +328,9 @@ UnifyRules::go ()
case TyTy::OPAQUE:
return expect_opaque (static_cast<TyTy::OpaqueType *> (ltype), rtype);
+ case TyTy::CONST:
+ return expect_const (static_cast<TyTy::ConstType *> (ltype), rtype);
+
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -328,30 +344,33 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype,
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
switch (ltype->get_infer_kind ())
{
case TyTy::InferType::InferTypeKind::GENERAL:
return rtype->clone ();
- case TyTy::InferType::InferTypeKind::INTEGRAL: {
+ case TyTy::InferType::InferTypeKind::INTEGRAL:
+ {
bool is_valid = r->get_infer_kind ()
== TyTy::InferType::InferTypeKind::INTEGRAL
|| r->get_infer_kind ()
== TyTy::InferType::InferTypeKind::GENERAL;
if (is_valid)
- return rtype->clone ();
+ return rtype;
}
break;
- case TyTy::InferType::InferTypeKind::FLOAT: {
+ case TyTy::InferType::InferTypeKind::FLOAT:
+ {
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT
|| r->get_infer_kind ()
== TyTy::InferType::InferTypeKind::GENERAL;
if (is_valid)
- return rtype->clone ();
+ return rtype;
}
break;
}
@@ -361,7 +380,8 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype,
case TyTy::INT:
case TyTy::UINT:
case TyTy::USIZE:
- case TyTy::ISIZE: {
+ case TyTy::ISIZE:
+ {
bool is_valid = (ltype->get_infer_kind ()
== TyTy::InferType::InferTypeKind::GENERAL)
|| (ltype->get_infer_kind ()
@@ -369,12 +389,13 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype,
if (is_valid)
{
ltype->apply_primitive_type_hint (*rtype);
- return rtype->clone ();
+ return rtype;
}
}
break;
- case TyTy::FLOAT: {
+ case TyTy::FLOAT:
+ {
bool is_valid = (ltype->get_infer_kind ()
== TyTy::InferType::InferTypeKind::GENERAL)
|| (ltype->get_infer_kind ()
@@ -382,7 +403,7 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype,
if (is_valid)
{
ltype->apply_primitive_type_hint (*rtype);
- return rtype->clone ();
+ return rtype;
}
}
break;
@@ -404,7 +425,9 @@ UnifyRules::expect_inference_variable (TyTy::InferType *ltype,
case TyTy::PROJECTION:
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
- case TyTy::OPAQUE: {
+ case TyTy::CONST:
+ case TyTy::OPAQUE:
+ {
bool is_valid = (ltype->get_infer_kind ()
== TyTy::InferType::InferTypeKind::GENERAL);
if (is_valid)
@@ -424,7 +447,8 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -433,7 +457,8 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::ADT: {
+ case TyTy::ADT:
+ {
TyTy::ADTType &type = *static_cast<TyTy::ADTType *> (rtype);
if (ltype->get_adt_kind () != type.get_adt_kind ())
{
@@ -469,11 +494,8 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype)
TyTy::BaseType *other_field_ty = other_field->get_field_type ();
TyTy::BaseType *unified_ty
- = UnifyRules::Resolve (TyTy::TyWithLocation (this_field_ty),
- TyTy::TyWithLocation (other_field_ty),
- locus, commit_flag,
- false /* emit_error */, infer_flag,
- commits, infers);
+ = resolve_subtype (TyTy::TyWithLocation (this_field_ty),
+ TyTy::TyWithLocation (other_field_ty));
if (unified_ty->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
@@ -495,11 +517,8 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype)
auto pa = a.get_param_ty ();
auto pb = b.get_param_ty ();
- auto res
- = UnifyRules::Resolve (TyTy::TyWithLocation (pa),
- TyTy::TyWithLocation (pb), locus,
- commit_flag, false /* emit_error */,
- infer_flag, commits, infers);
+ auto res = resolve_subtype (TyTy::TyWithLocation (pa),
+ TyTy::TyWithLocation (pb));
if (res->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
@@ -533,6 +552,7 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -544,7 +564,8 @@ UnifyRules::expect_str (TyTy::StrType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -578,6 +599,7 @@ UnifyRules::expect_str (TyTy::StrType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -589,7 +611,8 @@ UnifyRules::expect_reference (TyTy::ReferenceType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -598,16 +621,15 @@ UnifyRules::expect_reference (TyTy::ReferenceType *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::REF: {
+ case TyTy::REF:
+ {
TyTy::ReferenceType &type = *static_cast<TyTy::ReferenceType *> (rtype);
auto base_type = ltype->get_base ();
auto other_base_type = type.get_base ();
TyTy::BaseType *base_resolved
- = UnifyRules::Resolve (TyTy::TyWithLocation (base_type),
- TyTy::TyWithLocation (other_base_type), locus,
- commit_flag, false /* emit_error */,
- infer_flag, commits, infers);
+ = resolve_subtype (TyTy::TyWithLocation (base_type),
+ TyTy::TyWithLocation (other_base_type));
if (base_resolved->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
@@ -649,6 +671,7 @@ UnifyRules::expect_reference (TyTy::ReferenceType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -660,7 +683,8 @@ UnifyRules::expect_pointer (TyTy::PointerType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -669,16 +693,15 @@ UnifyRules::expect_pointer (TyTy::PointerType *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::POINTER: {
+ case TyTy::POINTER:
+ {
TyTy::PointerType &type = *static_cast<TyTy::PointerType *> (rtype);
auto base_type = ltype->get_base ();
auto other_base_type = type.get_base ();
TyTy::BaseType *base_resolved
- = UnifyRules::Resolve (TyTy::TyWithLocation (base_type),
- TyTy::TyWithLocation (other_base_type), locus,
- commit_flag, false /* emit_error */,
- infer_flag, commits, infers);
+ = resolve_subtype (TyTy::TyWithLocation (base_type),
+ TyTy::TyWithLocation (other_base_type));
if (base_resolved->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
@@ -720,6 +743,7 @@ UnifyRules::expect_pointer (TyTy::PointerType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -731,7 +755,8 @@ UnifyRules::expect_param (TyTy::ParamType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -740,7 +765,8 @@ UnifyRules::expect_param (TyTy::ParamType *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::PARAM: {
+ case TyTy::PARAM:
+ {
TyTy::ParamType &type = *static_cast<TyTy::ParamType *> (rtype);
// bool symbol_matches
// = ltype->get_symbol ().compare (type.get_symbol ()) == 0;
@@ -782,6 +808,7 @@ UnifyRules::expect_param (TyTy::ParamType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -793,7 +820,8 @@ UnifyRules::expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -802,21 +830,32 @@ UnifyRules::expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::ARRAY: {
+ case TyTy::ARRAY:
+ {
TyTy::ArrayType &type = *static_cast<TyTy::ArrayType *> (rtype);
- TyTy::BaseType *element_unify = UnifyRules::Resolve (
- TyTy::TyWithLocation (ltype->get_element_type ()),
- TyTy::TyWithLocation (type.get_element_type ()), locus, commit_flag,
- false /* emit_error*/, infer_flag, commits, infers);
-
- if (element_unify->get_kind () != TyTy::TypeKind::ERROR)
- {
- return new TyTy::ArrayType (type.get_ref (), type.get_ty_ref (),
- type.get_ident ().locus,
- type.get_capacity_expr (),
- TyTy::TyVar (
- element_unify->get_ref ()));
- }
+ TyTy::BaseType *element_unify
+ = resolve_subtype (TyTy::TyWithLocation (ltype->get_element_type ()),
+ TyTy::TyWithLocation (type.get_element_type ()));
+
+ if (element_unify->get_kind () == TyTy::TypeKind::ERROR)
+ return new TyTy::ErrorType (0);
+
+ bool save_emit_error = emit_error;
+ emit_error = false;
+ TyTy::BaseType *capacity_unify
+ = resolve_subtype (TyTy::TyWithLocation (ltype->get_capacity ()),
+ TyTy::TyWithLocation (type.get_capacity ()));
+ emit_error = save_emit_error;
+
+ if (capacity_unify->get_kind () != TyTy::TypeKind::CONST)
+ return new TyTy::ErrorType (0);
+
+ TyTy::ConstType *capacity_type_unify
+ = static_cast<TyTy::ConstType *> (capacity_unify);
+ return new TyTy::ArrayType (type.get_ref (), type.get_ty_ref (),
+ type.get_ident ().locus,
+ capacity_type_unify,
+ TyTy::TyVar (element_unify->get_ref ()));
}
break;
@@ -842,6 +881,7 @@ UnifyRules::expect_array (TyTy::ArrayType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -853,7 +893,8 @@ UnifyRules::expect_slice (TyTy::SliceType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -862,12 +903,12 @@ UnifyRules::expect_slice (TyTy::SliceType *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::SLICE: {
+ case TyTy::SLICE:
+ {
TyTy::SliceType &type = *static_cast<TyTy::SliceType *> (rtype);
- TyTy::BaseType *element_unify = UnifyRules::Resolve (
- TyTy::TyWithLocation (ltype->get_element_type ()),
- TyTy::TyWithLocation (type.get_element_type ()), locus, commit_flag,
- false /* emit_error*/, infer_flag, commits, infers);
+ TyTy::BaseType *element_unify
+ = resolve_subtype (TyTy::TyWithLocation (ltype->get_element_type ()),
+ TyTy::TyWithLocation (type.get_element_type ()));
if (element_unify->get_kind () != TyTy::TypeKind::ERROR)
{
@@ -901,6 +942,7 @@ UnifyRules::expect_slice (TyTy::SliceType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -912,7 +954,8 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -921,7 +964,8 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::FNDEF: {
+ case TyTy::FNDEF:
+ {
TyTy::FnType &type = *static_cast<TyTy::FnType *> (rtype);
if (ltype->num_params () != type.num_params ())
{
@@ -933,21 +977,17 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype)
auto a = ltype->param_at (i).get_type ();
auto b = type.param_at (i).get_type ();
- auto unified_param
- = UnifyRules::Resolve (TyTy::TyWithLocation (a),
- TyTy::TyWithLocation (b), locus,
- commit_flag, false /* emit_errors */,
- infer_flag, commits, infers);
+ auto unified_param = resolve_subtype (TyTy::TyWithLocation (a),
+ TyTy::TyWithLocation (b));
if (unified_param->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
}
}
- auto unified_return = UnifyRules::Resolve (
- TyTy::TyWithLocation (ltype->get_return_type ()),
- TyTy::TyWithLocation (type.get_return_type ()), locus, commit_flag,
- false /* emit_errors */, infer_flag, commits, infers);
+ auto unified_return
+ = resolve_subtype (TyTy::TyWithLocation (ltype->get_return_type ()),
+ TyTy::TyWithLocation (type.get_return_type ()));
if (unified_return->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
@@ -992,6 +1032,7 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -1003,7 +1044,8 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -1012,7 +1054,8 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::FNPTR: {
+ case TyTy::FNPTR:
+ {
TyTy::FnPtr &type = *static_cast<TyTy::FnPtr *> (rtype);
if (ltype->num_params () != type.num_params ())
{
@@ -1024,21 +1067,17 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype)
auto a = ltype->get_param_type_at (i);
auto b = type.get_param_type_at (i);
- auto unified_param
- = UnifyRules::Resolve (TyTy::TyWithLocation (a),
- TyTy::TyWithLocation (b), locus,
- commit_flag, false /* emit_errors */,
- infer_flag, commits, infers);
+ auto unified_param = resolve_subtype (TyTy::TyWithLocation (a),
+ TyTy::TyWithLocation (b));
if (unified_param->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
}
}
- auto unified_return = UnifyRules::Resolve (
- TyTy::TyWithLocation (ltype->get_return_type ()),
- TyTy::TyWithLocation (type.get_return_type ()), locus, commit_flag,
- false /* emit_errors */, infer_flag, commits, infers);
+ auto unified_return
+ = resolve_subtype (TyTy::TyWithLocation (ltype->get_return_type ()),
+ TyTy::TyWithLocation (type.get_return_type ()));
if (unified_return->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
@@ -1048,16 +1087,15 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::FNDEF: {
+ case TyTy::FNDEF:
+ {
TyTy::FnType &type = *static_cast<TyTy::FnType *> (rtype);
auto this_ret_type = ltype->get_return_type ();
auto other_ret_type = type.get_return_type ();
auto unified_result
- = UnifyRules::Resolve (TyTy::TyWithLocation (this_ret_type),
- TyTy::TyWithLocation (other_ret_type), locus,
- commit_flag, false /*emit_errors*/, infer_flag,
- commits, infers);
+ = resolve_subtype (TyTy::TyWithLocation (this_ret_type),
+ TyTy::TyWithLocation (other_ret_type));
if (unified_result->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
@@ -1074,10 +1112,45 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype)
auto other_param = type.param_at (i).get_type ();
auto unified_param
- = UnifyRules::Resolve (TyTy::TyWithLocation (this_param),
- TyTy::TyWithLocation (other_param), locus,
- commit_flag, false /* emit_errors */,
- infer_flag, commits, infers);
+ = resolve_subtype (TyTy::TyWithLocation (this_param),
+ TyTy::TyWithLocation (other_param));
+ if (unified_param->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ return new TyTy::ErrorType (0);
+ }
+ }
+
+ return ltype->clone ();
+ }
+ break;
+
+ case TyTy::CLOSURE:
+ {
+ TyTy::ClosureType &type = *static_cast<TyTy::ClosureType *> (rtype);
+ auto this_ret_type = ltype->get_return_type ();
+ auto other_ret_type = type.get_return_type ();
+
+ auto unified_result
+ = resolve_subtype (TyTy::TyWithLocation (this_ret_type),
+ TyTy::TyWithLocation (other_ret_type));
+ if (unified_result->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ if (ltype->num_params () != type.get_num_params ())
+ {
+ return new TyTy::ErrorType (0);
+ }
+
+ for (size_t i = 0; i < ltype->num_params (); i++)
+ {
+ auto this_param = ltype->get_param_type_at (i);
+ auto other_param = type.get_param_type_at (i);
+
+ auto unified_param
+ = resolve_subtype (TyTy::TyWithLocation (this_param),
+ TyTy::TyWithLocation (other_param));
if (unified_param->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
@@ -1107,8 +1180,8 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, TyTy::BaseType *rtype)
case TyTy::PLACEHOLDER:
case TyTy::PROJECTION:
case TyTy::DYNAMIC:
- case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -1120,7 +1193,8 @@ UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -1129,7 +1203,8 @@ UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::TUPLE: {
+ case TyTy::TUPLE:
+ {
TyTy::TupleType &type = *static_cast<TyTy::TupleType *> (rtype);
if (ltype->num_fields () != type.num_fields ())
{
@@ -1143,10 +1218,8 @@ UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype)
TyTy::BaseType *fo = type.get_field (i);
TyTy::BaseType *unified_ty
- = UnifyRules::Resolve (TyTy::TyWithLocation (bo),
- TyTy::TyWithLocation (fo), locus,
- commit_flag, false /* emit_errors */,
- infer_flag, commits, infers);
+ = resolve_subtype (TyTy::TyWithLocation (bo),
+ TyTy::TyWithLocation (fo));
if (unified_ty->get_kind () == TyTy::TypeKind::ERROR)
return new TyTy::ErrorType (0);
@@ -1180,6 +1253,7 @@ UnifyRules::expect_tuple (TyTy::TupleType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -1191,7 +1265,8 @@ UnifyRules::expect_bool (TyTy::BoolType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -1228,6 +1303,7 @@ UnifyRules::expect_bool (TyTy::BoolType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -1239,7 +1315,8 @@ UnifyRules::expect_char (TyTy::CharType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -1276,6 +1353,7 @@ UnifyRules::expect_char (TyTy::CharType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -1287,7 +1365,8 @@ UnifyRules::expect_int (TyTy::IntType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL
@@ -1300,7 +1379,8 @@ UnifyRules::expect_int (TyTy::IntType *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::INT: {
+ case TyTy::INT:
+ {
TyTy::IntType &type = *static_cast<TyTy::IntType *> (rtype);
bool is_valid = ltype->get_int_kind () == type.get_int_kind ();
if (is_valid)
@@ -1331,6 +1411,7 @@ UnifyRules::expect_int (TyTy::IntType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -1342,7 +1423,8 @@ UnifyRules::expect_uint (TyTy::UintType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL
@@ -1355,7 +1437,8 @@ UnifyRules::expect_uint (TyTy::UintType *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::UINT: {
+ case TyTy::UINT:
+ {
TyTy::UintType &type = *static_cast<TyTy::UintType *> (rtype);
bool is_valid = ltype->get_uint_kind () == type.get_uint_kind ();
if (is_valid)
@@ -1386,6 +1469,7 @@ UnifyRules::expect_uint (TyTy::UintType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -1397,7 +1481,8 @@ UnifyRules::expect_float (TyTy::FloatType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL
@@ -1410,7 +1495,8 @@ UnifyRules::expect_float (TyTy::FloatType *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::FLOAT: {
+ case TyTy::FLOAT:
+ {
TyTy::FloatType &type = *static_cast<TyTy::FloatType *> (rtype);
bool is_valid = ltype->get_float_kind () == type.get_float_kind ();
if (is_valid)
@@ -1441,6 +1527,7 @@ UnifyRules::expect_float (TyTy::FloatType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -1452,7 +1539,8 @@ UnifyRules::expect_isize (TyTy::ISizeType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () != TyTy::InferType::InferTypeKind::FLOAT;
@@ -1489,6 +1577,7 @@ UnifyRules::expect_isize (TyTy::ISizeType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -1500,7 +1589,8 @@ UnifyRules::expect_usize (TyTy::USizeType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () != TyTy::InferType::InferTypeKind::FLOAT;
@@ -1537,6 +1627,7 @@ UnifyRules::expect_usize (TyTy::USizeType *ltype, TyTy::BaseType *rtype)
case TyTy::DYNAMIC:
case TyTy::CLOSURE:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -1548,7 +1639,8 @@ UnifyRules::expect_never (TyTy::NeverType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -1569,7 +1661,8 @@ UnifyRules::expect_placeholder (TyTy::PlaceholderType *ltype,
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -1607,6 +1700,7 @@ UnifyRules::expect_placeholder (TyTy::PlaceholderType *ltype,
return rtype->clone ();
gcc_fallthrough ();
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -1619,7 +1713,8 @@ UnifyRules::expect_projection (TyTy::ProjectionType *ltype,
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -1655,6 +1750,7 @@ UnifyRules::expect_projection (TyTy::ProjectionType *ltype,
case TyTy::NEVER:
case TyTy::PLACEHOLDER:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -1666,7 +1762,8 @@ UnifyRules::expect_dyn (TyTy::DynamicObjectType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -1675,7 +1772,8 @@ UnifyRules::expect_dyn (TyTy::DynamicObjectType *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::DYNAMIC: {
+ case TyTy::DYNAMIC:
+ {
TyTy::DynamicObjectType &type
= *static_cast<TyTy::DynamicObjectType *> (rtype);
if (ltype->num_specified_bounds () != type.num_specified_bounds ())
@@ -1714,6 +1812,7 @@ UnifyRules::expect_dyn (TyTy::DynamicObjectType *ltype, TyTy::BaseType *rtype)
case TyTy::PLACEHOLDER:
case TyTy::PROJECTION:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -1725,7 +1824,8 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype)
{
switch (rtype->get_kind ())
{
- case TyTy::INFER: {
+ case TyTy::INFER:
+ {
TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
bool is_valid
= r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
@@ -1734,26 +1834,25 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype)
}
break;
- case TyTy::CLOSURE: {
+ case TyTy::CLOSURE:
+ {
TyTy::ClosureType &type = *static_cast<TyTy::ClosureType *> (rtype);
if (ltype->get_def_id () != type.get_def_id ())
{
return new TyTy::ErrorType (0);
}
- TyTy::BaseType *args_res = UnifyRules::Resolve (
- TyTy::TyWithLocation (&ltype->get_parameters ()),
- TyTy::TyWithLocation (&type.get_parameters ()), locus, commit_flag,
- false /* emit_error */, infer_flag, commits, infers);
+ TyTy::BaseType *args_res
+ = resolve_subtype (TyTy::TyWithLocation (&ltype->get_parameters ()),
+ TyTy::TyWithLocation (&type.get_parameters ()));
if (args_res->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
}
- TyTy::BaseType *res = UnifyRules::Resolve (
- TyTy::TyWithLocation (&ltype->get_result_type ()),
- TyTy::TyWithLocation (&type.get_result_type ()), locus, commit_flag,
- false /* emit_error */, infer_flag, commits, infers);
+ TyTy::BaseType *res
+ = resolve_subtype (TyTy::TyWithLocation (&ltype->get_result_type ()),
+ TyTy::TyWithLocation (&type.get_result_type ()));
if (res == nullptr || res->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
@@ -1785,6 +1884,7 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype)
case TyTy::PROJECTION:
case TyTy::DYNAMIC:
case TyTy::OPAQUE:
+ case TyTy::CONST:
case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
@@ -1794,58 +1894,113 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, TyTy::BaseType *rtype)
TyTy::BaseType *
UnifyRules::expect_opaque (TyTy::OpaqueType *ltype, TyTy::BaseType *rtype)
{
- switch (rtype->get_kind ())
+ if (rtype->is<TyTy::OpaqueType> ())
{
- case TyTy::INFER: {
- TyTy::InferType *r = static_cast<TyTy::InferType *> (rtype);
- bool is_valid
- = r->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL;
- if (is_valid)
- return ltype->clone ();
- }
- break;
+ TyTy::OpaqueType *ro = rtype->as<TyTy::OpaqueType> ();
+ if (!ltype->is_equal (*ro))
+ return new TyTy::ErrorType (0);
- case TyTy::OPAQUE: {
- auto &type = *static_cast<TyTy::OpaqueType *> (rtype);
- if (ltype->num_specified_bounds () != type.num_specified_bounds ())
- {
- return new TyTy::ErrorType (0);
- }
+ if (ltype->can_resolve () && ro->can_resolve ())
+ {
+ auto lr = ltype->resolve ();
+ auto rr = ro->resolve ();
- if (!ltype->bounds_compatible (type, locus, true))
- {
+ auto res = resolve_subtype (TyTy::TyWithLocation (lr),
+ TyTy::TyWithLocation (rr));
+ if (res->get_kind () == TyTy::TypeKind::ERROR)
return new TyTy::ErrorType (0);
- }
+ }
+ else if (ltype->can_resolve ())
+ {
+ auto lr = ltype->resolve ();
+ ro->set_ty_ref (lr->get_ref ());
+ }
+ else if (ro->can_resolve ())
+ {
+ auto rr = ro->resolve ();
+ ltype->set_ty_ref (rr->get_ref ());
+ }
+ }
+ else if (ltype->can_resolve ())
+ {
+ auto underly = ltype->resolve ();
+ auto res = resolve_subtype (TyTy::TyWithLocation (underly),
+ TyTy::TyWithLocation (rtype));
+ if (res->get_kind () == TyTy::TypeKind::ERROR)
+ return new TyTy::ErrorType (0);
+ }
+ else
+ {
+ ltype->set_ty_ref (rtype->get_ref ());
+ }
- return ltype->clone ();
- }
- break;
+ return ltype;
+}
+
+TyTy::BaseType *
+UnifyRules::expect_const (TyTy::ConstType *ltype, TyTy::BaseType *rtype)
+{
+ if (rtype->get_kind () != TyTy::TypeKind::CONST)
+ return new TyTy::ErrorType (0);
+
+ TyTy::ConstType &lhs = *ltype;
+ TyTy::ConstType &rhs = *static_cast<TyTy::ConstType *> (rtype);
+
+ auto res = resolve_subtype (TyTy::TyWithLocation (lhs.get_ty ()),
+ TyTy::TyWithLocation (rhs.get_ty ()));
+ if (res->get_kind () == TyTy::TypeKind::ERROR)
+ return new TyTy::ErrorType (0);
+
+ tree lv = lhs.get_value ();
+ tree rv = rhs.get_value ();
+
+ if (error_operand_p (lv) && error_operand_p (rv))
+ {
+ // this is only allowed for some silly senarios like:
+ // gcc/testsuite/rust/compile/issue-const_generics_5.rs
+ if (lhs.get_const_kind () == rhs.get_const_kind ())
+ {
+ return new TyTy::ConstType (lhs.get_const_kind (), lhs.get_symbol (),
+ res, error_mark_node,
+ lhs.get_specified_bounds (),
+ lhs.get_locus (), lhs.get_ref (),
+ lhs.get_ty_ref (),
+ lhs.get_combined_refs ());
+ }
- case TyTy::CLOSURE:
- case TyTy::SLICE:
- case TyTy::PARAM:
- case TyTy::POINTER:
- case TyTy::STR:
- case TyTy::ADT:
- case TyTy::REF:
- case TyTy::ARRAY:
- case TyTy::FNDEF:
- case TyTy::FNPTR:
- case TyTy::TUPLE:
- case TyTy::BOOL:
- case TyTy::CHAR:
- case TyTy::INT:
- case TyTy::UINT:
- case TyTy::FLOAT:
- case TyTy::USIZE:
- case TyTy::ISIZE:
- case TyTy::NEVER:
- case TyTy::PLACEHOLDER:
- case TyTy::PROJECTION:
- case TyTy::DYNAMIC:
- case TyTy::ERROR:
return new TyTy::ErrorType (0);
}
+
+ bool equal = operand_equal_p (lv, rv, 0);
+ if (equal)
+ {
+ return new TyTy::ConstType (TyTy::ConstType::ConstKind::Value,
+ lhs.get_symbol (), res, lv,
+ lhs.get_specified_bounds (), lhs.get_locus (),
+ lhs.get_ref (), lhs.get_ty_ref (),
+ lhs.get_combined_refs ());
+ }
+
+ if (lhs.get_const_kind () == TyTy::ConstType::Infer && !error_operand_p (rv))
+ {
+ lhs.set_value (rv);
+ return new TyTy::ConstType (TyTy::ConstType::ConstKind::Value,
+ lhs.get_symbol (), res, rv,
+ lhs.get_specified_bounds (), lhs.get_locus (),
+ lhs.get_ref (), lhs.get_ty_ref (),
+ lhs.get_combined_refs ());
+ }
+ else if (rhs.get_const_kind () == TyTy::ConstType::Infer
+ && !error_operand_p (lv))
+ {
+ rhs.set_value (lv);
+ return new TyTy::ConstType (TyTy::ConstType::ConstKind::Value,
+ rhs.get_symbol (), res, lv,
+ rhs.get_specified_bounds (), rhs.get_locus (),
+ rhs.get_ref (), rhs.get_ty_ref (),
+ rhs.get_combined_refs ());
+ }
+
return new TyTy::ErrorType (0);
}
diff --git a/gcc/rust/typecheck/rust-unify.h b/gcc/rust/typecheck/rust-unify.h
index 5ff3b7c..b8c9cbc 100644
--- a/gcc/rust/typecheck/rust-unify.h
+++ b/gcc/rust/typecheck/rust-unify.h
@@ -84,6 +84,7 @@ protected:
TyTy::BaseType *rtype);
TyTy::BaseType *expect_opaque (TyTy::OpaqueType *ltype,
TyTy::BaseType *rtype);
+ TyTy::BaseType *expect_const (TyTy::ConstType *ltype, TyTy::BaseType *rtype);
private:
UnifyRules (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
@@ -91,6 +92,9 @@ private:
std::vector<CommitSite> &commits,
std::vector<InferenceSite> &infers);
+ TyTy::BaseType *resolve_subtype (TyTy::TyWithLocation lhs,
+ TyTy::TyWithLocation rhs);
+
void emit_type_mismatch () const;
void emit_abi_mismatch (const TyTy::FnType &expected,
const TyTy::FnType &got) const;
diff --git a/gcc/rust/util/optional.h b/gcc/rust/util/optional.h
index 2c59459..9d2cd97 100644
--- a/gcc/rust/util/optional.h
+++ b/gcc/rust/util/optional.h
@@ -1364,7 +1364,7 @@ public:
this->m_has_value = false;
}
}
-}; // namespace tl
+};
/// Compares two optional objects
template <class T, class U>
@@ -2110,7 +2110,7 @@ public:
private:
T *m_value;
-}; // namespace tl
+};
@@ -2128,4 +2128,4 @@ template <class T> struct hash<tl::optional<T>> {
};
} // namespace std
-#endif \ No newline at end of file
+#endif
diff --git a/gcc/rust/util/rust-abi.h b/gcc/rust/util/rust-abi.h
index a0180ed..357a5db 100644
--- a/gcc/rust/util/rust-abi.h
+++ b/gcc/rust/util/rust-abi.h
@@ -34,11 +34,9 @@ enum ABI
SYSV64
};
-extern Rust::ABI
-get_abi_from_string (const std::string &abi);
+extern Rust::ABI get_abi_from_string (const std::string &abi);
-extern std::string
-get_string_from_abi (Rust::ABI abi);
+extern std::string get_string_from_abi (Rust::ABI abi);
} // namespace Rust
diff --git a/gcc/rust/util/rust-attribute-values.h b/gcc/rust/util/rust-attribute-values.h
index 47e6a17..367044a 100644
--- a/gcc/rust/util/rust-attribute-values.h
+++ b/gcc/rust/util/rust-attribute-values.h
@@ -85,6 +85,13 @@ public:
static constexpr auto &NON_EXHAUSTIVE = "non_exhaustive";
static constexpr auto &RUSTFMT = "rustfmt";
+
+ static constexpr auto &TEST = "test";
+
+ static constexpr auto &SIMD_TEST = "simd_test";
+
+ static constexpr auto &RUSTC_ARGS_REQUIRED_CONST
+ = "rustc_args_required_const";
};
} // namespace Values
} // namespace Rust
diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc
index c77e99c..c846c2d 100644
--- a/gcc/rust/util/rust-attributes.cc
+++ b/gcc/rust/util/rust-attributes.cc
@@ -88,6 +88,9 @@ static const BuiltinAttrDefinition __definitions[]
{Attrs::RUSTC_LAYOUT_SCALAR_VALID_RANGE_START, CODE_GENERATION},
+ // TODO: be careful about calling functions marked with this?
+ {Attrs::RUSTC_ARGS_REQUIRED_CONST, CODE_GENERATION},
+
{Attrs::PRELUDE_IMPORT, NAME_RESOLUTION},
{Attrs::RUSTC_DIAGNOSTIC_ITEM, STATIC_ANALYSIS},
@@ -95,7 +98,10 @@ static const BuiltinAttrDefinition __definitions[]
{Attrs::FUNDAMENTAL, TYPE_CHECK},
{Attrs::NON_EXHAUSTIVE, TYPE_CHECK},
- {Attrs::RUSTFMT, EXTERNAL}};
+ {Attrs::RUSTFMT, EXTERNAL},
+
+ {Attrs::TEST, CODE_GENERATION},
+ {Attrs::SIMD_TEST, CODE_GENERATION}};
BuiltinAttributeMappings *
BuiltinAttributeMappings::get ()
@@ -221,7 +227,8 @@ check_doc_attribute (const AST::Attribute &attribute)
break;
// FIXME: Handle them as well
- case AST::AttrInput::TOKEN_TREE: {
+ case AST::AttrInput::TOKEN_TREE:
+ {
// FIXME: This doesn't check for #[doc(alias(...))]
const auto &option = static_cast<const AST::DelimTokenTree &> (
attribute.get_attr_input ());
@@ -388,7 +395,7 @@ AttributeChecker::visit (AST::MetaItemLitExpr &)
{}
void
-AttributeChecker::visit (AST::MetaItemPathLit &)
+AttributeChecker::visit (AST::MetaItemPathExpr &)
{}
void
diff --git a/gcc/rust/util/rust-attributes.h b/gcc/rust/util/rust-attributes.h
index 7c7a1fc..db8fe23 100644
--- a/gcc/rust/util/rust-attributes.h
+++ b/gcc/rust/util/rust-attributes.h
@@ -130,7 +130,7 @@ private:
void visit (AST::AttrInputLiteral &attr_input) override;
void visit (AST::AttrInputMacro &attr_input) override;
void visit (AST::MetaItemLitExpr &meta_item) override;
- void visit (AST::MetaItemPathLit &meta_item) override;
+ void visit (AST::MetaItemPathExpr &meta_item) override;
void visit (AST::BorrowExpr &expr) override;
void visit (AST::DereferenceExpr &expr) override;
void visit (AST::ErrorPropagationExpr &expr) override;
diff --git a/gcc/rust/util/rust-base62.h b/gcc/rust/util/rust-base62.h
index e751c95..5fd7a37 100644
--- a/gcc/rust/util/rust-base62.h
+++ b/gcc/rust/util/rust-base62.h
@@ -26,8 +26,7 @@ namespace Rust {
/**
* Get the Base62 representation of an integer
*/
-std::string
-base62_integer (uint64_t value);
+std::string base62_integer (uint64_t value);
} // namespace Rust
diff --git a/gcc/rust/util/rust-canonical-path.h b/gcc/rust/util/rust-canonical-path.h
index 4d8f954..079ae76 100644
--- a/gcc/rust/util/rust-canonical-path.h
+++ b/gcc/rust/util/rust-canonical-path.h
@@ -57,10 +57,11 @@ public:
return *this;
}
- static CanonicalPath new_seg (NodeId id, const std::string &path)
+ static CanonicalPath new_seg (NodeId id, std::string path)
{
rust_assert (!path.empty ());
- return CanonicalPath ({std::pair<NodeId, std::string> (id, path)},
+ return CanonicalPath ({std::pair<NodeId, std::string> (id,
+ std::move (path))},
UNKNOWN_CRATENUM);
}
@@ -68,14 +69,18 @@ public:
trait_impl_projection_seg (NodeId id, const CanonicalPath &trait_seg,
const CanonicalPath &impl_type_seg)
{
- return CanonicalPath::new_seg (id, "<" + impl_type_seg.get () + " as "
+ // https://doc.rust-lang.org/reference/paths.html#canonical-paths
+ // should be "<X>"?
+ return CanonicalPath::new_seg (id, "<impl " + impl_type_seg.get () + " as "
+ trait_seg.get () + ">");
}
static CanonicalPath inherent_impl_seg (NodeId id,
const CanonicalPath &impl_type_seg)
{
- return CanonicalPath::new_seg (id, "<" + impl_type_seg.get () + ">");
+ // https://doc.rust-lang.org/reference/paths.html#canonical-paths
+ // should be "<X as Y>"?
+ return CanonicalPath::new_seg (id, "<impl " + impl_type_seg.get () + ">");
}
std::string get () const
diff --git a/gcc/rust/util/rust-dir-owner.h b/gcc/rust/util/rust-dir-owner.h
index dcb45d8..fb72bb1 100644
--- a/gcc/rust/util/rust-dir-owner.h
+++ b/gcc/rust/util/rust-dir-owner.h
@@ -26,8 +26,7 @@
namespace Rust {
// extracts the owned subdirectory name from a file name
-bool
-get_file_subdir (const std::string &filename, std::string &subdir);
+bool get_file_subdir (const std::string &filename, std::string &subdir);
} // namespace Rust
diff --git a/gcc/rust/util/rust-edition.h b/gcc/rust/util/rust-edition.h
index d034ea0..532fedb 100644
--- a/gcc/rust/util/rust-edition.h
+++ b/gcc/rust/util/rust-edition.h
@@ -33,8 +33,7 @@ enum class Edition
E2021
};
-Edition
-get_rust_edition ();
+Edition get_rust_edition ();
} // namespace Rust
diff --git a/gcc/rust/util/rust-ggc.cc b/gcc/rust/util/rust-ggc.cc
new file mode 100644
index 0000000..0722af2
--- /dev/null
+++ b/gcc/rust/util/rust-ggc.cc
@@ -0,0 +1,41 @@
+// 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-ggc.h"
+#include "stringpool.h"
+
+namespace Rust {
+
+namespace GGC {
+
+Ident::Ident (const char *str) : inner (get_identifier (str)) {}
+
+Ident::Ident (const std::string &str)
+ : inner (get_identifier_with_length (str.c_str (), str.length ()))
+{}
+
+bool
+Ident::operator== (const std::string &other) const
+{
+ // maybe_get_identifier_with_length doesn't seem to exist
+ return maybe_get_identifier (other.c_str ()) == inner;
+}
+
+} // namespace GGC
+
+} // namespace Rust
diff --git a/gcc/rust/util/rust-ggc.h b/gcc/rust/util/rust-ggc.h
new file mode 100644
index 0000000..da28ede
--- /dev/null
+++ b/gcc/rust/util/rust-ggc.h
@@ -0,0 +1,63 @@
+// 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_GGC_H
+#define RUST_GGC_H
+
+#include "rust-system.h"
+#include "tree.h"
+
+namespace Rust {
+
+namespace GGC {
+
+class Ident
+{
+ tree inner;
+
+public:
+ Ident (const char *str);
+ Ident (const std::string &str);
+
+ bool operator== (const Ident &other) const { return inner == other.inner; }
+ bool operator== (const std::string &other) const;
+
+ const char *c_str () const { return IDENTIFIER_POINTER (inner); }
+ size_t size () const { return IDENTIFIER_LENGTH (inner); }
+
+ bool empty () const { return !size (); }
+
+ std::string as_string () const
+ {
+ return std::string (c_str (), c_str () + size ());
+ }
+
+ tree as_tree () const { return inner; }
+};
+
+static inline bool
+operator== (const std::string &a, const Ident &b)
+{
+ return b == a;
+}
+
+} // namespace GGC
+
+} // namespace Rust
+
+#endif // RUST_GGC_H
diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc
index eaa640c..4629e6a 100644
--- a/gcc/rust/util/rust-hir-map.cc
+++ b/gcc/rust/util/rust-hir-map.cc
@@ -1148,17 +1148,19 @@ Mappings::lookup_module_children (NodeId module)
}
void
-Mappings::insert_ast_module (AST::Module *module)
+Mappings::insert_glob_container (AST::Item *container)
{
- rust_assert (modules.find (module->get_node_id ()) == modules.end ());
- modules[module->get_node_id ()] = module;
+ rust_assert (glob_containers.find (container->get_node_id ())
+ == glob_containers.end ());
+
+ glob_containers[container->get_node_id ()] = container;
}
-tl::optional<AST::Module *>
-Mappings::lookup_ast_module (NodeId id)
+tl::optional<AST::Item *>
+Mappings::lookup_glob_container (NodeId id)
{
- auto it = modules.find (id);
- if (it == modules.end ())
+ auto it = glob_containers.find (id);
+ if (it == glob_containers.end ())
return tl::nullopt;
return {it->second};
diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h
index b523a36..c8fafa4 100644
--- a/gcc/rust/util/rust-hir-map.h
+++ b/gcc/rust/util/rust-hir-map.h
@@ -321,8 +321,8 @@ public:
void insert_visibility (NodeId id, Privacy::ModuleVisibility visibility);
tl::optional<Privacy::ModuleVisibility &> lookup_visibility (NodeId id);
- void insert_ast_module (AST::Module *);
- tl::optional<AST::Module *> lookup_ast_module (NodeId id);
+ void insert_glob_container (AST::Item *);
+ tl::optional<AST::Item *> lookup_glob_container (NodeId id);
void insert_module_child (NodeId module, NodeId child);
tl::optional<std::vector<NodeId> &> lookup_module_children (NodeId module);
@@ -436,7 +436,7 @@ private:
std::map<NodeId, std::vector<NodeId>> module_child_map;
std::map<NodeId, std::vector<Resolver::CanonicalPath>> module_child_items;
std::map<NodeId, NodeId> child_to_parent_module_map;
- std::map<NodeId, AST::Module *> modules;
+ std::map<NodeId, AST::Item *> glob_containers;
// AST mappings
std::map<NodeId, AST::Item *> ast_item_mappings;
diff --git a/gcc/rust/util/rust-punycode.h b/gcc/rust/util/rust-punycode.h
index a939f05..75260ce 100644
--- a/gcc/rust/util/rust-punycode.h
+++ b/gcc/rust/util/rust-punycode.h
@@ -27,8 +27,7 @@ namespace Rust {
/* Encode a string as punycode. Returns a string if encoding is successful.
* Returns nullopt otherwise. Note that a returned string contains only ASCII
* characters and does not start with `xn--`. */
-tl::optional<std::string>
-encode_punycode (const Utf8String &src);
+tl::optional<std::string> encode_punycode (const Utf8String &src);
} // namespace Rust
@@ -36,8 +35,7 @@ encode_punycode (const Utf8String &src);
namespace selftest {
-void
-rust_punycode_encode_test ();
+void rust_punycode_encode_test ();
} // namespace selftest
diff --git a/gcc/rust/util/rust-token-converter.cc b/gcc/rust/util/rust-token-converter.cc
index fc34adb..52172f4 100644
--- a/gcc/rust/util/rust-token-converter.cc
+++ b/gcc/rust/util/rust-token-converter.cc
@@ -202,7 +202,8 @@ convert (const std::vector<const_TokenPtr> &tokens)
case PERCENT_EQ:
case SCOPE_RESOLUTION:
case NOT_EQUAL:
- case EQUAL_EQUAL: {
+ case EQUAL_EQUAL:
+ {
auto str = token->as_string ();
auto it = str.cbegin ();
for (; it != str.cend () - 1; it++)
@@ -260,9 +261,8 @@ convert (const std::vector<const_TokenPtr> &tokens)
return trees.back ();
}
-static void
-from_tokenstream (const ProcMacro::TokenStream &ts,
- std::vector<const_TokenPtr> &result);
+static void from_tokenstream (const ProcMacro::TokenStream &ts,
+ std::vector<const_TokenPtr> &result);
/**
* Append the token corresponding to a given Ident to a vector.
diff --git a/gcc/rust/util/rust-token-converter.h b/gcc/rust/util/rust-token-converter.h
index 5405d6e..6e4af50 100644
--- a/gcc/rust/util/rust-token-converter.h
+++ b/gcc/rust/util/rust-token-converter.h
@@ -23,14 +23,11 @@
namespace Rust {
-ProcMacro::TokenStream
-convert (const std::vector<const_TokenPtr> &tokens);
+ProcMacro::TokenStream convert (const std::vector<const_TokenPtr> &tokens);
-std::vector<const_TokenPtr>
-convert (const ProcMacro::TokenStream &ts);
+std::vector<const_TokenPtr> convert (const ProcMacro::TokenStream &ts);
-ProcMacro::Literal
-convert_literal (const_TokenPtr lit);
+ProcMacro::Literal convert_literal (const_TokenPtr lit);
} // namespace Rust
diff --git a/gcc/rust/util/rust-unicode.h b/gcc/rust/util/rust-unicode.h
index 6a6526d..6579b80 100644
--- a/gcc/rust/util/rust-unicode.h
+++ b/gcc/rust/util/rust-unicode.h
@@ -59,20 +59,15 @@ public:
Utf8String nfc_normalize () const;
};
-bool
-is_alphabetic (uint32_t codepoint);
+bool is_alphabetic (uint32_t codepoint);
-bool
-is_ascii_only (const std::string &str);
+bool is_ascii_only (const std::string &str);
-bool
-is_numeric (uint32_t codepoint);
+bool is_numeric (uint32_t codepoint);
-bool
-is_nfc_qc_no (uint32_t codepoint);
+bool is_nfc_qc_no (uint32_t codepoint);
-bool
-is_nfc_qc_maybe (uint32_t codepoint);
+bool is_nfc_qc_maybe (uint32_t codepoint);
enum class QuickCheckResult
{
@@ -81,8 +76,7 @@ enum class QuickCheckResult
MAYBE
};
-QuickCheckResult
-nfc_quick_check (const std::vector<Codepoint> &s);
+QuickCheckResult nfc_quick_check (const std::vector<Codepoint> &s);
} // namespace Rust
@@ -90,14 +84,11 @@ nfc_quick_check (const std::vector<Codepoint> &s);
namespace selftest {
-void
-rust_nfc_qc_test ();
+void rust_nfc_qc_test ();
-void
-rust_utf8_normalize_test ();
+void rust_utf8_normalize_test ();
-void
-rust_utf8_property_test ();
+void rust_utf8_property_test ();
} // namespace selftest
diff --git a/gcc/rust/util/rust-unwrap-segment.h b/gcc/rust/util/rust-unwrap-segment.h
index bebdc3a..af3a237 100644
--- a/gcc/rust/util/rust-unwrap-segment.h
+++ b/gcc/rust/util/rust-unwrap-segment.h
@@ -83,14 +83,11 @@ public:
/*
* Used to get the node id of a path segment object
*/
-NodeId
-unwrap_segment_node_id (const AST::TypePathSegment &seg);
+NodeId unwrap_segment_node_id (const AST::TypePathSegment &seg);
-NodeId
-unwrap_segment_node_id (const AST::SimplePathSegment &seg);
+NodeId unwrap_segment_node_id (const AST::SimplePathSegment &seg);
-NodeId
-unwrap_segment_node_id (const AST::PathExprSegment &seg);
+NodeId unwrap_segment_node_id (const AST::PathExprSegment &seg);
template <class T>
NodeId
diff --git a/gcc/sarif-replay.cc b/gcc/sarif-replay.cc
index a96c97b..c740c29 100644
--- a/gcc/sarif-replay.cc
+++ b/gcc/sarif-replay.cc
@@ -93,6 +93,11 @@ static const char *const usage_msg = (
"\n"
" --usage\n"
" Print this message and exit.\n"
+"\n"
+"Options for maintainers:\n"
+"\n"
+" -fdebug-physical-locations\n"
+" Dump debugging information about physical locations to stderr.\n"
"\n");
static void
@@ -182,7 +187,11 @@ parse_options (int argc, char **argv,
print_version ();
exit (0);
}
-
+ else if (strcmp (option, "-fdebug-physical-locations") == 0)
+ {
+ opts.m_replay_opts.m_debug_physical_locations = true;
+ handled = true;
+ }
if (!handled)
{
if (option[0] == '-')
@@ -245,6 +254,8 @@ main (int argc, char **argv)
note.finish ("about to replay %qs...", filename);
}
libgdiagnostics::manager playback_mgr;
+ playback_mgr.set_debug_physical_locations
+ (opts.m_replay_opts.m_debug_physical_locations);
playback_mgr.add_text_sink (stderr,
opts.m_replay_opts.m_diagnostics_colorize);
for (auto spec : opts.m_extra_output_specs)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index db4d560..1ac6084 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,758 @@
+2025-08-05 Jason Merrill <jason@redhat.com>
+
+ PR c++/121068
+ * g++.dg/cpp26/constexpr-new5.C: New test.
+
+2025-08-05 Mikael Morin <morin-mikael@orange.fr>
+
+ * gfortran.dg/pointer_assign_16.f90: New test.
+
+2025-08-05 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/121410
+ * gcc.target/i386/pr121410.c: New test.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * rust/execute/torture/offset_of1.rs: New test.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/execute/torture/const-generics-1.rs: New test.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/generics8.rs: extra error message
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/issue-3546.rs: New test.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/issue-3885.rs: New test.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/const_generics_3.rs: this works now
+ * rust/compile/const_generics_5.rs: likewise
+ * rust/compile/const_generics_8.rs: move the failure to another test case
+ * rust/compile/const_generics_10.rs: New test.
+ * rust/compile/const_generics_11.rs: New test.
+ * rust/compile/const_generics_12.rs: New test.
+ * rust/compile/const_generics_13.rs: New test.
+ * rust/compile/const_generics_14.rs: New test.
+ * rust/compile/const_generics_15.rs: New test.
+ * rust/compile/const_generics_16.rs: New test.
+ * rust/compile/const_generics_9.rs: New test.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/issue-3960.rs: New test.
+
+2025-08-05 Ryutaro Okada <1015ryu88@gmail.com>
+
+ * rust/compile/auto_traits2.rs:
+ emove warning for unused `self` parameter
+ * rust/compile/derive-debug1.rs:
+ emove warning for unused `self` parameter
+ * rust/compile/derive_macro1.rs:
+ Remove warning for unused `self` parameter
+ * rust/compile/format_args_basic_expansion.rs:
+ Remove warning for unused `self` parameter
+ * rust/compile/format_args_extra_comma.rs:
+ Remove warning for unused `self` parameter
+ * rust/compile/issue-2043.rs:
+ Remove warning for unused `self` parameter
+ * rust/compile/issue-2166.rs:
+ Remove warning for unused `self` parameter
+ * rust/compile/issue-2238.rs:
+ Remove warning for unused `self` parameter
+ * rust/compile/issue-2907.rs:
+ Remove warning for unused `self` parameter
+ * rust/compile/min_specialization1.rs:
+ Remove warning for unused `self` parameter
+ * rust/compile/name_resolution2.rs:
+ Remove warning for unused `self` parameter
+ * rust/compile/name_resolution4.rs:
+ Remove warning for unused `self` parameter
+ * rust/compile/torture/generics29.rs:
+ Remove warning for unused `self` parameter
+ * rust/compile/torture/generics30.rs:
+ Remove warning for unused `self` parameter
+ * rust/compile/torture/traits3.rs:
+ Remove warning for unused `self` parameter
+ * rust/compile/torture/traits7.rs:
+ Remove warning for unused `self` parameter
+ * rust/execute/torture/impl_trait3.rs:
+ Remove warning for unused `self` parameter
+ * rust/execute/torture/min_specialization2.rs:
+ Remove warning for unused `self` parameter
+ * rust/execute/torture/trait10.rs:
+ Remove warning for unused `self` parameter
+ * rust/execute/torture/trait11.rs:
+ Remove warning for unused `self` parameter
+ * rust/execute/torture/trait12.rs:
+ Remove warning for unused `self` parameter
+ * rust/execute/torture/trait13.rs:
+ Remove warning for unused `self` parameter
+ * rust/execute/torture/trait9.rs:
+ Remove warning for unused `self` parameter
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * rust/compile/while_let1.rs: New test.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * rust/compile/offset_of2.rs: New test.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * rust/compile/offset_of1.rs: New test.
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * rust/compile/issue-4006.rs: New test.
+
+2025-08-05 Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * rust/execute/inline_asm_inout_ident.rs: New test.
+ * rust/execute/inline_asm_inout_var.rs: New test.
+
+2025-08-05 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * rust/compile/match-slicepattern-slice.rs: New file.
+ * rust/execute/torture/match-slicepattern-slice-1.rs: New file.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * rust/compile/try_block1.rs: New test.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * rust/compile/deferred_const_inference.rs: New test.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * rust/compile/glob_import_enum.rs: New test.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/issue-3915.rs: New test.
+ * rust/execute/torture/sip-hasher.rs: New test.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/issue-3916.rs: New test.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/issue-3978.rs: New test.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * rust/compile/parse_simple_path_fail_1.rs: New test.
+ * rust/compile/parse_simple_path_fail_2.rs: New test.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/issue-3524.rs: New test.
+
+2025-08-05 lishin <lishin1008@gmail.com>
+
+ * rust/compile/loop_constant_context.rs: New test.
+ * rust/compile/issue-3618.rs:
+
+2025-08-05 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * rust/compile/match-slicepattern-array.rs: New file.
+ * rust/execute/torture/match-slicepattern-array-1.rs: New file.
+
+2025-08-05 Yap Zhi Heng <yapzhhg@gmail.com>
+
+ * rust/compile/slicepattern-size-mismatch.rs: New file.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/execute/torture/issue-2005.rs: New test.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/issue-1048.rs: New test.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/issue-3144.rs: New test.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/issue-3599.rs: New test.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/issue-3876.rs: New test.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/issue-2680.rs: New test.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/derive_partial_ord1.rs: this is now fully supported
+ * rust/execute/torture/basic_partial_ord1.rs: add missing i32 impl
+ * rust/execute/torture/basic_partial_ord2.rs: likewise
+ * rust/compile/issue-3836.rs: New test.
+ * rust/execute/torture/issue-3836.rs: New test.
+ * rust/execute/torture/partial-ord-6.rs: New test.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/issue-3874.rs: New test.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/all-cast.rs: shows array capacity now
+ * rust/compile/arrays2.rs: likewise
+ * rust/compile/const3.rs: fix error message
+ * rust/compile/const_generics_3.rs: disable until typecheck we get proper errors now!
+ * rust/compile/usize1.rs: proper capacity error message
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * rust/compile/while_let_without_label.rs: New test.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * rust/compile/additional-trait-bounds2nr2.rs: Remove
+ -frust-name-resolution-2.0 usage.
+ * rust/compile/const_generics_3.rs: Likewise.
+ * rust/compile/enum_variant_name.rs: Likewise.
+ * rust/compile/generics9.rs: Likewise.
+ * rust/compile/invalid_label_name.rs: Likewise.
+ * rust/compile/issue-3304.rs: Likewise.
+ * rust/compile/macros/mbe/macro-issue3708.rs: Likewise.
+ * rust/compile/macros/mbe/macro-issue3709-2.rs: Likewise.
+ * rust/compile/name_resolution10.rs: Likewise.
+ * rust/compile/name_resolution11.rs: Likewise.
+ * rust/compile/name_resolution12.rs: Likewise.
+ * rust/compile/name_resolution13.rs: Likewise.
+ * rust/compile/name_resolution14.rs: Likewise.
+ * rust/compile/name_resolution15.rs: Likewise.
+ * rust/compile/name_resolution16.rs: Likewise.
+ * rust/compile/name_resolution17.rs: Likewise.
+ * rust/compile/name_resolution18.rs: Likewise.
+ * rust/compile/name_resolution20.rs: Likewise.
+ * rust/compile/name_resolution22.rs: Likewise.
+ * rust/compile/name_resolution23.rs: Likewise.
+ * rust/compile/name_resolution24.rs: Likewise.
+ * rust/compile/name_resolution25.rs: Likewise.
+ * rust/compile/name_resolution6.rs: Likewise.
+ * rust/compile/name_resolution7.rs: Likewise.
+ * rust/compile/name_resolution8.rs: Likewise.
+ * rust/compile/name_resolution9.rs: Likewise.
+ * rust/compile/nested_macro_definition.rs: Likewise.
+ * rust/compile/pub_restricted_1.rs: Likewise.
+ * rust/compile/pub_restricted_2.rs: Likewise.
+ * rust/compile/self-in-impl.rs: Likewise.
+ * rust/compile/self_import_namespace.rs: Likewise.
+ * rust/compile/use_1.rs: Likewise.
+ * rust/compile/xfail/name_resolution21.rs: Likewise.
+ * rust/execute/torture/name_resolution.rs: Likewise.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * rust/compile/nr2/compile.exp: Removed.
+ * rust/compile/nr2/exclude: Removed.
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * rust/compile/match-restpattern-tuple-1.rs: New file.
+ * rust/compile/match-restpattern-tuple-2.rs: New file.
+ * rust/execute/torture/match-restpattern-tuple.rs: New file.
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * rust/compile/tuple_mismatch.rs: Include RestPattern in test.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * rust/compile/nr2/exclude: Remove issue-3315-2.rs.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * rust/compile/nr2/exclude: Remove torture/alt_patterns1.rs.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * rust/compile/macros/builtin/recurse2.rs: Match "abheyho\0" as
+ well as "abheyho", to handle slight differences in assembly
+ output for null-terminated strings.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/issue-3525.rs: New test.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/issue-3551.rs: New test.
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * rust/compile/match-tuplestructpattern.rs: New file.
+ * rust/execute/torture/match-tuplestructpattern.rs: New file.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * rust/compile/nr2/exclude: Remove issue-3642.rs.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/silly-order-bug.rs: New test.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * rust/compile/nr2/exclude: Remove entries.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/execute/torture/issue-1481.rs: New test.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/nr2/exclude: nr2 puts out an extra error
+ * rust/compile/issue-3642.rs: New test.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * rust/execute/black_box.rs: Return 0 from main.
+ * rust/execute/match-identifierpattern-enum.rs: Move to...
+ * rust/execute/xfail/match-identifierpattern-enum.rs: ...here.
+ * rust/execute/execute.exp: New file.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/bug-with-default-generic.rs: New test.
+ * rust/execute/torture/partial-eq-1.rs: New test.
+ * rust/execute/torture/partial-eq-2.rs: New test.
+ * rust/execute/torture/partial-eq-3.rs: New test.
+ * rust/execute/torture/partial-eq-4.rs: New test.
+ * rust/execute/torture/partial-ord-1.rs: New test.
+ * rust/execute/torture/partial-ord-2.rs: New test.
+ * rust/execute/torture/partial-ord-3.rs: New test.
+ * rust/execute/torture/partial-ord-4.rs: New test.
+ * rust/execute/torture/partial-ord-5.rs: New test.
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * rust/compile/match-identifierpattern-enum.rs: New file.
+ * rust/execute/match-identifierpattern-enum.rs: New file.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * rust/compile/nr2/exclude: Remove entries.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * rust/compile/derive_partial_ord1.rs: New test.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * rust/execute/torture/derive-partialeq2.rs: Add declaration for
+ discriminant_value.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/execute/torture/basic_partial_ord1.rs: New test.
+ * rust/execute/torture/basic_partial_ord2.rs: New test.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/const_generics_3.rs:
+ * rust/compile/issue-3660.rs: New test.
+
+2025-08-05 Zhi Heng <yapzhhg@gmail.com>
+
+ * rust/compile/match-identifierpattern.rs: New file.
+ * rust/execute/torture/match-identifierpattern.rs: New file.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * rust/compile/nr2/exclude: Remove entries.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * rust/compile/nr2/exclude: Remove entries.
+ * rust/compile/pub_restricted_1.rs: Adjust expected error
+ messages and only run with name resolution 2.0 enabled.
+ * rust/compile/pub_restricted_2.rs: Likewise.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * rust/compile/nr2/exclude: Remove canonical_paths1.rs.
+
+2025-08-05 Vishruth-Thimmaiah <vishruththimmaiah@gmail.com>
+
+ * rust/compile/torture/unended-raw-byte-string.rs:
+ New test to ensure correct error message for unended raw byte string.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * rust/compile/issue-3671.rs: Remove usage of Self.
+ * rust/compile/nr2/exclude: Remove issue-3671.rs.
+ * rust/compile/self-in-impl.rs: New test.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * rust/compile/nr2/exclude: Remove entries.
+
+2025-08-05 Vishruth-Thimmaiah <vishruththimmaiah@gmail.com>
+
+ * rust/compile/torture/extern_mod2.rs:
+ New test to ensure an error is emitted for empty path attributes.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * rust/execute/torture/const_block1.rs: New test.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/traits9.rs: update errors
+ * rust/compile/unify-errors1.rs: New test.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/bad-rpit1.rs: New test.
+ * rust/execute/torture/impl_rpit1.rs: New test.
+ * rust/execute/torture/impl_rpit2.rs: New test.
+ * rust/execute/torture/impl_rpit3.rs: New test.
+
+2025-08-05 Parthib <parthibdutta02@gmail.com>
+
+ * lib/rust.exp: Remove timeout.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * rust/execute/torture/for-loop1.rs: Adjust paths.
+ * rust/execute/torture/for-loop2.rs: Likewise.
+ * rust/execute/torture/iter1.rs: Likewise.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * rust/execute/torture/builtin_abort.rs: Fix path to
+ intrinsics::abort.
+
+2025-08-05 Tom Schollenberger <tss2344@g.rit.edu>
+
+ * rust/compile/issue-3661.rs: Test NR2 has expected behavior
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * rust/compile/macros/mbe/meta-param.rs: New test.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * rust/execute/same_field_name.rs: Move to...
+ * rust/compile/same_field_name.rs: ...here and adjust expected
+ errors.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/nr2/exclude: these are fixed now
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * rust/compile/nr2/exclude: Remove entries.
+
+2025-08-05 Tom Schollenberger <tss2344@g.rit.edu>
+
+ * rust/compile/issue-3618.rs: Test empty loops error properly.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/nr2/exclude: nr2 cant handle this
+ * rust/compile/impl_trait_generic_arg.rs: New test.
+
+2025-08-05 Owen Avery <powerboat9.gamer@gmail.com>
+
+ * rust/execute/torture/struct-pattern-match.rs: New test.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/issue-2015.rs: fully supported now
+ * rust/compile/nr2/exclude: nr2 cant handle some of these
+ * rust/compile/issue-1487.rs: New test.
+ * rust/compile/issue-3454.rs: New test.
+ * rust/execute/torture/impl_desugar-2.rs: New test.
+ * rust/execute/torture/impl_desugar.rs: New test.
+ * rust/execute/torture/impl_trait1.rs: New test.
+ * rust/execute/torture/impl_trait2.rs: New test.
+ * rust/execute/torture/impl_trait3.rs: New test.
+ * rust/execute/torture/impl_trait4.rs: New test.
+ * rust/execute/torture/issue-1482.rs: New test.
+
+2025-08-05 Philip Herron <herron.philip@googlemail.com>
+
+ * rust/compile/impl_trait_diag.rs: New test.
+ * rust/compile/issue-1485.rs: New test.
+
+2025-08-05 CohenArthur <cohenarthur.dev@gmail.com>
+ Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
+
+ * rust/execute/torture/derive-partialeq2.rs: Add missing terminating nul char.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * rust/execute/torture/derive-partialeq2.rs: New test.
+
+2025-08-05 Arthur Cohen <arthur.cohen@embecosm.com>
+
+ * rust/execute/torture/struct_pattern1.rs: New test.
+
+2025-08-05 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/121359
+ * gcc.target/avr/torture/pr118591-1.c: Remove -mlra.
+ * gcc.target/avr/torture/pr118591-2.c: Same.
+
+2025-08-05 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/121395
+ * gcc.dg/vect/pr59984.c: Adjust.
+
+2025-08-05 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/121382
+ * gcc.dg/torture/pr121382.c: New testcase.
+
+2025-08-05 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/121370
+ * gcc.dg/torture/pr121370.c: New testcase.
+
+2025-08-05 Yang Yujie <yangyujie@loongson.cn>
+
+ * gcc.dg/bitintext.h (S, CEIL, PROMOTED_SIZE): Define.
+ (BEXTC): Generalize to only check extension within PROMOTED_SIZE bits.
+
+2025-08-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR preprocessor/120778
+ * g++.dg/DRs/dr2579.C: New test.
+ * c-c++-common/cpp/va-opt-6.c: Expect ' rather than \" around
+ tokens in incorrect pasting diagnostics.
+ * gcc.dg/c23-attr-syntax-6.c: Likewise.
+ * gcc.dg/cpp/paste12.c: Likewise.
+ * gcc.dg/cpp/paste12-2.c: Likewise.
+ * gcc.dg/cpp/paste14.c: Likewise.
+ * gcc.dg/cpp/paste14-2.c: Likewise.
+
+2025-08-05 Pan Li <pan2.li@intel.com>
+
+ * gcc.target/riscv/sat/sat_u_mul-1-u32-from-u64.c: Add mulhu
+ asm check.
+ * gcc.target/riscv/sat/sat_u_mul-1-u64-from-u128.c: Ditto.
+
+2025-08-04 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/121351
+ * g++.dg/cpp2a/concepts-using6.C: New test.
+
+2025-08-04 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/121351
+ PR c++/119859
+ * g++.dg/cpp2a/concepts-using5.C: New test.
+ * g++.dg/cpp2a/concepts-using5a.C: New test.
+
+2025-08-04 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/120620
+ * g++.dg/cpp2a/constexpr-dynamic19.C: New test.
+ * g++.dg/cpp2a/constexpr-dynamic1a.C: New test.
+
+2025-08-04 David Malcolm <dmalcolm@redhat.com>
+
+ PR diagnostics/116253
+ * gcc.dg/plugin/diagnostic-test-nesting-html.c: New test.
+ * gcc.dg/plugin/diagnostic-test-nesting-html.py: New test script.
+ * gcc.dg/plugin/plugin.exp: Add it.
+ * libgdiagnostics.dg/test-multiple-lines.c: Update expected output
+ to show fix-it hint.
+ * sarif-replay.dg/2.1.0-valid/nested-diagnostics-1.sarif: New test.
+
+2025-08-04 David Malcolm <dmalcolm@redhat.com>
+
+ PR diagnostics/116792
+ * gcc.dg/plugin/diagnostic-test-graphs-html.py: Remove trailing
+ space from expected text of message.
+ * sarif-replay.dg/2.1.0-valid/embedded-links-check-html.py:
+ Likewise.
+ * sarif-replay.dg/2.1.0-valid/graphs-check-html.py: Likewise.
+
+2025-08-04 Konstantinos Eleftheriou <konstantinos.eleftheriou@vrull.eu>
+
+ PR rtl-optimization/121303
+ * gcc.target/i386/pr121303.c: New test.
+
+2025-08-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR preprocessor/120778
+ * g++.dg/DRs/dr2580.C: New test.
+
+2025-08-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR preprocessor/120778
+ * g++.dg/DRs/dr2578.C: New test.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/sve/acle/general/dupq_13.c: New test.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/sve/acle/general/dup_1.c: New test.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/sve/acle/general/pnext_3.c: New test.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/sve2/acle/general/match_4.c: New test.
+ * gcc.target/aarch64/sve2/acle/general/nmatch_1.c: Likewise.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/sve/acle/general/acge_1.c: New test.
+ * gcc.target/aarch64/sve/acle/general/acgt_1.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/acle_1.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/aclt_1.c: Likewise.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/sve/acle/general/cmpeq_6.c: New test.
+ * gcc.target/aarch64/sve/acle/general/cmpge_9.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmpgt_9.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmple_9.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmplt_9.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmpne_5.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmpuo_1.c: Likewise.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/sve/acle/general/cmpeq_5.c: New test.
+ * gcc.target/aarch64/sve/acle/general/cmpge_7.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmpge_8.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmpgt_7.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmpgt_8.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmple_7.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmple_8.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmplt_7.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmplt_8.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmpne_4.c: Likewise.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/sve/acle/general/cmpeq_1.c: Check the number
+ of PTRUEs.
+ * gcc.target/aarch64/sve/acle/general/cmpge_5.c: New test.
+ * gcc.target/aarch64/sve/acle/general/cmpge_6.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmpgt_5.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmpgt_6.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmple_5.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmple_6.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmplt_5.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmplt_6.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmpne_3.c: Likewise.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/sve/acle/general/cmpeq_1.c: Add more tests.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/sve/pred_clobber_1.c: Disable combine.
+ * gcc.target/aarch64/sve/pred_clobber_2.c: Likewise.
+ * gcc.target/aarch64/sve/pred_clobber_3.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmpeq_2.c: Add more cases.
+ * gcc.target/aarch64/sve/acle/general/cmpeq_4.c: New test.
+ * gcc.target/aarch64/sve/acle/general/cmpge_1.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmpge_2.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmpge_3.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmpge_4.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmpgt_1.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmpgt_2.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmpgt_3.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmpgt_4.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmple_1.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmple_2.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmple_3.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmple_4.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmplt_1.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmplt_2.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmplt_3.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmplt_4.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmpne_1.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/cmpne_2.c: Likewise.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/sve/acle/general/unpkhi_1.c: New test.
+ * gcc.target/aarch64/sve/acle/general/unpklo_1.c: Likewise.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR target/121294
+ * gcc.target/aarch64/sve/acle/general/rev_2.c: New test.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR target/121294
+ * gcc.target/aarch64/sve/acle/general/perm_2.c: New test.
+ * gcc.target/aarch64/sve/acle/general/perm_3.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/perm_4.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/perm_5.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/perm_6.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/perm_7.c: Likewise.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR testsuite/121118
+ * gcc.target/aarch64/sve/acle/general/pr121118_1.c: New test.
+ * gcc.target/aarch64/sve/acle/general/whilele_13.c: Likewise.
+ * gcc.target/aarch64/sve/acle/general/whilelt_6.c: Likewise.
+ * gcc.target/aarch64/sve2/acle/general/whilege_1.c: Likewise.
+ * gcc.target/aarch64/sve2/acle/general/whilegt_1.c: Likewise.
+ * gcc.target/aarch64/sve2/acle/general/whilerw_5.c: Likewise.
+ * gcc.target/aarch64/sve2/acle/general/whilewr_5.c: Likewise.
+
+2025-08-04 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR target/121293
+ * gcc.target/aarch64/sve/acle/general/dupq_lane_9.c: New test.
+
+2025-08-04 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/121362
+ * gcc.dg/tree-ssa/ssa-fre-105.c: New testcase.
+ * gcc.dg/tree-ssa/ssa-fre-106.c: Likewise.
+
+2025-08-04 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/120941
+ * gcc.target/i386/pr120941-1.c: New test.
+
+2025-08-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR preprocessor/120778
+ * g++.dg/DRs/dr1709.C: New test.
+
+2025-08-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/120845
+ * g++.dg/modules/cpp-21.C: New test.
+
2025-08-02 Martin Uecker <uecker@tugraz.at>
* gcc.dg/Warray-parameter-11.c: Change Warray-parameter to
diff --git a/gcc/testsuite/c-c++-common/cpp/va-opt-6.c b/gcc/testsuite/c-c++-common/cpp/va-opt-6.c
index 8a7761b..9a92431 100644
--- a/gcc/testsuite/c-c++-common/cpp/va-opt-6.c
+++ b/gcc/testsuite/c-c++-common/cpp/va-opt-6.c
@@ -3,15 +3,15 @@
/* { dg-options "-std=c++20" { target c++ } } */
#define a ""
-#define b(...) a ## #__VA_OPT__(1) /* { dg-error "pasting \"a\" and \"\"\"\" does not give a valid preprocessing token" } */
-#define c(...) a ## #__VA_OPT__(1) /* { dg-error "pasting \"a\" and \"\"1\"\" does not give a valid preprocessing token" } */
+#define b(...) a ## #__VA_OPT__(1) /* { dg-error "pasting 'a' and '\"\"' does not give a valid preprocessing token" } */
+#define c(...) a ## #__VA_OPT__(1) /* { dg-error "pasting 'a' and '\"1\"' does not give a valid preprocessing token" } */
#define d(...) #__VA_OPT__(1) ## !
#define e(...) #__VA_OPT__(1) ## !
#define f(...) #__VA_OPT__(. ## !)
#define g(...) #__VA_OPT__(. ## !)
b()
c(1)
-d( ) /* { dg-error "pasting \"\"\"\" and \"!\" does not give a valid preprocessing token" } */
-e( 1 ) /* { dg-error "pasting \"\"1\"\" and \"!\" does not give a valid preprocessing token" } */
+d( ) /* { dg-error "pasting '\"\"' and '!' does not give a valid preprocessing token" } */
+e( 1 ) /* { dg-error "pasting '\"1\"' and '!' does not give a valid preprocessing token" } */
f()
-g(0) /* { dg-error "pasting \".\" and \"!\" does not give a valid preprocessing token" } */
+g(0) /* { dg-error "pasting '.' and '!' does not give a valid preprocessing token" } */
diff --git a/gcc/testsuite/c-c++-common/gomp/map-6.c b/gcc/testsuite/c-c++-common/gomp/map-6.c
index 852839e..d76f9ae 100644
--- a/gcc/testsuite/c-c++-common/gomp/map-6.c
+++ b/gcc/testsuite/c-c++-common/gomp/map-6.c
@@ -13,20 +13,20 @@ foo (void)
#pragma omp target map (to:a)
;
- #pragma omp target map (a to: b) /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'mapper' or 'present'" "" { target c++ } } */
- ; /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'mapper' or 'present' before 'a'" "" { target c } .-1 } */
+ #pragma omp target map (a to: b) /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'iterator', 'mapper' or 'present'" "" { target c++ } } */
+ ; /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'iterator', 'mapper' or 'present' before 'a'" "" { target c } .-1 } */
- #pragma omp target map (close, a to: b) /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'mapper' or 'present'" "" { target c++ } } */
- ; /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'mapper' or 'present' before 'a'" "" { target c } .-1 } */
+ #pragma omp target map (close, a to: b) /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'iterator', 'mapper' or 'present'" "" { target c++ } } */
+ ; /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'iterator', 'mapper' or 'present' before 'a'" "" { target c } .-1 } */
- #pragma omp target enter data map(b7) map (close, a to: b) /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'mapper' or 'present'" "" { target c++ } } */
- ; /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'mapper' or 'present' before 'a'" "" { target c } .-1 } */
+ #pragma omp target enter data map(b7) map (close, a to: b) /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'iterator', 'mapper' or 'present'" "" { target c++ } } */
+ ; /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'iterator', 'mapper' or 'present' before 'a'" "" { target c } .-1 } */
- #pragma omp target exit data map(b7) map (close, a from: b) /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'mapper' or 'present'" "" { target c++ } } */
- ; /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'mapper' or 'present' before 'a'" "" { target c } .-1 } */
+ #pragma omp target exit data map(b7) map (close, a from: b) /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'iterator', 'mapper' or 'present'" "" { target c++ } } */
+ ; /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'iterator', 'mapper' or 'present' before 'a'" "" { target c } .-1 } */
- #pragma omp target data map(b7) map (close, a from: b) /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'mapper' or 'present'" "" { target c++ } } */
- ; /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'mapper' or 'present' before 'a'" "" { target c } .-1 } */
+ #pragma omp target data map(b7) map (close, a from: b) /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'iterator', 'mapper' or 'present'" "" { target c++ } } */
+ ; /* { dg-error "'map' clause with map-type modifier other than 'always', 'close', 'iterator', 'mapper' or 'present' before 'a'" "" { target c } .-1 } */
#pragma omp target map (close a) /* { dg-error "'close' undeclared" "" { target c } } */
diff --git a/gcc/testsuite/c-c++-common/gomp/target-map-iterators-1.c b/gcc/testsuite/c-c++-common/gomp/target-map-iterators-1.c
new file mode 100644
index 0000000..7d6c8dc
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/target-map-iterators-1.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+#define DIM1 17
+#define DIM2 39
+
+void f (int **x, int **y)
+{
+ #pragma omp target map(iterator(i=0:DIM1), to: x[i][:DIM2])
+ ;
+
+ #pragma omp target map(iterator(i=0:DIM1), to: x[i][:DIM2], y[i][:DIM2])
+ ;
+
+ #pragma omp target map(iterator(i=0:DIM1), to: x[i][:DIM2] + 2) /* { dg-message "unsupported map expression" } */
+ ;
+
+ #pragma omp target map(iterator(i=0:DIM1), iterator(j=0:DIM2), to: x[i][j]) /* { dg-error "too many 'iterator' modifiers" } */
+ ;
+
+ #pragma omp target map(iterator(i=0:DIM1), to: (i % 2 == 0) ? x[i] : y[i]) /* { dg-message "unsupported map expression" } */
+ ;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/target-map-iterators-2.c b/gcc/testsuite/c-c++-common/gomp/target-map-iterators-2.c
new file mode 100644
index 0000000..42c6d75
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/target-map-iterators-2.c
@@ -0,0 +1,41 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp -fdump-tree-gimple" } */
+
+void f (int *x, float *y, double *z)
+{
+ #pragma omp target map(iterator(i=0:10), to: x) /* { dg-warning "iterator variable 'i' not used in clause expression" } */
+ /* Add a reference to x to ensure that the 'to' clause does not get
+ dropped. */
+ x[0] = 0;
+
+ #pragma omp target map(iterator(i2=0:10, j2=0:20), from: x[i2]) /* { dg-warning "iterator variable 'j2' not used in clause expression" } */
+ ;
+
+ #pragma omp target map(iterator(i3=0:10, j3=0:20, k3=0:30), to: x[i3+j3], y[j3+k3], z[k3+i3])
+ /* { dg-warning "iterator variable 'i3' not used in clause expression" "" { target *-*-* } .-1 } */
+ /* { dg-warning "iterator variable 'j3' not used in clause expression" "" { target *-*-* } .-2 } */
+ /* { dg-warning "iterator variable 'k3' not used in clause expression" "" { target *-*-* } .-3 } */
+ ;
+
+ /* Test iterator with zero iterations. */
+ #pragma omp target map(iterator(i4=0:0), to: x[i4]) /* { dg-warning "iteration count is zero" } */
+ ;
+
+ /* Test iterator where the beginning is greater than the end. */
+ #pragma omp target map(iterator(i5=10:0), to: x[i5]) /* { dg-warning "iteration count is zero" } */
+ ;
+
+ /* Test iterator where the beginning is greater than the end, but with a
+ negative step. */
+ #pragma omp target map(iterator(i6=10:0:-1), to: x[i6])
+ ;
+}
+
+/* { dg-final { scan-tree-dump-times "map\\\(to:x" 1 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "map\\\(iterator\\\(int i2=0:10:1, loop_label=\[^\\\)\]+\\\):from:" 1 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "map\\\(iterator\\\(int i3=0:10:1, int j3=0:20:1, loop_label=\[^\\\)\]+\\\):to:" 1 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "map\\\(iterator\\\(int j3=0:20:1, int k3=0:30:1, loop_label=\[^\\\)\]+\\\):to:" 1 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "map\\\(iterator\\\(int i3=0:10:1, int k3=0:30:1, loop_label=\[^\\\)\]+\\\):to:" 1 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "map\\\(iterator\\\(int i4=0:0:1, loop_label=\[^\\\)\]+\\\):to:" 1 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "map\\\(iterator\\\(int i5=10:0:1, loop_label=\[^\\\)\]+\\\):to:" 1 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "map\\\(iterator\\\(int i6=10:0:-1, loop_label=\[^\\\)\]+\\\):to:" 1 "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/gomp/target-map-iterators-3.c b/gcc/testsuite/c-c++-common/gomp/target-map-iterators-3.c
new file mode 100644
index 0000000..62df42f
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/target-map-iterators-3.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp -fdump-tree-gimple" } */
+
+#define DIM1 10
+#define DIM2 20
+#define DIM3 30
+
+void f (int ***x, float ***y, double **z)
+{
+ #pragma omp target \
+ map(to: x, y) \
+ map(iterator(i=0:DIM1, j=0:DIM2), to: x[i][j][:DIM3], y[i][j][:DIM3]) \
+ map(from: z) \
+ map(iterator(i=0:DIM1), from: z[i][:DIM2])
+ ;
+}
+
+/* { dg-final { scan-tree-dump-times "if \\(i <= 9\\) goto <D\\\.\[0-9\]+>; else goto <D\\\.\[0-9\]+>;" 3 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "if \\(j <= 19\\) goto <D\\\.\[0-9\]+>; else goto <D\\\.\[0-9\]+>;" 1 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "map\\(iterator\\(int i=0:10:1, loop_label=<D\\\.\[0-9\]+>, elems=omp_iter_data\\\.\[0-9\]+, index=D\\\.\[0-9\]+\\):from:\\*D\\\.\[0-9\]+" 1 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "map\\(iterator\\(int i=0:10:1, loop_label=<D\\\.\[0-9\]+>, elems=omp_iter_data\\\.\[0-9\]+, index=D\\\.\[0-9\]+\\):attach:\\*D\\\.\[0-9\]+" 1 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "map\\(iterator\\(int i=0:10:1, int j=0:20:1, loop_label=<D\\\.\[0-9\]+>, elems=omp_iter_data\\\.\[0-9\]+, index=D\\\.\[0-9\]+\\):to:\\*D\\\.\[0-9\]+" 2 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "map\\(iterator\\(int i=0:10:1, int j=0:20:1, loop_label=<D\\\.\[0-9\]+>, elems=omp_iter_data\\\.\[0-9\]+, index=D\\\.\[0-9\]+\\):attach:\\*D\\\.\[0-9\]+" 4 "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/gomp/target-map-iterators-4.c b/gcc/testsuite/c-c++-common/gomp/target-map-iterators-4.c
new file mode 100644
index 0000000..5dc5ad5
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/target-map-iterators-4.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp -fdump-tree-gimple" } */
+/* { dg-additional-options "-std=c++98" { target c++ } } */
+
+int bar (int, int);
+void baz (int, int *);
+#pragma omp declare target enter (baz)
+
+void
+foo (int x, int *p)
+{
+ #pragma omp target map (iterator (i=0:4), to: p[bar (x, i)])
+ baz (x, p);
+}
+
+/* { dg-final { scan-tree-dump "firstprivate\\\(x\\\)" "gimple" } } */
+/* { dg-final { scan-tree-dump-times "bar \\\(x, i\\\)" 2 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "map\\\(iterator\\\(int i=0:4:1, loop_label=" 2 "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/gomp/target-update-iterators-1.c b/gcc/testsuite/c-c++-common/gomp/target-update-iterators-1.c
new file mode 100644
index 0000000..53b22f0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/target-update-iterators-1.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+#define DIM1 17
+#define DIM2 39
+
+void f (int **x, float **y)
+{
+ #pragma omp target update to (iterator(i=0:DIM1): x[i][:DIM2])
+
+ #pragma omp target update to (iterator(i=0:DIM1): x[i][:DIM2], y[i][:DIM2])
+
+ #pragma omp target update to (iterator(i=0:DIM1), present: x[i][:DIM2])
+
+ #pragma omp target update to (iterator(i=0:DIM1), iterator(j=0:DIM2): x[i][j]) /* { dg-error "too many 'iterator' modifiers" } */
+ /* { dg-error "'#pragma omp target update' must contain at least one 'from' or 'to' clauses" "" { target *-*-* } .-1 } */
+
+ #pragma omp target update from (iterator(i=0:DIM1), something: x[i][j]) /* { dg-error "'from' clause with modifier other than 'iterator' or 'present'" } */
+ /* { dg-error "expected '\\)' before 'something'" "" { target c } .-1 } */
+ /* { dg-error "'#pragma omp target update' must contain at least one 'from' or 'to' clauses" "" { target *-*-* } .-2 } */
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/target-update-iterators-2.c b/gcc/testsuite/c-c++-common/gomp/target-update-iterators-2.c
new file mode 100644
index 0000000..dbd43e0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/target-update-iterators-2.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp -fdump-tree-gimple" } */
+
+void f (int *x, float *y, double *z)
+{
+ #pragma omp target update to(iterator(i=0:10): x) /* { dg-warning "iterator variable 'i' not used in clause expression" }*/
+ ;
+
+ #pragma omp target update from(iterator(i2=0:10, j2=0:20): x[i2]) /* { dg-warning "iterator variable 'j2' not used in clause expression" }*/
+ ;
+
+ #pragma omp target update to(iterator(i3=0:10, j3=0:20, k3=0:30): x[i3+j3], y[j3+k3], z[k3+i3])
+ /* { dg-warning "iterator variable 'i3' not used in clause expression" "" { target *-*-* } .-1 } */
+ /* { dg-warning "iterator variable 'j3' not used in clause expression" "" { target *-*-* } .-2 } */
+ /* { dg-warning "iterator variable 'k3' not used in clause expression" "" { target *-*-* } .-3 } */
+ ;
+}
+
+/* { dg-final { scan-tree-dump "update to\\\(x " "gimple" } } */
+/* { dg-final { scan-tree-dump "update from\\\(iterator\\\(int i2=0:10:1, loop_label=" "gimple" } } */
+/* { dg-final { scan-tree-dump "to\\\(iterator\\\(int i3=0:10:1, int k3=0:30:1, loop_label=" "gimple" } } */
+/* { dg-final { scan-tree-dump "to\\\(iterator\\\(int j3=0:20:1, int k3=0:30:1, loop_label=" "gimple" } } */
+/* { dg-final { scan-tree-dump "to\\\(iterator\\\(int i3=0:10:1, int j3=0:20:1, loop_label=" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/gomp/target-update-iterators-3.c b/gcc/testsuite/c-c++-common/gomp/target-update-iterators-3.c
new file mode 100644
index 0000000..ef55216
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/target-update-iterators-3.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp -fdump-tree-gimple" } */
+
+#define DIM1 10
+#define DIM2 20
+#define DIM3 30
+
+void f (int ***x, float ***y, double **z)
+{
+ #pragma omp target update to (iterator(i=0:DIM1, j=0:DIM2): x[i][j][:DIM3], y[i][j][:DIM3])
+ #pragma omp target update from (iterator(i=0:DIM1): z[i][:DIM2])
+}
+
+/* { dg-final { scan-tree-dump-times "if \\(i <= 9\\) goto <D\.\[0-9\]+>; else goto <D\.\[0-9\]+>;" 2 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "if \\(j <= 19\\) goto <D\.\[0-9\]+>; else goto <D\.\[0-9\]+>;" 1 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "to\\(iterator\\(int i=0:10:1, int j=0:20:1, loop_label=<D\.\[0-9\]+>, elems=omp_iter_data\.\[0-9\]+, index=D\.\[0-9\]+\\):\\*D\.\[0-9\]+" 2 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "from\\(iterator\\(int i=0:10:1, loop_label=<D\.\[0-9\]+>, elems=omp_iter_data\.\[0-9\]+, index=D\.\[0-9\]+\\):\\*D\.\[0-9\]+" 1 "gimple" } } */
diff --git a/gcc/testsuite/g++.dg/DRs/dr1709.C b/gcc/testsuite/g++.dg/DRs/dr1709.C
new file mode 100644
index 0000000..d3854d8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/DRs/dr1709.C
@@ -0,0 +1,18 @@
+// DR 1709 - Stringizing raw string literals containing newline
+// { dg-do run { target c++26 } }
+
+#define A(a) #a
+const char *a = A(a\f\\b"c");
+const char *b = A(R"abc(a\b
+
+)abc");
+
+int
+main ()
+{
+ if (a[1] != '\f' || a[2] != '\\' || a[4] != '"' || a[6] != '"')
+ __builtin_abort ();
+ if (b[1] != '"' || b[7] != '\\' || b[9] != '\n' || b[10] != '\n'
+ || b[11] != ')' || b[15] != '"')
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/DRs/dr2578.C b/gcc/testsuite/g++.dg/DRs/dr2578.C
new file mode 100644
index 0000000..0dce23b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/DRs/dr2578.C
@@ -0,0 +1,10 @@
+// DR 2578 - Undefined behavior when creating an invalid string literal via stringizing
+// { dg-do preprocess }
+// { dg-options "-pedantic-errors" }
+
+#define A(a) #a
+#define B(a) A(a)
+#define C \\
+
+const char *x = B(C); // { dg-warning "invalid string literal, ignoring final '\\\\'" "" { target c++23_down } }
+// { dg-error "invalid string literal, ignoring final '\\\\'" "" { target c++26 } .-1 }
diff --git a/gcc/testsuite/g++.dg/DRs/dr2579.C b/gcc/testsuite/g++.dg/DRs/dr2579.C
new file mode 100644
index 0000000..dda3643
--- /dev/null
+++ b/gcc/testsuite/g++.dg/DRs/dr2579.C
@@ -0,0 +1,9 @@
+// DR 2579 - Undefined behavior when token pasting does not create a preprocessing token
+// { dg-do preprocess }
+// { dg-options "-pedantic-errors" }
+
+#define A(a, b) a ## b
+A(5,6)
+A(-,32) // { dg-error "pasting '-' and '32' does not give a valid preprocessing token" }
+A("","") // { dg-error "pasting '\"\"' and '\"\"' does not give a valid preprocessing token" }
+A(\,u0393)
diff --git a/gcc/testsuite/g++.dg/DRs/dr2580.C b/gcc/testsuite/g++.dg/DRs/dr2580.C
new file mode 100644
index 0000000..462f300
--- /dev/null
+++ b/gcc/testsuite/g++.dg/DRs/dr2580.C
@@ -0,0 +1,87 @@
+// DR 2580 - Undefined behavior with #line
+// { dg-do preprocess }
+
+#line 630 "foobar.h"
+#line 6 "dr2580.C"
+#line 0 // { dg-error "line number out of range" }
+#line 8
+#line 2147483648 // { dg-error "line number out of range" }
+#line 10
+#line 4294967295 // { dg-error "line number out of range" }
+#line 12
+#line 12345678912345 // { dg-error "line number out of range" }
+#line 14
+#line 15 ""
+#line 16 "foobar.h"
+#line 17 "/a/b/c/baz.h"
+#line 18 "dr2580.C"
+#line 0 "dr2580.C" // { dg-error "line number out of range" }
+#line 20
+#line 2147483648 "dr2580.C" // { dg-error "line number out of range" }
+#line 22
+#line 4294967295 "dr2580.C" // { dg-error "line number out of range" }
+#line 24
+#line 12345678912345 "dr2580.C" // { dg-error "line number out of range" }
+#line 26
+#line 27 1 // { dg-error "'1' is not a valid filename" }
+#line 28
+#line 29 foo bar baz // { dg-error "'foo' is not a valid filename" }
+#line 30
+#line 31 "dr2580.C" 1 // { dg-error "extra tokens at end of '#line' directive" }
+#line 32
+#line 33 "dr2580.C" foo bar baz // { dg-error "extra tokens at end of '#line' directive" }
+#define A 35
+#line A
+#define B 0
+#line B // { dg-error "line number out of range" }
+#line 38
+#define C 2147483648
+#line C // { dg-error "line number out of range" }
+#line 41
+#define D 4294967295
+#line D // { dg-error "line number out of range" }
+#line 44
+#define E 12345678912345
+#line E // { dg-error "line number out of range" }
+#line 47
+#define F 49 "dr2580.C"
+#line F
+#define G 0 "dr2580.C"
+#line G // { dg-error "line number out of range" }
+#line 52 "dr2580.C"
+#define H 2147483647 "dr2580.C"
+#line H // { dg-error "line number out of range" "" { target c++98_only } }
+#line 55
+#define I 2147483648 "dr2580.C"
+#line I // { dg-error "line number out of range" }
+#line 58
+#define J 4294967295 "dr2580.C"
+#line J // { dg-error "line number out of range" }
+#line 61
+#define K 12345678912345 "dr2580.C"
+#line K // { dg-error "line number out of range" }
+#line 64
+#define M 7 0
+#line M // { dg-error "'0' is not a valid filename" }
+#line 67
+#define N 90 foo bar baz
+#line N // { dg-error "'foo' is not a valid filename" }
+#line 70
+#define O 75 "dr2580.C" 2
+#line O // { dg-error "extra tokens at end of '#line' directive" }
+#line 73
+#define P 90 "dr2580.C" foo bar baz
+#line P // { dg-error "extra tokens at end of '#line' directive" }
+#line 76
+#line -5 // { dg-error "'-' after '#line' is not a positive integer" }
+#line 78
+#line -7 "dr2580.C" // { dg-error "'-' after '#line' is not a positive integer" }
+#line 80
+#line 32767
+#line 82
+#line 32768 // { dg-error "line number out of range" "" { target c++98_only } }
+#line 84
+#line 32767 "dr2580.C"
+#line 86
+#line 32768 "dr2580.C" // { dg-error "line number out of range" "" { target c++98_only } }
+#line 88
diff --git a/gcc/testsuite/g++.dg/cpp26/constexpr-new5.C b/gcc/testsuite/g++.dg/cpp26/constexpr-new5.C
new file mode 100644
index 0000000..b98b9e9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/constexpr-new5.C
@@ -0,0 +1,43 @@
+// PR c++/121068
+// { dg-do compile { target c++26 } }
+
+#include <new>
+
+struct S
+{
+ constexpr S() = default;
+ constexpr S(int x) : s(x) {}
+ constexpr S(S&& x) : s(x.s) {}
+ constexpr S& operator=(S&& x) { s = x.s; return *this; }
+ unsigned char s;
+};
+
+constexpr
+int foo()
+{
+ union { S a[20]; };
+ new (&a) S[20](); // OK
+ for (int i = 0; i < 20; ++i)
+ a[i].~S();
+
+ auto* sf = ::new(&a[2]) S(11);
+ return 1;
+}
+
+static_assert(foo());
+
+constexpr
+int foo2()
+{
+ union { S a[20]; };
+ new (&a) S[20]; // ILL-FORMED
+ for (int i = 0; i < 20; ++i)
+ a[i].~S();
+
+ auto* sf = ::new(&a[2]) S(11);
+ return 1;
+}
+
+static_assert(foo2());
+
+auto p = foo2;
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-using5.C b/gcc/testsuite/g++.dg/cpp2a/concepts-using5.C
new file mode 100644
index 0000000..d42b8a0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-using5.C
@@ -0,0 +1,19 @@
+// PR c++/121351
+// { dg-do compile { target c++20 } }
+
+template<class T> concept C = true;
+
+template<class T>
+struct A {
+ template<class U> void f(U) requires C<T> = delete; // #1
+};
+
+struct B : A<int> {
+ using A::f;
+ template<class U> void f(U) requires C<int>; // #2
+};
+
+int main() {
+ B b;
+ b.f(42); // OK, #2 corresponds to and therefore hides #1
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-using5a.C b/gcc/testsuite/g++.dg/cpp2a/concepts-using5a.C
new file mode 100644
index 0000000..5d31948
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-using5a.C
@@ -0,0 +1,20 @@
+// PR c++/121351
+// { dg-do compile { target c++20 } }
+// A version of concepts-using5a.C where B instead of A is a template.
+
+template<class T> concept C = true;
+
+struct A {
+ template<class U> void f(U) requires C<int> = delete; // #1
+};
+
+template<class T>
+struct B : A {
+ using A::f;
+ template<class U> void f(U) requires C<T>; // #2
+};
+
+int main() {
+ B<int> b;
+ b.f(42); // OK, #2 corresponds to and therefore hides #1
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-using6.C b/gcc/testsuite/g++.dg/cpp2a/concepts-using6.C
new file mode 100644
index 0000000..a40519a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-using6.C
@@ -0,0 +1,20 @@
+// PR c++/121351
+// { dg-do compile { target c++20 } }
+
+template<class T> concept C = true;
+
+template<class T>
+struct A {
+ template<class U> void f(U) requires C<T>; // #1
+};
+
+template<class T>
+struct B : A<T*> {
+ using A<T*>::f;
+ template<class U> void f(U) requires C<T>; // #2
+};
+
+int main() {
+ B<int> b;
+ b.f(42); // { dg-error "ambiguous" } #1 and #2 don't correspond
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic19.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic19.C
new file mode 100644
index 0000000..27d167c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic19.C
@@ -0,0 +1,10 @@
+// PR c++/120620
+// { dg-do compile }
+
+#include <cxxabi.h>
+
+struct A* a;
+
+void f() {
+ void* const p = abi::__dynamic_cast(&a, 0, 0, 42);
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic1a.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic1a.C
new file mode 100644
index 0000000..4077a47
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic1a.C
@@ -0,0 +1,6 @@
+// Test that including <cxxabi.h>, whence the actual abi:__dynamic_cast
+// is declared, doesn't affect our constexpr dynamic_cast handling.
+// { dg-do compile { target c++20 } }
+
+#include <cxxabi.h>
+#include "constexpr-dynamic1.C"
diff --git a/gcc/testsuite/g++.dg/modules/cpp-21.C b/gcc/testsuite/g++.dg/modules/cpp-21.C
new file mode 100644
index 0000000..fdd0492
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/cpp-21.C
@@ -0,0 +1,8 @@
+// PR c++/120845
+// { dg-do compile }
+// { dg-additional-options "-fmodules" }
+
+export module pr120485
+ [[foobarbaz]];
+// { dg-error "expected ';' before end of line" "" { target *-*-* } .-2 }
+// { dg-warning "attribute ignored" "" { target *-*-* } .-2 }
diff --git a/gcc/testsuite/gcc.dg/bitintext.h b/gcc/testsuite/gcc.dg/bitintext.h
index 99fedb3..d5f2689d 100644
--- a/gcc/testsuite/gcc.dg/bitintext.h
+++ b/gcc/testsuite/gcc.dg/bitintext.h
@@ -4,6 +4,24 @@ do_copy (void *p, const void *q, __SIZE_TYPE__ r)
__builtin_memcpy (p, q, r);
}
+/* Obtain the value of N from a _BitInt(N)-typed expression X
+ at compile time. */
+#define S(x) \
+ ((typeof (x)) -1 < 0 \
+ ? __builtin_clrsbg (__builtin_choose_expr ((typeof (x)) -1 < 0, \
+ (typeof (x)) -1, -1)) + 1 \
+ : __builtin_popcountg (__builtin_choose_expr ((typeof (x)) -1 < 0, \
+ 0U, (typeof (x)) -1)))
+
+#define CEIL(x,y) (((x) + (y) - 1) / (y))
+
+/* Promote a _BitInt type to include its padding bits. */
+#if defined (__s390x__) || defined(__arm__)
+#define PROMOTED_SIZE(x) sizeof (x)
+#elif defined(__loongarch__)
+#define PROMOTED_SIZE(x) (sizeof (x) > 8 ? CEIL (S (x), 64) * 8 : sizeof (x))
+#endif
+
/* Macro to test whether (on targets where psABI requires it) _BitInt
with padding bits have those filled with sign or zero extension. */
#if defined(__s390x__) || defined(__arm__) || defined(__loongarch__)
@@ -11,14 +29,14 @@ do_copy (void *p, const void *q, __SIZE_TYPE__ r)
do { \
if ((typeof (x)) -1 < 0) \
{ \
- _BitInt(sizeof (x) * __CHAR_BIT__) __x; \
+ _BitInt(PROMOTED_SIZE (x) * __CHAR_BIT__) __x; \
do_copy (&__x, &(x), sizeof (__x)); \
if (__x != (x)) \
__builtin_abort (); \
} \
else \
{ \
- unsigned _BitInt(sizeof (x) * __CHAR_BIT__) __x; \
+ unsigned _BitInt(PROMOTED_SIZE (x) * __CHAR_BIT__) __x; \
do_copy (&__x, &(x), sizeof (__x)); \
if (__x != (x)) \
__builtin_abort (); \
diff --git a/gcc/testsuite/gcc.dg/c23-attr-syntax-6.c b/gcc/testsuite/gcc.dg/c23-attr-syntax-6.c
index f8c5b0f..4e6b80b 100644
--- a/gcc/testsuite/gcc.dg/c23-attr-syntax-6.c
+++ b/gcc/testsuite/gcc.dg/c23-attr-syntax-6.c
@@ -45,7 +45,7 @@ typedef int [[__extension__ __extension__]] b2; /* { dg-error {'extension' attri
typedef int [[__extension__ unknown_attribute]] b3; /* { dg-error {'unknown_attribute' attribute ignored} } */
typedef int [[__extension__ gnu:vector_size(4)]] b4; /* { dg-error {expected '\]' before ':'} } */
/* { dg-error {'gnu' attribute ignored} "" { target *-*-* } .-1 } */
-typedef int [[__extension__ gnu JOIN2(:,:) vector_size (4)]] b5; /* { dg-error {pasting ":" and ":" does not give a valid preprocessing token} } */
+typedef int [[__extension__ gnu JOIN2(:,:) vector_size (4)]] b5; /* { dg-error {pasting ':' and ':' does not give a valid preprocessing token} } */
/* { dg-error {expected '\]' before ':'} "" { target *-*-* } .-1 } */
/* { dg-error {'gnu' attribute ignored} "" { target *-*-* } .-2 } */
typedef int [[__extension__ gnu : : vector_size (4)]] b6; /* { dg-error {expected '\]' before ':'} } */
@@ -81,7 +81,7 @@ typedef int [[gnu :: vector_size (4)]] b18; /* { dg-error {attributes before C23
typedef int [[gnu FOO vector_size (4)]] b19; /* { dg-error {attributes before C23} } */
typedef int [[gnu :: vector_size (sizeof (void (*)(...)))]] b20; /* { dg-error {attributes before C23} } */
/* { dg-error {requires a named argument before} "" { target *-*-* } .-1 } */
-typedef int [[gnu JOIN2(:,:) vector_size (4)]] b21; /* { dg-error {pasting ":" and ":" does not give a valid preprocessing token} } */
+typedef int [[gnu JOIN2(:,:) vector_size (4)]] b21; /* { dg-error {pasting ':' and ':' does not give a valid preprocessing token} } */
/* { dg-error {expected '\]' before ':'} "" { target *-*-* } .-1 } */
/* { dg-error {'gnu' attribute ignored} "" { target *-*-* } .-2 } */
/* { dg-error {attributes before C23} "" { target *-*-* } .-3 } */
diff --git a/gcc/testsuite/gcc.dg/cpp/paste12-2.c b/gcc/testsuite/gcc.dg/cpp/paste12-2.c
index 6e2e4f1..f46645a 100644
--- a/gcc/testsuite/gcc.dg/cpp/paste12-2.c
+++ b/gcc/testsuite/gcc.dg/cpp/paste12-2.c
@@ -6,6 +6,6 @@
/* Test correct diagnostics when pasting in #include.
Source: PR preprocessor/6780. */
-#define inc2(a,b) <##a.b> /* { dg-error "pasting \"<\" and \"stdio\" does not" } */
+#define inc2(a,b) <##a.b> /* { dg-error "pasting '<' and 'stdio' does not" } */
#define INC(X) inc2(X,h)
#include INC(stdio)
diff --git a/gcc/testsuite/gcc.dg/cpp/paste12.c b/gcc/testsuite/gcc.dg/cpp/paste12.c
index 3e0f7b9..f6b3696 100644
--- a/gcc/testsuite/gcc.dg/cpp/paste12.c
+++ b/gcc/testsuite/gcc.dg/cpp/paste12.c
@@ -8,4 +8,4 @@
#define inc2(a,b) <##a.b>
#define INC(X) inc2(X,h)
-#include INC(stdio) /* { dg-error "pasting \"<\" and \"stdio\" does not" } */
+#include INC(stdio) /* { dg-error "pasting '<' and 'stdio' does not" } */
diff --git a/gcc/testsuite/gcc.dg/cpp/paste14-2.c b/gcc/testsuite/gcc.dg/cpp/paste14-2.c
index 3b23ada..bb51999 100644
--- a/gcc/testsuite/gcc.dg/cpp/paste14-2.c
+++ b/gcc/testsuite/gcc.dg/cpp/paste14-2.c
@@ -4,8 +4,8 @@
{ dg-do preprocess }
*/
-#define foo - ## >> /* { dg-error "pasting \"-\" and \">>\"" } */
+#define foo - ## >> /* { dg-error "pasting '-' and '>>'" } */
foo
-#define bar = ## == /* { dg-error "pasting \"=\" and \"==\"" } */
+#define bar = ## == /* { dg-error "pasting '=' and '=='" } */
bar
diff --git a/gcc/testsuite/gcc.dg/cpp/paste14.c b/gcc/testsuite/gcc.dg/cpp/paste14.c
index 043d5e5..d60b328 100644
--- a/gcc/testsuite/gcc.dg/cpp/paste14.c
+++ b/gcc/testsuite/gcc.dg/cpp/paste14.c
@@ -5,6 +5,6 @@
*/
#define foo - ## >>
-foo /* { dg-error "pasting \"-\" and \">>\"" } */
+foo /* { dg-error "pasting '-' and '>>'" } */
#define bar = ## ==
-bar /* { dg-error "pasting \"=\" and \"==\"" } */
+bar /* { dg-error "pasting '=' and '=='" } */
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-graphs-html.py b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-graphs-html.py
index 11e5fd1..9ff4645 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-graphs-html.py
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-graphs-html.py
@@ -26,7 +26,7 @@ def test_result_graph(html_tree):
assert message.attrib['id'] == 'gcc-diag-0-message'
assert message[0].tag == make_tag('strong')
- assert message[0].tail == ' this is a placeholder error, with graphs '
+ assert message[0].tail == ' this is a placeholder error, with graphs'
graph = diag.find("./xhtml:div[@class='gcc-directed-graph']", ns)
assert graph is not None
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-html.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-html.c
new file mode 100644
index 0000000..8ff7b35
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-html.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-fdiagnostics-add-output=experimental-html:javascript=no" } */
+
+extern void foo (void);
+
+void test_nesting (void)
+{
+ foo (); /* { dg-error "top-level error" } */
+}
+
+/* Use a Python script to verify various properties about the generated
+ .html file:
+ { dg-final { run-html-pytest diagnostic-test-nesting-html.c "diagnostic-test-nesting-html.py" } } */
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-html.py b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-html.py
new file mode 100644
index 0000000..3899ba5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-nesting-html.py
@@ -0,0 +1,69 @@
+# Verify that nesting works in HTML output.
+
+from htmltest import *
+
+import pytest
+
+@pytest.fixture(scope='function', autouse=True)
+def html_tree():
+ return html_tree_from_env()
+
+def test_nesting(html_tree):
+ root = html_tree.getroot ()
+ assert root.tag == make_tag('html')
+
+ body = root.find('xhtml:body', ns)
+ assert body is not None
+
+ diag_list = body.find('xhtml:div', ns)
+ assert diag_list is not None
+ assert diag_list.attrib['class'] == 'gcc-diagnostic-list'
+
+ diag = diag_list.find('xhtml:div', ns)
+ assert diag is not None
+
+ message = diag.find("./xhtml:div[@class='gcc-message']", ns)
+ assert message.attrib['id'] == 'gcc-diag-0-message'
+
+ assert message[0].tag == make_tag('strong')
+ assert message[0].tail == ' top-level error'
+
+ # We expect 12 messages, with the given IDs and text:
+ for i in range(12):
+ child = diag.find(".//xhtml:div[@id='gcc-diag-%i']" % (i + 1),
+ ns)
+ assert child is not None
+
+ message = child.find("./xhtml:div[@class='gcc-message']", ns)
+ assert message.attrib['id'] == 'gcc-diag-%i-message' % (i + 1)
+
+ if i % 4 == 0:
+ assert message.text == 'child %i' % (i / 4)
+ else:
+ assert message.text == 'grandchild %i %i' % ((i / 4), (i % 4) - 1)
+
+ # We expect the messages to be organized into nested <ul> with
+ # "nesting-level" set, all below a <ul>
+ child_ul = diag.find("./xhtml:ul[@nesting-level='1']", ns)
+ assert child_ul is not None
+ msg_id = 1
+ for i in range(3):
+ child_li = child_ul.find("./xhtml:li[@nesting-level='1'][%i]" % (i + 1), ns)
+ assert child_li is not None
+ child = child_li.find("./xhtml:div[@id='gcc-diag-%i']" % msg_id, ns)
+ assert child is not None
+ message = child.find("./xhtml:div[@class='gcc-message']", ns)
+ assert message.attrib['id'] == 'gcc-diag-%i-message' % msg_id
+ assert message.text == 'child %i' % i
+ msg_id += 1
+ grandchild_ul = child_ul.find("./xhtml:ul[@nesting-level='2'][%i]" % (i + 1), ns)
+ assert grandchild_ul is not None
+ for j in range(3):
+ grandchild_li = grandchild_ul.find("./xhtml:li[@nesting-level='2'][%i]" % (j + 1), ns)
+ assert grandchild_li is not None
+ grandchild = grandchild_li.find("./xhtml:div[@id='gcc-diag-%i']" % msg_id, ns)
+ assert grandchild is not None
+ message = grandchild.find("./xhtml:div[@class='gcc-message']", ns)
+ assert message.attrib['id'] == 'gcc-diag-%i-message' % msg_id
+ assert message.text == 'grandchild %i %i' % (i, j)
+ msg_id += 1
diff --git a/gcc/testsuite/gcc.dg/plugin/plugin.exp b/gcc/testsuite/gcc.dg/plugin/plugin.exp
index ce25c0a..3bb6063 100644
--- a/gcc/testsuite/gcc.dg/plugin/plugin.exp
+++ b/gcc/testsuite/gcc.dg/plugin/plugin.exp
@@ -116,6 +116,7 @@ set plugin_test_list [list \
diagnostic-test-nesting-text-indented.c \
diagnostic-test-nesting-text-indented-show-levels.c \
diagnostic-test-nesting-text-indented-unicode.c \
+ diagnostic-test-nesting-html.c \
diagnostic-test-nesting-sarif.c } \
{ diagnostic_plugin_test_paths.cc \
diagnostic-test-paths-1.c \
diff --git a/gcc/testsuite/gcc.dg/torture/pr121370.c b/gcc/testsuite/gcc.dg/torture/pr121370.c
new file mode 100644
index 0000000..d40f3b2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr121370.c
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-require-effective-target int32plus } */
+
+int a;
+int main()
+{
+ int c = -2147483647;
+ int d = -2147483647;
+ int e = 2147483647;
+ if (0)
+ f:
+ e = d + e - 2;
+g:
+ if (d - c - e > 0) {
+ a = -c;
+ if (a + d) {
+ d = 1;
+ goto g;
+ }
+ return 0;
+ }
+ if (e)
+ goto f;
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr121382.c b/gcc/testsuite/gcc.dg/torture/pr121382.c
new file mode 100644
index 0000000..20b49b1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr121382.c
@@ -0,0 +1,23 @@
+/* { dg-do run } */
+/* { dg-require-effective-target int32plus } */
+
+int a, b, c;
+__attribute__((noipa))
+static void d(int e, int f)
+{
+ if (e != 5 && e != 2147483647)
+ __builtin_abort();
+ f = 2147483647;
+ do {
+ f = f - e;
+ if (c - 9 * f) {
+ __builtin_abort();
+ }
+ } while (c);
+}
+__attribute__((noipa))
+int main(void)
+{
+ d(2147483647, 2147483647);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-105.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-105.c
new file mode 100644
index 0000000..61b93c0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-105.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fno-tree-sra -fdump-tree-fre1-details" } */
+
+struct s1
+{
+ int t, t1;
+};
+
+struct s3
+{
+ struct s1 t;
+};
+
+struct s2
+{
+ struct s3 t;
+};
+
+void f(int, int);
+void l();
+void g(int a, int b, int *p)
+{
+ struct s2 c;
+ {
+ struct s1 tmp = {a,b};
+ struct s3 *t = &c.t;
+ t->t = tmp;
+ }
+ f(c.t.t.t, c.t.t.t1);
+}
+
+/* { dg-final { scan-tree-dump "Replaced c.t.t.t1 with b" "fre1" } } */
+/* { dg-final { scan-tree-dump "Replaced c.t.t.t with a" "fre1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-106.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-106.c
new file mode 100644
index 0000000..6da4201
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-106.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fno-tree-sra -fdump-tree-fre1-details" } */
+
+struct s1
+{
+ int t, t1;
+};
+
+struct s3
+{
+ struct s1 t;
+};
+
+struct s2
+{
+ struct s3 t;
+};
+
+void f(int, int);
+void l();
+void g(int a, int b, int *p)
+{
+ struct s2 c;
+ {
+ struct s1 tmp = {a,b};
+ c.t.t = tmp;
+ }
+ struct s1 *t = &c.t.t;
+ f(t->t, t->t1);
+}
+
+/* { dg-final { scan-tree-dump "Replaced \[^\r\n\]*.t1 with b" "fre1" } } */
+/* { dg-final { scan-tree-dump "Replaced \[^\r\n\]*.t with a" "fre1" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/pr59984.c b/gcc/testsuite/gcc.dg/vect/pr59984.c
index c00c2267..8ca446e 100644
--- a/gcc/testsuite/gcc.dg/vect/pr59984.c
+++ b/gcc/testsuite/gcc.dg/vect/pr59984.c
@@ -64,3 +64,7 @@ main ()
return 0;
}
+/* { dg-final { scan-tree-dump "31:17: optimized: loop vectorized" "vect" } } */
+/* { dg-final { scan-tree-dump "37:7: optimized: loop vectorized" "vect" } } */
+/* { dg-final { scan-tree-dump "44:17: optimized: loop vectorized" "vect" } } */
+/* { dg-final { scan-tree-dump "50:7: optimized: loop vectorized" "vect" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/acge_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/acge_1.c
new file mode 100644
index 0000000..37428a8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/acge_1.c
@@ -0,0 +1,104 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** facge p0\.h, p0/z, z0\.h, z1\.h
+** ret
+*/
+svbool_t
+test1 (svbool_t pg, svfloat16_t x, svfloat16_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svacge (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test2:
+** facge p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test2 (svbool_t pg, svfloat32_t x, svfloat32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svacge (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test3:
+** facge p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test3 (svbool_t pg, svfloat32_t x, svfloat32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svacge (pg, x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test4:
+** facge p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test4 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svacge (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test5:
+** facge p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test5 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b32 (),
+ svacge (pg, x, y),
+ svptrue_b8 ());
+}
+
+/*
+** test6:
+** facge p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test6 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svacge (pg, x, y),
+ svptrue_b64 ());
+}
+
+/*
+** test7:
+** facge p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test7 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b32 (),
+ svacge (pg, x, y),
+ svptrue_b64 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/acgt_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/acgt_1.c
new file mode 100644
index 0000000..5829369
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/acgt_1.c
@@ -0,0 +1,104 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** facgt p0\.h, p0/z, z0\.h, z1\.h
+** ret
+*/
+svbool_t
+test1 (svbool_t pg, svfloat16_t x, svfloat16_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svacgt (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test2:
+** facgt p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test2 (svbool_t pg, svfloat32_t x, svfloat32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svacgt (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test3:
+** facgt p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test3 (svbool_t pg, svfloat32_t x, svfloat32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svacgt (pg, x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test4:
+** facgt p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test4 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svacgt (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test5:
+** facgt p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test5 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b32 (),
+ svacgt (pg, x, y),
+ svptrue_b8 ());
+}
+
+/*
+** test6:
+** facgt p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test6 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svacgt (pg, x, y),
+ svptrue_b64 ());
+}
+
+/*
+** test7:
+** facgt p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test7 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b32 (),
+ svacgt (pg, x, y),
+ svptrue_b64 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/acle_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/acle_1.c
new file mode 100644
index 0000000..bd5200e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/acle_1.c
@@ -0,0 +1,104 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** facle p0\.h, p0/z, z0\.h, z1\.h
+** ret
+*/
+svbool_t
+test1 (svbool_t pg, svfloat16_t x, svfloat16_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svacle (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test2:
+** facle p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test2 (svbool_t pg, svfloat32_t x, svfloat32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svacle (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test3:
+** facle p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test3 (svbool_t pg, svfloat32_t x, svfloat32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svacle (pg, x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test4:
+** facle p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test4 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svacle (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test5:
+** facle p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test5 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b32 (),
+ svacle (pg, x, y),
+ svptrue_b8 ());
+}
+
+/*
+** test6:
+** facle p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test6 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svacle (pg, x, y),
+ svptrue_b64 ());
+}
+
+/*
+** test7:
+** facle p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test7 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b32 (),
+ svacle (pg, x, y),
+ svptrue_b64 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/aclt_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/aclt_1.c
new file mode 100644
index 0000000..876aba9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/aclt_1.c
@@ -0,0 +1,104 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** faclt p0\.h, p0/z, z0\.h, z1\.h
+** ret
+*/
+svbool_t
+test1 (svbool_t pg, svfloat16_t x, svfloat16_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svaclt (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test2:
+** faclt p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test2 (svbool_t pg, svfloat32_t x, svfloat32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svaclt (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test3:
+** faclt p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test3 (svbool_t pg, svfloat32_t x, svfloat32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svaclt (pg, x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test4:
+** faclt p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test4 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svaclt (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test5:
+** faclt p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test5 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b32 (),
+ svaclt (pg, x, y),
+ svptrue_b8 ());
+}
+
+/*
+** test6:
+** faclt p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test6 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svaclt (pg, x, y),
+ svptrue_b64 ());
+}
+
+/*
+** test7:
+** faclt p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test7 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b32 (),
+ svaclt (pg, x, y),
+ svptrue_b64 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_1.c
index dd8f6c4..d6aabc8 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_1.c
@@ -18,5 +18,57 @@ test2 (svbool_t pg, svint8_t x, svint64_t y, int *any)
return svptest_any (pg, res);
}
-/* { dg-final { scan-assembler-times {\tcmpeq\t} 2 } } */
+void
+test3 (svint8_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b8 ();
+ svbool_t res = svcmpeq_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test4 (svint8_t x, svint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b8 ();
+ svbool_t res = svcmpeq_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test5 (svint16_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpeq_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test6 (svint16_t x, svint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpeq_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test7 (svint32_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpeq_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test8 (svint32_t x, svint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpeq_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tcmpeq\t} 8 } } */
+/* { dg-final { scan-assembler-times {\tptrue\t} 6 } } */
/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_2.c
index 028d375..df98d27 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_2.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_2.c
@@ -33,6 +33,108 @@ test4 (svbool_t pg, svint8_t x, int *any)
return svptest_any (pg, res);
}
-/* { dg-final { scan-assembler-times {\tcmpeq\t} 4 } } */
-/* { dg-final { scan-assembler-times {\tcmpeq\t[^\n]*, #10} 2 } } */
+void
+test5 (svint16_t x, svint16_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpeq (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test6 (svint16_t x, svint16_t y)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpeq (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test7 (svint16_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpeq (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test8 (svint16_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpeq (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test9 (svint32_t x, svint32_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpeq (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test10 (svint32_t x, svint32_t y)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpeq (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test11 (svint32_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpeq (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test12 (svint32_t x)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpeq (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test13 (svint64_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmpeq (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test14 (svint64_t x, svint64_t y)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmpeq (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test15 (svint64_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmpeq (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test16 (svint64_t x)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmpeq (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tcmpeq\t} 16 } } */
+/* { dg-final { scan-assembler-times {\tcmpeq\t[^\n]*, #10} 8 } } */
/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_4.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_4.c
new file mode 100644
index 0000000..8e4b931
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_4.c
@@ -0,0 +1,157 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** cmpeq p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test1 (svbool_t p0, svint8_t x, svint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpeq (pg, x, y), p0);
+}
+
+/*
+** test2:
+** cmpeq p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test2 (svbool_t p0, svint8_t x, svint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmpeq (pg, x, y), p0);
+}
+
+/*
+** test3:
+** cmpeq p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test3 (svbool_t p0, svint8_t x, svint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmpeq (pg, x, y), pg);
+}
+
+/*
+** test4:
+** cmpeq p0\.b, p0/z, z0\.b, #10
+** ret
+*/
+svbool_t
+test4 (svbool_t p0, svint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpeq (pg, x, 10), p0);
+}
+
+/*
+** test5:
+** cmpeq p0\.b, p0/z, z0\.b, #10
+** ret
+*/
+svbool_t
+test5 (svbool_t p0, svint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmpeq (pg, x, 10), p0);
+}
+
+/*
+** test6:
+** cmpeq p0\.b, p0/z, z0\.b, #10
+** ret
+*/
+svbool_t
+test6 (svbool_t p0, svint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmpeq (pg, x, 10), pg);
+}
+
+/*
+** test7:
+** cmpeq p0\.h, p0/z, z0\.h, z1\.h
+** ret
+*/
+svbool_t
+test7 (svbool_t p0, svint16_t x, svint16_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpeq (pg, x, y), p0);
+}
+
+/*
+** test8:
+** cmpeq p0\.h, p0/z, z0\.h, #10
+** ret
+*/
+svbool_t
+test8 (svbool_t p0, svint16_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmpeq (pg, x, 10), p0);
+}
+
+/*
+** test9:
+** cmpeq p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test9 (svbool_t p0, svint32_t x, svint32_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpeq (pg, x, y), p0);
+}
+
+/*
+** test10:
+** cmpeq p0\.s, p0/z, z0\.s, #10
+** ret
+*/
+svbool_t
+test10 (svbool_t p0, svint32_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmpeq (pg, x, 10), p0);
+}
+
+/*
+** test11:
+** cmpeq p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test11 (svbool_t p0, svint64_t x, svint64_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpeq (pg, x, y), p0);
+}
+
+/*
+** test12:
+** cmpeq p0\.d, p0/z, z0\.d, #10
+** ret
+*/
+svbool_t
+test12 (svbool_t p0, svint64_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmpeq (pg, x, 10), p0);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_5.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_5.c
new file mode 100644
index 0000000..2958bc2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_5.c
@@ -0,0 +1,52 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** cmpeq p0\.h, p0/z, z0\.h, z1\.d
+** ret
+*/
+svbool_t
+test1 (svbool_t pg, svint16_t x, svint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpeq_wide (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test2:
+** cmpeq p0\.s, p0/z, z0\.s, z1\.d
+** ret
+*/
+svbool_t
+test2 (svbool_t pg, svint32_t x, svint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpeq_wide (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test3:
+** cmpeq p0\.s, p0/z, z0\.s, z1\.d
+** ret
+*/
+svbool_t
+test3 (svbool_t pg, svint32_t x, svint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpeq_wide (pg, x, y),
+ svptrue_b32 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_6.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_6.c
new file mode 100644
index 0000000..9233de9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_6.c
@@ -0,0 +1,104 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** fcmeq p0\.h, p0/z, z0\.h, z1\.h
+** ret
+*/
+svbool_t
+test1 (svbool_t pg, svfloat16_t x, svfloat16_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpeq (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test2:
+** fcmeq p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test2 (svbool_t pg, svfloat32_t x, svfloat32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpeq (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test3:
+** fcmeq p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test3 (svbool_t pg, svfloat32_t x, svfloat32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpeq (pg, x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test4:
+** fcmeq p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test4 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpeq (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test5:
+** fcmeq p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test5 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b32 (),
+ svcmpeq (pg, x, y),
+ svptrue_b8 ());
+}
+
+/*
+** test6:
+** fcmeq p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test6 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpeq (pg, x, y),
+ svptrue_b64 ());
+}
+
+/*
+** test7:
+** fcmeq p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test7 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b32 (),
+ svcmpeq (pg, x, y),
+ svptrue_b64 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_1.c
new file mode 100644
index 0000000..f6bb3c8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_1.c
@@ -0,0 +1,140 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svint8_t x, svint8_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmpge (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svint8_t x, svint8_t y, int *any)
+{
+ svbool_t res = svcmpge (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test3 (svbool_t pg, svint8_t x, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmpge (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test4 (svbool_t pg, svint8_t x, int *any)
+{
+ svbool_t res = svcmpge (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test5 (svint16_t x, svint16_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpge (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test6 (svint16_t x, svint16_t y)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpge (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test7 (svint16_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpge (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test8 (svint16_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpge (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test9 (svint32_t x, svint32_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpge (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test10 (svint32_t x, svint32_t y)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpge (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test11 (svint32_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpge (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test12 (svint32_t x)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpge (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test13 (svint64_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmpge (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test14 (svint64_t x, svint64_t y)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmpge (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test15 (svint64_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmpge (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test16 (svint64_t x)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmpge (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tcmpge\t} 16 } } */
+/* { dg-final { scan-assembler-times {\tcmpge\t[^\n]*, #10} 8 } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_2.c
new file mode 100644
index 0000000..fc92291
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_2.c
@@ -0,0 +1,140 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svuint8_t x, svuint8_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmpge (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svuint8_t x, svuint8_t y, int *any)
+{
+ svbool_t res = svcmpge (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test3 (svbool_t pg, svuint8_t x, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmpge (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test4 (svbool_t pg, svuint8_t x, int *any)
+{
+ svbool_t res = svcmpge (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test5 (svuint16_t x, svuint16_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpge (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test6 (svuint16_t x, svuint16_t y)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpge (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test7 (svuint16_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpge (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test8 (svuint16_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpge (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test9 (svuint32_t x, svuint32_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpge (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test10 (svuint32_t x, svuint32_t y)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpge (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test11 (svuint32_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpge (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test12 (svuint32_t x)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpge (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test13 (svuint64_t x, svuint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmpge (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test14 (svuint64_t x, svuint64_t y)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmpge (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test15 (svuint64_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmpge (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test16 (svuint64_t x)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmpge (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tcmphs\t} 16 } } */
+/* { dg-final { scan-assembler-times {\tcmphs\t[^\n]*, #10} 8 } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_3.c
new file mode 100644
index 0000000..6d50df5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_3.c
@@ -0,0 +1,169 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** cmpge p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test1 (svbool_t p0, svint8_t x, svint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpge (pg, x, y), p0);
+}
+
+/*
+** test2:
+** cmpge p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test2 (svbool_t p0, svint8_t x, svint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmpge (pg, x, y), p0);
+}
+
+/*
+** test3:
+** cmpge p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test3 (svbool_t p0, svint8_t x, svint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmpge (pg, x, y), pg);
+}
+
+/*
+** test4:
+** (
+** cmpge p0\.b, p0/z, z0\.b, #10
+** |
+** cmpgt p0\.b, p0/z, z0\.b, #9
+** )
+** ret
+*/
+svbool_t
+test4 (svbool_t p0, svint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpge (pg, x, 10), p0);
+}
+
+/*
+** test5:
+** (
+** cmpge p0\.b, p0/z, z0\.b, #10
+** |
+** cmpgt p0\.b, p0/z, z0\.b, #9
+** )
+** ret
+*/
+svbool_t
+test5 (svbool_t p0, svint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmpge (pg, x, 10), p0);
+}
+
+/*
+** test6:
+** (
+** cmpge p0\.b, p0/z, z0\.b, #10
+** |
+** cmpgt p0\.b, p0/z, z0\.b, #9
+** )
+** ret
+*/
+svbool_t
+test6 (svbool_t p0, svint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmpge (pg, x, 10), pg);
+}
+
+/*
+** test7:
+** cmpge p0\.h, p0/z, z0\.h, z1\.h
+** ret
+*/
+svbool_t
+test7 (svbool_t p0, svint16_t x, svint16_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpge (pg, x, y), p0);
+}
+
+/*
+** test8:
+** cmpge p0\.h, p0/z, z0\.h, #10
+** ret
+*/
+svbool_t
+test8 (svbool_t p0, svint16_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmpge (pg, x, 10), p0);
+}
+
+/*
+** test9:
+** cmpge p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test9 (svbool_t p0, svint32_t x, svint32_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpge (pg, x, y), p0);
+}
+
+/*
+** test10:
+** cmpge p0\.s, p0/z, z0\.s, #10
+** ret
+*/
+svbool_t
+test10 (svbool_t p0, svint32_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmpge (pg, x, 10), p0);
+}
+
+/*
+** test11:
+** cmpge p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test11 (svbool_t p0, svint64_t x, svint64_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpge (pg, x, y), p0);
+}
+
+/*
+** test12:
+** cmpge p0\.d, p0/z, z0\.d, #10
+** ret
+*/
+svbool_t
+test12 (svbool_t p0, svint64_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmpge (pg, x, 10), p0);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_4.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_4.c
new file mode 100644
index 0000000..2430e80
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_4.c
@@ -0,0 +1,169 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** cmphs p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test1 (svbool_t p0, svuint8_t x, svuint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpge (pg, x, y), p0);
+}
+
+/*
+** test2:
+** cmphs p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test2 (svbool_t p0, svuint8_t x, svuint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmpge (pg, x, y), p0);
+}
+
+/*
+** test3:
+** cmphs p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test3 (svbool_t p0, svuint8_t x, svuint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmpge (pg, x, y), pg);
+}
+
+/*
+** test4:
+** (
+** cmphs p0\.b, p0/z, z0\.b, #10
+** |
+** cmphi p0\.b, p0/z, z0\.b, #9
+** )
+** ret
+*/
+svbool_t
+test4 (svbool_t p0, svuint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpge (pg, x, 10), p0);
+}
+
+/*
+** test5:
+** (
+** cmphs p0\.b, p0/z, z0\.b, #10
+** |
+** cmphi p0\.b, p0/z, z0\.b, #9
+** )
+** ret
+*/
+svbool_t
+test5 (svbool_t p0, svuint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmpge (pg, x, 10), p0);
+}
+
+/*
+** test6:
+** (
+** cmphs p0\.b, p0/z, z0\.b, #10
+** |
+** cmphi p0\.b, p0/z, z0\.b, #9
+** )
+** ret
+*/
+svbool_t
+test6 (svbool_t p0, svuint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmpge (pg, x, 10), pg);
+}
+
+/*
+** test7:
+** cmphs p0\.h, p0/z, z0\.h, z1\.h
+** ret
+*/
+svbool_t
+test7 (svbool_t p0, svuint16_t x, svuint16_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpge (pg, x, y), p0);
+}
+
+/*
+** test8:
+** cmphs p0\.h, p0/z, z0\.h, #10
+** ret
+*/
+svbool_t
+test8 (svbool_t p0, svuint16_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmpge (pg, x, 10), p0);
+}
+
+/*
+** test9:
+** cmphs p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test9 (svbool_t p0, svuint32_t x, svuint32_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpge (pg, x, y), p0);
+}
+
+/*
+** test10:
+** cmphs p0\.s, p0/z, z0\.s, #10
+** ret
+*/
+svbool_t
+test10 (svbool_t p0, svuint32_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmpge (pg, x, 10), p0);
+}
+
+/*
+** test11:
+** cmphs p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test11 (svbool_t p0, svuint64_t x, svuint64_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpge (pg, x, y), p0);
+}
+
+/*
+** test12:
+** cmphs p0\.d, p0/z, z0\.d, #10
+** ret
+*/
+svbool_t
+test12 (svbool_t p0, svuint64_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmpge (pg, x, 10), p0);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_5.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_5.c
new file mode 100644
index 0000000..f4fa758
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_5.c
@@ -0,0 +1,74 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svint8_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmpge_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svint8_t x, svint64_t y, int *any)
+{
+ svbool_t res = svcmpge_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test3 (svint8_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b8 ();
+ svbool_t res = svcmpge_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test4 (svint8_t x, svint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b8 ();
+ svbool_t res = svcmpge_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test5 (svint16_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpge_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test6 (svint16_t x, svint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpge_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test7 (svint32_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpge_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test8 (svint32_t x, svint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpge_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tcmpge\t} 8 } } */
+/* { dg-final { scan-assembler-times {\tptrue\t} 6 } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_6.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_6.c
new file mode 100644
index 0000000..979db4c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_6.c
@@ -0,0 +1,74 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svuint8_t x, svuint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmpge_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svuint8_t x, svuint64_t y, int *any)
+{
+ svbool_t res = svcmpge_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test3 (svuint8_t x, svuint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b8 ();
+ svbool_t res = svcmpge_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test4 (svuint8_t x, svuint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b8 ();
+ svbool_t res = svcmpge_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test5 (svuint16_t x, svuint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpge_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test6 (svuint16_t x, svuint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpge_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test7 (svuint32_t x, svuint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpge_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test8 (svuint32_t x, svuint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpge_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tcmphs\t} 8 } } */
+/* { dg-final { scan-assembler-times {\tptrue\t} 6 } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_7.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_7.c
new file mode 100644
index 0000000..d6abab0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_7.c
@@ -0,0 +1,52 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** cmpge p0\.h, p0/z, z0\.h, z1\.d
+** ret
+*/
+svbool_t
+test1 (svbool_t pg, svint16_t x, svint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpge_wide (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test2:
+** cmpge p0\.s, p0/z, z0\.s, z1\.d
+** ret
+*/
+svbool_t
+test2 (svbool_t pg, svint32_t x, svint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpge_wide (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test3:
+** cmpge p0\.s, p0/z, z0\.s, z1\.d
+** ret
+*/
+svbool_t
+test3 (svbool_t pg, svint32_t x, svint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpge_wide (pg, x, y),
+ svptrue_b32 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_8.c
new file mode 100644
index 0000000..70be917
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_8.c
@@ -0,0 +1,52 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** cmphs p0\.h, p0/z, z0\.h, z1\.d
+** ret
+*/
+svbool_t
+test1 (svbool_t pg, svuint16_t x, svuint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpge_wide (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test2:
+** cmphs p0\.s, p0/z, z0\.s, z1\.d
+** ret
+*/
+svbool_t
+test2 (svbool_t pg, svuint32_t x, svuint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpge_wide (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test3:
+** cmphs p0\.s, p0/z, z0\.s, z1\.d
+** ret
+*/
+svbool_t
+test3 (svbool_t pg, svuint32_t x, svuint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpge_wide (pg, x, y),
+ svptrue_b32 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_9.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_9.c
new file mode 100644
index 0000000..0d4140e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpge_9.c
@@ -0,0 +1,104 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** fcmge p0\.h, p0/z, z0\.h, z1\.h
+** ret
+*/
+svbool_t
+test1 (svbool_t pg, svfloat16_t x, svfloat16_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpge (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test2:
+** fcmge p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test2 (svbool_t pg, svfloat32_t x, svfloat32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpge (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test3:
+** fcmge p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test3 (svbool_t pg, svfloat32_t x, svfloat32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpge (pg, x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test4:
+** fcmge p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test4 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpge (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test5:
+** fcmge p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test5 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b32 (),
+ svcmpge (pg, x, y),
+ svptrue_b8 ());
+}
+
+/*
+** test6:
+** fcmge p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test6 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpge (pg, x, y),
+ svptrue_b64 ());
+}
+
+/*
+** test7:
+** fcmge p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test7 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b32 (),
+ svcmpge (pg, x, y),
+ svptrue_b64 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_1.c
new file mode 100644
index 0000000..6c28d6f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_1.c
@@ -0,0 +1,140 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svint8_t x, svint8_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmpgt (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svint8_t x, svint8_t y, int *any)
+{
+ svbool_t res = svcmpgt (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test3 (svbool_t pg, svint8_t x, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmpgt (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test4 (svbool_t pg, svint8_t x, int *any)
+{
+ svbool_t res = svcmpgt (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test5 (svint16_t x, svint16_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpgt (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test6 (svint16_t x, svint16_t y)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpgt (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test7 (svint16_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpgt (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test8 (svint16_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpgt (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test9 (svint32_t x, svint32_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpgt (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test10 (svint32_t x, svint32_t y)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpgt (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test11 (svint32_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpgt (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test12 (svint32_t x)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpgt (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test13 (svint64_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmpgt (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test14 (svint64_t x, svint64_t y)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmpgt (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test15 (svint64_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmpgt (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test16 (svint64_t x)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmpgt (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tcmpgt\t} 16 } } */
+/* { dg-final { scan-assembler-times {\tcmpgt\t[^\n]*, #10} 8 } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_2.c
new file mode 100644
index 0000000..2160484
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_2.c
@@ -0,0 +1,140 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svuint8_t x, svuint8_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmpgt (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svuint8_t x, svuint8_t y, int *any)
+{
+ svbool_t res = svcmpgt (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test3 (svbool_t pg, svuint8_t x, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmpgt (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test4 (svbool_t pg, svuint8_t x, int *any)
+{
+ svbool_t res = svcmpgt (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test5 (svuint16_t x, svuint16_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpgt (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test6 (svuint16_t x, svuint16_t y)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpgt (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test7 (svuint16_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpgt (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test8 (svuint16_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpgt (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test9 (svuint32_t x, svuint32_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpgt (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test10 (svuint32_t x, svuint32_t y)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpgt (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test11 (svuint32_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpgt (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test12 (svuint32_t x)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpgt (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test13 (svuint64_t x, svuint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmpgt (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test14 (svuint64_t x, svuint64_t y)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmpgt (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test15 (svuint64_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmpgt (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test16 (svuint64_t x)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmpgt (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tcmphi\t} 16 } } */
+/* { dg-final { scan-assembler-times {\tcmphi\t[^\n]*, #10} 8 } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_3.c
new file mode 100644
index 0000000..cc48b7e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_3.c
@@ -0,0 +1,157 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** cmpgt p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test1 (svbool_t p0, svint8_t x, svint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpgt (pg, x, y), p0);
+}
+
+/*
+** test2:
+** cmpgt p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test2 (svbool_t p0, svint8_t x, svint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmpgt (pg, x, y), p0);
+}
+
+/*
+** test3:
+** cmpgt p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test3 (svbool_t p0, svint8_t x, svint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmpgt (pg, x, y), pg);
+}
+
+/*
+** test4:
+** cmpgt p0\.b, p0/z, z0\.b, #10
+** ret
+*/
+svbool_t
+test4 (svbool_t p0, svint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpgt (pg, x, 10), p0);
+}
+
+/*
+** test5:
+** cmpgt p0\.b, p0/z, z0\.b, #10
+** ret
+*/
+svbool_t
+test5 (svbool_t p0, svint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmpgt (pg, x, 10), p0);
+}
+
+/*
+** test6:
+** cmpgt p0\.b, p0/z, z0\.b, #10
+** ret
+*/
+svbool_t
+test6 (svbool_t p0, svint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmpgt (pg, x, 10), pg);
+}
+
+/*
+** test7:
+** cmpgt p0\.h, p0/z, z0\.h, z1\.h
+** ret
+*/
+svbool_t
+test7 (svbool_t p0, svint16_t x, svint16_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpgt (pg, x, y), p0);
+}
+
+/*
+** test8:
+** cmpgt p0\.h, p0/z, z0\.h, #10
+** ret
+*/
+svbool_t
+test8 (svbool_t p0, svint16_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmpgt (pg, x, 10), p0);
+}
+
+/*
+** test9:
+** cmpgt p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test9 (svbool_t p0, svint32_t x, svint32_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpgt (pg, x, y), p0);
+}
+
+/*
+** test10:
+** cmpgt p0\.s, p0/z, z0\.s, #10
+** ret
+*/
+svbool_t
+test10 (svbool_t p0, svint32_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmpgt (pg, x, 10), p0);
+}
+
+/*
+** test11:
+** cmpgt p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test11 (svbool_t p0, svint64_t x, svint64_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpgt (pg, x, y), p0);
+}
+
+/*
+** test12:
+** cmpgt p0\.d, p0/z, z0\.d, #10
+** ret
+*/
+svbool_t
+test12 (svbool_t p0, svint64_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmpgt (pg, x, 10), p0);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_4.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_4.c
new file mode 100644
index 0000000..bd49fe8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_4.c
@@ -0,0 +1,157 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** cmphi p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test1 (svbool_t p0, svuint8_t x, svuint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpgt (pg, x, y), p0);
+}
+
+/*
+** test2:
+** cmphi p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test2 (svbool_t p0, svuint8_t x, svuint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmpgt (pg, x, y), p0);
+}
+
+/*
+** test3:
+** cmphi p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test3 (svbool_t p0, svuint8_t x, svuint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmpgt (pg, x, y), pg);
+}
+
+/*
+** test4:
+** cmphi p0\.b, p0/z, z0\.b, #10
+** ret
+*/
+svbool_t
+test4 (svbool_t p0, svuint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpgt (pg, x, 10), p0);
+}
+
+/*
+** test5:
+** cmphi p0\.b, p0/z, z0\.b, #10
+** ret
+*/
+svbool_t
+test5 (svbool_t p0, svuint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmpgt (pg, x, 10), p0);
+}
+
+/*
+** test6:
+** cmphi p0\.b, p0/z, z0\.b, #10
+** ret
+*/
+svbool_t
+test6 (svbool_t p0, svuint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmpgt (pg, x, 10), pg);
+}
+
+/*
+** test7:
+** cmphi p0\.h, p0/z, z0\.h, z1\.h
+** ret
+*/
+svbool_t
+test7 (svbool_t p0, svuint16_t x, svuint16_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpgt (pg, x, y), p0);
+}
+
+/*
+** test8:
+** cmphi p0\.h, p0/z, z0\.h, #10
+** ret
+*/
+svbool_t
+test8 (svbool_t p0, svuint16_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmpgt (pg, x, 10), p0);
+}
+
+/*
+** test9:
+** cmphi p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test9 (svbool_t p0, svuint32_t x, svuint32_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpgt (pg, x, y), p0);
+}
+
+/*
+** test10:
+** cmphi p0\.s, p0/z, z0\.s, #10
+** ret
+*/
+svbool_t
+test10 (svbool_t p0, svuint32_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmpgt (pg, x, 10), p0);
+}
+
+/*
+** test11:
+** cmphi p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test11 (svbool_t p0, svuint64_t x, svuint64_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpgt (pg, x, y), p0);
+}
+
+/*
+** test12:
+** cmphi p0\.d, p0/z, z0\.d, #10
+** ret
+*/
+svbool_t
+test12 (svbool_t p0, svuint64_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmpgt (pg, x, 10), p0);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_5.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_5.c
new file mode 100644
index 0000000..f9f4c7d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_5.c
@@ -0,0 +1,74 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svint8_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmpgt_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svint8_t x, svint64_t y, int *any)
+{
+ svbool_t res = svcmpgt_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test3 (svint8_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b8 ();
+ svbool_t res = svcmpgt_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test4 (svint8_t x, svint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b8 ();
+ svbool_t res = svcmpgt_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test5 (svint16_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpgt_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test6 (svint16_t x, svint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpgt_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test7 (svint32_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpgt_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test8 (svint32_t x, svint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpgt_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tcmpgt\t} 8 } } */
+/* { dg-final { scan-assembler-times {\tptrue\t} 6 } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_6.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_6.c
new file mode 100644
index 0000000..6df15b9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_6.c
@@ -0,0 +1,74 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svuint8_t x, svuint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmpgt_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svuint8_t x, svuint64_t y, int *any)
+{
+ svbool_t res = svcmpgt_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test3 (svuint8_t x, svuint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b8 ();
+ svbool_t res = svcmpgt_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test4 (svuint8_t x, svuint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b8 ();
+ svbool_t res = svcmpgt_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test5 (svuint16_t x, svuint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpgt_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test6 (svuint16_t x, svuint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpgt_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test7 (svuint32_t x, svuint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpgt_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test8 (svuint32_t x, svuint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpgt_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tcmphi\t} 8 } } */
+/* { dg-final { scan-assembler-times {\tptrue\t} 6 } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_7.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_7.c
new file mode 100644
index 0000000..0656b29
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_7.c
@@ -0,0 +1,52 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** cmpgt p0\.h, p0/z, z0\.h, z1\.d
+** ret
+*/
+svbool_t
+test1 (svbool_t pg, svint16_t x, svint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpgt_wide (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test2:
+** cmpgt p0\.s, p0/z, z0\.s, z1\.d
+** ret
+*/
+svbool_t
+test2 (svbool_t pg, svint32_t x, svint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpgt_wide (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test3:
+** cmpgt p0\.s, p0/z, z0\.s, z1\.d
+** ret
+*/
+svbool_t
+test3 (svbool_t pg, svint32_t x, svint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpgt_wide (pg, x, y),
+ svptrue_b32 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_8.c
new file mode 100644
index 0000000..b0a9ac8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_8.c
@@ -0,0 +1,52 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** cmphi p0\.h, p0/z, z0\.h, z1\.d
+** ret
+*/
+svbool_t
+test1 (svbool_t pg, svuint16_t x, svuint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpgt_wide (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test2:
+** cmphi p0\.s, p0/z, z0\.s, z1\.d
+** ret
+*/
+svbool_t
+test2 (svbool_t pg, svuint32_t x, svuint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpgt_wide (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test3:
+** cmphi p0\.s, p0/z, z0\.s, z1\.d
+** ret
+*/
+svbool_t
+test3 (svbool_t pg, svuint32_t x, svuint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpgt_wide (pg, x, y),
+ svptrue_b32 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_9.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_9.c
new file mode 100644
index 0000000..dcd84f7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpgt_9.c
@@ -0,0 +1,104 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** fcmgt p0\.h, p0/z, z0\.h, z1\.h
+** ret
+*/
+svbool_t
+test1 (svbool_t pg, svfloat16_t x, svfloat16_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpgt (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test2:
+** fcmgt p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test2 (svbool_t pg, svfloat32_t x, svfloat32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpgt (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test3:
+** fcmgt p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test3 (svbool_t pg, svfloat32_t x, svfloat32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpgt (pg, x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test4:
+** fcmgt p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test4 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpgt (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test5:
+** fcmgt p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test5 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b32 (),
+ svcmpgt (pg, x, y),
+ svptrue_b8 ());
+}
+
+/*
+** test6:
+** fcmgt p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test6 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpgt (pg, x, y),
+ svptrue_b64 ());
+}
+
+/*
+** test7:
+** fcmgt p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test7 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b32 (),
+ svcmpgt (pg, x, y),
+ svptrue_b64 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_1.c
new file mode 100644
index 0000000..f2d7d2b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_1.c
@@ -0,0 +1,140 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svint8_t x, svint8_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmple (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svint8_t x, svint8_t y, int *any)
+{
+ svbool_t res = svcmple (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test3 (svbool_t pg, svint8_t x, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmple (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test4 (svbool_t pg, svint8_t x, int *any)
+{
+ svbool_t res = svcmple (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test5 (svint16_t x, svint16_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmple (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test6 (svint16_t x, svint16_t y)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmple (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test7 (svint16_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmple (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test8 (svint16_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmple (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test9 (svint32_t x, svint32_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmple (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test10 (svint32_t x, svint32_t y)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmple (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test11 (svint32_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmple (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test12 (svint32_t x)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmple (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test13 (svint64_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmple (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test14 (svint64_t x, svint64_t y)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmple (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test15 (svint64_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmple (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test16 (svint64_t x)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmple (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tcmple\t} 16 } } */
+/* { dg-final { scan-assembler-times {\tcmple\t[^\n]*, #10} 8 } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_2.c
new file mode 100644
index 0000000..9d13d7a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_2.c
@@ -0,0 +1,140 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svuint8_t x, svuint8_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmple (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svuint8_t x, svuint8_t y, int *any)
+{
+ svbool_t res = svcmple (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test3 (svbool_t pg, svuint8_t x, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmple (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test4 (svbool_t pg, svuint8_t x, int *any)
+{
+ svbool_t res = svcmple (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test5 (svuint16_t x, svuint16_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmple (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test6 (svuint16_t x, svuint16_t y)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmple (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test7 (svuint16_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmple (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test8 (svuint16_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmple (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test9 (svuint32_t x, svuint32_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmple (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test10 (svuint32_t x, svuint32_t y)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmple (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test11 (svuint32_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmple (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test12 (svuint32_t x)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmple (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test13 (svuint64_t x, svuint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmple (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test14 (svuint64_t x, svuint64_t y)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmple (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test15 (svuint64_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmple (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test16 (svuint64_t x)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmple (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tcmpls\t} 16 } } */
+/* { dg-final { scan-assembler-times {\tcmpls\t[^\n]*, #10} 8 } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_3.c
new file mode 100644
index 0000000..7a9326c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_3.c
@@ -0,0 +1,157 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** cmple p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test1 (svbool_t p0, svint8_t x, svint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmple (pg, x, y), p0);
+}
+
+/*
+** test2:
+** cmple p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test2 (svbool_t p0, svint8_t x, svint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmple (pg, x, y), p0);
+}
+
+/*
+** test3:
+** cmple p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test3 (svbool_t p0, svint8_t x, svint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmple (pg, x, y), pg);
+}
+
+/*
+** test4:
+** cmple p0\.b, p0/z, z0\.b, #10
+** ret
+*/
+svbool_t
+test4 (svbool_t p0, svint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmple (pg, x, 10), p0);
+}
+
+/*
+** test5:
+** cmple p0\.b, p0/z, z0\.b, #10
+** ret
+*/
+svbool_t
+test5 (svbool_t p0, svint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmple (pg, x, 10), p0);
+}
+
+/*
+** test6:
+** cmple p0\.b, p0/z, z0\.b, #10
+** ret
+*/
+svbool_t
+test6 (svbool_t p0, svint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmple (pg, x, 10), pg);
+}
+
+/*
+** test7:
+** cmple p0\.h, p0/z, z0\.h, z1\.h
+** ret
+*/
+svbool_t
+test7 (svbool_t p0, svint16_t x, svint16_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmple (pg, x, y), p0);
+}
+
+/*
+** test8:
+** cmple p0\.h, p0/z, z0\.h, #10
+** ret
+*/
+svbool_t
+test8 (svbool_t p0, svint16_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmple (pg, x, 10), p0);
+}
+
+/*
+** test9:
+** cmple p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test9 (svbool_t p0, svint32_t x, svint32_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmple (pg, x, y), p0);
+}
+
+/*
+** test10:
+** cmple p0\.s, p0/z, z0\.s, #10
+** ret
+*/
+svbool_t
+test10 (svbool_t p0, svint32_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmple (pg, x, 10), p0);
+}
+
+/*
+** test11:
+** cmple p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test11 (svbool_t p0, svint64_t x, svint64_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmple (pg, x, y), p0);
+}
+
+/*
+** test12:
+** cmple p0\.d, p0/z, z0\.d, #10
+** ret
+*/
+svbool_t
+test12 (svbool_t p0, svint64_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmple (pg, x, 10), p0);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_4.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_4.c
new file mode 100644
index 0000000..aca4385
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_4.c
@@ -0,0 +1,157 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** cmpls p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test1 (svbool_t p0, svuint8_t x, svuint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmple (pg, x, y), p0);
+}
+
+/*
+** test2:
+** cmpls p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test2 (svbool_t p0, svuint8_t x, svuint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmple (pg, x, y), p0);
+}
+
+/*
+** test3:
+** cmpls p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test3 (svbool_t p0, svuint8_t x, svuint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmple (pg, x, y), pg);
+}
+
+/*
+** test4:
+** cmpls p0\.b, p0/z, z0\.b, #10
+** ret
+*/
+svbool_t
+test4 (svbool_t p0, svuint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmple (pg, x, 10), p0);
+}
+
+/*
+** test5:
+** cmpls p0\.b, p0/z, z0\.b, #10
+** ret
+*/
+svbool_t
+test5 (svbool_t p0, svuint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmple (pg, x, 10), p0);
+}
+
+/*
+** test6:
+** cmpls p0\.b, p0/z, z0\.b, #10
+** ret
+*/
+svbool_t
+test6 (svbool_t p0, svuint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmple (pg, x, 10), pg);
+}
+
+/*
+** test7:
+** cmpls p0\.h, p0/z, z0\.h, z1\.h
+** ret
+*/
+svbool_t
+test7 (svbool_t p0, svuint16_t x, svuint16_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmple (pg, x, y), p0);
+}
+
+/*
+** test8:
+** cmpls p0\.h, p0/z, z0\.h, #10
+** ret
+*/
+svbool_t
+test8 (svbool_t p0, svuint16_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmple (pg, x, 10), p0);
+}
+
+/*
+** test9:
+** cmpls p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test9 (svbool_t p0, svuint32_t x, svuint32_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmple (pg, x, y), p0);
+}
+
+/*
+** test10:
+** cmpls p0\.s, p0/z, z0\.s, #10
+** ret
+*/
+svbool_t
+test10 (svbool_t p0, svuint32_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmple (pg, x, 10), p0);
+}
+
+/*
+** test11:
+** cmpls p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test11 (svbool_t p0, svuint64_t x, svuint64_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmple (pg, x, y), p0);
+}
+
+/*
+** test12:
+** cmpls p0\.d, p0/z, z0\.d, #10
+** ret
+*/
+svbool_t
+test12 (svbool_t p0, svuint64_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmple (pg, x, 10), p0);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_5.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_5.c
new file mode 100644
index 0000000..1caf496
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_5.c
@@ -0,0 +1,74 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svint8_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmple_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svint8_t x, svint64_t y, int *any)
+{
+ svbool_t res = svcmple_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test3 (svint8_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b8 ();
+ svbool_t res = svcmple_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test4 (svint8_t x, svint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b8 ();
+ svbool_t res = svcmple_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test5 (svint16_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmple_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test6 (svint16_t x, svint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmple_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test7 (svint32_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmple_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test8 (svint32_t x, svint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmple_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tcmple\t} 8 } } */
+/* { dg-final { scan-assembler-times {\tptrue\t} 6 } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_6.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_6.c
new file mode 100644
index 0000000..ae85e89
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_6.c
@@ -0,0 +1,74 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svuint8_t x, svuint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmple_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svuint8_t x, svuint64_t y, int *any)
+{
+ svbool_t res = svcmple_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test3 (svuint8_t x, svuint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b8 ();
+ svbool_t res = svcmple_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test4 (svuint8_t x, svuint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b8 ();
+ svbool_t res = svcmple_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test5 (svuint16_t x, svuint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmple_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test6 (svuint16_t x, svuint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmple_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test7 (svuint32_t x, svuint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmple_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test8 (svuint32_t x, svuint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmple_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tcmpls\t} 8 } } */
+/* { dg-final { scan-assembler-times {\tptrue\t} 6 } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_7.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_7.c
new file mode 100644
index 0000000..3f3ea53
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_7.c
@@ -0,0 +1,52 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** cmple p0\.h, p0/z, z0\.h, z1\.d
+** ret
+*/
+svbool_t
+test1 (svbool_t pg, svint16_t x, svint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmple_wide (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test2:
+** cmple p0\.s, p0/z, z0\.s, z1\.d
+** ret
+*/
+svbool_t
+test2 (svbool_t pg, svint32_t x, svint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmple_wide (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test3:
+** cmple p0\.s, p0/z, z0\.s, z1\.d
+** ret
+*/
+svbool_t
+test3 (svbool_t pg, svint32_t x, svint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmple_wide (pg, x, y),
+ svptrue_b32 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_8.c
new file mode 100644
index 0000000..01281ca
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_8.c
@@ -0,0 +1,52 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** cmpls p0\.h, p0/z, z0\.h, z1\.d
+** ret
+*/
+svbool_t
+test1 (svbool_t pg, svuint16_t x, svuint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmple_wide (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test2:
+** cmpls p0\.s, p0/z, z0\.s, z1\.d
+** ret
+*/
+svbool_t
+test2 (svbool_t pg, svuint32_t x, svuint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmple_wide (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test3:
+** cmpls p0\.s, p0/z, z0\.s, z1\.d
+** ret
+*/
+svbool_t
+test3 (svbool_t pg, svuint32_t x, svuint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmple_wide (pg, x, y),
+ svptrue_b32 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_9.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_9.c
new file mode 100644
index 0000000..8d008b4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmple_9.c
@@ -0,0 +1,104 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** fcmle p0\.h, p0/z, z0\.h, z1\.h
+** ret
+*/
+svbool_t
+test1 (svbool_t pg, svfloat16_t x, svfloat16_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmple (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test2:
+** fcmle p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test2 (svbool_t pg, svfloat32_t x, svfloat32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmple (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test3:
+** fcmle p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test3 (svbool_t pg, svfloat32_t x, svfloat32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmple (pg, x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test4:
+** fcmle p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test4 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmple (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test5:
+** fcmle p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test5 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b32 (),
+ svcmple (pg, x, y),
+ svptrue_b8 ());
+}
+
+/*
+** test6:
+** fcmle p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test6 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmple (pg, x, y),
+ svptrue_b64 ());
+}
+
+/*
+** test7:
+** fcmle p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test7 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b32 (),
+ svcmple (pg, x, y),
+ svptrue_b64 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_1.c
new file mode 100644
index 0000000..a15bb4a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_1.c
@@ -0,0 +1,140 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svint8_t x, svint8_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmplt (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svint8_t x, svint8_t y, int *any)
+{
+ svbool_t res = svcmplt (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test3 (svbool_t pg, svint8_t x, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmplt (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test4 (svbool_t pg, svint8_t x, int *any)
+{
+ svbool_t res = svcmplt (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test5 (svint16_t x, svint16_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmplt (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test6 (svint16_t x, svint16_t y)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmplt (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test7 (svint16_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmplt (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test8 (svint16_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmplt (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test9 (svint32_t x, svint32_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmplt (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test10 (svint32_t x, svint32_t y)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmplt (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test11 (svint32_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmplt (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test12 (svint32_t x)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmplt (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test13 (svint64_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmplt (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test14 (svint64_t x, svint64_t y)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmplt (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test15 (svint64_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmplt (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test16 (svint64_t x)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmplt (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tcmplt\t} 16 } } */
+/* { dg-final { scan-assembler-times {\tcmplt\t[^\n]*, #10} 8 } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_2.c
new file mode 100644
index 0000000..43c53a1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_2.c
@@ -0,0 +1,140 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svuint8_t x, svuint8_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmplt (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svuint8_t x, svuint8_t y, int *any)
+{
+ svbool_t res = svcmplt (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test3 (svbool_t pg, svuint8_t x, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmplt (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test4 (svbool_t pg, svuint8_t x, int *any)
+{
+ svbool_t res = svcmplt (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test5 (svuint16_t x, svuint16_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmplt (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test6 (svuint16_t x, svuint16_t y)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmplt (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test7 (svuint16_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmplt (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test8 (svuint16_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmplt (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test9 (svuint32_t x, svuint32_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmplt (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test10 (svuint32_t x, svuint32_t y)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmplt (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test11 (svuint32_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmplt (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test12 (svuint32_t x)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmplt (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test13 (svuint64_t x, svuint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmplt (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test14 (svuint64_t x, svuint64_t y)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmplt (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test15 (svuint64_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmplt (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test16 (svuint64_t x)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmplt (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tcmplo\t} 16 } } */
+/* { dg-final { scan-assembler-times {\tcmplo\t[^\n]*, #10} 8 } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_3.c
new file mode 100644
index 0000000..bddbbeb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_3.c
@@ -0,0 +1,169 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** cmplt p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test1 (svbool_t p0, svint8_t x, svint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmplt (pg, x, y), p0);
+}
+
+/*
+** test2:
+** cmplt p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test2 (svbool_t p0, svint8_t x, svint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmplt (pg, x, y), p0);
+}
+
+/*
+** test3:
+** cmplt p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test3 (svbool_t p0, svint8_t x, svint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmplt (pg, x, y), pg);
+}
+
+/*
+** test4:
+** (
+** cmplt p0\.b, p0/z, z0\.b, #10
+** |
+** cmple p0\.b, p0/z, z0\.b, #9
+** )
+** ret
+*/
+svbool_t
+test4 (svbool_t p0, svint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmplt (pg, x, 10), p0);
+}
+
+/*
+** test5:
+** (
+** cmplt p0\.b, p0/z, z0\.b, #10
+** |
+** cmple p0\.b, p0/z, z0\.b, #9
+** )
+** ret
+*/
+svbool_t
+test5 (svbool_t p0, svint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmplt (pg, x, 10), p0);
+}
+
+/*
+** test6:
+** (
+** cmplt p0\.b, p0/z, z0\.b, #10
+** |
+** cmple p0\.b, p0/z, z0\.b, #9
+** )
+** ret
+*/
+svbool_t
+test6 (svbool_t p0, svint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmplt (pg, x, 10), pg);
+}
+
+/*
+** test7:
+** cmplt p0\.h, p0/z, z0\.h, z1\.h
+** ret
+*/
+svbool_t
+test7 (svbool_t p0, svint16_t x, svint16_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmplt (pg, x, y), p0);
+}
+
+/*
+** test8:
+** cmplt p0\.h, p0/z, z0\.h, #10
+** ret
+*/
+svbool_t
+test8 (svbool_t p0, svint16_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmplt (pg, x, 10), p0);
+}
+
+/*
+** test9:
+** cmplt p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test9 (svbool_t p0, svint32_t x, svint32_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmplt (pg, x, y), p0);
+}
+
+/*
+** test10:
+** cmplt p0\.s, p0/z, z0\.s, #10
+** ret
+*/
+svbool_t
+test10 (svbool_t p0, svint32_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmplt (pg, x, 10), p0);
+}
+
+/*
+** test11:
+** cmplt p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test11 (svbool_t p0, svint64_t x, svint64_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmplt (pg, x, y), p0);
+}
+
+/*
+** test12:
+** cmplt p0\.d, p0/z, z0\.d, #10
+** ret
+*/
+svbool_t
+test12 (svbool_t p0, svint64_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmplt (pg, x, 10), p0);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_4.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_4.c
new file mode 100644
index 0000000..b71c8e9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_4.c
@@ -0,0 +1,169 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** cmplo p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test1 (svbool_t p0, svuint8_t x, svuint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmplt (pg, x, y), p0);
+}
+
+/*
+** test2:
+** cmplo p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test2 (svbool_t p0, svuint8_t x, svuint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmplt (pg, x, y), p0);
+}
+
+/*
+** test3:
+** cmplo p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test3 (svbool_t p0, svuint8_t x, svuint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmplt (pg, x, y), pg);
+}
+
+/*
+** test4:
+** (
+** cmplo p0\.b, p0/z, z0\.b, #10
+** |
+** cmpls p0\.b, p0/z, z0\.b, #9
+** )
+** ret
+*/
+svbool_t
+test4 (svbool_t p0, svuint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmplt (pg, x, 10), p0);
+}
+
+/*
+** test5:
+** (
+** cmplo p0\.b, p0/z, z0\.b, #10
+** |
+** cmpls p0\.b, p0/z, z0\.b, #9
+** )
+** ret
+*/
+svbool_t
+test5 (svbool_t p0, svuint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmplt (pg, x, 10), p0);
+}
+
+/*
+** test6:
+** (
+** cmplo p0\.b, p0/z, z0\.b, #10
+** |
+** cmpls p0\.b, p0/z, z0\.b, #9
+** )
+** ret
+*/
+svbool_t
+test6 (svbool_t p0, svuint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmplt (pg, x, 10), pg);
+}
+
+/*
+** test7:
+** cmplo p0\.h, p0/z, z0\.h, z1\.h
+** ret
+*/
+svbool_t
+test7 (svbool_t p0, svuint16_t x, svuint16_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmplt (pg, x, y), p0);
+}
+
+/*
+** test8:
+** cmplo p0\.h, p0/z, z0\.h, #10
+** ret
+*/
+svbool_t
+test8 (svbool_t p0, svuint16_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmplt (pg, x, 10), p0);
+}
+
+/*
+** test9:
+** cmplo p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test9 (svbool_t p0, svuint32_t x, svuint32_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmplt (pg, x, y), p0);
+}
+
+/*
+** test10:
+** cmplo p0\.s, p0/z, z0\.s, #10
+** ret
+*/
+svbool_t
+test10 (svbool_t p0, svuint32_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmplt (pg, x, 10), p0);
+}
+
+/*
+** test11:
+** cmplo p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test11 (svbool_t p0, svuint64_t x, svuint64_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmplt (pg, x, y), p0);
+}
+
+/*
+** test12:
+** cmplo p0\.d, p0/z, z0\.d, #10
+** ret
+*/
+svbool_t
+test12 (svbool_t p0, svuint64_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmplt (pg, x, 10), p0);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_5.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_5.c
new file mode 100644
index 0000000..6885e4d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_5.c
@@ -0,0 +1,74 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svint8_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmplt_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svint8_t x, svint64_t y, int *any)
+{
+ svbool_t res = svcmplt_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test3 (svint8_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b8 ();
+ svbool_t res = svcmplt_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test4 (svint8_t x, svint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b8 ();
+ svbool_t res = svcmplt_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test5 (svint16_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmplt_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test6 (svint16_t x, svint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmplt_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test7 (svint32_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmplt_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test8 (svint32_t x, svint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmplt_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tcmplt\t} 8 } } */
+/* { dg-final { scan-assembler-times {\tptrue\t} 6 } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_6.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_6.c
new file mode 100644
index 0000000..e9be9e8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_6.c
@@ -0,0 +1,74 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svuint8_t x, svuint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmplt_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svuint8_t x, svuint64_t y, int *any)
+{
+ svbool_t res = svcmplt_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test3 (svuint8_t x, svuint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b8 ();
+ svbool_t res = svcmplt_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test4 (svuint8_t x, svuint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b8 ();
+ svbool_t res = svcmplt_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test5 (svuint16_t x, svuint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmplt_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test6 (svuint16_t x, svuint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmplt_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test7 (svuint32_t x, svuint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmplt_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test8 (svuint32_t x, svuint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmplt_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tcmplo\t} 8 } } */
+/* { dg-final { scan-assembler-times {\tptrue\t} 6 } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_7.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_7.c
new file mode 100644
index 0000000..a4de6ab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_7.c
@@ -0,0 +1,52 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** cmplt p0\.h, p0/z, z0\.h, z1\.d
+** ret
+*/
+svbool_t
+test1 (svbool_t pg, svint16_t x, svint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmplt_wide (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test2:
+** cmplt p0\.s, p0/z, z0\.s, z1\.d
+** ret
+*/
+svbool_t
+test2 (svbool_t pg, svint32_t x, svint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmplt_wide (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test3:
+** cmplt p0\.s, p0/z, z0\.s, z1\.d
+** ret
+*/
+svbool_t
+test3 (svbool_t pg, svint32_t x, svint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmplt_wide (pg, x, y),
+ svptrue_b32 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_8.c
new file mode 100644
index 0000000..0a095eb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_8.c
@@ -0,0 +1,52 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** cmplo p0\.h, p0/z, z0\.h, z1\.d
+** ret
+*/
+svbool_t
+test1 (svbool_t pg, svuint16_t x, svuint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmplt_wide (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test2:
+** cmplo p0\.s, p0/z, z0\.s, z1\.d
+** ret
+*/
+svbool_t
+test2 (svbool_t pg, svuint32_t x, svuint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmplt_wide (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test3:
+** cmplo p0\.s, p0/z, z0\.s, z1\.d
+** ret
+*/
+svbool_t
+test3 (svbool_t pg, svuint32_t x, svuint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmplt_wide (pg, x, y),
+ svptrue_b32 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_9.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_9.c
new file mode 100644
index 0000000..4f4b7b4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmplt_9.c
@@ -0,0 +1,104 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** fcmlt p0\.h, p0/z, z0\.h, z1\.h
+** ret
+*/
+svbool_t
+test1 (svbool_t pg, svfloat16_t x, svfloat16_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmplt (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test2:
+** fcmlt p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test2 (svbool_t pg, svfloat32_t x, svfloat32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmplt (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test3:
+** fcmlt p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test3 (svbool_t pg, svfloat32_t x, svfloat32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmplt (pg, x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test4:
+** fcmlt p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test4 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmplt (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test5:
+** fcmlt p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test5 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b32 (),
+ svcmplt (pg, x, y),
+ svptrue_b8 ());
+}
+
+/*
+** test6:
+** fcmlt p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test6 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmplt (pg, x, y),
+ svptrue_b64 ());
+}
+
+/*
+** test7:
+** fcmlt p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test7 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b32 (),
+ svcmplt (pg, x, y),
+ svptrue_b64 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpne_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpne_1.c
new file mode 100644
index 0000000..61f7718
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpne_1.c
@@ -0,0 +1,140 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svint8_t x, svint8_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmpne (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svint8_t x, svint8_t y, int *any)
+{
+ svbool_t res = svcmpne (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test3 (svbool_t pg, svint8_t x, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmpne (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test4 (svbool_t pg, svint8_t x, int *any)
+{
+ svbool_t res = svcmpne (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test5 (svint16_t x, svint16_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpne (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test6 (svint16_t x, svint16_t y)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpne (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test7 (svint16_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpne (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test8 (svint16_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpne (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test9 (svint32_t x, svint32_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpne (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test10 (svint32_t x, svint32_t y)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpne (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test11 (svint32_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpne (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test12 (svint32_t x)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpne (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+void
+test13 (svint64_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmpne (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test14 (svint64_t x, svint64_t y)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmpne (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test15 (svint64_t x, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmpne (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test16 (svint64_t x)
+{
+ svbool_t pg = svptrue_b64 ();
+ svbool_t res = svcmpne (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tcmpne\t} 16 } } */
+/* { dg-final { scan-assembler-times {\tcmpne\t[^\n]*, #10} 8 } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpne_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpne_2.c
new file mode 100644
index 0000000..53cedb3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpne_2.c
@@ -0,0 +1,157 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** cmpne p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test1 (svbool_t p0, svint8_t x, svint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpne (pg, x, y), p0);
+}
+
+/*
+** test2:
+** cmpne p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test2 (svbool_t p0, svint8_t x, svint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmpne (pg, x, y), p0);
+}
+
+/*
+** test3:
+** cmpne p0\.b, p0/z, z0\.b, z1\.b
+** ret
+*/
+svbool_t
+test3 (svbool_t p0, svint8_t x, svint8_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmpne (pg, x, y), pg);
+}
+
+/*
+** test4:
+** cmpne p0\.b, p0/z, z0\.b, #10
+** ret
+*/
+svbool_t
+test4 (svbool_t p0, svint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpne (pg, x, 10), p0);
+}
+
+/*
+** test5:
+** cmpne p0\.b, p0/z, z0\.b, #10
+** ret
+*/
+svbool_t
+test5 (svbool_t p0, svint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmpne (pg, x, 10), p0);
+}
+
+/*
+** test6:
+** cmpne p0\.b, p0/z, z0\.b, #10
+** ret
+*/
+svbool_t
+test6 (svbool_t p0, svint8_t x)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (p0, svcmpne (pg, x, 10), pg);
+}
+
+/*
+** test7:
+** cmpne p0\.h, p0/z, z0\.h, z1\.h
+** ret
+*/
+svbool_t
+test7 (svbool_t p0, svint16_t x, svint16_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpne (pg, x, y), p0);
+}
+
+/*
+** test8:
+** cmpne p0\.h, p0/z, z0\.h, #10
+** ret
+*/
+svbool_t
+test8 (svbool_t p0, svint16_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmpne (pg, x, 10), p0);
+}
+
+/*
+** test9:
+** cmpne p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test9 (svbool_t p0, svint32_t x, svint32_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpne (pg, x, y), p0);
+}
+
+/*
+** test10:
+** cmpne p0\.s, p0/z, z0\.s, #10
+** ret
+*/
+svbool_t
+test10 (svbool_t p0, svint32_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmpne (pg, x, 10), p0);
+}
+
+/*
+** test11:
+** cmpne p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test11 (svbool_t p0, svint64_t x, svint64_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ return svand_z (pg, svcmpne (pg, x, y), p0);
+}
+
+/*
+** test12:
+** cmpne p0\.d, p0/z, z0\.d, #10
+** ret
+*/
+svbool_t
+test12 (svbool_t p0, svint64_t x)
+{
+ svbool_t pg = svptrue_b16 ();
+ return svand_z (pg, svcmpne (pg, x, 10), p0);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpne_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpne_3.c
new file mode 100644
index 0000000..c5c3936
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpne_3.c
@@ -0,0 +1,74 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svint8_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmpne_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svint8_t x, svint64_t y, int *any)
+{
+ svbool_t res = svcmpne_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test3 (svint8_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b8 ();
+ svbool_t res = svcmpne_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test4 (svint8_t x, svint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b8 ();
+ svbool_t res = svcmpne_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test5 (svint16_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpne_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test6 (svint16_t x, svint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b16 ();
+ svbool_t res = svcmpne_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test7 (svint32_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpne_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test8 (svint32_t x, svint64_t y, int *any)
+{
+ svbool_t pg = svptrue_b32 ();
+ svbool_t res = svcmpne_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tcmpne\t} 8 } } */
+/* { dg-final { scan-assembler-times {\tptrue\t} 6 } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpne_4.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpne_4.c
new file mode 100644
index 0000000..595e024
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpne_4.c
@@ -0,0 +1,52 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** cmpne p0\.h, p0/z, z0\.h, z1\.d
+** ret
+*/
+svbool_t
+test1 (svbool_t pg, svint16_t x, svint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpne_wide (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test2:
+** cmpne p0\.s, p0/z, z0\.s, z1\.d
+** ret
+*/
+svbool_t
+test2 (svbool_t pg, svint32_t x, svint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpne_wide (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test3:
+** cmpne p0\.s, p0/z, z0\.s, z1\.d
+** ret
+*/
+svbool_t
+test3 (svbool_t pg, svint32_t x, svint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpne_wide (pg, x, y),
+ svptrue_b32 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpne_5.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpne_5.c
new file mode 100644
index 0000000..94fecd8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpne_5.c
@@ -0,0 +1,104 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** fcmne p0\.h, p0/z, z0\.h, z1\.h
+** ret
+*/
+svbool_t
+test1 (svbool_t pg, svfloat16_t x, svfloat16_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpne (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test2:
+** fcmne p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test2 (svbool_t pg, svfloat32_t x, svfloat32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpne (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test3:
+** fcmne p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test3 (svbool_t pg, svfloat32_t x, svfloat32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpne (pg, x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test4:
+** fcmne p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test4 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpne (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test5:
+** fcmne p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test5 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b32 (),
+ svcmpne (pg, x, y),
+ svptrue_b8 ());
+}
+
+/*
+** test6:
+** fcmne p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test6 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpne (pg, x, y),
+ svptrue_b64 ());
+}
+
+/*
+** test7:
+** fcmne p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test7 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b32 (),
+ svcmpne (pg, x, y),
+ svptrue_b64 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpuo_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpuo_1.c
new file mode 100644
index 0000000..4b124b3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpuo_1.c
@@ -0,0 +1,104 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** fcmuo p0\.h, p0/z, z0\.h, z1\.h
+** ret
+*/
+svbool_t
+test1 (svbool_t pg, svfloat16_t x, svfloat16_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpuo (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test2:
+** fcmuo p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test2 (svbool_t pg, svfloat32_t x, svfloat32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpuo (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test3:
+** fcmuo p0\.s, p0/z, z0\.s, z1\.s
+** ret
+*/
+svbool_t
+test3 (svbool_t pg, svfloat32_t x, svfloat32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpuo (pg, x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test4:
+** fcmuo p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test4 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpuo (pg, x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test5:
+** fcmuo p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test5 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b32 (),
+ svcmpuo (pg, x, y),
+ svptrue_b8 ());
+}
+
+/*
+** test6:
+** fcmuo p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test6 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svcmpuo (pg, x, y),
+ svptrue_b64 ());
+}
+
+/*
+** test7:
+** fcmuo p0\.d, p0/z, z0\.d, z1\.d
+** ret
+*/
+svbool_t
+test7 (svbool_t pg, svfloat64_t x, svfloat64_t y)
+{
+ return svand_z (svptrue_b32 (),
+ svcmpuo (pg, x, y),
+ svptrue_b64 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dup_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dup_1.c
new file mode 100644
index 0000000..c3c4e2d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dup_1.c
@@ -0,0 +1,47 @@
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+svbool_t
+test1 (int x)
+{
+ return svand_z (svptrue_b16 (), svdup_b16 (x), svptrue_b16 ());
+}
+
+svbool_t
+test2 (int x)
+{
+ return svand_z (svptrue_b8 (), svdup_b32 (x), svptrue_b16 ());
+}
+
+svbool_t
+test3 (int x)
+{
+ return svand_z (svptrue_b32 (), svdup_b32 (x), svptrue_b16 ());
+}
+
+svbool_t
+test4 (int x)
+{
+ return svand_z (svptrue_b32 (), svdup_b32 (x), svptrue_b32 ());
+}
+
+svbool_t
+test5 (int x)
+{
+ return svand_z (svptrue_b8 (), svdup_b64 (x), svptrue_b32 ());
+}
+
+svbool_t
+test6 (int x)
+{
+ return svand_z (svptrue_b16 (), svdup_b64 (x), svptrue_b8 ());
+}
+
+svbool_t
+test7 (int x)
+{
+ return svand_z (svptrue_b16 (), svdup_b64 (x), svptrue_b64 ());
+}
+
+/* { dg-final { scan-assembler-not {\tand\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_13.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_13.c
new file mode 100644
index 0000000..6d702b8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_13.c
@@ -0,0 +1,45 @@
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+svbool_t
+test1 (int x0, int x1)
+{
+ return svand_z (svptrue_b8 (), svdupq_b64 (x0, x1), svptrue_b16 ());
+}
+
+svbool_t
+test2 (int x0, int x1, int x2, int x3)
+{
+ return svand_z (svptrue_b8 (), svdupq_b32 (x0, x1, x2, x3), svptrue_b16 ());
+}
+
+svbool_t
+test3 (int x0, int x1, int x2, int x3)
+{
+ return svand_z (svptrue_b32 (), svdupq_b32 (x0, x1, x2, x3), svptrue_b16 ());
+}
+
+svbool_t
+test4 (int x0, int x1, int x2, int x3)
+{
+ return svand_z (svptrue_b32 (), svdupq_b32 (x0, x1, x2, x3), svptrue_b32 ());
+}
+
+svbool_t
+test5 (int x0, int x1, int x2, int x3)
+{
+ return svand_z (svptrue_b8 (),
+ svdupq_b16 (x0, x1, x2, x3, x2, x0, x1, x3),
+ svptrue_b32 ());
+}
+
+svbool_t
+test6 (int x0, int x1, int x2, int x3)
+{
+ return svand_z (svptrue_b64 (),
+ svdupq_b16 (x0, x1, x2, x3, x2, x0, x1, x3),
+ svptrue_b16 ());
+}
+
+/* { dg-final { scan-assembler-not {\tand\tp} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_lane_9.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_lane_9.c
new file mode 100644
index 0000000..e3f352b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_lane_9.c
@@ -0,0 +1,8 @@
+/* { dg-options "-O2 -mbig-endian" } */
+
+#pragma GCC aarch64 "arm_sve.h"
+
+svint32_t f(svint32_t x) { return svdupq_lane (x, 17); }
+void g(svint32_t *a, svint32_t *b) { *a = svdupq_lane (*b, 17); }
+
+/* { dg-final { scan-assembler-not {\trevw\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/perm_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/perm_2.c
new file mode 100644
index 0000000..9b3daaa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/perm_2.c
@@ -0,0 +1,96 @@
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** ...
+** ptrue (p[0-3])\.h, all
+** ...
+** trn1 p0\.h, p[0-3]\.h, \1\.h
+** ret
+*/
+svbool_t
+test1 ()
+{
+ return svtrn1_b16 (svptrue_b8 (), svptrue_b16 ());
+}
+
+/*
+** test2:
+** ...
+** ptrue (p[0-3])\.h, all
+** ...
+** trn1 p0\.h, \1\.h, p[0-3]\.h
+** ret
+*/
+svbool_t
+test2 ()
+{
+ return svtrn1_b16 (svptrue_b16 (), svptrue_b8 ());
+}
+
+/*
+** test3:
+** ...
+** ptrue (p[0-3])\.s, all
+** ...
+** trn1 p0\.s, p[0-3]\.s, \1\.s
+** ret
+*/
+svbool_t
+test3 ()
+{
+ return svtrn1_b32 (svptrue_b8 (), svptrue_b32 ());
+}
+
+/*
+** test4:
+** ...
+** ptrue (p[0-3])\.s, all
+** ...
+** trn1 p0\.s, \1\.s, p[0-3]\.s
+** ret
+*/
+svbool_t
+test4 ()
+{
+ return svtrn1_b32 (svptrue_b32 (), svptrue_b8 ());
+}
+
+/*
+** test5:
+** ...
+** ptrue (p[0-3])\.d, all
+** ...
+** trn1 p0\.d, p[0-3]\.d, \1\.d
+** ret
+*/
+svbool_t
+test5 ()
+{
+ return svtrn1_b64 (svptrue_b8 (), svptrue_b64 ());
+}
+
+/*
+** test6:
+** ...
+** ptrue (p[0-3])\.d, all
+** ...
+** trn1 p0\.d, \1\.d, p[0-3]\.d
+** ret
+*/
+svbool_t
+test6 ()
+{
+ return svtrn1_b64 (svptrue_b64 (), svptrue_b8 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/perm_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/perm_3.c
new file mode 100644
index 0000000..678c541
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/perm_3.c
@@ -0,0 +1,96 @@
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** ...
+** ptrue (p[0-3])\.h, all
+** ...
+** trn2 p0\.h, p[0-3]\.h, \1\.h
+** ret
+*/
+svbool_t
+test1 ()
+{
+ return svtrn2_b16 (svptrue_b8 (), svptrue_b16 ());
+}
+
+/*
+** test2:
+** ...
+** ptrue (p[0-3])\.h, all
+** ...
+** trn2 p0\.h, \1\.h, p[0-3]\.h
+** ret
+*/
+svbool_t
+test2 ()
+{
+ return svtrn2_b16 (svptrue_b16 (), svptrue_b8 ());
+}
+
+/*
+** test3:
+** ...
+** ptrue (p[0-3])\.s, all
+** ...
+** trn2 p0\.s, p[0-3]\.s, \1\.s
+** ret
+*/
+svbool_t
+test3 ()
+{
+ return svtrn2_b32 (svptrue_b8 (), svptrue_b32 ());
+}
+
+/*
+** test4:
+** ...
+** ptrue (p[0-3])\.s, all
+** ...
+** trn2 p0\.s, \1\.s, p[0-3]\.s
+** ret
+*/
+svbool_t
+test4 ()
+{
+ return svtrn2_b32 (svptrue_b32 (), svptrue_b8 ());
+}
+
+/*
+** test5:
+** ...
+** ptrue (p[0-3])\.d, all
+** ...
+** trn2 p0\.d, p[0-3]\.d, \1\.d
+** ret
+*/
+svbool_t
+test5 ()
+{
+ return svtrn2_b64 (svptrue_b8 (), svptrue_b64 ());
+}
+
+/*
+** test6:
+** ...
+** ptrue (p[0-3])\.d, all
+** ...
+** trn2 p0\.d, \1\.d, p[0-3]\.d
+** ret
+*/
+svbool_t
+test6 ()
+{
+ return svtrn2_b64 (svptrue_b64 (), svptrue_b8 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/perm_4.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/perm_4.c
new file mode 100644
index 0000000..28c6018
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/perm_4.c
@@ -0,0 +1,96 @@
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** ...
+** ptrue (p[0-3])\.h, all
+** ...
+** zip1 p0\.h, p[0-3]\.h, \1\.h
+** ret
+*/
+svbool_t
+test1 ()
+{
+ return svzip1_b16 (svptrue_b8 (), svptrue_b16 ());
+}
+
+/*
+** test2:
+** ...
+** ptrue (p[0-3])\.h, all
+** ...
+** zip1 p0\.h, \1\.h, p[0-3]\.h
+** ret
+*/
+svbool_t
+test2 ()
+{
+ return svzip1_b16 (svptrue_b16 (), svptrue_b8 ());
+}
+
+/*
+** test3:
+** ...
+** ptrue (p[0-3])\.s, all
+** ...
+** zip1 p0\.s, p[0-3]\.s, \1\.s
+** ret
+*/
+svbool_t
+test3 ()
+{
+ return svzip1_b32 (svptrue_b8 (), svptrue_b32 ());
+}
+
+/*
+** test4:
+** ...
+** ptrue (p[0-3])\.s, all
+** ...
+** zip1 p0\.s, \1\.s, p[0-3]\.s
+** ret
+*/
+svbool_t
+test4 ()
+{
+ return svzip1_b32 (svptrue_b32 (), svptrue_b8 ());
+}
+
+/*
+** test5:
+** ...
+** ptrue (p[0-3])\.d, all
+** ...
+** zip1 p0\.d, p[0-3]\.d, \1\.d
+** ret
+*/
+svbool_t
+test5 ()
+{
+ return svzip1_b64 (svptrue_b8 (), svptrue_b64 ());
+}
+
+/*
+** test6:
+** ...
+** ptrue (p[0-3])\.d, all
+** ...
+** zip1 p0\.d, \1\.d, p[0-3]\.d
+** ret
+*/
+svbool_t
+test6 ()
+{
+ return svzip1_b64 (svptrue_b64 (), svptrue_b8 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/perm_5.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/perm_5.c
new file mode 100644
index 0000000..a8aec2b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/perm_5.c
@@ -0,0 +1,96 @@
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** ...
+** ptrue (p[0-3])\.h, all
+** ...
+** zip2 p0\.h, p[0-3]\.h, \1\.h
+** ret
+*/
+svbool_t
+test1 ()
+{
+ return svzip2_b16 (svptrue_b8 (), svptrue_b16 ());
+}
+
+/*
+** test2:
+** ...
+** ptrue (p[0-3])\.h, all
+** ...
+** zip2 p0\.h, \1\.h, p[0-3]\.h
+** ret
+*/
+svbool_t
+test2 ()
+{
+ return svzip2_b16 (svptrue_b16 (), svptrue_b8 ());
+}
+
+/*
+** test3:
+** ...
+** ptrue (p[0-3])\.s, all
+** ...
+** zip2 p0\.s, p[0-3]\.s, \1\.s
+** ret
+*/
+svbool_t
+test3 ()
+{
+ return svzip2_b32 (svptrue_b8 (), svptrue_b32 ());
+}
+
+/*
+** test4:
+** ...
+** ptrue (p[0-3])\.s, all
+** ...
+** zip2 p0\.s, \1\.s, p[0-3]\.s
+** ret
+*/
+svbool_t
+test4 ()
+{
+ return svzip2_b32 (svptrue_b32 (), svptrue_b8 ());
+}
+
+/*
+** test5:
+** ...
+** ptrue (p[0-3])\.d, all
+** ...
+** zip2 p0\.d, p[0-3]\.d, \1\.d
+** ret
+*/
+svbool_t
+test5 ()
+{
+ return svzip2_b64 (svptrue_b8 (), svptrue_b64 ());
+}
+
+/*
+** test6:
+** ...
+** ptrue (p[0-3])\.d, all
+** ...
+** zip2 p0\.d, \1\.d, p[0-3]\.d
+** ret
+*/
+svbool_t
+test6 ()
+{
+ return svzip2_b64 (svptrue_b64 (), svptrue_b8 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/perm_6.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/perm_6.c
new file mode 100644
index 0000000..3405004
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/perm_6.c
@@ -0,0 +1,96 @@
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** ...
+** ptrue (p[0-3])\.h, all
+** ...
+** uzp1 p0\.h, p[0-3]\.h, \1\.h
+** ret
+*/
+svbool_t
+test1 ()
+{
+ return svuzp1_b16 (svptrue_b8 (), svptrue_b16 ());
+}
+
+/*
+** test2:
+** ...
+** ptrue (p[0-3])\.h, all
+** ...
+** uzp1 p0\.h, \1\.h, p[0-3]\.h
+** ret
+*/
+svbool_t
+test2 ()
+{
+ return svuzp1_b16 (svptrue_b16 (), svptrue_b8 ());
+}
+
+/*
+** test3:
+** ...
+** ptrue (p[0-3])\.s, all
+** ...
+** uzp1 p0\.s, p[0-3]\.s, \1\.s
+** ret
+*/
+svbool_t
+test3 ()
+{
+ return svuzp1_b32 (svptrue_b8 (), svptrue_b32 ());
+}
+
+/*
+** test4:
+** ...
+** ptrue (p[0-3])\.s, all
+** ...
+** uzp1 p0\.s, \1\.s, p[0-3]\.s
+** ret
+*/
+svbool_t
+test4 ()
+{
+ return svuzp1_b32 (svptrue_b32 (), svptrue_b8 ());
+}
+
+/*
+** test5:
+** ...
+** ptrue (p[0-3])\.d, all
+** ...
+** uzp1 p0\.d, p[0-3]\.d, \1\.d
+** ret
+*/
+svbool_t
+test5 ()
+{
+ return svuzp1_b64 (svptrue_b8 (), svptrue_b64 ());
+}
+
+/*
+** test6:
+** ...
+** ptrue (p[0-3])\.d, all
+** ...
+** uzp1 p0\.d, \1\.d, p[0-3]\.d
+** ret
+*/
+svbool_t
+test6 ()
+{
+ return svuzp1_b64 (svptrue_b64 (), svptrue_b8 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/perm_7.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/perm_7.c
new file mode 100644
index 0000000..1758d00
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/perm_7.c
@@ -0,0 +1,96 @@
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** ...
+** ptrue (p[0-3])\.h, all
+** ...
+** uzp2 p0\.h, p[0-3]\.h, \1\.h
+** ret
+*/
+svbool_t
+test1 ()
+{
+ return svuzp2_b16 (svptrue_b8 (), svptrue_b16 ());
+}
+
+/*
+** test2:
+** ...
+** ptrue (p[0-3])\.h, all
+** ...
+** uzp2 p0\.h, \1\.h, p[0-3]\.h
+** ret
+*/
+svbool_t
+test2 ()
+{
+ return svuzp2_b16 (svptrue_b16 (), svptrue_b8 ());
+}
+
+/*
+** test3:
+** ...
+** ptrue (p[0-3])\.s, all
+** ...
+** uzp2 p0\.s, p[0-3]\.s, \1\.s
+** ret
+*/
+svbool_t
+test3 ()
+{
+ return svuzp2_b32 (svptrue_b8 (), svptrue_b32 ());
+}
+
+/*
+** test4:
+** ...
+** ptrue (p[0-3])\.s, all
+** ...
+** uzp2 p0\.s, \1\.s, p[0-3]\.s
+** ret
+*/
+svbool_t
+test4 ()
+{
+ return svuzp2_b32 (svptrue_b32 (), svptrue_b8 ());
+}
+
+/*
+** test5:
+** ...
+** ptrue (p[0-3])\.d, all
+** ...
+** uzp2 p0\.d, p[0-3]\.d, \1\.d
+** ret
+*/
+svbool_t
+test5 ()
+{
+ return svuzp2_b64 (svptrue_b8 (), svptrue_b64 ());
+}
+
+/*
+** test6:
+** ...
+** ptrue (p[0-3])\.d, all
+** ...
+** uzp2 p0\.d, \1\.d, p[0-3]\.d
+** ret
+*/
+svbool_t
+test6 ()
+{
+ return svuzp2_b64 (svptrue_b64 (), svptrue_b8 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pnext_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pnext_3.c
new file mode 100644
index 0000000..d9c0090
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pnext_3.c
@@ -0,0 +1,130 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** pnext p0\.h, p1, p0\.h
+** ret
+*/
+svbool_t
+test1 (svbool_t pg, svbool_t prev)
+{
+ return svand_z (svptrue_b8 (),
+ svpnext_b16 (prev, pg),
+ svptrue_b16 ());
+}
+
+/*
+** test2:
+** pnext p0\.h, p1, p0\.h
+** ret
+*/
+svbool_t
+test2 (svbool_t pg, svbool_t prev)
+{
+ return svand_z (svptrue_b16 (),
+ svpnext_b16 (prev, pg),
+ svptrue_b8 ());
+}
+
+/*
+** test3:
+** pnext p0\.h, p1, p0\.h
+** ret
+*/
+svbool_t
+test3 (svbool_t pg, svbool_t prev)
+{
+ return svand_z (svptrue_b16 (),
+ svpnext_b16 (prev, pg),
+ svptrue_b16 ());
+}
+
+/*
+** test4:
+** pnext p0\.s, p1, p0\.s
+** ret
+*/
+svbool_t
+test4 (svbool_t pg, svbool_t prev)
+{
+ return svand_z (svptrue_b32 (),
+ svpnext_b32 (prev, pg),
+ svptrue_b8 ());
+}
+
+/*
+** test5:
+** pnext p0\.s, p1, p0\.s
+** ret
+*/
+svbool_t
+test5 (svbool_t pg, svbool_t prev)
+{
+ return svand_z (svptrue_b16 (),
+ svpnext_b32 (prev, pg),
+ svptrue_b8 ());
+}
+
+/*
+** test6:
+** pnext p0\.s, p1, p0\.s
+** ret
+*/
+svbool_t
+test6 (svbool_t pg, svbool_t prev)
+{
+ return svand_z (svptrue_b8 (),
+ svpnext_b32 (prev, pg),
+ svptrue_b32 ());
+}
+
+/*
+** test7:
+** pnext p0\.d, p1, p0\.d
+** ret
+*/
+svbool_t
+test7 (svbool_t pg, svbool_t prev)
+{
+ return svand_z (svptrue_b16 (),
+ svpnext_b64 (prev, pg),
+ svptrue_b8 ());
+}
+
+/*
+** test8:
+** pnext p0\.d, p1, p0\.d
+** ret
+*/
+svbool_t
+test8 (svbool_t pg, svbool_t prev)
+{
+ return svand_z (svptrue_b32 (),
+ svpnext_b64 (prev, pg),
+ svptrue_b8 ());
+}
+
+/*
+** test9:
+** pnext p0\.d, p1, p0\.d
+** ret
+*/
+svbool_t
+test9 (svbool_t pg, svbool_t prev)
+{
+ return svand_z (svptrue_b8 (),
+ svpnext_b64 (prev, pg),
+ svptrue_b64 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr121118_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr121118_1.c
new file mode 100644
index 0000000..b59a972
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr121118_1.c
@@ -0,0 +1,16 @@
+/* { dg-options "-O2 -msve-vector-bits=512" } */
+
+typedef __SVBool_t fixed_bool __attribute__((arm_sve_vector_bits(512)));
+
+#define TEST_CONST(NAME, CONST) \
+ fixed_bool \
+ NAME () \
+ { \
+ union { unsigned long long i; fixed_bool pg; } u = { CONST }; \
+ return u.pg; \
+ }
+
+TEST_CONST (test1, 0x02aaaaaaaa)
+TEST_CONST (test2, 0x0155555557)
+TEST_CONST (test3, 0x0013333333333333ULL)
+TEST_CONST (test4, 0x0011111111111113ULL)
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/rev_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/rev_2.c
new file mode 100644
index 0000000..3dc4eb9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/rev_2.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+svbool_t test1()
+{
+ return svrev_b16 (svptrue_b16 ());
+}
+
+svbool_t test2()
+{
+ return svrev_b32 (svptrue_b32 ());
+}
+
+svbool_t test3()
+{
+ return svrev_b64 (svptrue_b64 ());
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.h} } } */
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.s} } } */
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.d} } } */
+/* { dg-final { scan-assembler-not {\tptrue\tp[0-7]\.b} } } */
+/* { dg-final { scan-assembler {\trev\tp0\.h} } } */
+/* { dg-final { scan-assembler {\trev\tp0\.s} } } */
+/* { dg-final { scan-assembler {\trev\tp0\.d} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/unpkhi_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/unpkhi_1.c
new file mode 100644
index 0000000..9c7b4bc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/unpkhi_1.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+svbool_t
+test1 (svbool_t p)
+{
+ return svand_z (svptrue_b8 (), svunpkhi (p), svptrue_b16 ());
+}
+
+svbool_t
+test2 (svbool_t p)
+{
+ return svand_z (svptrue_b16 (), svunpkhi (p), svptrue_b8 ());
+}
+
+svbool_t
+test3 (svbool_t p)
+{
+ return svand_z (svptrue_b16 (), svunpkhi (p), svptrue_b16 ());
+}
+
+/* { dg-final { scan-assembler-not {\tand\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/unpklo_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/unpklo_1.c
new file mode 100644
index 0000000..f072a2f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/unpklo_1.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+svbool_t
+test1 (svbool_t p)
+{
+ return svand_z (svptrue_b8 (), svunpklo (p), svptrue_b16 ());
+}
+
+svbool_t
+test2 (svbool_t p)
+{
+ return svand_z (svptrue_b16 (), svunpklo (p), svptrue_b8 ());
+}
+
+svbool_t
+test3 (svbool_t p)
+{
+ return svand_z (svptrue_b16 (), svunpklo (p), svptrue_b16 ());
+}
+
+/* { dg-final { scan-assembler-not {\tand\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_13.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_13.c
new file mode 100644
index 0000000..cf50dc1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_13.c
@@ -0,0 +1,130 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** whilele p0\.h, w0, w1
+** ret
+*/
+svbool_t
+test1 (int32_t x, int32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svwhilele_b16 (x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test2:
+** whilele p0\.h, x0, x1
+** ret
+*/
+svbool_t
+test2 (int64_t x, int64_t y)
+{
+ return svand_z (svptrue_b16 (),
+ svwhilele_b16 (x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test3:
+** whilels p0\.s, w0, w1
+** ret
+*/
+svbool_t
+test3 (uint32_t x, uint32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svwhilele_b32 (x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test4:
+** whilels p0\.s, x0, x1
+** ret
+*/
+svbool_t
+test4 (uint64_t x, uint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svwhilele_b32 (x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test5:
+** whilele p0\.s, w0, w1
+** ret
+*/
+svbool_t
+test5 (int32_t x, int32_t y)
+{
+ return svand_z (svptrue_b16 (),
+ svwhilele_b32 (x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test6:
+** whilels p0\.s, w0, w1
+** ret
+*/
+svbool_t
+test6 (uint32_t x, uint32_t y)
+{
+ return svand_z (svptrue_b32 (),
+ svwhilele_b32 (x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test7:
+** whilels p0\.d, w0, w1
+** ret
+*/
+svbool_t
+test7 (uint32_t x, uint32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svwhilele_b64 (x, y),
+ svptrue_b64 ());
+}
+
+/*
+** test8:
+** whilele p0\.d, x0, x1
+** ret
+*/
+svbool_t
+test8 (int64_t x, int64_t y)
+{
+ return svand_z (svptrue_b16 (),
+ svwhilele_b64 (x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test9:
+** whilels p0\.d, x0, x1
+** ret
+*/
+svbool_t
+test9 (uint64_t x, uint64_t y)
+{
+ return svand_z (svptrue_b64 (),
+ svwhilele_b64 (x, y),
+ svptrue_b64 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilelt_6.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilelt_6.c
new file mode 100644
index 0000000..27bf0c2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilelt_6.c
@@ -0,0 +1,130 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** whilelt p0\.h, w0, w1
+** ret
+*/
+svbool_t
+test1 (int32_t x, int32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svwhilelt_b16 (x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test2:
+** whilelt p0\.h, x0, x1
+** ret
+*/
+svbool_t
+test2 (int64_t x, int64_t y)
+{
+ return svand_z (svptrue_b16 (),
+ svwhilelt_b16 (x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test3:
+** whilelo p0\.s, w0, w1
+** ret
+*/
+svbool_t
+test3 (uint32_t x, uint32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svwhilelt_b32 (x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test4:
+** whilelo p0\.s, x0, x1
+** ret
+*/
+svbool_t
+test4 (uint64_t x, uint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svwhilelt_b32 (x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test5:
+** whilelt p0\.s, w0, w1
+** ret
+*/
+svbool_t
+test5 (int32_t x, int32_t y)
+{
+ return svand_z (svptrue_b16 (),
+ svwhilelt_b32 (x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test6:
+** whilelo p0\.s, w0, w1
+** ret
+*/
+svbool_t
+test6 (uint32_t x, uint32_t y)
+{
+ return svand_z (svptrue_b32 (),
+ svwhilelt_b32 (x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test7:
+** whilelo p0\.d, w0, w1
+** ret
+*/
+svbool_t
+test7 (uint32_t x, uint32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svwhilelt_b64 (x, y),
+ svptrue_b64 ());
+}
+
+/*
+** test8:
+** whilelt p0\.d, x0, x1
+** ret
+*/
+svbool_t
+test8 (int64_t x, int64_t y)
+{
+ return svand_z (svptrue_b16 (),
+ svwhilelt_b64 (x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test9:
+** whilelo p0\.d, x0, x1
+** ret
+*/
+svbool_t
+test9 (uint64_t x, uint64_t y)
+{
+ return svand_z (svptrue_b64 (),
+ svwhilelt_b64 (x, y),
+ svptrue_b64 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pred_clobber_1.c b/gcc/testsuite/gcc.target/aarch64/sve/pred_clobber_1.c
index 38dfdd4..e777f03 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/pred_clobber_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/pred_clobber_1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mcpu=neoverse-n2" } */
+/* { dg-options "-O2 -mcpu=neoverse-n2 -fdisable-rtl-combine" } */
/* { dg-final { check-function-bodies "**" "" } } */
#pragma GCC target "+sve"
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pred_clobber_2.c b/gcc/testsuite/gcc.target/aarch64/sve/pred_clobber_2.c
index 45363cc..41182e1 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/pred_clobber_2.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/pred_clobber_2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mcpu=neoverse-v2" } */
+/* { dg-options "-O2 -mcpu=neoverse-v2 -fdisable-rtl-combine" } */
/* { dg-final { check-function-bodies "**" "" } } */
#pragma GCC target "+sve"
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pred_clobber_3.c b/gcc/testsuite/gcc.target/aarch64/sve/pred_clobber_3.c
index c50a581..04a9023 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/pred_clobber_3.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/pred_clobber_3.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mcpu=neoverse-v1" } */
+/* { dg-options "-O2 -mcpu=neoverse-v1 -fdisable-rtl-combine" } */
/* { dg-final { check-function-bodies "**" "" } } */
#pragma GCC target "+sve"
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/match_4.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/match_4.c
new file mode 100644
index 0000000..57f625b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/match_4.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+svbool_t
+test1 (svbool_t pg, svint16_t x, svint16_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svmatch (pg, x, y),
+ svptrue_b16 ());
+}
+
+svbool_t
+test2 (svbool_t pg, svint16_t x, svint16_t y)
+{
+ return svand_z (svptrue_b16 (),
+ svmatch (pg, x, y),
+ svptrue_b8 ());
+}
+
+svbool_t
+test3 (svbool_t pg, svint16_t x, svint16_t y)
+{
+ return svand_z (svptrue_b16 (),
+ svmatch (pg, x, y),
+ svptrue_b16 ());
+}
+
+/* { dg-final { scan-assembler-not {\tand\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/nmatch_1.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/nmatch_1.c
new file mode 100644
index 0000000..a3b1e2d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/nmatch_1.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+svbool_t
+test1 (svbool_t pg, svint16_t x, svint16_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svnmatch (pg, x, y),
+ svptrue_b16 ());
+}
+
+svbool_t
+test2 (svbool_t pg, svint16_t x, svint16_t y)
+{
+ return svand_z (svptrue_b16 (),
+ svnmatch (pg, x, y),
+ svptrue_b8 ());
+}
+
+svbool_t
+test3 (svbool_t pg, svint16_t x, svint16_t y)
+{
+ return svand_z (svptrue_b16 (),
+ svnmatch (pg, x, y),
+ svptrue_b16 ());
+}
+
+/* { dg-final { scan-assembler-not {\tand\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilege_1.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilege_1.c
new file mode 100644
index 0000000..07b56a8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilege_1.c
@@ -0,0 +1,130 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** whilege p0\.h, w0, w1
+** ret
+*/
+svbool_t
+test1 (int32_t x, int32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svwhilege_b16 (x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test2:
+** whilege p0\.h, x0, x1
+** ret
+*/
+svbool_t
+test2 (int64_t x, int64_t y)
+{
+ return svand_z (svptrue_b16 (),
+ svwhilege_b16 (x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test3:
+** whilehs p0\.s, w0, w1
+** ret
+*/
+svbool_t
+test3 (uint32_t x, uint32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svwhilege_b32 (x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test4:
+** whilehs p0\.s, x0, x1
+** ret
+*/
+svbool_t
+test4 (uint64_t x, uint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svwhilege_b32 (x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test5:
+** whilege p0\.s, w0, w1
+** ret
+*/
+svbool_t
+test5 (int32_t x, int32_t y)
+{
+ return svand_z (svptrue_b16 (),
+ svwhilege_b32 (x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test6:
+** whilehs p0\.s, w0, w1
+** ret
+*/
+svbool_t
+test6 (uint32_t x, uint32_t y)
+{
+ return svand_z (svptrue_b32 (),
+ svwhilege_b32 (x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test7:
+** whilehs p0\.d, w0, w1
+** ret
+*/
+svbool_t
+test7 (uint32_t x, uint32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svwhilege_b64 (x, y),
+ svptrue_b64 ());
+}
+
+/*
+** test8:
+** whilege p0\.d, x0, x1
+** ret
+*/
+svbool_t
+test8 (int64_t x, int64_t y)
+{
+ return svand_z (svptrue_b16 (),
+ svwhilege_b64 (x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test9:
+** whilehs p0\.d, x0, x1
+** ret
+*/
+svbool_t
+test9 (uint64_t x, uint64_t y)
+{
+ return svand_z (svptrue_b64 (),
+ svwhilege_b64 (x, y),
+ svptrue_b64 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilegt_1.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilegt_1.c
new file mode 100644
index 0000000..df707c3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilegt_1.c
@@ -0,0 +1,130 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** whilegt p0\.h, w0, w1
+** ret
+*/
+svbool_t
+test1 (int32_t x, int32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svwhilegt_b16 (x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test2:
+** whilegt p0\.h, x0, x1
+** ret
+*/
+svbool_t
+test2 (int64_t x, int64_t y)
+{
+ return svand_z (svptrue_b16 (),
+ svwhilegt_b16 (x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test3:
+** whilehi p0\.s, w0, w1
+** ret
+*/
+svbool_t
+test3 (uint32_t x, uint32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svwhilegt_b32 (x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test4:
+** whilehi p0\.s, x0, x1
+** ret
+*/
+svbool_t
+test4 (uint64_t x, uint64_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svwhilegt_b32 (x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test5:
+** whilegt p0\.s, w0, w1
+** ret
+*/
+svbool_t
+test5 (int32_t x, int32_t y)
+{
+ return svand_z (svptrue_b16 (),
+ svwhilegt_b32 (x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test6:
+** whilehi p0\.s, w0, w1
+** ret
+*/
+svbool_t
+test6 (uint32_t x, uint32_t y)
+{
+ return svand_z (svptrue_b32 (),
+ svwhilegt_b32 (x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test7:
+** whilehi p0\.d, w0, w1
+** ret
+*/
+svbool_t
+test7 (uint32_t x, uint32_t y)
+{
+ return svand_z (svptrue_b8 (),
+ svwhilegt_b64 (x, y),
+ svptrue_b64 ());
+}
+
+/*
+** test8:
+** whilegt p0\.d, x0, x1
+** ret
+*/
+svbool_t
+test8 (int64_t x, int64_t y)
+{
+ return svand_z (svptrue_b16 (),
+ svwhilegt_b64 (x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test9:
+** whilehi p0\.d, x0, x1
+** ret
+*/
+svbool_t
+test9 (uint64_t x, uint64_t y)
+{
+ return svand_z (svptrue_b64 (),
+ svwhilegt_b64 (x, y),
+ svptrue_b64 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilerw_5.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilerw_5.c
new file mode 100644
index 0000000..0c24199
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilerw_5.c
@@ -0,0 +1,130 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** whilerw p0\.h, x0, x1
+** ret
+*/
+svbool_t
+test1 (int16_t *x, int16_t *y)
+{
+ return svand_z (svptrue_b8 (),
+ svwhilerw (x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test2:
+** whilerw p0\.h, x0, x1
+** ret
+*/
+svbool_t
+test2 (uint16_t *x, uint16_t *y)
+{
+ return svand_z (svptrue_b16 (),
+ svwhilerw (x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test3:
+** whilerw p0\.s, x0, x1
+** ret
+*/
+svbool_t
+test3 (int32_t *x, int32_t *y)
+{
+ return svand_z (svptrue_b8 (),
+ svwhilerw (x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test4:
+** whilerw p0\.s, x0, x1
+** ret
+*/
+svbool_t
+test4 (uint32_t *x, uint32_t *y)
+{
+ return svand_z (svptrue_b8 (),
+ svwhilerw (x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test5:
+** whilerw p0\.s, x0, x1
+** ret
+*/
+svbool_t
+test5 (float32_t *x, float32_t *y)
+{
+ return svand_z (svptrue_b16 (),
+ svwhilerw (x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test6:
+** whilerw p0\.s, x0, x1
+** ret
+*/
+svbool_t
+test6 (int32_t *x, int32_t *y)
+{
+ return svand_z (svptrue_b32 (),
+ svwhilerw (x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test7:
+** whilerw p0\.d, x0, x1
+** ret
+*/
+svbool_t
+test7 (int64_t *x, int64_t *y)
+{
+ return svand_z (svptrue_b8 (),
+ svwhilerw (x, y),
+ svptrue_b64 ());
+}
+
+/*
+** test8:
+** whilerw p0\.d, x0, x1
+** ret
+*/
+svbool_t
+test8 (uint64_t *x, uint64_t *y)
+{
+ return svand_z (svptrue_b16 (),
+ svwhilerw (x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test9:
+** whilerw p0\.d, x0, x1
+** ret
+*/
+svbool_t
+test9 (float64_t *x, float64_t *y)
+{
+ return svand_z (svptrue_b64 (),
+ svwhilerw (x, y),
+ svptrue_b64 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilewr_5.c b/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilewr_5.c
new file mode 100644
index 0000000..38db9af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/general/whilewr_5.c
@@ -0,0 +1,130 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** test1:
+** whilewr p0\.h, x0, x1
+** ret
+*/
+svbool_t
+test1 (int16_t *x, int16_t *y)
+{
+ return svand_z (svptrue_b8 (),
+ svwhilewr (x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test2:
+** whilewr p0\.h, x0, x1
+** ret
+*/
+svbool_t
+test2 (uint16_t *x, uint16_t *y)
+{
+ return svand_z (svptrue_b16 (),
+ svwhilewr (x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test3:
+** whilewr p0\.s, x0, x1
+** ret
+*/
+svbool_t
+test3 (int32_t *x, int32_t *y)
+{
+ return svand_z (svptrue_b8 (),
+ svwhilewr (x, y),
+ svptrue_b16 ());
+}
+
+/*
+** test4:
+** whilewr p0\.s, x0, x1
+** ret
+*/
+svbool_t
+test4 (uint32_t *x, uint32_t *y)
+{
+ return svand_z (svptrue_b8 (),
+ svwhilewr (x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test5:
+** whilewr p0\.s, x0, x1
+** ret
+*/
+svbool_t
+test5 (float32_t *x, float32_t *y)
+{
+ return svand_z (svptrue_b16 (),
+ svwhilewr (x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test6:
+** whilewr p0\.s, x0, x1
+** ret
+*/
+svbool_t
+test6 (int32_t *x, int32_t *y)
+{
+ return svand_z (svptrue_b32 (),
+ svwhilewr (x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test7:
+** whilewr p0\.d, x0, x1
+** ret
+*/
+svbool_t
+test7 (int64_t *x, int64_t *y)
+{
+ return svand_z (svptrue_b8 (),
+ svwhilewr (x, y),
+ svptrue_b64 ());
+}
+
+/*
+** test8:
+** whilewr p0\.d, x0, x1
+** ret
+*/
+svbool_t
+test8 (uint64_t *x, uint64_t *y)
+{
+ return svand_z (svptrue_b16 (),
+ svwhilewr (x, y),
+ svptrue_b32 ());
+}
+
+/*
+** test9:
+** whilewr p0\.d, x0, x1
+** ret
+*/
+svbool_t
+test9 (float64_t *x, float64_t *y)
+{
+ return svand_z (svptrue_b64 (),
+ svwhilewr (x, y),
+ svptrue_b64 ());
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr118591-1.c b/gcc/testsuite/gcc.target/avr/torture/pr118591-1.c
index 814f041..6f54c63 100644
--- a/gcc/testsuite/gcc.target/avr/torture/pr118591-1.c
+++ b/gcc/testsuite/gcc.target/avr/torture/pr118591-1.c
@@ -1,5 +1,5 @@
/* { dg-do run { target { ! avr_tiny } } } */
-/* { dg-additional-options "-std=c99 -mlra" } */
+/* { dg-additional-options "-std=c99" } */
__attribute__((noipa))
void func2 (long long a1, long long a2, long b)
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr118591-2.c b/gcc/testsuite/gcc.target/avr/torture/pr118591-2.c
index 83d3606..222af09 100644
--- a/gcc/testsuite/gcc.target/avr/torture/pr118591-2.c
+++ b/gcc/testsuite/gcc.target/avr/torture/pr118591-2.c
@@ -1,6 +1,6 @@
/* Test case failed on avrtiny. */
/* { dg-do run } */
-/* { dg-additional-options "-std=c99 -mlra" } */
+/* { dg-additional-options "-std=c99" } */
__attribute__((noipa))
void func2 (long a, long b)
diff --git a/gcc/testsuite/gcc.target/i386/pr120941-1.c b/gcc/testsuite/gcc.target/i386/pr120941-1.c
new file mode 100644
index 0000000..b4fc6ac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr120941-1.c
@@ -0,0 +1,49 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -march=x86-64-v3" } */
+/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */
+/* { dg-final { check-function-bodies "**" "" "" { target lp64 } {^\t?\.} } } */
+
+/*
+**bar:
+**.LFB[0-9]+:
+**...
+** vbroadcastsd .LC4\(%rip\), %ymm2
+** leal 2\(%rbx\), %eax
+** vbroadcastsd .LC2\(%rip\), %ymm4
+** negl %eax
+**...
+*/
+
+extern void foo (int);
+
+enum { N_CELL_ENTRIES1 = 2 }
+typedef LBM_Grid1[64];
+enum { N_CELL_ENTRIES2 = 2 }
+typedef LBM_Grid2[64];
+LBM_Grid1 grid1;
+LBM_Grid2 grid2;
+extern int n;
+
+void
+LBM_handleInOutFlow()
+{
+ int i, j;
+ for (; i; i += 2)
+ {
+ for (j = 0; j < n; j++)
+ {
+ grid1[i] = 1.0 / 36.0 * i;
+ grid2[i] = 1.0 / 36.0 * i;
+ }
+ }
+}
+
+int main_t;
+void
+bar (void)
+{
+ for (; main_t; main_t++) {
+ LBM_handleInOutFlow();
+ foo (main_t);
+ }
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr121303.c b/gcc/testsuite/gcc.target/i386/pr121303.c
new file mode 100644
index 0000000..7900bce
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr121303.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -favoid-store-forwarding" } */
+
+typedef struct {
+ bool is_ssa;
+} nir_src;
+
+nir_src nir_src_init;
+
+typedef struct {
+ nir_src src;
+ char swizzle[6];
+} nir_alu_src;
+
+void nir_src_bit_size(nir_src);
+
+void nir_lower_fb_read_instr() {
+ {
+ nir_alu_src alu_src = {nir_src_init}, src = alu_src;
+ nir_src_bit_size(src.src);
+ }
+ {
+ nir_alu_src alu_src = {nir_src_init}, src = alu_src;
+ nir_src_bit_size(src.src);
+ }
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr121410.c b/gcc/testsuite/gcc.target/i386/pr121410.c
new file mode 100644
index 0000000..04bab91
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr121410.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=x86-64 -mavx512f -mstore-max=128" } */
+
+extern unsigned _BitInt(3719) a;
+extern _BitInt(465) g;
+void
+foo(void)
+{
+ _BitInt(465) b = a >> 1860;
+ g = b + b;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u32-from-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u32-from-u64.c
index 8d5449b..fa3758a 100644
--- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u32-from-u64.c
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u32-from-u64.c
@@ -9,3 +9,5 @@
DEF_SAT_U_MUL_FMT_1_WRAP(NT, WT)
/* { dg-final { scan-tree-dump-times ".SAT_MUL" 1 "optimized" } } */
+/* { dg-final { scan-assembler-not "\.L\[0-9\]+" } } */
+/* { dg-final { scan-assembler-times "mulhu" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u64-from-u128.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u64-from-u128.c
index d8a01d1..b1bf4fa 100644
--- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u64-from-u128.c
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u64-from-u128.c
@@ -10,3 +10,4 @@ DEF_SAT_U_MUL_FMT_1_WRAP(NT, WT)
/* { dg-final { scan-tree-dump-times ".SAT_MUL" 1 "optimized" } } */
/* { dg-final { scan-assembler-not "\.L\[0-9\]+" } } */
+/* { dg-final { scan-assembler-times "mulhu" 1 } } */
diff --git a/gcc/testsuite/gfortran.dg/pointer_assign_16.f90 b/gcc/testsuite/gfortran.dg/pointer_assign_16.f90
new file mode 100644
index 0000000..9282283
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pointer_assign_16.f90
@@ -0,0 +1,25 @@
+! { dg-do run }
+!
+! Check the span of the descriptor of an array pointer after it has been
+! assigned to from a polymorphic function result.
+
+program test
+ implicit none
+ type t
+ integer :: c
+ end type t
+ type, extends(t) :: u
+ integer :: d
+ end type u
+ type(t), pointer :: p(:)
+ class(t), allocatable, target :: a(:)
+ p => f()
+ ! print *, p%c
+ if (any(p%c /= [2,5,11,17,23])) error stop 1
+contains
+ function f()
+ class(t), pointer :: f(:)
+ a = [ u(2,3), u(5,7), u(11,13), u(17,19), u(23,29) ]
+ f => a
+ end function
+end program
diff --git a/gcc/testsuite/gfortran.dg/pr121234.f90 b/gcc/testsuite/gfortran.dg/pr121234.f90
new file mode 100644
index 0000000..8eb1af53
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr121234.f90
@@ -0,0 +1,28 @@
+! { dg-do run }
+! PR121234 Bogus diagnostic on READ of string with semicolon.
+ character(12) buffer,a
+ a = 'xxxxxxxxxx'
+ buffer="33;44"
+ read(buffer,*) a
+ if (a .ne. "33;44") stop 1
+ a = 'xxxxxxxxxx'
+ buffer=" ;;33 ,44 "
+ read(buffer,*,decimal="comma") a
+ if (a .ne. 'xxxxxxxxxx') stop 2 ! A null read
+ a = 'xxxxxxxxxx'
+ buffer=" ;;33 ,44 "
+ read(buffer,*,decimal="point") a
+ if (a .ne. ';;33') stop 3 ! Spaces are delimiting
+ a = 'xxxxxxxxxx'
+ buffer=";;33;,44 "
+ read(buffer,*) a
+ if (a .ne. ';;33;') stop 4 ! Comma is delimiting
+ a = 'xxxxxxxxxx'
+ buffer=";;33;44;; "
+ read(buffer,*) a
+ if (a .ne. ';;33;44;;') stop 5 ! Space is delimiting
+ a = 'xxxxxxxxxx'
+ buffer=";;33;44;;;.7"
+ read(buffer,*) a
+ if (a .ne. ';;33;44;;;.7') stop 6 ! Space is delimiting
+end
diff --git a/gcc/testsuite/lib/rust.exp b/gcc/testsuite/lib/rust.exp
index 9513e1c..692030c 100644
--- a/gcc/testsuite/lib/rust.exp
+++ b/gcc/testsuite/lib/rust.exp
@@ -168,10 +168,7 @@ proc rust_target_compile { source dest type options } {
global gluefile wrap_flags
global ALWAYS_RUSTFLAGS
global RUST_UNDER_TEST
- global individual_timeout
-
- # HACK: guard against infinite loops in the compiler
- set individual_timeout 10
+
if { [target_info needs_status_wrapper] != "" && [info exists gluefile] } {
lappend options "libs=${gluefile}"
diff --git a/gcc/testsuite/libgdiagnostics.dg/test-multiple-lines.c b/gcc/testsuite/libgdiagnostics.dg/test-multiple-lines.c
index e761110..39af810 100644
--- a/gcc/testsuite/libgdiagnostics.dg/test-multiple-lines.c
+++ b/gcc/testsuite/libgdiagnostics.dg/test-multiple-lines.c
@@ -66,6 +66,7 @@ main ()
| ~~~~~
23 | "bar"
| ~~~~~^
+ | ,
24 | "baz"};
| ~~~~~
{ dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/rust/compile/additional-trait-bounds2nr2.rs b/gcc/testsuite/rust/compile/additional-trait-bounds2nr2.rs
index 6764f6e..1c49b75 100644
--- a/gcc/testsuite/rust/compile/additional-trait-bounds2nr2.rs
+++ b/gcc/testsuite/rust/compile/additional-trait-bounds2nr2.rs
@@ -1,5 +1,3 @@
-// { dg-additional-options "-frust-name-resolution-2.0" }
-
#![feature(optin_builtin_traits)]
pub unsafe auto trait Send {}
diff --git a/gcc/testsuite/rust/compile/all-cast.rs b/gcc/testsuite/rust/compile/all-cast.rs
index fa24373..6d8576c 100644
--- a/gcc/testsuite/rust/compile/all-cast.rs
+++ b/gcc/testsuite/rust/compile/all-cast.rs
@@ -4,7 +4,7 @@ fn main() {
0u32 as char; // { dg-error "cannot cast .u32. as .char., only .u8. can be cast as .char." }
- let x = &[1_usize, 2] as [usize]; // { dg-error "cast to unsized type: .& .usize:CAPACITY.. as ..usize.." }
+ let x = &[1_usize, 2] as [usize]; // { dg-error "cast to unsized type: .& .usize; 2.. as ..usize.." }
let a = &0u8; // Here, `x` is a `&u8`.
let y: u32 = a as u32; // { dg-error "casting .& u8. as .u32. is invalid" }
diff --git a/gcc/testsuite/rust/compile/arrays2.rs b/gcc/testsuite/rust/compile/arrays2.rs
index 668bcf0..1090059 100644
--- a/gcc/testsuite/rust/compile/arrays2.rs
+++ b/gcc/testsuite/rust/compile/arrays2.rs
@@ -1,5 +1,4 @@
-// { dg-additional-options "-w" }
fn main() {
let array: [i32; 5] = [1, 2, 3];
- // { dg-error "mismatched types, expected an array with a fixed size of 5 elements, found one with 3 elements" "" { target *-*-* } .-1 }
+ // { dg-error "mismatched types, expected ..i32; 5.. but got ...integer.; 3.. .E0308." "" { target *-*-* } .-1 }
}
diff --git a/gcc/testsuite/rust/compile/auto_traits2.rs b/gcc/testsuite/rust/compile/auto_traits2.rs
index 382d446..7004761 100644
--- a/gcc/testsuite/rust/compile/auto_traits2.rs
+++ b/gcc/testsuite/rust/compile/auto_traits2.rs
@@ -15,7 +15,7 @@ fn foo(a: &(dyn A + Send + Sync)) {
struct S;
impl A for S {
- fn a_method(&self) {} // { dg-warning "unused name" }
+ fn a_method(&self) {}
}
fn main() {
diff --git a/gcc/testsuite/rust/compile/bad-rpit1.rs b/gcc/testsuite/rust/compile/bad-rpit1.rs
new file mode 100644
index 0000000..d8c21b1
--- /dev/null
+++ b/gcc/testsuite/rust/compile/bad-rpit1.rs
@@ -0,0 +1,26 @@
+#[lang = "sized"]
+trait Sized {}
+
+trait Foo {
+ fn id(&self) -> i32;
+}
+
+struct A;
+struct B;
+
+impl Foo for A {
+ fn id(&self) -> i32 {
+ 1
+ }
+}
+
+impl Foo for B {
+ fn id(&self) -> i32 {
+ 2
+ }
+}
+
+fn make_foo(cond: bool) -> impl Foo {
+ if cond { A } else { B }
+ // { dg-error "mismatched types, expected .A. but got .B. .E0308." "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/bug-with-default-generic.rs b/gcc/testsuite/rust/compile/bug-with-default-generic.rs
new file mode 100644
index 0000000..25f46a0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/bug-with-default-generic.rs
@@ -0,0 +1,15 @@
+#[lang = "sized"]
+pub trait Sized {}
+
+pub trait MyBinaryTrait<Rhs = Self> {
+ fn do_something(&self, rhs: &Rhs);
+}
+
+struct Foo<T> {
+ // { dg-warning "struct is never constructed" "" { target *-*-* } .-1 }
+ value: T,
+}
+
+impl<T> MyBinaryTrait for Foo<T> {
+ fn do_something(&self, _rhs: &Self) {}
+}
diff --git a/gcc/testsuite/rust/compile/const3.rs b/gcc/testsuite/rust/compile/const3.rs
index 22dc3d3..c1d0f29 100644
--- a/gcc/testsuite/rust/compile/const3.rs
+++ b/gcc/testsuite/rust/compile/const3.rs
@@ -3,5 +3,5 @@ fn size() -> usize {
}
fn main() {
- let a = [15; size()]; // { dg-error "only functions marked as .const. are allowed to be called from constant contexts" }
+ let a = [15; size()]; // { dg-error "calls in constants are limited to constant functions, tuple structs and tuple variants" }
}
diff --git a/gcc/testsuite/rust/compile/const_generics_10.rs b/gcc/testsuite/rust/compile/const_generics_10.rs
new file mode 100644
index 0000000..7e3bc86
--- /dev/null
+++ b/gcc/testsuite/rust/compile/const_generics_10.rs
@@ -0,0 +1,32 @@
+#[lang = "sized"]
+trait Sized {}
+
+const M: usize = 4;
+
+struct Foo<T, const N: usize = 1> {
+ value: [T; N],
+}
+
+fn main() {
+ let foo = Foo::<i32> { value: [15] };
+ let foo = Foo::<i32, 2> { value: [15, 13] };
+ let foo: Foo<i32, 2> = Foo { value: [15, 13] };
+ let foo: Foo<i32, 2> = Foo::<i32, 2> { value: [15, 13] };
+ let foo: Foo<i32, { 1 + 1 }> = Foo { value: [15, 13] };
+ let foo = Foo::<i32, { 1 + 1 }> { value: [15, 13] };
+ let foo: Foo<i32, { 1 + 1 }> = Foo::<i32, { 1 + 1 }> { value: [15, 13] };
+ let foo: Foo<i32, M> = Foo::<i32, 4> {
+ value: [15, 13, 11, 9],
+ };
+
+ let invalid_foo: Foo<i32, { 1 + 1 }> = Foo::<i32, 3> { value: [15, 13] };
+ // { dg-error {mismatched types, expected ..T=i32; 3.. but got ...integer.; 2.. .E0308.} "" { target *-*-* } .-1 }
+ // { dg-error {mismatched types, expected ..T=i32; 2.. but got ..T=i32; 3.. .E0308.} "" { target *-*-* } .-2 }
+
+ let invalid_foo: Foo<i32, { 1 + 1 }> = Foo::<i32, M> { value: [15, 13] };
+ // { dg-error {mismatched types, expected ..T=i32; 4.. but got ...integer.; 2.. .E0308.} "" { target *-*-* } .-1 }
+ // { dg-error {mismatched types, expected ..T=i32; 2.. but got ..T=i32; 4.. .E0308.} "" { target *-*-* } .-2 }
+
+ let invalid_foo: Foo<i32> = Foo::<i32, 2> { value: [15, 13] };
+ // { dg-error {mismatched types, expected ..T=i32; 1.. but got ..T=i32; 2.. .E0308.} "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/const_generics_11.rs b/gcc/testsuite/rust/compile/const_generics_11.rs
new file mode 100644
index 0000000..de902ee
--- /dev/null
+++ b/gcc/testsuite/rust/compile/const_generics_11.rs
@@ -0,0 +1,14 @@
+// { dg-options "-w" }
+
+#[lang = "sized"]
+trait Sized {}
+
+struct Matrix<T, const ROWS: usize, const COLS: usize> {
+ data: [[T; COLS]; ROWS],
+}
+
+fn main() {
+ let _: Matrix<u8, 2, 3> = Matrix {
+ data: [[1, 2, 3], [4, 5, 6]],
+ };
+}
diff --git a/gcc/testsuite/rust/compile/const_generics_12.rs b/gcc/testsuite/rust/compile/const_generics_12.rs
new file mode 100644
index 0000000..a17c525
--- /dev/null
+++ b/gcc/testsuite/rust/compile/const_generics_12.rs
@@ -0,0 +1,14 @@
+// { dg-options "-w" }
+
+#[lang = "sized"]
+trait Sized {}
+
+const BASE: usize = 2;
+
+struct Foo<T, const N: usize> {
+ data: [T; N],
+}
+
+fn main() {
+ let _ = Foo::<u8, { BASE + 1 * 2 }> { data: [0; 4] };
+}
diff --git a/gcc/testsuite/rust/compile/const_generics_13.rs b/gcc/testsuite/rust/compile/const_generics_13.rs
new file mode 100644
index 0000000..20dd0b90
--- /dev/null
+++ b/gcc/testsuite/rust/compile/const_generics_13.rs
@@ -0,0 +1,11 @@
+#[lang = "sized"]
+trait Sized {}
+
+struct Foo<T, const N: usize> {
+ value: [T; N],
+}
+
+fn main() {
+ let foo: Foo<_, _>;
+ // { dg-error {type provided when a constant was expected .E0747.} "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/const_generics_14.rs b/gcc/testsuite/rust/compile/const_generics_14.rs
new file mode 100644
index 0000000..4d52efb
--- /dev/null
+++ b/gcc/testsuite/rust/compile/const_generics_14.rs
@@ -0,0 +1,13 @@
+#[lang = "sized"]
+trait Sized {}
+
+type MyLen = usize;
+struct Foo<T, const N: usize> {
+ data: [T; N],
+}
+
+fn main() {
+ let _ = Foo::<u8, MyLen> { data: [1, 2, 3] };
+ // { dg-error {type provided when a constant was expected .E0747.} "" { target *-*-* } .-1 }
+ // { dg-error {expected an ADT type for constructor} "" { target *-*-* } .-2 }
+}
diff --git a/gcc/testsuite/rust/compile/const_generics_15.rs b/gcc/testsuite/rust/compile/const_generics_15.rs
new file mode 100644
index 0000000..a160abf
--- /dev/null
+++ b/gcc/testsuite/rust/compile/const_generics_15.rs
@@ -0,0 +1,16 @@
+#[lang = "sized"]
+trait Sized {}
+
+enum Foo<const N: usize> {
+ A([u8; N]),
+}
+
+union Bar<const N: usize> {
+ a: [i32; N],
+ b: [u8; N],
+}
+
+fn main() {
+ let _ = Foo::<4>::A([1, 2, 3, 4]);
+ let _ = Bar::<4> { a: [0; 4] };
+}
diff --git a/gcc/testsuite/rust/compile/const_generics_16.rs b/gcc/testsuite/rust/compile/const_generics_16.rs
new file mode 100644
index 0000000..060dbda
--- /dev/null
+++ b/gcc/testsuite/rust/compile/const_generics_16.rs
@@ -0,0 +1,10 @@
+#[lang = "sized"]
+trait Sized {}
+
+struct Foo<T = u8, const N: usize = 4> {
+ data: [T; N], // { dg-warning "field is never read: .data." }
+}
+
+fn main() {
+ let _x = Foo { data: [1, 2, 3, 4] };
+}
diff --git a/gcc/testsuite/rust/compile/const_generics_3.rs b/gcc/testsuite/rust/compile/const_generics_3.rs
index 524d48d..3415f17 100644
--- a/gcc/testsuite/rust/compile/const_generics_3.rs
+++ b/gcc/testsuite/rust/compile/const_generics_3.rs
@@ -1,28 +1,21 @@
-// { dg-additional-options "-w -frust-name-resolution-2.0" }
-
#[lang = "sized"]
trait Sized {}
const M: usize = 4;
struct Foo<T, const N: usize = 1> {
- value: [T; N],
+ value: [T; N], // { dg-warning "field is never read: .value." }
}
fn main() {
- let foo = Foo::<i32> { value: [15] };
- let foo = Foo::<i32, 2> { value: [15, 13] };
- let foo: Foo<i32, 2> = Foo { value: [15, 13] };
- let foo: Foo<i32, 2> = Foo::<i32, 2> { value: [15, 13] };
- let foo: Foo<i32, { 1 + 1 }> = Foo { value: [15, 13] };
- let foo = Foo::<i32, { 1 + 1 }> { value: [15, 13] };
- let foo: Foo<i32, { 1 + 1 }> = Foo::<i32, { 1 + 1 }> { value: [15, 13] };
- let foo: Foo<i32, M> = Foo::<i32, 4> {
+ let _foo = Foo::<i32> { value: [15] };
+ let _foo = Foo::<i32, 2> { value: [15, 13] };
+ let _foo: Foo<i32, 2> = Foo { value: [15, 13] };
+ let _foo: Foo<i32, 2> = Foo::<i32, 2> { value: [15, 13] };
+ let _foo: Foo<i32, { 1 + 1 }> = Foo { value: [15, 13] };
+ let _foo = Foo::<i32, { 1 + 1 }> { value: [15, 13] };
+ let _foo: Foo<i32, { 1 + 1 }> = Foo::<i32, { 1 + 1 }> { value: [15, 13] };
+ let _foo: Foo<i32, M> = Foo::<i32, 4> {
value: [15, 13, 11, 9],
};
-
- // FIXME: Add proper const typecheck errors here
- let invalid_foo: Foo<i32, { 1 + 1 }> = Foo::<i32, 3> { value: [15, 13] };
- let invalid_foo: Foo<i32, { 1 + 1 }> = Foo::<i32, M> { value: [15, 13] };
- let invalid_foo: Foo<i32> = Foo::<i32, 2> { value: [15, 13] };
}
diff --git a/gcc/testsuite/rust/compile/const_generics_5.rs b/gcc/testsuite/rust/compile/const_generics_5.rs
index 685229e..4d05569 100644
--- a/gcc/testsuite/rust/compile/const_generics_5.rs
+++ b/gcc/testsuite/rust/compile/const_generics_5.rs
@@ -1,4 +1,3 @@
-// { dg-options "-w" }
struct Foo<const N: usize = { 14 }>;
const M: usize = 15;
@@ -8,5 +7,6 @@ fn main() {
let _: Foo<15> = Foo;
let _: Foo<{ M }> = Foo;
let _: Foo<M> = Foo;
- // let _: Foo<N> = Foo; this causes an ICE we need to do const generics
+ let _: Foo<N> = Foo;
+ // { dg-error {type provided when a constant was expected .E0747.} "" { target *-*-* } .-1 }
}
diff --git a/gcc/testsuite/rust/compile/const_generics_8.rs b/gcc/testsuite/rust/compile/const_generics_8.rs
index bb34652..ce5e1b5 100644
--- a/gcc/testsuite/rust/compile/const_generics_8.rs
+++ b/gcc/testsuite/rust/compile/const_generics_8.rs
@@ -9,12 +9,13 @@ type Bipboupe<const N: i32 = 15> = Bidule;
trait Fooable<const N: i32 = 15> {}
union Bidoulepe<const N: i32 = 15> {
- // { dg-error "default values for const generic parameters are not allowed in .union. items" "" {target *-*-* } .-1 }
int: i32,
float: f32,
}
-fn const_default<const N: i32 = 15>() {} // { dg-error "default values for const generic parameters are not allowed in .function. items" }
+fn const_default<const N: i32 = 15>() {} // { dg-error "default values for const generic parameters are not allowed here" }
// Note - missing generic parameter - needs name resolution on const generics
-impl<const N: i32 = 15> Bidule {} // { dg-error "default values for const generic parameters are not allowed in .impl. items" }
+impl<const N: i32 = 15> Bidule {}
+// { dg-error "default values for const generic parameters are not allowed here" "" {target *-*-* } .-1 }
+// { dg-error "unconstrained type parameter" "" {target *-*-* } .-2 }
diff --git a/gcc/testsuite/rust/compile/const_generics_9.rs b/gcc/testsuite/rust/compile/const_generics_9.rs
new file mode 100644
index 0000000..98e2d3f
--- /dev/null
+++ b/gcc/testsuite/rust/compile/const_generics_9.rs
@@ -0,0 +1,13 @@
+// { dg-options "-w" }
+
+#[lang = "sized"]
+trait Sized {}
+
+struct ArrayWrapper<T, const N: usize> {
+ data: [T; N],
+}
+
+pub fn test() -> [u8; 4] {
+ let a = ArrayWrapper { data: [1u8; 4] };
+ a.data
+}
diff --git a/gcc/testsuite/rust/compile/deferred_const_inference.rs b/gcc/testsuite/rust/compile/deferred_const_inference.rs
new file mode 100644
index 0000000..25a3b17
--- /dev/null
+++ b/gcc/testsuite/rust/compile/deferred_const_inference.rs
@@ -0,0 +1,7 @@
+// { dg-additional-options "-frust-compile-until=typecheck" }
+
+// #![feature(generic_arg_infer)]
+
+fn main() {
+ let a: [u32; _] = [15u32];
+}
diff --git a/gcc/testsuite/rust/compile/derive-debug1.rs b/gcc/testsuite/rust/compile/derive-debug1.rs
index cf2187d..5927374 100644
--- a/gcc/testsuite/rust/compile/derive-debug1.rs
+++ b/gcc/testsuite/rust/compile/derive-debug1.rs
@@ -23,15 +23,15 @@ mod core {
}
}
-#[derive(Debug)] // { dg-warning "unused name" }
+#[derive(Debug)]
// { dg-warning "stub implementation" "" { target *-*-* } .-1 }
struct Foo { a: i32, b: i64 } // { dg-warning "is never constructed" }
-#[derive(Debug)] // { dg-warning "unused name" }
+#[derive(Debug)]
// { dg-warning "stub implementation" "" { target *-*-* } .-1 }
struct Bar(i32, i32); // { dg-warning "is never constructed" }
-#[derive(Debug)] // { dg-warning "unused name" }
+#[derive(Debug)]
// { dg-warning "stub implementation" "" { target *-*-* } .-1 }
enum Baz {
A,
diff --git a/gcc/testsuite/rust/compile/derive_macro1.rs b/gcc/testsuite/rust/compile/derive_macro1.rs
index bc10d60..8c42aba 100644
--- a/gcc/testsuite/rust/compile/derive_macro1.rs
+++ b/gcc/testsuite/rust/compile/derive_macro1.rs
@@ -7,7 +7,7 @@ pub trait Clone {
}
// This warning can be removed once we properly handle implems with #[automatically_derived]
-#[derive(Clone)] // { dg-warning "unused name .self." }
+#[derive(Clone)]
pub struct S;
fn main() {
diff --git a/gcc/testsuite/rust/compile/derive_partial_ord1.rs b/gcc/testsuite/rust/compile/derive_partial_ord1.rs
new file mode 100644
index 0000000..eeca62d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/derive_partial_ord1.rs
@@ -0,0 +1,464 @@
+// { dg-additional-options "-w" }
+
+#![feature(intrinsics)]
+
+mod core {
+ mod option {
+ // #[rustc_diagnostic_item = "option_type"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub enum Option<T> {
+ /// No value
+ #[lang = "None"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ None,
+ /// Some value `T`
+ #[lang = "Some"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Some(#[stable(feature = "rust1", since = "1.0.0")] T),
+ }
+ }
+
+ mod marker {
+ #[lang = "phantom_data"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub struct PhantomData<T: ?Sized>;
+
+ #[unstable(feature = "structural_match", issue = "31434")]
+ // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(PartialEq)]`")]
+ #[lang = "structural_peq"]
+ pub trait StructuralPartialEq {
+ // Empty.
+ }
+
+ #[unstable(feature = "structural_match", issue = "31434")]
+ // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(Eq)]`")]
+ #[lang = "structural_teq"]
+ pub trait StructuralEq {
+ // Empty.
+ }
+
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[lang = "sized"]
+ // #[rustc_on_unimplemented(
+ // message = "the size for values of type `{Self}` cannot be known at compilation time",
+ // label = "doesn't have a size known at compile-time"
+ // )]
+ // #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
+ // #[rustc_specialization_trait]
+ pub trait Sized {
+ // Empty.
+ }
+ }
+
+ mod cmp {
+ use super::marker::Sized;
+ use super::option::Option;
+
+ // #[derive(Clone, Copy, PartialEq, Debug, Hash)]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub enum Ordering {
+ /// An ordering where a compared value is less than another.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Less = -1,
+ /// An ordering where a compared value is equal to another.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Equal = 0,
+ /// An ordering where a compared value is greater than another.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Greater = 1,
+ }
+
+ #[lang = "eq"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[doc(alias = "==")]
+ #[doc(alias = "!=")]
+ // #[rustc_on_unimplemented(
+ // message = "can't compare `{Self}` with `{Rhs}`",
+ // label = "no implementation for `{Self} == {Rhs}`"
+ // )]
+ pub trait PartialEq<Rhs: ?Sized = Self> {
+ /// This method tests for `self` and `other` values to be equal, and is used
+ /// by `==`.
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn eq(&self, other: &Rhs) -> bool;
+
+ fn ne(&self, other: &Rhs) -> bool {
+ !self.eq(other)
+ }
+ }
+
+ #[doc(alias = "==")]
+ #[doc(alias = "!=")]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub trait Eq: PartialEq<Self> {
+ // this method is used solely by #[deriving] to assert
+ // that every component of a type implements #[deriving]
+ // itself, the current deriving infrastructure means doing this
+ // assertion without using a method on this trait is nearly
+ // impossible.
+ //
+ // This should never be implemented by hand.
+ #[doc(hidden)]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn assert_receiver_is_total_eq(&self) {}
+ }
+
+ #[lang = "partial_ord"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[doc(alias = ">")]
+ #[doc(alias = "<")]
+ #[doc(alias = "<=")]
+ #[doc(alias = ">=")]
+ // #[rustc_on_unimplemented(
+ // message = "can't compare `{Self}` with `{Rhs}`",
+ // label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`"
+ // )]
+ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
+ /// This method returns an ordering between `self` and `other` values if one exists.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::cmp::Ordering;
+ ///
+ /// let result = 1.0.partial_cmp(&2.0);
+ /// assert_eq!(result, Some(Ordering::Less));
+ ///
+ /// let result = 1.0.partial_cmp(&1.0);
+ /// assert_eq!(result, Some(Ordering::Equal));
+ ///
+ /// let result = 2.0.partial_cmp(&1.0);
+ /// assert_eq!(result, Some(Ordering::Greater));
+ /// ```
+ ///
+ /// When comparison is impossible:
+ ///
+ /// ```
+ /// let result = f64::NAN.partial_cmp(&1.0);
+ /// assert_eq!(result, None);
+ /// ```
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+
+ /// This method tests less than (for `self` and `other`) and is used by the `<` operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 < 2.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 < 1.0;
+ /// assert_eq!(result, false);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn lt(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Less) => true,
+ _ => false,
+ }
+ }
+
+ /// This method tests less than or equal to (for `self` and `other`) and is used by the `<=`
+ /// operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 <= 2.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 <= 2.0;
+ /// assert_eq!(result, true);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn le(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Less | Ordering::Equal) => true,
+ _ => false,
+ }
+ }
+
+ /// This method tests greater than (for `self` and `other`) and is used by the `>` operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 > 2.0;
+ /// assert_eq!(result, false);
+ ///
+ /// let result = 2.0 > 2.0;
+ /// assert_eq!(result, false);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn gt(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Greater) => true,
+ _ => false,
+ }
+ }
+
+ /// This method tests greater than or equal to (for `self` and `other`) and is used by the `>=`
+ /// operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 2.0 >= 1.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 >= 2.0;
+ /// assert_eq!(result, true);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn ge(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Greater | Ordering::Equal) => true,
+ _ => false,
+ }
+ }
+ }
+
+ #[doc(alias = "<")]
+ #[doc(alias = ">")]
+ #[doc(alias = "<=")]
+ #[doc(alias = ">=")]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub trait Ord: Eq + PartialOrd<Self> {
+ /// This method returns an [`Ordering`] between `self` and `other`.
+ ///
+ /// By convention, `self.cmp(&other)` returns the ordering matching the expression
+ /// `self <operator> other` if true.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::cmp::Ordering;
+ ///
+ /// assert_eq!(5.cmp(&10), Ordering::Less);
+ /// assert_eq!(10.cmp(&5), Ordering::Greater);
+ /// assert_eq!(5.cmp(&5), Ordering::Equal);
+ /// ```
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn cmp(&self, other: &Self) -> Ordering;
+
+ /// Compares and returns the maximum of two values.
+ ///
+ /// Returns the second argument if the comparison determines them to be equal.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// assert_eq!(2, 1.max(2));
+ /// assert_eq!(2, 2.max(2));
+ /// ```
+ #[stable(feature = "ord_max_min", since = "1.21.0")]
+ #[must_use]
+ fn max(self, other: Self) -> Self
+ where
+ Self: Sized,
+ {
+ self
+ }
+
+ /// Compares and returns the minimum of two values.
+ ///
+ /// Returns the first argument if the comparison determines them to be equal.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// assert_eq!(1, 1.min(2));
+ /// assert_eq!(2, 2.min(2));
+ /// ```
+ #[stable(feature = "ord_max_min", since = "1.21.0")]
+ #[must_use]
+ fn min(self, other: Self) -> Self
+ where
+ Self: Sized,
+ {
+ self
+ }
+
+ /// Restrict a value to a certain interval.
+ ///
+ /// Returns `max` if `self` is greater than `max`, and `min` if `self` is
+ /// less than `min`. Otherwise this returns `self`.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `min > max`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(clamp)]
+ ///
+ /// assert!((-3).clamp(-2, 1) == -2);
+ /// assert!(0.clamp(-2, 1) == 0);
+ /// assert!(2.clamp(-2, 1) == 1);
+ /// ```
+ #[must_use]
+ #[unstable(feature = "clamp", issue = "44095")]
+ fn clamp(self, min: Self, max: Self) -> Self
+ where
+ Self: Sized,
+ {
+ if self < min {
+ min
+ } else if self > max {
+ max
+ } else {
+ self
+ }
+ }
+ }
+ }
+
+ pub mod intrinsics {
+ #[lang = "discriminant_kind"]
+ pub trait DiscriminantKind {
+ #[lang = "discriminant_type"]
+ type Discriminant;
+ }
+
+ extern "rust-intrinsic" {
+ pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
+ }
+ }
+}
+
+use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
+use core::marker::Sized;
+use core::option::Option;
+
+// for comparing discriminant_value
+impl PartialEq for isize {
+ fn eq(&self, other: &Self) -> bool {
+ *self == *other
+ }
+}
+
+// for comparing discriminant_value
+impl PartialOrd for isize {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ if *self > *other {
+ Option::Some(Ordering::Greater)
+ } else if *self < *other {
+ Option::Some(Ordering::Less)
+ } else {
+ Option::Some(Ordering::Equal)
+ }
+ }
+
+ fn lt(&self, other: &Self) -> bool {
+ *self < *other
+ }
+ fn le(&self, other: &Self) -> bool {
+ *self <= *other
+ }
+ fn ge(&self, other: &Self) -> bool {
+ *self >= *other
+ }
+ fn gt(&self, other: &Self) -> bool {
+ *self > *other
+ }
+}
+
+impl PartialEq for i32 {
+ fn eq(&self, other: &Self) -> bool {
+ *self == *other
+ }
+}
+
+impl PartialOrd for i32 {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ if *self > *other {
+ Option::Some(Ordering::Greater)
+ } else if *self < *other {
+ Option::Some(Ordering::Less)
+ } else {
+ Option::Some(Ordering::Equal)
+ }
+ }
+
+ fn lt(&self, other: &Self) -> bool {
+ *self < *other
+ }
+ fn le(&self, other: &Self) -> bool {
+ *self <= *other
+ }
+ fn ge(&self, other: &Self) -> bool {
+ *self >= *other
+ }
+ fn gt(&self, other: &Self) -> bool {
+ *self > *other
+ }
+}
+
+impl Ord for i32 {
+ fn cmp(&self, other: &Self) -> Ordering {
+ if *self > *other {
+ Ordering::Greater
+ } else if *self < *other {
+ Ordering::Less
+ } else {
+ Ordering::Equal
+ }
+ }
+}
+
+impl Eq for i32 {}
+
+#[derive(PartialEq, PartialOrd)]
+enum Foo {
+ A,
+ B(i32, i32, i32),
+ C { inner: i32, outer: i32 },
+}
+
+#[derive(Ord, PartialOrd, PartialEq, Eq)]
+struct Bar {
+ a: i32,
+}
+
+#[derive(Ord, PartialOrd, PartialEq, Eq)]
+struct BarFull {
+ a: i32,
+ b: i32,
+ c: i32,
+ d: i32,
+}
+
+extern "C" {
+ fn puts(s: *const i8);
+}
+
+fn print(s: &str) {
+ unsafe {
+ puts(s as *const str as *const i8);
+ }
+}
+
+fn main() {
+ let a = Foo::A;
+ let b = Foo::B(15, 14, 13);
+
+ match a.partial_cmp(&b) {
+ Option::Some(Ordering::Less) => print("less"),
+ Option::Some(Ordering::Greater) => print("greater"),
+ Option::Some(Ordering::Equal) => print("equal"),
+ _ => print("uuuuh woops lol"),
+ }
+}
diff --git a/gcc/testsuite/rust/compile/enum_variant_name.rs b/gcc/testsuite/rust/compile/enum_variant_name.rs
index 671fced..965acd1 100644
--- a/gcc/testsuite/rust/compile/enum_variant_name.rs
+++ b/gcc/testsuite/rust/compile/enum_variant_name.rs
@@ -1,4 +1,4 @@
-// { dg-additional-options "-w -frust-name-resolution-2.0" }
+// { dg-additional-options "-w" }
struct E1;
enum Test {
diff --git a/gcc/testsuite/rust/compile/format_args_basic_expansion.rs b/gcc/testsuite/rust/compile/format_args_basic_expansion.rs
index 40bcd3c..cedb62c 100644
--- a/gcc/testsuite/rust/compile/format_args_basic_expansion.rs
+++ b/gcc/testsuite/rust/compile/format_args_basic_expansion.rs
@@ -35,7 +35,6 @@ pub mod core {
impl Display for i32 {
fn fmt(&self, _: &mut Formatter) -> Result {
- // { dg-warning "unused name .self." "" { target *-*-* } .-1 }
Result
}
}
diff --git a/gcc/testsuite/rust/compile/format_args_extra_comma.rs b/gcc/testsuite/rust/compile/format_args_extra_comma.rs
index fcc435c..dc48a3a 100644
--- a/gcc/testsuite/rust/compile/format_args_extra_comma.rs
+++ b/gcc/testsuite/rust/compile/format_args_extra_comma.rs
@@ -35,7 +35,6 @@ pub mod core {
impl Display for i32 {
fn fmt(&self, _: &mut Formatter) -> Result {
- // { dg-warning "unused name .self." "" { target *-*-* } .-1 }
Result
}
}
diff --git a/gcc/testsuite/rust/compile/generics8.rs b/gcc/testsuite/rust/compile/generics8.rs
index 88c4bac..2d30a9e 100644
--- a/gcc/testsuite/rust/compile/generics8.rs
+++ b/gcc/testsuite/rust/compile/generics8.rs
@@ -4,7 +4,7 @@ pub trait Sized {}
struct Foo<A, B>(A, B);
impl<T> Foo<i32, T> {
- fn test(a: T) -> T {
+ fn test(a: T) -> T { // { dg-error "duplicate definitions with name .test." }
a
}
}
diff --git a/gcc/testsuite/rust/compile/generics9.rs b/gcc/testsuite/rust/compile/generics9.rs
index 56c6198..949fbb1 100644
--- a/gcc/testsuite/rust/compile/generics9.rs
+++ b/gcc/testsuite/rust/compile/generics9.rs
@@ -1,4 +1,3 @@
-// { dg-additional-options "-frust-name-resolution-2.0" }
struct Foo<A, B = (A, B)>(A, B);
// { dg-error "type parameters with a default cannot use forward declared identifiers" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/rust/compile/glob_import_enum.rs b/gcc/testsuite/rust/compile/glob_import_enum.rs
new file mode 100644
index 0000000..032a1db
--- /dev/null
+++ b/gcc/testsuite/rust/compile/glob_import_enum.rs
@@ -0,0 +1,16 @@
+use self::Ordering::*;
+use Ordering::*;
+
+enum Ordering {
+ A,
+ B,
+}
+
+fn foo(_: Ordering) {}
+
+fn main() {
+ let a = A;
+
+ foo(a);
+ foo(B);
+}
diff --git a/gcc/testsuite/rust/compile/impl_trait_diag.rs b/gcc/testsuite/rust/compile/impl_trait_diag.rs
new file mode 100644
index 0000000..54a0cd2
--- /dev/null
+++ b/gcc/testsuite/rust/compile/impl_trait_diag.rs
@@ -0,0 +1,17 @@
+#[lang = "sized"]
+pub trait Sized {}
+
+trait Foo {
+ fn method(&self);
+}
+
+struct Bar;
+impl Foo for Bar {}
+
+fn main() {
+ let x: impl Foo = Bar; // { dg-error ".impl Trait. not allowed outside of function and inherent method return types .E0562." }
+
+ struct Wrapper {
+ field: impl Foo, // { dg-error ".impl Trait. not allowed outside of function and inherent method return types .E0562." }
+ }
+}
diff --git a/gcc/testsuite/rust/compile/impl_trait_generic_arg.rs b/gcc/testsuite/rust/compile/impl_trait_generic_arg.rs
new file mode 100644
index 0000000..ecdb088
--- /dev/null
+++ b/gcc/testsuite/rust/compile/impl_trait_generic_arg.rs
@@ -0,0 +1,24 @@
+#[lang = "sized"]
+trait Sized {}
+
+trait Foo {
+ fn id(&self) -> u8;
+}
+
+struct Bar;
+
+impl Foo for Bar {
+ fn id(&self) -> u8 {
+ 1
+ }
+}
+
+fn takes(val: impl Foo) -> u8 {
+ val.id()
+}
+
+fn main() {
+ let b = Bar;
+ let x = takes::<Bar>(b);
+ // { dg-error "cannot provide explicit generic arguments when .impl Trait. is used in argument position .E0632." "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/invalid_label_name.rs b/gcc/testsuite/rust/compile/invalid_label_name.rs
index 66e40a6..d1c5a33 100644
--- a/gcc/testsuite/rust/compile/invalid_label_name.rs
+++ b/gcc/testsuite/rust/compile/invalid_label_name.rs
@@ -1,4 +1,3 @@
-// { dg-additional-options "-frust-name-resolution-2.0" }
pub fn function() {
'continue: loop {
// { dg-error "invalid label name .'continue." "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/rust/compile/issue-1048.rs b/gcc/testsuite/rust/compile/issue-1048.rs
new file mode 100644
index 0000000..8d4053a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1048.rs
@@ -0,0 +1,8 @@
+macro_rules! maybe_return { ($e:expr) => ($e); }
+
+fn frob(x: i32) -> i32{
+ maybe_return! {x}
+ // { dg-error "mismatched types. expected .... but got .i32. .E0308." "" { target *-*-* } .-1 }
+ // should return -1
+ -1
+}
diff --git a/gcc/testsuite/rust/compile/issue-1485.rs b/gcc/testsuite/rust/compile/issue-1485.rs
new file mode 100644
index 0000000..a0cd5a0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1485.rs
@@ -0,0 +1,16 @@
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "fn_once"]
+pub trait FnOnce<Args> {
+ #[lang = "fn_once_output"]
+ type Output;
+
+ extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+}
+
+struct BinOpInvalid {
+ lhs: i32,
+ rhs: i32,
+ f: impl FnOnce(i32) -> i32, // { dg-error ".impl Trait. not allowed outside of function and inherent method return types .E0562." }
+}
diff --git a/gcc/testsuite/rust/compile/issue-1487.rs b/gcc/testsuite/rust/compile/issue-1487.rs
new file mode 100644
index 0000000..4a4d759
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1487.rs
@@ -0,0 +1,15 @@
+// { dg-options "-w" }
+#[lang = "sized"]
+trait Sized {}
+
+trait Printable {
+ fn print(&self);
+}
+
+struct Foo;
+
+impl Printable for Foo {
+ fn print(&self) {}
+}
+
+fn take_printable(_: impl Printable) {}
diff --git a/gcc/testsuite/rust/compile/issue-2015.rs b/gcc/testsuite/rust/compile/issue-2015.rs
index 7789ecd..7e03651 100644
--- a/gcc/testsuite/rust/compile/issue-2015.rs
+++ b/gcc/testsuite/rust/compile/issue-2015.rs
@@ -1,4 +1,5 @@
-// { dg-additional-options "-frust-compile-until=lowering" }
+#[lang = "sized"]
+trait Sized {}
macro_rules! impl_foo {
() => { impl Foo }
diff --git a/gcc/testsuite/rust/compile/issue-2043.rs b/gcc/testsuite/rust/compile/issue-2043.rs
index efa1ded..92532b7 100644
--- a/gcc/testsuite/rust/compile/issue-2043.rs
+++ b/gcc/testsuite/rust/compile/issue-2043.rs
@@ -6,7 +6,6 @@ struct Foo<'a> {
impl<'a> Foo<'a> {
fn bar(self: &mut Foo<'a>) {}
// { dg-warning "associated function is never used: .bar." "" { target *-*-* } .-1 }
- // { dg-warning "unused name .self." "" { target *-*-* } .-2 }
}
fn main() {}
diff --git a/gcc/testsuite/rust/compile/issue-2166.rs b/gcc/testsuite/rust/compile/issue-2166.rs
index 318f0a6..142ed17 100644
--- a/gcc/testsuite/rust/compile/issue-2166.rs
+++ b/gcc/testsuite/rust/compile/issue-2166.rs
@@ -11,7 +11,6 @@ impl Add for u32 {
type Output = u32;
fn add(self) -> u32 {
- // { dg-warning "unused name" "" { target *-*-* } .-1 }
0
}
}
@@ -20,7 +19,6 @@ impl<'a> Add for &'a u32 {
type Output = u32;
fn add(self) -> <u32 as Add>::Output {
- // { dg-warning "unused name" "" { target *-*-* } .-1 }
0
}
}
diff --git a/gcc/testsuite/rust/compile/issue-2238.rs b/gcc/testsuite/rust/compile/issue-2238.rs
index 38871b3..6a43a13 100644
--- a/gcc/testsuite/rust/compile/issue-2238.rs
+++ b/gcc/testsuite/rust/compile/issue-2238.rs
@@ -10,7 +10,6 @@ fn main() {
impl Bar for Foo {
fn foo(&self) {}
- // { dg-warning "unused name" "" { target *-*-* } .-1 }
}
let s = Foo;
diff --git a/gcc/testsuite/rust/compile/issue-2680.rs b/gcc/testsuite/rust/compile/issue-2680.rs
new file mode 100644
index 0000000..d5ae2ff44
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2680.rs
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fdump-tree-gimple" }
+pub fn test_cast() {
+ let i = 1;
+ // { dg-final { scan-tree-dump-times {const i32 i;} 1 gimple } }
+ let _j = i as i64;
+}
diff --git a/gcc/testsuite/rust/compile/issue-2907.rs b/gcc/testsuite/rust/compile/issue-2907.rs
index 1af843f..fdf1953 100644
--- a/gcc/testsuite/rust/compile/issue-2907.rs
+++ b/gcc/testsuite/rust/compile/issue-2907.rs
@@ -15,7 +15,6 @@ impl<B: Bar> Foo for B {
type Ty = u32;
fn foo(self) -> Self::Ty {
- // { dg-warning "unused name" "" { target *-*-* } .-1 }
14
}
}
diff --git a/gcc/testsuite/rust/compile/issue-3144.rs b/gcc/testsuite/rust/compile/issue-3144.rs
new file mode 100644
index 0000000..4e61078
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3144.rs
@@ -0,0 +1,29 @@
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "copy"]
+trait Copy {}
+
+#[lang = "clone"]
+pub trait Clone {
+ fn clone(&self) -> Self;
+}
+
+impl Clone for i32 {
+ fn clone(&self) -> i32 {
+ *self
+ }
+}
+
+struct S {}
+
+#[derive(Clone, Copy)]
+// { dg-error {bounds not satisfied for S .Clone. is not satisfied .E0277.} "" { target *-*-* } .-1 }
+struct S2 {
+ a: i32,
+ s: S,
+}
+
+fn main() -> i32 {
+ 0
+}
diff --git a/gcc/testsuite/rust/compile/issue-3304.rs b/gcc/testsuite/rust/compile/issue-3304.rs
index 6ab614f..cc376fa 100644
--- a/gcc/testsuite/rust/compile/issue-3304.rs
+++ b/gcc/testsuite/rust/compile/issue-3304.rs
@@ -1,4 +1,3 @@
-// { dg-additional-options "-frust-name-resolution-2.0" }
#[lang = "sized"]
trait Sized {}
diff --git a/gcc/testsuite/rust/compile/issue-3454.rs b/gcc/testsuite/rust/compile/issue-3454.rs
new file mode 100644
index 0000000..2a3c0c7
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3454.rs
@@ -0,0 +1,20 @@
+#[lang = "sized"]
+pub trait Sized {}
+
+macro_rules! impl_foo {
+ () => { impl Foo }
+}
+
+pub trait Foo {}
+
+pub trait Bar {
+ type Baz;
+}
+
+pub fn foo(_value: impl Bar<Baz = impl_foo!()>) -> i32 {
+ 15
+}
+
+pub fn bar(_value: impl Bar<Baz = impl Foo>) -> i32 {
+ 16
+}
diff --git a/gcc/testsuite/rust/compile/issue-3524.rs b/gcc/testsuite/rust/compile/issue-3524.rs
new file mode 100644
index 0000000..62c8c35
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3524.rs
@@ -0,0 +1,9 @@
+struct A {}
+// { dg-warning "struct is never constructed" "" { target *-*-* } .-1 }
+
+impl A {
+ fn main() {}
+ // { dg-warning "associated function is never used: .main." "" { target *-*-* } .-1 }
+}
+
+fn main() {}
diff --git a/gcc/testsuite/rust/compile/issue-3525.rs b/gcc/testsuite/rust/compile/issue-3525.rs
new file mode 100644
index 0000000..84a7ebe
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3525.rs
@@ -0,0 +1,6 @@
+// { dg-options "-w" }
+
+struct Foo(usize);
+
+const B: usize = A.0;
+const A: Foo = Foo(123);
diff --git a/gcc/testsuite/rust/compile/issue-3546.rs b/gcc/testsuite/rust/compile/issue-3546.rs
new file mode 100644
index 0000000..d4ec0bb
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3546.rs
@@ -0,0 +1,16 @@
+const L: usize = 3;
+
+fn main() {
+ let p = Printer {};
+ p.print();
+}
+
+trait Print<const N: usize> {
+ fn print(&self) -> usize {
+ 3
+ }
+}
+
+struct Printer {}
+impl Print<L> for Printer {}
+// { dg-error "generic item takes at most 1 type arguments but 1 were supplied" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/rust/compile/issue-3551.rs b/gcc/testsuite/rust/compile/issue-3551.rs
new file mode 100644
index 0000000..6d6a812
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3551.rs
@@ -0,0 +1,15 @@
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "fn_once"]
+pub trait FnOnce<Args> {
+ #[lang = "fn_once_output"]
+ type Output;
+
+ extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+}
+
+struct Bug {
+ a: [(); (|| 0)()],
+ // { dg-error "calls in constants are limited to constant functions, tuple structs and tuple variants" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/issue-3599.rs b/gcc/testsuite/rust/compile/issue-3599.rs
new file mode 100644
index 0000000..1d29fac
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3599.rs
@@ -0,0 +1,8 @@
+#[lang = "sized"]
+trait Sized {}
+
+trait Bar {}
+
+struct S; // { dg-warning "struct is never constructed" }
+
+pub fn test(foo: impl Bar) {}
diff --git a/gcc/testsuite/rust/compile/issue-3618.rs b/gcc/testsuite/rust/compile/issue-3618.rs
new file mode 100644
index 0000000..3bf2c7e
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3618.rs
@@ -0,0 +1,2 @@
+static _X : ()
+ = loop{}; // { dg-error "'loop' is not allowed in const context" }
diff --git a/gcc/testsuite/rust/compile/issue-3642.rs b/gcc/testsuite/rust/compile/issue-3642.rs
new file mode 100644
index 0000000..6d9decc
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3642.rs
@@ -0,0 +1,9 @@
+#[lang = "sized"]
+trait Sized {}
+
+pub trait T<X> {
+ const D: i32 = {
+ // { dg-error "mismatched types, expected .i32. but got .()." "" { target *-*-* } .-1 }
+ const C: X;
+ };
+}
diff --git a/gcc/testsuite/rust/compile/issue-3660.rs b/gcc/testsuite/rust/compile/issue-3660.rs
new file mode 100644
index 0000000..1f1c583
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3660.rs
@@ -0,0 +1,3 @@
+pub static A: [u32; 2] = [1, 2];
+
+pub static B: [u8; 2] = [3, 4];
diff --git a/gcc/testsuite/rust/compile/issue-3661.rs b/gcc/testsuite/rust/compile/issue-3661.rs
new file mode 100644
index 0000000..8d03c36
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3661.rs
@@ -0,0 +1,10 @@
+pub macro m($inner_str:expr) {
+ #[m = $inner_str]
+ // { dg-error "macro not found" "" { target *-*-* } .-1 }
+
+ struct S;
+}
+
+fn main() {
+ m!(stringify!(foo));
+}
diff --git a/gcc/testsuite/rust/compile/issue-3671.rs b/gcc/testsuite/rust/compile/issue-3671.rs
index e800d53..8015653 100644
--- a/gcc/testsuite/rust/compile/issue-3671.rs
+++ b/gcc/testsuite/rust/compile/issue-3671.rs
@@ -1,2 +1,2 @@
-impl Self<0> {}
+impl Foo<0> {}
// { dg-error "could not resolve type path" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/rust/compile/issue-3836.rs b/gcc/testsuite/rust/compile/issue-3836.rs
new file mode 100644
index 0000000..a228795
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3836.rs
@@ -0,0 +1,67 @@
+// { dg-options "-w" }
+mod core {
+ mod option {
+ pub enum Option<T> {
+ #[lang = "None"]
+ None,
+ #[lang = "Some"]
+ Some(T),
+ }
+ }
+
+ mod marker {
+ #[lang = "sized"]
+ pub trait Sized {}
+ }
+
+ mod cmp {
+ use super::marker::Sized;
+ use super::option::Option;
+
+ pub enum Ordering {
+ Less = -1,
+ Equal = 0,
+ Greater = 1,
+ }
+
+ #[lang = "eq"]
+ pub trait PartialEq<Rhs: ?Sized = Self> {
+ fn eq(&self, other: &Rhs) -> bool;
+
+ fn ne(&self, other: &Rhs) -> bool {
+ !self.eq(other)
+ }
+ }
+
+ #[lang = "partial_ord"]
+ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
+ fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+ }
+ }
+}
+
+use core::cmp::{Ordering, PartialEq, PartialOrd};
+use core::marker::Sized;
+use core::option::Option;
+
+impl PartialEq for i32 {
+ fn eq(&self, other: &Self) -> bool {
+ false
+ }
+}
+
+impl PartialOrd for i32 {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ Option::Some(Ordering::Equal)
+ }
+}
+
+struct Foo {
+ a: i32,
+}
+
+impl PartialEq for Foo {
+ fn eq(&self, other: &'_ Self) -> bool {
+ ::core::cmp::PartialEq::eq(&self.a, &other.a)
+ }
+}
diff --git a/gcc/testsuite/rust/compile/issue-3874.rs b/gcc/testsuite/rust/compile/issue-3874.rs
new file mode 100644
index 0000000..ebce4b6
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3874.rs
@@ -0,0 +1,4 @@
+fn wow(){
+ &#[serde]
+ // { dg-error "found unexpected token .#. in null denotation" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/issue-3876.rs b/gcc/testsuite/rust/compile/issue-3876.rs
new file mode 100644
index 0000000..17b1590
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3876.rs
@@ -0,0 +1,8 @@
+enum test {
+ A(i32),
+}
+
+fn fun(x: i32) {
+ test::A { x }
+ // { dg-error "unknown field" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/issue-3885.rs b/gcc/testsuite/rust/compile/issue-3885.rs
new file mode 100644
index 0000000..050a59c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3885.rs
@@ -0,0 +1,7 @@
+pub fn test() {
+ let _u: [_; _] = [15u32];
+ let _v: [u8; _] = [1, 2, 3];
+ let _w: [_; 2] = [1.0, 2.0];
+ let _x = [42; 5];
+ let _y: [_; _] = _x;
+}
diff --git a/gcc/testsuite/rust/compile/issue-3915.rs b/gcc/testsuite/rust/compile/issue-3915.rs
new file mode 100644
index 0000000..7132036
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3915.rs
@@ -0,0 +1,28 @@
+// { dg-options "-w" }
+#[lang = "sized"]
+trait Sized {}
+
+trait Trait {
+ fn do_thing();
+}
+
+struct MyType;
+
+impl Trait for MyType {
+ fn do_thing() {}
+}
+
+struct Wrapper<T: Trait> {
+ value: T,
+}
+
+impl<T: Trait> Wrapper<T> {
+ fn call_it() {
+ T::do_thing();
+ }
+}
+
+fn main() {
+ let _ = Wrapper::<MyType> { value: MyType };
+ Wrapper::<MyType>::call_it();
+}
diff --git a/gcc/testsuite/rust/compile/issue-3916.rs b/gcc/testsuite/rust/compile/issue-3916.rs
new file mode 100644
index 0000000..59b522b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3916.rs
@@ -0,0 +1,36 @@
+#![feature(rustc_attrs)]
+
+#[lang = "sized"]
+trait Sized {}
+
+#[lang = "add"]
+trait Add<Rhs = Self> {
+ type Output;
+
+ fn add(self, rhs: Rhs) -> Self::Output;
+}
+
+macro_rules! add_impl {
+ ($($t:ty)*) => ($(
+ impl Add for $t {
+ type Output = $t;
+
+ #[inline]
+ #[rustc_inherit_overflow_checks]
+ fn add(self, other: $t) -> $t { self + other }
+ }
+ )*)
+}
+
+add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
+
+pub fn test(len: usize) -> u64 {
+ let mut i = 0;
+ let mut out = 0;
+ if i + 3 < len {
+ out = 123;
+ } else {
+ out = 456;
+ }
+ out
+}
diff --git a/gcc/testsuite/rust/compile/issue-3960.rs b/gcc/testsuite/rust/compile/issue-3960.rs
new file mode 100644
index 0000000..57329f0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3960.rs
@@ -0,0 +1,7 @@
+fn main() {
+ struct G {
+ g: (),
+ }
+ let g = [0; G { g: () }];
+ // { dg-error "mismatched types, expected .usize. but got .G. .E0308." "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/issue-3978.rs b/gcc/testsuite/rust/compile/issue-3978.rs
new file mode 100644
index 0000000..4f17d3d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3978.rs
@@ -0,0 +1,8 @@
+type Dimension = usize;
+
+pub fn main() {}
+
+mod m2 {
+ fn main() {}
+ // { dg-warning "function is never used" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/issue-4006.rs b/gcc/testsuite/rust/compile/issue-4006.rs
new file mode 100644
index 0000000..328c7b6
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-4006.rs
@@ -0,0 +1,13 @@
+#![feature(rustc_attrs)]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+ () => {};
+}
+
+pub fn main() {
+ asm!(
+ "xor eax, eax"
+ "xor eax, eax");
+ // { dg-error "expected token .;." "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/loop_constant_context.rs b/gcc/testsuite/rust/compile/loop_constant_context.rs
new file mode 100644
index 0000000..ed0782b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/loop_constant_context.rs
@@ -0,0 +1,5 @@
+// { dg-error "'loop' is not allowed in const context" "" { target *-*-* } .+1 }
+const CONST_LOOP : () = loop{};
+
+// { dg-error "'loop' is not allowed in const context" "" { target *-*-* } .+1 }
+static STATIC_LOOP : () = loop{}; \ No newline at end of file
diff --git a/gcc/testsuite/rust/compile/macros/builtin/recurse2.rs b/gcc/testsuite/rust/compile/macros/builtin/recurse2.rs
index 73e6ab4..fbb4b10 100644
--- a/gcc/testsuite/rust/compile/macros/builtin/recurse2.rs
+++ b/gcc/testsuite/rust/compile/macros/builtin/recurse2.rs
@@ -34,7 +34,7 @@ fn print_str(s: &str) {
}
}
-// { dg-final { scan-assembler {"abheyho"} } }
+// { dg-final { scan-assembler {"abheyho(\\0)?"} } }
static S: &str = concat!("a", 'b', a!(), a!(b c d e f a!()), '\0');
fn main() {
diff --git a/gcc/testsuite/rust/compile/macros/mbe/macro-issue3708.rs b/gcc/testsuite/rust/compile/macros/mbe/macro-issue3708.rs
index e5b38bb..bcbc8dd 100644
--- a/gcc/testsuite/rust/compile/macros/mbe/macro-issue3708.rs
+++ b/gcc/testsuite/rust/compile/macros/mbe/macro-issue3708.rs
@@ -1,4 +1,4 @@
-// { dg-additional-options "-frust-name-resolution-2.0 -frust-compile-until=lowering" }
+// { dg-additional-options "-frust-compile-until=lowering" }
macro_rules! impl_fn_for_zst {
($(
diff --git a/gcc/testsuite/rust/compile/macros/mbe/macro-issue3709-2.rs b/gcc/testsuite/rust/compile/macros/mbe/macro-issue3709-2.rs
index cfc8ab4..47514f1 100644
--- a/gcc/testsuite/rust/compile/macros/mbe/macro-issue3709-2.rs
+++ b/gcc/testsuite/rust/compile/macros/mbe/macro-issue3709-2.rs
@@ -1,4 +1,4 @@
-// { dg-additional-options "-frust-name-resolution-2.0 -frust-compile-until=lowering" }
+// { dg-additional-options "-frust-compile-until=lowering" }
macro_rules! impl_fn_for_zst {
($(
diff --git a/gcc/testsuite/rust/compile/macros/mbe/meta-param.rs b/gcc/testsuite/rust/compile/macros/mbe/meta-param.rs
new file mode 100644
index 0000000..ed6e100
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macros/mbe/meta-param.rs
@@ -0,0 +1,7 @@
+macro_rules! foo {
+ ($x:meta) => {0}
+}
+
+pub fn main() -> i32 {
+ foo!(Clone)
+}
diff --git a/gcc/testsuite/rust/compile/match-identifierpattern-enum.rs b/gcc/testsuite/rust/compile/match-identifierpattern-enum.rs
new file mode 100644
index 0000000..c712667
--- /dev/null
+++ b/gcc/testsuite/rust/compile/match-identifierpattern-enum.rs
@@ -0,0 +1,12 @@
+enum Foo {
+ I(i32),
+}
+
+fn main() {
+ let x = Foo::I(1);
+
+ match x {
+ a @ Foo::I(b) => {},
+ _ => {},
+ };
+}
diff --git a/gcc/testsuite/rust/compile/match-identifierpattern.rs b/gcc/testsuite/rust/compile/match-identifierpattern.rs
new file mode 100644
index 0000000..6c558ac
--- /dev/null
+++ b/gcc/testsuite/rust/compile/match-identifierpattern.rs
@@ -0,0 +1,9 @@
+fn main() {
+ let x = 1;
+
+ match x {
+ 2 => {},
+ a @ 3 => {},
+ _ => {},
+ }
+}
diff --git a/gcc/testsuite/rust/compile/match-restpattern-tuple-1.rs b/gcc/testsuite/rust/compile/match-restpattern-tuple-1.rs
new file mode 100644
index 0000000..5cce3c4
--- /dev/null
+++ b/gcc/testsuite/rust/compile/match-restpattern-tuple-1.rs
@@ -0,0 +1,8 @@
+fn main() {
+ let x = (1, 2, 3, 4);
+
+ match x {
+ (1, .., 4) => {},
+ _ => {}
+ }
+} \ No newline at end of file
diff --git a/gcc/testsuite/rust/compile/match-restpattern-tuple-2.rs b/gcc/testsuite/rust/compile/match-restpattern-tuple-2.rs
new file mode 100644
index 0000000..40900a3
--- /dev/null
+++ b/gcc/testsuite/rust/compile/match-restpattern-tuple-2.rs
@@ -0,0 +1,8 @@
+fn main() {
+ let x = (1, 2, 3, 4);
+
+ match x {
+ (1, .., 2, 3, 4, 5) => {}, // { dg-error "expected a tuple with 4 elements, found one with 5 elements" }
+ _ => {}
+ }
+} \ No newline at end of file
diff --git a/gcc/testsuite/rust/compile/match-slicepattern-array.rs b/gcc/testsuite/rust/compile/match-slicepattern-array.rs
new file mode 100644
index 0000000..e48ca75
--- /dev/null
+++ b/gcc/testsuite/rust/compile/match-slicepattern-array.rs
@@ -0,0 +1,8 @@
+fn main() {
+ let a = [0, 1];
+
+ match a {
+ [0, 1] => {},
+ _ => {}
+ }
+}
diff --git a/gcc/testsuite/rust/compile/match-slicepattern-slice.rs b/gcc/testsuite/rust/compile/match-slicepattern-slice.rs
new file mode 100644
index 0000000..cc33d93
--- /dev/null
+++ b/gcc/testsuite/rust/compile/match-slicepattern-slice.rs
@@ -0,0 +1,10 @@
+fn main() {
+ let arr = [1, 2];
+ let slice: &[i32] = &arr;
+
+ match slice {
+ [1] => {},
+ [_, 2] => {},
+ _ => {}
+ }
+} \ No newline at end of file
diff --git a/gcc/testsuite/rust/compile/match-tuplestructpattern.rs b/gcc/testsuite/rust/compile/match-tuplestructpattern.rs
new file mode 100644
index 0000000..0dae71e
--- /dev/null
+++ b/gcc/testsuite/rust/compile/match-tuplestructpattern.rs
@@ -0,0 +1,9 @@
+fn main() {
+ struct A (i32, i32);
+ let a = A (0, 1);
+
+ match a {
+ A (0, 1) => {},
+ _ => {}
+ }
+}
diff --git a/gcc/testsuite/rust/compile/min_specialization1.rs b/gcc/testsuite/rust/compile/min_specialization1.rs
index d38167e..ba97f87 100644
--- a/gcc/testsuite/rust/compile/min_specialization1.rs
+++ b/gcc/testsuite/rust/compile/min_specialization1.rs
@@ -9,7 +9,7 @@ pub trait Foo {
pub struct Bar;
impl Foo for Bar {
- default fn foo(&self) -> bool { // { dg-warning "unused" }
+ default fn foo(&self) -> bool {
true
}
}
diff --git a/gcc/testsuite/rust/compile/name_resolution10.rs b/gcc/testsuite/rust/compile/name_resolution10.rs
index 33643bd..f156f98 100644
--- a/gcc/testsuite/rust/compile/name_resolution10.rs
+++ b/gcc/testsuite/rust/compile/name_resolution10.rs
@@ -1,4 +1,4 @@
-// { dg-options "-frust-name-resolution-2.0 -frust-compile-until=lowering" }
+// { dg-options "-frust-compile-until=lowering" }
#![feature(decl_macro)]
diff --git a/gcc/testsuite/rust/compile/name_resolution11.rs b/gcc/testsuite/rust/compile/name_resolution11.rs
index a464d2a..329567a 100644
--- a/gcc/testsuite/rust/compile/name_resolution11.rs
+++ b/gcc/testsuite/rust/compile/name_resolution11.rs
@@ -1,4 +1,4 @@
-// { dg-additional-options "-frust-name-resolution-2.0 -frust-compile-until=lowering" }
+// { dg-additional-options "-frust-compile-until=lowering" }
fn foo() {
let b = 10;
fn bar() {
diff --git a/gcc/testsuite/rust/compile/name_resolution12.rs b/gcc/testsuite/rust/compile/name_resolution12.rs
index 9cce31c..0f217aa 100644
--- a/gcc/testsuite/rust/compile/name_resolution12.rs
+++ b/gcc/testsuite/rust/compile/name_resolution12.rs
@@ -1,4 +1,4 @@
-// { dg-additional-options "-frust-name-resolution-2.0 -frust-compile-until=lowering" }
+// { dg-additional-options "-frust-compile-until=lowering" }
const TOTO: i32 = 10;
diff --git a/gcc/testsuite/rust/compile/name_resolution13.rs b/gcc/testsuite/rust/compile/name_resolution13.rs
index 33edbf9..8356cf6 100644
--- a/gcc/testsuite/rust/compile/name_resolution13.rs
+++ b/gcc/testsuite/rust/compile/name_resolution13.rs
@@ -1,5 +1,3 @@
-// { dg-options "-frust-name-resolution-2.0" }
-
pub mod foo {
pub macro bar() {}
}
diff --git a/gcc/testsuite/rust/compile/name_resolution14.rs b/gcc/testsuite/rust/compile/name_resolution14.rs
index eaef6a5..44c43aa 100644
--- a/gcc/testsuite/rust/compile/name_resolution14.rs
+++ b/gcc/testsuite/rust/compile/name_resolution14.rs
@@ -1,5 +1,3 @@
-// { dg-options "-frust-name-resolution-2.0" }
-
pub mod foo {
pub macro bar() {}
}
diff --git a/gcc/testsuite/rust/compile/name_resolution15.rs b/gcc/testsuite/rust/compile/name_resolution15.rs
index 45f38da..e82c90e 100644
--- a/gcc/testsuite/rust/compile/name_resolution15.rs
+++ b/gcc/testsuite/rust/compile/name_resolution15.rs
@@ -1,4 +1,3 @@
-// { dg-additional-options "-frust-name-resolution-2.0" }
#![feature(decl_macro)]
pub mod foo {
diff --git a/gcc/testsuite/rust/compile/name_resolution16.rs b/gcc/testsuite/rust/compile/name_resolution16.rs
index 230722e..4db7b2e 100644
--- a/gcc/testsuite/rust/compile/name_resolution16.rs
+++ b/gcc/testsuite/rust/compile/name_resolution16.rs
@@ -1,4 +1,3 @@
-// { dg-additional-options "-frust-name-resolution-2.0" }
#![feature(decl_macro)]
pub mod foo {
diff --git a/gcc/testsuite/rust/compile/name_resolution17.rs b/gcc/testsuite/rust/compile/name_resolution17.rs
index 4859476..84ad380 100644
--- a/gcc/testsuite/rust/compile/name_resolution17.rs
+++ b/gcc/testsuite/rust/compile/name_resolution17.rs
@@ -1,5 +1,3 @@
-// { dg-options "-frust-name-resolution-2.0" }
-
struct Foo;
fn Foo() {} // { dg-error ".Foo. defined multiple times" }
diff --git a/gcc/testsuite/rust/compile/name_resolution18.rs b/gcc/testsuite/rust/compile/name_resolution18.rs
index 5940149..17a3352 100644
--- a/gcc/testsuite/rust/compile/name_resolution18.rs
+++ b/gcc/testsuite/rust/compile/name_resolution18.rs
@@ -1,5 +1,3 @@
-// { dg-options "-frust-name-resolution-2.0" }
-
struct Marker;
struct Foo {
diff --git a/gcc/testsuite/rust/compile/name_resolution2.rs b/gcc/testsuite/rust/compile/name_resolution2.rs
index 7e4f5a1..564c5d2 100644
--- a/gcc/testsuite/rust/compile/name_resolution2.rs
+++ b/gcc/testsuite/rust/compile/name_resolution2.rs
@@ -4,7 +4,7 @@ pub trait Sized {}
struct Bar;
trait Foo {
- fn bar(&self) {} // { dg-warning "unused name" }
+ fn bar(&self) {}
}
pub fn outer() {
diff --git a/gcc/testsuite/rust/compile/name_resolution20.rs b/gcc/testsuite/rust/compile/name_resolution20.rs
index e6c2dd5..f131bb4 100644
--- a/gcc/testsuite/rust/compile/name_resolution20.rs
+++ b/gcc/testsuite/rust/compile/name_resolution20.rs
@@ -1,5 +1,3 @@
-// { dg-options "-frust-name-resolution-2.0" }
-
pub mod foo {
pub macro bar() {}
}
diff --git a/gcc/testsuite/rust/compile/name_resolution22.rs b/gcc/testsuite/rust/compile/name_resolution22.rs
index c49331e..bb5edda 100644
--- a/gcc/testsuite/rust/compile/name_resolution22.rs
+++ b/gcc/testsuite/rust/compile/name_resolution22.rs
@@ -1,4 +1,3 @@
-// { dg-options "-frust-name-resolution-2.0" }
struct Marker;
struct Foo(Marker);
diff --git a/gcc/testsuite/rust/compile/name_resolution23.rs b/gcc/testsuite/rust/compile/name_resolution23.rs
index 50b8e81..843be2a 100644
--- a/gcc/testsuite/rust/compile/name_resolution23.rs
+++ b/gcc/testsuite/rust/compile/name_resolution23.rs
@@ -1,5 +1,3 @@
-// { dg-options "-frust-name-resolution-2.0" }
-
mod a {
pub mod b {
pub fn foo() {}
diff --git a/gcc/testsuite/rust/compile/name_resolution24.rs b/gcc/testsuite/rust/compile/name_resolution24.rs
index f4eb7b2..4350cd8 100644
--- a/gcc/testsuite/rust/compile/name_resolution24.rs
+++ b/gcc/testsuite/rust/compile/name_resolution24.rs
@@ -1,5 +1,3 @@
-// { dg-options "-frust-name-resolution-2.0" }
-
mod a {
pub mod b {
pub fn baz() {}
diff --git a/gcc/testsuite/rust/compile/name_resolution25.rs b/gcc/testsuite/rust/compile/name_resolution25.rs
index 3cacac7..0cadd9e 100644
--- a/gcc/testsuite/rust/compile/name_resolution25.rs
+++ b/gcc/testsuite/rust/compile/name_resolution25.rs
@@ -1,5 +1,3 @@
-// { dg-options "-frust-name-resolution-2.0" }
-
struct Test; // { dg-warning "struct is never constructed: .Test." }
impl Test {}
diff --git a/gcc/testsuite/rust/compile/name_resolution4.rs b/gcc/testsuite/rust/compile/name_resolution4.rs
index b2eadbe..0fc72f6 100644
--- a/gcc/testsuite/rust/compile/name_resolution4.rs
+++ b/gcc/testsuite/rust/compile/name_resolution4.rs
@@ -2,7 +2,7 @@
pub trait Sized {}
trait Foo {
- fn foo(&self) {} // { dg-warning "unused name" }
+ fn foo(&self) {}
}
struct Bar;
diff --git a/gcc/testsuite/rust/compile/name_resolution6.rs b/gcc/testsuite/rust/compile/name_resolution6.rs
index e4087e6..b2b5f6b 100644
--- a/gcc/testsuite/rust/compile/name_resolution6.rs
+++ b/gcc/testsuite/rust/compile/name_resolution6.rs
@@ -1,4 +1,4 @@
-// { dg-options "-frust-name-resolution-2.0 -frust-compile-until=lowering" }
+// { dg-options "-frust-compile-until=lowering" }
pub mod foo {
pub mod bar {
diff --git a/gcc/testsuite/rust/compile/name_resolution7.rs b/gcc/testsuite/rust/compile/name_resolution7.rs
index fa84e2f..78cb0b2 100644
--- a/gcc/testsuite/rust/compile/name_resolution7.rs
+++ b/gcc/testsuite/rust/compile/name_resolution7.rs
@@ -1,5 +1,3 @@
-// { dg-options "-frust-name-resolution-2.0" }
-
// check that macros by example do not get inserted in ribs like regular items
pub mod foo {
pub mod bar {
diff --git a/gcc/testsuite/rust/compile/name_resolution8.rs b/gcc/testsuite/rust/compile/name_resolution8.rs
index 6fb5170..aca1945 100644
--- a/gcc/testsuite/rust/compile/name_resolution8.rs
+++ b/gcc/testsuite/rust/compile/name_resolution8.rs
@@ -1,5 +1,3 @@
-// { dg-options "-frust-name-resolution-2.0" }
-
// check that macros by example get exported to the crate's root with #[macro_export]
pub mod foo {
pub mod bar {
diff --git a/gcc/testsuite/rust/compile/name_resolution9.rs b/gcc/testsuite/rust/compile/name_resolution9.rs
index 792b3bd..84ba3c5 100644
--- a/gcc/testsuite/rust/compile/name_resolution9.rs
+++ b/gcc/testsuite/rust/compile/name_resolution9.rs
@@ -1,5 +1,3 @@
-// { dg-options "-frust-name-resolution-2.0" }
-
pub mod foo {
pub mod bar {
fn f() {
diff --git a/gcc/testsuite/rust/compile/nested_macro_definition.rs b/gcc/testsuite/rust/compile/nested_macro_definition.rs
index c0b7250..b71afbd 100644
--- a/gcc/testsuite/rust/compile/nested_macro_definition.rs
+++ b/gcc/testsuite/rust/compile/nested_macro_definition.rs
@@ -1,5 +1,3 @@
-// { dg-options "-frust-name-resolution-2.0" }
-
macro_rules! toto {
() => {
macro_rules! tata {
diff --git a/gcc/testsuite/rust/compile/nr2/compile.exp b/gcc/testsuite/rust/compile/nr2/compile.exp
deleted file mode 100644
index 9e15cdd..0000000
--- a/gcc/testsuite/rust/compile/nr2/compile.exp
+++ /dev/null
@@ -1,149 +0,0 @@
-# Copyright (C) 2021-2024 Free Software Foundation, Inc.
-
-# This program 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 of the License, or
-# (at your option) any later version.
-#
-# This program 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/>.
-
-# Run compile tests with name resolution 2.0 enabled
-
-# Load support procs.
-load_lib rust-dg.exp
-
-# These tests don't run runtest_file_p consistently if it
-# doesn't return the same values, so disable parallelization
-# of this *.exp file. The first parallel runtest to reach
-# this will run all the tests serially.
-if ![gcc_parallel_test_run_p compile] {
- return
-}
-gcc_parallel_test_enable 0
-
-# Initialize `dg'.
-dg-init
-
-namespace eval rust-nr2-ns {
- # Exclude tests which aren't passing yet
- # These should be removed from the exclude file over time
-
- set exclude_fh [open $srcdir/$subdir/exclude r]
- set exclude_raw [lsort [split [read $exclude_fh] "\n"]]
- close $exclude_fh
- unset exclude_fh
-
- set exclude ""
- foreach ent $exclude_raw {
- if [regexp {^[^#].*} $ent] {
- lappend exclude $ent
- }
- }
- unset exclude_raw
-
- # Run tests in directories
- # Manually specifying these, in case some other test file
- # does something weird
- set test_dirs {{} {macros builtin} {macros mbe} {macros proc} {torture}}
-
- set tests_expect_ok ""
- set tests_expect_err ""
-
- set compile_dir [list {*}[file split $srcdir] {*}[file split $subdir]]
- set compile_dir [lreplace $compile_dir end end]
-
- foreach test_dir $test_dirs {
- foreach test [lsort [glob -nocomplain -tails -directory [file join {*}$compile_dir {*}$test_dir] *.rs]] {
- # use '/' as the path seperator for entries in the exclude file
- set test_lbl [join [list {*}$test_dir $test] "/"]
- set idx [lsearch -exact -sorted $exclude $test_lbl]
- if {$idx == -1} {
- if {[runtest_file_p $runtests [file join {*}$compile_dir {*}$test_dir $test]]} {
- lappend tests_expect_ok [list {*}$test_dir $test]
- }
- } else {
- if {[runtest_file_p $runtests [file join {*}$compile_dir {*}$test_dir $test]]} {
- lappend tests_expect_err [list {*}$test_dir $test]
- }
- set exclude [lreplace $exclude $idx $idx]
- }
- }
- }
-
- # Generate failures for unmatched tests in the exclude list
- foreach ent $exclude {
- fail "$ent: could not exclude test"
- }
- unset exclude
-
- # run a test while catching record_test calls
- set record_test_out ""
- proc try_test { test } {
- variable record_test_out
- rename ::record_test record_test_old
-
- proc ::record_test { type msg args } {
- namespace eval ::rust-nr2-ns {
- set type [uplevel 1 {set type}]
- set msg [uplevel 1 {set msg}]
- variable record_test_out
- switch $type {
- FAIL {
- lappend record_test_out [list $type $msg]
- }
- XPASS {
- lappend record_test_out [list $type $msg]
- }
- }
- }
- }
-
- namespace eval :: {
- set saved-dg-do-what-default ${dg-do-what-default}
- set dg-do-what-default "compile"
- dg-runtest [list [uplevel 1 {set test}]] "-frust-name-resolution-2.0" ""
- set dg-do-what-default ${saved-dg-do-what-default}
- }
-
- rename ::record_test ""
- rename record_test_old ::record_test
-
- set record_test_cache $record_test_out
- set record_test_out ""
- return $record_test_cache
- }
-
- # check for unexpected failures
- foreach test $tests_expect_ok {
- set fails [try_test [file join {*}$compile_dir {*}$test]]
- if {[llength $fails] != 0} {
- foreach ent $fails {
- record_test [lindex $ent 0] "on nr2: [lindex $ent 1]"
- }
- } else {
- record_test PASS "[file join {*}$test] on nr2"
- }
- }
-
- #check for unexpected successes
- foreach test $tests_expect_err {
- set fails [try_test [file join {*}$compile_dir {*}$test]]
- if {[llength $fails] == 0} {
- record_test XPASS "[file join {*}$test] on nr2"
- } else {
- record_test XFAIL "[file join {*}$test] on nr2 was rightfully excluded"
- }
- }
-}
-
-# All done.
-dg-finish
-
-gcc_parallel_test_enable 1
diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude
deleted file mode 100644
index c020e36..0000000
--- a/gcc/testsuite/rust/compile/nr2/exclude
+++ /dev/null
@@ -1,17 +0,0 @@
-canonical_paths1.rs
-issue-3315-2.rs
-privacy5.rs
-privacy8.rs
-pub_restricted_1.rs
-pub_restricted_2.rs
-pub_restricted_3.rs
-issue-2905-2.rs
-derive-default1.rs
-derive-eq-invalid.rs
-torture/alt_patterns1.rs
-torture/name_resolve1.rs
-issue-3663.rs
-issue-3671.rs
-issue-3652.rs
-issue-3649.rs
-# please don't delete the trailing newline
diff --git a/gcc/testsuite/rust/compile/offset_of1.rs b/gcc/testsuite/rust/compile/offset_of1.rs
new file mode 100644
index 0000000..5b79699
--- /dev/null
+++ b/gcc/testsuite/rust/compile/offset_of1.rs
@@ -0,0 +1,11 @@
+// { dg-additional-options "-frust-compile-until=lowering -frust-assume-builtin-offset-of" }
+
+pub struct Foo {
+ a: i32,
+}
+
+fn main() {
+ let _ = offset_of!(Foo, a); // valid
+ let _ = offset_of!("bloop", a); // { dg-error "could not parse type" }
+ let _ = offset_of!(Foo, 15); // { dg-error "could not parse field" }
+}
diff --git a/gcc/testsuite/rust/compile/offset_of2.rs b/gcc/testsuite/rust/compile/offset_of2.rs
new file mode 100644
index 0000000..d4ad9c2
--- /dev/null
+++ b/gcc/testsuite/rust/compile/offset_of2.rs
@@ -0,0 +1,9 @@
+// { dg-additional-options "-frust-compile-until=compilation -frust-assume-builtin-offset-of" }
+
+pub struct Foo {
+ a: i32,
+}
+
+fn main() {
+ let _ = offset_of!(Foo, a); // valid
+}
diff --git a/gcc/testsuite/rust/compile/parse_simple_path_fail_1.rs b/gcc/testsuite/rust/compile/parse_simple_path_fail_1.rs
new file mode 100644
index 0000000..c112e40
--- /dev/null
+++ b/gcc/testsuite/rust/compile/parse_simple_path_fail_1.rs
@@ -0,0 +1,3 @@
+pub(in crate::) struct S;
+// { dg-error "expecting ... but .::. found" "" { target *-*-* } .-1 }
+// { dg-error "failed to parse item in crate" "" { target *-*-* } .-2 }
diff --git a/gcc/testsuite/rust/compile/parse_simple_path_fail_2.rs b/gcc/testsuite/rust/compile/parse_simple_path_fail_2.rs
new file mode 100644
index 0000000..94c49c3
--- /dev/null
+++ b/gcc/testsuite/rust/compile/parse_simple_path_fail_2.rs
@@ -0,0 +1,9 @@
+mod A {
+ struct B;
+}
+
+use A{B};
+// { dg-error "unexpected token" "" { target *-*-* } .-1 }
+// { dg-error "could not parse use tree" "" { target *-*-* } .-2 }
+// { dg-error "failed to parse item in crate" "" { target *-*-* } 10 }
+// ^^^ TODO: should the above error happen at line 10?
diff --git a/gcc/testsuite/rust/compile/pub_restricted_1.rs b/gcc/testsuite/rust/compile/pub_restricted_1.rs
index 9bda968..2afbeb4 100644
--- a/gcc/testsuite/rust/compile/pub_restricted_1.rs
+++ b/gcc/testsuite/rust/compile/pub_restricted_1.rs
@@ -6,8 +6,8 @@ pub mod foo {
}
}
-pub(in foo::fah::baz) struct A1; // { dg-error "cannot find simple path segment .fah." }
-pub(in fro::bulator::saindoux) struct A2; // { dg-error "cannot find simple path segment .fro." }
-pub(in foo::bar::saindoux) struct A3; // { dg-error "cannot find simple path segment .saindoux." }
+pub(in foo::fah::baz) struct A1; // { dg-error "could not resolve path .foo::fah::baz." }
+pub(in fro::bulator::saindoux) struct A2; // { dg-error "could not resolve path .fro::bulator::saindoux." }
+pub(in foo::bar::saindoux) struct A3; // { dg-error "could not resolve path .foo::bar::saindoux." }
fn main() {}
diff --git a/gcc/testsuite/rust/compile/pub_restricted_2.rs b/gcc/testsuite/rust/compile/pub_restricted_2.rs
index 8588f27..fea9379 100644
--- a/gcc/testsuite/rust/compile/pub_restricted_2.rs
+++ b/gcc/testsuite/rust/compile/pub_restricted_2.rs
@@ -3,16 +3,16 @@
mod foo {
mod bar {
mod baz {
- pub(in baz) struct A0;
- pub(in bar::baz) struct A1;
+ pub(in super::baz) struct A0;
+ pub(in super::super::bar::baz) struct A1;
pub(in foo::bar::baz) struct A2;
mod sain {
mod doux {}
}
- pub(in sain) struct A3; // { dg-error "restricted path is not an ancestor of the current module" }
- pub(in sain::doux) struct A4; // { dg-error "restricted path is not an ancestor of the current module" }
+ pub(in self::sain) struct A3; // { dg-error "restricted path is not an ancestor of the current module" }
+ pub(in self::sain::doux) struct A4; // { dg-error "restricted path is not an ancestor of the current module" }
}
}
}
diff --git a/gcc/testsuite/rust/execute/same_field_name.rs b/gcc/testsuite/rust/compile/same_field_name.rs
index d57562b..8e5b78c 100644
--- a/gcc/testsuite/rust/execute/same_field_name.rs
+++ b/gcc/testsuite/rust/compile/same_field_name.rs
@@ -1,7 +1,7 @@
// https://doc.rust-lang.org/error_codes/E0124.html
fn main() {
struct Foo {
- field1: i32, // { dg-error "field .field1. is already declared" }
+ field1: i32,
field1: i32, // { dg-error "field .field1. is already declared" }
field1: i32, // { dg-error "field .field1. is already declared" }
}
diff --git a/gcc/testsuite/rust/compile/self-in-impl.rs b/gcc/testsuite/rust/compile/self-in-impl.rs
new file mode 100644
index 0000000..a567897
--- /dev/null
+++ b/gcc/testsuite/rust/compile/self-in-impl.rs
@@ -0,0 +1,15 @@
+// the error message here is what rustc >=1.66 emits
+// rustc <1.66 emits a "cycle detected" error when
+// trying to calculate the impl type
+//
+// since we aren't trying to match error messages too closely
+// and the >=1.66 error message is nicer
+// we may as well mimic that
+
+impl ((Self, i32)) {}
+// { dg-error ".Self. is not valid in the self" "" { target *-*-* } .-1 }
+
+trait Foo {}
+
+impl Foo for ((Self, i32)) {}
+// { dg-error ".Self. is not valid in the self" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/rust/compile/self_import_namespace.rs b/gcc/testsuite/rust/compile/self_import_namespace.rs
index 2d9b2ed..a63c1d7 100644
--- a/gcc/testsuite/rust/compile/self_import_namespace.rs
+++ b/gcc/testsuite/rust/compile/self_import_namespace.rs
@@ -1,5 +1,3 @@
-// { dg-additional-options "-frust-name-resolution-2.0" }
-
mod bar {
pub mod foo {}
pub fn foo() {}
diff --git a/gcc/testsuite/rust/compile/silly-order-bug.rs b/gcc/testsuite/rust/compile/silly-order-bug.rs
new file mode 100644
index 0000000..0d9cf1d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/silly-order-bug.rs
@@ -0,0 +1,8 @@
+#[lang = "sized"]
+trait Sized {}
+
+#[lang = "fn_once"]
+pub trait FnOnce<Args> {
+ extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+ type Output;
+}
diff --git a/gcc/testsuite/rust/compile/slicepattern-size-mismatch.rs b/gcc/testsuite/rust/compile/slicepattern-size-mismatch.rs
new file mode 100644
index 0000000..b54b532
--- /dev/null
+++ b/gcc/testsuite/rust/compile/slicepattern-size-mismatch.rs
@@ -0,0 +1,8 @@
+fn main() {
+ let arr = [0, 1];
+
+ match arr {
+ [0, 1, 2] => {} // { dg-error "pattern requires 3 elements but array has 2 .E0527." }
+ _ => {}
+ }
+} \ No newline at end of file
diff --git a/gcc/testsuite/rust/compile/torture/extern_mod2.rs b/gcc/testsuite/rust/compile/torture/extern_mod2.rs
index 4984d5d..f3a4f79 100644
--- a/gcc/testsuite/rust/compile/torture/extern_mod2.rs
+++ b/gcc/testsuite/rust/compile/torture/extern_mod2.rs
@@ -12,6 +12,12 @@ mod no_leading_equal;
#[path = "modules/valid_path.rs"]
mod extra_spaces;
+#[path = ""] // { dg-error "path attributes must contain a filename" }
+mod empty_path; // { dg-error "no candidate found" }
+
+#[path = " "] // { dg-error "path attributes must contain a filename" }
+mod path_with_spaces; // { dg-error "no candidate found" }
+
#[path] // { dg-error "path attributes must contain a filename" }
mod error; // { dg-error "no candidate found" }
diff --git a/gcc/testsuite/rust/compile/torture/generics29.rs b/gcc/testsuite/rust/compile/torture/generics29.rs
index e9c693e..baf53e4 100644
--- a/gcc/testsuite/rust/compile/torture/generics29.rs
+++ b/gcc/testsuite/rust/compile/torture/generics29.rs
@@ -5,7 +5,6 @@ struct Foo<A, B>(A, B);
impl Foo<i32, f32> {
fn test<X>(self, a: X) -> X {
- // { dg-warning "unused name" "" { target *-*-* } .-1 }
a
}
}
diff --git a/gcc/testsuite/rust/compile/torture/generics30.rs b/gcc/testsuite/rust/compile/torture/generics30.rs
index 24ae58f..a84f140 100644
--- a/gcc/testsuite/rust/compile/torture/generics30.rs
+++ b/gcc/testsuite/rust/compile/torture/generics30.rs
@@ -5,7 +5,6 @@ struct Foo<A, B>(A, B);
impl<T> Foo<T, f32> {
fn test<X>(self, a: X) -> X {
- // { dg-warning "unused name" "" { target *-*-* } .-1 }
a
}
}
diff --git a/gcc/testsuite/rust/compile/torture/traits3.rs b/gcc/testsuite/rust/compile/torture/traits3.rs
index d805da5..dad6dda 100644
--- a/gcc/testsuite/rust/compile/torture/traits3.rs
+++ b/gcc/testsuite/rust/compile/torture/traits3.rs
@@ -10,7 +10,6 @@ struct Baz;
impl Foo for Baz {
fn Bar(self) -> i32 {
- // { dg-warning "unused name .self." "" { target *-*-* } .-1 }
123
}
}
diff --git a/gcc/testsuite/rust/compile/torture/traits7.rs b/gcc/testsuite/rust/compile/torture/traits7.rs
index 8e4472d..545fd39 100644
--- a/gcc/testsuite/rust/compile/torture/traits7.rs
+++ b/gcc/testsuite/rust/compile/torture/traits7.rs
@@ -13,7 +13,6 @@ impl Foo for Bar {
// { dg-warning "unused name" "" { target *-*-* } .-1 }
fn test(self) {}
- // { dg-warning "unused name" "" { target *-*-* } .-1 }
}
fn main() {
diff --git a/gcc/testsuite/rust/compile/torture/unended-raw-byte-string.rs b/gcc/testsuite/rust/compile/torture/unended-raw-byte-string.rs
new file mode 100644
index 0000000..91a3c9a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/unended-raw-byte-string.rs
@@ -0,0 +1,6 @@
+// { dg-excess-errors "...." }
+fn main() {
+ // { dg-error "unended raw byte string literal" "" { target *-*-* } .+1 }
+ let s = br##"123"#
+}
+
diff --git a/gcc/testsuite/rust/compile/traits9.rs b/gcc/testsuite/rust/compile/traits9.rs
index bb3034d..f4308e8 100644
--- a/gcc/testsuite/rust/compile/traits9.rs
+++ b/gcc/testsuite/rust/compile/traits9.rs
@@ -11,6 +11,5 @@ fn main() {
a = Foo(123);
let b: &dyn Bar = &a;
- // { dg-error "bounds not satisfied for Foo .Bar. is not satisfied" "" { target *-*-* } .-1 }
- // { dg-error "expected" "" { target *-*-* } .-2 }
+ // { dg-error "bounds not satisfied for Foo .Bar. is not satisfied .E0277." "" { target *-*-* } .-1 }
}
diff --git a/gcc/testsuite/rust/compile/try_block1.rs b/gcc/testsuite/rust/compile/try_block1.rs
new file mode 100644
index 0000000..7ae0536
--- /dev/null
+++ b/gcc/testsuite/rust/compile/try_block1.rs
@@ -0,0 +1,89 @@
+// { dg-additional-options "-frust-edition=2018" }
+
+#[lang = "sized"]
+trait Sized {}
+
+enum Result<T, E> {
+ Ok(T),
+ Err(E)
+}
+
+pub trait Try {
+ /// The type of this value when viewed as successful.
+ #[unstable(feature = "try_trait", issue = "42327")]
+ type Ok;
+ /// The type of this value when viewed as failed.
+ #[unstable(feature = "try_trait", issue = "42327")]
+ type Error;
+
+ /// Applies the "?" operator. A return of `Ok(t)` means that the
+ /// execution should continue normally, and the result of `?` is the
+ /// value `t`. A return of `Err(e)` means that execution should branch
+ /// to the innermost enclosing `catch`, or return from the function.
+ ///
+ /// If an `Err(e)` result is returned, the value `e` will be "wrapped"
+ /// in the return type of the enclosing scope (which must itself implement
+ /// `Try`). Specifically, the value `X::from_error(From::from(e))`
+ /// is returned, where `X` is the return type of the enclosing function.
+ #[lang = "into_result"]
+ #[unstable(feature = "try_trait", issue = "42327")]
+ fn into_result(self) -> Result<Self::Ok, Self::Error>;
+
+ /// Wrap an error value to construct the composite result. For example,
+ /// `Result::Err(x)` and `Result::from_error(x)` are equivalent.
+ #[lang = "from_error"]
+ #[unstable(feature = "try_trait", issue = "42327")]
+ fn from_error(v: Self::Error) -> Self;
+
+ /// Wrap an OK value to construct the composite result. For example,
+ /// `Result::Ok(x)` and `Result::from_ok(x)` are equivalent.
+ #[lang = "from_ok"]
+ #[unstable(feature = "try_trait", issue = "42327")]
+ fn from_ok(v: Self::Ok) -> Self;
+}
+
+pub struct NoneError;
+
+
+pub enum Option<T> {
+ /// No value
+ None,
+ /// Some value `T`
+ Some(T),
+}
+
+impl<T> Option<T> {
+ pub fn ok_or<E>(self, err: E) -> Result<T, E> {
+ match self {
+ Some(ok) => Result::Ok(ok),
+ None => Result::Err(err)
+ }
+ }
+}
+
+use Option::*;
+
+#[unstable(feature = "try_trait", issue = "42327")]
+impl<T> Try for Option<T> {
+ type Ok = T;
+ type Error = NoneError;
+
+ #[inline]
+ fn into_result(self) -> Result<T, NoneError> {
+ self.ok_or(NoneError)
+ }
+
+ #[inline]
+ fn from_ok(v: T) -> Self {
+ Some(v)
+ }
+
+ #[inline]
+ fn from_error(_: NoneError) -> Self {
+ None
+ }
+}
+
+fn main() {
+ let _: Option<i32> = try { 15i32 };
+}
diff --git a/gcc/testsuite/rust/compile/tuple_mismatch.rs b/gcc/testsuite/rust/compile/tuple_mismatch.rs
index 828586b..1ff358b 100644
--- a/gcc/testsuite/rust/compile/tuple_mismatch.rs
+++ b/gcc/testsuite/rust/compile/tuple_mismatch.rs
@@ -3,6 +3,7 @@ fn main() {
let (_,) = (1, 2); // { dg-error "expected a tuple with 2 elements, found one with 1 element" }
let (_, _) = (1, 2, 3); // { dg-error "expected a tuple with 3 elements, found one with 2 elements" }
let (_, _) = (1,); // { dg-error "expected a tuple with 1 element, found one with 2 elements" }
+ let (_, .., _) = (1,); // { dg-error "expected a tuple with 1 element, found one with 2 elements" }
}
// The lhs and rhs sizes don't match, but we still resolve 'a' to be bool, we don't
diff --git a/gcc/testsuite/rust/compile/unify-errors1.rs b/gcc/testsuite/rust/compile/unify-errors1.rs
new file mode 100644
index 0000000..0fe95ef
--- /dev/null
+++ b/gcc/testsuite/rust/compile/unify-errors1.rs
@@ -0,0 +1,49 @@
+#[lang = "sized"]
+trait Sized {}
+
+#[lang = "copy"]
+trait Copy {}
+
+trait MyTrait {}
+
+struct Wrapper<T: MyTrait> {
+ value: T,
+}
+
+struct NotImpl;
+
+trait A {}
+trait B {}
+
+struct Wrapper2<T: A + B> {
+ value: T,
+}
+
+struct NotImpl2;
+
+impl A for NotImpl2 {}
+
+fn takes_tuple(x: (i32, bool)) {}
+
+fn requires_copy<T: Copy>(value: T) {}
+
+pub fn test() {
+ takes_tuple((1, 2));
+ // { dg-error "mismatched types, expected .bool. but got .<integer>. .E0308." "" { target *-*-* } .-1 }
+
+ takes_tuple((1, 2, 3));
+ // { dg-error "mismatched types, expected ..i32, bool.. but got ..<integer>, <integer>, <integer>.. .E0308." "" { target *-*-* } .-1 }
+
+ takes_tuple("hello");
+ // { dg-error "mismatched types, expected ..i32, bool.. but got .& str. .E0308." "" { target *-*-* } .-1 }
+
+ let x = &mut 5;
+ requires_copy(x);
+ // { dg-error "bounds not satisfied for &mut <integer> .Copy. is not satisfied .E0277." "" { target *-*-* } .-1 }
+
+ let _x = Wrapper { value: NotImpl };
+ // { dg-error "bounds not satisfied for NotImpl .MyTrait. is not satisfied .E0277." "" { target *-*-* } .-1 }
+
+ let _x = Wrapper2 { value: NotImpl2 };
+ // { dg-error "bounds not satisfied for NotImpl2 .B. is not satisfied .E0277." "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/use_1.rs b/gcc/testsuite/rust/compile/use_1.rs
index e8e2037..21ee3e1 100644
--- a/gcc/testsuite/rust/compile/use_1.rs
+++ b/gcc/testsuite/rust/compile/use_1.rs
@@ -1,4 +1,3 @@
-// { dg-additional-options "-frust-name-resolution-2.0" }
mod frob {}
use foo::bar::baz; // { dg-error "unresolved import .foo::bar::baz." }
diff --git a/gcc/testsuite/rust/compile/usize1.rs b/gcc/testsuite/rust/compile/usize1.rs
index 36cb99b..08f6c9c 100644
--- a/gcc/testsuite/rust/compile/usize1.rs
+++ b/gcc/testsuite/rust/compile/usize1.rs
@@ -1,5 +1,5 @@
fn main() {
let a = [1, 2, 3];
let b: u32 = 1;
- let c = a[b]; // { dg-error "the type ...integer..CAPACITY.. cannot be indexed by .u32." }
+ let c = a[b]; // { dg-error "the type ...integer.; 3.. cannot be indexed by .u32." }
}
diff --git a/gcc/testsuite/rust/compile/while_let1.rs b/gcc/testsuite/rust/compile/while_let1.rs
new file mode 100644
index 0000000..a3fa305
--- /dev/null
+++ b/gcc/testsuite/rust/compile/while_let1.rs
@@ -0,0 +1,109 @@
+// use self::Ordering::*;
+// use Ordering::*;
+
+// enum Ordering {
+// A,
+// B,
+// }
+
+// fn foo(_: Ordering) {}
+
+// fn main() {
+// let a = A;
+
+// foo(a);
+// foo(B);
+// }
+
+#[lang = "sized"]
+trait Sized {}
+
+enum Result<T, E> {
+ Ok(T),
+ Err(E),
+}
+
+pub trait Try {
+ /// The type of this value when viewed as successful.
+ #[unstable(feature = "try_trait", issue = "42327")]
+ type Ok;
+ /// The type of this value when viewed as failed.
+ #[unstable(feature = "try_trait", issue = "42327")]
+ type Error;
+
+ /// Applies the "?" operator. A return of `Ok(t)` means that the
+ /// execution should continue normally, and the result of `?` is the
+ /// value `t`. A return of `Err(e)` means that execution should branch
+ /// to the innermost enclosing `catch`, or return from the function.
+ ///
+ /// If an `Err(e)` result is returned, the value `e` will be "wrapped"
+ /// in the return type of the enclosing scope (which must itself implement
+ /// `Try`). Specifically, the value `X::from_error(From::from(e))`
+ /// is returned, where `X` is the return type of the enclosing function.
+ #[lang = "into_result"]
+ #[unstable(feature = "try_trait", issue = "42327")]
+ fn into_result(self) -> Result<Self::Ok, Self::Error>;
+
+ /// Wrap an error value to construct the composite result. For example,
+ /// `Result::Err(x)` and `Result::from_error(x)` are equivalent.
+ #[lang = "from_error"]
+ #[unstable(feature = "try_trait", issue = "42327")]
+ fn from_error(v: Self::Error) -> Self;
+
+ /// Wrap an OK value to construct the composite result. For example,
+ /// `Result::Ok(x)` and `Result::from_ok(x)` are equivalent.
+ #[lang = "from_ok"]
+ #[unstable(feature = "try_trait", issue = "42327")]
+ fn from_ok(v: Self::Ok) -> Self;
+}
+
+pub struct NoneError;
+
+pub enum Option<T> {
+ /// No value
+ None,
+ /// Some value `T`
+ Some(T),
+}
+
+impl<T> Option<T> {
+ pub fn ok_or<E>(self, err: E) -> Result<T, E> {
+ match self {
+ Some(ok) => Result::Ok(ok),
+ None => Result::Err(err),
+ }
+ }
+}
+
+use Option::*;
+
+#[unstable(feature = "try_trait", issue = "42327")]
+impl<T> Try for Option<T> {
+ type Ok = T;
+ type Error = NoneError;
+
+ #[inline]
+ fn into_result(self) -> Result<T, NoneError> {
+ self.ok_or(NoneError)
+ }
+
+ #[inline]
+ fn from_ok(v: T) -> Self {
+ Some(v)
+ }
+
+ #[inline]
+ fn from_error(_: NoneError) -> Self {
+ None
+ }
+}
+
+fn foo() -> Option<i32> {
+ Option::Some(15)
+}
+
+fn main() {
+ // let _: Option<i32> = try { 15i32 };
+
+ while let Option::Some(15) = foo() {}
+}
diff --git a/gcc/testsuite/rust/compile/while_let_without_label.rs b/gcc/testsuite/rust/compile/while_let_without_label.rs
new file mode 100644
index 0000000..e04e4b5
--- /dev/null
+++ b/gcc/testsuite/rust/compile/while_let_without_label.rs
@@ -0,0 +1,11 @@
+// { dg-additional-options "-frust-compile-until=lowering" }
+
+enum Foo {
+ A(i32),
+}
+
+fn main() {
+ let b = Foo::A(15);
+
+ while let Foo::A(x) = b {}
+}
diff --git a/gcc/testsuite/rust/compile/xfail/name_resolution21.rs b/gcc/testsuite/rust/compile/xfail/name_resolution21.rs
index df48d00..fc8e94b 100644
--- a/gcc/testsuite/rust/compile/xfail/name_resolution21.rs
+++ b/gcc/testsuite/rust/compile/xfail/name_resolution21.rs
@@ -1,5 +1,3 @@
-// { dg-additional-options "-frust-name-resolution-2.0" }
-
pub mod foo {
pub macro bar() {}
}
diff --git a/gcc/testsuite/rust/execute/black_box.rs b/gcc/testsuite/rust/execute/black_box.rs
index 7a9920e..58d10a3 100644
--- a/gcc/testsuite/rust/execute/black_box.rs
+++ b/gcc/testsuite/rust/execute/black_box.rs
@@ -21,10 +21,11 @@ pub fn black_box<T>(mut dummy: T) -> T {
dummy
}
-fn main() {
+fn main() -> i32 {
let dummy: i32 = 42;
let result = black_box(dummy);
unsafe {
printf("Value is: %i\n\0" as *const str as *const i8, result);
}
+ 0
}
diff --git a/gcc/testsuite/rust/execute/execute.exp b/gcc/testsuite/rust/execute/execute.exp
new file mode 100644
index 0000000..3754778
--- /dev/null
+++ b/gcc/testsuite/rust/execute/execute.exp
@@ -0,0 +1,33 @@
+# Copyright (C) 2021-2025 Free Software Foundation, Inc.
+
+# This program 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 of the License, or
+# (at your option) any later version.
+#
+# This program 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/>.
+
+# Execute tests.
+
+# Load support procs.
+load_lib rust-dg.exp
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+set saved-dg-do-what-default ${dg-do-what-default}
+
+set dg-do-what-default "run"
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.rs]] "" ""
+set dg-do-what-default ${saved-dg-do-what-default}
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/rust/execute/inline_asm_inout_ident.rs b/gcc/testsuite/rust/execute/inline_asm_inout_ident.rs
new file mode 100644
index 0000000..b0a3d25
--- /dev/null
+++ b/gcc/testsuite/rust/execute/inline_asm_inout_ident.rs
@@ -0,0 +1,23 @@
+/* { dg-output "Value is: 5\r*\n" } */
+#![feature(rustc_attrs)]
+
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+ () => {};
+}
+
+fn main() -> i32 {
+ let x: i32;
+ // `inout` can also move values to different places
+ unsafe {
+ asm!("inc {}", inout(reg) 4u64=>x);
+ }
+ unsafe {
+ printf("Value is: %i\n\0" as *const str as *const i8, x);
+ }
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/inline_asm_inout_var.rs b/gcc/testsuite/rust/execute/inline_asm_inout_var.rs
new file mode 100644
index 0000000..ff101b8
--- /dev/null
+++ b/gcc/testsuite/rust/execute/inline_asm_inout_var.rs
@@ -0,0 +1,24 @@
+/* { dg-output "Value is: 5\r*\n" } */
+#![feature(rustc_attrs)]
+
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+ () => {};
+}
+
+fn main() -> i32 {
+ let y: i32 = 4;
+ let x: i32;
+ // `inout` can also move values to different places
+ unsafe {
+ asm!("inc {}", inout(reg) y=>x);
+ }
+ unsafe {
+ printf("Value is: %i\n\0" as *const str as *const i8, x);
+ }
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/basic_partial_ord1.rs b/gcc/testsuite/rust/execute/torture/basic_partial_ord1.rs
new file mode 100644
index 0000000..0431629
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/basic_partial_ord1.rs
@@ -0,0 +1,189 @@
+/* { dg-output "less\r*" }*/
+mod core {
+ mod option {
+ pub enum Option<T> {
+ None,
+ Some(T),
+ }
+ }
+
+ mod marker {
+ #[lang = "phantom_data"]
+ pub struct PhantomData<T: ?Sized>;
+
+ #[lang = "structural_peq"]
+ pub trait StructuralPartialEq {}
+
+ #[lang = "structural_teq"]
+ pub trait StructuralEq {}
+
+ #[lang = "sized"]
+ pub trait Sized {}
+ }
+
+ mod cmp {
+ use super::marker::Sized;
+ use super::option::Option;
+
+ pub enum Ordering {
+ Less = -1,
+ Equal = 0,
+ Greater = 1,
+ }
+
+ #[lang = "eq"]
+ pub trait PartialEq<Rhs: ?Sized = Self> {
+ fn eq(&self, other: &Rhs) -> bool;
+
+ fn ne(&self, other: &Rhs) -> bool {
+ !self.eq(other)
+ }
+ }
+
+ pub trait Eq: PartialEq<Self> {
+ fn assert_receiver_is_total_eq(&self) {}
+ }
+
+ #[lang = "partial_ord"]
+ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
+ fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+
+ fn lt(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Less) => true,
+ _ => false,
+ }
+ }
+
+ fn le(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Less) | Option::Some(Ordering::Equal) => true,
+ _ => false,
+ }
+ }
+
+ fn gt(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Greater) => true,
+ _ => false,
+ }
+ }
+
+ fn ge(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Greater) | Option::Some(Ordering::Equal) => true,
+ _ => false,
+ }
+ }
+ }
+
+ pub trait Ord: Eq + PartialOrd<Self> {
+ fn cmp(&self, other: &Self) -> Ordering;
+ }
+ }
+}
+
+use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
+use core::option::Option;
+
+// Needed impls for primitives
+impl PartialEq for i32 {
+ fn eq(&self, other: &Self) -> bool {
+ *self == *other
+ }
+}
+
+impl PartialOrd for i32 {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ if *self < *other {
+ Option::Some(Ordering::Less)
+ } else if *self > *other {
+ Option::Some(Ordering::Greater)
+ } else {
+ Option::Some(Ordering::Equal)
+ }
+ }
+
+ fn lt(&self, other: &Self) -> bool {
+ *self < *other
+ }
+ fn le(&self, other: &Self) -> bool {
+ *self <= *other
+ }
+ fn ge(&self, other: &Self) -> bool {
+ *self >= *other
+ }
+ fn gt(&self, other: &Self) -> bool {
+ *self > *other
+ }
+}
+
+impl Eq for i32 {}
+impl Ord for i32 {
+ fn cmp(&self, other: &Self) -> Ordering {
+ if *self < *other {
+ Ordering::Less
+ } else if *self > *other {
+ Ordering::Greater
+ } else {
+ Ordering::Equal
+ }
+ }
+}
+
+// Manual impl for struct Bar
+struct Bar {
+ a: i32,
+ b: i32,
+}
+
+impl PartialEq for Bar {
+ fn eq(&self, other: &Self) -> bool {
+ self.a.eq(&other.a) && self.b.eq(&other.b)
+ }
+}
+
+impl Eq for Bar {}
+
+impl PartialOrd for Bar {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ match self.a.partial_cmp(&other.a) {
+ Option::Some(Ordering::Equal) => self.b.partial_cmp(&other.b),
+ ord => ord,
+ }
+ }
+}
+
+impl Ord for Bar {
+ fn cmp(&self, other: &Self) -> Ordering {
+ match self.a.cmp(&other.a) {
+ Ordering::Equal => self.b.cmp(&other.b),
+ ord => ord,
+ }
+ }
+}
+
+// External print shim
+extern "C" {
+ fn puts(s: *const i8);
+}
+
+fn print(s: &str) {
+ unsafe {
+ puts(s as *const str as *const i8);
+ }
+}
+
+fn main() -> i32 {
+ let x = Bar { a: 1, b: 2 };
+ let y = Bar { a: 1, b: 3 };
+
+ match x.partial_cmp(&y) {
+ Option::Some(Ordering::Less) => print("less"),
+ Option::Some(Ordering::Greater) => print("greater"),
+ Option::Some(Ordering::Equal) => print("equal"),
+ _ => print("none"),
+ }
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/basic_partial_ord2.rs b/gcc/testsuite/rust/execute/torture/basic_partial_ord2.rs
new file mode 100644
index 0000000..b6a9695
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/basic_partial_ord2.rs
@@ -0,0 +1,197 @@
+/* { dg-output "<><=>=\r*" } */
+/* { dg-options "-w" } */
+mod core {
+ mod option {
+ pub enum Option<T> {
+ None,
+ Some(T),
+ }
+ }
+
+ mod marker {
+ #[lang = "phantom_data"]
+ pub struct PhantomData<T: ?Sized>;
+
+ #[lang = "structural_peq"]
+ pub trait StructuralPartialEq {}
+
+ #[lang = "structural_teq"]
+ pub trait StructuralEq {}
+
+ #[lang = "sized"]
+ pub trait Sized {}
+ }
+
+ mod cmp {
+ use super::marker::Sized;
+ use super::option::Option;
+
+ pub enum Ordering {
+ Less = -1,
+ Equal = 0,
+ Greater = 1,
+ }
+
+ #[lang = "eq"]
+ pub trait PartialEq<Rhs: ?Sized = Self> {
+ fn eq(&self, other: &Rhs) -> bool;
+
+ fn ne(&self, other: &Rhs) -> bool {
+ !self.eq(other)
+ }
+ }
+
+ pub trait Eq: PartialEq<Self> {
+ fn assert_receiver_is_total_eq(&self) {}
+ }
+
+ #[lang = "partial_ord"]
+ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
+ fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+
+ fn lt(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Less) => true,
+ _ => false,
+ }
+ }
+
+ fn le(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Less) | Option::Some(Ordering::Equal) => true,
+ _ => false,
+ }
+ }
+
+ fn gt(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Greater) => true,
+ _ => false,
+ }
+ }
+
+ fn ge(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Greater) | Option::Some(Ordering::Equal) => true,
+ _ => false,
+ }
+ }
+ }
+
+ pub trait Ord: Eq + PartialOrd<Self> {
+ fn cmp(&self, other: &Self) -> Ordering;
+ }
+ }
+}
+
+use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
+use core::option::Option;
+
+// Needed impls for primitives
+impl PartialEq for i32 {
+ fn eq(&self, other: &Self) -> bool {
+ *self == *other
+ }
+}
+
+impl PartialOrd for i32 {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ if *self < *other {
+ Option::Some(Ordering::Less)
+ } else if *self > *other {
+ Option::Some(Ordering::Greater)
+ } else {
+ Option::Some(Ordering::Equal)
+ }
+ }
+
+ fn lt(&self, other: &Self) -> bool {
+ *self < *other
+ }
+ fn le(&self, other: &Self) -> bool {
+ *self <= *other
+ }
+ fn ge(&self, other: &Self) -> bool {
+ *self >= *other
+ }
+ fn gt(&self, other: &Self) -> bool {
+ *self > *other
+ }
+}
+
+impl Eq for i32 {}
+impl Ord for i32 {
+ fn cmp(&self, other: &Self) -> Ordering {
+ if *self < *other {
+ Ordering::Less
+ } else if *self > *other {
+ Ordering::Greater
+ } else {
+ Ordering::Equal
+ }
+ }
+}
+
+// Manual impl for struct Bar
+struct Bar {
+ a: i32,
+ b: i32,
+}
+
+impl PartialEq for Bar {
+ fn eq(&self, other: &Self) -> bool {
+ self.a.eq(&other.a) && self.b.eq(&other.b)
+ }
+}
+
+impl Eq for Bar {}
+
+impl PartialOrd for Bar {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ match self.a.partial_cmp(&other.a) {
+ Option::Some(Ordering::Equal) => self.b.partial_cmp(&other.b),
+ ord => ord,
+ }
+ }
+}
+
+impl Ord for Bar {
+ fn cmp(&self, other: &Self) -> Ordering {
+ match self.a.cmp(&other.a) {
+ Ordering::Equal => self.b.cmp(&other.b),
+ ord => ord,
+ }
+ }
+}
+
+// External print shim
+extern "C" {
+ fn printf(s: *const i8);
+}
+
+fn print(s: &str) {
+ unsafe {
+ printf(s as *const str as *const i8);
+ }
+}
+
+fn main() -> i32 {
+ let a = Bar { a: 1, b: 2 };
+ let b = Bar { a: 1, b: 3 };
+ let c = Bar { a: 1, b: 2 };
+
+ if a < b {
+ print("<");
+ }
+ if b > a {
+ print(">");
+ }
+ if a <= c {
+ print("<=");
+ }
+ if b >= c {
+ print(">=");
+ }
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/builtin_abort.rs b/gcc/testsuite/rust/execute/torture/builtin_abort.rs
index 9f2d8c2..8c8259a 100644
--- a/gcc/testsuite/rust/execute/torture/builtin_abort.rs
+++ b/gcc/testsuite/rust/execute/torture/builtin_abort.rs
@@ -9,6 +9,6 @@ mod intrinsics {
}
pub fn main () -> i32 {
- abort();
+ intrinsics::abort();
0
}
diff --git a/gcc/testsuite/rust/execute/torture/const-generics-1.rs b/gcc/testsuite/rust/execute/torture/const-generics-1.rs
new file mode 100644
index 0000000..dbb7afe
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/const-generics-1.rs
@@ -0,0 +1,24 @@
+#[lang = "sized"]
+trait Sized {}
+
+struct Foo<const N: usize>;
+
+impl Foo<1> {
+ fn call(&self) -> i32 {
+ 10
+ }
+}
+
+impl Foo<2> {
+ fn call(&self) -> i32 {
+ 20
+ }
+}
+
+fn main() -> i32 {
+ let a = Foo::<1> {};
+ let b = Foo::<2> {};
+ let aa = a.call();
+ let bb = b.call();
+ bb - aa - 10
+}
diff --git a/gcc/testsuite/rust/execute/torture/const_block1.rs b/gcc/testsuite/rust/execute/torture/const_block1.rs
new file mode 100644
index 0000000..eaf3432
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/const_block1.rs
@@ -0,0 +1,9 @@
+const X: i32 = const {
+ let a = 15;
+ let b = 14;
+ a + b
+};
+
+fn main() -> i32 {
+ X - 29
+}
diff --git a/gcc/testsuite/rust/execute/torture/derive-partialeq2.rs b/gcc/testsuite/rust/execute/torture/derive-partialeq2.rs
new file mode 100644
index 0000000..e316017
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/derive-partialeq2.rs
@@ -0,0 +1,80 @@
+// { dg-output "true\r*\nfalse\r*\nfalse\r*\nfalse\r*\nfalse\r*\n" }
+
+#![feature(intrinsics)]
+
+pub mod core {
+ pub mod intrinsics {
+ #[lang = "discriminant_kind"]
+ pub trait DiscriminantKind {
+ #[lang = "discriminant_type"]
+ type Discriminant;
+ }
+
+ extern "rust-intrinsic" {
+ pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
+ }
+ }
+}
+
+#[lang = "sized"]
+trait Sized {}
+
+#[lang = "copy"]
+trait Copy {}
+
+#[lang = "structural_peq"]
+trait StructuralPartialEq {}
+
+#[lang = "eq"]
+pub trait PartialEq<Rhs: ?Sized = Self> {
+ /// This method tests for `self` and `other` values to be equal, and is used
+ /// by `==`.
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn eq(&self, other: &Rhs) -> bool;
+
+ /// This method tests for `!=`.
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn ne(&self, other: &Rhs) -> bool {
+ !self.eq(other)
+ }
+}
+
+#[derive(PartialEq)]
+enum Foo {
+ A { a: i32, b: i32 },
+ B(i32, i32),
+ C,
+}
+
+extern "C" {
+ fn puts(s: *const i8);
+}
+
+fn print(b: bool) {
+ if b {
+ unsafe { puts("true\0" as *const str as *const i8) }
+ } else {
+ unsafe { puts("false\0" as *const str as *const i8) }
+ }
+}
+
+fn main() -> i32 {
+ let x = Foo::A { a: 15, b: 14 };
+
+ let b1 = x == Foo::A { a: 15, b: 14 };
+ let b12 = x == Foo::A { a: 15, b: 19 };
+ let b13 = x == Foo::A { a: 19, b: 14 };
+ let b2 = x == Foo::B(15, 14);
+ let b3 = x == Foo::C;
+
+ print(b1);
+ print(b12);
+ print(b13);
+ print(b2);
+ print(b3);
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/for-loop1.rs b/gcc/testsuite/rust/execute/torture/for-loop1.rs
index 5a6a70c..3342189 100644
--- a/gcc/testsuite/rust/execute/torture/for-loop1.rs
+++ b/gcc/testsuite/rust/execute/torture/for-loop1.rs
@@ -102,30 +102,30 @@ mod ptr {
#[lang = "const_ptr"]
impl<T> *const T {
pub unsafe fn offset(self, count: isize) -> *const T {
- intrinsics::offset(self, count)
+ crate::intrinsics::offset(self, count)
}
}
#[lang = "mut_ptr"]
impl<T> *mut T {
pub unsafe fn offset(self, count: isize) -> *mut T {
- intrinsics::offset(self, count) as *mut T
+ crate::intrinsics::offset(self, count) as *mut T
}
}
pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
let x = x as *mut u8;
let y = y as *mut u8;
- let len = mem::size_of::<T>() * count;
+ let len = crate::mem::size_of::<T>() * count;
swap_nonoverlapping_bytes(x, y, len)
}
pub unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) {
// For types smaller than the block optimization below,
// just swap directly to avoid pessimizing codegen.
- if mem::size_of::<T>() < 32 {
+ if crate::mem::size_of::<T>() < 32 {
let z = read(x);
- intrinsics::copy_nonoverlapping(y, x, 1);
+ crate::intrinsics::copy_nonoverlapping(y, x, 1);
write(y, z);
} else {
swap_nonoverlapping(x, y, 1);
@@ -133,12 +133,12 @@ mod ptr {
}
pub unsafe fn write<T>(dst: *mut T, src: T) {
- intrinsics::move_val_init(&mut *dst, src)
+ crate::intrinsics::move_val_init(&mut *dst, src)
}
pub unsafe fn read<T>(src: *const T) -> T {
- let mut tmp: T = mem::uninitialized();
- intrinsics::copy_nonoverlapping(src, &mut tmp, 1);
+ let mut tmp: T = crate::mem::uninitialized();
+ crate::intrinsics::copy_nonoverlapping(src, &mut tmp, 1);
tmp
}
@@ -146,7 +146,7 @@ mod ptr {
struct Block(u64, u64, u64, u64);
struct UnalignedBlock(u64, u64, u64, u64);
- let block_size = mem::size_of::<Block>();
+ let block_size = crate::mem::size_of::<Block>();
// Loop through x & y, copying them `Block` at a time
// The optimizer should unroll the loop fully for most types
@@ -155,31 +155,31 @@ mod ptr {
while i + block_size <= len {
// Create some uninitialized memory as scratch space
// Declaring `t` here avoids aligning the stack when this loop is unused
- let mut t: Block = mem::uninitialized();
+ let mut t: Block = crate::mem::uninitialized();
let t = &mut t as *mut _ as *mut u8;
let x = x.offset(i as isize);
let y = y.offset(i as isize);
// Swap a block of bytes of x & y, using t as a temporary buffer
// This should be optimized into efficient SIMD operations where available
- intrinsics::copy_nonoverlapping(x, t, block_size);
- intrinsics::copy_nonoverlapping(y, x, block_size);
- intrinsics::copy_nonoverlapping(t, y, block_size);
+ crate::intrinsics::copy_nonoverlapping(x, t, block_size);
+ crate::intrinsics::copy_nonoverlapping(y, x, block_size);
+ crate::intrinsics::copy_nonoverlapping(t, y, block_size);
i += block_size;
}
if i < len {
// Swap any remaining bytes
- let mut t: UnalignedBlock = mem::uninitialized();
+ let mut t: UnalignedBlock = crate::mem::uninitialized();
let rem = len - i;
let t = &mut t as *mut _ as *mut u8;
let x = x.offset(i as isize);
let y = y.offset(i as isize);
- intrinsics::copy_nonoverlapping(x, t, rem);
- intrinsics::copy_nonoverlapping(y, x, rem);
- intrinsics::copy_nonoverlapping(t, y, rem);
+ crate::intrinsics::copy_nonoverlapping(x, t, rem);
+ crate::intrinsics::copy_nonoverlapping(y, x, rem);
+ crate::intrinsics::copy_nonoverlapping(t, y, rem);
}
}
}
@@ -194,7 +194,7 @@ mod mem {
pub fn swap<T>(x: &mut T, y: &mut T) {
unsafe {
- ptr::swap_nonoverlapping_one(x, y);
+ crate::ptr::swap_nonoverlapping_one(x, y);
}
}
@@ -204,7 +204,7 @@ mod mem {
}
pub unsafe fn uninitialized<T>() -> T {
- intrinsics::uninit()
+ crate::intrinsics::uninit()
}
}
diff --git a/gcc/testsuite/rust/execute/torture/for-loop2.rs b/gcc/testsuite/rust/execute/torture/for-loop2.rs
index 5ba2cd1..4f5dfe1 100644
--- a/gcc/testsuite/rust/execute/torture/for-loop2.rs
+++ b/gcc/testsuite/rust/execute/torture/for-loop2.rs
@@ -101,30 +101,30 @@ mod ptr {
#[lang = "const_ptr"]
impl<T> *const T {
pub unsafe fn offset(self, count: isize) -> *const T {
- intrinsics::offset(self, count)
+ crate::intrinsics::offset(self, count)
}
}
#[lang = "mut_ptr"]
impl<T> *mut T {
pub unsafe fn offset(self, count: isize) -> *mut T {
- intrinsics::offset(self, count) as *mut T
+ crate::intrinsics::offset(self, count) as *mut T
}
}
pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
let x = x as *mut u8;
let y = y as *mut u8;
- let len = mem::size_of::<T>() * count;
+ let len = crate::mem::size_of::<T>() * count;
swap_nonoverlapping_bytes(x, y, len)
}
pub unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) {
// For types smaller than the block optimization below,
// just swap directly to avoid pessimizing codegen.
- if mem::size_of::<T>() < 32 {
+ if crate::mem::size_of::<T>() < 32 {
let z = read(x);
- intrinsics::copy_nonoverlapping(y, x, 1);
+ crate::intrinsics::copy_nonoverlapping(y, x, 1);
write(y, z);
} else {
swap_nonoverlapping(x, y, 1);
@@ -132,12 +132,12 @@ mod ptr {
}
pub unsafe fn write<T>(dst: *mut T, src: T) {
- intrinsics::move_val_init(&mut *dst, src)
+ crate::intrinsics::move_val_init(&mut *dst, src)
}
pub unsafe fn read<T>(src: *const T) -> T {
- let mut tmp: T = mem::uninitialized();
- intrinsics::copy_nonoverlapping(src, &mut tmp, 1);
+ let mut tmp: T = crate::mem::uninitialized();
+ crate::intrinsics::copy_nonoverlapping(src, &mut tmp, 1);
tmp
}
@@ -145,7 +145,7 @@ mod ptr {
struct Block(u64, u64, u64, u64);
struct UnalignedBlock(u64, u64, u64, u64);
- let block_size = mem::size_of::<Block>();
+ let block_size = crate::mem::size_of::<Block>();
// Loop through x & y, copying them `Block` at a time
// The optimizer should unroll the loop fully for most types
@@ -154,31 +154,31 @@ mod ptr {
while i + block_size <= len {
// Create some uninitialized memory as scratch space
// Declaring `t` here avoids aligning the stack when this loop is unused
- let mut t: Block = mem::uninitialized();
+ let mut t: Block = crate::mem::uninitialized();
let t = &mut t as *mut _ as *mut u8;
let x = x.offset(i as isize);
let y = y.offset(i as isize);
// Swap a block of bytes of x & y, using t as a temporary buffer
// This should be optimized into efficient SIMD operations where available
- intrinsics::copy_nonoverlapping(x, t, block_size);
- intrinsics::copy_nonoverlapping(y, x, block_size);
- intrinsics::copy_nonoverlapping(t, y, block_size);
+ crate::intrinsics::copy_nonoverlapping(x, t, block_size);
+ crate::intrinsics::copy_nonoverlapping(y, x, block_size);
+ crate::intrinsics::copy_nonoverlapping(t, y, block_size);
i += block_size;
}
if i < len {
// Swap any remaining bytes
- let mut t: UnalignedBlock = mem::uninitialized();
+ let mut t: UnalignedBlock = crate::mem::uninitialized();
let rem = len - i;
let t = &mut t as *mut _ as *mut u8;
let x = x.offset(i as isize);
let y = y.offset(i as isize);
- intrinsics::copy_nonoverlapping(x, t, rem);
- intrinsics::copy_nonoverlapping(y, x, rem);
- intrinsics::copy_nonoverlapping(t, y, rem);
+ crate::intrinsics::copy_nonoverlapping(x, t, rem);
+ crate::intrinsics::copy_nonoverlapping(y, x, rem);
+ crate::intrinsics::copy_nonoverlapping(t, y, rem);
}
}
}
@@ -193,7 +193,7 @@ mod mem {
pub fn swap<T>(x: &mut T, y: &mut T) {
unsafe {
- ptr::swap_nonoverlapping_one(x, y);
+ crate::ptr::swap_nonoverlapping_one(x, y);
}
}
@@ -203,7 +203,7 @@ mod mem {
}
pub unsafe fn uninitialized<T>() -> T {
- intrinsics::uninit()
+ crate::intrinsics::uninit()
}
}
diff --git a/gcc/testsuite/rust/execute/torture/impl_desugar-2.rs b/gcc/testsuite/rust/execute/torture/impl_desugar-2.rs
new file mode 100644
index 0000000..c73ea34
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/impl_desugar-2.rs
@@ -0,0 +1,32 @@
+#[lang = "sized"]
+trait Sized {}
+
+macro_rules! impl_foo {
+ () => { impl Foo }
+}
+
+pub trait Foo {}
+
+pub trait Bar {
+ type Baz;
+}
+
+struct MyBaz; // { dg-warning "struct is never constructed" }
+impl Foo for MyBaz {}
+
+struct MyBar;
+
+impl Bar for MyBar {
+ type Baz = MyBaz;
+}
+
+pub fn foo(_value: impl Bar<Baz = impl_foo!()>) -> i32 {
+ 15
+}
+
+fn main() -> i32 {
+ let bar = MyBar;
+ let result: i32 = foo(bar);
+
+ result - 15
+}
diff --git a/gcc/testsuite/rust/execute/torture/impl_desugar.rs b/gcc/testsuite/rust/execute/torture/impl_desugar.rs
new file mode 100644
index 0000000..22d3951
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/impl_desugar.rs
@@ -0,0 +1,32 @@
+#[lang = "sized"]
+trait Sized {}
+
+pub trait Foo {}
+
+pub trait Bar {
+ type Baz;
+}
+
+struct MyBaz; // { dg-warning "struct is never constructed" }
+impl Foo for MyBaz {}
+
+struct MyBar;
+
+impl Bar for MyBar {
+ type Baz = MyBaz;
+}
+
+pub fn foo<T, U>(_value: T) -> i32
+where
+ T: Bar<Baz = U>,
+ U: Foo,
+{
+ 15
+}
+
+fn main() -> i32 {
+ let bar = MyBar;
+ let result: i32 = foo::<MyBar, MyBaz>(bar);
+
+ result - 15
+}
diff --git a/gcc/testsuite/rust/execute/torture/impl_rpit1.rs b/gcc/testsuite/rust/execute/torture/impl_rpit1.rs
new file mode 100644
index 0000000..8ce5f21
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/impl_rpit1.rs
@@ -0,0 +1,28 @@
+#[lang = "sized"]
+trait Sized {}
+
+trait Foo {
+ fn id(&self) -> i32;
+}
+
+struct Thing(i32);
+
+impl Foo for Thing {
+ fn id(&self) -> i32 {
+ self.0
+ }
+}
+
+fn make_thing(a: i32) -> impl Foo {
+ Thing(a)
+}
+
+fn use_foo(f: impl Foo) -> i32 {
+ f.id()
+}
+
+fn main() -> i32 {
+ let value = make_thing(42);
+ let val = use_foo(value);
+ val - 42
+}
diff --git a/gcc/testsuite/rust/execute/torture/impl_rpit2.rs b/gcc/testsuite/rust/execute/torture/impl_rpit2.rs
new file mode 100644
index 0000000..f7cbbb6
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/impl_rpit2.rs
@@ -0,0 +1,36 @@
+#[lang = "sized"]
+trait Sized {}
+
+trait Foo {
+ fn id(&self) -> i32;
+}
+
+struct Thing(i32);
+
+impl Thing {
+ fn double(&self) -> i32 {
+ // { dg-warning "associated function is never used: .double." "" { target *-*-* } .-1 }
+ self.0 * 2
+ }
+}
+
+impl Foo for Thing {
+ fn id(&self) -> i32 {
+ self.0
+ }
+}
+
+fn make_thing(a: i32) -> impl Foo {
+ Thing(a)
+}
+
+fn use_foo(f: impl Foo) -> i32 {
+ f.id()
+}
+
+fn main() -> i32 {
+ let value = make_thing(21);
+ let id = use_foo(value);
+
+ id - 21
+}
diff --git a/gcc/testsuite/rust/execute/torture/impl_rpit3.rs b/gcc/testsuite/rust/execute/torture/impl_rpit3.rs
new file mode 100644
index 0000000..dd68eb2
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/impl_rpit3.rs
@@ -0,0 +1,25 @@
+#[lang = "sized"]
+trait Sized {}
+
+trait Foo {
+ fn id(&self) -> i32;
+}
+
+struct Thing(i32);
+
+impl Foo for Thing {
+ fn id(&self) -> i32 {
+ self.0
+ }
+}
+
+fn make_thing() -> impl Foo {
+ Thing(99)
+}
+
+fn main() -> i32 {
+ let v = make_thing();
+ let r = &v;
+ let val = r.id();
+ val - 99
+}
diff --git a/gcc/testsuite/rust/execute/torture/impl_trait1.rs b/gcc/testsuite/rust/execute/torture/impl_trait1.rs
new file mode 100644
index 0000000..33a5c8c
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/impl_trait1.rs
@@ -0,0 +1,31 @@
+#[lang = "sized"]
+trait Sized {}
+
+pub trait Value {
+ fn get(&self) -> i32;
+}
+
+struct Foo(i32);
+struct Bar(i32);
+
+impl Value for Foo {
+ fn get(&self) -> i32 {
+ self.0
+ }
+}
+impl Value for Bar {
+ fn get(&self) -> i32 {
+ self.0
+ }
+}
+
+pub fn foo(a: impl Value, b: impl Value) -> i32 {
+ a.get() + b.get()
+}
+
+fn main() -> i32 {
+ let a = Foo(1);
+ let b = Bar(2);
+
+ foo(a, b) - 3
+}
diff --git a/gcc/testsuite/rust/execute/torture/impl_trait2.rs b/gcc/testsuite/rust/execute/torture/impl_trait2.rs
new file mode 100644
index 0000000..29f393d
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/impl_trait2.rs
@@ -0,0 +1,31 @@
+#[lang = "sized"]
+trait Sized {}
+
+pub trait Value {
+ fn get(&self) -> i32;
+}
+
+struct Foo(i32);
+struct Bar(i32);
+
+impl Value for Foo {
+ fn get(&self) -> i32 {
+ self.0
+ }
+}
+impl Value for Bar {
+ fn get(&self) -> i32 {
+ self.0
+ }
+}
+
+pub fn foo(a: &impl Value, b: &impl Value) -> i32 {
+ a.get() + b.get()
+}
+
+fn main() -> i32 {
+ let a = Foo(1);
+ let b = Bar(2);
+
+ foo(&a, &b) - 3
+}
diff --git a/gcc/testsuite/rust/execute/torture/impl_trait3.rs b/gcc/testsuite/rust/execute/torture/impl_trait3.rs
new file mode 100644
index 0000000..c1cec07
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/impl_trait3.rs
@@ -0,0 +1,45 @@
+/* { dg-output "Hello from Message\r*\n" } */
+#[lang = "sized"]
+pub trait Sized {}
+
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+trait Speak {
+ fn speak(&self) -> &'static str;
+}
+
+trait Printer {
+ fn print(&self, input: impl Speak);
+}
+
+struct Console;
+
+impl Printer for Console {
+ fn print(&self, input: impl Speak) {
+ unsafe {
+ let a = input.speak();
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+ }
+}
+
+struct Message(&'static str);
+
+impl Speak for Message {
+ fn speak(&self) -> &'static str {
+ self.0
+ }
+}
+
+fn main() -> i32 {
+ let c = Console;
+ let msg = Message("Hello from Message\n");
+ c.print(msg);
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/impl_trait4.rs b/gcc/testsuite/rust/execute/torture/impl_trait4.rs
new file mode 100644
index 0000000..67d0095
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/impl_trait4.rs
@@ -0,0 +1,31 @@
+#[lang = "sized"]
+trait Sized {}
+
+trait Foo {
+ fn id(&self) -> i32;
+}
+
+struct A(i32);
+struct B(i32);
+
+impl Foo for A {
+ fn id(&self) -> i32 {
+ self.0
+ }
+}
+
+impl Foo for B {
+ fn id(&self) -> i32 {
+ self.0
+ }
+}
+
+fn takes_tuple(pair: (impl Foo, impl Foo)) -> i32 {
+ pair.0.id() + pair.1.id()
+}
+
+fn main() -> i32 {
+ let a = A(1);
+ let b = B(2);
+ takes_tuple((a, b)) - 3
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-1481.rs b/gcc/testsuite/rust/execute/torture/issue-1481.rs
new file mode 100644
index 0000000..2ff78d9
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-1481.rs
@@ -0,0 +1,35 @@
+/* { dg-output "called Foo::print\\(\\)\r*" } */
+/* { dg-options "-w" } */
+
+#[lang = "sized"]
+trait Sized {}
+
+trait Printable {
+ fn print(&self);
+}
+
+struct Foo;
+
+impl Printable for Foo {
+ fn print(&self) {
+ // Simulate output
+ unsafe {
+ puts("called Foo::print()\0" as *const _ as *const i8);
+ }
+ }
+}
+
+fn get_printable() -> impl Printable {
+ Foo
+}
+
+extern "C" {
+ fn puts(s: *const i8);
+}
+
+fn main() -> i32 {
+ let p = get_printable();
+ p.print();
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-1482.rs b/gcc/testsuite/rust/execute/torture/issue-1482.rs
new file mode 100644
index 0000000..ed8dc81
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-1482.rs
@@ -0,0 +1,23 @@
+#[lang = "sized"]
+trait Sized {}
+
+#[lang = "fn_once"]
+pub trait FnOnce<Args> {
+ #[lang = "fn_once_output"]
+ type Output;
+
+ extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+}
+
+fn takes_fn(a: i32, f: impl FnOnce(i32) -> i32) -> i32 {
+ f(a)
+}
+
+pub fn main() -> i32 {
+ let capture = 2;
+ let a = |i: i32| {
+ let b = i + capture;
+ b
+ };
+ takes_fn(1, a) - 3
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-2005.rs b/gcc/testsuite/rust/execute/torture/issue-2005.rs
new file mode 100644
index 0000000..87edb95
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-2005.rs
@@ -0,0 +1,465 @@
+// { dg-additional-options "-w" }
+/* { dg-output "WORKS\r?\n" } */
+#![feature(intrinsics)]
+
+mod core {
+ mod option {
+ // #[rustc_diagnostic_item = "option_type"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub enum Option<T> {
+ /// No value
+ #[lang = "None"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ None,
+ /// Some value `T`
+ #[lang = "Some"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Some(#[stable(feature = "rust1", since = "1.0.0")] T),
+ }
+ }
+
+ mod marker {
+ #[lang = "phantom_data"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub struct PhantomData<T: ?Sized>;
+
+ #[unstable(feature = "structural_match", issue = "31434")]
+ // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(PartialEq)]`")]
+ #[lang = "structural_peq"]
+ pub trait StructuralPartialEq {
+ // Empty.
+ }
+
+ #[unstable(feature = "structural_match", issue = "31434")]
+ // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(Eq)]`")]
+ #[lang = "structural_teq"]
+ pub trait StructuralEq {
+ // Empty.
+ }
+
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[lang = "sized"]
+ // #[rustc_on_unimplemented(
+ // message = "the size for values of type `{Self}` cannot be known at compilation time",
+ // label = "doesn't have a size known at compile-time"
+ // )]
+ // #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
+ // #[rustc_specialization_trait]
+ pub trait Sized {
+ // Empty.
+ }
+ }
+
+ mod cmp {
+ use super::marker::Sized;
+ use super::option::Option;
+
+ // #[derive(Clone, Copy, PartialEq, Debug, Hash)]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub enum Ordering {
+ /// An ordering where a compared value is less than another.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Less = -1,
+ /// An ordering where a compared value is equal to another.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Equal = 0,
+ /// An ordering where a compared value is greater than another.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Greater = 1,
+ }
+
+ #[lang = "eq"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[doc(alias = "==")]
+ #[doc(alias = "!=")]
+ // #[rustc_on_unimplemented(
+ // message = "can't compare `{Self}` with `{Rhs}`",
+ // label = "no implementation for `{Self} == {Rhs}`"
+ // )]
+ pub trait PartialEq<Rhs: ?Sized = Self> {
+ /// This method tests for `self` and `other` values to be equal, and is used
+ /// by `==`.
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn eq(&self, other: &Rhs) -> bool;
+
+ fn ne(&self, other: &Rhs) -> bool {
+ !self.eq(other)
+ }
+ }
+
+ #[doc(alias = "==")]
+ #[doc(alias = "!=")]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub trait Eq: PartialEq<Self> {
+ // this method is used solely by #[deriving] to assert
+ // that every component of a type implements #[deriving]
+ // itself, the current deriving infrastructure means doing this
+ // assertion without using a method on this trait is nearly
+ // impossible.
+ //
+ // This should never be implemented by hand.
+ #[doc(hidden)]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn assert_receiver_is_total_eq(&self) {}
+ }
+
+ #[lang = "partial_ord"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[doc(alias = ">")]
+ #[doc(alias = "<")]
+ #[doc(alias = "<=")]
+ #[doc(alias = ">=")]
+ // #[rustc_on_unimplemented(
+ // message = "can't compare `{Self}` with `{Rhs}`",
+ // label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`"
+ // )]
+ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
+ /// This method returns an ordering between `self` and `other` values if one exists.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::cmp::Ordering;
+ ///
+ /// let result = 1.0.partial_cmp(&2.0);
+ /// assert_eq!(result, Some(Ordering::Less));
+ ///
+ /// let result = 1.0.partial_cmp(&1.0);
+ /// assert_eq!(result, Some(Ordering::Equal));
+ ///
+ /// let result = 2.0.partial_cmp(&1.0);
+ /// assert_eq!(result, Some(Ordering::Greater));
+ /// ```
+ ///
+ /// When comparison is impossible:
+ ///
+ /// ```
+ /// let result = f64::NAN.partial_cmp(&1.0);
+ /// assert_eq!(result, None);
+ /// ```
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+
+ /// This method tests less than (for `self` and `other`) and is used by the `<` operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 < 2.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 < 1.0;
+ /// assert_eq!(result, false);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn lt(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Less) => true,
+ _ => false,
+ }
+ }
+
+ /// This method tests less than or equal to (for `self` and `other`) and is used by the `<=`
+ /// operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 <= 2.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 <= 2.0;
+ /// assert_eq!(result, true);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn le(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Less | Ordering::Equal) => true,
+ _ => false,
+ }
+ }
+
+ /// This method tests greater than (for `self` and `other`) and is used by the `>` operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 > 2.0;
+ /// assert_eq!(result, false);
+ ///
+ /// let result = 2.0 > 2.0;
+ /// assert_eq!(result, false);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn gt(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Greater) => true,
+ _ => false,
+ }
+ }
+
+ /// This method tests greater than or equal to (for `self` and `other`) and is used by the `>=`
+ /// operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 2.0 >= 1.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 >= 2.0;
+ /// assert_eq!(result, true);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn ge(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Greater | Ordering::Equal) => true,
+ _ => false,
+ }
+ }
+ }
+
+ #[doc(alias = "<")]
+ #[doc(alias = ">")]
+ #[doc(alias = "<=")]
+ #[doc(alias = ">=")]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub trait Ord: Eq + PartialOrd<Self> {
+ /// This method returns an [`Ordering`] between `self` and `other`.
+ ///
+ /// By convention, `self.cmp(&other)` returns the ordering matching the expression
+ /// `self <operator> other` if true.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::cmp::Ordering;
+ ///
+ /// assert_eq!(5.cmp(&10), Ordering::Less);
+ /// assert_eq!(10.cmp(&5), Ordering::Greater);
+ /// assert_eq!(5.cmp(&5), Ordering::Equal);
+ /// ```
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn cmp(&self, other: &Self) -> Ordering;
+
+ /// Compares and returns the maximum of two values.
+ ///
+ /// Returns the second argument if the comparison determines them to be equal.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// assert_eq!(2, 1.max(2));
+ /// assert_eq!(2, 2.max(2));
+ /// ```
+ #[stable(feature = "ord_max_min", since = "1.21.0")]
+ #[must_use]
+ fn max(self, other: Self) -> Self
+ where
+ Self: Sized,
+ {
+ self
+ }
+
+ /// Compares and returns the minimum of two values.
+ ///
+ /// Returns the first argument if the comparison determines them to be equal.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// assert_eq!(1, 1.min(2));
+ /// assert_eq!(2, 2.min(2));
+ /// ```
+ #[stable(feature = "ord_max_min", since = "1.21.0")]
+ #[must_use]
+ fn min(self, other: Self) -> Self
+ where
+ Self: Sized,
+ {
+ self
+ }
+
+ /// Restrict a value to a certain interval.
+ ///
+ /// Returns `max` if `self` is greater than `max`, and `min` if `self` is
+ /// less than `min`. Otherwise this returns `self`.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `min > max`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(clamp)]
+ ///
+ /// assert!((-3).clamp(-2, 1) == -2);
+ /// assert!(0.clamp(-2, 1) == 0);
+ /// assert!(2.clamp(-2, 1) == 1);
+ /// ```
+ #[must_use]
+ #[unstable(feature = "clamp", issue = "44095")]
+ fn clamp(self, min: Self, max: Self) -> Self
+ where
+ Self: Sized,
+ {
+ if self < min {
+ min
+ } else if self > max {
+ max
+ } else {
+ self
+ }
+ }
+ }
+ }
+
+ pub mod intrinsics {
+ #[lang = "discriminant_kind"]
+ pub trait DiscriminantKind {
+ #[lang = "discriminant_type"]
+ type Discriminant;
+ }
+
+ extern "rust-intrinsic" {
+ pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
+ }
+ }
+}
+
+use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
+use core::marker::Sized;
+use core::option::Option;
+
+// --------------
+
+impl PartialEq for isize {
+ fn eq(&self, other: &Self) -> bool {
+ *self == *other
+ }
+}
+
+impl PartialOrd for isize {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ if *self > *other {
+ Option::Some(Ordering::Greater)
+ } else if *self < *other {
+ Option::Some(Ordering::Less)
+ } else {
+ Option::Some(Ordering::Equal)
+ }
+ }
+
+ fn lt(&self, other: &Self) -> bool {
+ *self < *other
+ }
+ fn le(&self, other: &Self) -> bool {
+ *self <= *other
+ }
+ fn ge(&self, other: &Self) -> bool {
+ *self >= *other
+ }
+ fn gt(&self, other: &Self) -> bool {
+ *self > *other
+ }
+}
+
+impl Eq for isize {}
+
+impl Ord for isize {
+ fn cmp(&self, other: &Self) -> Ordering {
+ if *self > *other {
+ Ordering::Greater
+ } else if *self < *other {
+ Ordering::Less
+ } else {
+ Ordering::Equal
+ }
+ }
+}
+
+// ----------------------------------
+
+impl PartialEq for i32 {
+ fn eq(&self, other: &Self) -> bool {
+ *self == *other
+ }
+}
+
+impl PartialOrd for i32 {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ if *self > *other {
+ Option::Some(Ordering::Greater)
+ } else if *self < *other {
+ Option::Some(Ordering::Less)
+ } else {
+ Option::Some(Ordering::Equal)
+ }
+ }
+
+ fn lt(&self, other: &Self) -> bool {
+ *self < *other
+ }
+ fn le(&self, other: &Self) -> bool {
+ *self <= *other
+ }
+ fn ge(&self, other: &Self) -> bool {
+ *self >= *other
+ }
+ fn gt(&self, other: &Self) -> bool {
+ *self > *other
+ }
+}
+
+impl Ord for i32 {
+ fn cmp(&self, other: &Self) -> Ordering {
+ if *self > *other {
+ Ordering::Greater
+ } else if *self < *other {
+ Ordering::Less
+ } else {
+ Ordering::Equal
+ }
+ }
+}
+
+impl Eq for i32 {}
+
+#[derive(Ord, PartialOrd, PartialEq, Eq)]
+enum Foo {
+ A,
+ B(i32),
+}
+
+extern "C" {
+ fn puts(s: *const i8);
+}
+
+fn print(s: &str) {
+ unsafe {
+ puts(s as *const str as *const i8);
+ }
+}
+
+fn main() -> i32 {
+ let a = Foo::A;
+ let b = Foo::B(15);
+
+ if (a != b) {
+ print("WORKS");
+ }
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/issue-3836.rs b/gcc/testsuite/rust/execute/torture/issue-3836.rs
new file mode 100644
index 0000000..61ad424
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-3836.rs
@@ -0,0 +1,454 @@
+// { dg-options "-w" }
+// { dg-output "less\r*\n" }
+
+#![feature(intrinsics)]
+
+mod core {
+ mod option {
+ // #[rustc_diagnostic_item = "option_type"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub enum Option<T> {
+ /// No value
+ #[lang = "None"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ None,
+ /// Some value `T`
+ #[lang = "Some"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Some(#[stable(feature = "rust1", since = "1.0.0")] T),
+ }
+ }
+
+ mod marker {
+ #[lang = "phantom_data"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub struct PhantomData<T: ?Sized>;
+
+ #[unstable(feature = "structural_match", issue = "31434")]
+ // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(PartialEq)]`")]
+ #[lang = "structural_peq"]
+ pub trait StructuralPartialEq {
+ // Empty.
+ }
+
+ #[unstable(feature = "structural_match", issue = "31434")]
+ // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(Eq)]`")]
+ #[lang = "structural_teq"]
+ pub trait StructuralEq {
+ // Empty.
+ }
+
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[lang = "sized"]
+ // #[rustc_on_unimplemented(
+ // message = "the size for values of type `{Self}` cannot be known at compilation time",
+ // label = "doesn't have a size known at compile-time"
+ // )]
+ // #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
+ // #[rustc_specialization_trait]
+ pub trait Sized {
+ // Empty.
+ }
+ }
+
+ mod cmp {
+ use super::marker::Sized;
+ use super::option::Option;
+
+ // #[derive(Clone, Copy, PartialEq, Debug, Hash)]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub enum Ordering {
+ /// An ordering where a compared value is less than another.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Less = -1,
+ /// An ordering where a compared value is equal to another.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Equal = 0,
+ /// An ordering where a compared value is greater than another.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Greater = 1,
+ }
+
+ #[lang = "eq"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[doc(alias = "==")]
+ #[doc(alias = "!=")]
+ // #[rustc_on_unimplemented(
+ // message = "can't compare `{Self}` with `{Rhs}`",
+ // label = "no implementation for `{Self} == {Rhs}`"
+ // )]
+ pub trait PartialEq<Rhs: ?Sized = Self> {
+ /// This method tests for `self` and `other` values to be equal, and is used
+ /// by `==`.
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn eq(&self, other: &Rhs) -> bool;
+
+ fn ne(&self, other: &Rhs) -> bool {
+ !self.eq(other)
+ }
+ }
+
+ #[doc(alias = "==")]
+ #[doc(alias = "!=")]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub trait Eq: PartialEq<Self> {
+ // this method is used solely by #[deriving] to assert
+ // that every component of a type implements #[deriving]
+ // itself, the current deriving infrastructure means doing this
+ // assertion without using a method on this trait is nearly
+ // impossible.
+ //
+ // This should never be implemented by hand.
+ #[doc(hidden)]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn assert_receiver_is_total_eq(&self) {}
+ }
+
+ #[lang = "partial_ord"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[doc(alias = ">")]
+ #[doc(alias = "<")]
+ #[doc(alias = "<=")]
+ #[doc(alias = ">=")]
+ // #[rustc_on_unimplemented(
+ // message = "can't compare `{Self}` with `{Rhs}`",
+ // label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`"
+ // )]
+ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
+ /// This method returns an ordering between `self` and `other` values if one exists.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::cmp::Ordering;
+ ///
+ /// let result = 1.0.partial_cmp(&2.0);
+ /// assert_eq!(result, Some(Ordering::Less));
+ ///
+ /// let result = 1.0.partial_cmp(&1.0);
+ /// assert_eq!(result, Some(Ordering::Equal));
+ ///
+ /// let result = 2.0.partial_cmp(&1.0);
+ /// assert_eq!(result, Some(Ordering::Greater));
+ /// ```
+ ///
+ /// When comparison is impossible:
+ ///
+ /// ```
+ /// let result = f64::NAN.partial_cmp(&1.0);
+ /// assert_eq!(result, None);
+ /// ```
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+
+ /// This method tests less than (for `self` and `other`) and is used by the `<` operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 < 2.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 < 1.0;
+ /// assert_eq!(result, false);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn lt(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Less) => true,
+ _ => false,
+ }
+ }
+
+ /// This method tests less than or equal to (for `self` and `other`) and is used by the `<=`
+ /// operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 <= 2.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 <= 2.0;
+ /// assert_eq!(result, true);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn le(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Less | Ordering::Equal) => true,
+ _ => false,
+ }
+ }
+
+ /// This method tests greater than (for `self` and `other`) and is used by the `>` operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 > 2.0;
+ /// assert_eq!(result, false);
+ ///
+ /// let result = 2.0 > 2.0;
+ /// assert_eq!(result, false);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn gt(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Greater) => true,
+ _ => false,
+ }
+ }
+
+ /// This method tests greater than or equal to (for `self` and `other`) and is used by the `>=`
+ /// operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 2.0 >= 1.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 >= 2.0;
+ /// assert_eq!(result, true);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn ge(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Greater | Ordering::Equal) => true,
+ _ => false,
+ }
+ }
+ }
+
+ #[doc(alias = "<")]
+ #[doc(alias = ">")]
+ #[doc(alias = "<=")]
+ #[doc(alias = ">=")]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub trait Ord: Eq + PartialOrd<Self> {
+ /// This method returns an [`Ordering`] between `self` and `other`.
+ ///
+ /// By convention, `self.cmp(&other)` returns the ordering matching the expression
+ /// `self <operator> other` if true.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::cmp::Ordering;
+ ///
+ /// assert_eq!(5.cmp(&10), Ordering::Less);
+ /// assert_eq!(10.cmp(&5), Ordering::Greater);
+ /// assert_eq!(5.cmp(&5), Ordering::Equal);
+ /// ```
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn cmp(&self, other: &Self) -> Ordering;
+
+ /// Compares and returns the maximum of two values.
+ ///
+ /// Returns the second argument if the comparison determines them to be equal.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// assert_eq!(2, 1.max(2));
+ /// assert_eq!(2, 2.max(2));
+ /// ```
+ #[stable(feature = "ord_max_min", since = "1.21.0")]
+ #[must_use]
+ fn max(self, other: Self) -> Self
+ where
+ Self: Sized,
+ {
+ self
+ }
+
+ /// Compares and returns the minimum of two values.
+ ///
+ /// Returns the first argument if the comparison determines them to be equal.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// assert_eq!(1, 1.min(2));
+ /// assert_eq!(2, 2.min(2));
+ /// ```
+ #[stable(feature = "ord_max_min", since = "1.21.0")]
+ #[must_use]
+ fn min(self, other: Self) -> Self
+ where
+ Self: Sized,
+ {
+ self
+ }
+
+ /// Restrict a value to a certain interval.
+ ///
+ /// Returns `max` if `self` is greater than `max`, and `min` if `self` is
+ /// less than `min`. Otherwise this returns `self`.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `min > max`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(clamp)]
+ ///
+ /// assert!((-3).clamp(-2, 1) == -2);
+ /// assert!(0.clamp(-2, 1) == 0);
+ /// assert!(2.clamp(-2, 1) == 1);
+ /// ```
+ #[must_use]
+ #[unstable(feature = "clamp", issue = "44095")]
+ fn clamp(self, min: Self, max: Self) -> Self
+ where
+ Self: Sized,
+ {
+ if self < min {
+ min
+ } else if self > max {
+ max
+ } else {
+ self
+ }
+ }
+ }
+ }
+
+ pub mod intrinsics {
+ #[lang = "discriminant_kind"]
+ pub trait DiscriminantKind {
+ #[lang = "discriminant_type"]
+ type Discriminant;
+ }
+
+ extern "rust-intrinsic" {
+ pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
+ }
+ }
+}
+
+use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
+use core::marker::Sized;
+use core::option::Option;
+
+// for comparing discriminant_value
+impl PartialEq for isize {
+ fn eq(&self, other: &Self) -> bool {
+ *self == *other
+ }
+}
+
+// for comparing discriminant_value
+impl PartialOrd for isize {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ if *self > *other {
+ Option::Some(Ordering::Greater)
+ } else if *self < *other {
+ Option::Some(Ordering::Less)
+ } else {
+ Option::Some(Ordering::Equal)
+ }
+ }
+
+ fn lt(&self, other: &Self) -> bool {
+ *self < *other
+ }
+ fn le(&self, other: &Self) -> bool {
+ *self <= *other
+ }
+ fn ge(&self, other: &Self) -> bool {
+ *self >= *other
+ }
+ fn gt(&self, other: &Self) -> bool {
+ *self > *other
+ }
+}
+
+impl PartialEq for i32 {
+ fn eq(&self, other: &Self) -> bool {
+ *self == *other
+ }
+}
+impl Eq for i32 {}
+
+impl PartialOrd for i32 {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ if *self > *other {
+ Option::Some(Ordering::Greater)
+ } else if *self < *other {
+ Option::Some(Ordering::Less)
+ } else {
+ Option::Some(Ordering::Equal)
+ }
+ }
+
+ fn lt(&self, other: &Self) -> bool {
+ *self < *other
+ }
+ fn le(&self, other: &Self) -> bool {
+ *self <= *other
+ }
+ fn ge(&self, other: &Self) -> bool {
+ *self >= *other
+ }
+ fn gt(&self, other: &Self) -> bool {
+ *self > *other
+ }
+}
+
+impl Ord for i32 {
+ fn cmp(&self, other: &Self) -> Ordering {
+ if *self > *other {
+ Ordering::Greater
+ } else if *self < *other {
+ Ordering::Less
+ } else {
+ Ordering::Equal
+ }
+ }
+}
+
+// ------------
+
+#[derive(Ord, PartialOrd, PartialEq, Eq)]
+struct Bar {
+ a: i32,
+ b: i32,
+}
+
+extern "C" {
+ fn puts(s: *const i8);
+}
+
+fn print(s: &str) {
+ unsafe {
+ puts(s as *const str as *const i8);
+ }
+}
+
+fn main() -> i32 {
+ let x = Bar { a: 1, b: 2 };
+ let y = Bar { a: 1, b: 3 };
+
+ match x.partial_cmp(&y) {
+ Option::Some(Ordering::Less) => print("less"),
+ Option::Some(Ordering::Greater) => print("greater"),
+ Option::Some(Ordering::Equal) => print("equal"),
+ _ => print("none"),
+ }
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/iter1.rs b/gcc/testsuite/rust/execute/torture/iter1.rs
index c3b6c7b..233eb60 100644
--- a/gcc/testsuite/rust/execute/torture/iter1.rs
+++ b/gcc/testsuite/rust/execute/torture/iter1.rs
@@ -99,30 +99,30 @@ mod ptr {
#[lang = "const_ptr"]
impl<T> *const T {
pub unsafe fn offset(self, count: isize) -> *const T {
- intrinsics::offset(self, count)
+ crate::intrinsics::offset(self, count)
}
}
#[lang = "mut_ptr"]
impl<T> *mut T {
pub unsafe fn offset(self, count: isize) -> *mut T {
- intrinsics::offset(self, count) as *mut T
+ crate::intrinsics::offset(self, count) as *mut T
}
}
pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
let x = x as *mut u8;
let y = y as *mut u8;
- let len = mem::size_of::<T>() * count;
+ let len = crate::mem::size_of::<T>() * count;
swap_nonoverlapping_bytes(x, y, len)
}
pub unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) {
// For types smaller than the block optimization below,
// just swap directly to avoid pessimizing codegen.
- if mem::size_of::<T>() < 32 {
+ if crate::mem::size_of::<T>() < 32 {
let z = read(x);
- intrinsics::copy_nonoverlapping(y, x, 1);
+ crate::intrinsics::copy_nonoverlapping(y, x, 1);
write(y, z);
} else {
swap_nonoverlapping(x, y, 1);
@@ -130,12 +130,12 @@ mod ptr {
}
pub unsafe fn write<T>(dst: *mut T, src: T) {
- intrinsics::move_val_init(&mut *dst, src)
+ crate::intrinsics::move_val_init(&mut *dst, src)
}
pub unsafe fn read<T>(src: *const T) -> T {
- let mut tmp: T = mem::uninitialized();
- intrinsics::copy_nonoverlapping(src, &mut tmp, 1);
+ let mut tmp: T = crate::mem::uninitialized();
+ crate::intrinsics::copy_nonoverlapping(src, &mut tmp, 1);
tmp
}
@@ -143,7 +143,7 @@ mod ptr {
struct Block(u64, u64, u64, u64);
struct UnalignedBlock(u64, u64, u64, u64);
- let block_size = mem::size_of::<Block>();
+ let block_size = crate::mem::size_of::<Block>();
// Loop through x & y, copying them `Block` at a time
// The optimizer should unroll the loop fully for most types
@@ -152,31 +152,31 @@ mod ptr {
while i + block_size <= len {
// Create some uninitialized memory as scratch space
// Declaring `t` here avoids aligning the stack when this loop is unused
- let mut t: Block = mem::uninitialized();
+ let mut t: Block = crate::mem::uninitialized();
let t = &mut t as *mut _ as *mut u8;
let x = x.offset(i as isize);
let y = y.offset(i as isize);
// Swap a block of bytes of x & y, using t as a temporary buffer
// This should be optimized into efficient SIMD operations where available
- intrinsics::copy_nonoverlapping(x, t, block_size);
- intrinsics::copy_nonoverlapping(y, x, block_size);
- intrinsics::copy_nonoverlapping(t, y, block_size);
+ crate::intrinsics::copy_nonoverlapping(x, t, block_size);
+ crate::intrinsics::copy_nonoverlapping(y, x, block_size);
+ crate::intrinsics::copy_nonoverlapping(t, y, block_size);
i += block_size;
}
if i < len {
// Swap any remaining bytes
- let mut t: UnalignedBlock = mem::uninitialized();
+ let mut t: UnalignedBlock = crate::mem::uninitialized();
let rem = len - i;
let t = &mut t as *mut _ as *mut u8;
let x = x.offset(i as isize);
let y = y.offset(i as isize);
- intrinsics::copy_nonoverlapping(x, t, rem);
- intrinsics::copy_nonoverlapping(y, x, rem);
- intrinsics::copy_nonoverlapping(t, y, rem);
+ crate::intrinsics::copy_nonoverlapping(x, t, rem);
+ crate::intrinsics::copy_nonoverlapping(y, x, rem);
+ crate::intrinsics::copy_nonoverlapping(t, y, rem);
}
}
}
@@ -191,7 +191,7 @@ mod mem {
pub fn swap<T>(x: &mut T, y: &mut T) {
unsafe {
- ptr::swap_nonoverlapping_one(x, y);
+ crate::ptr::swap_nonoverlapping_one(x, y);
}
}
@@ -201,7 +201,7 @@ mod mem {
}
pub unsafe fn uninitialized<T>() -> T {
- intrinsics::uninit()
+ crate::intrinsics::uninit()
}
}
diff --git a/gcc/testsuite/rust/execute/torture/match-identifierpattern.rs b/gcc/testsuite/rust/execute/torture/match-identifierpattern.rs
new file mode 100644
index 0000000..b102ad1
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match-identifierpattern.rs
@@ -0,0 +1,10 @@
+fn main() -> i32 {
+ let mut x = 2;
+
+ match x {
+ a @ 2 => { x = a + 1 },
+ _ => {}
+ }
+
+ x - 3
+}
diff --git a/gcc/testsuite/rust/execute/torture/match-restpattern-tuple.rs b/gcc/testsuite/rust/execute/torture/match-restpattern-tuple.rs
new file mode 100644
index 0000000..2c1418c
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match-restpattern-tuple.rs
@@ -0,0 +1,27 @@
+// { dg-output "correct\r*" }
+extern "C" {
+ fn puts(s: *const i8);
+}
+
+fn main() -> i32 {
+ let x = (1, 2, 3, 4);
+ let mut ret = 1;
+
+ match x {
+ (1, .., 2, 4) => {
+ /* should not take this path */
+ unsafe { puts("wrong\0" as *const str as *const i8) }
+ },
+ (2, ..) => {
+ /* should not take this path */
+ unsafe { puts("wrong\0" as *const str as *const i8) }
+ },
+ (b, .., 4) => {
+ ret -= b;
+ unsafe { puts("correct\0" as *const str as *const i8) }
+ },
+ _ => {}
+ }
+
+ ret
+} \ No newline at end of file
diff --git a/gcc/testsuite/rust/execute/torture/match-slicepattern-array-1.rs b/gcc/testsuite/rust/execute/torture/match-slicepattern-array-1.rs
new file mode 100644
index 0000000..95c55d8
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match-slicepattern-array-1.rs
@@ -0,0 +1,23 @@
+// { dg-output "correct\r*" }
+extern "C" {
+ fn puts(s: *const i8);
+}
+
+fn main() -> i32 {
+ let a = [0, 1];
+ let mut ret = 1;
+
+ match a {
+ [0, 0] => {
+ /* should not take this path */
+ unsafe { puts("wrong\0" as *const str as *const i8) }
+ },
+ [0, b] => {
+ ret -= b;
+ unsafe { puts("correct\0" as *const str as *const i8) }
+ },
+ _ => {}
+ }
+
+ ret
+}
diff --git a/gcc/testsuite/rust/execute/torture/match-slicepattern-slice-1.rs b/gcc/testsuite/rust/execute/torture/match-slicepattern-slice-1.rs
new file mode 100644
index 0000000..3ed0b644
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match-slicepattern-slice-1.rs
@@ -0,0 +1,24 @@
+// { dg-output "correct\r*" }
+extern "C" {
+ fn puts(s: *const i8);
+}
+
+fn main() -> i32 {
+ let arr = [0, 1];
+ let a: &[i32] = &arr;
+ let mut ret = 1;
+
+ match a {
+ [0, 0] => {
+ /* should not take this path */
+ unsafe { puts("wrong\0" as *const str as *const i8) }
+ },
+ [0, b] => {
+ ret -= b;
+ unsafe { puts("correct\0" as *const str as *const i8) }
+ },
+ _ => {}
+ }
+
+ ret
+}
diff --git a/gcc/testsuite/rust/execute/torture/match-tuplestructpattern.rs b/gcc/testsuite/rust/execute/torture/match-tuplestructpattern.rs
new file mode 100644
index 0000000..323109c
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/match-tuplestructpattern.rs
@@ -0,0 +1,12 @@
+fn main() -> i32 {
+ struct A (i32, i32);
+ let a = A (0, 1);
+ let mut ret = 1;
+
+ match a {
+ A (0, b) => { ret -= b },
+ _ => {}
+ }
+
+ ret
+}
diff --git a/gcc/testsuite/rust/execute/torture/min_specialization2.rs b/gcc/testsuite/rust/execute/torture/min_specialization2.rs
index d3239ee..74faee4 100644
--- a/gcc/testsuite/rust/execute/torture/min_specialization2.rs
+++ b/gcc/testsuite/rust/execute/torture/min_specialization2.rs
@@ -8,7 +8,7 @@ trait Foo {
}
impl<T> Foo for T {
- default fn foo(&self) -> i32 { // { dg-warning "unused" }
+ default fn foo(&self) -> i32 {
15
}
}
diff --git a/gcc/testsuite/rust/execute/torture/name_resolution.rs b/gcc/testsuite/rust/execute/torture/name_resolution.rs
index 7492183..a2eaf48 100644
--- a/gcc/testsuite/rust/execute/torture/name_resolution.rs
+++ b/gcc/testsuite/rust/execute/torture/name_resolution.rs
@@ -1,4 +1,3 @@
-// { dg-additional-options "-frust-name-resolution-2.0" }
// { dg-output "Value is 10\r*\n" }
const BAZ: i32 = 10;
diff --git a/gcc/testsuite/rust/execute/torture/offset_of1.rs b/gcc/testsuite/rust/execute/torture/offset_of1.rs
new file mode 100644
index 0000000..7d39483
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/offset_of1.rs
@@ -0,0 +1,16 @@
+// { dg-do run { target x86_64*-*-* } }
+// { dg-additional-options "-frust-assume-builtin-offset-of" }
+
+pub struct Foo {
+ pub a: i32,
+ pub b: i32,
+}
+
+fn main() -> i32 {
+ let a = offset_of!(Foo, a); // valid
+ let b = offset_of!(Foo, b); // valid
+
+ let res = a + b - 4;
+
+ res as i32
+}
diff --git a/gcc/testsuite/rust/execute/torture/partial-eq-1.rs b/gcc/testsuite/rust/execute/torture/partial-eq-1.rs
new file mode 100644
index 0000000..db123a1
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/partial-eq-1.rs
@@ -0,0 +1,103 @@
+/* { dg-output "a == b\r*\na != c\r*\n" }*/
+/* { dg-options "-w" } */
+
+mod core {
+ mod marker {
+ #[lang = "phantom_data"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub struct PhantomData<T: ?Sized>;
+
+ #[unstable(feature = "structural_match", issue = "31434")]
+ #[lang = "structural_peq"]
+ pub trait StructuralPartialEq {
+ // Empty.
+ }
+
+ #[unstable(feature = "structural_match", issue = "31434")]
+ #[lang = "structural_teq"]
+ pub trait StructuralEq {
+ // Empty.
+ }
+
+ #[lang = "sized"]
+ pub trait Sized {}
+ }
+
+ pub mod cmp {
+ use super::marker::Sized;
+
+ #[lang = "eq"]
+ pub trait PartialEq<Rhs: ?Sized = Self> {
+ fn eq(&self, other: &Rhs) -> bool;
+
+ fn ne(&self, other: &Rhs) -> bool {
+ !self.eq(other)
+ }
+ }
+
+ pub trait Eq: PartialEq<Self> {
+ fn assert_receiver_is_total_eq(&self) {}
+ }
+ }
+}
+
+use core::cmp::{Eq, PartialEq};
+
+// PartialEq for i32 and u32 so we can compare across types
+impl PartialEq<u32> for i32 {
+ fn eq(&self, other: &u32) -> bool {
+ *self >= 0 && (*self as u32) == *other
+ }
+}
+impl PartialEq<i32> for u32 {
+ fn eq(&self, other: &i32) -> bool {
+ *other >= 0 && *self == *other as u32
+ }
+}
+
+// Our generic struct
+struct Foo<T> {
+ value: T,
+}
+
+// Manual impl of PartialEq for different generic params
+impl<T, U> PartialEq<Foo<U>> for Foo<T>
+where
+ T: PartialEq<U>,
+{
+ fn eq(&self, other: &Foo<U>) -> bool {
+ self.value.eq(&other.value)
+ }
+}
+
+impl<T: PartialEq> Eq for Foo<T> {}
+
+extern "C" {
+ fn puts(s: *const i8);
+}
+
+fn print(s: &str) {
+ unsafe {
+ puts(s as *const str as *const i8);
+ }
+}
+
+fn main() -> i32 {
+ let a = Foo { value: 42i32 };
+ let b = Foo { value: 42u32 };
+ let c = Foo { value: 7u32 };
+
+ if a == b {
+ print("a == b");
+ } else {
+ print("a != b");
+ }
+
+ if a == c {
+ print("a == c");
+ } else {
+ print("a != c");
+ }
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/partial-eq-2.rs b/gcc/testsuite/rust/execute/torture/partial-eq-2.rs
new file mode 100644
index 0000000..debed8c
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/partial-eq-2.rs
@@ -0,0 +1,60 @@
+/* { dg-output "a == b\r*\na != c\r*\n" }*/
+/* { dg-options "-w" } */
+
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "eq"]
+pub trait PartialEq<Rhs: ?Sized = Self> {
+ fn eq(&self, other: &Rhs) -> bool;
+
+ fn ne(&self, other: &Rhs) -> bool {
+ !self.eq(other)
+ }
+}
+
+impl PartialEq for i32 {
+ fn eq(&self, other: &Self) -> bool {
+ *self == *other
+ }
+}
+
+struct Foo<T> {
+ value: T,
+}
+
+impl<T: PartialEq> PartialEq for Foo<T> {
+ fn eq(&self, other: &Self) -> bool {
+ self.value.eq(&other.value)
+ }
+}
+
+extern "C" {
+ fn puts(s: *const i8);
+}
+
+fn print(s: &str) {
+ unsafe {
+ puts(s as *const str as *const i8);
+ }
+}
+
+fn main() -> i32 {
+ let a = Foo { value: 42i32 };
+ let b = Foo { value: 42i32 };
+ let c = Foo { value: 99i32 };
+
+ if a == b {
+ print("a == b");
+ } else {
+ print("a != b");
+ }
+
+ if a == c {
+ print("a == c");
+ } else {
+ print("a != c");
+ }
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/partial-eq-3.rs b/gcc/testsuite/rust/execute/torture/partial-eq-3.rs
new file mode 100644
index 0000000..849910a
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/partial-eq-3.rs
@@ -0,0 +1,457 @@
+/* { dg-output "a == b\r*\na != c\r*\n" }*/
+/* { dg-options "-w" } */
+
+#![feature(intrinsics)]
+
+mod core {
+ mod option {
+ // #[rustc_diagnostic_item = "option_type"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub enum Option<T> {
+ /// No value
+ #[lang = "None"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ None,
+ /// Some value `T`
+ #[lang = "Some"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Some(#[stable(feature = "rust1", since = "1.0.0")] T),
+ }
+ }
+
+ mod marker {
+ #[lang = "phantom_data"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub struct PhantomData<T: ?Sized>;
+
+ #[unstable(feature = "structural_match", issue = "31434")]
+ // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(PartialEq)]`")]
+ #[lang = "structural_peq"]
+ pub trait StructuralPartialEq {
+ // Empty.
+ }
+
+ #[unstable(feature = "structural_match", issue = "31434")]
+ // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(Eq)]`")]
+ #[lang = "structural_teq"]
+ pub trait StructuralEq {
+ // Empty.
+ }
+
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[lang = "sized"]
+ // #[rustc_on_unimplemented(
+ // message = "the size for values of type `{Self}` cannot be known at compilation time",
+ // label = "doesn't have a size known at compile-time"
+ // )]
+ // #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
+ // #[rustc_specialization_trait]
+ pub trait Sized {
+ // Empty.
+ }
+ }
+
+ mod cmp {
+ use super::marker::Sized;
+ use super::option::Option;
+
+ // #[derive(Clone, Copy, PartialEq, Debug, Hash)]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub enum Ordering {
+ /// An ordering where a compared value is less than another.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Less = -1,
+ /// An ordering where a compared value is equal to another.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Equal = 0,
+ /// An ordering where a compared value is greater than another.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Greater = 1,
+ }
+
+ #[lang = "eq"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[doc(alias = "==")]
+ #[doc(alias = "!=")]
+ // #[rustc_on_unimplemented(
+ // message = "can't compare `{Self}` with `{Rhs}`",
+ // label = "no implementation for `{Self} == {Rhs}`"
+ // )]
+ pub trait PartialEq<Rhs: ?Sized = Self> {
+ /// This method tests for `self` and `other` values to be equal, and is used
+ /// by `==`.
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn eq(&self, other: &Rhs) -> bool;
+
+ fn ne(&self, other: &Rhs) -> bool {
+ !self.eq(other)
+ }
+ }
+
+ #[doc(alias = "==")]
+ #[doc(alias = "!=")]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub trait Eq: PartialEq<Self> {
+ // this method is used solely by #[deriving] to assert
+ // that every component of a type implements #[deriving]
+ // itself, the current deriving infrastructure means doing this
+ // assertion without using a method on this trait is nearly
+ // impossible.
+ //
+ // This should never be implemented by hand.
+ #[doc(hidden)]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn assert_receiver_is_total_eq(&self) {}
+ }
+
+ #[lang = "partial_ord"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[doc(alias = ">")]
+ #[doc(alias = "<")]
+ #[doc(alias = "<=")]
+ #[doc(alias = ">=")]
+ // #[rustc_on_unimplemented(
+ // message = "can't compare `{Self}` with `{Rhs}`",
+ // label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`"
+ // )]
+ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
+ /// This method returns an ordering between `self` and `other` values if one exists.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::cmp::Ordering;
+ ///
+ /// let result = 1.0.partial_cmp(&2.0);
+ /// assert_eq!(result, Some(Ordering::Less));
+ ///
+ /// let result = 1.0.partial_cmp(&1.0);
+ /// assert_eq!(result, Some(Ordering::Equal));
+ ///
+ /// let result = 2.0.partial_cmp(&1.0);
+ /// assert_eq!(result, Some(Ordering::Greater));
+ /// ```
+ ///
+ /// When comparison is impossible:
+ ///
+ /// ```
+ /// let result = f64::NAN.partial_cmp(&1.0);
+ /// assert_eq!(result, None);
+ /// ```
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+
+ /// This method tests less than (for `self` and `other`) and is used by the `<` operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 < 2.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 < 1.0;
+ /// assert_eq!(result, false);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn lt(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Less) => true,
+ _ => false,
+ }
+ }
+
+ /// This method tests less than or equal to (for `self` and `other`) and is used by the `<=`
+ /// operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 <= 2.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 <= 2.0;
+ /// assert_eq!(result, true);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn le(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Less | Ordering::Equal) => true,
+ _ => false,
+ }
+ }
+
+ /// This method tests greater than (for `self` and `other`) and is used by the `>` operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 > 2.0;
+ /// assert_eq!(result, false);
+ ///
+ /// let result = 2.0 > 2.0;
+ /// assert_eq!(result, false);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn gt(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Greater) => true,
+ _ => false,
+ }
+ }
+
+ /// This method tests greater than or equal to (for `self` and `other`) and is used by the `>=`
+ /// operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 2.0 >= 1.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 >= 2.0;
+ /// assert_eq!(result, true);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn ge(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Greater | Ordering::Equal) => true,
+ _ => false,
+ }
+ }
+ }
+
+ #[doc(alias = "<")]
+ #[doc(alias = ">")]
+ #[doc(alias = "<=")]
+ #[doc(alias = ">=")]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub trait Ord: Eq + PartialOrd<Self> {
+ /// This method returns an [`Ordering`] between `self` and `other`.
+ ///
+ /// By convention, `self.cmp(&other)` returns the ordering matching the expression
+ /// `self <operator> other` if true.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::cmp::Ordering;
+ ///
+ /// assert_eq!(5.cmp(&10), Ordering::Less);
+ /// assert_eq!(10.cmp(&5), Ordering::Greater);
+ /// assert_eq!(5.cmp(&5), Ordering::Equal);
+ /// ```
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn cmp(&self, other: &Self) -> Ordering;
+
+ /// Compares and returns the maximum of two values.
+ ///
+ /// Returns the second argument if the comparison determines them to be equal.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// assert_eq!(2, 1.max(2));
+ /// assert_eq!(2, 2.max(2));
+ /// ```
+ #[stable(feature = "ord_max_min", since = "1.21.0")]
+ #[must_use]
+ fn max(self, other: Self) -> Self
+ where
+ Self: Sized,
+ {
+ self
+ }
+
+ /// Compares and returns the minimum of two values.
+ ///
+ /// Returns the first argument if the comparison determines them to be equal.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// assert_eq!(1, 1.min(2));
+ /// assert_eq!(2, 2.min(2));
+ /// ```
+ #[stable(feature = "ord_max_min", since = "1.21.0")]
+ #[must_use]
+ fn min(self, other: Self) -> Self
+ where
+ Self: Sized,
+ {
+ self
+ }
+
+ /// Restrict a value to a certain interval.
+ ///
+ /// Returns `max` if `self` is greater than `max`, and `min` if `self` is
+ /// less than `min`. Otherwise this returns `self`.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `min > max`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(clamp)]
+ ///
+ /// assert!((-3).clamp(-2, 1) == -2);
+ /// assert!(0.clamp(-2, 1) == 0);
+ /// assert!(2.clamp(-2, 1) == 1);
+ /// ```
+ #[must_use]
+ #[unstable(feature = "clamp", issue = "44095")]
+ fn clamp(self, min: Self, max: Self) -> Self
+ where
+ Self: Sized,
+ {
+ if self < min {
+ min
+ } else if self > max {
+ max
+ } else {
+ self
+ }
+ }
+ }
+ }
+
+ pub mod intrinsics {
+ #[lang = "discriminant_kind"]
+ pub trait DiscriminantKind {
+ #[lang = "discriminant_type"]
+ type Discriminant;
+ }
+
+ extern "rust-intrinsic" {
+ pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
+ }
+ }
+}
+
+use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
+use core::marker::Sized;
+use core::option::Option;
+
+// for comparing discriminant_value
+impl PartialEq for isize {
+ fn eq(&self, other: &Self) -> bool {
+ *self == *other
+ }
+}
+
+// for comparing discriminant_value
+impl PartialOrd for isize {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ if *self > *other {
+ Option::Some(Ordering::Greater)
+ } else if *self < *other {
+ Option::Some(Ordering::Less)
+ } else {
+ Option::Some(Ordering::Equal)
+ }
+ }
+
+ fn lt(&self, other: &Self) -> bool {
+ *self < *other
+ }
+ fn le(&self, other: &Self) -> bool {
+ *self <= *other
+ }
+ fn ge(&self, other: &Self) -> bool {
+ *self >= *other
+ }
+ fn gt(&self, other: &Self) -> bool {
+ *self > *other
+ }
+}
+
+impl PartialEq for i32 {
+ fn eq(&self, other: &Self) -> bool {
+ *self == *other
+ }
+}
+impl Eq for i32 {}
+
+impl PartialOrd for i32 {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ if *self > *other {
+ Option::Some(Ordering::Greater)
+ } else if *self < *other {
+ Option::Some(Ordering::Less)
+ } else {
+ Option::Some(Ordering::Equal)
+ }
+ }
+
+ fn lt(&self, other: &Self) -> bool {
+ *self < *other
+ }
+ fn le(&self, other: &Self) -> bool {
+ *self <= *other
+ }
+ fn ge(&self, other: &Self) -> bool {
+ *self >= *other
+ }
+ fn gt(&self, other: &Self) -> bool {
+ *self > *other
+ }
+}
+
+impl Ord for i32 {
+ fn cmp(&self, other: &Self) -> Ordering {
+ if *self > *other {
+ Ordering::Greater
+ } else if *self < *other {
+ Ordering::Less
+ } else {
+ Ordering::Equal
+ }
+ }
+}
+
+#[derive(PartialEq)]
+struct Foo {
+ a: i32,
+}
+
+extern "C" {
+ fn puts(s: *const i8);
+}
+
+fn print(s: &str) {
+ unsafe {
+ puts(s as *const str as *const i8);
+ }
+}
+
+fn main() -> i32 {
+ let a = Foo { a: 42i32 };
+ let b = Foo { a: 42i32 };
+ let c = Foo { a: 7i32 };
+
+ if a == b {
+ print("a == b");
+ } else {
+ print("a != b");
+ }
+
+ if a == c {
+ print("a == c");
+ } else {
+ print("a != c");
+ }
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/partial-eq-4.rs b/gcc/testsuite/rust/execute/torture/partial-eq-4.rs
new file mode 100644
index 0000000..b6997d8
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/partial-eq-4.rs
@@ -0,0 +1,457 @@
+/* { dg-output "a == b\r*\na != c\r*\n" }*/
+/* { dg-options "-w" } */
+
+#![feature(intrinsics)]
+
+mod core {
+ mod option {
+ // #[rustc_diagnostic_item = "option_type"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub enum Option<T> {
+ /// No value
+ #[lang = "None"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ None,
+ /// Some value `T`
+ #[lang = "Some"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Some(#[stable(feature = "rust1", since = "1.0.0")] T),
+ }
+ }
+
+ mod marker {
+ #[lang = "phantom_data"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub struct PhantomData<T: ?Sized>;
+
+ #[unstable(feature = "structural_match", issue = "31434")]
+ // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(PartialEq)]`")]
+ #[lang = "structural_peq"]
+ pub trait StructuralPartialEq {
+ // Empty.
+ }
+
+ #[unstable(feature = "structural_match", issue = "31434")]
+ // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(Eq)]`")]
+ #[lang = "structural_teq"]
+ pub trait StructuralEq {
+ // Empty.
+ }
+
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[lang = "sized"]
+ // #[rustc_on_unimplemented(
+ // message = "the size for values of type `{Self}` cannot be known at compilation time",
+ // label = "doesn't have a size known at compile-time"
+ // )]
+ // #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
+ // #[rustc_specialization_trait]
+ pub trait Sized {
+ // Empty.
+ }
+ }
+
+ mod cmp {
+ use super::marker::Sized;
+ use super::option::Option;
+
+ // #[derive(Clone, Copy, PartialEq, Debug, Hash)]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub enum Ordering {
+ /// An ordering where a compared value is less than another.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Less = -1,
+ /// An ordering where a compared value is equal to another.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Equal = 0,
+ /// An ordering where a compared value is greater than another.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Greater = 1,
+ }
+
+ #[lang = "eq"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[doc(alias = "==")]
+ #[doc(alias = "!=")]
+ // #[rustc_on_unimplemented(
+ // message = "can't compare `{Self}` with `{Rhs}`",
+ // label = "no implementation for `{Self} == {Rhs}`"
+ // )]
+ pub trait PartialEq<Rhs: ?Sized = Self> {
+ /// This method tests for `self` and `other` values to be equal, and is used
+ /// by `==`.
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn eq(&self, other: &Rhs) -> bool;
+
+ fn ne(&self, other: &Rhs) -> bool {
+ !self.eq(other)
+ }
+ }
+
+ #[doc(alias = "==")]
+ #[doc(alias = "!=")]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub trait Eq: PartialEq<Self> {
+ // this method is used solely by #[deriving] to assert
+ // that every component of a type implements #[deriving]
+ // itself, the current deriving infrastructure means doing this
+ // assertion without using a method on this trait is nearly
+ // impossible.
+ //
+ // This should never be implemented by hand.
+ #[doc(hidden)]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn assert_receiver_is_total_eq(&self) {}
+ }
+
+ #[lang = "partial_ord"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[doc(alias = ">")]
+ #[doc(alias = "<")]
+ #[doc(alias = "<=")]
+ #[doc(alias = ">=")]
+ // #[rustc_on_unimplemented(
+ // message = "can't compare `{Self}` with `{Rhs}`",
+ // label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`"
+ // )]
+ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
+ /// This method returns an ordering between `self` and `other` values if one exists.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::cmp::Ordering;
+ ///
+ /// let result = 1.0.partial_cmp(&2.0);
+ /// assert_eq!(result, Some(Ordering::Less));
+ ///
+ /// let result = 1.0.partial_cmp(&1.0);
+ /// assert_eq!(result, Some(Ordering::Equal));
+ ///
+ /// let result = 2.0.partial_cmp(&1.0);
+ /// assert_eq!(result, Some(Ordering::Greater));
+ /// ```
+ ///
+ /// When comparison is impossible:
+ ///
+ /// ```
+ /// let result = f64::NAN.partial_cmp(&1.0);
+ /// assert_eq!(result, None);
+ /// ```
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+
+ /// This method tests less than (for `self` and `other`) and is used by the `<` operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 < 2.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 < 1.0;
+ /// assert_eq!(result, false);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn lt(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Less) => true,
+ _ => false,
+ }
+ }
+
+ /// This method tests less than or equal to (for `self` and `other`) and is used by the `<=`
+ /// operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 <= 2.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 <= 2.0;
+ /// assert_eq!(result, true);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn le(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Less | Ordering::Equal) => true,
+ _ => false,
+ }
+ }
+
+ /// This method tests greater than (for `self` and `other`) and is used by the `>` operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 > 2.0;
+ /// assert_eq!(result, false);
+ ///
+ /// let result = 2.0 > 2.0;
+ /// assert_eq!(result, false);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn gt(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Greater) => true,
+ _ => false,
+ }
+ }
+
+ /// This method tests greater than or equal to (for `self` and `other`) and is used by the `>=`
+ /// operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 2.0 >= 1.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 >= 2.0;
+ /// assert_eq!(result, true);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn ge(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Greater | Ordering::Equal) => true,
+ _ => false,
+ }
+ }
+ }
+
+ #[doc(alias = "<")]
+ #[doc(alias = ">")]
+ #[doc(alias = "<=")]
+ #[doc(alias = ">=")]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub trait Ord: Eq + PartialOrd<Self> {
+ /// This method returns an [`Ordering`] between `self` and `other`.
+ ///
+ /// By convention, `self.cmp(&other)` returns the ordering matching the expression
+ /// `self <operator> other` if true.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::cmp::Ordering;
+ ///
+ /// assert_eq!(5.cmp(&10), Ordering::Less);
+ /// assert_eq!(10.cmp(&5), Ordering::Greater);
+ /// assert_eq!(5.cmp(&5), Ordering::Equal);
+ /// ```
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn cmp(&self, other: &Self) -> Ordering;
+
+ /// Compares and returns the maximum of two values.
+ ///
+ /// Returns the second argument if the comparison determines them to be equal.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// assert_eq!(2, 1.max(2));
+ /// assert_eq!(2, 2.max(2));
+ /// ```
+ #[stable(feature = "ord_max_min", since = "1.21.0")]
+ #[must_use]
+ fn max(self, other: Self) -> Self
+ where
+ Self: Sized,
+ {
+ self
+ }
+
+ /// Compares and returns the minimum of two values.
+ ///
+ /// Returns the first argument if the comparison determines them to be equal.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// assert_eq!(1, 1.min(2));
+ /// assert_eq!(2, 2.min(2));
+ /// ```
+ #[stable(feature = "ord_max_min", since = "1.21.0")]
+ #[must_use]
+ fn min(self, other: Self) -> Self
+ where
+ Self: Sized,
+ {
+ self
+ }
+
+ /// Restrict a value to a certain interval.
+ ///
+ /// Returns `max` if `self` is greater than `max`, and `min` if `self` is
+ /// less than `min`. Otherwise this returns `self`.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `min > max`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(clamp)]
+ ///
+ /// assert!((-3).clamp(-2, 1) == -2);
+ /// assert!(0.clamp(-2, 1) == 0);
+ /// assert!(2.clamp(-2, 1) == 1);
+ /// ```
+ #[must_use]
+ #[unstable(feature = "clamp", issue = "44095")]
+ fn clamp(self, min: Self, max: Self) -> Self
+ where
+ Self: Sized,
+ {
+ if self < min {
+ min
+ } else if self > max {
+ max
+ } else {
+ self
+ }
+ }
+ }
+ }
+
+ pub mod intrinsics {
+ #[lang = "discriminant_kind"]
+ pub trait DiscriminantKind {
+ #[lang = "discriminant_type"]
+ type Discriminant;
+ }
+
+ extern "rust-intrinsic" {
+ pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
+ }
+ }
+}
+
+use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
+use core::marker::Sized;
+use core::option::Option;
+
+// for comparing discriminant_value
+impl PartialEq for isize {
+ fn eq(&self, other: &Self) -> bool {
+ *self == *other
+ }
+}
+
+// for comparing discriminant_value
+impl PartialOrd for isize {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ if *self > *other {
+ Option::Some(Ordering::Greater)
+ } else if *self < *other {
+ Option::Some(Ordering::Less)
+ } else {
+ Option::Some(Ordering::Equal)
+ }
+ }
+
+ fn lt(&self, other: &Self) -> bool {
+ *self < *other
+ }
+ fn le(&self, other: &Self) -> bool {
+ *self <= *other
+ }
+ fn ge(&self, other: &Self) -> bool {
+ *self >= *other
+ }
+ fn gt(&self, other: &Self) -> bool {
+ *self > *other
+ }
+}
+
+impl PartialEq for i32 {
+ fn eq(&self, other: &Self) -> bool {
+ *self == *other
+ }
+}
+impl Eq for i32 {}
+
+impl PartialOrd for i32 {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ if *self > *other {
+ Option::Some(Ordering::Greater)
+ } else if *self < *other {
+ Option::Some(Ordering::Less)
+ } else {
+ Option::Some(Ordering::Equal)
+ }
+ }
+
+ fn lt(&self, other: &Self) -> bool {
+ *self < *other
+ }
+ fn le(&self, other: &Self) -> bool {
+ *self <= *other
+ }
+ fn ge(&self, other: &Self) -> bool {
+ *self >= *other
+ }
+ fn gt(&self, other: &Self) -> bool {
+ *self > *other
+ }
+}
+
+impl Ord for i32 {
+ fn cmp(&self, other: &Self) -> Ordering {
+ if *self > *other {
+ Ordering::Greater
+ } else if *self < *other {
+ Ordering::Less
+ } else {
+ Ordering::Equal
+ }
+ }
+}
+
+#[derive(PartialEq, Eq)]
+struct Foo {
+ a: i32,
+}
+
+extern "C" {
+ fn puts(s: *const i8);
+}
+
+fn print(s: &str) {
+ unsafe {
+ puts(s as *const str as *const i8);
+ }
+}
+
+fn main() -> i32 {
+ let a = Foo { a: 42i32 };
+ let b = Foo { a: 42i32 };
+ let c = Foo { a: 7i32 };
+
+ if a == b {
+ print("a == b");
+ } else {
+ print("a != b");
+ }
+
+ if a == c {
+ print("a == c");
+ } else {
+ print("a != c");
+ }
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/partial-ord-1.rs b/gcc/testsuite/rust/execute/torture/partial-ord-1.rs
new file mode 100644
index 0000000..a3558e7
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/partial-ord-1.rs
@@ -0,0 +1,101 @@
+/* { dg-output "x == y\r*\nx > z\r*\n" }*/
+#[lang = "sized"]
+pub trait Sized {}
+
+pub enum Option<T> {
+ #[lang = "None"]
+ None,
+ #[lang = "Some"]
+ Some(T),
+}
+
+use Option::{None, Some};
+
+#[lang = "eq"]
+pub trait PartialEq<Rhs: ?Sized = Self> {
+ fn eq(&self, other: &Rhs) -> bool;
+
+ fn ne(&self, other: &Rhs) -> bool {
+ !self.eq(other)
+ }
+}
+
+pub enum Ordering {
+ Less = -1,
+ Equal = 0,
+ Greater = 1,
+}
+
+#[lang = "partial_ord"]
+pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
+ fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+}
+
+// Implement for i32
+impl PartialEq for i32 {
+ fn eq(&self, other: &Self) -> bool {
+ *self == *other
+ }
+}
+
+// Implement PartialOrd for i32
+impl PartialOrd for i32 {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ if *self < *other {
+ Some(Ordering::Less)
+ } else if *self > *other {
+ Some(Ordering::Greater)
+ } else {
+ Some(Ordering::Equal)
+ }
+ }
+}
+
+// Struct with manual PartialEq
+struct Foo {
+ a: i32,
+}
+
+impl PartialEq for Foo {
+ fn eq(&self, other: &Self) -> bool {
+ self.a.eq(&other.a)
+ }
+}
+
+impl PartialOrd for Foo {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ self.a.partial_cmp(&other.a)
+ }
+}
+
+extern "C" {
+ fn puts(s: *const i8);
+}
+
+fn print(s: &str) {
+ unsafe {
+ puts(s as *const str as *const i8);
+ }
+}
+
+fn main() -> i32 {
+ let x = Foo { a: 42 };
+ let y = Foo { a: 42 };
+ let z = Foo { a: 7 };
+
+ match x.partial_cmp(&y) {
+ Some(Ordering::Equal) => print("x == y"),
+ Some(Ordering::Less) => print("x < y"),
+ Some(Ordering::Greater) => print("x > y"),
+ None => print("x ? y"),
+ }
+
+ match x.partial_cmp(&z) {
+ Some(Ordering::Equal) => print("x == z"),
+ Some(Ordering::Less) => print("x < z"),
+ Some(Ordering::Greater) => print("x > z"),
+ None => print("x ? z"),
+ }
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/partial-ord-2.rs b/gcc/testsuite/rust/execute/torture/partial-ord-2.rs
new file mode 100644
index 0000000..d3b713f
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/partial-ord-2.rs
@@ -0,0 +1,469 @@
+/* { dg-output "x == y\r*\nx > z\r*\n" }*/
+
+#![feature(intrinsics)]
+
+mod core {
+ mod option {
+ // #[rustc_diagnostic_item = "option_type"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub enum Option<T> {
+ /// No value
+ #[lang = "None"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ None,
+ /// Some value `T`
+ #[lang = "Some"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Some(#[stable(feature = "rust1", since = "1.0.0")] T),
+ }
+ }
+
+ mod marker {
+ #[lang = "phantom_data"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub struct PhantomData<T: ?Sized>;
+
+ #[unstable(feature = "structural_match", issue = "31434")]
+ // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(PartialEq)]`")]
+ #[lang = "structural_peq"]
+ pub trait StructuralPartialEq {
+ // Empty.
+ }
+
+ #[unstable(feature = "structural_match", issue = "31434")]
+ // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(Eq)]`")]
+ #[lang = "structural_teq"]
+ pub trait StructuralEq {
+ // Empty.
+ }
+
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[lang = "sized"]
+ // #[rustc_on_unimplemented(
+ // message = "the size for values of type `{Self}` cannot be known at compilation time",
+ // label = "doesn't have a size known at compile-time"
+ // )]
+ // #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
+ // #[rustc_specialization_trait]
+ pub trait Sized {
+ // Empty.
+ }
+ }
+
+ mod cmp {
+ use super::marker::Sized;
+ use super::option::Option;
+
+ // #[derive(Clone, Copy, PartialEq, Debug, Hash)]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub enum Ordering {
+ /// An ordering where a compared value is less than another.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Less = -1,
+ /// An ordering where a compared value is equal to another.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Equal = 0,
+ /// An ordering where a compared value is greater than another.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Greater = 1,
+ }
+
+ #[lang = "eq"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[doc(alias = "==")]
+ #[doc(alias = "!=")]
+ // #[rustc_on_unimplemented(
+ // message = "can't compare `{Self}` with `{Rhs}`",
+ // label = "no implementation for `{Self} == {Rhs}`"
+ // )]
+ pub trait PartialEq<Rhs: ?Sized = Self> {
+ /// This method tests for `self` and `other` values to be equal, and is used
+ /// by `==`.
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn eq(&self, other: &Rhs) -> bool;
+
+ fn ne(&self, other: &Rhs) -> bool {
+ !self.eq(other)
+ }
+ }
+
+ #[doc(alias = "==")]
+ #[doc(alias = "!=")]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub trait Eq: PartialEq<Self> {
+ // this method is used solely by #[deriving] to assert
+ // that every component of a type implements #[deriving]
+ // itself, the current deriving infrastructure means doing this
+ // assertion without using a method on this trait is nearly
+ // impossible.
+ //
+ // This should never be implemented by hand.
+ #[doc(hidden)]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn assert_receiver_is_total_eq(&self) {}
+ }
+
+ #[lang = "partial_ord"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[doc(alias = ">")]
+ #[doc(alias = "<")]
+ #[doc(alias = "<=")]
+ #[doc(alias = ">=")]
+ // #[rustc_on_unimplemented(
+ // message = "can't compare `{Self}` with `{Rhs}`",
+ // label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`"
+ // )]
+ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
+ /// This method returns an ordering between `self` and `other` values if one exists.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::cmp::Ordering;
+ ///
+ /// let result = 1.0.partial_cmp(&2.0);
+ /// assert_eq!(result, Some(Ordering::Less));
+ ///
+ /// let result = 1.0.partial_cmp(&1.0);
+ /// assert_eq!(result, Some(Ordering::Equal));
+ ///
+ /// let result = 2.0.partial_cmp(&1.0);
+ /// assert_eq!(result, Some(Ordering::Greater));
+ /// ```
+ ///
+ /// When comparison is impossible:
+ ///
+ /// ```
+ /// let result = f64::NAN.partial_cmp(&1.0);
+ /// assert_eq!(result, None);
+ /// ```
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+
+ /// This method tests less than (for `self` and `other`) and is used by the `<` operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 < 2.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 < 1.0;
+ /// assert_eq!(result, false);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn lt(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Less) => true,
+ _ => false,
+ }
+ }
+
+ /// This method tests less than or equal to (for `self` and `other`) and is used by the `<=`
+ /// operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 <= 2.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 <= 2.0;
+ /// assert_eq!(result, true);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn le(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Less | Ordering::Equal) => true,
+ _ => false,
+ }
+ }
+
+ /// This method tests greater than (for `self` and `other`) and is used by the `>` operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 > 2.0;
+ /// assert_eq!(result, false);
+ ///
+ /// let result = 2.0 > 2.0;
+ /// assert_eq!(result, false);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn gt(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Greater) => true,
+ _ => false,
+ }
+ }
+
+ /// This method tests greater than or equal to (for `self` and `other`) and is used by the `>=`
+ /// operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 2.0 >= 1.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 >= 2.0;
+ /// assert_eq!(result, true);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn ge(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Greater | Ordering::Equal) => true,
+ _ => false,
+ }
+ }
+ }
+
+ #[doc(alias = "<")]
+ #[doc(alias = ">")]
+ #[doc(alias = "<=")]
+ #[doc(alias = ">=")]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub trait Ord: Eq + PartialOrd<Self> {
+ /// This method returns an [`Ordering`] between `self` and `other`.
+ ///
+ /// By convention, `self.cmp(&other)` returns the ordering matching the expression
+ /// `self <operator> other` if true.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::cmp::Ordering;
+ ///
+ /// assert_eq!(5.cmp(&10), Ordering::Less);
+ /// assert_eq!(10.cmp(&5), Ordering::Greater);
+ /// assert_eq!(5.cmp(&5), Ordering::Equal);
+ /// ```
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn cmp(&self, other: &Self) -> Ordering;
+
+ /// Compares and returns the maximum of two values.
+ ///
+ /// Returns the second argument if the comparison determines them to be equal.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// assert_eq!(2, 1.max(2));
+ /// assert_eq!(2, 2.max(2));
+ /// ```
+ #[stable(feature = "ord_max_min", since = "1.21.0")]
+ #[must_use]
+ fn max(self, other: Self) -> Self
+ where
+ Self: Sized,
+ {
+ self
+ }
+
+ /// Compares and returns the minimum of two values.
+ ///
+ /// Returns the first argument if the comparison determines them to be equal.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// assert_eq!(1, 1.min(2));
+ /// assert_eq!(2, 2.min(2));
+ /// ```
+ #[stable(feature = "ord_max_min", since = "1.21.0")]
+ #[must_use]
+ fn min(self, other: Self) -> Self
+ where
+ Self: Sized,
+ {
+ self
+ }
+
+ /// Restrict a value to a certain interval.
+ ///
+ /// Returns `max` if `self` is greater than `max`, and `min` if `self` is
+ /// less than `min`. Otherwise this returns `self`.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `min > max`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(clamp)]
+ ///
+ /// assert!((-3).clamp(-2, 1) == -2);
+ /// assert!(0.clamp(-2, 1) == 0);
+ /// assert!(2.clamp(-2, 1) == 1);
+ /// ```
+ #[must_use]
+ #[unstable(feature = "clamp", issue = "44095")]
+ fn clamp(self, min: Self, max: Self) -> Self
+ where
+ Self: Sized,
+ {
+ if self < min {
+ min
+ } else if self > max {
+ max
+ } else {
+ self
+ }
+ }
+ }
+ }
+
+ pub mod intrinsics {
+ #[lang = "discriminant_kind"]
+ pub trait DiscriminantKind {
+ #[lang = "discriminant_type"]
+ type Discriminant;
+ }
+
+ extern "rust-intrinsic" {
+ pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
+ }
+ }
+}
+
+use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
+use core::marker::Sized;
+use core::option::Option;
+
+// for comparing discriminant_value
+impl PartialEq for isize {
+ fn eq(&self, other: &Self) -> bool {
+ *self == *other
+ }
+}
+
+// for comparing discriminant_value
+impl PartialOrd for isize {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ if *self > *other {
+ Option::Some(Ordering::Greater)
+ } else if *self < *other {
+ Option::Some(Ordering::Less)
+ } else {
+ Option::Some(Ordering::Equal)
+ }
+ }
+
+ fn lt(&self, other: &Self) -> bool {
+ *self < *other
+ }
+ fn le(&self, other: &Self) -> bool {
+ *self <= *other
+ }
+ fn ge(&self, other: &Self) -> bool {
+ *self >= *other
+ }
+ fn gt(&self, other: &Self) -> bool {
+ *self > *other
+ }
+}
+
+impl PartialEq for i32 {
+ fn eq(&self, other: &Self) -> bool {
+ *self == *other
+ }
+}
+impl Eq for i32 {}
+
+impl PartialOrd for i32 {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ if *self > *other {
+ Option::Some(Ordering::Greater)
+ } else if *self < *other {
+ Option::Some(Ordering::Less)
+ } else {
+ Option::Some(Ordering::Equal)
+ }
+ }
+
+ fn lt(&self, other: &Self) -> bool {
+ *self < *other
+ }
+ fn le(&self, other: &Self) -> bool {
+ *self <= *other
+ }
+ fn ge(&self, other: &Self) -> bool {
+ *self >= *other
+ }
+ fn gt(&self, other: &Self) -> bool {
+ *self > *other
+ }
+}
+
+impl Ord for i32 {
+ fn cmp(&self, other: &Self) -> Ordering {
+ if *self > *other {
+ Ordering::Greater
+ } else if *self < *other {
+ Ordering::Less
+ } else {
+ Ordering::Equal
+ }
+ }
+}
+
+struct Foo {
+ a: i32,
+}
+
+impl PartialEq for Foo {
+ fn eq(&self, other: &'_ Self) -> bool {
+ self.a == other.a
+ }
+}
+
+impl PartialOrd for Foo {
+ fn partial_cmp(&self, other: &'_ Foo) -> Option<::core::cmp::Ordering> {
+ self.a.partial_cmp(&other.a)
+ }
+}
+
+extern "C" {
+ fn puts(s: *const i8);
+}
+
+fn print(s: &str) {
+ unsafe {
+ puts(s as *const str as *const i8);
+ }
+}
+
+fn main() -> i32 {
+ let x = Foo { a: 42 };
+ let y = Foo { a: 42 };
+ let z = Foo { a: 7 };
+
+ match x.partial_cmp(&y) {
+ Option::Some(Ordering::Equal) => print("x == y"),
+ Option::Some(Ordering::Less) => print("x < y"),
+ Option::Some(Ordering::Greater) => print("x > y"),
+ Option::None => print("x ? y"),
+ }
+
+ match x.partial_cmp(&z) {
+ Option::Some(Ordering::Equal) => print("x == z"),
+ Option::Some(Ordering::Less) => print("x < z"),
+ Option::Some(Ordering::Greater) => print("x > z"),
+ Option::None => print("x ? z"),
+ }
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/partial-ord-3.rs b/gcc/testsuite/rust/execute/torture/partial-ord-3.rs
new file mode 100644
index 0000000..7aec07c
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/partial-ord-3.rs
@@ -0,0 +1,489 @@
+/* { dg-output "x == y\r*\nx > z\r*\nx < z\r*\nx >= y\r*\nx <= y\r*\n" } */
+/* { dg-options "-w" } */
+
+#![feature(intrinsics)]
+
+mod core {
+ mod option {
+ // #[rustc_diagnostic_item = "option_type"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub enum Option<T> {
+ /// No value
+ #[lang = "None"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ None,
+ /// Some value `T`
+ #[lang = "Some"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Some(#[stable(feature = "rust1", since = "1.0.0")] T),
+ }
+ }
+
+ mod marker {
+ #[lang = "phantom_data"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub struct PhantomData<T: ?Sized>;
+
+ #[unstable(feature = "structural_match", issue = "31434")]
+ // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(PartialEq)]`")]
+ #[lang = "structural_peq"]
+ pub trait StructuralPartialEq {
+ // Empty.
+ }
+
+ #[unstable(feature = "structural_match", issue = "31434")]
+ // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(Eq)]`")]
+ #[lang = "structural_teq"]
+ pub trait StructuralEq {
+ // Empty.
+ }
+
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[lang = "sized"]
+ // #[rustc_on_unimplemented(
+ // message = "the size for values of type `{Self}` cannot be known at compilation time",
+ // label = "doesn't have a size known at compile-time"
+ // )]
+ // #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
+ // #[rustc_specialization_trait]
+ pub trait Sized {
+ // Empty.
+ }
+ }
+
+ mod cmp {
+ use super::marker::Sized;
+ use super::option::Option;
+
+ // #[derive(Clone, Copy, PartialEq, Debug, Hash)]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub enum Ordering {
+ /// An ordering where a compared value is less than another.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Less = -1,
+ /// An ordering where a compared value is equal to another.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Equal = 0,
+ /// An ordering where a compared value is greater than another.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Greater = 1,
+ }
+
+ #[lang = "eq"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[doc(alias = "==")]
+ #[doc(alias = "!=")]
+ // #[rustc_on_unimplemented(
+ // message = "can't compare `{Self}` with `{Rhs}`",
+ // label = "no implementation for `{Self} == {Rhs}`"
+ // )]
+ pub trait PartialEq<Rhs: ?Sized = Self> {
+ /// This method tests for `self` and `other` values to be equal, and is used
+ /// by `==`.
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn eq(&self, other: &Rhs) -> bool;
+
+ fn ne(&self, other: &Rhs) -> bool {
+ !self.eq(other)
+ }
+ }
+
+ #[doc(alias = "==")]
+ #[doc(alias = "!=")]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub trait Eq: PartialEq<Self> {
+ // this method is used solely by #[deriving] to assert
+ // that every component of a type implements #[deriving]
+ // itself, the current deriving infrastructure means doing this
+ // assertion without using a method on this trait is nearly
+ // impossible.
+ //
+ // This should never be implemented by hand.
+ #[doc(hidden)]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn assert_receiver_is_total_eq(&self) {}
+ }
+
+ #[lang = "partial_ord"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[doc(alias = ">")]
+ #[doc(alias = "<")]
+ #[doc(alias = "<=")]
+ #[doc(alias = ">=")]
+ // #[rustc_on_unimplemented(
+ // message = "can't compare `{Self}` with `{Rhs}`",
+ // label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`"
+ // )]
+ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
+ /// This method returns an ordering between `self` and `other` values if one exists.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::cmp::Ordering;
+ ///
+ /// let result = 1.0.partial_cmp(&2.0);
+ /// assert_eq!(result, Some(Ordering::Less));
+ ///
+ /// let result = 1.0.partial_cmp(&1.0);
+ /// assert_eq!(result, Some(Ordering::Equal));
+ ///
+ /// let result = 2.0.partial_cmp(&1.0);
+ /// assert_eq!(result, Some(Ordering::Greater));
+ /// ```
+ ///
+ /// When comparison is impossible:
+ ///
+ /// ```
+ /// let result = f64::NAN.partial_cmp(&1.0);
+ /// assert_eq!(result, None);
+ /// ```
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+
+ /// This method tests less than (for `self` and `other`) and is used by the `<` operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 < 2.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 < 1.0;
+ /// assert_eq!(result, false);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn lt(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Less) => true,
+ _ => false,
+ }
+ }
+
+ /// This method tests less than or equal to (for `self` and `other`) and is used by the `<=`
+ /// operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 <= 2.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 <= 2.0;
+ /// assert_eq!(result, true);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn le(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Less | Ordering::Equal) => true,
+ _ => false,
+ }
+ }
+
+ /// This method tests greater than (for `self` and `other`) and is used by the `>` operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 > 2.0;
+ /// assert_eq!(result, false);
+ ///
+ /// let result = 2.0 > 2.0;
+ /// assert_eq!(result, false);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn gt(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Greater) => true,
+ _ => false,
+ }
+ }
+
+ /// This method tests greater than or equal to (for `self` and `other`) and is used by the `>=`
+ /// operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 2.0 >= 1.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 >= 2.0;
+ /// assert_eq!(result, true);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn ge(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Greater | Ordering::Equal) => true,
+ _ => false,
+ }
+ }
+ }
+
+ #[doc(alias = "<")]
+ #[doc(alias = ">")]
+ #[doc(alias = "<=")]
+ #[doc(alias = ">=")]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub trait Ord: Eq + PartialOrd<Self> {
+ /// This method returns an [`Ordering`] between `self` and `other`.
+ ///
+ /// By convention, `self.cmp(&other)` returns the ordering matching the expression
+ /// `self <operator> other` if true.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::cmp::Ordering;
+ ///
+ /// assert_eq!(5.cmp(&10), Ordering::Less);
+ /// assert_eq!(10.cmp(&5), Ordering::Greater);
+ /// assert_eq!(5.cmp(&5), Ordering::Equal);
+ /// ```
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn cmp(&self, other: &Self) -> Ordering;
+
+ /// Compares and returns the maximum of two values.
+ ///
+ /// Returns the second argument if the comparison determines them to be equal.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// assert_eq!(2, 1.max(2));
+ /// assert_eq!(2, 2.max(2));
+ /// ```
+ #[stable(feature = "ord_max_min", since = "1.21.0")]
+ #[must_use]
+ fn max(self, other: Self) -> Self
+ where
+ Self: Sized,
+ {
+ self
+ }
+
+ /// Compares and returns the minimum of two values.
+ ///
+ /// Returns the first argument if the comparison determines them to be equal.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// assert_eq!(1, 1.min(2));
+ /// assert_eq!(2, 2.min(2));
+ /// ```
+ #[stable(feature = "ord_max_min", since = "1.21.0")]
+ #[must_use]
+ fn min(self, other: Self) -> Self
+ where
+ Self: Sized,
+ {
+ self
+ }
+
+ /// Restrict a value to a certain interval.
+ ///
+ /// Returns `max` if `self` is greater than `max`, and `min` if `self` is
+ /// less than `min`. Otherwise this returns `self`.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `min > max`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(clamp)]
+ ///
+ /// assert!((-3).clamp(-2, 1) == -2);
+ /// assert!(0.clamp(-2, 1) == 0);
+ /// assert!(2.clamp(-2, 1) == 1);
+ /// ```
+ #[must_use]
+ #[unstable(feature = "clamp", issue = "44095")]
+ fn clamp(self, min: Self, max: Self) -> Self
+ where
+ Self: Sized,
+ {
+ if self < min {
+ min
+ } else if self > max {
+ max
+ } else {
+ self
+ }
+ }
+ }
+ }
+
+ pub mod intrinsics {
+ #[lang = "discriminant_kind"]
+ pub trait DiscriminantKind {
+ #[lang = "discriminant_type"]
+ type Discriminant;
+ }
+
+ extern "rust-intrinsic" {
+ pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
+ }
+ }
+}
+
+use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
+use core::marker::Sized;
+use core::option::Option;
+
+// for comparing discriminant_value
+impl PartialEq for isize {
+ fn eq(&self, other: &Self) -> bool {
+ *self == *other
+ }
+}
+
+// for comparing discriminant_value
+impl PartialOrd for isize {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ if *self > *other {
+ Option::Some(Ordering::Greater)
+ } else if *self < *other {
+ Option::Some(Ordering::Less)
+ } else {
+ Option::Some(Ordering::Equal)
+ }
+ }
+
+ fn lt(&self, other: &Self) -> bool {
+ *self < *other
+ }
+ fn le(&self, other: &Self) -> bool {
+ *self <= *other
+ }
+ fn ge(&self, other: &Self) -> bool {
+ *self >= *other
+ }
+ fn gt(&self, other: &Self) -> bool {
+ *self > *other
+ }
+}
+
+impl PartialEq for i32 {
+ fn eq(&self, other: &Self) -> bool {
+ *self == *other
+ }
+}
+impl Eq for i32 {}
+
+impl PartialOrd for i32 {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ if *self > *other {
+ Option::Some(Ordering::Greater)
+ } else if *self < *other {
+ Option::Some(Ordering::Less)
+ } else {
+ Option::Some(Ordering::Equal)
+ }
+ }
+
+ fn lt(&self, other: &Self) -> bool {
+ *self < *other
+ }
+ fn le(&self, other: &Self) -> bool {
+ *self <= *other
+ }
+ fn ge(&self, other: &Self) -> bool {
+ *self >= *other
+ }
+ fn gt(&self, other: &Self) -> bool {
+ *self > *other
+ }
+}
+
+impl Ord for i32 {
+ fn cmp(&self, other: &Self) -> Ordering {
+ if *self > *other {
+ Ordering::Greater
+ } else if *self < *other {
+ Ordering::Less
+ } else {
+ Ordering::Equal
+ }
+ }
+}
+
+struct Foo {
+ a: i32,
+}
+
+impl PartialEq for Foo {
+ fn eq(&self, other: &Self) -> bool {
+ self.a == other.a
+ }
+}
+impl Eq for Foo {}
+
+impl PartialOrd for Foo {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ self.a.partial_cmp(&other.a)
+ }
+}
+
+impl Ord for Foo {
+ fn cmp(&self, other: &Self) -> Ordering {
+ self.a.cmp(&other.a)
+ }
+}
+
+extern "C" {
+ fn puts(s: *const i8);
+}
+
+fn print(s: &str) {
+ unsafe {
+ puts(s as *const str as *const i8);
+ }
+}
+
+fn main() -> i32 {
+ let x = Foo { a: 42 };
+ let y = Foo { a: 42 };
+ let z = Foo { a: 7 };
+
+ // test direct equality
+ if x == y {
+ print("x == y");
+ }
+
+ // test PartialOrd via match
+ match x.partial_cmp(&z) {
+ Option::Some(Ordering::Greater) => print("x > z"),
+ _ => print("x ? z"),
+ }
+
+ // test `<` directly
+ if z < x {
+ print("x < z");
+ }
+
+ // test `>=`
+ if x >= y {
+ print("x >= y");
+ }
+
+ // test `<=`
+ if x <= y {
+ print("x <= y");
+ }
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/partial-ord-4.rs b/gcc/testsuite/rust/execute/torture/partial-ord-4.rs
new file mode 100644
index 0000000..fd52f32
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/partial-ord-4.rs
@@ -0,0 +1,115 @@
+/* { dg-output "a == b\r*\na != c\r*\n" }*/
+/* { dg-options "-w" } */
+
+#![feature(intrinsics)]
+
+mod core {
+ mod option {
+ pub enum Option<T> {
+ #[lang = "None"]
+ None,
+ #[lang = "Some"]
+ Some(T),
+ }
+ }
+
+ mod marker {
+ #[lang = "sized"]
+ pub trait Sized {}
+ }
+
+ mod cmp {
+ use super::marker::Sized;
+ use super::option::Option;
+
+ pub enum Ordering {
+ Less = -1,
+ Equal = 0,
+ Greater = 1,
+ }
+
+ #[lang = "eq"]
+ pub trait PartialEq<Rhs: ?Sized = Self> {
+ fn eq(&self, other: &Rhs) -> bool;
+
+ fn ne(&self, other: &Rhs) -> bool {
+ !self.eq(other)
+ }
+ }
+
+ #[lang = "partial_ord"]
+ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+ }
+ }
+}
+
+use core::cmp::{Ordering, PartialEq, PartialOrd};
+use core::marker::Sized;
+use core::option::Option;
+
+impl PartialEq for i32 {
+ fn eq(&self, other: &Self) -> bool {
+ *self == *other
+ }
+}
+
+impl PartialOrd for i32 {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ if *self > *other {
+ Option::Some(Ordering::Greater)
+ } else if *self < *other {
+ Option::Some(Ordering::Less)
+ } else {
+ Option::Some(Ordering::Equal)
+ }
+ }
+}
+
+struct Foo {
+ a: i32,
+}
+
+impl PartialEq for Foo {
+ fn eq(&self, other: &'_ Self) -> bool {
+ self.a == other.a
+ }
+}
+
+impl PartialOrd for Foo {
+ fn partial_cmp(&self, other: &'_ Foo) -> Option<::core::cmp::Ordering> {
+ ::core::cmp::PartialOrd::partial_cmp(&self.a, &other.a)
+ }
+}
+
+extern "C" {
+ fn puts(s: *const i8);
+}
+
+fn print(s: &str) {
+ unsafe {
+ puts(s as *const str as *const i8);
+ }
+}
+
+fn main() -> i32 {
+ let a = Foo { a: 42i32 };
+ let b = Foo { a: 42i32 };
+ let c = Foo { a: 7i32 };
+
+ if a == b {
+ print("a == b");
+ } else {
+ print("a != b");
+ }
+
+ if a == c {
+ print("a == c");
+ } else {
+ print("a != c");
+ }
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/partial-ord-5.rs b/gcc/testsuite/rust/execute/torture/partial-ord-5.rs
new file mode 100644
index 0000000..721d2aa
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/partial-ord-5.rs
@@ -0,0 +1,487 @@
+/* { dg-output "a == b\r*\na != c\r*\na >= c\r*\na <= b\r*\na > c\r*\nc < b\r*\n" } */
+/* { dg-options "-w" } */
+
+#![feature(intrinsics)]
+
+mod core {
+ mod option {
+ // #[rustc_diagnostic_item = "option_type"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub enum Option<T> {
+ /// No value
+ #[lang = "None"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ None,
+ /// Some value `T`
+ #[lang = "Some"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Some(#[stable(feature = "rust1", since = "1.0.0")] T),
+ }
+ }
+
+ mod marker {
+ #[lang = "phantom_data"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub struct PhantomData<T: ?Sized>;
+
+ #[unstable(feature = "structural_match", issue = "31434")]
+ // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(PartialEq)]`")]
+ #[lang = "structural_peq"]
+ pub trait StructuralPartialEq {
+ // Empty.
+ }
+
+ #[unstable(feature = "structural_match", issue = "31434")]
+ // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(Eq)]`")]
+ #[lang = "structural_teq"]
+ pub trait StructuralEq {
+ // Empty.
+ }
+
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[lang = "sized"]
+ // #[rustc_on_unimplemented(
+ // message = "the size for values of type `{Self}` cannot be known at compilation time",
+ // label = "doesn't have a size known at compile-time"
+ // )]
+ // #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
+ // #[rustc_specialization_trait]
+ pub trait Sized {
+ // Empty.
+ }
+ }
+
+ mod cmp {
+ use super::marker::Sized;
+ use super::option::Option;
+
+ // #[derive(Clone, Copy, PartialEq, Debug, Hash)]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub enum Ordering {
+ /// An ordering where a compared value is less than another.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Less = -1,
+ /// An ordering where a compared value is equal to another.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Equal = 0,
+ /// An ordering where a compared value is greater than another.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Greater = 1,
+ }
+
+ #[lang = "eq"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[doc(alias = "==")]
+ #[doc(alias = "!=")]
+ // #[rustc_on_unimplemented(
+ // message = "can't compare `{Self}` with `{Rhs}`",
+ // label = "no implementation for `{Self} == {Rhs}`"
+ // )]
+ pub trait PartialEq<Rhs: ?Sized = Self> {
+ /// This method tests for `self` and `other` values to be equal, and is used
+ /// by `==`.
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn eq(&self, other: &Rhs) -> bool;
+
+ fn ne(&self, other: &Rhs) -> bool {
+ !self.eq(other)
+ }
+ }
+
+ #[doc(alias = "==")]
+ #[doc(alias = "!=")]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub trait Eq: PartialEq<Self> {
+ // this method is used solely by #[deriving] to assert
+ // that every component of a type implements #[deriving]
+ // itself, the current deriving infrastructure means doing this
+ // assertion without using a method on this trait is nearly
+ // impossible.
+ //
+ // This should never be implemented by hand.
+ #[doc(hidden)]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn assert_receiver_is_total_eq(&self) {}
+ }
+
+ #[lang = "partial_ord"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[doc(alias = ">")]
+ #[doc(alias = "<")]
+ #[doc(alias = "<=")]
+ #[doc(alias = ">=")]
+ // #[rustc_on_unimplemented(
+ // message = "can't compare `{Self}` with `{Rhs}`",
+ // label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`"
+ // )]
+ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
+ /// This method returns an ordering between `self` and `other` values if one exists.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::cmp::Ordering;
+ ///
+ /// let result = 1.0.partial_cmp(&2.0);
+ /// assert_eq!(result, Some(Ordering::Less));
+ ///
+ /// let result = 1.0.partial_cmp(&1.0);
+ /// assert_eq!(result, Some(Ordering::Equal));
+ ///
+ /// let result = 2.0.partial_cmp(&1.0);
+ /// assert_eq!(result, Some(Ordering::Greater));
+ /// ```
+ ///
+ /// When comparison is impossible:
+ ///
+ /// ```
+ /// let result = f64::NAN.partial_cmp(&1.0);
+ /// assert_eq!(result, None);
+ /// ```
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+
+ /// This method tests less than (for `self` and `other`) and is used by the `<` operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 < 2.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 < 1.0;
+ /// assert_eq!(result, false);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn lt(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Less) => true,
+ _ => false,
+ }
+ }
+
+ /// This method tests less than or equal to (for `self` and `other`) and is used by the `<=`
+ /// operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 <= 2.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 <= 2.0;
+ /// assert_eq!(result, true);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn le(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Less | Ordering::Equal) => true,
+ _ => false,
+ }
+ }
+
+ /// This method tests greater than (for `self` and `other`) and is used by the `>` operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 > 2.0;
+ /// assert_eq!(result, false);
+ ///
+ /// let result = 2.0 > 2.0;
+ /// assert_eq!(result, false);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn gt(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Greater) => true,
+ _ => false,
+ }
+ }
+
+ /// This method tests greater than or equal to (for `self` and `other`) and is used by the `>=`
+ /// operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 2.0 >= 1.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 >= 2.0;
+ /// assert_eq!(result, true);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn ge(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Greater | Ordering::Equal) => true,
+ _ => false,
+ }
+ }
+ }
+
+ #[doc(alias = "<")]
+ #[doc(alias = ">")]
+ #[doc(alias = "<=")]
+ #[doc(alias = ">=")]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub trait Ord: Eq + PartialOrd<Self> {
+ /// This method returns an [`Ordering`] between `self` and `other`.
+ ///
+ /// By convention, `self.cmp(&other)` returns the ordering matching the expression
+ /// `self <operator> other` if true.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::cmp::Ordering;
+ ///
+ /// assert_eq!(5.cmp(&10), Ordering::Less);
+ /// assert_eq!(10.cmp(&5), Ordering::Greater);
+ /// assert_eq!(5.cmp(&5), Ordering::Equal);
+ /// ```
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn cmp(&self, other: &Self) -> Ordering;
+
+ /// Compares and returns the maximum of two values.
+ ///
+ /// Returns the second argument if the comparison determines them to be equal.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// assert_eq!(2, 1.max(2));
+ /// assert_eq!(2, 2.max(2));
+ /// ```
+ #[stable(feature = "ord_max_min", since = "1.21.0")]
+ #[must_use]
+ fn max(self, other: Self) -> Self
+ where
+ Self: Sized,
+ {
+ self
+ }
+
+ /// Compares and returns the minimum of two values.
+ ///
+ /// Returns the first argument if the comparison determines them to be equal.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// assert_eq!(1, 1.min(2));
+ /// assert_eq!(2, 2.min(2));
+ /// ```
+ #[stable(feature = "ord_max_min", since = "1.21.0")]
+ #[must_use]
+ fn min(self, other: Self) -> Self
+ where
+ Self: Sized,
+ {
+ self
+ }
+
+ /// Restrict a value to a certain interval.
+ ///
+ /// Returns `max` if `self` is greater than `max`, and `min` if `self` is
+ /// less than `min`. Otherwise this returns `self`.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `min > max`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(clamp)]
+ ///
+ /// assert!((-3).clamp(-2, 1) == -2);
+ /// assert!(0.clamp(-2, 1) == 0);
+ /// assert!(2.clamp(-2, 1) == 1);
+ /// ```
+ #[must_use]
+ #[unstable(feature = "clamp", issue = "44095")]
+ fn clamp(self, min: Self, max: Self) -> Self
+ where
+ Self: Sized,
+ {
+ if self < min {
+ min
+ } else if self > max {
+ max
+ } else {
+ self
+ }
+ }
+ }
+ }
+
+ pub mod intrinsics {
+ #[lang = "discriminant_kind"]
+ pub trait DiscriminantKind {
+ #[lang = "discriminant_type"]
+ type Discriminant;
+ }
+
+ extern "rust-intrinsic" {
+ pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
+ }
+ }
+}
+
+use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
+use core::marker::Sized;
+use core::option::Option;
+
+// for comparing discriminant_value
+impl PartialEq for isize {
+ fn eq(&self, other: &Self) -> bool {
+ *self == *other
+ }
+}
+
+// for comparing discriminant_value
+impl PartialOrd for isize {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ if *self > *other {
+ Option::Some(Ordering::Greater)
+ } else if *self < *other {
+ Option::Some(Ordering::Less)
+ } else {
+ Option::Some(Ordering::Equal)
+ }
+ }
+
+ fn lt(&self, other: &Self) -> bool {
+ *self < *other
+ }
+ fn le(&self, other: &Self) -> bool {
+ *self <= *other
+ }
+ fn ge(&self, other: &Self) -> bool {
+ *self >= *other
+ }
+ fn gt(&self, other: &Self) -> bool {
+ *self > *other
+ }
+}
+
+impl PartialEq for i32 {
+ fn eq(&self, other: &Self) -> bool {
+ *self == *other
+ }
+}
+impl Eq for i32 {}
+
+impl PartialOrd for i32 {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ if *self > *other {
+ Option::Some(Ordering::Greater)
+ } else if *self < *other {
+ Option::Some(Ordering::Less)
+ } else {
+ Option::Some(Ordering::Equal)
+ }
+ }
+
+ fn lt(&self, other: &Self) -> bool {
+ *self < *other
+ }
+ fn le(&self, other: &Self) -> bool {
+ *self <= *other
+ }
+ fn ge(&self, other: &Self) -> bool {
+ *self >= *other
+ }
+ fn gt(&self, other: &Self) -> bool {
+ *self > *other
+ }
+}
+
+impl Ord for i32 {
+ fn cmp(&self, other: &Self) -> Ordering {
+ if *self > *other {
+ Ordering::Greater
+ } else if *self < *other {
+ Ordering::Less
+ } else {
+ Ordering::Equal
+ }
+ }
+}
+
+#[derive(PartialEq, Eq, Ord)]
+struct Foo {
+ a: i32,
+}
+
+impl PartialOrd for Foo {
+ fn partial_cmp(&self, other: &'_ Foo) -> Option<::core::cmp::Ordering> {
+ self.a.partial_cmp(&other.a)
+ }
+}
+
+extern "C" {
+ fn puts(s: *const i8);
+}
+
+fn print(s: &str) {
+ unsafe {
+ puts(s as *const str as *const i8);
+ }
+}
+
+fn main() -> i32 {
+ let a = Foo { a: 42 };
+ let b = Foo { a: 42 };
+ let c = Foo { a: 7 };
+
+ if a == b {
+ print("a == b");
+ } else {
+ print("a != b");
+ }
+
+ if a != c {
+ print("a != c");
+ } else {
+ print("a == c");
+ }
+
+ if a < c {
+ print("a < c");
+ } else {
+ print("a >= c");
+ }
+
+ if a <= b {
+ print("a <= b");
+ } else {
+ print("a > b");
+ }
+
+ if a > c {
+ print("a > c");
+ } else {
+ print("a <= c");
+ }
+
+ if c >= b {
+ print("c >= b");
+ } else {
+ print("c < b");
+ }
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/partial-ord-6.rs b/gcc/testsuite/rust/execute/torture/partial-ord-6.rs
new file mode 100644
index 0000000..5d64f8c
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/partial-ord-6.rs
@@ -0,0 +1,518 @@
+// { dg-additional-options "-w" }
+/* { dg-output "Foo A < B\r?\nFoo B < C\r?\nFoo C == C\r?\nBar x < y\r?\nBarFull s1 < s2\r?\n" } */
+
+#![feature(intrinsics)]
+
+mod core {
+ mod option {
+ // #[rustc_diagnostic_item = "option_type"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub enum Option<T> {
+ /// No value
+ #[lang = "None"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ None,
+ /// Some value `T`
+ #[lang = "Some"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Some(#[stable(feature = "rust1", since = "1.0.0")] T),
+ }
+ }
+
+ mod marker {
+ #[lang = "phantom_data"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub struct PhantomData<T: ?Sized>;
+
+ #[unstable(feature = "structural_match", issue = "31434")]
+ // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(PartialEq)]`")]
+ #[lang = "structural_peq"]
+ pub trait StructuralPartialEq {
+ // Empty.
+ }
+
+ #[unstable(feature = "structural_match", issue = "31434")]
+ // #[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(Eq)]`")]
+ #[lang = "structural_teq"]
+ pub trait StructuralEq {
+ // Empty.
+ }
+
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[lang = "sized"]
+ // #[rustc_on_unimplemented(
+ // message = "the size for values of type `{Self}` cannot be known at compilation time",
+ // label = "doesn't have a size known at compile-time"
+ // )]
+ // #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
+ // #[rustc_specialization_trait]
+ pub trait Sized {
+ // Empty.
+ }
+ }
+
+ mod cmp {
+ use super::marker::Sized;
+ use super::option::Option;
+
+ // #[derive(Clone, Copy, PartialEq, Debug, Hash)]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub enum Ordering {
+ /// An ordering where a compared value is less than another.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Less = -1,
+ /// An ordering where a compared value is equal to another.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Equal = 0,
+ /// An ordering where a compared value is greater than another.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ Greater = 1,
+ }
+
+ #[lang = "eq"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[doc(alias = "==")]
+ #[doc(alias = "!=")]
+ // #[rustc_on_unimplemented(
+ // message = "can't compare `{Self}` with `{Rhs}`",
+ // label = "no implementation for `{Self} == {Rhs}`"
+ // )]
+ pub trait PartialEq<Rhs: ?Sized = Self> {
+ /// This method tests for `self` and `other` values to be equal, and is used
+ /// by `==`.
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn eq(&self, other: &Rhs) -> bool;
+
+ fn ne(&self, other: &Rhs) -> bool {
+ !self.eq(other)
+ }
+ }
+
+ #[doc(alias = "==")]
+ #[doc(alias = "!=")]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub trait Eq: PartialEq<Self> {
+ // this method is used solely by #[deriving] to assert
+ // that every component of a type implements #[deriving]
+ // itself, the current deriving infrastructure means doing this
+ // assertion without using a method on this trait is nearly
+ // impossible.
+ //
+ // This should never be implemented by hand.
+ #[doc(hidden)]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn assert_receiver_is_total_eq(&self) {}
+ }
+
+ #[lang = "partial_ord"]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[doc(alias = ">")]
+ #[doc(alias = "<")]
+ #[doc(alias = "<=")]
+ #[doc(alias = ">=")]
+ // #[rustc_on_unimplemented(
+ // message = "can't compare `{Self}` with `{Rhs}`",
+ // label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`"
+ // )]
+ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
+ /// This method returns an ordering between `self` and `other` values if one exists.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::cmp::Ordering;
+ ///
+ /// let result = 1.0.partial_cmp(&2.0);
+ /// assert_eq!(result, Some(Ordering::Less));
+ ///
+ /// let result = 1.0.partial_cmp(&1.0);
+ /// assert_eq!(result, Some(Ordering::Equal));
+ ///
+ /// let result = 2.0.partial_cmp(&1.0);
+ /// assert_eq!(result, Some(Ordering::Greater));
+ /// ```
+ ///
+ /// When comparison is impossible:
+ ///
+ /// ```
+ /// let result = f64::NAN.partial_cmp(&1.0);
+ /// assert_eq!(result, None);
+ /// ```
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
+
+ /// This method tests less than (for `self` and `other`) and is used by the `<` operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 < 2.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 < 1.0;
+ /// assert_eq!(result, false);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn lt(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Less) => true,
+ _ => false,
+ }
+ }
+
+ /// This method tests less than or equal to (for `self` and `other`) and is used by the `<=`
+ /// operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 <= 2.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 <= 2.0;
+ /// assert_eq!(result, true);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn le(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Less | Ordering::Equal) => true,
+ _ => false,
+ }
+ }
+
+ /// This method tests greater than (for `self` and `other`) and is used by the `>` operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 1.0 > 2.0;
+ /// assert_eq!(result, false);
+ ///
+ /// let result = 2.0 > 2.0;
+ /// assert_eq!(result, false);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn gt(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Greater) => true,
+ _ => false,
+ }
+ }
+
+ /// This method tests greater than or equal to (for `self` and `other`) and is used by the `>=`
+ /// operator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let result = 2.0 >= 1.0;
+ /// assert_eq!(result, true);
+ ///
+ /// let result = 2.0 >= 2.0;
+ /// assert_eq!(result, true);
+ /// ```
+ #[inline]
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn ge(&self, other: &Rhs) -> bool {
+ match self.partial_cmp(other) {
+ Option::Some(Ordering::Greater | Ordering::Equal) => true,
+ _ => false,
+ }
+ }
+ }
+
+ #[doc(alias = "<")]
+ #[doc(alias = ">")]
+ #[doc(alias = "<=")]
+ #[doc(alias = ">=")]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub trait Ord: Eq + PartialOrd<Self> {
+ /// This method returns an [`Ordering`] between `self` and `other`.
+ ///
+ /// By convention, `self.cmp(&other)` returns the ordering matching the expression
+ /// `self <operator> other` if true.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::cmp::Ordering;
+ ///
+ /// assert_eq!(5.cmp(&10), Ordering::Less);
+ /// assert_eq!(10.cmp(&5), Ordering::Greater);
+ /// assert_eq!(5.cmp(&5), Ordering::Equal);
+ /// ```
+ #[must_use]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn cmp(&self, other: &Self) -> Ordering;
+
+ /// Compares and returns the maximum of two values.
+ ///
+ /// Returns the second argument if the comparison determines them to be equal.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// assert_eq!(2, 1.max(2));
+ /// assert_eq!(2, 2.max(2));
+ /// ```
+ #[stable(feature = "ord_max_min", since = "1.21.0")]
+ #[must_use]
+ fn max(self, other: Self) -> Self
+ where
+ Self: Sized,
+ {
+ self
+ }
+
+ /// Compares and returns the minimum of two values.
+ ///
+ /// Returns the first argument if the comparison determines them to be equal.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// assert_eq!(1, 1.min(2));
+ /// assert_eq!(2, 2.min(2));
+ /// ```
+ #[stable(feature = "ord_max_min", since = "1.21.0")]
+ #[must_use]
+ fn min(self, other: Self) -> Self
+ where
+ Self: Sized,
+ {
+ self
+ }
+
+ /// Restrict a value to a certain interval.
+ ///
+ /// Returns `max` if `self` is greater than `max`, and `min` if `self` is
+ /// less than `min`. Otherwise this returns `self`.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `min > max`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(clamp)]
+ ///
+ /// assert!((-3).clamp(-2, 1) == -2);
+ /// assert!(0.clamp(-2, 1) == 0);
+ /// assert!(2.clamp(-2, 1) == 1);
+ /// ```
+ #[must_use]
+ #[unstable(feature = "clamp", issue = "44095")]
+ fn clamp(self, min: Self, max: Self) -> Self
+ where
+ Self: Sized,
+ {
+ if self < min {
+ min
+ } else if self > max {
+ max
+ } else {
+ self
+ }
+ }
+ }
+ }
+
+ pub mod intrinsics {
+ #[lang = "discriminant_kind"]
+ pub trait DiscriminantKind {
+ #[lang = "discriminant_type"]
+ type Discriminant;
+ }
+
+ extern "rust-intrinsic" {
+ pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
+ }
+ }
+}
+
+use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
+use core::marker::Sized;
+use core::option::Option;
+
+// for comparing discriminant_value
+impl PartialEq for isize {
+ fn eq(&self, other: &Self) -> bool {
+ *self == *other
+ }
+}
+
+// for comparing discriminant_value
+impl PartialOrd for isize {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ if *self > *other {
+ Option::Some(Ordering::Greater)
+ } else if *self < *other {
+ Option::Some(Ordering::Less)
+ } else {
+ Option::Some(Ordering::Equal)
+ }
+ }
+
+ fn lt(&self, other: &Self) -> bool {
+ *self < *other
+ }
+ fn le(&self, other: &Self) -> bool {
+ *self <= *other
+ }
+ fn ge(&self, other: &Self) -> bool {
+ *self >= *other
+ }
+ fn gt(&self, other: &Self) -> bool {
+ *self > *other
+ }
+}
+
+impl PartialEq for i32 {
+ fn eq(&self, other: &Self) -> bool {
+ *self == *other
+ }
+}
+
+impl PartialOrd for i32 {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ if *self > *other {
+ Option::Some(Ordering::Greater)
+ } else if *self < *other {
+ Option::Some(Ordering::Less)
+ } else {
+ Option::Some(Ordering::Equal)
+ }
+ }
+
+ fn lt(&self, other: &Self) -> bool {
+ *self < *other
+ }
+ fn le(&self, other: &Self) -> bool {
+ *self <= *other
+ }
+ fn ge(&self, other: &Self) -> bool {
+ *self >= *other
+ }
+ fn gt(&self, other: &Self) -> bool {
+ *self > *other
+ }
+}
+
+impl Ord for i32 {
+ fn cmp(&self, other: &Self) -> Ordering {
+ if *self > *other {
+ Ordering::Greater
+ } else if *self < *other {
+ Ordering::Less
+ } else {
+ Ordering::Equal
+ }
+ }
+}
+
+impl Eq for i32 {}
+
+#[derive(PartialEq, PartialOrd)]
+enum Foo {
+ A,
+ B(i32, i32, i32),
+ C { inner: i32, outer: i32 },
+}
+
+#[derive(Ord, PartialOrd, PartialEq, Eq)]
+struct Bar {
+ a: i32,
+}
+
+#[derive(Ord, PartialOrd, PartialEq, Eq)]
+struct BarFull {
+ a: i32,
+ b: i32,
+ c: i32,
+ d: i32,
+}
+
+extern "C" {
+ fn puts(s: *const i8);
+}
+
+fn print(s: &str) {
+ unsafe {
+ puts(s as *const str as *const i8);
+ }
+}
+
+fn main() -> i32 {
+ // Enum comparison
+ let a = Foo::A;
+ let b = Foo::B(15, 14, 13);
+ let c = Foo::C {
+ inner: 10,
+ outer: 20,
+ };
+
+ match a.partial_cmp(&b) {
+ Option::Some(Ordering::Less) => print("Foo A < B"),
+ Option::Some(Ordering::Greater) => print("Foo A > B"),
+ Option::Some(Ordering::Equal) => print("Foo A == B"),
+ _ => print("Foo A ? B"),
+ }
+
+ match b.partial_cmp(&c) {
+ Option::Some(Ordering::Less) => print("Foo B < C"),
+ Option::Some(Ordering::Greater) => print("Foo B > C"),
+ Option::Some(Ordering::Equal) => print("Foo B == C"),
+ _ => print("Foo B ? C"),
+ }
+
+ match c.partial_cmp(&c) {
+ Option::Some(Ordering::Less) => print("Foo C < C ???"),
+ Option::Some(Ordering::Greater) => print("Foo C > C ???"),
+ Option::Some(Ordering::Equal) => print("Foo C == C"),
+ _ => print("Foo C ? C"),
+ }
+
+ // Struct comparison: Bar
+ let x = Bar { a: 10 };
+ let y = Bar { a: 20 };
+
+ if x < y {
+ print("Bar x < y");
+ } else if x > y {
+ print("Bar x > y");
+ } else {
+ print("Bar x == y");
+ }
+
+ // Struct comparison: BarFull
+ let s1 = BarFull {
+ a: 1,
+ b: 2,
+ c: 3,
+ d: 4,
+ };
+ let s2 = BarFull {
+ a: 1,
+ b: 2,
+ c: 3,
+ d: 5,
+ };
+
+ match s1.cmp(&s2) {
+ Ordering::Less => print("BarFull s1 < s2"),
+ Ordering::Greater => print("BarFull s1 > s2"),
+ Ordering::Equal => print("BarFull s1 == s2"),
+ }
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/sip-hasher.rs b/gcc/testsuite/rust/execute/torture/sip-hasher.rs
new file mode 100644
index 0000000..60826a3
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/sip-hasher.rs
@@ -0,0 +1,438 @@
+// { dg-skip-if "" { *-*-* } { "-m32" } { "" } }
+// { dg-options "-w" }
+// { dg-output "Hash: 0x63d53fd2170bbb8c\r*\n" }
+#![feature(intrinsics)]
+#![feature(rustc_attrs)]
+
+#[lang = "sized"]
+trait Sized {}
+
+mod intrinsics {
+ extern "rust-intrinsic" {
+ pub fn wrapping_add<T>(a: T, b: T) -> T;
+ pub fn rotate_left<T>(a: T, b: T) -> T;
+ pub fn offset<T>(ptr: *const T, count: isize) -> *const T;
+ }
+}
+
+#[lang = "add"]
+trait Add<Rhs = Self> {
+ type Output;
+
+ fn add(self, rhs: Rhs) -> Self::Output;
+}
+
+macro_rules! add_impl {
+ ($($t:ty)*) => ($(
+ impl Add for $t {
+ type Output = $t;
+
+ #[inline]
+ #[rustc_inherit_overflow_checks]
+ fn add(self, other: $t) -> $t { self + other }
+ }
+
+
+ )*)
+}
+
+add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
+
+impl<T> *const T {
+ pub unsafe fn add(self, count: usize) -> Self {
+ // SAFETY: the caller must uphold the safety contract for `offset`.
+ unsafe { self.offset(count as isize) }
+ }
+
+ pub unsafe fn offset(self, count: isize) -> *const T {
+ // SAFETY: the caller must uphold the safety contract for `offset`.
+ unsafe { intrinsics::offset(self, count) }
+ }
+}
+
+macro_rules! impl_uint {
+ ($($ty:ident = $lang:literal),*) => {
+ $(
+ #[lang = $lang]
+ impl $ty {
+ pub fn wrapping_add(self, rhs: Self) -> Self {
+ intrinsics::wrapping_add(self, rhs)
+ }
+
+ pub fn rotate_left(self, n: u32) -> Self {
+ intrinsics::rotate_left(self, n as Self)
+ }
+
+ pub fn to_le(self) -> Self {
+ #[cfg(target_endian = "little")]
+ {
+ self
+ }
+ #[cfg(not(target_endian = "little"))]
+ {
+ self.swap_bytes()
+ }
+ }
+ }
+ )*
+ }
+}
+
+impl_uint!(
+ u8 = "u8",
+ u16 = "u16",
+ u32 = "u32",
+ u64 = "u64",
+ u128 = "u128",
+ usize = "usize"
+);
+
+#[repr(C)]
+pub(crate) struct SliceComponents {
+ pub(crate) data_address: *const (),
+ pub(crate) metadata: usize,
+}
+
+#[repr(C)]
+pub(crate) union SliceRepr<T> {
+ pub(crate) const_ptr: *const [T],
+ pub(crate) mut_ptr: *mut [T],
+ pub(crate) components: SliceComponents,
+}
+
+impl<T> [T] {
+ pub const fn as_ptr(&self) -> *const T {
+ self as *const [T] as *const T
+ }
+
+ pub unsafe fn get_unchecked(&self, index: usize) -> &T {
+ unsafe { &*self.as_ptr().add(index) }
+ }
+
+ pub fn len(&self) -> usize {
+ unsafe {
+ SliceRepr {
+ const_ptr: self as *const _,
+ }
+ .components
+ .metadata
+ }
+ }
+}
+
+trait HasherTrait {
+ fn write(&mut self, msg: &[u8]);
+ fn finish(&self) -> u64;
+}
+
+mod cmp {
+ pub fn min(a: usize, b: usize) -> usize {
+ if a < b {
+ a
+ } else {
+ b
+ }
+ }
+}
+
+struct PhantomData<T>;
+
+mod mem {
+ extern "rust-intrinsic" {
+ fn transmute<T, U>(_: T) -> U;
+ fn size_of<T>() -> usize;
+ }
+}
+
+mod ptr {
+ extern "rust-intrinsic" {
+ fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
+ }
+}
+
+#[repr(C)]
+struct State {
+ v0: u64,
+ v2: u64,
+ v1: u64,
+ v3: u64,
+}
+
+struct Hasher<S: Sip> {
+ k0: u64,
+ k1: u64,
+ length: usize, // how many bytes we've processed
+ state: State, // hash State
+ tail: u64, // unprocessed bytes le
+ ntail: usize, // how many bytes in tail are valid
+ _marker: PhantomData<S>,
+}
+
+macro_rules! compress {
+ ($state:expr) => {{
+ compress!($state.v0, $state.v1, $state.v2, $state.v3)
+ }};
+ ($v0:expr, $v1:expr, $v2:expr, $v3:expr) => {{
+ $v0 = $v0.wrapping_add($v1);
+ $v1 = $v1.rotate_left(13);
+ $v1 ^= $v0;
+ $v0 = $v0.rotate_left(32);
+ $v2 = $v2.wrapping_add($v3);
+ $v3 = $v3.rotate_left(16);
+ $v3 ^= $v2;
+ $v0 = $v0.wrapping_add($v3);
+ $v3 = $v3.rotate_left(21);
+ $v3 ^= $v0;
+ $v2 = $v2.wrapping_add($v1);
+ $v1 = $v1.rotate_left(17);
+ $v1 ^= $v2;
+ $v2 = $v2.rotate_left(32);
+ }};
+}
+
+#[doc(hidden)]
+trait Sip {
+ fn c_rounds(_: &mut State);
+ fn d_rounds(_: &mut State);
+}
+
+struct Sip13Rounds;
+
+impl Sip for Sip13Rounds {
+ #[inline]
+ fn c_rounds(state: &mut State) {
+ compress!(state);
+ }
+
+ #[inline]
+ fn d_rounds(state: &mut State) {
+ compress!(state);
+ compress!(state);
+ compress!(state);
+ }
+}
+
+struct Sip24Rounds;
+
+impl Sip for Sip24Rounds {
+ #[inline]
+ fn c_rounds(state: &mut State) {
+ compress!(state);
+ compress!(state);
+ }
+
+ #[inline]
+ fn d_rounds(state: &mut State) {
+ compress!(state);
+ compress!(state);
+ compress!(state);
+ compress!(state);
+ }
+}
+
+pub struct SipHasher13 {
+ hasher: Hasher<Sip13Rounds>,
+}
+
+struct SipHasher24 {
+ hasher: Hasher<Sip24Rounds>,
+}
+
+pub struct SipHasher(SipHasher24);
+
+macro_rules! load_int_le {
+ ($buf:expr, $i:expr, $int_ty:ident) => {{
+ let mut data = 0 as $int_ty;
+ ptr::copy_nonoverlapping(
+ $buf.as_ptr().add($i),
+ &mut data as *mut _ as *mut u8,
+ mem::size_of::<$int_ty>(),
+ );
+ data.to_le()
+ }};
+}
+
+#[inline]
+unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 {
+ let mut i = 0; // current byte index (from LSB) in the output u64
+ let mut out = 0;
+ if i + 3 < len {
+ // SAFETY: `i` cannot be greater than `len`, and the caller must guarantee
+ // that the index start..start+len is in bounds.
+ out = unsafe { load_int_le!(buf, start + i, u32) } as u64;
+ i += 4;
+ }
+ if i + 1 < len {
+ // SAFETY: same as above.
+ out |= (unsafe { load_int_le!(buf, start + i, u16) } as u64) << ((i * 8) as u64);
+ i += 2
+ }
+ if i < len {
+ // SAFETY: same as above.
+ out |= (unsafe { *buf.get_unchecked(start + i) } as u64) << ((i * 8) as u64);
+ i += 1;
+ }
+ out
+}
+
+impl SipHasher {
+ #[inline]
+ #[must_use]
+ pub fn new() -> SipHasher {
+ SipHasher::new_with_keys(0, 0)
+ }
+
+ #[inline]
+ #[must_use]
+ pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
+ SipHasher(SipHasher24 {
+ hasher: Hasher::new_with_keys(key0, key1),
+ })
+ }
+}
+
+impl SipHasher13 {
+ #[inline]
+ pub fn new() -> SipHasher13 {
+ SipHasher13::new_with_keys(0, 0)
+ }
+
+ #[inline]
+ pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 {
+ SipHasher13 {
+ hasher: Hasher::new_with_keys(key0, key1),
+ }
+ }
+}
+
+impl<S: Sip> Hasher<S> {
+ #[inline]
+ fn new_with_keys(key0: u64, key1: u64) -> Hasher<S> {
+ let mut state = Hasher {
+ k0: key0,
+ k1: key1,
+ length: 0,
+ state: State {
+ v0: 0,
+ v1: 0,
+ v2: 0,
+ v3: 0,
+ },
+ tail: 0,
+ ntail: 0,
+ _marker: PhantomData,
+ };
+ state.reset();
+ state
+ }
+
+ #[inline]
+ fn reset(&mut self) {
+ self.length = 0;
+ self.state.v0 = self.k0 ^ 0x736f6d6570736575;
+ self.state.v1 = self.k1 ^ 0x646f72616e646f6d;
+ self.state.v2 = self.k0 ^ 0x6c7967656e657261;
+ self.state.v3 = self.k1 ^ 0x7465646279746573;
+ self.ntail = 0;
+ }
+}
+
+impl HasherTrait for SipHasher {
+ #[inline]
+ fn write(&mut self, msg: &[u8]) {
+ self.0.hasher.write(msg)
+ }
+
+ #[inline]
+ fn finish(&self) -> u64 {
+ self.0.hasher.finish()
+ }
+}
+
+impl HasherTrait for SipHasher13 {
+ #[inline]
+ fn write(&mut self, msg: &[u8]) {
+ self.hasher.write(msg)
+ }
+
+ #[inline]
+ fn finish(&self) -> u64 {
+ self.hasher.finish()
+ }
+}
+
+impl<S: Sip> HasherTrait for Hasher<S> {
+ #[inline]
+ fn write(&mut self, msg: &[u8]) {
+ let length = msg.len();
+ self.length += length;
+
+ let mut needed = 0;
+
+ if self.ntail != 0 {
+ needed = 8 - self.ntail;
+ // SAFETY: `cmp::min(length, needed)` is guaranteed to not be over `length`
+ self.tail |=
+ unsafe { u8to64_le(msg, 0, cmp::min(length, needed)) } << ((8 * self.ntail) as u64);
+ if length < needed {
+ self.ntail += length;
+ return;
+ } else {
+ self.state.v3 ^= self.tail;
+ S::c_rounds(&mut self.state);
+ self.state.v0 ^= self.tail;
+ self.ntail = 0;
+ }
+ }
+
+ // Buffered tail is now flushed, process new input.
+ let len = length - needed;
+ let left = len & 0x7; // len % 8
+
+ let mut i = needed;
+ while i < len - left {
+ let mi = unsafe { load_int_le!(msg, i, u64) };
+
+ self.state.v3 ^= mi;
+ S::c_rounds(&mut self.state);
+ self.state.v0 ^= mi;
+
+ i += 8;
+ }
+
+ self.tail = unsafe { u8to64_le(msg, i, left) };
+ self.ntail = left;
+ }
+
+ #[inline]
+ fn finish(&self) -> u64 {
+ let mut state = self.state;
+
+ let b: u64 = ((self.length as u64 & 0xff) << 56) | self.tail;
+
+ state.v3 ^= b;
+ S::c_rounds(&mut state);
+ state.v0 ^= b;
+
+ state.v2 ^= 0xff;
+ S::d_rounds(&mut state);
+
+ state.v0 ^ state.v1 ^ state.v2 ^ state.v3
+ }
+}
+
+extern "C" {
+ fn printf(fmt: *const u8, ...) -> i32;
+}
+
+fn main() -> i32 {
+ let mut hasher = SipHasher::new_with_keys(0x0706050403020100, 0x0f0e0d0c0b0a0908);
+ hasher.write(b"Hello");
+ let result = hasher.finish();
+
+ unsafe {
+ printf("Hash: 0x%016llx\n\0" as *const str as *const u8, result);
+ }
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/struct-pattern-match.rs b/gcc/testsuite/rust/execute/torture/struct-pattern-match.rs
new file mode 100644
index 0000000..6aec51f
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/struct-pattern-match.rs
@@ -0,0 +1,13 @@
+enum Foo {
+ A { x: i32 },
+ B { y: i32 }
+}
+
+fn main() -> i32 {
+ let x = Foo::A { x: 12 };
+ match x {
+ Foo::A { x: 10 } => 1,
+ Foo::B { y: 11 } => 2,
+ Foo::A { x: abc } => { abc - 12 }
+ }
+}
diff --git a/gcc/testsuite/rust/execute/torture/struct_pattern1.rs b/gcc/testsuite/rust/execute/torture/struct_pattern1.rs
new file mode 100644
index 0000000..7a74092
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/struct_pattern1.rs
@@ -0,0 +1,19 @@
+struct A {
+ // the two warnings are invalid but this should be fixed by our lint rework
+ // with this year's GSoC so ok for now
+ a: i32, // { dg-warning "never read" }
+ b: i32, // { dg-warning "never read" }
+}
+
+fn main() -> i32 {
+ let a = A { a: 15, b: 14 };
+
+ let result = match a {
+ A {
+ a: self_a,
+ b: self_b,
+ } => self_a + self_b,
+ };
+
+ result - 29
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait10.rs b/gcc/testsuite/rust/execute/torture/trait10.rs
index a595122..4e576eb 100644
--- a/gcc/testsuite/rust/execute/torture/trait10.rs
+++ b/gcc/testsuite/rust/execute/torture/trait10.rs
@@ -26,7 +26,6 @@ impl Bar for Foo {
struct S;
impl S {
fn dynamic_dispatch(self, t: &dyn Bar) {
- // { dg-warning "unused name" "" { target *-*-* } .-1 }
t.baz();
}
}
diff --git a/gcc/testsuite/rust/execute/torture/trait11.rs b/gcc/testsuite/rust/execute/torture/trait11.rs
index 093343c..cca084a 100644
--- a/gcc/testsuite/rust/execute/torture/trait11.rs
+++ b/gcc/testsuite/rust/execute/torture/trait11.rs
@@ -13,7 +13,6 @@ trait FnLike<A, R> {
struct S;
impl<'a, T> FnLike<&'a T, &'a T> for S {
fn call(&self, arg: &'a T) -> &'a T {
- // { dg-warning "unused name .self." "" { target *-*-* } .-1 }
arg
}
}
diff --git a/gcc/testsuite/rust/execute/torture/trait12.rs b/gcc/testsuite/rust/execute/torture/trait12.rs
index 83cf107..d174a89 100644
--- a/gcc/testsuite/rust/execute/torture/trait12.rs
+++ b/gcc/testsuite/rust/execute/torture/trait12.rs
@@ -16,7 +16,6 @@ struct Identity;
impl<'a, T> FnLike<&'a T, &'a T> for Identity {
fn call(&self, arg: &'a T) -> &'a T {
- // { dg-warning "unused name .self." "" { target *-*-* } .-1 }
arg
}
}
diff --git a/gcc/testsuite/rust/execute/torture/trait13.rs b/gcc/testsuite/rust/execute/torture/trait13.rs
index 928a37c..0d8f894 100644
--- a/gcc/testsuite/rust/execute/torture/trait13.rs
+++ b/gcc/testsuite/rust/execute/torture/trait13.rs
@@ -11,7 +11,6 @@ trait Bar {
fn baz(&self);
fn qux(&self) {
- // { dg-warning "unused name" "" { target *-*-* } .-1 }
unsafe {
let a = "%i\n\0";
let b = a as *const str;
diff --git a/gcc/testsuite/rust/execute/torture/trait9.rs b/gcc/testsuite/rust/execute/torture/trait9.rs
index a1642f6..f60554a 100644
--- a/gcc/testsuite/rust/execute/torture/trait9.rs
+++ b/gcc/testsuite/rust/execute/torture/trait9.rs
@@ -13,7 +13,6 @@ trait FnLike<A, R> {
struct S;
impl<T> FnLike<&T, &T> for S {
fn call(&self, arg: &T) -> &T {
- // { dg-warning "unused name .self." "" { target *-*-* } .-1 }
arg
}
}
diff --git a/gcc/testsuite/rust/execute/xfail/match-identifierpattern-enum.rs b/gcc/testsuite/rust/execute/xfail/match-identifierpattern-enum.rs
new file mode 100644
index 0000000..c3a0f65
--- /dev/null
+++ b/gcc/testsuite/rust/execute/xfail/match-identifierpattern-enum.rs
@@ -0,0 +1,15 @@
+enum Foo {
+ I(i32),
+}
+
+fn main() -> i32 {
+ let x = Foo::I(0);
+ let ret = 1;
+
+ match x {
+ _ @ Foo::I(b) => { ret = b },
+ _ => {},
+ };
+
+ ret
+}
diff --git a/gcc/testsuite/sarif-replay.dg/2.1.0-valid/embedded-links-check-html.py b/gcc/testsuite/sarif-replay.dg/2.1.0-valid/embedded-links-check-html.py
index ff1c2f2..845a7af 100644
--- a/gcc/testsuite/sarif-replay.dg/2.1.0-valid/embedded-links-check-html.py
+++ b/gcc/testsuite/sarif-replay.dg/2.1.0-valid/embedded-links-check-html.py
@@ -25,4 +25,4 @@ def test_generated_html(html_tree):
assert_tag(msg[1], 'a')
assert msg[1].text == 'link'
assert msg[1].get('href') == 'http://www.example.com'
- assert msg[1].tail == '. '
+ assert msg[1].tail == '.'
diff --git a/gcc/testsuite/sarif-replay.dg/2.1.0-valid/graphs-check-html.py b/gcc/testsuite/sarif-replay.dg/2.1.0-valid/graphs-check-html.py
index 63b80c9..355c84b 100644
--- a/gcc/testsuite/sarif-replay.dg/2.1.0-valid/graphs-check-html.py
+++ b/gcc/testsuite/sarif-replay.dg/2.1.0-valid/graphs-check-html.py
@@ -24,7 +24,7 @@ def test_result_graph(html_tree):
assert message.attrib['id'] == 'gcc-diag-0-message'
assert message[0].tag == make_tag('strong')
- assert message[0].tail == ' this is a placeholder error, with graphs '
+ assert message[0].tail == ' this is a placeholder error, with graphs'
graph = diag.find("./xhtml:div[@class='gcc-directed-graph']", ns)
assert graph is not None
diff --git a/gcc/testsuite/sarif-replay.dg/2.1.0-valid/nested-diagnostics-1.sarif b/gcc/testsuite/sarif-replay.dg/2.1.0-valid/nested-diagnostics-1.sarif
new file mode 100644
index 0000000..b924012
--- /dev/null
+++ b/gcc/testsuite/sarif-replay.dg/2.1.0-valid/nested-diagnostics-1.sarif
@@ -0,0 +1,164 @@
+/* Test a replay of a .sarif file generated from GCC testsuite.
+
+ The dg directives were stripped out from the generated .sarif
+ to avoid confusing DejaGnu for this test. */
+/* { dg-additional-options "-fdiagnostics-add-output=sarif:file=nested-diagnostics-1.roundtrip.sarif" } */
+/* { dg-additional-options "-fdiagnostics-add-output=experimental-html:file=nested-diagnostics-1.sarif.html,javascript=no" } */
+
+{"$schema": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json",
+ "version": "2.1.0",
+ "runs": [{"tool": {"driver": {"name": "GNU C23",
+ "fullName": "GNU C23 (GCC) version 16.0.0 20250723 (experimental) (x86_64-pc-linux-gnu)",
+ "version": "16.0.0 20250723 (experimental)",
+ "informationUri": "https://gcc.gnu.org/gcc-16/",
+ "rules": []},
+ "extensions": [{"name": "diagnostic_plugin_test_nesting",
+ "fullName": "./diagnostic_plugin_test_nesting.so"}]},
+ "invocations": [{"executionSuccessful": false,
+ "toolExecutionNotifications": []}],
+ "artifacts": [{"location": {"uri": "diagnostic-test-nesting-sarif.c"},
+ "sourceLanguage": "c",
+ "contents": {"text": "\n\nextern void foo (void);\n\nvoid test_nesting (void)\n{\n foo ();\n}\n"},
+ "roles": ["analysisTarget"]}],
+ "results": [{"ruleId": "error",
+ "level": "error",
+ "message": {"text": "top-level error"},
+ "locations": [{"physicalLocation": {"artifactLocation": {"uri": "diagnostic-test-nesting-sarif.c"},
+ "region": {"startLine": 8,
+ "startColumn": 3,
+ "endColumn": 9},
+ "contextRegion": {"startLine": 8,
+ "snippet": {"text": " foo ();\n"}}},
+ "logicalLocations": [{"index": 0,
+ "fullyQualifiedName": "test_nesting"}]}],
+ "relatedLocations": [{"physicalLocation": {"artifactLocation": {"uri": "diagnostic-test-nesting-sarif.c"},
+ "region": {"startLine": 8,
+ "startColumn": 3,
+ "endColumn": 9},
+ "contextRegion": {"startLine": 8,
+ "snippet": {"text": " foo ();\n"}}},
+ "message": {"text": "child 0"},
+ "properties": {"nestingLevel": 1}},
+ {"physicalLocation": {"artifactLocation": {"uri": "diagnostic-test-nesting-sarif.c"},
+ "region": {"startLine": 8,
+ "startColumn": 3,
+ "endColumn": 9},
+ "contextRegion": {"startLine": 8,
+ "snippet": {"text": " foo ();\n"}}},
+ "message": {"text": "grandchild 0 0"},
+ "properties": {"nestingLevel": 2}},
+ {"physicalLocation": {"artifactLocation": {"uri": "diagnostic-test-nesting-sarif.c"},
+ "region": {"startLine": 8,
+ "startColumn": 3,
+ "endColumn": 9},
+ "contextRegion": {"startLine": 8,
+ "snippet": {"text": " foo ();\n"}}},
+ "message": {"text": "grandchild 0 1"},
+ "properties": {"nestingLevel": 2}},
+ {"physicalLocation": {"artifactLocation": {"uri": "diagnostic-test-nesting-sarif.c"},
+ "region": {"startLine": 8,
+ "startColumn": 3,
+ "endColumn": 9},
+ "contextRegion": {"startLine": 8,
+ "snippet": {"text": " foo ();\n"}}},
+ "message": {"text": "grandchild 0 2"},
+ "properties": {"nestingLevel": 2}},
+ {"physicalLocation": {"artifactLocation": {"uri": "diagnostic-test-nesting-sarif.c"},
+ "region": {"startLine": 8,
+ "startColumn": 3,
+ "endColumn": 9},
+ "contextRegion": {"startLine": 8,
+ "snippet": {"text": " foo ();\n"}}},
+ "message": {"text": "child 1"},
+ "properties": {"nestingLevel": 1}},
+ {"physicalLocation": {"artifactLocation": {"uri": "diagnostic-test-nesting-sarif.c"},
+ "region": {"startLine": 8,
+ "startColumn": 3,
+ "endColumn": 9},
+ "contextRegion": {"startLine": 8,
+ "snippet": {"text": " foo ();\n"}}},
+ "message": {"text": "grandchild 1 0"},
+ "properties": {"nestingLevel": 2}},
+ {"physicalLocation": {"artifactLocation": {"uri": "diagnostic-test-nesting-sarif.c"},
+ "region": {"startLine": 8,
+ "startColumn": 3,
+ "endColumn": 9},
+ "contextRegion": {"startLine": 8,
+ "snippet": {"text": " foo ();\n"}}},
+ "message": {"text": "grandchild 1 1"},
+ "properties": {"nestingLevel": 2}},
+ {"physicalLocation": {"artifactLocation": {"uri": "diagnostic-test-nesting-sarif.c"},
+ "region": {"startLine": 8,
+ "startColumn": 3,
+ "endColumn": 9},
+ "contextRegion": {"startLine": 8,
+ "snippet": {"text": " foo ();\n"}}},
+ "message": {"text": "grandchild 1 2"},
+ "properties": {"nestingLevel": 2}},
+ {"physicalLocation": {"artifactLocation": {"uri": "diagnostic-test-nesting-sarif.c"},
+ "region": {"startLine": 8,
+ "startColumn": 3,
+ "endColumn": 9},
+ "contextRegion": {"startLine": 8,
+ "snippet": {"text": " foo ();\n"}}},
+ "message": {"text": "child 2"},
+ "properties": {"nestingLevel": 1}},
+ {"physicalLocation": {"artifactLocation": {"uri": "diagnostic-test-nesting-sarif.c"},
+ "region": {"startLine": 8,
+ "startColumn": 3,
+ "endColumn": 9},
+ "contextRegion": {"startLine": 8,
+ "snippet": {"text": " foo ();\n"}}},
+ "message": {"text": "grandchild 2 0"},
+ "properties": {"nestingLevel": 2}},
+ {"physicalLocation": {"artifactLocation": {"uri": "diagnostic-test-nesting-sarif.c"},
+ "region": {"startLine": 8,
+ "startColumn": 3,
+ "endColumn": 9},
+ "contextRegion": {"startLine": 8,
+ "snippet": {"text": " foo ();\n"}}},
+ "message": {"text": "grandchild 2 1"},
+ "properties": {"nestingLevel": 2}},
+ {"physicalLocation": {"artifactLocation": {"uri": "diagnostic-test-nesting-sarif.c"},
+ "region": {"startLine": 8,
+ "startColumn": 3,
+ "endColumn": 9},
+ "contextRegion": {"startLine": 8,
+ "snippet": {"text": " foo ();\n"}}},
+ "message": {"text": "grandchild 2 2"},
+ "properties": {"nestingLevel": 2}}]}],
+ "logicalLocations": [{"name": "test_nesting",
+ "fullyQualifiedName": "test_nesting",
+ "decoratedName": "test_nesting",
+ "kind": "function",
+ "index": 0}]}]}
+
+/* For now, we don't have a way of enabling showing the nesting
+ on the default text output. However we do test the nesting
+ in the SARIF and HTML outputs below. */
+/* { dg-begin-multiline-output "" }
+In function 'test_nesting':
+diagnostic-test-nesting-sarif.c:8:3: error: top-level error
+ 8 | }
+ | ^
+diagnostic-test-nesting-sarif.c:8:3: note: child 0
+diagnostic-test-nesting-sarif.c:8:3: note: grandchild 0 0
+diagnostic-test-nesting-sarif.c:8:3: note: grandchild 0 1
+diagnostic-test-nesting-sarif.c:8:3: note: grandchild 0 2
+diagnostic-test-nesting-sarif.c:8:3: note: child 1
+diagnostic-test-nesting-sarif.c:8:3: note: grandchild 1 0
+diagnostic-test-nesting-sarif.c:8:3: note: grandchild 1 1
+diagnostic-test-nesting-sarif.c:8:3: note: grandchild 1 2
+diagnostic-test-nesting-sarif.c:8:3: note: child 2
+diagnostic-test-nesting-sarif.c:8:3: note: grandchild 2 0
+diagnostic-test-nesting-sarif.c:8:3: note: grandchild 2 1
+diagnostic-test-nesting-sarif.c:8:3: note: grandchild 2 2
+ { dg-end-multiline-output "" } */
+
+/* Use a Python script to verify various properties about the *generated*
+ .sarif file:
+ { dg-final { run-sarif-pytest nested-diagnostics-1.roundtrip "../gcc.dg/plugin/diagnostic-test-nesting-sarif.py" } } */
+
+/* Use a Python script to verify various properties about the generated
+ .html file:
+ { dg-final { run-html-pytest nested-diagnostics-1.sarif "../gcc.dg/plugin/diagnostic-test-nesting-html.py" } } */
diff --git a/gcc/toplev.cc b/gcc/toplev.cc
index 70dbb3e..d349d83 100644
--- a/gcc/toplev.cc
+++ b/gcc/toplev.cc
@@ -1096,10 +1096,10 @@ general_init (const char *argv0, bool init_signals, unique_argv original_argv)
(global_options_init.x_flag_diagnostics_show_highlight_colors);
global_dc->set_internal_error_callback (internal_error_function);
const unsigned lang_mask = lang_hooks.option_lang_mask ();
- global_dc->set_option_manager
- (std::make_unique<compiler_diagnostic_option_manager> (*global_dc,
- lang_mask,
- &global_options),
+ global_dc->set_option_id_manager
+ (std::make_unique<compiler_diagnostic_option_id_manager> (*global_dc,
+ lang_mask,
+ &global_options),
lang_mask);
global_dc->push_owned_urlifier (make_gcc_urlifier (lang_mask));
diff --git a/gcc/tree-nested.cc b/gcc/tree-nested.cc
index 8d75a2f..813334b 100644
--- a/gcc/tree-nested.cc
+++ b/gcc/tree-nested.cc
@@ -1796,6 +1796,8 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
break;
case GIMPLE_OMP_TARGET:
+ walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
+ info, gimple_omp_target_iterator_loops_ptr (stmt));
if (!is_gimple_omp_offloaded (stmt))
{
save_suppress = info->suppress_expansion;
@@ -2517,6 +2519,9 @@ convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
break;
case GIMPLE_OMP_TARGET:
+ walk_body (convert_local_reference_stmt, convert_local_reference_op, info,
+ gimple_omp_target_iterator_loops_ptr (stmt));
+
if (!is_gimple_omp_offloaded (stmt))
{
save_suppress = info->suppress_expansion;
@@ -2898,6 +2903,8 @@ convert_tramp_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
*handled_ops_p = false;
return NULL_TREE;
}
+ walk_body (convert_tramp_reference_stmt, convert_tramp_reference_op,
+ info, gimple_omp_target_iterator_loops_ptr (stmt));
/* FALLTHRU */
case GIMPLE_OMP_PARALLEL:
case GIMPLE_OMP_TASK:
diff --git a/gcc/tree-pretty-print.cc b/gcc/tree-pretty-print.cc
index 50d0851..c19baba 100644
--- a/gcc/tree-pretty-print.cc
+++ b/gcc/tree-pretty-print.cc
@@ -448,6 +448,15 @@ dump_omp_iterators (pretty_printer *pp, tree iter, int spc, dump_flags_t flags)
pp_colon (pp);
dump_generic_node (pp, TREE_VEC_ELT (it, 3), spc, flags, false);
}
+ if (TREE_VEC_LENGTH (iter) > 6)
+ {
+ pp_string (pp, ", loop_label=");
+ dump_generic_node (pp, TREE_VEC_ELT (iter, 6), spc, flags, false);
+ pp_string (pp, ", elems=");
+ dump_generic_node (pp, TREE_VEC_ELT (iter, 7), spc, flags, false);
+ pp_string (pp, ", index=");
+ dump_generic_node (pp, TREE_VEC_ELT (iter, 8), spc, flags, false);
+ }
pp_right_paren (pp);
}
@@ -1008,6 +1017,11 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
pp_string (pp, "map(");
if (OMP_CLAUSE_MAP_READONLY (clause))
pp_string (pp, "readonly,");
+ if (OMP_CLAUSE_ITERATORS (clause))
+ {
+ dump_omp_iterators (pp, OMP_CLAUSE_ITERATORS (clause), spc, flags);
+ pp_colon (pp);
+ }
switch (OMP_CLAUSE_MAP_KIND (clause))
{
case GOMP_MAP_ALLOC:
@@ -1185,6 +1199,11 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
pp_string (pp, "from(");
if (OMP_CLAUSE_MOTION_PRESENT (clause))
pp_string (pp, "present:");
+ if (OMP_CLAUSE_ITERATORS (clause))
+ {
+ dump_omp_iterators (pp, OMP_CLAUSE_ITERATORS (clause), spc, flags);
+ pp_colon (pp);
+ }
dump_generic_node (pp, OMP_CLAUSE_DECL (clause),
spc, flags, false);
goto print_clause_size;
@@ -1193,6 +1212,11 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
pp_string (pp, "to(");
if (OMP_CLAUSE_MOTION_PRESENT (clause))
pp_string (pp, "present:");
+ if (OMP_CLAUSE_ITERATORS (clause))
+ {
+ dump_omp_iterators (pp, OMP_CLAUSE_ITERATORS (clause), spc, flags);
+ pp_colon (pp);
+ }
dump_generic_node (pp, OMP_CLAUSE_DECL (clause),
spc, flags, false);
goto print_clause_size;
diff --git a/gcc/tree-scalar-evolution.cc b/gcc/tree-scalar-evolution.cc
index 413ca49..3b3748a 100644
--- a/gcc/tree-scalar-evolution.cc
+++ b/gcc/tree-scalar-evolution.cc
@@ -670,6 +670,17 @@ scev_dfs::add_to_evolution_1 (tree chrec_before, tree to_add, gimple *at_stmt)
to_add = chrec_convert (type, to_add, at_stmt);
right = chrec_convert_rhs (type, right, at_stmt);
right = chrec_fold_plus (chrec_type (right), right, to_add);
+ /* When we have an evolution in a non-wrapping type and
+ in the process of accumulating CHREC_RIGHT there was
+ overflow this indicates in the association that happened
+ in building the CHREC clearly involved UB. Avoid this.
+ In building a CHREC we basically turn (a + INCR1) + INCR2
+ into a + (INCR1 + INCR2) which is not always valid.
+ Note this check only catches few invalid cases. */
+ if ((INTEGRAL_TYPE_P (type) && ! TYPE_OVERFLOW_WRAPS (type))
+ && TREE_CODE (right) == INTEGER_CST
+ && TREE_OVERFLOW (right))
+ return chrec_dont_know;
return build_polynomial_chrec (var, left, right);
}
else
diff --git a/gcc/tree-ssa-loop-ivopts.cc b/gcc/tree-ssa-loop-ivopts.cc
index 879668c..2fe2655 100644
--- a/gcc/tree-ssa-loop-ivopts.cc
+++ b/gcc/tree-ssa-loop-ivopts.cc
@@ -132,6 +132,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-vectorizer.h"
#include "dbgcnt.h"
#include "cfganal.h"
+#include "gimple-fold.h"
/* For lang_hooks.types.type_for_mode. */
#include "langhooks.h"
@@ -7252,7 +7253,24 @@ create_new_iv (struct ivopts_data *data, struct iv_cand *cand)
base = unshare_expr (cand->iv->base);
- create_iv (base, PLUS_EXPR, unshare_expr (cand->iv->step),
+ /* The step computation could invoke UB when the loop does not iterate.
+ Avoid inserting it on the preheader in its native form but rewrite
+ it to a well-defined form. This also helps masking SCEV issues
+ which freely re-associates the IV computations when building up
+ CHRECs without much regard for signed overflow invoking UB. */
+ gimple_seq stmts = NULL;
+ tree step = force_gimple_operand (unshare_expr (cand->iv->step), &stmts,
+ true, NULL_TREE);
+ if (stmts)
+ {
+ for (auto gsi = gsi_start (stmts); !gsi_end_p (gsi); gsi_next (&gsi))
+ if (gimple_needing_rewrite_undefined (gsi_stmt (gsi)))
+ rewrite_to_defined_unconditional (&gsi);
+ gsi_insert_seq_on_edge_immediate
+ (loop_preheader_edge (data->current_loop), stmts);
+ }
+
+ create_iv (base, PLUS_EXPR, step,
cand->var_before, data->current_loop,
&incr_pos, after, &cand->var_before, &cand->var_after);
}
diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
index 3974c4d..00315d1 100644
--- a/gcc/tree-ssa-sccvn.cc
+++ b/gcc/tree-ssa-sccvn.cc
@@ -3549,8 +3549,95 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
/* Find the common base of ref and the lhs. lhs_ops already
contains valueized operands for the lhs. */
+ poly_int64 extra_off = 0;
i = vr->operands.length () - 1;
j = lhs_ops.length () - 1;
+
+ /* The base should be always equal due to the above check. */
+ if (! vn_reference_op_eq (&vr->operands[i], &lhs_ops[j]))
+ return (void *)-1;
+ i--, j--;
+
+ /* The 2nd component should always exist and be a MEM_REF. */
+ if (!(i >= 0 && j >= 0))
+ ;
+ else if (vn_reference_op_eq (&vr->operands[i], &lhs_ops[j]))
+ i--, j--;
+ else if (vr->operands[i].opcode == MEM_REF
+ && lhs_ops[j].opcode == MEM_REF
+ && known_ne (lhs_ops[j].off, -1)
+ && known_ne (vr->operands[i].off, -1))
+ {
+ bool found = false;
+ /* When we ge a mismatch at a MEM_REF that is not the sole component
+ try finding a match in one of the outer components and continue
+ stripping there. This happens when addresses of components get
+ forwarded into dereferences. */
+ if (j > 0)
+ {
+ int temi = i - 1;
+ extra_off = vr->operands[i].off;
+ while (temi >= 0
+ && known_ne (vr->operands[temi].off, -1))
+ {
+ if (vr->operands[temi].type
+ && lhs_ops[j].type
+ && (TYPE_MAIN_VARIANT (vr->operands[temi].type)
+ == TYPE_MAIN_VARIANT (lhs_ops[j].type)))
+ {
+ i = temi;
+ /* Strip the component that was type matched to
+ the MEM_REF. */
+ extra_off += vr->operands[i].off - lhs_ops[j].off;
+ i--, j--;
+ /* Strip further equal components. */
+ found = true;
+ break;
+ }
+ extra_off += vr->operands[temi].off;
+ temi--;
+ }
+ }
+ if (!found && i > 0)
+ {
+ int temj = j - 1;
+ extra_off = -lhs_ops[j].off;
+ while (temj >= 0
+ && known_ne (lhs_ops[temj].off, -1))
+ {
+ if (vr->operands[i].type
+ && lhs_ops[temj].type
+ && (TYPE_MAIN_VARIANT (vr->operands[i].type)
+ == TYPE_MAIN_VARIANT (lhs_ops[temj].type)))
+ {
+ j = temj;
+ /* Strip the component that was type matched to
+ the MEM_REF. */
+ extra_off += vr->operands[i].off - lhs_ops[j].off;
+ i--, j--;
+ /* Strip further equal components. */
+ found = true;
+ break;
+ }
+ extra_off += -lhs_ops[temj].off;
+ temj--;
+ }
+ }
+ /* When the LHS is already at the outermost level simply
+ adjust for any offset difference. Further lookups
+ will fail when there's too gross of a type compatibility
+ issue. */
+ if (!found && j == 0)
+ {
+ extra_off = vr->operands[i].off - lhs_ops[j].off;
+ i--, j--;
+ }
+ }
+ else
+ return (void *)-1;
+
+ /* Strip further common components, attempting to consume lhs_ops
+ in full. */
while (j >= 0 && i >= 0
&& vn_reference_op_eq (&vr->operands[i], &lhs_ops[j]))
{
@@ -3558,27 +3645,6 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
j--;
}
- /* ??? The innermost op should always be a MEM_REF and we already
- checked that the assignment to the lhs kills vr. Thus for
- aggregate copies using char[] types the vn_reference_op_eq
- may fail when comparing types for compatibility. But we really
- don't care here - further lookups with the rewritten operands
- will simply fail if we messed up types too badly. */
- poly_int64 extra_off = 0;
- if (j == 0 && i >= 0
- && lhs_ops[0].opcode == MEM_REF
- && maybe_ne (lhs_ops[0].off, -1))
- {
- if (known_eq (lhs_ops[0].off, vr->operands[i].off))
- i--, j--;
- else if (vr->operands[i].opcode == MEM_REF
- && maybe_ne (vr->operands[i].off, -1))
- {
- extra_off = vr->operands[i].off - lhs_ops[0].off;
- i--, j--;
- }
- }
-
/* i now points to the first additional op.
??? LHS may not be completely contained in VR, one or more
VIEW_CONVERT_EXPRs could be in its way. We could at least
diff --git a/gcc/tree-vect-data-refs.cc b/gcc/tree-vect-data-refs.cc
index da700cd..dc82bf6 100644
--- a/gcc/tree-vect-data-refs.cc
+++ b/gcc/tree-vect-data-refs.cc
@@ -1856,21 +1856,14 @@ vect_get_data_access_cost (vec_info *vinfo, dr_vec_info *dr_info,
stmt_vector_for_cost *prologue_cost_vec)
{
stmt_vec_info stmt_info = dr_info->stmt;
- loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
- int ncopies;
-
- if (PURE_SLP_STMT (stmt_info))
- ncopies = 1;
- else
- ncopies = vect_get_num_copies (loop_vinfo, STMT_VINFO_VECTYPE (stmt_info));
if (DR_IS_READ (dr_info->dr))
- vect_get_load_cost (vinfo, stmt_info, NULL, ncopies,
+ vect_get_load_cost (vinfo, stmt_info, NULL, 1,
alignment_support_scheme, misalignment, true,
inside_cost, outside_cost, prologue_cost_vec,
body_cost_vec, false);
else
- vect_get_store_cost (vinfo,stmt_info, NULL, ncopies,
+ vect_get_store_cost (vinfo,stmt_info, NULL, 1,
alignment_support_scheme, misalignment, inside_cost,
body_cost_vec);
diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
index 460de57..85f3e90 100644
--- a/gcc/tree-vect-loop.cc
+++ b/gcc/tree-vect-loop.cc
@@ -2512,9 +2512,8 @@ start_over:
if (!vect_make_slp_decision (loop_vinfo))
return opt_result::failure_at (vect_location, "no stmts to vectorize.\n");
- /* Find stmts that need to be both vectorized and SLPed. */
- if (!vect_detect_hybrid_slp (loop_vinfo))
- return opt_result::failure_at (vect_location, "needs non-SLP handling\n");
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location, "Loop contains only SLP stmts\n");
/* Determine the vectorization factor from the SLP decision. */
LOOP_VINFO_VECT_FACTOR (loop_vinfo)
@@ -2923,7 +2922,7 @@ again:
!gsi_end_p (si); gsi_next (&si))
{
stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (gsi_stmt (si));
- STMT_SLP_TYPE (stmt_info) = loop_vect;
+ STMT_SLP_TYPE (stmt_info) = not_vect;
if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_reduction_def
|| STMT_VINFO_DEF_TYPE (stmt_info) == vect_double_reduction_def)
{
@@ -2942,7 +2941,7 @@ again:
if (is_gimple_debug (gsi_stmt (si)))
continue;
stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (gsi_stmt (si));
- STMT_SLP_TYPE (stmt_info) = loop_vect;
+ STMT_SLP_TYPE (stmt_info) = not_vect;
if (STMT_VINFO_IN_PATTERN_P (stmt_info))
{
stmt_vec_info pattern_stmt_info
@@ -2951,11 +2950,11 @@ again:
STMT_VINFO_IN_PATTERN_P (stmt_info) = false;
gimple *pattern_def_seq = STMT_VINFO_PATTERN_DEF_SEQ (stmt_info);
- STMT_SLP_TYPE (pattern_stmt_info) = loop_vect;
+ STMT_SLP_TYPE (pattern_stmt_info) = not_vect;
for (gimple_stmt_iterator pi = gsi_start (pattern_def_seq);
!gsi_end_p (pi); gsi_next (&pi))
STMT_SLP_TYPE (loop_vinfo->lookup_stmt (gsi_stmt (pi)))
- = loop_vect;
+ = not_vect;
}
}
}
diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
index ca14a2d..794a073 100644
--- a/gcc/tree-vect-slp.cc
+++ b/gcc/tree-vect-slp.cc
@@ -1140,7 +1140,7 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
soft_fail_nunits_vectype = nunits_vectype;
}
- gcc_assert (vectype);
+ gcc_assert (vectype || !gimple_get_lhs (first_stmt_info->stmt));
*node_vectype = vectype;
/* For every stmt in NODE find its def stmt/s. */
@@ -1187,10 +1187,7 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
gcall *call_stmt = dyn_cast <gcall *> (stmt);
tree lhs = gimple_get_lhs (stmt);
- if (lhs == NULL_TREE
- && (!call_stmt
- || !gimple_call_internal_p (stmt)
- || !internal_store_fn_p (gimple_call_internal_fn (stmt))))
+ if (lhs == NULL_TREE && !call_stmt)
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -4888,9 +4885,11 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size,
/* Find SLP sequences starting from groups of grouped stores. */
FOR_EACH_VEC_ELT (vinfo->grouped_stores, i, first_element)
- vect_analyze_slp_instance (vinfo, bst_map, first_element,
- slp_inst_kind_store, max_tree_size, &limit,
- force_single_lane);
+ if (! vect_analyze_slp_instance (vinfo, bst_map, first_element,
+ slp_inst_kind_store, max_tree_size, &limit,
+ force_single_lane)
+ && loop_vinfo)
+ return opt_result::failure_at (vect_location, "SLP build failed.\n");
/* For loops also start SLP discovery from non-grouped stores. */
if (loop_vinfo)
@@ -4908,10 +4907,29 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size,
vec<tree> remain = vNULL;
stmts.create (1);
stmts.quick_push (stmt_info);
- vect_build_slp_instance (vinfo, slp_inst_kind_store,
- stmts, roots, remain, max_tree_size,
- &limit, bst_map, NULL, force_single_lane);
+ if (! vect_build_slp_instance (vinfo, slp_inst_kind_store,
+ stmts, roots, remain, max_tree_size,
+ &limit, bst_map, NULL,
+ force_single_lane))
+ return opt_result::failure_at (vect_location,
+ "SLP build failed.\n");
}
+
+ stmt_vec_info stmt_info;
+ FOR_EACH_VEC_ELT (LOOP_VINFO_ALTERNATE_DEFS (loop_vinfo), i, stmt_info)
+ {
+ vec<stmt_vec_info> stmts;
+ vec<stmt_vec_info> roots = vNULL;
+ vec<tree> remain = vNULL;
+ stmts.create (1);
+ stmts.quick_push (stmt_info);
+ if (! vect_build_slp_instance (vinfo, slp_inst_kind_store,
+ stmts, roots, remain, max_tree_size,
+ &limit, bst_map, NULL,
+ force_single_lane))
+ return opt_result::failure_at (vect_location,
+ "SLP build failed.\n");
+ }
}
if (bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo))
@@ -5002,12 +5020,14 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size,
vec<tree> remain = vNULL;
stmts.create (1);
stmts.quick_push (next_info);
- vect_build_slp_instance (vinfo,
- slp_inst_kind_reduc_group,
- stmts, roots, remain,
- max_tree_size, &limit,
- bst_map, NULL,
- force_single_lane);
+ if (! vect_build_slp_instance (vinfo,
+ slp_inst_kind_reduc_group,
+ stmts, roots, remain,
+ max_tree_size, &limit,
+ bst_map, NULL,
+ force_single_lane))
+ return opt_result::failure_at (vect_location,
+ "SLP build failed.\n");
}
}
}
@@ -5032,11 +5052,14 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size,
vec<tree> remain = vNULL;
stmts.create (1);
stmts.quick_push (vect_stmt_to_vectorize (stmt_info));
- vect_build_slp_instance (vinfo,
- slp_inst_kind_reduc_group,
- stmts, roots, remain,
- max_tree_size, &limit,
- bst_map, NULL, force_single_lane);
+ if (! vect_build_slp_instance (vinfo,
+ slp_inst_kind_reduc_group,
+ stmts, roots, remain,
+ max_tree_size, &limit,
+ bst_map, NULL,
+ force_single_lane))
+ return opt_result::failure_at (vect_location,
+ "SLP build failed.\n");
}
}
saved_stmts.release ();
@@ -5065,11 +5088,14 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size,
vec<tree> remain = vNULL;
stmts.create (1);
stmts.quick_push (vect_stmt_to_vectorize (stmt_info));
- vect_build_slp_instance (vinfo,
- slp_inst_kind_reduc_group,
- stmts, roots, remain,
- max_tree_size, &limit,
- bst_map, NULL, force_single_lane);
+ if (! vect_build_slp_instance (vinfo,
+ slp_inst_kind_reduc_group,
+ stmts, roots, remain,
+ max_tree_size, &limit,
+ bst_map, NULL,
+ force_single_lane))
+ return opt_result::failure_at (vect_location,
+ "SLP build failed.\n");
}
}
@@ -5092,7 +5118,8 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size,
|| !integer_zerop (args1))
{
roots.release ();
- continue;
+ return opt_result::failure_at (vect_location,
+ "SLP build failed.\n");
}
/* An argument without a loop def will be codegened from vectorizing the
@@ -5110,7 +5137,11 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size,
stmts, roots, remain,
max_tree_size, &limit,
bst_map, NULL, force_single_lane))
- roots.release ();
+ {
+ roots.release ();
+ return opt_result::failure_at (vect_location,
+ "SLP build failed.\n");
+ }
}
/* Find and create slp instances for inductions that have been forced
@@ -5128,10 +5159,13 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size,
{
stmts.create (1);
stmts.quick_push (vect_stmt_to_vectorize (lc_info));
- vect_build_slp_instance (vinfo, slp_inst_kind_reduc_group,
- stmts, roots, remain,
- max_tree_size, &limit,
- bst_map, NULL, force_single_lane);
+ if (! vect_build_slp_instance (vinfo, slp_inst_kind_reduc_group,
+ stmts, roots, remain,
+ max_tree_size, &limit,
+ bst_map, NULL,
+ force_single_lane))
+ return opt_result::failure_at (vect_location,
+ "SLP build failed.\n");
}
/* When the latch def is from a different cycle this can only
be a induction. Build a simple instance for this.
@@ -5144,10 +5178,13 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size,
{
stmts.create (1);
stmts.quick_push (stmt_info);
- vect_build_slp_instance (vinfo, slp_inst_kind_reduc_group,
- stmts, roots, remain,
- max_tree_size, &limit,
- bst_map, NULL, force_single_lane);
+ if (! vect_build_slp_instance (vinfo, slp_inst_kind_reduc_group,
+ stmts, roots, remain,
+ max_tree_size, &limit,
+ bst_map, NULL,
+ force_single_lane))
+ return opt_result::failure_at (vect_location,
+ "SLP build failed.\n");
}
}
}
@@ -7610,7 +7647,8 @@ vect_make_slp_decision (loop_vec_info loop_vinfo)
/* If all instances ended up with vector(1) T roots make sure to
not vectorize. RVV for example relies on loop vectorization
when some instances are essentially kept scalar. See PR121048. */
- if (known_gt (TYPE_VECTOR_SUBPARTS (SLP_TREE_VECTYPE (root)), 1U))
+ if (SLP_TREE_VECTYPE (root)
+ && known_gt (TYPE_VECTOR_SUBPARTS (SLP_TREE_VECTYPE (root)), 1U))
decided_to_slp++;
}
@@ -7628,232 +7666,6 @@ vect_make_slp_decision (loop_vec_info loop_vinfo)
return (decided_to_slp > 0);
}
-/* Private data for vect_detect_hybrid_slp. */
-struct vdhs_data
-{
- loop_vec_info loop_vinfo;
- vec<stmt_vec_info> *worklist;
-};
-
-/* Walker for walk_gimple_op. */
-
-static tree
-vect_detect_hybrid_slp (tree *tp, int *, void *data)
-{
- walk_stmt_info *wi = (walk_stmt_info *)data;
- vdhs_data *dat = (vdhs_data *)wi->info;
-
- if (wi->is_lhs)
- return NULL_TREE;
-
- stmt_vec_info def_stmt_info = dat->loop_vinfo->lookup_def (*tp);
- if (!def_stmt_info)
- return NULL_TREE;
- def_stmt_info = vect_stmt_to_vectorize (def_stmt_info);
- if (PURE_SLP_STMT (def_stmt_info))
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location, "marking hybrid: %G",
- def_stmt_info->stmt);
- STMT_SLP_TYPE (def_stmt_info) = hybrid;
- dat->worklist->safe_push (def_stmt_info);
- }
-
- return NULL_TREE;
-}
-
-/* Look if STMT_INFO is consumed by SLP indirectly and mark it pure_slp
- if so, otherwise pushing it to WORKLIST. */
-
-static void
-maybe_push_to_hybrid_worklist (vec_info *vinfo,
- vec<stmt_vec_info> &worklist,
- stmt_vec_info stmt_info)
-{
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location,
- "Processing hybrid candidate : %G", stmt_info->stmt);
- stmt_vec_info orig_info = vect_orig_stmt (stmt_info);
- imm_use_iterator iter2;
- ssa_op_iter iter1;
- use_operand_p use_p;
- def_operand_p def_p;
- bool any_def = false;
- FOR_EACH_PHI_OR_STMT_DEF (def_p, orig_info->stmt, iter1, SSA_OP_DEF)
- {
- any_def = true;
- FOR_EACH_IMM_USE_FAST (use_p, iter2, DEF_FROM_PTR (def_p))
- {
- if (is_gimple_debug (USE_STMT (use_p)))
- continue;
- stmt_vec_info use_info = vinfo->lookup_stmt (USE_STMT (use_p));
- /* An out-of loop use means this is a loop_vect sink. */
- if (!use_info)
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location,
- "Found loop_vect sink: %G", stmt_info->stmt);
- worklist.safe_push (stmt_info);
- return;
- }
- else if (!STMT_SLP_TYPE (vect_stmt_to_vectorize (use_info)))
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location,
- "Found loop_vect use: %G", use_info->stmt);
- worklist.safe_push (stmt_info);
- return;
- }
- }
- }
- /* No def means this is a loop_vect sink. Gimple conditionals also don't have a
- def but shouldn't be considered sinks. */
- if (!any_def && STMT_VINFO_DEF_TYPE (stmt_info) != vect_condition_def)
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location,
- "Found loop_vect sink: %G", stmt_info->stmt);
- worklist.safe_push (stmt_info);
- return;
- }
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location,
- "Marked SLP consumed stmt pure: %G", stmt_info->stmt);
- STMT_SLP_TYPE (stmt_info) = pure_slp;
-}
-
-/* Find stmts that must be both vectorized and SLPed. */
-
-bool
-vect_detect_hybrid_slp (loop_vec_info loop_vinfo)
-{
- DUMP_VECT_SCOPE ("vect_detect_hybrid_slp");
-
- /* All stmts participating in SLP are marked pure_slp, all other
- stmts are loop_vect.
- First collect all loop_vect stmts into a worklist.
- SLP patterns cause not all original scalar stmts to appear in
- SLP_TREE_SCALAR_STMTS and thus not all of them are marked pure_slp.
- Rectify this here and do a backward walk over the IL only considering
- stmts as loop_vect when they are used by a loop_vect stmt and otherwise
- mark them as pure_slp. */
- auto_vec<stmt_vec_info> worklist;
- for (int i = LOOP_VINFO_LOOP (loop_vinfo)->num_nodes - 1; i >= 0; --i)
- {
- basic_block bb = LOOP_VINFO_BBS (loop_vinfo)[i];
- for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
- gsi_next (&gsi))
- {
- gphi *phi = gsi.phi ();
- stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (phi);
- if (!STMT_SLP_TYPE (stmt_info) && STMT_VINFO_RELEVANT (stmt_info))
- maybe_push_to_hybrid_worklist (loop_vinfo,
- worklist, stmt_info);
- }
- for (gimple_stmt_iterator gsi = gsi_last_bb (bb); !gsi_end_p (gsi);
- gsi_prev (&gsi))
- {
- gimple *stmt = gsi_stmt (gsi);
- if (is_gimple_debug (stmt))
- continue;
- stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (stmt);
- if (STMT_VINFO_IN_PATTERN_P (stmt_info))
- {
- for (gimple_stmt_iterator gsi2
- = gsi_start (STMT_VINFO_PATTERN_DEF_SEQ (stmt_info));
- !gsi_end_p (gsi2); gsi_next (&gsi2))
- {
- stmt_vec_info patt_info
- = loop_vinfo->lookup_stmt (gsi_stmt (gsi2));
- if (!STMT_SLP_TYPE (patt_info)
- && STMT_VINFO_RELEVANT (patt_info))
- maybe_push_to_hybrid_worklist (loop_vinfo,
- worklist, patt_info);
- }
- stmt_info = STMT_VINFO_RELATED_STMT (stmt_info);
- }
- if (!STMT_SLP_TYPE (stmt_info) && STMT_VINFO_RELEVANT (stmt_info))
- maybe_push_to_hybrid_worklist (loop_vinfo,
- worklist, stmt_info);
- }
- }
-
- /* Now we have a worklist of non-SLP stmts, follow use->def chains and
- mark any SLP vectorized stmt as hybrid.
- ??? We're visiting def stmts N times (once for each non-SLP and
- once for each hybrid-SLP use). */
- walk_stmt_info wi;
- vdhs_data dat;
- dat.worklist = &worklist;
- dat.loop_vinfo = loop_vinfo;
- memset (&wi, 0, sizeof (wi));
- wi.info = (void *)&dat;
- while (!worklist.is_empty ())
- {
- stmt_vec_info stmt_info = worklist.pop ();
- /* Since SSA operands are not set up for pattern stmts we need
- to use walk_gimple_op. */
- wi.is_lhs = 0;
- walk_gimple_op (stmt_info->stmt, vect_detect_hybrid_slp, &wi);
- /* For gather/scatter make sure to walk the offset operand, that
- can be a scaling and conversion away. */
- gather_scatter_info gs_info;
- if (STMT_VINFO_GATHER_SCATTER_P (stmt_info)
- && vect_check_gather_scatter (stmt_info, loop_vinfo, &gs_info))
- {
- int dummy;
- vect_detect_hybrid_slp (&gs_info.offset, &dummy, &wi);
- }
- }
-
- /* Determine if all the stmts in the loop can be SLPed. */
- for (unsigned i = 0; i < LOOP_VINFO_LOOP (loop_vinfo)->num_nodes; i++)
- {
- basic_block bb = LOOP_VINFO_BBS (loop_vinfo)[i];
- for (gphi_iterator si = gsi_start_phis (bb); !gsi_end_p (si);
- gsi_next (&si))
- {
- stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (si.phi ());
- if (!stmt_info)
- continue;
- if ((STMT_VINFO_RELEVANT_P (stmt_info)
- || VECTORIZABLE_CYCLE_DEF (STMT_VINFO_DEF_TYPE (stmt_info)))
- && !PURE_SLP_STMT (stmt_info))
- {
- /* STMT needs both SLP and loop-based vectorization. */
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location,
- "Loop contains SLP and non-SLP stmts\n");
- return false;
- }
- }
- for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si);
- gsi_next (&si))
- {
- if (is_gimple_debug (gsi_stmt (si)))
- continue;
- stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (gsi_stmt (si));
- stmt_info = vect_stmt_to_vectorize (stmt_info);
- if ((STMT_VINFO_RELEVANT_P (stmt_info)
- || VECTORIZABLE_CYCLE_DEF (STMT_VINFO_DEF_TYPE (stmt_info)))
- && !PURE_SLP_STMT (stmt_info))
- {
- /* STMT needs both SLP and loop-based vectorization. */
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location,
- "Loop contains SLP and non-SLP stmts\n");
- return false;
- }
- }
- }
-
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location,
- "Loop contains only SLP stmts\n");
- return true;
-}
-
-
/* Initialize a bb_vec_info struct for the statements in BBS basic blocks. */
_bb_vec_info::_bb_vec_info (vec<basic_block> _bbs, vec_info_shared *shared)
@@ -7937,7 +7749,10 @@ vect_slp_analyze_node_operations_1 (vec_info *vinfo, slp_tree node,
elements in a vector. For single-defuse-cycle, lane-reducing op, and
PHI statement that starts reduction comprised of only lane-reducing ops,
the number is more than effective vector statements actually required. */
- SLP_TREE_NUMBER_OF_VEC_STMTS (node) = vect_get_num_copies (vinfo, node);
+ if (SLP_TREE_VECTYPE (node))
+ SLP_TREE_NUMBER_OF_VEC_STMTS (node) = vect_get_num_copies (vinfo, node);
+ else
+ SLP_TREE_NUMBER_OF_VEC_STMTS (node) = 0;
/* Handle purely internal nodes. */
if (SLP_TREE_CODE (node) == VEC_PERM_EXPR)
@@ -11294,8 +11109,10 @@ vect_schedule_slp_node (vec_info *vinfo,
stmt_vec_info stmt_info = SLP_TREE_REPRESENTATIVE (node);
- gcc_assert (SLP_TREE_NUMBER_OF_VEC_STMTS (node) != 0);
- SLP_TREE_VEC_DEFS (node).create (SLP_TREE_NUMBER_OF_VEC_STMTS (node));
+ gcc_assert (!SLP_TREE_VECTYPE (node)
+ || SLP_TREE_NUMBER_OF_VEC_STMTS (node) != 0);
+ if (SLP_TREE_NUMBER_OF_VEC_STMTS (node) != 0)
+ SLP_TREE_VEC_DEFS (node).create (SLP_TREE_NUMBER_OF_VEC_STMTS (node));
if (SLP_TREE_CODE (node) != VEC_PERM_EXPR
&& STMT_VINFO_DATA_REF (stmt_info))
@@ -11540,8 +11357,6 @@ vect_remove_slp_scalar_calls (vec_info *vinfo,
{
if (!stmt_info)
continue;
- if (!PURE_SLP_STMT (stmt_info))
- continue;
stmt_info = vect_orig_stmt (stmt_info);
gcall *stmt = dyn_cast <gcall *> (stmt_info->stmt);
if (!stmt || gimple_bb (stmt) == NULL)
diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc
index 97222f6..f7a052b 100644
--- a/gcc/tree-vect-stmts.cc
+++ b/gcc/tree-vect-stmts.cc
@@ -386,6 +386,9 @@ vect_stmt_relevant_p (stmt_vec_info stmt_info, loop_vec_info loop_vinfo,
dump_printf_loc (MSG_NOTE, vect_location,
"vec_stmt_relevant_p: stmt has vdefs.\n");
*relevant = vect_used_in_scope;
+ if (! STMT_VINFO_DATA_REF (stmt_info)
+ && zero_ssa_operands (stmt_info->stmt, SSA_OP_DEF))
+ LOOP_VINFO_ALTERNATE_DEFS (loop_vinfo).safe_push (stmt_info);
}
/* uses outside the loop. */
@@ -4752,7 +4755,8 @@ vectorizable_simd_clone_call (vec_info *vinfo, stmt_vec_info stmt_info,
}
}
- SLP_TREE_VEC_DEFS (slp_node).quick_push (gimple_get_lhs (new_stmt));
+ if (gimple_get_lhs (new_stmt))
+ SLP_TREE_VEC_DEFS (slp_node).quick_push (gimple_get_lhs (new_stmt));
}
for (i = 0; i < nargs; ++i)
@@ -7780,10 +7784,6 @@ vectorizable_store (vec_info *vinfo,
return false;
}
- /* Cannot have hybrid store SLP -- that would mean storing to the
- same location twice. */
- gcc_assert (PURE_SLP_STMT (stmt_info));
-
tree vectype = SLP_TREE_VECTYPE (stmt_info), rhs_vectype = NULL_TREE;
poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype);
diff --git a/gcc/tree-vectorizer.cc b/gcc/tree-vectorizer.cc
index f992856..50985a6 100644
--- a/gcc/tree-vectorizer.cc
+++ b/gcc/tree-vectorizer.cc
@@ -733,7 +733,7 @@ vec_info::new_stmt_vec_info (gimple *stmt)
else
STMT_VINFO_DEF_TYPE (res) = vect_internal_def;
- STMT_SLP_TYPE (res) = loop_vect;
+ STMT_SLP_TYPE (res) = not_vect;
/* This is really "uninitialized" until vect_compute_data_ref_alignment. */
res->dr_aux.misalignment = DR_MISALIGNMENT_UNINITIALIZED;
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 0a75ee1..52e1075 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -947,6 +947,10 @@ public:
stmt in the chain. */
auto_vec<stmt_vec_info> reduction_chains;
+ /* Defs that could not be analyzed such as OMP SIMD calls without
+ a LHS. */
+ auto_vec<stmt_vec_info> alternate_defs;
+
/* Cost vector for a single scalar iteration. */
auto_vec<stmt_info_for_cost> scalar_cost_vec;
@@ -1186,6 +1190,7 @@ public:
#define LOOP_VINFO_INNER_LOOP_COST_FACTOR(L) (L)->inner_loop_cost_factor
#define LOOP_VINFO_INV_PATTERN_DEF_SEQ(L) (L)->inv_pattern_def_seq
#define LOOP_VINFO_DRS_ADVANCED_BY(L) (L)->drs_advanced_by
+#define LOOP_VINFO_ALTERNATE_DEFS(L) (L)->alternate_defs
#define LOOP_VINFO_FULLY_MASKED_P(L) \
(LOOP_VINFO_USING_PARTIAL_VECTORS_P (L) \
@@ -1288,26 +1293,12 @@ enum vect_relevant {
vect_used_in_scope
};
-/* The type of vectorization that can be applied to the stmt: regular loop-based
- vectorization; pure SLP - the stmt is a part of SLP instances and does not
- have uses outside SLP instances; or hybrid SLP and loop-based - the stmt is
- a part of SLP instance and also must be loop-based vectorized, since it has
- uses outside SLP sequences.
-
- In the loop context the meanings of pure and hybrid SLP are slightly
- different. By saying that pure SLP is applied to the loop, we mean that we
- exploit only intra-iteration parallelism in the loop; i.e., the loop can be
- vectorized without doing any conceptual unrolling, cause we don't pack
- together stmts from different iterations, only within a single iteration.
- Loop hybrid SLP means that we exploit both intra-iteration and
- inter-iteration parallelism (e.g., number of elements in the vector is 4
- and the slp-group-size is 2, in which case we don't have enough parallelism
- within an iteration, so we obtain the rest of the parallelism from subsequent
- iterations by unrolling the loop by 2). */
+/* The type of vectorization. pure_slp means the stmt is covered by the
+ SLP graph, not_vect means it is not. This is mostly used by BB
+ vectorization. */
enum slp_vect_type {
- loop_vect = 0,
+ not_vect = 0,
pure_slp,
- hybrid
};
/* Says whether a statement is a load, a store of a vectorized statement
@@ -1655,7 +1646,6 @@ struct gather_scatter_info {
#define STMT_VINFO_RELEVANT_P(S) ((S)->relevant != vect_unused_in_scope)
-#define HYBRID_SLP_STMT(S) ((S)->slp_type == hybrid)
#define PURE_SLP_STMT(S) ((S)->slp_type == pure_slp)
#define STMT_SLP_TYPE(S) (S)->slp_type
diff --git a/gcc/tree.cc b/gcc/tree.cc
index 0f02924..dcc1abd 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -323,9 +323,9 @@ unsigned const char omp_clause_num_ops[] =
1, /* OMP_CLAUSE_IS_DEVICE_PTR */
1, /* OMP_CLAUSE_INCLUSIVE */
1, /* OMP_CLAUSE_EXCLUSIVE */
- 2, /* OMP_CLAUSE_FROM */
- 2, /* OMP_CLAUSE_TO */
- 2, /* OMP_CLAUSE_MAP */
+ 3, /* OMP_CLAUSE_FROM */
+ 3, /* OMP_CLAUSE_TO */
+ 3, /* OMP_CLAUSE_MAP (update walk_tree_1 if this is changed) */
1, /* OMP_CLAUSE_HAS_DEVICE_ADDR */
1, /* OMP_CLAUSE_DOACROSS */
3, /* OMP_CLAUSE__MAPPER_BINDING_ */
@@ -11769,6 +11769,9 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
case OMP_CLAUSE:
{
int len = omp_clause_num_ops[OMP_CLAUSE_CODE (t)];
+ /* Do not walk the iterator operand of OpenMP MAP clauses. */
+ if (OMP_CLAUSE_HAS_ITERATORS (t))
+ len--;
for (int i = 0; i < len; i++)
WALK_SUBTREE (OMP_CLAUSE_OPERAND (t, i));
WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (t));
diff --git a/gcc/tree.h b/gcc/tree.h
index c0e434b..f1aacb31b 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1659,6 +1659,16 @@ class auto_suppress_location_wrappers
!= UNKNOWN_LOCATION)
#define OMP_CLAUSE_LOCATION(NODE) (OMP_CLAUSE_CHECK (NODE))->omp_clause.locus
+#define OMP_CLAUSE_HAS_ITERATORS(NODE) \
+ ((OMP_CLAUSE_CODE (NODE) == OMP_CLAUSE_FROM \
+ || OMP_CLAUSE_CODE (NODE) == OMP_CLAUSE_TO \
+ || OMP_CLAUSE_CODE (NODE) == OMP_CLAUSE_MAP) \
+ && OMP_CLAUSE_ITERATORS (NODE))
+#define OMP_CLAUSE_ITERATORS(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (OMP_CLAUSE_CHECK (NODE), \
+ OMP_CLAUSE_FROM, \
+ OMP_CLAUSE_MAP), 2)
+
/* True on OMP_FOR and other OpenMP/OpenACC looping constructs if the loop nest
is non-rectangular. */
#define OMP_FOR_NON_RECTANGULAR(NODE) \