From patchwork Fri Nov 29 15:05:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: unmush X-Patchwork-Id: 34255 Return-Path: X-Original-To: patchwork@mira.cbaines.net Delivered-To: patchwork@mira.cbaines.net Received: by mira.cbaines.net (Postfix, from userid 113) id 6E17D27BBEA; Fri, 29 Nov 2024 20:58:27 +0000 (GMT) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mira.cbaines.net (Postfix) with ESMTPS id D1EB527BBE9 for ; Fri, 29 Nov 2024 20:58:26 +0000 (GMT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tH845-0007tQ-Nf; Fri, 29 Nov 2024 15:58:13 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tH548-0001c2-Vj for guix-patches@gnu.org; Fri, 29 Nov 2024 12:46:05 -0500 Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1tH548-0007K2-Km for guix-patches@gnu.org; Fri, 29 Nov 2024 12:46:04 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=debbugs.gnu.org; s=debbugs-gnu-org; h=MIME-Version:From:Date:To:Subject; bh=5BdJ2GZZrTwq59Xn8qI8n3DnwsHxQIOn2BX8rf3v+xo=; b=hclhQHgb63C8TLQwwIDGXAgUID+lCKG+WQhKYU99/z3wxKFmGSpEylLpS+pPpRQRmXgYLocH18PJ07hQVTGsy/97zYWNsozbtztDW7pnttSk6d1/W+SCu7Qb9M0QP95/PoSeRy3cUf/TqDDUgbQgN9qA++oJcW2/i/0KI8GcuadSQ5KfU+gfzmsVlXtUQ97tCGZU0EHT90wDvc7l/Soc9X3LUxqN9V90rv12wH7vIhU7ZgUC9NjCXIvJRwQGmTjaM2IuHmWumPWHcQDBtuGtkJE8is+D2jxrvcFfaUEqSW0WLe9HpEY+HXJGn0hETp3i22oQ+7d36qHW/p4/NCgRaA==; Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1tH547-0005Tn-GZ for guix-patches@gnu.org; Fri, 29 Nov 2024 12:46:03 -0500 X-Loop: help-debbugs@gnu.org Subject: [bug#74609] [PATCH] Adding a fully-bootstrapped mono Resent-From: unmush Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Fri, 29 Nov 2024 17:46:03 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 74609 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 74609@debbugs.gnu.org X-Debbugs-Original-To: "guix-patches@gnu.org" Received: via spool by submit@debbugs.gnu.org id=B.173290233721004 (code B ref -1); Fri, 29 Nov 2024 17:46:03 +0000 Received: (at submit) by debbugs.gnu.org; 29 Nov 2024 17:45:37 +0000 Received: from localhost ([127.0.0.1]:44296 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tH53h-0005Sh-FF for submit@debbugs.gnu.org; Fri, 29 Nov 2024 12:45:37 -0500 Received: from lists.gnu.org ([209.51.188.17]:55242) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tH2Z9-0005ka-4U for submit@debbugs.gnu.org; Fri, 29 Nov 2024 10:05:55 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tH2Z7-0003dZ-PM for guix-patches@gnu.org; Fri, 29 Nov 2024 10:05:54 -0500 Received: from mail-40135.protonmail.ch ([185.70.40.135]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tH2Yk-0000pA-Do for guix-patches@gnu.org; Fri, 29 Nov 2024 10:05:53 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=proton.me; s=protonmail; t=1732892717; x=1733151917; bh=5BdJ2GZZrTwq59Xn8qI8n3DnwsHxQIOn2BX8rf3v+xo=; h=Date:To:From:Subject:Message-ID:Feedback-ID:From:To:Cc:Date: Subject:Reply-To:Feedback-ID:Message-ID:BIMI-Selector: List-Unsubscribe:List-Unsubscribe-Post; b=Fw05FbZh7y0wfyJ8cg7e19IyCNOcCahVjvLVXGv5sk0+4xm2sGULVQhbHYDVwqvgF mSNaVmP6MILbco29iQBSKHCKfn56Kr4NGj8dU+sImBwdgh0WSGE+p2CqqyiIyxLExe dS1BVl14Kr8lyAhG18yHcnysSoJ4hLzF+JCWKQsBhSyx9NRVi278I+TqGNg/klmjOF amI9DJAdXUF/CEZNIhk3xk6zJrlhvtWIliGKRE3wwWRkQ7YXbZ2n+FbNoCGMx9HU1p wxn1iyCgwxlqwfLnZZyJRvuYFIIvCitvV3RUbciOL8po7p4088xlHOzUdTwTikzSW2 ANDwy1yS7HmnQ== Date: Fri, 29 Nov 2024 15:05:09 +0000 Message-ID: Feedback-ID: 126986417:user:proton X-Pm-Message-ID: 6499f2f3bd38752c35c3f0b32ffba1249db73cd3 MIME-Version: 1.0 Received-SPF: pass client-ip=185.70.40.135; envelope-from=unmush@proton.me; helo=mail-40135.protonmail.ch X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Fri, 29 Nov 2024 12:45:36 -0500 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-Mailman-Approved-At: Fri, 29 Nov 2024 15:58:09 -0500 X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-to: unmush X-ACL-Warn: , unmush via Guix-patches X-Patchwork-Original-From: unmush via Guix-patches via From: unmush Errors-To: guix-patches-bounces+patchwork=mira.cbaines.net@gnu.org Sender: guix-patches-bounces+patchwork=mira.cbaines.net@gnu.org X-getmail-retrieved-from-mailbox: Patches We used to have a mono package, but it was removed due to includingbootstrap binaries (among others).  This patch series introduces a full, 17-mono-package sequence that takes us from a mono-1.2.6 built fully from source to mono-6.12.0 built fully from source, using only packages that already have full bootstrap paths.  I make no promise that this is the shortest or most optimal path, but it exists and I have verified it works. As I've spent what is probably an unreasonable amount of time working toward this, I thought I'd share some of my thoughts, experiences, and commentary.  Sorry in advance if it gets a bit rambly or lecture-ish. * Prologue I started down this road because someone I'm working on a project with decided to depend on a C# package that requires C# 12.0 features, and my personal mono package based on the tarball releases (which include bootstrap binaries) only went up to C# 7.0.  This meant that the C# package in question de facto required strictly Microsoft's (er, I mean, "the .NET foundation"'s) .NET implementation - hereafter referred to as "dotnet" - and a very recent version no less.  The bootstrapping story with dotnet is very bad: https://github.com/dotnet/source-build/issues/1930.  Even beginning to untangle it would probably require a relatively modern C# compiler, and something that at least sort of understands msbuild.  And there's not much point to "bootstrapping" dotnet from something that isn't bootstrapped itself.  So I figured I may as well start with mono. * History While mono is today probably the most well-known alternative to Microsoft's .NET offerings, it is not the only one.  Indeed, in the early 2000s there were at least 2 competing free software implementations: Mono, and DotGNU's Portable.NET (abbreviated pnet). They differed in goals, licenses, and methods: Portable.NET was a GNU project concerned with, among other things, limiting the ability of Microsoft to impose vendor lock-in via its proprietary .NET implementation and software patents.  As a GNU project, it used the GPL for its runtime and compiler, and the GPL with a linking exception for its standard library, pnetlib.  Mono, on the other hand, used a mix of many copyleft and permissive licenses: X11 for the standard library, GPL for the compiler (later dual-licensed to add an X11 option), and LGPL for the runtime, with GPL and LGPL code also offered "under commercial terms for when the GPL and the LGPL are not suitable".  In 2016 after its acquisition by Microsoft, the runtime was relicensed to use the Expat (MIT) license. But perhaps most importantly to us, while Mono opted to write its C# compiler, mcs, in... C#, Portable.NET's runtime and C# compiler were both written in C.  Portable.NET along with the entire DotGNU project was decommissioned in 2012, but the source is still available, and it still works fine (with a few modifications for compatibility with newer versions of its dependencies).  In https://issues.guix.gnu.org/57625 Adam Faiz submitted patches to package pnet and pnetlib, along with one of their dependencies named treecc.  These packages were based on the last release of Portable.NET, version 0.8.0, released in 2007.  I initially used these packages as the basis for my bootstrap efforts, and even managed to get mono-1.2.6 built using them, but later discovered that using a more recent version from git made it much easier.  For example, while pnet-0.8.0 can do pointer arithmetic inside unsafe code blocks, it doesn't support the += or -= operators specifically, which requires lots of patching (after all, who would use x = x + y when you could do x+= y?).  There are many other similar improvements in the git version, so for this patch series I've decided to go with pnet-git. * The start After building mono-1.2.6, I tried a few later versions, and the third or fourth one would always fail with errors about missing methods.  It turns out that the reason for this is that, contrary to what their marketing suggests, C# and Java are not "write once, run everywhere". This is because their compilers rely on the details of the libraries that the program will be run with at compile-time.  This is used, for example, to do overload resolution.  Suppose, for example, that a certain implementation of the "==" operator is present in version 1.0 of a library, and then in version 2.0 of a library a more specific implementation is introduced.  Now code that is compiled against version 2.0 may instead automatically reference the more-specific implementation, as is in accordance with the rules of C#.  But when it is run with version 1.0, it will fail because that implementation doesn't exist.  In my case, for some reason the initial mcs and core libraries being built to compile the rest of mono were being compiled against a 2.0 library and then run with a 1.0 library.  It turns out that this was because mcs uses mono's code for producing assemblies (.NET dlls and exes), and mono decides which version to put in an assembly it writes based on "which runtime version" is being used, and that version is decided at startup based on... the version that was put in the assembly it is running.  So for example, mono-1.9.1 would produce 2.0 assemblies because mono-1.2.6 produced 2.0 assemblies because pnet produced 2.0 assemblies.  So I modified mono's runtime in mono-1.9.1 to allow for this version to be overridden via environment variable, and set it to "v1.1.4322", and things went a lot more smoothly after that. From there on it was mostly the usual trial-and-error process of identifying where things had bitrotted.  I made sure to unvendor libgc wherever possible, though eventually by mono-4.9.0 they explicitly dropped support in their configure script for using any libgc other than what was bundled, so at that point I switched to using their homebrewed sgen garbage collector. * A concerning development Once I got to mono-2.11.4, though, things took a turn for the interesting: mono started using git submodules, and the (recursive? #t) clones were all failing.  It turns out that this is because their submodules reference github.com using the git:// protocol. This is notable for a few reasons. First, github dropped support for the git:// protocol in 2021, so recursive clones won't work now.  This means I have to explicitly list out every submodule, its commit, and its sha256 hash, for every mono version until they switched to using http or https.  mono-2.11.4 has only 4 submodules, but that doesn't last for long: by mono-4.9.0 it has 14 submodules.  A significant portion of these patches is just listing these submodules and their hashes.  It's a bit annoying. The more concerning reason, though, is *why* github dropped support for the git:// protocol: it is unencrypted and unauthenticated.  This is mitigated somewhat by the use of sha-1 hashes to identify commits in the referenced submodules, putting a significant computational burden on anyone who would try to alter what was fetched corresponding to a given submodule.  Significantly more risky, though, is the process of *updating* submodules that use git:// URLs.  It is quite unlikely that a developer is going to independently clone one of the submodules over https, navigate to a desirable commit, copy the sha-1 hash, and manually update the submodule reference's commit.  They're far more likely to run 'cd submodule; git pull; cd ..; git add submodule; git commit ...' or an equivalent. Of course, any changes a network man-in-the-middle might try to make here would still be reflected in the commit history, so even if a developer did that, they or any of their fellow committers could spot anything strange or malicious and point it out.  Also, the changes couldn't be propagated to others trying to pull them who weren't on a path containing the MITM because the potentially-malicious commit wouldn't be present in the real submodule's repository.  So the transparency of git clearly showing changes to text files, combined with the fact that surely no git hosting platform would just allow arbitrary entities to make whatever commits they want accessible under any arbitrary repository URL, rather mitigate this security issue. This usage of git:// URLs lasted all the way until September 28, 2021, when github's removal of support for it forced the developers to change them to https. * Meanwhile, in reality On November 28, 2016, mono added a submodule named roslyn-binaries. Unsurprisingly, it included binary blobs for Microsoft's Roslyn compiler (which I believe had been open-sourced shortly prior).  From here on, mono's build system would default to using these binaries for building on little-endian systems (though another compiler could be specified with the --with-csc configure flag).  I happen to know that it is extremely unlikely that many mono developers used this configure flag. I know this because the 5.0 series is an absolute pain in the neck to build from source, because they consistently depend on new C# features *before* they implement them. To go on a brief tangent: does anyone remember back when youtube-dl was temporarily taken down from github due to the RIAA's DMCA request?  Many were unhappy about that.  One such unhappy person made news when they made the full contents of youtube-dl's repository available to access through the DMCA request repository: https://gist.github.com/lrvick/02088ee5466ca51116bdaf1e709ddd7c.  It turns out that there are many actions that one can take on github that will make arbitrary commits available under arbitrary repository URLs. So, in reality, for the span of time from November 28, 2016 to September 28, 2021, anybody sitting on the network path between github and any mono developer updating the roslyn-binaries submodule could decide on any arbitrary new commit to be used.  Of course, merely inspecting the diff for the commit will reveal nothing of use, because the contents are binary blobs.  And not only are these blobs those of a compiler, they are the blobs of a compiler that is sure to be used to compile another compiler, which will then be redistributed as an opaque, non-bootstrappable binary blob to be used for compiling other compilers. You would be hard-pressed to find a more fertile breeding ground for Ken Thompson / Trusting Trust attacks.  If every agent of the NSA (and whatever other agencies, including those of other countries, had access to the appropriate network traffic) somehow failed to capitalize on 6 years of opportunity to compromise an entire software ecosystem using only a basic MITM of unencrypted traffic, they deserve to be sacked. Whether such an attack actually occurred or not, this is a case study in carelessness and why bootstrappability is so important; discovering all this made me quite worried about having used a mono version built from blobs previously, and has convinced me that, as time-wasting and tedious as this project has been, it is nevertheless probably an important one. * Another note on roslyn-binaries If you're going to write a self-hosting compiler, the least you can do is keep it self-hosting.  Deciding to write a self-hosting compiler is a valid choice, of course, with its own merits and demerits, but there is something bitterly poetic about mono starting out requiring specifically Microsoft's C# compiler in order to build (mono did its initial bootstrapping using Microsoft's proprietary csc), achieving independence through self-hosting, being acquired by Microsoft, and thereafter coming crawling back to Microsoft's C# compiler once more before eventually dying. The funny thing is that it's not even necessary.  The dependencies on new C# features are all in mono's standard library (which increasingly borrowed code from Microsoft's corefx library), not in mono's compiler. * More binary submodules? Even before roslyn-binaries, there was binary-reference-assemblies, which contained prebuilt "reference" blobs for the various versions of the standard libraries.  These exist, I assume, precisely because of the library incompatibility problems regarding overloading that I mentioned earlier.  While later versions of mono included sources and a build system for producing these reference binaries, mono-4.9.0 and earlier did not.  Mono's build system still demanded /something/ to install, though, so I told it to use the real standard library of the input mono version.  When I did get to a mono version that at least claimed to support regenerating the reference binaries, I found that it didn't work with mcs due to differences in which libraries had to be referenced, so I had to patch it to add a bunch of references determined through trial and error. The xunit-binaries submodule was also added sometime before mono-5.1.0. This dependency makes it impossible to run the full test suite without binary blobs.  Presumably for this reason, Debian elects to only run tests within the mono/mini/ and mono/tests/ subdirectories.  For my part, I've disabled all tests except for those of mono-6.12.0, the final version, limited to the two aforementioned subdirectories.  This is because it would take extra time for the builds, because several of the tests depend on binary blobs bundled into the mono repository itself (which my thorough cleaning of all dlls and exes from the sources removes), because a large chunk of the tests depend on binary blobs in xunit-binaries in later versions, and because "expect some test failures" is part of the mono documentation and I don't have the time to figure out for the mono developers every reason why each of 17 versions of their test suite is broken. * The long march through the 5.0s The 5.0 series was when Microsoft acquired Mono, and it shows.  You'll notice I needed to introduce "pre-" packages for various versions because in several cases a tagged release could not build the following tagged release.  For that matter, they couldn't build the pre- package either, but it at least took fewer patches to get them working.  The reason for this is that Mono added a dependency on Microsoft's corefx library source code, and it usually started using C# features well before mcs was able to compile them.  Because of this, despite taking 8 versions to get from 1.2.6 to 4.9.0, it took another 8 versions to get through the 5.0 series, and 5 of them required nontrivial patching to massage the source into a form compilable by mcs. * The final stretch Eventually I realized that the dependencies on new features were all coming from corefx, not from mono's compiler.  Consequently, the only reason for this particular bootstrap-hostile ordering of builds is that it happened to be the order the mono devs committed things.  So I just cherry-picked every commit I could find touching mcs/mcs (magit was quite useful for this) and applied it to 5.10.0 to produce what is essentially the 6.12.0 compiler, then used it to jump straight to building 6.12.0. Use of this technique earlier on in the bootstrap process may be of interest to anyone looking to shorten the chain of packages. * The finishing touches My initial goal was to package dotnet, and I had tried to progress toward that from mono-4.9.0 for a period, but with no success.  During that time, though, I did encounter a bug in mono's xbuild condition parser, which I wrote a patch for, and included in mono-6.12.0. I also discovered that xbuild would wrongly complain about missing references even when the proper assemblies were in MONO_PATH or MONO_GAC_PREFIX, because xbuild would erroneously only consider the path /gnu/store/...mono-6.12.0/lib/mono/gac when looking for global assembly caches, completely ignoring MONO_GAC_PREFIX.  So I wrote a patch to fix that, and included it in mono-6.12.0. Having witnessed how much nicer it is to package things that use rpath / runpath than things that use environment variables (like python) and therefore require constant wrapping of executables and use of propagated-inputs, I devised a patch that would extend mono's per-assembly config files to support a element.  For example, if you have a file /tmp/dir2/test2.exe, and there is also a file /tmp/dir2/test2.exe.config, and its contents are   and it references test1.dll, it will first look for it at /tmp/dir1/test1.dll.  Note that, of course, test1.dll still needs to be accessible to the compiler at compile-time through MONO_PATH or an explicitly-specified path passed on the mcs command line. It is my hope that this feature will be of use to anybody interested in developing a build system. * Future work Mono had several difficult points in bootstrapping and packaging, but at the end of the day it still met the basic description of a software package: well-defined environment-supplied inputs and sources, a user-supplied install prefix, and files installed under that prefix. The dotnet world is an entirely different beast.  The first step of most build systems I have encountered from that realm is downloading an entire toolchain, among other dependencies, as a binary blob.  They heavily depend on the exact packages they specify being available exactly where they say to install them.  There is no "install", there are no "install directories" to my knowledge.  A build that doesn't contact nuget.org is an abberation.  I am at a loss how to build these things, much less package them.  I badly need help. * Closing thoughts "You wish now that our places had been exchanged.  That I had died, and DotGNU had lived?" "... Yes.  I wish that." Maintenance of Mono was recently transferred over to WineHQ.  With that announcement this statement was placed at https://www.mono-project.com: "We want to recognize that the Mono Project was the first .NET implementation on Android, iOS, Linux, and other operating systems. The Mono Project was a trailblazer for the .NET platform across many operating systems. It helped make cross-platform .NET a reality and enabled .NET in many new places and we appreciate the work of those who came before us." I would like to clarify that, according to Miguel de Icaza himself (https://www.mono-project.com/archived/mailpostearlystory/), DotGNU "started working on the system about the same time".  According to https://lwn.net/2002/0103/a/dotgnu.php3 Portable.NET began "in January 2001".  While it's unclear exactly when Portable.NET reached various milestones, and the significance of the various milestones varies somewhat (for example, mono probably does not care that Portable.NET also includes a Java and C compiler), I think that there is cause to dispute the claim that Mono was "the first" .NET implementation on Linux. On a related note, if we haven't looked at the possibility of using Portable.NET in the Java bootstrap process, it may be worth visiting at some point. Thank you for your time, I think I need to get some rest now. - unmush From f33bc85d3e99204338a69a50af045e7eb977eda7 Mon Sep 17 00:00:00 2001 Message-ID: In-Reply-To: <3f8af65f72871d61fa85e6939f46cb8dac185c70.1732707288.git.unmush@hashbang.sh> References: <3f8af65f72871d61fa85e6939f46cb8dac185c70.1732707288.git.unmush@hashbang.sh> From: unmush Date: Wed, 27 Nov 2024 00:54:28 Subject: [PATCH 19/21] gnu: Add mono-5.10.0. * gnu/packages/dotnet.scm (mono-5.10.0-external-repo-specs, mono-5.10.0): New variables. * gnu/packages/patches/mono-5.10.0-later-mcs-changes.patch: New patch. * gnu/local.mk (dist_patch_DATA): Register new patch. Change-Id: Ic5e123c2cd12f9b77d012cd7d73f9be0b5a608ec --- gnu/local.mk | 1 + gnu/packages/dotnet.scm | 119 + .../mono-5.10.0-later-mcs-changes.patch | 4601 +++++++++++++++++ 3 files changed, 4721 insertions(+) create mode 100644 gnu/packages/patches/mono-5.10.0-later-mcs-changes.patch diff --git a/gnu/local.mk b/gnu/local.mk index 7e26416e78..6b0ebdf2d7 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -1771,6 +1771,7 @@ dist_patch_DATA = \ %D%/packages/patches/mono-4.9.0-fix-runtimemetadataversion.patch \ %D%/packages/patches/mono-5.4.0-patches.patch \ %D%/packages/patches/mono-5.8.0-patches.patch \ + %D%/packages/patches/mono-5.10.0-later-mcs-changes.patch \ %D%/packages/patches/mono-mcs-patches-from-5.10.0.patch \ %D%/packages/patches/mosaicatcher-unbundle-htslib.patch \ %D%/packages/patches/mrrescue-support-love-11.patch \ diff --git a/gnu/packages/dotnet.scm b/gnu/packages/dotnet.scm index 439e9779bb..3309cec3f5 100644 --- a/gnu/packages/dotnet.scm +++ b/gnu/packages/dotnet.scm @@ -1472,3 +1472,122 @@ (define-public mono-pre-5.10.0 (search-patches "mono-mcs-patches-from-5.10.0.patch")))) (native-inputs (modify-inputs (package-native-inputs mono-5.8.0) (replace "mono" mono-5.8.0)))))) + +(define mono-5.10.0-external-repo-specs + '(("api-doc-tools" "d03e819838c6241f92f90655cb448cc47c9e8791" + "1riki79f3ig3cxigviss81dz601hn92a1gifglm0mzjbs76sf3fj" + #:recursive? #t) + ("api-snapshot" "da8bb8c7b970383ce26c9b09ce3689d843a6222e" + "00kxw09yirdh0bzkvs0v3h6bkdjv9d4g9agn3b8640awvpym3yqw") + ("aspnetwebstack" "e77b12e6cc5ed260a98447f609e887337e44e299" + "0rks344qr4fmp3fs1264d2qkmm348m8d1kjd7z4l94iiirwn1fq1") + (("reference-assemblies" "binary-reference-assemblies") + "e048fe4a88d237d105ae02fe0363a68296099362" + "0i87i3x694f4g8s2flflv0ah88blxds7gbiyrwrmscqdjsifhy49") + ("bockbuild" "1908d43ec630544189bd11630a59ec4ef571db28" + "1h13lgic2dwnbzc58nqhjhagn0f100nl5mhzryjdmypgrf3cr1b3") + ("boringssl" "3e0770e18835714708860ba9fe1af04a932971ff" + "139a0gl91a52k2r6na6ialzkqykaj1rk88zjrkaz3sdxx7nmmg6y") + ("cecil" "dfee11e80d59e1a3d6d9c914c3f277c726bace52" + "1y2f59v988y2llqpqi0zl9ly0lkym8zw0a4vkav7cpp6m5mkq208") + (("cecil" "cecil-legacy") "33d50b874fd527118bc361d83de3d494e8bb55e1" + "1p4hl1796ib26ykyf5snl6cj0lx0v7mjh0xqhjw6qdh753nsjyhb") + ("corefx" "e327d2855ed74dac96f684797e4820345297a690" + "11pinnn8zwf4hi0gfj98cyqkmh7wrmd5mhcdm84gkl9s2g18iaq0") + ("corert" "aa64b376c1a2238b1a768e158d1b11dac77d722a" + "1gg4m49s0ry5yx96dwjary7r395ypzzg4ssz1ajld2x5g7ggvwgg") + ("ikdasm" "465c0815558fd43c0110f8d00fc186ac0044ac6a" + "0xir7pcgq04hb7s8g9wsqdrypb6l29raj3iz5rcqzdm0056k75w2") + (("ikvm-fork" "ikvm") "847e05fced5c9a41ff0f24f1f9d40d5a8a5772c1" + "1fl9bm3lmzf8iqv3x4iqkz9fc54mwdvrxisxg2nvwwcsi4saffpi") + ("linker" "84d37424cde6e66bbf997110a4dbdba7e60038e9" + "07ffkc9ijzsdvbkrc1fn5sb25sgxyabs54kzyblwkzparwj047qr") + ("Newtonsoft.Json" "471c3e0803a9f40a0acc8aeceb31de6ff93a52c4" + "0dgngd5hqk6yhlg40kabn6qdnknm32zcx9q6bm2w31csnsk5978s") + (("NuGet.BuildTasks" "nuget-buildtasks") + "b2c30bc81b2a7733a4eeb252a55f6b4d50cfc3a1" + "01vajrfx6y12f525xdiwfbn9qzmym2s65rbiqpy9d9xw0pnq7gbl") + (("NUnitLite" "nunit-lite") "70bb70b0ffd0109aadaa6e4ea178972d4fb63ea3" + "0ln7rn1960cdwmfqcscp2d2ncpwnknhq9rf8v53ay8g2c3g6gh4q") + ;; ("roslyn-binaries" "00da53c4746250988a92055ef3ac653ccf84fc40" + ;; "") + ("rx" "b29a4b0fda609e0af33ff54ed13652b6ccf0e05e" + "1n1jwhmsbkcv2d806immcpzkb72rz04xy98myw355a8w5ah25yiv") + ;; ("xunit-binaries" "c5a907be25c201cda38bec99f6c82548ab3d9b5a" + ;; "") + )) + +(define-public mono-5.10.0 + (package + (inherit mono-pre-5.10.0) + (version "5.10.0.179") + (name "mono") + (source (origin + (method git-fetch) + (uri + (git-reference + (url "https://gitlab.winehq.org/mono/mono.git") + (commit "mono-5.10.0.179"))) + (file-name (git-file-name name version)) + (sha256 + (base32 + "1zvib164w4mzrsk06ym9my0208ccdanja2fx6x6mlyib358h3626")) + (modules '((guix build utils) + (ice-9 string-fun))) + (snippet #~(begin + #$(add-external-repos + mono-5.10.0-external-repo-specs) + #$@prepare-mono-source-0)) + (patches + (search-patches "mono-5.10.0-later-mcs-changes.patch")))) + (native-inputs (modify-inputs (package-native-inputs mono-pre-5.10.0) + (replace "mono" mono-pre-5.10.0) + (append (default-python)))) + (arguments + (substitute-keyword-arguments (package-arguments mono-pre-5.10.0) + ((#:phases phases #~%standard-phases) + #~(modify-phases #$phases + ;; Build now relies on these being built before any mcs is built; + ;; have to use the input mcs. + (delete 'build-reference-assemblies) + (add-before 'build 'build-reference-assemblies + (lambda* (#:key make-flags #:allow-other-keys) + (let ((top (getcwd))) + (with-directory-excursion + "external/binary-reference-assemblies" + (substitute* (find-files "." "^Makefile$") + (("CSC_COMMON_ARGS := " all) + (string-append all "-delaysign+ ")) + (("IBM\\.Data\\.DB2_REFS := " all) + (string-append all "System.Xml ")) + (("Mono\\.Data\\.Sqlite_REFS := " all) + (string-append all "System.Xml ")) + (("System\\.Data\\.DataSetExtensions_REFS := " all) + (string-append all "System.Xml ")) + (("System\\.Data\\.OracleClient_REFS := " all) + (string-append all "System.Xml ")) + (("System\\.IdentityModel_REFS := " all) + (string-append all "System.Configuration ")) + (("System\\.Design_REFS := " all) + (string-append all "Accessibility ")) + (("System\\.Web\\.Extensions\\.Design_REFS := " all) + (string-append all "System.Windows.Forms System.Web ")) + (("System\\.ServiceModel\\.Routing_REFS := " all) + (string-append all "System.Xml ")) + (("System\\.Web\\.Abstractions_REFS := " all) + (string-append all "System ")) + (("System\\.Reactive\\.Windows\\.Forms_REFS := " all) + (string-append all "System ")) + (("System\\.Windows\\.Forms\\.DataVisualization_REFS := " all) + (string-append all "Accessibility ")) + (("Facades/System\\.ServiceModel\\.Primitives_REFS := " all) + (string-append all "System.Xml ")) + (("Facades/System\\.Dynamic\\.Runtime_REFS := " all) + (string-append all "System ")) + (("Facades/System\\.Xml\\.XDocument_REFS := " all) + (string-append all "System.Xml ")) + (("Facades/System\\.Runtime\\.Serialization.Xml_REFS := " all) + (string-append all "System.Xml ")) + (("Facades/System\\.Data\\.Common_REFS := " all) + (string-append all "System System.Xml "))) + (apply invoke "make" "CSC=mcs" make-flags))))))))))) diff --git a/gnu/packages/patches/mono-5.10.0-later-mcs-changes.patch b/gnu/packages/patches/mono-5.10.0-later-mcs-changes.patch new file mode 100644 index 0000000000..c4e211a8a3 --- /dev/null +++ b/gnu/packages/patches/mono-5.10.0-later-mcs-changes.patch @@ -0,0 +1,4601 @@ +The result of cherry-picking every commit (except ones that seemed to not +affect the compiler itself) from mono-5.10.0.179 to mono-6.12.0.206 that +touched ./mcs/mcs. + +Mono seems to consistently, almost as a rule, depend on C# features before +they implement them. This is extremely awkward for building using previous +versions, so hopefully this will allow us to jump straight to a high version. + +Includes the following commits, in order of most-recent to least-recent: + +b3911589b37 +6700dd220fe +2a7dfb28e07 +eea6f11a3e6 +3fc047c6f3a +ac6666f5b0b +927b27bb9d8 +4ab24d4c059 +aa836b46a23 +ee7dccfb320 +23510f26915 +d9f26547d88 +9dc1c885a0f +ef558ead89a +2cb7909b13c +0390ea2e78c +b4f6659bdc0 +e92d6070eaf +4c5b3fbd4f4 +e6507f2da8a +656a4b1120c +9bd2fa4cf33 +be2d1aeffe0 +454a76cfa4a +60c1ee454d4 +53f1ef506ea +d3487bfebb3 +92f6e5b1a81 + +diff --git a/.gitignore b/.gitignore +index c6ef19a849b..c37d4fce3f0 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -40,6 +40,7 @@ Ankh.NoLoad + *.gpState + .vscode/ + *.exp ++.vs/ + + # Tooling + _ReSharper*/ +diff --git a/mcs/class/Commons.Xml.Relaxng/Makefile b/mcs/class/Commons.Xml.Relaxng/Makefile +index 1febae4eb1e..f9b57fea265 100644 +--- a/mcs/class/Commons.Xml.Relaxng/Makefile ++++ b/mcs/class/Commons.Xml.Relaxng/Makefile +@@ -22,7 +22,7 @@ EXTRA_DISTFILES = \ + $(RESOURCE_FILES) + + Commons.Xml.Relaxng.Rnc/RncParser.cs: Commons.Xml.Relaxng.Rnc/RncParser.jay $(topdir)/jay/skeleton.cs +- $(topdir)/jay/jay -ctv < $(topdir)/jay/skeleton.cs $(CURDIR)/Commons.Xml.Relaxng.Rnc/RncParser.jay > Commons.Xml.Relaxng.Rnc/RncParser.cs ++ $(topdir)/jay/jay -ctv -o Commons.Xml.Relaxng.Rnc/RncParser.cs $< < $(topdir)/jay/skeleton.cs + + BUILT_SOURCES = Commons.Xml.Relaxng.Rnc/RncParser.cs + +diff --git a/mcs/class/Microsoft.Build/Makefile b/mcs/class/Microsoft.Build/Makefile +index 2dcbefdf7f9..1a711069b0b 100644 +--- a/mcs/class/Microsoft.Build/Makefile ++++ b/mcs/class/Microsoft.Build/Makefile +@@ -26,7 +26,7 @@ EXTRA_DISTFILES = \ + EXPR_PARSER = Microsoft.Build.Internal/ExpressionParser + + $(EXPR_PARSER).cs: $(EXPR_PARSER).jay $(topdir)/jay/skeleton.cs +- (cd Microsoft.Build.Internal; $(topdir)/../jay/jay -ctv < $(topdir)/../jay/skeleton.cs ExpressionParser.jay > ExpressionParser.cs) ++ (cd Microsoft.Build.Internal; $(topdir)/../jay/jay -ctv -o ExpressionParser.cs ExpressionParser.jay < $(topdir)/../jay/skeleton.cs ) + + BUILT_SOURCES = $(EXPR_PARSER).cs + +diff --git a/mcs/class/Mono.CSharp/Makefile b/mcs/class/Mono.CSharp/Makefile +index 7b1986b78e5..3615532853d 100644 +--- a/mcs/class/Mono.CSharp/Makefile ++++ b/mcs/class/Mono.CSharp/Makefile +@@ -24,7 +24,7 @@ LIB_MCS_FLAGS += $(REFERENCE_SOURCES_FLAGS) + BUILT_SOURCES = $(PROFILE)-parser.cs + + $(PROFILE)-parser.cs: $(topdir)/mcs/cs-parser.jay $(topdir)/jay/skeleton.cs +- $(topdir)/jay/jay -c < $(topdir)/jay/skeleton.cs $< > $(PROFILE)-jay-tmp.out && mv $(PROFILE)-jay-tmp.out $@ ++ $(topdir)/jay/jay -c -o $(PROFILE)-jay-tmp.out $< < $(topdir)/jay/skeleton.cs && mv $(PROFILE)-jay-tmp.out $@ + + include ../../build/library.make + +diff --git a/mcs/class/Mono.Xml.Ext/Makefile b/mcs/class/Mono.Xml.Ext/Makefile +index dc49f816fee..16498215a38 100644 +--- a/mcs/class/Mono.Xml.Ext/Makefile ++++ b/mcs/class/Mono.Xml.Ext/Makefile +@@ -29,13 +29,13 @@ Mono.Xml.XPath2/XQueryParser.jay: Mono.Xml.XPath2/ParserBase.jay $(SKELETON) + Mono.Xml.XPath2/XPath2Parser.cs: Mono.Xml.XPath2/XPath2Parser.jay + echo "#define XPATH2_PARSER" > $@ + echo "#if NET_2_0" >> $@ +- $(topdir)/jay/jay -ct < $(SKELETON) $(CURDIR)/$< >>$@ ++ $(topdir)/jay/jay -ct $(CURDIR)/$< < $(SKELETON) >>$@ + echo "#endif" >> $@ + + Mono.Xml.XPath2/XQueryParser.cs: Mono.Xml.XPath2/XQueryParser.jay $(SKELETON) + echo "#define XQUERY_PARSER" > $@ + echo "#if NET_2_0" >> $@ +- $(topdir)/jay/jay -ct < $(SKELETON) $(CURDIR)/$< >>$@ ++ $(topdir)/jay/jay -ct $(CURDIR)/$< < $(SKELETON) >>$@ + echo "#endif" >> $@ + + Mono.Xml.XPath2/XPath2Tokenizer.cs: Mono.Xml.XPath2/TokenizerBase.cs +diff --git a/mcs/class/corlib/System/RuntimeArgumentHandle.cs b/mcs/class/corlib/System/RuntimeArgumentHandle.cs +index 216c4ea3924..c10d3f174d1 100644 +--- a/mcs/class/corlib/System/RuntimeArgumentHandle.cs ++++ b/mcs/class/corlib/System/RuntimeArgumentHandle.cs +@@ -31,13 +31,9 @@ + // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + // + +-using System; +-using System.Runtime.InteropServices; +- + namespace System + { +- [ComVisible (true)] +- public struct RuntimeArgumentHandle ++ public ref struct RuntimeArgumentHandle + { + #pragma warning disable 649 + internal IntPtr args; +diff --git a/mcs/class/referencesource/mscorlib/system/typedreference.cs b/mcs/class/referencesource/mscorlib/system/typedreference.cs +index 80bef5ab852..a30541f4399 100644 +--- a/mcs/class/referencesource/mscorlib/system/typedreference.cs ++++ b/mcs/class/referencesource/mscorlib/system/typedreference.cs +@@ -19,7 +19,11 @@ namespace System { + [CLSCompliant(false)] + [System.Runtime.InteropServices.ComVisible(true)] + [System.Runtime.Versioning.NonVersionable] // This only applies to field layout +- public struct TypedReference ++ public ++#if MONO ++ ref ++#endif ++ struct TypedReference + { + #if MONO + #pragma warning disable 169 +diff --git a/mcs/errors/cs0151-4.cs b/mcs/errors/cs0151-4.cs +index 0e45b1a9049..c9e05589e4d 100644 +--- a/mcs/errors/cs0151-4.cs ++++ b/mcs/errors/cs0151-4.cs +@@ -1,5 +1,6 @@ + // CS0151: A switch expression of type `S1?' cannot be converted to an integral type, bool, char, string, enum or nullable type +-// Line: 24 ++// Line: 25 ++// Compiler options: -langversion:5 + + using System; + +diff --git a/mcs/errors/cs0273-2.cs b/mcs/errors/cs0273-2.cs +new file mode 100644 +index 00000000000..b0bdbef9e75 +--- /dev/null ++++ b/mcs/errors/cs0273-2.cs +@@ -0,0 +1,9 @@ ++// CS0273: The accessibility modifier of the `C.S2.set' accessor must be more restrictive than the modifier of the property or indexer `C.S2' ++// Line: 7 ++// Compiler options: -langversion:7.2 ++ ++ class C ++ { ++ private string S2 { get; private protected set; } ++ } ++ +diff --git a/mcs/errors/cs0280.cs b/mcs/errors/cs0280.cs +new file mode 100644 +index 00000000000..62be8e39585 +--- /dev/null ++++ b/mcs/errors/cs0280.cs +@@ -0,0 +1,22 @@ ++// CS0280: `C.Fixable.GetPinnableReference(int)' has the wrong signature to be used in extensible fixed statement ++// Line: 11 ++// Compiler options: -unsafe -langversion:latest -warnaserror ++ ++using System; ++ ++unsafe class C ++{ ++ public static void Main () ++ { ++ fixed (int* p = new Fixable ()) { ++ } ++ } ++ ++ struct Fixable ++ { ++ public ref int GetPinnableReference (int i = 1) ++ { ++ throw new NotImplementedException (); ++ } ++ } ++} +\ No newline at end of file +diff --git a/mcs/errors/cs0826-9.cs b/mcs/errors/cs0826-9.cs +deleted file mode 100644 +index 4e098969b8c..00000000000 +--- a/mcs/errors/cs0826-9.cs ++++ /dev/null +@@ -1,16 +0,0 @@ +-// CS0826: The type of an implicitly typed array cannot be inferred from the initializer. Try specifying array type explicitly +-// Line: 8 +- +-class C +-{ +- static void Main() +- { +- object o = 1; +- dynamic d = 1; +- +- var a = new[] { +- new { X = o }, +- new { X = d } +- }; +- } +-} +diff --git a/mcs/errors/cs1013-1.cs b/mcs/errors/cs1013-1.cs +new file mode 100644 +index 00000000000..01827df4995 +--- /dev/null ++++ b/mcs/errors/cs1013-1.cs +@@ -0,0 +1,8 @@ ++// CS1013: Invalid number ++// Line : 6 ++ ++class X ++{ ++ static int i = 0b; ++ static void Main () {} ++} +\ No newline at end of file +diff --git a/mcs/errors/cs1013-2.cs b/mcs/errors/cs1013-2.cs +new file mode 100644 +index 00000000000..c868cb2a769 +--- /dev/null ++++ b/mcs/errors/cs1013-2.cs +@@ -0,0 +1,7 @@ ++// CS1013: Invalid number ++// Line : 6 ++ ++class X ++{ ++ static int i = 0x0_; ++} +\ No newline at end of file +diff --git a/mcs/errors/cs1013-3.cs b/mcs/errors/cs1013-3.cs +new file mode 100644 +index 00000000000..3145b1ba596 +--- /dev/null ++++ b/mcs/errors/cs1013-3.cs +@@ -0,0 +1,7 @@ ++// CS1013: Invalid number ++// Line : 6 ++ ++class X ++{ ++ static int i = 1_; ++} +\ No newline at end of file +diff --git a/mcs/errors/cs1013-4.cs b/mcs/errors/cs1013-4.cs +new file mode 100644 +index 00000000000..3a5e744ff4f +--- /dev/null ++++ b/mcs/errors/cs1013-4.cs +@@ -0,0 +1,7 @@ ++// CS1013: Invalid number ++// Line : 6 ++ ++class X ++{ ++ static double i = 1_.2; ++} +\ No newline at end of file +diff --git a/mcs/errors/cs1013-5.cs b/mcs/errors/cs1013-5.cs +new file mode 100644 +index 00000000000..8082743c0b5 +--- /dev/null ++++ b/mcs/errors/cs1013-5.cs +@@ -0,0 +1,7 @@ ++// CS1013: Invalid number ++// Line : 6 ++ ++class X ++{ ++ static int i = 1_e1; ++} +\ No newline at end of file +diff --git a/mcs/errors/cs1013-6.cs b/mcs/errors/cs1013-6.cs +new file mode 100644 +index 00000000000..d2cea2c72dd +--- /dev/null ++++ b/mcs/errors/cs1013-6.cs +@@ -0,0 +1,7 @@ ++// CS1013: Invalid number ++// Line : 6 ++ ++class X ++{ ++ static float i = 1_f; ++} +\ No newline at end of file +diff --git a/mcs/errors/cs1013-7.cs b/mcs/errors/cs1013-7.cs +new file mode 100644 +index 00000000000..8030d6ed095 +--- /dev/null ++++ b/mcs/errors/cs1013-7.cs +@@ -0,0 +1,7 @@ ++// CS1013: Invalid number ++// Line : 6 ++ ++class X ++{ ++ static int i = 0x_1; ++} +\ No newline at end of file +diff --git a/mcs/errors/cs1013-8.cs b/mcs/errors/cs1013-8.cs +new file mode 100644 +index 00000000000..d26c7acacb7 +--- /dev/null ++++ b/mcs/errors/cs1013-8.cs +@@ -0,0 +1,7 @@ ++// CS1013: Invalid number ++// Line : 6 ++ ++class X ++{ ++ static int i = 0b_1; ++} +\ No newline at end of file +diff --git a/mcs/errors/cs1021-4.cs b/mcs/errors/cs1021-4.cs +new file mode 100644 +index 00000000000..75c2ff70360 +--- /dev/null ++++ b/mcs/errors/cs1021-4.cs +@@ -0,0 +1,8 @@ ++// CS1021: Integral constant is too large ++// Line: 6 ++ ++class X { ++ public static void Main() { ++ int h = 0b11111111111111111111111111111111111111111111111111111111111111111; ++ } ++} +diff --git a/mcs/errors/cs1061-18.cs b/mcs/errors/cs1061-18.cs +new file mode 100644 +index 00000000000..3ac82b7f2d3 +--- /dev/null ++++ b/mcs/errors/cs1061-18.cs +@@ -0,0 +1,10 @@ ++// CS1061: Type `int' does not contain a definition for `__0' and no extension method `__0' of type `int' could be found. Are you missing an assembly reference? ++// Line: 8 ++ ++static class C ++{ ++ static void Main () ++ { ++ int c = 0.__0; ++ } ++} +\ No newline at end of file +diff --git a/mcs/errors/cs1525-27.cs b/mcs/errors/cs1525-27.cs +index dc184931667..d4c1f326be2 100644 +--- a/mcs/errors/cs1525-27.cs ++++ b/mcs/errors/cs1525-27.cs +@@ -1,4 +1,4 @@ +-// CS1525: Unexpected symbol `fe', expecting `class', `delegate', `enum', `interface', `partial', or `struct' ++// CS1525: Unexpected symbol `fe', expecting `class', `delegate', `enum', `interface', `partial', `ref', or `struct' + // Line: 6 + + namespace X +diff --git a/mcs/errors/cs1525-43.cs b/mcs/errors/cs1525-43.cs +index d83d4d847fa..26f466a2528 100644 +--- a/mcs/errors/cs1525-43.cs ++++ b/mcs/errors/cs1525-43.cs +@@ -1,4 +1,4 @@ +-// CS1525: Unexpected symbol `)', expecting `(', `[', `out', `params', `ref', `this', or `type' ++// CS1525: Unexpected symbol `)' + // Line: 6 + + class TestClass +diff --git a/mcs/errors/cs1527-2.cs b/mcs/errors/cs1527-2.cs +index d38945f3c89..0256ee2b354 100644 +--- a/mcs/errors/cs1527-2.cs ++++ b/mcs/errors/cs1527-2.cs +@@ -1,4 +1,4 @@ +-// CS1527: Namespace elements cannot be explicitly declared as private, protected or protected internal ++// CS1527: Namespace elements cannot be explicitly declared as private, protected, protected internal, or private protected + // Line: 4 + + protected interface IFoo { +diff --git a/mcs/errors/cs1527-3.cs b/mcs/errors/cs1527-3.cs +index 763c75958ee..469d74cbb99 100644 +--- a/mcs/errors/cs1527-3.cs ++++ b/mcs/errors/cs1527-3.cs +@@ -1,4 +1,4 @@ +-// CS1527: Namespace elements cannot be explicitly declared as private, protected or protected internal ++// CS1527: Namespace elements cannot be explicitly declared as private, protected, protected internal, or private protected + // Line: 4 + + protected internal enum E { +diff --git a/mcs/errors/cs1527.cs b/mcs/errors/cs1527.cs +index 189cc472f4c..e847fd14e11 100644 +--- a/mcs/errors/cs1527.cs ++++ b/mcs/errors/cs1527.cs +@@ -1,4 +1,5 @@ +-// CS1527: Namespace elements cannot be explicitly declared as private, protected or protected internal +-// Line: ++// CS1527: Namespace elements cannot be explicitly declared as private, protected, protected internal, or private protected ++// Line: 4 ++ + private class X { + } +diff --git a/mcs/errors/cs1611-2.cs b/mcs/errors/cs1611-2.cs +new file mode 100644 +index 00000000000..882231378f0 +--- /dev/null ++++ b/mcs/errors/cs1611-2.cs +@@ -0,0 +1,8 @@ ++// CS1611: The params parameter cannot be declared as ref, out or in ++// Line: 6 ++// Compiler options: -langversion:latest ++ ++class Test ++{ ++ public static void Error (params in int args) {} ++} +\ No newline at end of file +diff --git a/mcs/errors/cs1611.cs b/mcs/errors/cs1611.cs +index 8df10fac0ce..469e083ec3c 100644 +--- a/mcs/errors/cs1611.cs ++++ b/mcs/errors/cs1611.cs +@@ -1,4 +1,4 @@ +-// CS1611: The params parameter cannot be declared as ref or out ++// CS1611: The params parameter cannot be declared as ref, out or in + // Line: 6 + + class Test +diff --git a/mcs/errors/cs1644-61.cs b/mcs/errors/cs1644-61.cs +new file mode 100644 +index 00000000000..d58ba64c7ec +--- /dev/null ++++ b/mcs/errors/cs1644-61.cs +@@ -0,0 +1,11 @@ ++// CS1644: Feature `digit separators' cannot be used because it is not part of the C# 6.0 language specification ++// Line: 9 ++// Compiler options: -langversion:6 ++ ++class X ++{ ++ int Test () ++ { ++ var i = 1_0; ++ } ++} +diff --git a/mcs/errors/cs1644-62.cs b/mcs/errors/cs1644-62.cs +new file mode 100644 +index 00000000000..5a29839610d +--- /dev/null ++++ b/mcs/errors/cs1644-62.cs +@@ -0,0 +1,10 @@ ++// CS1644: Feature `private protected' cannot be used because it is not part of the C# 6.0 language specification ++// Line: 7 ++// Compiler options: -langversion:6 ++ ++class C ++{ ++ private protected enum E ++ { ++ } ++} +\ No newline at end of file +diff --git a/mcs/errors/cs1644-63.cs b/mcs/errors/cs1644-63.cs +new file mode 100644 +index 00000000000..ce61d5ce046 +--- /dev/null ++++ b/mcs/errors/cs1644-63.cs +@@ -0,0 +1,22 @@ ++// CS1644: Feature `extensible fixed statement' cannot be used because it is not part of the C# 7.2 language specification ++// Line: 11 ++// Compiler options: -unsafe -langversion:7.2 ++ ++using System; ++ ++unsafe class C ++{ ++ public static void Main () ++ { ++ fixed (int* p = new Fixable ()) { ++ } ++ } ++ ++ struct Fixable ++ { ++ public ref int GetPinnableReference () ++ { ++ throw new NotImplementedException (); ++ } ++ } ++} +\ No newline at end of file +diff --git a/mcs/errors/cs1644-64.cs b/mcs/errors/cs1644-64.cs +new file mode 100644 +index 00000000000..88917a0a5d5 +--- /dev/null ++++ b/mcs/errors/cs1644-64.cs +@@ -0,0 +1,13 @@ ++// CS1644: Feature `expression body property accessor' cannot be used because it is not part of the C# 6.0 language specification ++// Line: 11 ++// Compiler options: -langversion:6 ++ ++using System; ++ ++class C ++{ ++ public int Integer ++ { ++ get => 0; ++ } ++} +\ No newline at end of file +diff --git a/mcs/errors/cs1644-65.cs b/mcs/errors/cs1644-65.cs +new file mode 100644 +index 00000000000..dea648b7846 +--- /dev/null ++++ b/mcs/errors/cs1644-65.cs +@@ -0,0 +1,13 @@ ++// CS1644: Feature `expression body property accessor' cannot be used because it is not part of the C# 6.0 language specification ++// Line: 11 ++// Compiler options: -langversion:6 ++ ++using System; ++ ++class C ++{ ++ public int this[int i] ++ { ++ get => i; ++ } ++} +\ No newline at end of file +diff --git a/mcs/errors/cs1644-66.cs b/mcs/errors/cs1644-66.cs +new file mode 100644 +index 00000000000..3f393b50d30 +--- /dev/null ++++ b/mcs/errors/cs1644-66.cs +@@ -0,0 +1,17 @@ ++// CS1644: Feature `expression body event accessor' cannot be used because it is not part of the C# 6.0 language specification ++// Line: 11 ++// Compiler options: -langversion:6 ++ ++using System; ++ ++class C ++{ ++ public event EventHandler Event ++ { ++ add => Ignore (); ++ } ++ ++ static void Ignore () ++ { ++ } ++} +\ No newline at end of file +diff --git a/mcs/errors/cs1763-2.cs b/mcs/errors/cs1763-2.cs +index 72f5370949a..7e4d091fc72 100644 +--- a/mcs/errors/cs1763-2.cs ++++ b/mcs/errors/cs1763-2.cs +@@ -1,4 +1,4 @@ +-// CS1763: Optional parameter `o' of type `object' can only be initialized with `null' ++// CS1763: Optional parameter `o' of type `object' can only be initialized with default value + // Line: 6 + + class C +diff --git a/mcs/errors/cs1763.cs b/mcs/errors/cs1763.cs +index d10a7bf2c20..03b5f28a19d 100644 +--- a/mcs/errors/cs1763.cs ++++ b/mcs/errors/cs1763.cs +@@ -1,4 +1,4 @@ +-// CS1763: Optional parameter `o' of type `object' can only be initialized with `null' ++// CS1763: Optional parameter `o' of type `object' can only be initialized with default value + // Line: 6 + + class C +diff --git a/mcs/errors/cs8326.cs b/mcs/errors/cs8326.cs +new file mode 100644 +index 00000000000..efd3a84fea7 +--- /dev/null ++++ b/mcs/errors/cs8326.cs +@@ -0,0 +1,13 @@ ++// CS8326: Both ref conditional operators must be ref values ++// Line: 11 ++ ++class Program ++{ ++ static int x, y; ++ ++ public static void Main () ++ { ++ bool b = false; ++ ref int targetBucket = ref b ? x : y; ++ } ++} +\ No newline at end of file +diff --git a/mcs/errors/cs8327.cs b/mcs/errors/cs8327.cs +new file mode 100644 +index 00000000000..8d0ccd86a70 +--- /dev/null ++++ b/mcs/errors/cs8327.cs +@@ -0,0 +1,14 @@ ++// CS8327: The ref conditional expression types `int' and `byte' have to match ++// Line: 12 ++ ++class Program ++{ ++ static int x; ++ static byte y; ++ ++ public static void Main () ++ { ++ bool b = false; ++ ref int targetBucket = ref b ? ref x : ref y; ++ } ++} +\ No newline at end of file +diff --git a/mcs/errors/cs0428-2.cs b/mcs/errors/cs8385-2.cs +similarity index 50% +rename from mcs/errors/cs0428-2.cs +rename to mcs/errors/cs8385-2.cs +index 5f468fd519a..cc7860faa62 100644 +--- a/mcs/errors/cs0428-2.cs ++++ b/mcs/errors/cs8385-2.cs +@@ -1,4 +1,4 @@ +-// CS0428: Cannot convert method group `Main' to non-delegate type `void*'. Consider using parentheses to invoke the method ++// CS8385: The given expression cannot be used in a fixed statement + // Line: 9 + // Compiler options: -unsafe + +diff --git a/mcs/errors/cs0213-2.cs b/mcs/errors/cs8385.cs +similarity index 54% +rename from mcs/errors/cs0213-2.cs +rename to mcs/errors/cs8385.cs +index ae72e4cd9aa..5fa9f794ccf 100644 +--- a/mcs/errors/cs0213-2.cs ++++ b/mcs/errors/cs8385.cs +@@ -1,4 +1,4 @@ +-// CS0213: You cannot use the fixed statement to take the address of an already fixed expression ++// CS8385: The given expression cannot be used in a fixed statement + // Line: 9 + // Compiler options: -unsafe + +diff --git a/mcs/errors/known-issues-net_4_x b/mcs/errors/known-issues-net_4_x +index c9ed9317350..54902e03e7b 100644 +--- a/mcs/errors/known-issues-net_4_x ++++ b/mcs/errors/known-issues-net_4_x +@@ -14,6 +14,9 @@ + # Parser problems + cs0080.cs + ++# Undocumented switch governing rules ++cs0151-4.cs NO ERROR ++ + # Operators + cs0457-2.cs + cs0457.cs +diff --git a/mcs/ilasm/Makefile b/mcs/ilasm/Makefile +index 090d1cc3231..4ca11545781 100644 +--- a/mcs/ilasm/Makefile ++++ b/mcs/ilasm/Makefile +@@ -13,7 +13,7 @@ EXTRA_DISTFILES = \ + $(wildcard tests/*.il) + + ILParser.cs: parser/ILParser.jay $(topdir)/jay/skeleton.cs +- $(topdir)/jay/jay -ct < $(topdir)/jay/skeleton.cs $(CURDIR)/$< >$@ ++ $(topdir)/jay/jay -ct -o $@ $(CURDIR)/$< < $(topdir)/jay/skeleton.cs + + include ../build/executable.make + +diff --git a/mcs/jay/defs.h b/mcs/jay/defs.h +index 2aade48dac2..3bd3c5859ce 100644 +--- a/mcs/jay/defs.h ++++ b/mcs/jay/defs.h +@@ -236,12 +236,14 @@ extern char *input_file_name; + extern char *prolog_file_name; + extern char *local_file_name; + extern char *verbose_file_name; ++extern char *output_file_name; + + extern FILE *action_file; + extern FILE *input_file; + extern FILE *prolog_file; + extern FILE *local_file; + extern FILE *verbose_file; ++extern FILE *output_file; + + extern int nitems; + extern int nrules; +diff --git a/mcs/jay/main.c b/mcs/jay/main.c +index fcac218b1df..7fb5e6c8ccb 100644 +--- a/mcs/jay/main.c ++++ b/mcs/jay/main.c +@@ -63,6 +63,7 @@ char *input_file_name = ""; + char *prolog_file_name; + char *local_file_name; + char *verbose_file_name; ++char *output_file_name = 0; + + FILE *action_file; /* a temp file, used to save actions associated */ + /* with rules until the parser is written */ +@@ -70,6 +71,7 @@ FILE *input_file; /* the input file */ + FILE *prolog_file; /* temp files, used to save text until all */ + FILE *local_file; /* symbols have been defined */ + FILE *verbose_file; /* y.output */ ++FILE *output_file; /* defaults to stdout */ + + int nitems; + int nrules; +@@ -106,6 +108,7 @@ int k; + if (action_file) { fclose(action_file); unlink(action_file_name); } + if (prolog_file) { fclose(prolog_file); unlink(prolog_file_name); } + if (local_file) { fclose(local_file); unlink(local_file_name); } ++ if (output_file && (output_file != stdout)) { fclose(output_file); if (k != 0) unlink(output_file_name); } + exit(k); + } + +@@ -137,7 +140,7 @@ set_signals() + + usage() + { +- fprintf(stderr, "usage: %s [-tvcp] [-b file_prefix] filename\n", myname); ++ fprintf(stderr, "usage: %s [-tvcp] [-b file_prefix] [-o output_filename] input_filename\n", myname); + exit(1); + } + +@@ -167,9 +170,9 @@ char *argv[]; + if (i + 1 < argc) usage(); + return; + +- case '-': +- ++i; +- goto no_more_options; ++ case '-': ++ ++i; ++ goto no_more_options; + + case 'b': + if (*++s) +@@ -180,13 +183,22 @@ char *argv[]; + usage(); + continue; + +- case 't': +- tflag = 1; +- break; ++ case 'o': ++ if (*++s) ++ output_file_name = s; ++ else if (++i < argc) ++ output_file_name = argv[i]; ++ else ++ usage(); ++ continue; ++ ++ case 't': ++ tflag = 1; ++ break; + + case 'p': +- print_skel_dir (); +- break; ++ print_skel_dir (); ++ break; + + case 'c': + csharp = 1; +@@ -217,12 +229,12 @@ char *argv[]; + vflag = 1; + break; + +- case 'p': +- print_skel_dir (); +- break; ++ case 'p': ++ print_skel_dir (); ++ break; + +- case 'c': +- csharp = 1; ++ case 'c': ++ csharp = 1; + line_format = "#line %d \"%s\"\n"; + default_line_format = "#line default\n"; + +@@ -355,6 +367,17 @@ open_files() + if (verbose_file == 0) + open_error(verbose_file_name); + } ++ ++ if (output_file == 0) ++ { ++ if (output_file_name != 0) { ++ output_file = fopen(output_file_name, "w"); ++ if (output_file == 0) ++ open_error(output_file_name); ++ } else { ++ output_file = stdout; ++ } ++ } + } + + +diff --git a/mcs/jay/output.c b/mcs/jay/output.c +index d1e2c14a1b2..ab9b2043be9 100644 +--- a/mcs/jay/output.c ++++ b/mcs/jay/output.c +@@ -73,7 +73,7 @@ output () { + fprintf(stderr, "jay: line %d is too long\n", lno), done(1); + switch (buf[0]) { + case '#': continue; +- case 't': if (!tflag) fputs("//t", stdout); ++ case 't': if (!tflag) fputs("//t", output_file); + case '.': break; + default: + cp = strtok(buf, " \t\r\n"); +@@ -93,7 +93,7 @@ output () { + fprintf(stderr, "jay: unknown call (%s) in line %d\n", cp, lno); + continue; + } +- fputs(buf+1, stdout), ++ outline; ++ fputs(buf+1, output_file), ++ outline; + } + free_parser(); + } +@@ -103,19 +103,19 @@ output_rule_data() + register int i; + register int j; + +- printf("/*\n All more than 3 lines long rules are wrapped into a method\n*/\n"); ++ fprintf(output_file, "/*\n All more than 3 lines long rules are wrapped into a method\n*/\n"); + + for (i = 0; i < nmethods; ++i) + { +- printf("%s", methods[i]); ++ fprintf(output_file, "%s", methods[i]); + FREE(methods[i]); +- printf("\n\n"); ++ fprintf(output_file, "\n\n"); + } + FREE(methods); + +- printf(default_line_format, ++outline + 1); ++ fprintf(output_file, default_line_format, ++outline + 1); + +- printf(" %s static %s short [] yyLhs = {%16d,", ++ fprintf(output_file, " %s static %s short [] yyLhs = {%16d,", + csharp ? "" : " protected", + csharp ? "readonly" : "final", + symbol_value[start_symbol]); +@@ -126,18 +126,18 @@ output_rule_data() + if (j >= 10) + { + ++outline; +- putchar('\n'); ++ putc('\n', output_file); + j = 1; + } + else + ++j; + +- printf("%5d,", symbol_value[rlhs[i]]); ++ fprintf(output_file, "%5d,", symbol_value[rlhs[i]]); + } + outline += 2; +- printf("\n };\n"); ++ fprintf(output_file, "\n };\n"); + +- printf(" %s static %s short [] yyLen = {%12d,", ++ fprintf(output_file, " %s static %s short [] yyLen = {%12d,", + csharp ? "" : "protected", + csharp ? "readonly" : "final", + 2); +@@ -148,16 +148,16 @@ output_rule_data() + if (j >= 10) + { + ++outline; +- putchar('\n'); ++ putc('\n', output_file); + j = 1; + } + else + j++; + +- printf("%5d,", rrhs[i + 1] - rrhs[i] - 1); ++ fprintf(output_file, "%5d,", rrhs[i + 1] - rrhs[i] - 1); + } + outline += 2; +- printf("\n };\n"); ++ fprintf(output_file, "\n };\n"); + } + + +@@ -165,7 +165,7 @@ output_yydefred() + { + register int i, j; + +- printf(" %s static %s short [] yyDefRed = {%13d,", ++ fprintf(output_file, " %s static %s short [] yyDefRed = {%13d,", + csharp ? "" : "protected", + csharp ? "readonly" : "final", + (defred[0] ? defred[0] - 2 : 0)); +@@ -178,15 +178,15 @@ output_yydefred() + else + { + ++outline; +- putchar('\n'); ++ putc('\n', output_file); + j = 1; + } + +- printf("%5d,", (defred[i] ? defred[i] - 2 : 0)); ++ fprintf(output_file, "%5d,", (defred[i] ? defred[i] - 2 : 0)); + } + + outline += 2; +- printf("\n };\n"); ++ fprintf(output_file, "\n };\n"); + } + + +@@ -309,7 +309,7 @@ goto_actions() + state_count = NEW2(nstates, short); + + k = default_goto(start_symbol + 1); +- printf(" protected static %s short [] yyDgoto = {%14d,", csharp ? "readonly" : "final", k); ++ fprintf(output_file, " protected static %s short [] yyDgoto = {%14d,", csharp ? "readonly" : "final", k); + save_column(start_symbol + 1, k); + + j = 10; +@@ -318,19 +318,19 @@ goto_actions() + if (j >= 10) + { + ++outline; +- putchar('\n'); ++ putc('\n', output_file); + j = 1; + } + else + ++j; + + k = default_goto(i); +- printf("%5d,", k); ++ fprintf(output_file, "%5d,", k); + save_column(i, k); + } + + outline += 2; +- printf("\n };\n"); ++ fprintf(output_file, "\n };\n"); + FREE(state_count); + } + +@@ -633,7 +633,7 @@ output_base() + { + register int i, j; + +- printf(" protected static %s short [] yySindex = {%13d,", csharp? "readonly":"final", base[0]); ++ fprintf(output_file, " protected static %s short [] yySindex = {%13d,", csharp? "readonly":"final", base[0]); + + j = 10; + for (i = 1; i < nstates; i++) +@@ -641,17 +641,17 @@ output_base() + if (j >= 10) + { + ++outline; +- putchar('\n'); ++ putc('\n', output_file); + j = 1; + } + else + ++j; + +- printf("%5d,", base[i]); ++ fprintf(output_file, "%5d,", base[i]); + } + + outline += 2; +- printf("\n };\n protected static %s short [] yyRindex = {%13d,", ++ fprintf(output_file, "\n };\n protected static %s short [] yyRindex = {%13d,", + csharp ? "readonly" : "final", + base[nstates]); + +@@ -661,17 +661,17 @@ output_base() + if (j >= 10) + { + ++outline; +- putchar('\n'); ++ putc('\n', output_file); + j = 1; + } + else + ++j; + +- printf("%5d,", base[i]); ++ fprintf(output_file, "%5d,", base[i]); + } + + outline += 2; +- printf("\n };\n protected static %s short [] yyGindex = {%13d,", ++ fprintf(output_file, "\n };\n protected static %s short [] yyGindex = {%13d,", + csharp ? "readonly" : "final", + base[2*nstates]); + +@@ -681,17 +681,17 @@ output_base() + if (j >= 10) + { + ++outline; +- putchar('\n'); ++ putc('\n', output_file); + j = 1; + } + else + ++j; + +- printf("%5d,", base[i]); ++ fprintf(output_file, "%5d,", base[i]); + } + + outline += 2; +- printf("\n };\n"); ++ fprintf(output_file, "\n };\n"); + FREE(base); + } + +@@ -702,7 +702,7 @@ output_table() + register int i; + register int j; + +- printf(" protected static %s short [] yyTable = {%14d,", csharp ? "readonly" : "final", table[0]); ++ fprintf(output_file, " protected static %s short [] yyTable = {%14d,", csharp ? "readonly" : "final", table[0]); + + j = 10; + for (i = 1; i <= high; i++) +@@ -710,17 +710,17 @@ output_table() + if (j >= 10) + { + ++outline; +- putchar('\n'); ++ putc('\n', output_file); + j = 1; + } + else + ++j; + +- printf("%5d,", table[i]); ++ fprintf(output_file, "%5d,", table[i]); + } + + outline += 2; +- printf("\n };\n"); ++ fprintf(output_file, "\n };\n"); + FREE(table); + } + +@@ -731,7 +731,7 @@ output_check() + register int i; + register int j; + +- printf(" protected static %s short [] yyCheck = {%14d,", ++ fprintf(output_file, " protected static %s short [] yyCheck = {%14d,", + csharp ? "readonly" : "final", + check[0]); + +@@ -741,17 +741,17 @@ output_check() + if (j >= 10) + { + ++outline; +- putchar('\n'); ++ putc('\n', output_file); + j = 1; + } + else + ++j; + +- printf("%5d,", check[i]); ++ fprintf(output_file, "%5d,", check[i]); + } + + outline += 2; +- printf("\n };\n"); ++ fprintf(output_file, "\n };\n"); + FREE(check); + } + +@@ -801,30 +801,30 @@ char *prefix; + if (is_C_identifier(s)) + { + if (prefix) +- printf(" %s ", prefix); ++ fprintf(output_file, " %s ", prefix); + c = *s; + if (c == '"') + { + while ((c = *++s) != '"') + { +- putchar(c); ++ putc(c, output_file); + } + } + else + { + do + { +- putchar(c); ++ putc(c, output_file); + } + while (c = *++s); + } + ++outline; +- printf(" = %d%s\n", symbol_value[i], csharp ? ";" : ";"); ++ fprintf(output_file, " = %d%s\n", symbol_value[i], csharp ? ";" : ";"); + } + } + + ++outline; +- printf(" %s yyErrorCode = %d%s\n", prefix ? prefix : "", symbol_value[1], csharp ? ";" : ";"); ++ fprintf(output_file, " %s yyErrorCode = %d%s\n", prefix ? prefix : "", symbol_value[1], csharp ? ";" : ";"); + } + + +@@ -842,14 +842,14 @@ char *name; + if ((c = getc(in)) != EOF) { + if (c == '\n') + ++outline; +- putchar(c); ++ putc(c, output_file); + while ((c = getc(in)) != EOF) + { + if (c == '\n') + ++outline; +- putchar(c); ++ putc(c, output_file); + } +- printf(default_line_format, ++outline + 1); ++ fprintf(output_file, default_line_format, ++outline + 1); + } + fclose(in); + } +@@ -862,67 +862,67 @@ output_debug() + char * prefix = tflag ? "" : "//t"; + + ++outline; +- printf(" protected %s int yyFinal = %d;\n", csharp ? "const" : "static final", final_state); ++ fprintf(output_file, " protected %s int yyFinal = %d;\n", csharp ? "const" : "static final", final_state); + + ++outline; +- printf ("%s // Put this array into a separate class so it is only initialized if debugging is actually used\n", prefix); +- printf ("%s // Use MarshalByRefObject to disable inlining\n", prefix); +- printf("%s class YYRules %s {\n", prefix, csharp ? ": MarshalByRefObject" : ""); +- printf("%s public static %s string [] yyRule = {\n", prefix, csharp ? "readonly" : "final"); ++ fprintf(output_file, "%s // Put this array into a separate class so it is only initialized if debugging is actually used\n", prefix); ++ fprintf(output_file, "%s // Use MarshalByRefObject to disable inlining\n", prefix); ++ fprintf(output_file, "%s class YYRules %s {\n", prefix, csharp ? ": MarshalByRefObject" : ""); ++ fprintf(output_file, "%s public static %s string [] yyRule = {\n", prefix, csharp ? "readonly" : "final"); + for (i = 2; i < nrules; ++i) + { +- printf("%s \"%s :", prefix, symbol_name[rlhs[i]]); ++ fprintf(output_file, "%s \"%s :", prefix, symbol_name[rlhs[i]]); + for (j = rrhs[i]; ritem[j] > 0; ++j) + { + s = symbol_name[ritem[j]]; + if (s[0] == '"') + { +- printf(" \\\""); ++ fprintf(output_file, " \\\""); + while (*++s != '"') + { + if (*s == '\\') + { + if (s[1] == '\\') +- printf("\\\\\\\\"); ++ fprintf(output_file, "\\\\\\\\"); + else +- printf("\\\\%c", s[1]); ++ fprintf(output_file, "\\\\%c", s[1]); + ++s; + } + else +- putchar(*s); ++ putc(*s, output_file); + } +- printf("\\\""); ++ fprintf(output_file, "\\\""); + } + else if (s[0] == '\'') + { + if (s[1] == '"') +- printf(" '\\\"'"); ++ fprintf(output_file, " '\\\"'"); + else if (s[1] == '\\') + { + if (s[2] == '\\') +- printf(" '\\\\\\\\"); ++ fprintf(output_file, " '\\\\\\\\"); + else +- printf(" '\\\\%c", s[2]); ++ fprintf(output_file, " '\\\\%c", s[2]); + s += 2; + while (*++s != '\'') +- putchar(*s); +- putchar('\''); ++ putc(*s, output_file); ++ putc('\'', output_file); + } + else +- printf(" '%c'", s[1]); ++ fprintf(output_file, " '%c'", s[1]); + } + else +- printf(" %s", s); ++ fprintf(output_file, " %s", s); + } + ++outline; +- printf("\",\n"); ++ fprintf(output_file, "\",\n"); + } + ++ outline; +- printf("%s };\n", prefix); +- printf ("%s public static string getRule (int index) {\n", prefix); +- printf ("%s return yyRule [index];\n", prefix); +- printf ("%s }\n", prefix); +- printf ("%s}\n", prefix); ++ fprintf(output_file, "%s };\n", prefix); ++ fprintf(output_file, "%s public static string getRule (int index) {\n", prefix); ++ fprintf(output_file, "%s return yyRule [index];\n", prefix); ++ fprintf(output_file, "%s }\n", prefix); ++ fprintf(output_file, "%s}\n", prefix); + + max = 0; + for (i = 2; i < ntokens; ++i) +@@ -931,7 +931,7 @@ output_debug() + + /* need yyNames for yyExpecting() */ + +- printf(" protected static %s string [] yyNames = {", csharp ? "readonly" : "final"); ++ fprintf(output_file, " protected static %s string [] yyNames = {", csharp ? "readonly" : "final"); + symnam = (char **) MALLOC((max+1)*sizeof(char *)); + if (symnam == 0) no_space(); + +@@ -943,7 +943,7 @@ output_debug() + symnam[symbol_value[i]] = symbol_name[i]; + symnam[0] = "end-of-file"; + +- j = 70; fputs(" ", stdout); ++ j = 70; fputs(" ", output_file); + for (i = 0; i <= max; ++i) + { + if (s = symnam[i]) +@@ -965,25 +965,25 @@ output_debug() + if (j > 70) + { + ++outline; +- printf("\n "); ++ fprintf(output_file, "\n "); + j = k; + } +- printf("\"\\\""); ++ fprintf(output_file, "\"\\\""); + s = symnam[i]; + while (*++s != '"') + { + if (*s == '\\') + { +- printf("\\\\"); ++ fprintf(output_file, "\\\\"); + if (*++s == '\\') +- printf("\\\\"); ++ fprintf(output_file, "\\\\"); + else +- putchar(*s); ++ putc(*s, output_file); + } + else +- putchar(*s); ++ putc(*s, output_file); + } +- printf("\\\"\","); ++ fprintf(output_file, "\\\"\","); + } + else if (s[0] == '\'') + { +@@ -993,10 +993,10 @@ output_debug() + if (j > 70) + { + ++outline; +- printf("\n "); ++ fprintf(output_file, "\n "); + j = 7; + } +- printf("\"'\\\"'\","); ++ fprintf(output_file, "\"'\\\"'\","); + } + else + { +@@ -1015,25 +1015,25 @@ output_debug() + if (j > 70) + { + ++outline; +- printf("\n "); ++ fprintf(output_file, "\n "); + j = k; + } +- printf("\"'"); ++ fprintf(output_file, "\"'"); + s = symnam[i]; + while (*++s != '\'') + { + if (*s == '\\') + { +- printf("\\\\"); ++ fprintf(output_file, "\\\\"); + if (*++s == '\\') +- printf("\\\\"); ++ fprintf(output_file, "\\\\"); + else +- putchar(*s); ++ putc(*s, output_file); + } + else +- putchar(*s); ++ putc(*s, output_file); + } +- printf("'\","); ++ fprintf(output_file, "'\","); + } + } + else +@@ -1043,12 +1043,12 @@ output_debug() + if (j > 70) + { + ++outline; +- printf("\n "); ++ fprintf(output_file, "\n "); + j = k; + } +- putchar('"'); +- do { putchar(*s); } while (*++s); +- printf("\","); ++ putc('"', output_file); ++ do { putc(*s, output_file); } while (*++s); ++ fprintf(output_file, "\","); + } + } + else +@@ -1057,14 +1057,14 @@ output_debug() + if (j > 70) + { + ++outline; +- printf("\n "); ++ fprintf(output_file, "\n "); + j = 5; + } +- printf("null,"); ++ fprintf(output_file, "null,"); + } + } + outline += 2; +- printf("\n };\n"); ++ fprintf(output_file, "\n };\n"); + FREE(symnam); + } + +@@ -1084,19 +1084,19 @@ output_trailing_text() + if ((c = getc(in)) == EOF) + return; + ++outline; +- printf(line_format, lineno, input_file_name); ++ fprintf(output_file, line_format, lineno, input_file_name); + if (c == '\n') + ++outline; +- putchar(c); ++ putc(c, output_file); + last = c; + } + else + { + ++outline; +- printf(line_format, lineno, input_file_name); +- do { putchar(c); } while ((c = *++cptr) != '\n'); ++ fprintf(output_file, line_format, lineno, input_file_name); ++ do { putc(c, output_file); } while ((c = *++cptr) != '\n'); + ++outline; +- putchar('\n'); ++ putc('\n', output_file); + last = '\n'; + } + +@@ -1104,16 +1104,16 @@ output_trailing_text() + { + if (c == '\n') + ++outline; +- putchar(c); ++ putc(c, output_file); + last = c; + } + + if (last != '\n') + { + ++outline; +- putchar('\n'); ++ putc('\n', output_file); + } +- printf(default_line_format, ++outline + 1); ++ fprintf(output_file, default_line_format, ++outline + 1); + } + + +@@ -1132,22 +1132,22 @@ output_semantic_actions() + last = c; + if (c == '\n') + ++outline; +- putchar(c); ++ putc(c, output_file); + while ((c = getc(action_file)) != EOF) + { + if (c == '\n') + ++outline; +- putchar(c); ++ putc(c, output_file); + last = c; + } + + if (last != '\n') + { + ++outline; +- putchar('\n'); ++ putc('\n', output_file); + } + +- printf(default_line_format, ++outline + 1); ++ fprintf(output_file, default_line_format, ++outline + 1); + } + + +diff --git a/mcs/mcs/Makefile b/mcs/mcs/Makefile +index dbd71a3d581..dbf040afdd6 100644 +--- a/mcs/mcs/Makefile ++++ b/mcs/mcs/Makefile +@@ -32,7 +32,7 @@ BUILT_SOURCES = cs-parser.cs + CLEAN_FILES += y.output + + %-parser.cs: %-parser.jay $(topdir)/jay/skeleton.cs +- $(topdir)/jay/jay $(JAY_FLAGS) < $(topdir)/jay/skeleton.cs $< > jay-tmp.out && mv jay-tmp.out $@ ++ $(topdir)/jay/jay $(JAY_FLAGS) -o jay-tmp.out $< < $(topdir)/jay/skeleton.cs && mv jay-tmp.out $@ + + KEEP_OUTPUT_FILE_COPY = yes + +diff --git a/mcs/mcs/argument.cs b/mcs/mcs/argument.cs +index 5b1003dbadf..4c75e41a9e5 100644 +--- a/mcs/mcs/argument.cs ++++ b/mcs/mcs/argument.cs +@@ -38,6 +38,8 @@ namespace Mono.CSharp + // Conditional instance expression inserted as the first argument + ExtensionTypeConditionalAccess = 5 | ConditionalAccessFlag, + ++ Readonly = 6, ++ + ConditionalAccessFlag = 1 << 7 + } + +diff --git a/mcs/mcs/assembly.cs b/mcs/mcs/assembly.cs +index aa4c54317a2..96e43e70d99 100644 +--- a/mcs/mcs/assembly.cs ++++ b/mcs/mcs/assembly.cs +@@ -554,7 +554,8 @@ namespace Mono.CSharp + if (prop != null) { + AttributeEncoder encoder = new AttributeEncoder (); + encoder.EncodeNamedPropertyArgument (prop, new BoolLiteral (Compiler.BuiltinTypes, true, Location.Null)); +- SetCustomAttribute (pa.Constructor, encoder.ToArray ()); ++ SetCustomAttribute (pa.Constructor, encoder.ToArray (out var references)); ++ module.AddAssemblyReferences (references); + } + } + } +diff --git a/mcs/mcs/attribute.cs b/mcs/mcs/attribute.cs +index 83d403118ad..faf2cfaa1d8 100644 +--- a/mcs/mcs/attribute.cs ++++ b/mcs/mcs/attribute.cs +@@ -1064,8 +1064,10 @@ namespace Mono.CSharp { + } + + byte[] cdata; ++ List references; + if (pos_args == null && named_values == null) { + cdata = AttributeEncoder.Empty; ++ references = null; + } else { + AttributeEncoder encoder = new AttributeEncoder (); + +@@ -1138,7 +1140,7 @@ namespace Mono.CSharp { + encoder.EncodeEmptyNamedArguments (); + } + +- cdata = encoder.ToArray (); ++ cdata = encoder.ToArray (out references); + } + + if (!IsConditionallyExcluded (ctor.DeclaringType)) { +@@ -1157,6 +1159,8 @@ namespace Mono.CSharp { + Error_AttributeEmitError (e.Message); + return; + } ++ ++ context.Module.AddAssemblyReferences (references); + } + + if (!usage_attr.AllowMultiple && allEmitted != null) { +@@ -1415,6 +1419,7 @@ namespace Mono.CSharp { + byte[] buffer; + int pos; + const ushort Version = 1; ++ List imports; + + static AttributeEncoder () + { +@@ -1594,7 +1599,15 @@ namespace Mono.CSharp { + public void EncodeTypeName (TypeSpec type) + { + var old_type = type.GetMetaInfo (); +- Encode (type.MemberDefinition.IsImported ? old_type.AssemblyQualifiedName : old_type.FullName); ++ if (type.MemberDefinition.IsImported) { ++ if (imports == null) ++ imports = new List (); ++ ++ imports.Add (old_type.Assembly); ++ Encode (old_type.AssemblyQualifiedName); ++ } else { ++ Encode (old_type.FullName); ++ } + } + + public void EncodeTypeName (TypeContainer type) +@@ -1675,8 +1688,10 @@ namespace Mono.CSharp { + Encode (value); + } + +- public byte[] ToArray () ++ public byte[] ToArray (out List assemblyReferences) + { ++ assemblyReferences = imports; ++ + byte[] buf = new byte[pos]; + Array.Copy (buffer, buf, pos); + return buf; +@@ -1990,7 +2005,8 @@ namespace Mono.CSharp { + encoder.Encode ((int) state); + encoder.EncodeEmptyNamedArguments (); + +- builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ()); ++ builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray (out var references)); ++ module.AddAssemblyReferences (references); + } + } + +@@ -2024,7 +2040,8 @@ namespace Mono.CSharp { + encoder.Encode ((int) modes); + encoder.EncodeEmptyNamedArguments (); + +- builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ()); ++ builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray (out var references)); ++ module.AddAssemblyReferences (references); + } + } + +@@ -2050,7 +2067,8 @@ namespace Mono.CSharp { + encoder.Encode ((uint) bits[0]); + encoder.EncodeEmptyNamedArguments (); + +- builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ()); ++ builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray (out var references)); ++ module.AddAssemblyReferences (references); + } + + public void EmitAttribute (FieldBuilder builder, decimal value, Location loc) +@@ -2068,7 +2086,8 @@ namespace Mono.CSharp { + encoder.Encode ((uint) bits[0]); + encoder.EncodeEmptyNamedArguments (); + +- builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ()); ++ builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray (out var references)); ++ module.AddAssemblyReferences (references); + } + } + +@@ -2092,7 +2111,8 @@ namespace Mono.CSharp { + encoder.EncodeTypeName (type); + encoder.EncodeEmptyNamedArguments (); + +- builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ()); ++ builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray (out var references)); ++ module.AddAssemblyReferences (references); + } + } + +diff --git a/mcs/mcs/class.cs b/mcs/mcs/class.cs +index 6b1adc297a3..dc61f6dc627 100644 +--- a/mcs/mcs/class.cs ++++ b/mcs/mcs/class.cs +@@ -2117,7 +2117,8 @@ namespace Mono.CSharp + encoder.Encode (GetAttributeDefaultMember ()); + encoder.EncodeEmptyNamedArguments (); + +- TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ()); ++ TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray (out var references)); ++ Module.AddAssemblyReferences (references); + } + + public override void VerifyMembers () +@@ -3962,7 +3963,10 @@ namespace Mono.CSharp + Report.Error (4013, Location, + "Local variables of type `{0}' cannot be used inside anonymous methods, lambda expressions or query expressions", + MemberType.GetSignatureForError ()); +- } else if (MemberType.IsByRefLike) { ++ } else if (MemberType.IsSpecialRuntimeType) { ++ Report.Error (610, Location, ++ "Field or property cannot be of type `{0}'", MemberType.GetSignatureForError ()); ++ } else { + if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0) + return; + +@@ -3975,9 +3979,6 @@ namespace Mono.CSharp + Report.Error (8345, Location, + "Field or auto-implemented property cannot be of type `{0}' unless it is an instance member of a ref struct", + MemberType.GetSignatureForError ()); +- } else { +- Report.Error (610, Location, +- "Field or property cannot be of type `{0}'", MemberType.GetSignatureForError ()); + } + } + } +diff --git a/mcs/mcs/convert.cs b/mcs/mcs/convert.cs +index ae153fc49e8..2c8d2a0204c 100644 +--- a/mcs/mcs/convert.cs ++++ b/mcs/mcs/convert.cs +@@ -1232,6 +1232,13 @@ namespace Mono.CSharp { + FindApplicableUserDefinedConversionOperators (rc, operators, source_type_expr, target_type, restr, ref candidates); + } + ++ if (source_type_expr == source && source_type.IsNullableType) { ++ operators = MemberCache.GetUserOperator (source_type.TypeArguments [0], Operator.OpType.Implicit, declared_only); ++ if (operators != null) { ++ FindApplicableUserDefinedConversionOperators (rc, operators, source_type_expr, target_type, restr, ref candidates); ++ } ++ } ++ + if (!implicitOnly) { + operators = MemberCache.GetUserOperator (source_type, Operator.OpType.Explicit, declared_only); + if (operators != null) { +diff --git a/mcs/mcs/cs-parser.jay b/mcs/mcs/cs-parser.jay +index 4d6fcb44c0d..4ca3bf74f3d 100644 +--- a/mcs/mcs/cs-parser.jay ++++ b/mcs/mcs/cs-parser.jay +@@ -34,13 +34,16 @@ namespace Mono.CSharp + Params = 1 << 4, + Arglist = 1 << 5, + DefaultValue = 1 << 6, ++ ReadOnly = 1 << 7, + +- All = Ref | Out | This | Params | Arglist | DefaultValue, ++ All = Ref | Out | This | Params | Arglist | DefaultValue | ReadOnly, + PrimaryConstructor = Ref | Out | Params | DefaultValue + } + + static readonly object ModifierNone = 0; +- ++ static readonly object RefStructToken = new object (); ++ static readonly object RefPartialStructToken = new object (); ++ + NamespaceContainer current_namespace; + TypeContainer current_container; + TypeDefinition current_type; +@@ -338,6 +341,7 @@ namespace Mono.CSharp + %token OPEN_BRACKET_EXPR + %token OPEN_PARENS_DECONSTRUCT + %token REF_STRUCT ++%token REF_PARTIAL + + // Make the parser go into eval mode parsing (statements and compilation units). + %token EVAL_STATEMENT_PARSER +@@ -648,8 +652,8 @@ namespace_or_type_declaration + TypeContainer ds = (TypeContainer)$1; + + if ((ds.ModFlags & (Modifiers.PRIVATE | Modifiers.PROTECTED)) != 0){ +- report.Error (1527, ds.Location, +- "Namespace elements cannot be explicitly declared as private, protected or protected internal"); ++ report.Error (1527, ds.Location, ++ "Namespace elements cannot be explicitly declared as private, protected, protected internal, or private protected"); + } + + // Here is a trick, for explicit attributes we don't know where they belong to until +@@ -1028,7 +1032,15 @@ struct_keyword + FeatureIsNotAvailable (GetLocation ($1), "ref structs"); + } + +- $$ = this; ++ $$ = RefStructToken; ++ } ++ | REF_PARTIAL STRUCT ++ { ++ if (lang_version < LanguageVersion.V_7_2) { ++ FeatureIsNotAvailable (GetLocation ($1), "ref structs"); ++ } ++ ++ $$ = RefPartialStructToken; + } + ; + +@@ -1043,8 +1055,13 @@ struct_declaration + if ((mods & Modifiers.READONLY) != 0 && lang_version < LanguageVersion.V_7_2) { + FeatureIsNotAvailable (GetLocation ($4), "readonly structs"); + } +- if ($4 != null) ++ if ($4 != null) { + mods |= Modifiers.REF; ++ if ($4 == RefPartialStructToken) { ++ mods |= Modifiers.PARTIAL; ++ $3 = $4; ++ } ++ } + + lexer.ConstraintsParsing = true; + valid_param_mod = ParameterModifierType.PrimaryConstructor; +@@ -1469,7 +1486,7 @@ method_header + OPEN_PARENS + { + lexer.parsing_generic_declaration = false; +- valid_param_mod = ParameterModifierType.All; ++ valid_param_mod = ParameterModifierType.All; + } + opt_formal_parameter_list CLOSE_PARENS + { +@@ -1569,7 +1586,7 @@ constructor_body + expression SEMICOLON + { + lexer.parsing_block = 0; +- current_block.AddStatement (new ContextualReturn ((Expression) $3)); ++ current_block.AddStatement (CreateExpressionBodiedStatement ((Expression) $3)); + var b = end_block (GetLocation ($4)); + b.IsCompilerGenerated = true; + $$ = b; +@@ -1590,7 +1607,7 @@ expression_block + lambda_arrow_expression SEMICOLON + { + lexer.parsing_block = 0; +- current_block.AddStatement (new ContextualReturn ((Expression) $3)); ++ current_block.AddStatement (CreateExpressionBodiedStatement ((Expression) $3)); + var b = end_block (GetLocation ($4)); + b.IsCompilerGenerated = true; + $$ = b; +@@ -1794,7 +1811,9 @@ parameter_modifiers + Parameter.Modifier mod = (Parameter.Modifier)$1 | p2; + if (((Parameter.Modifier)$1 & p2) == p2) { + Error_DuplicateParameterModifier (lexer.Location, p2); +- } else { ++ } else if ((mod & ~(Parameter.Modifier.This | Parameter.Modifier.ReadOnly)) == 0) { ++ // ok ++ } else { + switch (mod & ~Parameter.Modifier.This) { + case Parameter.Modifier.REF: + report.Error (1101, lexer.Location, "The parameter modifiers `this' and `ref' cannot be used altogether"); +@@ -1836,6 +1855,13 @@ parameter_modifier + + $$ = Parameter.Modifier.This; + } ++ | IN ++ { ++ if (lang_version < LanguageVersion.V_7_2) ++ FeatureIsNotAvailable (GetLocation ($1), "readonly references"); ++ ++ $$ = Parameter.Modifier.ReadOnly; ++ } + ; + + parameter_array +@@ -1871,7 +1897,7 @@ params_modifier + if ((mod & Parameter.Modifier.This) != 0) { + report.Error (1104, GetLocation ($1), "The parameter modifiers `this' and `params' cannot be used altogether"); + } else { +- report.Error (1611, GetLocation ($1), "The params parameter cannot be declared as ref or out"); ++ report.Error (1611, GetLocation ($1), "The params parameter cannot be declared as ref, out or in"); + } + } + | PARAMS params_modifier +@@ -2004,7 +2030,7 @@ indexer_declaration + : opt_attributes opt_modifiers + ref_member_type indexer_declaration_name OPEN_BRACKET + { +- valid_param_mod = ParameterModifierType.Params | ParameterModifierType.DefaultValue; ++ valid_param_mod = ParameterModifierType.Params | ParameterModifierType.DefaultValue | ParameterModifierType.ReadOnly; + } + opt_formal_parameter_list CLOSE_BRACKET + { +@@ -2181,6 +2207,11 @@ set_accessor_declaration + accessor_body + : block + | expression_block ++ { ++ if (lang_version < LanguageVersion.V_7) { ++ FeatureIsNotAvailable (GetLocation ($1), "expression body property accessor"); ++ } ++ } + | SEMICOLON + { + // TODO: lbag +@@ -2331,7 +2362,7 @@ operator_type + operator_declarator + : operator_type OPERATOR overloadable_operator OPEN_PARENS + { +- valid_param_mod = ParameterModifierType.DefaultValue; ++ valid_param_mod = ParameterModifierType.DefaultValue | ParameterModifierType.ReadOnly; + if ((Operator.OpType) $3 == Operator.OpType.Is) + valid_param_mod |= ParameterModifierType.Out; + } +@@ -2418,7 +2449,7 @@ overloadable_operator + conversion_operator_declarator + : IMPLICIT OPERATOR type OPEN_PARENS + { +- valid_param_mod = ParameterModifierType.DefaultValue; ++ valid_param_mod = ParameterModifierType.DefaultValue | ParameterModifierType.ReadOnly; + } + opt_formal_parameter_list CLOSE_PARENS + { +@@ -2441,7 +2472,7 @@ conversion_operator_declarator + } + | EXPLICIT OPERATOR type OPEN_PARENS + { +- valid_param_mod = ParameterModifierType.DefaultValue; ++ valid_param_mod = ParameterModifierType.DefaultValue | ParameterModifierType.ReadOnly; + } + opt_formal_parameter_list CLOSE_PARENS + { +@@ -2850,6 +2881,11 @@ event_accessor_block + } + | block + | expression_block ++ { ++ if (lang_version < LanguageVersion.V_7) { ++ FeatureIsNotAvailable (GetLocation ($1), "expression body event accessor"); ++ } ++ } + ; + + attributes_without_members +@@ -3014,7 +3050,7 @@ delegate_declaration + ref_member_type type_declaration_name + OPEN_PARENS + { +- valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out | ParameterModifierType.Params | ParameterModifierType.DefaultValue; ++ valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out | ParameterModifierType.Params | ParameterModifierType.DefaultValue | ParameterModifierType.ReadOnly; + } + opt_formal_parameter_list CLOSE_PARENS + { +@@ -3927,7 +3963,15 @@ non_simple_argument + { + $$ = new Argument (new Arglist (GetLocation ($1))); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($3)); +- } ++ } ++ | IN variable_reference ++ { ++ if (lang_version < LanguageVersion.V_7_2) ++ FeatureIsNotAvailable (GetLocation ($1), "readonly references"); ++ ++ $$ = new Argument ((Expression) $2, Argument.AType.Readonly); ++ lbag.AddLocation ($$, GetLocation ($1)); ++ } + ; + + out_variable_declaration +@@ -4408,7 +4452,7 @@ opt_anonymous_method_signature + anonymous_method_signature + : OPEN_PARENS + { +- valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; ++ valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out | ParameterModifierType.ReadOnly; + } + opt_formal_parameter_list CLOSE_PARENS + { +@@ -5014,36 +5058,47 @@ null_coalescing_expression + } + ; + ++ ++conditional_oper_expr ++ : expression ++ | stackalloc_expression ++ ; ++ + conditional_expression + : null_coalescing_expression +- | null_coalescing_expression INTERR expression COLON expression ++ | null_coalescing_expression INTERR conditional_oper_expr COLON conditional_oper_expr + { + $$ = new Conditional (new BooleanExpression ((Expression) $1), (Expression) $3, (Expression) $5, GetLocation ($2)); + lbag.AddLocation ($$, GetLocation ($4)); + } +- | null_coalescing_expression INTERR expression COLON THROW prefixed_unary_expression ++ | null_coalescing_expression INTERR conditional_oper_expr COLON THROW prefixed_unary_expression + { + if (lang_version < LanguageVersion.V_7) +- FeatureIsNotAvailable (lexer.Location, "throw expression"); ++ FeatureIsNotAvailable (GetLocation ($5), "throw expression"); + + var expr = new ThrowExpression ((Expression) $6, GetLocation ($5)); + $$ = new Conditional (new BooleanExpression ((Expression) $1), (Expression) $3, expr, GetLocation ($2)); + lbag.AddLocation ($$, GetLocation ($4)); + } +- | null_coalescing_expression INTERR expression error ++ | null_coalescing_expression INTERR reference_expression COLON reference_expression ++ { ++ $$ = new Conditional (new BooleanExpression ((Expression) $1), (Expression) $3, (Expression) $5, GetLocation ($2)); ++ lbag.AddLocation ($$, GetLocation ($4)); ++ } ++ | null_coalescing_expression INTERR conditional_oper_expr error + { + Error_SyntaxError (yyToken); + + $$ = new Conditional (new BooleanExpression ((Expression) $1), (Expression) $3, null, GetLocation ($2)); + } +- | null_coalescing_expression INTERR expression COLON error ++ | null_coalescing_expression INTERR conditional_oper_expr COLON error + { + Error_SyntaxError (yyToken); + + $$ = new Conditional (new BooleanExpression ((Expression) $1), (Expression) $3, null, GetLocation ($2)); + lbag.AddLocation ($$, GetLocation ($4)); + } +- | null_coalescing_expression INTERR expression COLON CLOSE_BRACE ++ | null_coalescing_expression INTERR conditional_oper_expr COLON CLOSE_BRACE + { + Error_SyntaxError (Token.CLOSE_BRACE); + +@@ -5308,7 +5363,7 @@ lambda_expression + } + | OPEN_PARENS_LAMBDA + { +- valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; ++ valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out | ParameterModifierType.ReadOnly; + } + opt_lambda_parameter_list CLOSE_PARENS ARROW + { +@@ -5322,7 +5377,7 @@ lambda_expression + } + | ASYNC OPEN_PARENS_LAMBDA + { +- valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; ++ valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out | ParameterModifierType.ReadOnly; + } + opt_lambda_parameter_list CLOSE_PARENS ARROW + { +@@ -5522,10 +5577,17 @@ modifiers + if ((m1 & m2) != 0) { + report.Error (1004, lexer.Location - ModifiersExtensions.Name (m2).Length, + "Duplicate `{0}' modifier", ModifiersExtensions.Name (m2)); +- } else if ((m2 & Modifiers.AccessibilityMask) != 0 && (m1 & Modifiers.AccessibilityMask) != 0 && +- ((m2 | m1 & Modifiers.AccessibilityMask) != (Modifiers.PROTECTED | Modifiers.INTERNAL))) { +- report.Error (107, lexer.Location - ModifiersExtensions.Name (m2).Length, +- "More than one protection modifier specified"); ++ } else if ((m2 & Modifiers.AccessibilityMask) != 0 && (m1 & Modifiers.AccessibilityMask) != 0) { ++ var accessibility = (m2 | m1 & Modifiers.AccessibilityMask); ++ ++ if (accessibility == (Modifiers.PRIVATE | Modifiers.PROTECTED)) { ++ if (lang_version < LanguageVersion.V_7_2) { ++ FeatureIsNotAvailable (lexer.Location, "private protected"); ++ } ++ } else if (accessibility != (Modifiers.PROTECTED | Modifiers.INTERNAL)) { ++ report.Error (107, lexer.Location - ModifiersExtensions.Name (m2).Length, ++ "More than one protection modifier specified"); ++ } + } + + $$ = m1 | m2; +@@ -6223,11 +6285,28 @@ block_variable_initializer + | STACKALLOC simple_type + { + report.Error (1575, GetLocation ($1), "A stackalloc expression requires [] after type"); +- $$ = new StackAlloc ((Expression) $2, null, GetLocation ($1)); ++ $$ = new StackAlloc ((Expression) $2, null, GetLocation ($1)); + } + | reference_expression + ; + ++stackalloc_expression ++ : STACKALLOC simple_type OPEN_BRACKET_EXPR expression CLOSE_BRACKET ++ { ++ if (lang_version < LanguageVersion.V_7_2) { ++ FeatureIsNotAvailable (GetLocation ($1), "ref structs"); ++ } ++ ++ $$ = new SpanStackAlloc ((Expression) $2, (Expression) $4, GetLocation ($1)); ++ lbag.AddLocation ($$, GetLocation ($3), GetLocation ($5)); ++ } ++ | STACKALLOC simple_type ++ { ++ report.Error (1575, GetLocation ($1), "A stackalloc expression requires [] after type"); ++ $$ = new StackAlloc ((Expression) $2, null, GetLocation ($1)); ++ } ++ ; ++ + reference_expression + : REF expression + { +@@ -7699,7 +7778,7 @@ doc_cref + } + | doc_type_declaration_name DOT THIS OPEN_BRACKET + { +- valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; ++ valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out | ParameterModifierType.ReadOnly; + } + opt_doc_parameters CLOSE_BRACKET + { +@@ -7743,7 +7822,7 @@ opt_doc_method_sig + : /* empty */ + | OPEN_PARENS + { +- valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; ++ valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out | ParameterModifierType.ReadOnly; + } + opt_doc_parameters CLOSE_PARENS + { +@@ -7951,6 +8030,14 @@ static bool IsUnaryOperator (Operator.OpType op) + return false; + } + ++static Statement CreateExpressionBodiedStatement (Expression expr) ++{ ++ if (expr is ThrowExpression te) ++ return new StatementExpression (te); ++ ++ return new ContextualReturn (expr); ++} ++ + void syntax_error (Location l, string msg) + { + report.Error (1003, l, "Syntax error, " + msg); +@@ -8430,6 +8517,8 @@ static string GetTokenName (int token) + case Token.READONLY: + return "readonly"; + case Token.REF: ++ case Token.REF_STRUCT: ++ case Token.REF_PARTIAL: + return "ref"; + case Token.RETURN: + return "return"; +@@ -8444,7 +8533,6 @@ static string GetTokenName (int token) + case Token.STATIC: + return "static"; + case Token.STRUCT: +- case Token.REF_STRUCT: + return "struct"; + case Token.SWITCH: + return "switch"; +diff --git a/mcs/mcs/cs-tokenizer.cs b/mcs/mcs/cs-tokenizer.cs +index 37edb5c1224..db5ba1f1f1b 100644 +--- a/mcs/mcs/cs-tokenizer.cs ++++ b/mcs/mcs/cs-tokenizer.cs +@@ -825,8 +825,7 @@ namespace Mono.CSharp + next_token == Token.CLASS || + next_token == Token.STRUCT || + next_token == Token.INTERFACE || +- next_token == Token.VOID || +- next_token == Token.REF_STRUCT; ++ next_token == Token.VOID; + + PopPosition (); + +@@ -916,14 +915,20 @@ namespace Mono.CSharp + + break; + case Token.REF: +- if (peek_token () == Token.STRUCT) { ++ var pp = peek_token (); ++ switch (pp) { ++ case Token.STRUCT: + token (); + res = Token.REF_STRUCT; ++ break; ++ case Token.PARTIAL: ++ token (); ++ res = Token.REF_PARTIAL; ++ break; + } + break; + } + +- + return res; + } + +@@ -1212,6 +1217,7 @@ namespace Mono.CSharp + + case Token.REF: + case Token.OUT: ++ case Token.IN: + can_be_type = is_type = false; + continue; + +@@ -1406,6 +1412,8 @@ namespace Mono.CSharp + case Token.INTERPOLATED_STRING: + case Token.THROW: + case Token.DEFAULT_COLON: ++ case Token.REF: ++ case Token.STACKALLOC: + next_token = Token.INTERR; + break; + +@@ -1567,28 +1575,53 @@ namespace Mono.CSharp + { + int d; + bool seen_digits = false; +- +- if (c != -1){ ++ bool digit_separator = false; ++ int prev = c; ++ var loc = Location; ++ ++ if (prev != -1){ + if (number_pos == MaxNumberLength) + Error_NumericConstantTooLong (); +- number_builder [number_pos++] = (char) c; ++ number_builder [number_pos++] = (char) prev; + } +- ++ + // + // We use peek_char2, because decimal_digits needs to do a + // 2-character look-ahead (5.ToString for example). + // + while ((d = peek_char2 ()) != -1){ +- if (d >= '0' && d <= '9'){ ++ if (d >= '0' && d <= '9') { + if (number_pos == MaxNumberLength) + Error_NumericConstantTooLong (); +- number_builder [number_pos++] = (char) d; +- get_char (); ++ number_builder [number_pos++] = (char)d; ++ prev = get_char (); + seen_digits = true; +- } else +- break; ++ continue; ++ } else if (d == '_') { ++ if (!digit_separator) { ++ if (context.Settings.Version < LanguageVersion.V_7) ++ Report.FeatureIsNotAvailable (context, Location, "digit separators"); ++ ++ digit_separator = true; ++ } ++ ++ if (prev == '.') ++ break; ++ ++ if (prev == 'e' || prev == 'E') ++ Error_InvalidNumber (); ++ ++ prev = get_char(); ++ continue; ++ } ++ ++ break; + } + ++ if (prev == '_') { ++ Error_InvalidNumber (); ++ } ++ + return seen_digits; + } + +@@ -1716,9 +1749,8 @@ namespace Mono.CSharp + } catch (OverflowException) { + Error_NumericConstantTooLong (); + return new IntLiteral (context.BuiltinTypes, 0, loc); +- } +- catch (FormatException) { +- Report.Error (1013, Location, "Invalid number"); ++ } catch (FormatException) { ++ Error_InvalidNumber (); + return new IntLiteral (context.BuiltinTypes, 0, loc); + } + } +@@ -1757,14 +1789,41 @@ namespace Mono.CSharp + { + int d; + ulong ul; +- +- get_char (); ++ bool digit_separator = false; ++ int prev = get_char (); ++ + while ((d = peek_char ()) != -1){ + if (is_hex (d)){ + number_builder [number_pos++] = (char) d; + get_char (); +- } else +- break; ++ ++ prev = d; ++ continue; ++ } ++ ++ if (d == '_') { ++ if (prev == 'x' || prev == 'X') ++ Error_InvalidNumber (); ++ ++ get_char (); ++ ++ if (!digit_separator) { ++ if (context.Settings.Version < LanguageVersion.V_7) ++ Report.FeatureIsNotAvailable (context, Location, "digit separators"); ++ ++ digit_separator = true; ++ } ++ ++ prev = d; ++ continue; ++ } ++ ++ break; ++ } ++ ++ if (number_pos == 0 || prev == '_') { ++ Error_InvalidNumber (); ++ return new IntLiteral (context.BuiltinTypes, 0, loc); + } + + string s = new String (number_builder, 0, number_pos); +@@ -1779,13 +1838,65 @@ namespace Mono.CSharp + } catch (OverflowException){ + Error_NumericConstantTooLong (); + return new IntLiteral (context.BuiltinTypes, 0, loc); +- } +- catch (FormatException) { +- Report.Error (1013, Location, "Invalid number"); ++ } catch (FormatException) { ++ Error_InvalidNumber (); + return new IntLiteral (context.BuiltinTypes, 0, loc); + } + } + ++ ILiteralConstant handle_binary (Location loc) ++ { ++ int d; ++ ulong ul = 0; ++ bool digit_separator = false; ++ int digits = 0; ++ int prev = get_char (); ++ ++ while ((d = peek_char ()) != -1){ ++ ++ if (d == '0' || d == '1') { ++ ul = (ul << 1); ++ digits++; ++ if (d == '1') ++ ul |= 1; ++ get_char (); ++ if (digits > 64) { ++ Error_NumericConstantTooLong (); ++ return new IntLiteral (context.BuiltinTypes, 0, loc); ++ } ++ ++ prev = d; ++ continue; ++ } ++ ++ if (d == '_') { ++ if (prev == 'b' || prev == 'B') ++ Error_InvalidNumber (); ++ ++ get_char (); ++ ++ if (!digit_separator) { ++ if (context.Settings.Version < LanguageVersion.V_7) ++ Report.FeatureIsNotAvailable (context, Location, "digit separators"); ++ ++ digit_separator = true; ++ } ++ ++ prev = d; ++ continue; ++ } ++ ++ break; ++ } ++ ++ if (digits == 0 || prev == '_') { ++ Error_InvalidNumber (); ++ return new IntLiteral (context.BuiltinTypes, 0, loc); ++ } ++ ++ return integer_type_suffix (ul, peek_char (), loc); ++ } ++ + // + // Invoked if we know we have .digits or digits + // +@@ -1817,7 +1928,20 @@ namespace Mono.CSharp + + return Token.LITERAL; + } ++ ++ if (peek == 'b' || peek == 'B'){ ++ if (context.Settings.Version < LanguageVersion.V_7) ++ Report.FeatureIsNotAvailable (context, Location, "binary literals"); ++ ++ val = res = handle_binary (loc); ++#if FULL_AST ++ res.ParsedValue = reader.ReadChars (read_start, reader.Position - 1); ++#endif ++ ++ return Token.LITERAL; ++ } + } ++ + decimal_digits (c); + c = peek_char (); + } +@@ -1869,7 +1993,7 @@ namespace Mono.CSharp + Error_NumericConstantTooLong (); + number_builder [number_pos++] = '+'; + } +- ++ + decimal_digits (c); + c = peek_char (); + } +@@ -2944,6 +3068,11 @@ namespace Mono.CSharp + { + Report.Error (1021, Location, "Integral constant is too large"); + } ++ ++ void Error_InvalidNumber () ++ { ++ Report.Error (1013, Location, "Invalid number"); ++ } + + void Error_InvalidDirective () + { +diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs +index 20ee9e73b19..d5926bf4d1f 100644 +--- a/mcs/mcs/ecore.cs ++++ b/mcs/mcs/ecore.cs +@@ -241,7 +241,7 @@ namespace Mono.CSharp { + + protected void CheckExpressionVariable (ResolveContext rc) + { +- if (rc.HasAny (ResolveContext.Options.BaseInitializer | ResolveContext.Options.FieldInitializerScope)) { ++ if (rc.HasAny (ResolveContext.Options.BaseInitializer | ResolveContext.Options.FieldInitializerScope) && rc.CurrentAnonymousMethod == null) { + rc.Report.Error (8200, loc, "Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers"); + } else if (rc.HasSet (ResolveContext.Options.QueryClauseScope)) { + rc.Report.Error (8201, loc, "Out variable and pattern variable declarations are not allowed within a query clause"); +diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs +index 518ccc8ef43..87db14a0ce7 100644 +--- a/mcs/mcs/expression.cs ++++ b/mcs/mcs/expression.cs +@@ -920,7 +920,7 @@ namespace Mono.CSharp + + public override bool ContainsEmitWithAwait () + { +- throw new NotImplementedException (); ++ return false; + } + + public override Expression CreateExpressionTree (ResolveContext ec) +@@ -2051,7 +2051,11 @@ namespace Mono.CSharp + + if (d.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + return this; +- ++ ++ // TODO: Requires custom optimized version with variable store ++ if (Variable != null) ++ return this; ++ + // + // Turn is check into simple null check for implicitly convertible reference types + // +@@ -2757,6 +2761,12 @@ namespace Mono.CSharp + } + } + ++ public override bool IsNull { ++ get { ++ return TypeSpec.IsReferenceType (type); ++ } ++ } ++ + public override bool ContainsEmitWithAwait () + { + return false; +@@ -5669,6 +5679,12 @@ namespace Mono.CSharp + ConvCast.Emit (ec, enum_conversion); + } + ++ public override void EmitPrepare (EmitContext ec) ++ { ++ Left.EmitPrepare (ec); ++ Right.EmitPrepare (ec); ++ } ++ + public override void EmitSideEffect (EmitContext ec) + { + if ((oper & Operator.LogicalMask) != 0 || +@@ -6385,7 +6401,7 @@ namespace Mono.CSharp + } + } + +- if (conv_false_expr != null) { ++ if (conv_false_expr != null && false_type != InternalType.ErrorType && true_type != InternalType.ErrorType) { + ec.Report.Error (172, true_expr.Location, + "Type of conditional expression cannot be determined as `{0}' and `{1}' convert implicitly to each other", + true_type.GetSignatureForError (), false_type.GetSignatureForError ()); +@@ -6398,7 +6414,7 @@ namespace Mono.CSharp + } else if ((conv = Convert.ImplicitConversion (ec, false_expr, true_type, loc)) != null) { + false_expr = conv; + } else { +- if (false_type != InternalType.ErrorType) { ++ if (false_type != InternalType.ErrorType && true_type != InternalType.ErrorType) { + ec.Report.Error (173, true_expr.Location, + "Type of conditional expression cannot be determined because there is no implicit conversion between `{0}' and `{1}'", + true_type.GetSignatureForError (), false_type.GetSignatureForError ()); +@@ -6427,6 +6443,30 @@ namespace Mono.CSharp + return this; + } + ++ public override Expression DoResolveLValue (ResolveContext rc, Expression right_side) ++ { ++ expr = expr.Resolve (rc); ++ true_expr = true_expr.Resolve (rc); ++ false_expr = false_expr.Resolve (rc); ++ ++ if (true_expr == null || false_expr == null || expr == null) ++ return null; ++ ++ if (!(true_expr is ReferenceExpression && false_expr is ReferenceExpression)) { ++ rc.Report.Error (8326, expr.Location, "Both ref conditional operators must be ref values"); ++ return null; ++ } ++ ++ if (!TypeSpecComparer.IsEqual (true_expr.Type, false_expr.Type)) { ++ rc.Report.Error (8327, true_expr.Location, "The ref conditional expression types `{0}' and `{1}' have to match", ++ true_expr.Type.GetSignatureForError (), false_expr.Type.GetSignatureForError ()); ++ } ++ ++ eclass = ExprClass.Value; ++ type = true_expr.Type; ++ return this; ++ } ++ + public override void Emit (EmitContext ec) + { + Label false_target = ec.DefineLabel (); +@@ -6774,7 +6814,7 @@ namespace Mono.CSharp + "Cannot use fixed variable `{0}' inside an anonymous method, lambda expression or query expression", + GetSignatureForError ()); + } else if (local_info.IsByRef || local_info.Type.IsByRefLike) { +- if (ec.CurrentAnonymousMethod is StateMachineInitializer) { ++ if (local_info.Type.IsSpecialRuntimeType || ec.CurrentAnonymousMethod is StateMachineInitializer) { + // It's reported later as 4012/4013 + } else { + ec.Report.Error (8175, loc, +@@ -11877,12 +11917,17 @@ namespace Mono.CSharp + if (!TypeManager.VerifyUnmanaged (ec.Module, otype, loc)) + return null; + +- type = PointerContainer.MakeType (ec.Module, otype); ++ ResolveExpressionType (ec, otype); + eclass = ExprClass.Value; + + return this; + } + ++ protected virtual void ResolveExpressionType (ResolveContext rc, TypeSpec elementType) ++ { ++ type = PointerContainer.MakeType (rc.Module, elementType); ++ } ++ + public override void Emit (EmitContext ec) + { + int size = BuiltinTypeSpec.GetSize (otype); +@@ -11931,14 +11976,36 @@ namespace Mono.CSharp + public bool ResolveSpanConversion (ResolveContext rc, TypeSpec spanType) + { + ctor = MemberCache.FindMember (spanType, MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (PointerContainer.MakeType (rc.Module, rc.Module.Compiler.BuiltinTypes.Void), rc.Module.Compiler.BuiltinTypes.Int)), BindingRestriction.DeclaredOnly) as MethodSpec; +- if (ctor == null) ++ if (ctor == null) { ++ this.type = InternalType.ErrorType; + return false; ++ } + + this.type = spanType; + return true; + } + } + ++ class SpanStackAlloc : StackAlloc ++ { ++ public SpanStackAlloc (Expression type, Expression count, Location l) ++ : base (type, count, l) ++ { ++ } ++ ++ protected override void ResolveExpressionType (ResolveContext rc, TypeSpec elementType) ++ { ++ var span = rc.Module.PredefinedTypes.SpanGeneric.Resolve (); ++ if (span == null) { ++ type = InternalType.ErrorType; ++ return; ++ } ++ ++ type = span.MakeGenericType (rc, new [] { elementType }); ++ ResolveSpanConversion (rc, type); ++ } ++ } ++ + // + // An object initializer expression + // +@@ -13085,6 +13152,9 @@ namespace Mono.CSharp + if (expr is IAssignMethod) + return true; + ++ if (expr is Conditional) ++ return true; ++ + var invocation = expr as Invocation; + if (invocation?.Type.Kind == MemberKind.ByRef) + return true; +@@ -13232,6 +13302,10 @@ namespace Mono.CSharp + this.loc = loc; + } + ++ protected override void CloneTo (CloneContext clonectx, Expression t) ++ { ++ } ++ + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotImplementedException (); +diff --git a/mcs/mcs/field.cs b/mcs/mcs/field.cs +index 86bb028defc..8c667328143 100644 +--- a/mcs/mcs/field.cs ++++ b/mcs/mcs/field.cs +@@ -542,7 +542,7 @@ namespace Mono.CSharp + } + ); + +- fixed_buffer_type.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ()); ++ fixed_buffer_type.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray (out _)); + #endif + // + // Don't emit FixedBufferAttribute attribute for private types +@@ -559,7 +559,8 @@ namespace Mono.CSharp + encoder.Encode (buffer_size); + encoder.EncodeEmptyNamedArguments (); + +- FieldBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ()); ++ FieldBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray (out var references)); ++ Module.AddAssemblyReferences (references); + } + } + +diff --git a/mcs/mcs/generic.cs b/mcs/mcs/generic.cs +index ec2965df63b..0c7032b2088 100644 +--- a/mcs/mcs/generic.cs ++++ b/mcs/mcs/generic.cs +@@ -3381,7 +3381,7 @@ namespace Mono.CSharp { + continue; + + var bound = candidates [ci]; +- if (bound.Type == best_candidate) ++ if (TypeSpecComparer.IsEqual (bound.Type, best_candidate)) + continue; + + int cii = 0; +diff --git a/mcs/mcs/modifiers.cs b/mcs/mcs/modifiers.cs +index 926ab5d1848..21dd52b3b14 100644 +--- a/mcs/mcs/modifiers.cs ++++ b/mcs/mcs/modifiers.cs +@@ -74,6 +74,8 @@ namespace Mono.CSharp + return "internal"; + case Modifiers.PRIVATE: + return "private"; ++ case Modifiers.PRIVATE | Modifiers.PROTECTED: ++ return "private protected"; + default: + throw new NotImplementedException (mod.ToString ()); + } +@@ -129,12 +131,16 @@ namespace Mono.CSharp + if ((modB & Modifiers.PUBLIC) != 0) { + flags = Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE; + } else if ((modB & Modifiers.PROTECTED) != 0) { +- if ((modB & Modifiers.INTERNAL) != 0) +- flags = Modifiers.PROTECTED | Modifiers.INTERNAL; +- +- flags |= Modifiers.PRIVATE; +- } else if ((modB & Modifiers.INTERNAL) != 0) ++ if ((modB & Modifiers.INTERNAL) != 0) { ++ flags = Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE; ++ } else { ++ modA &= ~Modifiers.PROTECTED; ++ flags = Modifiers.PRIVATE; ++ } ++ } else if ((modB & Modifiers.INTERNAL) != 0) { ++ modA &= ~Modifiers.PROTECTED; + flags = Modifiers.PRIVATE; ++ } + + return modB != modA && (modA & (~flags)) == 0; + } +@@ -151,6 +157,8 @@ namespace Mono.CSharp + } else { + if ((mod_flags & Modifiers.PUBLIC) != 0) + t = TypeAttributes.NestedPublic; ++ else if ((mod_flags & (Modifiers.PROTECTED | Modifiers.PRIVATE)) == (Modifiers.PROTECTED | Modifiers.PRIVATE)) ++ t = TypeAttributes.NestedFamANDAssem; + else if ((mod_flags & Modifiers.PRIVATE) != 0) + t = TypeAttributes.NestedPrivate; + else if ((mod_flags & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) +@@ -173,18 +181,27 @@ namespace Mono.CSharp + { + FieldAttributes fa = 0; + +- if ((mod_flags & Modifiers.PUBLIC) != 0) ++ switch (mod_flags & Modifiers.AccessibilityMask) { ++ case Modifiers.PUBLIC: + fa |= FieldAttributes.Public; +- if ((mod_flags & Modifiers.PRIVATE) != 0) ++ break; ++ case Modifiers.PRIVATE: + fa |= FieldAttributes.Private; +- if ((mod_flags & Modifiers.PROTECTED) != 0) { +- if ((mod_flags & Modifiers.INTERNAL) != 0) +- fa |= FieldAttributes.FamORAssem; +- else +- fa |= FieldAttributes.Family; +- } else { +- if ((mod_flags & Modifiers.INTERNAL) != 0) +- fa |= FieldAttributes.Assembly; ++ break; ++ case Modifiers.PROTECTED | Modifiers.INTERNAL: ++ fa |= FieldAttributes.FamORAssem; ++ break; ++ case Modifiers.PROTECTED: ++ fa |= FieldAttributes.Family; ++ break; ++ case Modifiers.INTERNAL: ++ fa |= FieldAttributes.Assembly; ++ break; ++ case Modifiers.PRIVATE | Modifiers.PROTECTED: ++ fa |= FieldAttributes.FamANDAssem; ++ break; ++ default: ++ throw new NotImplementedException (mod_flags.ToString ()); + } + + if ((mod_flags & Modifiers.STATIC) != 0) +@@ -215,6 +232,9 @@ namespace Mono.CSharp + case Modifiers.INTERNAL: + ma |= MethodAttributes.Assembly; + break; ++ case Modifiers.PRIVATE | Modifiers.PROTECTED: ++ ma |= MethodAttributes.FamANDAssem; ++ break; + default: + throw new NotImplementedException (mod_flags.ToString ()); + } +diff --git a/mcs/mcs/module.cs b/mcs/mcs/module.cs +index 2293d825b36..4680433bb01 100644 +--- a/mcs/mcs/module.cs ++++ b/mcs/mcs/module.cs +@@ -480,6 +480,18 @@ namespace Mono.CSharp + attributes.AddAttribute (attr); + } + ++ public void AddAssemblyReferences (List names) ++ { ++ if (names == null) ++ return; ++ ++#if STATIC ++ foreach (var name in names) { ++ Builder.__GetAssemblyToken (name); ++ } ++#endif ++ } ++ + public override void AddTypeContainer (TypeContainer tc) + { + AddTypeContainerMember (tc); +diff --git a/mcs/mcs/parameter.cs b/mcs/mcs/parameter.cs +index cc10eee162b..95851478010 100644 +--- a/mcs/mcs/parameter.cs ++++ b/mcs/mcs/parameter.cs +@@ -221,12 +221,13 @@ namespace Mono.CSharp { + REF = 1 << 1, + OUT = 1 << 2, + This = 1 << 3, +- CallerMemberName = 1 << 4, +- CallerLineNumber = 1 << 5, +- CallerFilePath = 1 << 6, ++ ReadOnly = 1 << 4, ++ CallerMemberName = 1 << 5, ++ CallerLineNumber = 1 << 6, ++ CallerFilePath = 1 << 7, + + RefOutMask = REF | OUT, +- ModifierMask = PARAMS | REF | OUT | This, ++ ModifierMask = PARAMS | REF | OUT | This | ReadOnly, + CallerMask = CallerMemberName | CallerLineNumber | CallerFilePath + } + +@@ -1474,9 +1475,9 @@ namespace Mono.CSharp { + } + } + +- if (!expr.IsNull && TypeSpec.IsReferenceType (parameter_type) && parameter_type.BuiltinType != BuiltinTypeSpec.Type.String) { ++ if (!res.IsNull && TypeSpec.IsReferenceType (parameter_type) && parameter_type.BuiltinType != BuiltinTypeSpec.Type.String) { + rc.Report.Error (1763, Location, +- "Optional parameter `{0}' of type `{1}' can only be initialized with `null'", ++ "Optional parameter `{0}' of type `{1}' can only be initialized with default value", + p.Name, parameter_type.GetSignatureForError ()); + + return; +diff --git a/mcs/mcs/report.cs b/mcs/mcs/report.cs +index cc3d82b26e0..5d64c8e766e 100644 +--- a/mcs/mcs/report.cs ++++ b/mcs/mcs/report.cs +@@ -42,7 +42,7 @@ namespace Mono.CSharp { + public static readonly int[] AllWarnings = new int[] { + 28, 67, 78, + 105, 108, 109, 114, 162, 164, 168, 169, 183, 184, 197, +- 219, 251, 252, 253, 278, 282, ++ 219, 251, 252, 253, 278, 280, 282, + 402, 414, 419, 420, 429, 436, 437, 440, 458, 464, 465, 467, 469, 472, 473, + 612, 618, 626, 628, 642, 649, 652, 657, 658, 659, 660, 661, 665, 672, 675, 693, + 728, +@@ -107,6 +107,15 @@ namespace Mono.CSharp { + case LanguageVersion.V_7: + version = "7.0"; + break; ++ case LanguageVersion.V_7_1: ++ version = "7.1"; ++ break; ++ case LanguageVersion.V_7_2: ++ version = "7.2"; ++ break; ++ case LanguageVersion.V_7_3: ++ version = "7.3"; ++ break; + default: + throw new InternalErrorException ("Invalid feature version", compiler.Settings.Version); + } +diff --git a/mcs/mcs/settings.cs b/mcs/mcs/settings.cs +index 37664187c71..976c9b68128 100644 +--- a/mcs/mcs/settings.cs ++++ b/mcs/mcs/settings.cs +@@ -32,10 +32,11 @@ namespace Mono.CSharp { + V_7 = 7, + V_7_1 = 71, + V_7_2 = 72, ++ V_7_3 = 73, + Experimental = 100, + + Default = V_7, +- Latest = V_7_2 ++ Latest = V_7_3 + } + + public enum RuntimeVersion +@@ -1270,6 +1271,7 @@ namespace Mono.CSharp { + case "/highentropyva+": + case "/highentropyva-": + case "/link": ++ case "/sourcelink": + case "/moduleassemblyname": + case "/nowin32manifest": + case "/pdb": +diff --git a/mcs/mcs/statement.cs b/mcs/mcs/statement.cs +index 9c51128548f..c8b77c1adc1 100644 +--- a/mcs/mcs/statement.cs ++++ b/mcs/mcs/statement.cs +@@ -928,8 +928,7 @@ namespace Mono.CSharp { + public override Reachability MarkReachable (Reachability rc) + { + base.MarkReachable (rc); +- expr.MarkReachable (rc); +- return rc; ++ return expr.MarkReachable (rc); + } + + public override bool Resolve (BlockContext ec) +@@ -2419,6 +2418,7 @@ namespace Mono.CSharp { + IsLocked = 1 << 8, + SymbolFileHidden = 1 << 9, + ByRef = 1 << 10, ++ PointerByRef = 1 << 11, + + ReadonlyMask = 1 << 20 + } +@@ -2609,20 +2609,22 @@ namespace Mono.CSharp { + + if (IsByRef) { + builder = ec.DeclareLocal (ReferenceContainer.MakeType (ec.Module, Type), IsFixed); ++ } else if ((flags & Flags.PointerByRef) != 0) { ++ builder = ec.DeclareLocal (ReferenceContainer.MakeType (ec.Module, ((PointerContainer) Type).Element), IsFixed); + } else { + // + // All fixed variabled are pinned, a slot has to be alocated + // +- builder = ec.DeclareLocal(Type, IsFixed); ++ builder = ec.DeclareLocal (Type, IsFixed); + } + + if ((flags & Flags.SymbolFileHidden) == 0) + ec.DefineLocalVariable (name, builder); + } + +- public static LocalVariable CreateCompilerGenerated (TypeSpec type, Block block, Location loc, bool writeToSymbolFile = false) ++ public static LocalVariable CreateCompilerGenerated (TypeSpec type, Block block, Location loc, bool writeToSymbolFile = false, Flags additionalFlags = 0) + { +- LocalVariable li = new LocalVariable (block, GetCompilerGeneratedName (block), Flags.CompilerGenerated | Flags.Used, loc); ++ LocalVariable li = new LocalVariable (block, GetCompilerGeneratedName (block), Flags.CompilerGenerated | Flags.Used | additionalFlags, loc); + if (!writeToSymbolFile) + li.flags |= Flags.SymbolFileHidden; + +@@ -2725,6 +2727,11 @@ namespace Mono.CSharp { + flags |= Flags.Used; + } + ++ public void SetIsPointerByRef () ++ { ++ flags |= Flags.PointerByRef; ++ } ++ + public void SetHasAddressTaken () + { + flags |= (Flags.AddressTaken | Flags.Used); +@@ -6562,18 +6569,26 @@ namespace Mono.CSharp { + + // TODO: Should use Binary::Add + pinned_string.Emit (ec); +- ec.Emit (OpCodes.Conv_I); ++ ec.Emit (OpCodes.Conv_U); + + var m = ec.Module.PredefinedMembers.RuntimeHelpersOffsetToStringData.Resolve (loc); + if (m == null) + return; + ++ var null_value = ec.DefineLabel (); ++ vi.EmitAssign (ec); ++ vi.Emit (ec); ++ ec.Emit (OpCodes.Brfalse_S, null_value); ++ ++ vi.Emit (ec); + PropertyExpr pe = new PropertyExpr (m, pinned_string.Location); + //pe.InstanceExpression = pinned_string; + pe.Resolve (new ResolveContext (ec.MemberContext)).Emit (ec); + + ec.Emit (OpCodes.Add); + vi.EmitAssign (ec); ++ ++ ec.MarkLabel (null_value); + } + + public override void EmitExit (EmitContext ec) +@@ -6660,31 +6675,94 @@ namespace Mono.CSharp { + return new ExpressionEmitter (res, li); + } + +- bool already_fixed = true; +- + // + // Case 4: & object. + // + Unary u = res as Unary; + if (u != null) { ++ bool already_fixed = true; ++ + if (u.Oper == Unary.Operator.AddressOf) { + IVariableReference vr = u.Expr as IVariableReference; + if (vr == null || !vr.IsFixed) { + already_fixed = false; + } + } +- } else if (initializer is Cast) { ++ ++ if (already_fixed) { ++ bc.Report.Error (213, loc, "You cannot use the fixed statement to take the address of an already fixed expression"); ++ return null; ++ } ++ ++ res = Convert.ImplicitConversionRequired (bc, res, li.Type, loc); ++ return new ExpressionEmitter (res, li); ++ } ++ ++ if (initializer is Cast) { + bc.Report.Error (254, initializer.Location, "The right hand side of a fixed statement assignment may not be a cast expression"); + return null; + } + +- if (already_fixed) { +- bc.Report.Error (213, loc, "You cannot use the fixed statement to take the address of an already fixed expression"); ++ // ++ // Case 5: by-ref GetPinnableReference method on the rhs expression ++ // ++ var method = GetPinnableReference (bc, res); ++ if (method == null) { ++ bc.Report.Error (8385, initializer.Location, "The given expression cannot be used in a fixed statement"); ++ return null; ++ } ++ ++ var compiler = bc.Module.Compiler; ++ if (compiler.Settings.Version < LanguageVersion.V_7_3) { ++ bc.Report.FeatureIsNotAvailable (compiler, initializer.Location, "extensible fixed statement"); ++ } ++ ++ method.InstanceExpression = res; ++ res = new Invocation.Predefined (method, null).ResolveLValue (bc, EmptyExpression.OutAccess); ++ if (res == null) ++ return null; ++ ++ ReferenceContainer rType = (ReferenceContainer)method.BestCandidateReturnType; ++ PointerContainer lType = li.Type as PointerContainer; ++ if (rType.Element != lType?.Element) { ++ // CSC: Should be better error code ++ res.Error_ValueCannotBeConverted (bc, lType, false); ++ return null; + } + +- res = Convert.ImplicitConversionRequired (bc, res, li.Type, loc); ++ li.SetIsPointerByRef (); + return new ExpressionEmitter (res, li); + } ++ ++ MethodGroupExpr GetPinnableReference (BlockContext bc, Expression expr) ++ { ++ TypeSpec type = expr.Type; ++ var mexpr = Expression.MemberLookup (bc, false, type, ++ "GetPinnableReference", 0, Expression.MemberLookupRestrictions.ExactArity, loc); ++ ++ if (mexpr == null) ++ return null; ++ ++ var mg = mexpr as MethodGroupExpr; ++ if (mg == null) ++ return null; ++ ++ mg.InstanceExpression = expr; ++ ++ // TODO: handle extension methods ++ Arguments args = new Arguments (0); ++ mg = mg.OverloadResolve (bc, ref args, null, OverloadResolver.Restrictions.None); ++ ++ if (mg == null || mg.BestCandidate.IsStatic || !mg.BestCandidate.IsPublic || mg.BestCandidateReturnType.Kind != MemberKind.ByRef || !mg.BestCandidate.Parameters.IsEmpty) { ++ if (bc.Module.Compiler.Settings.Version > LanguageVersion.V_7_2) { ++ bc.Report.Warning (280, 2, expr.Location, "`{0}' has the wrong signature to be used in extensible fixed statement", mg.GetSignatureForError ()); ++ } ++ ++ return null; ++ } ++ ++ return mg; ++ } + } + + +diff --git a/mcs/mcs/tuples.cs b/mcs/mcs/tuples.cs +index 901efdc9541..0b56859615f 100644 +--- a/mcs/mcs/tuples.cs ++++ b/mcs/mcs/tuples.cs +@@ -267,6 +267,11 @@ namespace Mono.CSharp + this.Location = expr.Location; + } + ++ public TupleLiteralElement Clone (CloneContext clonectx) ++ { ++ return new TupleLiteralElement (Name, Expr.Clone (clonectx), Location); ++ } ++ + public string Name { get; private set; } + public Expression Expr { get; set; } + public Location Location { get; private set; } +@@ -288,6 +293,16 @@ namespace Mono.CSharp + } + } + ++ protected override void CloneTo (CloneContext clonectx, Expression t) ++ { ++ var clone = new List (elements.Count); ++ foreach (var te in elements) ++ clone.Add (te.Clone (clonectx)); ++ ++ TupleLiteral target = (TupleLiteral)t; ++ target.elements = clone; ++ } ++ + public static bool ContainsNoTypeElement (TypeSpec type) + { + var ta = type.TypeArguments; +@@ -432,6 +447,7 @@ namespace Mono.CSharp + { + Expression source; + List targetExprs; ++ List tempExprs; + List variables; + Expression instance; + +@@ -440,6 +456,8 @@ namespace Mono.CSharp + this.source = source; + this.targetExprs = targetExprs; + this.loc = loc; ++ ++ tempExprs = new List (); + } + + public TupleDeconstruct (List variables, Expression source, Location loc) +@@ -447,6 +465,8 @@ namespace Mono.CSharp + this.source = source; + this.variables = variables; + this.loc = loc; ++ ++ tempExprs = new List (); + } + + public override Expression CreateExpressionTree (ResolveContext ec) +@@ -492,6 +512,15 @@ namespace Mono.CSharp + instance = expr_variable.CreateReferenceExpression (rc, loc); + } + ++ var element_srcs = new List (); ++ var src_names = new List (); ++ for (int i = 0; i < target_count; ++i) { ++ var element_src = tupleLiteral == null ? new MemberAccess (instance, NamedTupleSpec.GetElementPropertyName (i)) : tupleLiteral.Elements [i].Expr; ++ element_srcs.Add (element_src); ++ if (element_src is VariableReference) ++ src_names.Add ((element_src as VariableReference)?.Name); ++ } ++ + for (int i = 0; i < target_count; ++i) { + var tle = src_type.TypeArguments [i]; + +@@ -522,8 +551,17 @@ namespace Mono.CSharp + variable.PrepareAssignmentAnalysis ((BlockContext)rc); + } + +- var element_src = tupleLiteral == null ? new MemberAccess (instance, NamedTupleSpec.GetElementPropertyName (i)) : tupleLiteral.Elements [i].Expr; +- targetExprs [i] = new SimpleAssign (targetExprs [i], element_src).Resolve (rc); ++ var element_target = (targetExprs [i] as SimpleName)?.LookupNameExpression (rc, MemberLookupRestrictions.None); ++ ++ if (element_target != null && src_names.Contains ((element_target as VariableReference)?.Name)) { ++ var tempType = element_target.Resolve (rc).Type; ++ ++ var temp = new LocalTemporary (tempType); ++ tempExprs.Add (new SimpleAssign (temp, element_srcs [i]).Resolve (rc)); ++ targetExprs [i] = new SimpleAssign (targetExprs [i], temp).Resolve (rc); ++ } else { ++ targetExprs [i] = new SimpleAssign (targetExprs [i], element_srcs [i]).Resolve (rc); ++ } + } + + eclass = ExprClass.Value; +@@ -557,9 +595,24 @@ namespace Mono.CSharp + if (instance != null) + ((ExpressionStatement)source).EmitStatement (ec); + +- foreach (ExpressionStatement expr in targetExprs) ++ foreach (ExpressionStatement expr in tempExprs) { ++ var temp = (expr as Assign)?.Target as LocalTemporary; ++ if (temp == null) ++ continue; ++ ++ temp.AddressOf (ec, AddressOp.LoadStore); ++ ec.Emit (OpCodes.Initobj, temp.Type); ++ expr.Emit (ec); ++ } ++ ++ foreach (ExpressionStatement expr in targetExprs) { + expr.Emit (ec); + ++ var temp = (expr as Assign)?.Source as LocalTemporary; ++ if (temp != null) ++ temp.Release (ec); ++ } ++ + var ctor = MemberCache.FindMember (type, MemberFilter.Constructor (null), BindingRestriction.DeclaredOnly | BindingRestriction.InstanceOnly) as MethodSpec; + ec.Emit (OpCodes.Newobj, ctor); + } +@@ -574,9 +627,24 @@ namespace Mono.CSharp + + if (instance != null) + ((ExpressionStatement) source).EmitStatement (ec); +- +- foreach (ExpressionStatement expr in targetExprs) ++ ++ foreach (ExpressionStatement expr in tempExprs) { ++ var temp = (expr as Assign)?.Target as LocalTemporary; ++ if (temp == null) ++ continue; ++ ++ temp.AddressOf (ec, AddressOp.LoadStore); ++ ec.Emit (OpCodes.Initobj, temp.Type); ++ expr.EmitStatement (ec); ++ } ++ ++ foreach (ExpressionStatement expr in targetExprs) { + expr.EmitStatement (ec); ++ ++ var temp = (expr as Assign)?.Source as LocalTemporary; ++ if (temp != null) ++ temp.Release (ec); ++ } + } + + public void Emit (EmitContext ec, bool leave_copy) +@@ -594,6 +662,7 @@ namespace Mono.CSharp + + public override void FlowAnalysis (FlowAnalysisContext fc) + { ++ source.FlowAnalysis (fc); + foreach (var expr in targetExprs) + expr.FlowAnalysis (fc); + } +diff --git a/mcs/nunit24/ClientUtilities/util/AssemblyInfo.cs b/mcs/nunit24/ClientUtilities/util/AssemblyInfo.cs +index 919ca07ace3..6489c1b2a58 100644 +--- a/mcs/nunit24/ClientUtilities/util/AssemblyInfo.cs ++++ b/mcs/nunit24/ClientUtilities/util/AssemblyInfo.cs +@@ -5,7 +5,3 @@ + // **************************************************************** + + using System.Reflection; +- +-[assembly: AssemblyDelaySign(false)] +-[assembly: AssemblyKeyFile("../../nunit.snk")] +-[assembly: AssemblyKeyName("")] +diff --git a/mcs/nunit24/ConsoleRunner/nunit-console/AssemblyInfo.cs b/mcs/nunit24/ConsoleRunner/nunit-console/AssemblyInfo.cs +index 919ca07ace3..6489c1b2a58 100644 +--- a/mcs/nunit24/ConsoleRunner/nunit-console/AssemblyInfo.cs ++++ b/mcs/nunit24/ConsoleRunner/nunit-console/AssemblyInfo.cs +@@ -5,7 +5,3 @@ + // **************************************************************** + + using System.Reflection; +- +-[assembly: AssemblyDelaySign(false)] +-[assembly: AssemblyKeyFile("../../nunit.snk")] +-[assembly: AssemblyKeyName("")] +diff --git a/mcs/nunit24/NUnitCore/core/AssemblyInfo.cs b/mcs/nunit24/NUnitCore/core/AssemblyInfo.cs +index 747032c7e63..2f66d80222c 100644 +--- a/mcs/nunit24/NUnitCore/core/AssemblyInfo.cs ++++ b/mcs/nunit24/NUnitCore/core/AssemblyInfo.cs +@@ -7,7 +7,3 @@ using System; + using System.Reflection; + + [assembly: CLSCompliant(true)] +- +-[assembly: AssemblyDelaySign(false)] +-[assembly: AssemblyKeyFile("../../nunit.snk")] +-[assembly: AssemblyKeyName("")] +diff --git a/mcs/nunit24/NUnitCore/interfaces/AssemblyInfo.cs b/mcs/nunit24/NUnitCore/interfaces/AssemblyInfo.cs +index fa86732b3d3..efeaecf1986 100644 +--- a/mcs/nunit24/NUnitCore/interfaces/AssemblyInfo.cs ++++ b/mcs/nunit24/NUnitCore/interfaces/AssemblyInfo.cs +@@ -8,7 +8,3 @@ using System; + using System.Reflection; + + [assembly: CLSCompliant(true)] +- +-[assembly: AssemblyDelaySign(false)] +-[assembly: AssemblyKeyFile("../../nunit.snk")] +-[assembly: AssemblyKeyName("")] +diff --git a/mcs/nunit24/NUnitExtensions/core/AssemblyInfo.cs b/mcs/nunit24/NUnitExtensions/core/AssemblyInfo.cs +index fa86732b3d3..efeaecf1986 100644 +--- a/mcs/nunit24/NUnitExtensions/core/AssemblyInfo.cs ++++ b/mcs/nunit24/NUnitExtensions/core/AssemblyInfo.cs +@@ -8,7 +8,3 @@ using System; + using System.Reflection; + + [assembly: CLSCompliant(true)] +- +-[assembly: AssemblyDelaySign(false)] +-[assembly: AssemblyKeyFile("../../nunit.snk")] +-[assembly: AssemblyKeyName("")] +diff --git a/mcs/nunit24/NUnitExtensions/framework/AssemblyInfo.cs b/mcs/nunit24/NUnitExtensions/framework/AssemblyInfo.cs +index a9553f691cd..2b4b5bfb340 100644 +--- a/mcs/nunit24/NUnitExtensions/framework/AssemblyInfo.cs ++++ b/mcs/nunit24/NUnitExtensions/framework/AssemblyInfo.cs +@@ -8,7 +8,3 @@ using System; + using System.Reflection; + + [assembly: CLSCompliant(true)] +- +-[assembly: AssemblyDelaySign(false)] +-[assembly: AssemblyKeyFile("../../nunit.snk")] +-[assembly: AssemblyKeyName("")] +diff --git a/mcs/nunit24/NUnitFramework/framework/AssemblyInfo.cs b/mcs/nunit24/NUnitFramework/framework/AssemblyInfo.cs +index fa86732b3d3..efeaecf1986 100644 +--- a/mcs/nunit24/NUnitFramework/framework/AssemblyInfo.cs ++++ b/mcs/nunit24/NUnitFramework/framework/AssemblyInfo.cs +@@ -8,7 +8,3 @@ using System; + using System.Reflection; + + [assembly: CLSCompliant(true)] +- +-[assembly: AssemblyDelaySign(false)] +-[assembly: AssemblyKeyFile("../../nunit.snk")] +-[assembly: AssemblyKeyName("")] +diff --git a/mcs/nunit24/NUnitMocks/mocks/AssemblyInfo.cs b/mcs/nunit24/NUnitMocks/mocks/AssemblyInfo.cs +index 599b04ce453..f87ae602810 100644 +--- a/mcs/nunit24/NUnitMocks/mocks/AssemblyInfo.cs ++++ b/mcs/nunit24/NUnitMocks/mocks/AssemblyInfo.cs +@@ -6,7 +6,3 @@ + + using System; + using System.Reflection; +- +-[assembly: AssemblyDelaySign(false)] +-[assembly: AssemblyKeyFile("../../nunit.snk")] +-[assembly: AssemblyKeyName("")] +diff --git a/mcs/tests/dtest-066.cs b/mcs/tests/dtest-066.cs +new file mode 100644 +index 00000000000..893fb40dffa +--- /dev/null ++++ b/mcs/tests/dtest-066.cs +@@ -0,0 +1,13 @@ ++class C ++{ ++ static void Main() ++ { ++ object o = 1; ++ dynamic d = 1; ++ ++ var a = new[] { ++ new { X = o }, ++ new { X = d } ++ }; ++ } ++} +diff --git a/mcs/tests/gtest-647.cs b/mcs/tests/gtest-647.cs +new file mode 100644 +index 00000000000..4aae641f85f +--- /dev/null ++++ b/mcs/tests/gtest-647.cs +@@ -0,0 +1,34 @@ ++using System; ++ ++public class Program ++{ ++ public static int Main () ++ { ++ int B = default (MyStruct?); ++ if (MyStruct.counter != 1) ++ return 1; ++ ++ switch (default (MyStruct?)) { ++ case 0: ++ break; ++ default: ++ return 2; ++ } ++ ++ if (MyStruct.counter != 2) ++ return 4; ++ ++ return 0; ++ } ++ ++ public struct MyStruct ++ { ++ public static int counter; ++ ++ public static implicit operator int (MyStruct? s) ++ { ++ ++counter; ++ return 0; ++ } ++ } ++} +\ No newline at end of file +diff --git a/mcs/tests/test-928.cs b/mcs/tests/test-928.cs +index 90180137957..290ee4d1fb3 100644 +--- a/mcs/tests/test-928.cs ++++ b/mcs/tests/test-928.cs +@@ -15,6 +15,24 @@ unsafe class Program + } + } + ++ public static bool StringNull (string s) ++ { ++ unsafe { ++ fixed (char *a = s) { ++ return a == null; ++ } ++ } ++ } ++ ++ public static bool ArrayNull (int[] a) ++ { ++ unsafe { ++ fixed (int *e = a) { ++ return e == null; ++ } ++ } ++ } ++ + public static int Main () + { + Test (); +@@ -24,6 +42,12 @@ unsafe class Program + if (lv.IsPinned) + return 1; + ++ if (!StringNull (null)) ++ return 1; ++ ++ if (!ArrayNull (null)) ++ return 2; ++ + return 0; + } + } +diff --git a/mcs/tests/test-948.cs b/mcs/tests/test-948.cs +index 34b3ab9a0c4..563e37dc7d5 100644 +--- a/mcs/tests/test-948.cs ++++ b/mcs/tests/test-948.cs +@@ -1,4 +1,4 @@ +-// Compiler options: -langversion:7.2 -unsafe ++// Compiler options: -langversion:7.2 /unsafe + + using System; + +@@ -7,10 +7,16 @@ class X + public static void Main () + { + Span stackSpan = stackalloc int[100]; ++ ++ bool b = false; ++ ++ var r1 = !b ? stackalloc char[1] : throw null; ++ var r2 = b ? throw null : stackalloc char[1]; ++ var r3 = b ? stackalloc char[1] : stackalloc char[2]; + } + ++ // Disables verifier + unsafe void Foo () + { +- + } +-} +\ No newline at end of file ++} +diff --git a/mcs/tests/test-950.cs b/mcs/tests/test-950.cs +new file mode 100644 +index 00000000000..fef764c85cc +--- /dev/null ++++ b/mcs/tests/test-950.cs +@@ -0,0 +1,12 @@ ++using System; ++ ++public class B ++{ ++ public static void Main () ++ { ++ int a = 1_0_3; ++ double b = 0__0e+1_1; ++ int c = 0b0__1_0; ++ int d = 0x0__F_0; ++ } ++} +\ No newline at end of file +diff --git a/mcs/tests/test-960.cs b/mcs/tests/test-960.cs +new file mode 100644 +index 00000000000..ac2a1ca7435 +--- /dev/null ++++ b/mcs/tests/test-960.cs +@@ -0,0 +1,20 @@ ++// Compiler options: -langversion:7.2 ++ ++public class B ++{ ++ private protected enum E ++ { ++ } ++ ++ public int Index { get; protected private set; } ++ ++ internal string S1 { get; private protected set; } ++ ++ protected string S2 { get; private protected set; } ++ ++ private protected int field; ++ ++ public static void Main () ++ { ++ } ++} +\ No newline at end of file +diff --git a/mcs/tests/test-961.cs b/mcs/tests/test-961.cs +new file mode 100644 +index 00000000000..efe19673875 +--- /dev/null ++++ b/mcs/tests/test-961.cs +@@ -0,0 +1,34 @@ ++// Compiler options: -langversion:latest ++ ++using System; ++ ++public static class B { ++ public static void Main () ++ { ++ int lo = 1; ++ Bar (in lo); ++ } ++ ++ public static void Bar (in int arg) ++ { ++ } ++ ++ static void Foo (this in int src) ++ { ++ D p = (in int a) => {}; ++ } ++ ++} ++ ++delegate void D (in int arg); ++ ++class M ++{ ++ int this[in int a] { set { } } ++ public static implicit operator string (in M m) => null; ++ public M (in int arg) { } ++ ++ public void Test2 (in int arg) ++ { ++ } ++} +\ No newline at end of file +diff --git a/mcs/tests/test-anon-123.cs b/mcs/tests/test-anon-123.cs +index 91c72b45afe..45aab27c0a5 100644 +--- a/mcs/tests/test-anon-123.cs ++++ b/mcs/tests/test-anon-123.cs +@@ -1,3 +1,4 @@ ++// Compiler options: -langversion:latest + // Cloning tests + + using System; +@@ -103,7 +104,11 @@ public class C : B + default: + break; + } +- }); ++ }); ++ ++ Test (() => { ++ char ch = default; ++ }); + + var c = new C (); + c.InstanceTests (); +diff --git a/mcs/tests/test-binaryliteral.cs b/mcs/tests/test-binaryliteral.cs +new file mode 100644 +index 00000000000..3d9cc89bcbd +--- /dev/null ++++ b/mcs/tests/test-binaryliteral.cs +@@ -0,0 +1,57 @@ ++ ++class Demo { ++ static int Main () ++ { ++ if (0b1 != 1) ++ return 1; ++ var hex1 = 0x123ul; ++ var bin1 = 0b100100011ul; ++ var bin11 = 0b100100011lu; ++ if (hex1 != bin1) ++ return 2; ++ if (hex1 != bin11) ++ return 3; ++ if (hex1.GetType () != bin1.GetType ()) ++ return 4; ++ if (hex1.GetType () != bin11.GetType ()) ++ return 5; ++ ++ var hex2 = 0x7FFFFFFF; ++ var bin2 = 0b1111111111111111111111111111111; ++ ++ if (hex2 != bin2) ++ return 6; ++ if (hex2.GetType () != bin2.GetType ()) ++ return 7; ++ ++ var hex3 = 0xFFFFFFFF; ++ var bin3 = 0b11111111111111111111111111111111; ++ if (hex3 != bin3) ++ return 8; ++ if (hex3.GetType () != bin3.GetType ()) ++ return 9; ++ ++ var hex4 = 0xFFFFFFFFu; ++ var bin4 = 0b11111111111111111111111111111111u; ++ if (hex4 != bin4) ++ return 10; ++ if (hex4.GetType () != bin4.GetType ()) ++ return 11; ++ ++ var hex5 = 0x7FFFFFFFFFFFFFFF; ++ var bin5 = 0b111111111111111111111111111111111111111111111111111111111111111; ++ if (hex5 != bin5) ++ return 12; ++ if (hex5.GetType () != bin5.GetType ()) ++ return 13; ++ ++ var hex6 = 0xFFFFFFFFFFFFFFFF; ++ var bin6 = 0b1111111111111111111111111111111111111111111111111111111111111111; ++ if (hex6 != bin6) ++ return 14; ++ if (hex6.GetType () != bin6.GetType ()) ++ return 15; ++ ++ return 0; ++ } ++} +\ No newline at end of file +diff --git a/mcs/tests/test-decl-expr-05.cs b/mcs/tests/test-decl-expr-05.cs +index 730fd4278ca..907cde0b8d7 100644 +--- a/mcs/tests/test-decl-expr-05.cs ++++ b/mcs/tests/test-decl-expr-05.cs +@@ -6,6 +6,11 @@ class X + { + arg = s.ToString (); + } ++ ++ while (true && Call (out string s2)) ++ { ++ arg = s2.ToString (); ++ } + } + + static bool Call (out string s) +diff --git a/mcs/tests/test-decl-expr-06.cs b/mcs/tests/test-decl-expr-06.cs +new file mode 100644 +index 00000000000..9734f2ec2a7 +--- /dev/null ++++ b/mcs/tests/test-decl-expr-06.cs +@@ -0,0 +1,17 @@ ++using System; ++ ++public class C ++{ ++ Func f = () => Foo (out int arg); ++ ++ static bool Foo (out int arg) ++ { ++ arg = 2; ++ return false; ++ } ++ ++ public static void Main () ++ { ++ new C (); ++ } ++} +\ No newline at end of file +diff --git a/mcs/tests/test-default-01.cs b/mcs/tests/test-default-01.cs +index 823e33c451b..28aff830cd9 100644 +--- a/mcs/tests/test-default-01.cs ++++ b/mcs/tests/test-default-01.cs +@@ -41,7 +41,11 @@ static class X + static System.Func M4 () + { + return () => default; +- } ++ } ++ ++ static void Foo (II a = default (II), II b = default, II c = (II) null) ++ { ++ } + } + /* + enum E +@@ -49,4 +53,10 @@ enum E + A = default, + B = default + 1 + } +-*/ +\ No newline at end of file ++*/ ++ ++ ++interface II ++{ ++ ++} +\ No newline at end of file +diff --git a/mcs/tests/test-fixed-01.cs b/mcs/tests/test-fixed-01.cs +new file mode 100644 +index 00000000000..4684b0c5a06 +--- /dev/null ++++ b/mcs/tests/test-fixed-01.cs +@@ -0,0 +1,20 @@ ++// Compiler options: -unsafe -langversion:latest ++ ++unsafe class C ++{ ++ public static void Main () ++ { ++ fixed (int* p = new Fixable ()) { ++ System.Console.WriteLine (*p); ++ System.Console.WriteLine (p [2]); ++ } ++ } ++ ++ struct Fixable ++ { ++ public ref int GetPinnableReference () ++ { ++ return ref (new int[] { 1, 2, 3 })[0]; ++ } ++ } ++} +\ No newline at end of file +diff --git a/mcs/tests/test-pattern-13.cs b/mcs/tests/test-pattern-13.cs +new file mode 100644 +index 00000000000..315c7a9e4be +--- /dev/null ++++ b/mcs/tests/test-pattern-13.cs +@@ -0,0 +1,19 @@ ++using System; ++ ++class C : B ++{ ++ ++} ++ ++public class B ++{ ++ public static void Main () ++ { ++ C c = new C (); ++ ++ if (c is B b) ++ { ++ Console.WriteLine (b == null); ++ } ++ } ++} +\ No newline at end of file +diff --git a/mcs/tests/test-ref-07.cs b/mcs/tests/test-ref-07.cs +index 4aa16579752..f17cfb443b5 100644 +--- a/mcs/tests/test-ref-07.cs ++++ b/mcs/tests/test-ref-07.cs +@@ -1,6 +1,6 @@ + // Compiler options: -langversion:latest + +-public readonly partial ref struct Test ++public readonly ref partial struct Test + { + public static void Main () + { +@@ -14,6 +14,11 @@ public readonly partial ref struct Test + } + } + ++ref partial struct Test ++{ ++ ++} ++ + ref struct Second + { + Test field; +diff --git a/mcs/tests/test-ref-11.cs b/mcs/tests/test-ref-11.cs +new file mode 100644 +index 00000000000..8d392a77d07 +--- /dev/null ++++ b/mcs/tests/test-ref-11.cs +@@ -0,0 +1,13 @@ ++class Program ++{ ++ static int x; ++ static int y; ++ ++ public static int Main () ++ { ++ bool b = false; ++ ref int targetBucket = ref b ? ref x : ref y; ++ ++ return 0; ++ } ++} +\ No newline at end of file +diff --git a/mcs/tests/test-ref-12.cs b/mcs/tests/test-ref-12.cs +new file mode 100644 +index 00000000000..786a4162f4f +--- /dev/null ++++ b/mcs/tests/test-ref-12.cs +@@ -0,0 +1,22 @@ ++// Compiler options: -unsafe ++ ++unsafe class X ++{ ++ public static void Main () ++ { ++ void* pointer = null; ++ Bar (ref Foo (ref *(byte*)pointer)); ++ } ++ ++ static int field; ++ ++ static ref int Foo (ref byte b) ++ { ++ return ref field; ++ } ++ ++ static void Bar (ref int i) ++ { ++ ++ } ++} +\ No newline at end of file +diff --git a/mcs/tests/test-tuple-02.cs b/mcs/tests/test-tuple-02.cs +index c0492759452..ab722642aeb 100644 +--- a/mcs/tests/test-tuple-02.cs ++++ b/mcs/tests/test-tuple-02.cs +@@ -26,6 +26,11 @@ class TupleConversions + (string v1, object v2) b = ("a", "b"); + + (int v1, long v2)? x = null; ++ ++ var array = new [] { ++ (name: "A", offset: 0), ++ (name: "B", size: 4) ++ }; + } + + static void Foo (T arg) +diff --git a/mcs/tests/test-tuple-08.cs b/mcs/tests/test-tuple-08.cs +new file mode 100644 +index 00000000000..fd3375b4df6 +--- /dev/null ++++ b/mcs/tests/test-tuple-08.cs +@@ -0,0 +1,24 @@ ++using System; ++using System.Collections.Generic; ++using System.Threading.Tasks; ++ ++class X ++{ ++ public static void Main () ++ { ++ var x = new X (); ++ x.Test ().Wait (); ++ } ++ ++ int a, b; ++ ++ async Task Test () ++ { ++ (a, b) = await Waiting (); ++ } ++ ++ Task<(int, int)> Waiting () ++ { ++ return Task.FromResult ((1, 3)); ++ } ++} +\ No newline at end of file +diff --git a/mcs/tests/test-tuple-10.cs b/mcs/tests/test-tuple-10.cs +new file mode 100644 +index 00000000000..82f4e01ec1f +--- /dev/null ++++ b/mcs/tests/test-tuple-10.cs +@@ -0,0 +1,9 @@ ++using System.Linq; ++ ++class Program { ++ public static int Main () ++ { ++ var l = (from f in (typeof (Program)).GetFields() select (name: f.Name, offset: 0)).ToList(); ++ return 0; ++ } ++} +\ No newline at end of file +diff --git a/mcs/tests/test-tuple-11.cs b/mcs/tests/test-tuple-11.cs +new file mode 100644 +index 00000000000..b2aeb24026c +--- /dev/null ++++ b/mcs/tests/test-tuple-11.cs +@@ -0,0 +1,20 @@ ++using System; ++ ++class Program ++{ ++ public static int Main () ++ { ++ int x = 1; ++ int y = 2; ++ ++ (x, y) = (y, x); ++ ++ if (x != 2) ++ return 1; ++ ++ if (y != 1) ++ return 2; ++ ++ return 0; ++ } ++} +diff --git a/mcs/tests/ver-il-net_4_x.xml b/mcs/tests/ver-il-net_4_x.xml +index 4dbc7042a8a..2bde8270338 100644 +--- a/mcs/tests/ver-il-net_4_x.xml ++++ b/mcs/tests/ver-il-net_4_x.xml +@@ -3168,6 +3168,33 @@ + + + ++ ++ ++ ++ 41 ++ ++ ++ 7 ++ ++ ++ ++ ++ 7 ++ ++ ++ 39 ++ ++ ++ 63 ++ ++ ++ 67 ++ ++ ++ 14 ++ ++ ++ + + + +@@ -11064,7 +11091,7 @@ + + + +- 72 ++ 60 + + + 62 +@@ -19508,7 +19535,7 @@ + + + +- 267 ++ 255 + + + 7 +@@ -19742,7 +19769,7 @@ + + + +- 116 ++ 121 + + + 7 +@@ -20147,6 +20174,21 @@ + + + ++ ++ ++ ++ 99 ++ ++ ++ 7 ++ ++ ++ ++ ++ 22 ++ ++ ++ + + + +@@ -47609,7 +47651,7 @@ + 7 + + +- 73 ++ 78 + + + +@@ -51468,10 +51510,10 @@ + + + +- 20 ++ 12 + + +- 70 ++ 62 + + + 7 +@@ -52148,7 +52190,7 @@ + 14 + + +- 29 ++ 34 + + + 10 +@@ -52359,10 +52401,10 @@ + + + +- 25 ++ 30 + + +- 105 ++ 141 + + + 29 +@@ -52370,6 +52412,12 @@ + + 7 + ++ ++ 32 ++ ++ ++ 45 ++ + + + +@@ -52814,7 +52862,7 @@ + + + +- 16 ++ 103 + + + 2 +@@ -52834,6 +52882,16 @@ + + + ++ ++ ++ ++ 23 ++ ++ ++ 7 ++ ++ ++ + + + +@@ -52858,6 +52916,80 @@ + + + ++ ++ ++ ++ 14 ++ ++ ++ 8 ++ ++ ++ 14 ++ ++ ++ 8 ++ ++ ++ 14 ++ ++ ++ 8 ++ ++ ++ 2 ++ ++ ++ 7 ++ ++ ++ ++ ++ ++ ++ 10 ++ ++ ++ 32 ++ ++ ++ 2 ++ ++ ++ ++ ++ 0 ++ ++ ++ 0 ++ ++ ++ 0 ++ ++ ++ 0 ++ ++ ++ ++ ++ 2 ++ ++ ++ 9 ++ ++ ++ 2 ++ ++ ++ 8 ++ ++ ++ ++ ++ 2 ++ ++ ++ + + + +@@ -54448,7 +54580,7 @@ + 19 + + +- 247 ++ 281 + + + 7 +@@ -54518,6 +54650,9 @@ + + 35 + ++ ++ 4 ++ + + + +@@ -67020,6 +67155,16 @@ + + + ++ ++ ++ ++ 503 ++ ++ ++ 7 ++ ++ ++ + + + +@@ -68641,7 +68786,7 @@ + + + +- 29 ++ 62 + + + 17 +@@ -68654,6 +68799,22 @@ + + + ++ ++ ++ ++ 13 ++ ++ ++ 8 ++ ++ ++ 15 ++ ++ ++ 42 ++ ++ ++ + + + +@@ -68674,6 +68835,9 @@ + + 9 + ++ ++ 2 ++ + + + +@@ -69158,6 +69322,21 @@ + + + ++ ++ ++ ++ 39 ++ ++ ++ 7 ++ ++ ++ ++ ++ 32 ++ ++ ++ + + + +@@ -72564,7 +72743,7 @@ + + + +- 184 ++ 206 + + + 14 +@@ -72750,6 +72929,21 @@ + + + ++ ++ ++ ++ 7 ++ ++ ++ ++ ++ 35 ++ ++ ++ 7 ++ ++ ++ + + + +@@ -73155,6 +73349,11 @@ + + + ++ ++ ++ 6 ++ ++ + + + 18 +@@ -73243,6 +73442,32 @@ + + + ++ ++ ++ ++ 34 ++ ++ ++ 7 ++ ++ ++ ++ ++ ++ ++ 16 ++ ++ ++ 14 ++ ++ ++ 2 ++ ++ ++ 7 ++ ++ ++ + + + +@@ -73482,7 +73707,7 @@ + 32 + + +- 10 ++ 2 + + + 10 +@@ -73491,16 +73716,16 @@ + 23 + + +- 3 ++ 2 + + +- 10 ++ 2 + + +- 3 ++ 2 + + +- 3 ++ 2 + + + 21 +@@ -73527,7 +73752,7 @@ + 7 + + +- 10 ++ 2 + + + 15 +@@ -73569,7 +73794,7 @@ + + + +- 314 ++ 368 + + + 2 +@@ -73761,6 +73986,29 @@ + + + ++ ++ ++ ++ 65 ++ ++ ++ 21 ++ ++ ++ 7 ++ ++ ++ ++ ++ ++ ++ 70 ++ ++ ++ 7 ++ ++ ++ + + + +@@ -73896,4 +74144,4 @@ + + + +- +\ No newline at end of file ++ +diff --git a/msvc/scripts/System.Web.pre b/msvc/scripts/System.Web.pre +index c071bf45bfd..8f8d262597f 100644 +--- a/msvc/scripts/System.Web.pre ++++ b/msvc/scripts/System.Web.pre +@@ -1 +1 @@ +-@MONO@ $(ProjectDir)\..\lib\net_4_x\culevel.exe -o $(ProjectDir)\System.Web\UplevelHelper.cs $(ProjectDir)\UplevelHelperDefinitions.xml ++@MONO@ $([MSBuild]::GetDirectoryNameOfFileAbove($(TargetDir), culevel.exe))\culevel.exe -o $(ProjectDir)\System.Web\UplevelHelper.cs $(ProjectDir)\UplevelHelperDefinitions.xml +diff --git a/msvc/scripts/csproj.tmpl b/msvc/scripts/csproj.tmpl +index 642c9537321..c18b51d334e 100644 +--- a/msvc/scripts/csproj.tmpl ++++ b/msvc/scripts/csproj.tmpl +@@ -17,6 +17,7 @@ + obj-@OUTPUTSUFFIX@ + false + @NOSTDLIB@ ++ @METADATAVERSION@ + @STARTUPOBJECT@ + @NOCONFIG@ + @ALLOWUNSAFE@ +diff --git a/msvc/scripts/genproj.cs b/msvc/scripts/genproj.cs +index 3987abb212b..1440800b2b3 100644 +--- a/msvc/scripts/genproj.cs ++++ b/msvc/scripts/genproj.cs +@@ -27,27 +27,43 @@ public enum Target { + + class SlnGenerator { + public static readonly string NewLine = "\r\n"; //Environment.NewLine; // "\n"; +- public SlnGenerator (string formatVersion = "2012") ++ public SlnGenerator (string slnVersion) + { +- switch (formatVersion) { +- case "2008": +- this.header = MakeHeader ("10.00", "2008"); +- break; +- default: +- this.header = MakeHeader ("12.00", "2012"); +- break; +- } ++ Console.WriteLine("Requested sln version is {0}", slnVersion); ++ this.header = MakeHeader ("12.00", "15", "15.0.0.0"); + } + +- const string project_start = "Project(\"{{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}}\") = \"{0}\", \"{1}\", \"{2}\""; // Note: No need to double up on {} around {2} ++ const string project_start = "Project(\"{0}\") = \"{1}\", \"{2}\", \"{3}\""; // Note: No need to double up on {} around {2} + const string project_end = "EndProject"; + ++ public List profiles = new List { ++ "net_4_x", ++ "monodroid", ++ "monotouch", ++ "monotouch_tv", ++ "monotouch_watch", ++ "orbis", ++ "unreal", ++ "wasm", ++ "winaot", ++ "xammac", ++ }; ++ ++ const string jay_vcxproj_guid = "{5D485D32-3B9F-4287-AB24-C8DA5B89F537}"; ++ const string jay_sln_guid = "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}"; ++ + public List libraries = new List (); + string header; + +- string MakeHeader (string formatVersion, string yearTag) ++ string MakeHeader (string formatVersion, string yearTag, string minimumVersion) + { +- return string.Format ("Microsoft Visual Studio Solution File, Format Version {0}" + NewLine + "# Visual Studio {1}", formatVersion, yearTag); ++ return string.Format ( ++ "Microsoft Visual Studio Solution File, Format Version {0}" + NewLine + ++ "# Visual Studio {1}" + NewLine + ++ "MinimumVisualStudioVersion = {2}", ++ formatVersion, yearTag, ++ minimumVersion ++ ); + } + + public void Add (MsbuildGenerator.VsCsproj vsproj) +@@ -59,6 +75,40 @@ class SlnGenerator { + } + } + ++ private void WriteProjectReference (StreamWriter sln, string prefixGuid, string library, string relativePath, string projectGuid, params string[] dependencyGuids) ++ { ++ sln.WriteLine (project_start, prefixGuid, library, relativePath, projectGuid); ++ ++ foreach (var guid in dependencyGuids) { ++ sln.WriteLine (" ProjectSection(ProjectDependencies) = postProject"); ++ sln.WriteLine (" {0} = {0}", guid); ++ sln.WriteLine (" EndProjectSection"); ++ } ++ ++ sln.WriteLine (project_end); ++ } ++ ++ private void WriteProjectReference (StreamWriter sln, string slnFullPath, MsbuildGenerator.VsCsproj proj) ++ { ++ var unixProjFile = proj.csProjFilename.Replace ("\\", "/"); ++ var fullProjPath = Path.GetFullPath (unixProjFile); ++ var relativePath = MsbuildGenerator.GetRelativePath (slnFullPath, fullProjPath); ++ var dependencyGuids = new string[0]; ++ if (proj.preBuildEvent.Contains ("jay")) ++ dependencyGuids = new [] { jay_vcxproj_guid }; ++ WriteProjectReference(sln, "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}", proj.library, relativePath, proj.projectGuid, dependencyGuids); ++ } ++ ++ private void WriteProjectConfigurationPlatforms (StreamWriter sln, string guid, string platformToBuild) ++ { ++ foreach (var profile in profiles) { ++ sln.WriteLine ("\t\t{0}.Debug|{1}.ActiveCfg = Debug|{2}", guid, profile, platformToBuild); ++ sln.WriteLine ("\t\t{0}.Debug|{1}.Build.0 = Debug|{2}", guid, profile, platformToBuild); ++ sln.WriteLine ("\t\t{0}.Release|{1}.ActiveCfg = Release|{2}", guid, profile, platformToBuild); ++ sln.WriteLine ("\t\t{0}.Release|{1}.Build.0 = Release|{2}", guid, profile, platformToBuild); ++ } ++ } ++ + public void Write (string filename) + { + var fullPath = Path.GetDirectoryName (filename) + "/"; +@@ -66,27 +116,32 @@ class SlnGenerator { + using (var sln = new StreamWriter (filename)) { + sln.WriteLine (); + sln.WriteLine (header); ++ ++ // Manually insert jay's vcxproj. We depend on jay.exe to perform build steps later. ++ WriteProjectReference (sln, jay_sln_guid, "jay", "mcs\\jay\\jay.vcxproj", jay_vcxproj_guid); ++ + foreach (var proj in libraries) { +- var unixProjFile = proj.csProjFilename.Replace ("\\", "/"); +- var fullProjPath = Path.GetFullPath (unixProjFile); +- sln.WriteLine (project_start, proj.library, MsbuildGenerator.GetRelativePath (fullPath, fullProjPath), proj.projectGuid); +- sln.WriteLine (project_end); ++ WriteProjectReference (sln, fullPath, proj); + } ++ + sln.WriteLine ("Global"); + + sln.WriteLine ("\tGlobalSection(SolutionConfigurationPlatforms) = preSolution"); +- sln.WriteLine ("\t\tDebug|Any CPU = Debug|Any CPU"); +- sln.WriteLine ("\t\tRelease|Any CPU = Release|Any CPU"); ++ foreach (var profile in profiles) { ++ sln.WriteLine ("\t\tDebug|{0} = Debug|{0}", profile); ++ sln.WriteLine ("\t\tRelease|{0} = Release|{0}", profile); ++ } + sln.WriteLine ("\tEndGlobalSection"); + + sln.WriteLine ("\tGlobalSection(ProjectConfigurationPlatforms) = postSolution"); ++ ++ // Manually insert jay's configurations because they are different ++ WriteProjectConfigurationPlatforms (sln, jay_vcxproj_guid, "Win32"); ++ + foreach (var proj in libraries) { +- var guid = proj.projectGuid; +- sln.WriteLine ("\t\t{0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU", guid); +- sln.WriteLine ("\t\t{0}.Debug|Any CPU.Build.0 = Debug|Any CPU", guid); +- sln.WriteLine ("\t\t{0}.Release|Any CPU.ActiveCfg = Release|Any CPU", guid); +- sln.WriteLine ("\t\t{0}.Release|Any CPU.Build.0 = Release|Any CPU", guid); ++ WriteProjectConfigurationPlatforms (sln, proj.projectGuid, "Any CPU"); + } ++ + sln.WriteLine ("\tEndGlobalSection"); + + sln.WriteLine ("\tGlobalSection(SolutionProperties) = preSolution"); +@@ -634,6 +689,7 @@ class MsbuildGenerator { + public List projReferences = new List (); + public string library; + public MsbuildGenerator MsbuildGenerator; ++ public string preBuildEvent, postBuildEvent; + } + + public VsCsproj Csproj; +@@ -682,7 +738,7 @@ class MsbuildGenerator { + fx_version = "4.0"; + profile = "net_4_0"; + } else if (response.Contains (profile_4_x)) { +- fx_version = "4.5"; ++ fx_version = "4.6.2"; + profile = "net_4_x"; + } + } +@@ -882,6 +938,26 @@ class MsbuildGenerator { + + bool basic_or_build = (library.Contains ("-basic") || library.Contains ("-build")); + ++ // If an EXE is built with nostdlib, it won't work unless run with mono.exe. This stops our build steps ++ // from working in visual studio (because we already replace @MONO@ with '' on Windows.) ++ ++ if (Target != Target.Library) ++ StdLib = true; ++ ++ // We have our target framework set to 4.5 in many places because broken scripts check for files with 4.5 ++ // in the path, even though we compile code that uses 4.6 features. So we need to manually fix that here. ++ ++ if (fx_version == "4.5") ++ fx_version = "4.6.2"; ++ ++ // The VS2017 signing system fails to sign using this key for some reason, so for now, ++ // just disable code signing for the nunit assemblies. It's not important. ++ // I'd rather fix this by updating the makefiles but it seems to be impossible to disable ++ // code signing in our make system... ++ ++ if (StrongNameKeyFile?.Contains("nunit.snk") ?? false) ++ StrongNameKeyFile = null; ++ + // + // Replace the template values + // +@@ -894,6 +970,9 @@ class MsbuildGenerator { + " {0}", + StrongNameKeyFile, StrongNameDelaySign ? " true" + NewLine : ""); + } ++ ++ string assemblyName = Path.GetFileNameWithoutExtension (output_name); ++ + Csproj.output = template. + Replace ("@OUTPUTTYPE@", Target == Target.Library ? "Library" : "Exe"). + Replace ("@SIGNATURE@", strongNameSection). +@@ -906,7 +985,7 @@ class MsbuildGenerator { + Replace ("@NOCONFIG@", "" + (!load_default_config).ToString () + ""). + Replace ("@ALLOWUNSAFE@", Unsafe ? "true" : ""). + Replace ("@FX_VERSION", fx_version). +- Replace ("@ASSEMBLYNAME@", Path.GetFileNameWithoutExtension (output_name)). ++ Replace ("@ASSEMBLYNAME@", assemblyName). + Replace ("@OUTPUTDIR@", build_output_dir). + Replace ("@OUTPUTSUFFIX@", Path.GetFileName (build_output_dir)). + Replace ("@DEFINECONSTANTS@", defines.ToString ()). +@@ -920,7 +999,11 @@ class MsbuildGenerator { + Replace ("@ADDITIONALLIBPATHS@", String.Empty). + Replace ("@RESOURCES@", resources.ToString ()). + Replace ("@OPTIMIZE@", Optimize ? "true" : "false"). +- Replace ("@SOURCES@", sources.ToString ()); ++ Replace ("@SOURCES@", sources.ToString ()). ++ Replace ("@METADATAVERSION@", assemblyName == "mscorlib" ? "Mono" : ""); ++ ++ Csproj.preBuildEvent = prebuild; ++ Csproj.postBuildEvent = postbuild; + + //Console.WriteLine ("Generated {0}", ofile.Replace ("\\", "/")); + using (var o = new StreamWriter (generatedProjFile)) { +@@ -939,15 +1022,13 @@ class MsbuildGenerator { + if (q != -1) + target = target + Load (library.Substring (0, q) + suffix); + +- if (target.IndexOf ("@MONO@") != -1){ +- target_unix = target.Replace ("@MONO@", "mono").Replace ("@CAT@", "cat"); +- target_windows = target.Replace ("@MONO@", "").Replace ("@CAT@", "type"); +- } else { +- target_unix = target.Replace ("jay.exe", "jay"); +- target_windows = target; +- } ++ target_unix = target.Replace ("@MONO@", "mono").Replace ("@CAT@", "cat"); ++ target_windows = target.Replace ("@MONO@", "").Replace ("@CAT@", "type"); ++ ++ target_unix = target_unix.Replace ("\\jay\\jay.exe", "\\jay\\jay\\jay"); ++ + target_unix = target_unix.Replace ("@COPY@", "cp"); +- target_windows = target_unix.Replace ("@COPY@", "copy"); ++ target_windows = target_windows.Replace ("@COPY@", "copy"); + + target_unix = target_unix.Replace ("\r", ""); + const string condition_unix = "Condition=\" '$(OS)' != 'Windows_NT' \""; -- 2.45.2