diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
index 8c48a20e744d12..9ee93ce98120df 100644
--- a/.config/dotnet-tools.json
+++ b/.config/dotnet-tools.json
@@ -15,7 +15,7 @@
]
},
"microsoft.dotnet.xharness.cli": {
- "version": "1.0.0-prerelease.21201.1",
+ "version": "1.0.0-prerelease.21209.2",
"commands": [
"xharness"
]
diff --git a/Directory.Build.props b/Directory.Build.props
index be3d42e18ba93f..4ee7e1db360f89 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -233,7 +233,7 @@
MIT
$(CopyrightNetFoundation)
$(MSBuildThisFileDirectory)THIRD-PARTY-NOTICES.TXT
- https://go.microsoft.com/fwlink/?LinkID=799421
+ https://go.microsoft.com/fwlink/?LinkID=799421
true
diff --git a/docs/design/mono/mobile-runtimeconfig-json.md b/docs/design/mono/mobile-runtimeconfig-json.md
new file mode 100644
index 00000000000000..239826da05220e
--- /dev/null
+++ b/docs/design/mono/mobile-runtimeconfig-json.md
@@ -0,0 +1,142 @@
+# Mobile runtimeconfig.json host configuration
+
+## Motivation
+
+`runtimeconfig.json` is a file used by .NET 5+ applications to pass arbitrary configuration parameters via the application host to the .NET runtime. On mobile and WebAssembly, we would like to support passing configuration properties from the Mono embedder to the runtime.
+
+To minimize the impact on the app startup time, the design constraints are as follows:
+1. Don’t parse JSON at runtime during application startup
+2. Don’t need to support shared framework configuration parameters
+3. Don't need to support the desktop host environment variables, startup hooks, or other configuration mechanisms that do not make sense on mobile.
+4. This is separate from the key/value set passed to `monovm_initialize`/`coreclr_initialize` (ie we will not pass the additional properties via `monovm_initialize` - just using this new mechanism). Things like the TPA list, additional probing paths, PINVOKE_OVERRIDE, etc will be addressed by an evolution of `monovm_initialize` - https://github.com/dotnet/runtime/issues/48416
+
+## Design Overview
+
+We break up runtimeconfig.json loading into two parts:
+1. A new MSBuild task called `RuntimeConfigParser` will run after the `runtimeconfig.json` is created by the `dotnet build` process. The task will convert the properties and their values into a binary blob format. The resulting `runtimeconfig.bin` file will be bundled with the application.
+2. The runtime will expose a new API entrypoint `monovm_runtimeconfig_initialize` that gets either a path to pass to `mono_file_map_open` or a pointer to the blob in memory. When called, the runtime will read the binary data and populate the managed AppContext with the properties.
+
+We will only use the `runtimeOptions→configProperties` json key. Its content is a JSON dictionary with string keys and string/bool/numeric values. We convert the values to strings when we store them in the binary runtimeconfig.bin, which is the same way they are treated by the default host.
+
+The runtime assumes that the properties passed via `monovm_initialize` and `monovm_runtimeconfig_initialize` will be different. To ensure this, the provided MSBuild task will be passed a list of property names that the embedder promises it will pass to `monovm_initialize`. The MSBuild task will check that `runtimeconfig.json` does not set any of those same properties. If there is a duplicate, error out.
+
+All properties set in either the `runtimeconfig.json` or set via `monovm_initialize` will be propagated to the managed `AppContext`. Mono will also check for properties it supports in the runtime itself and make use of them as appropriate.
+
+## Design Details
+
+### Encoded file generation
+
+ The runtime pack will provide an MSBuild task called RuntimeConfigParserTask to generate the encoded file. The generator checks for duplicate property keys (by comparing the keys in the json file with an input list of properties that the embedder promises to pass to `monovm_initialize`).
+
+#### Task Contract:
+
+The task will take 3 input arguments:
+1. The path to the `runtimeconfig.json` file.
+2. The name of the destination file to be written in the encoded format.
+3. An item list (`ITaskItem[]`) that is the name of the properties that the embedder will set on `monovm_initialize`.
+
+The task should:
+1. Parse the given input file and create a dictionary from the configProperties key.
+2. Compare the keys from the input file with the names given in the item list. If there are any duplicates, return an MSBuild Error.
+3. Generate the output file.
+
+#### Example of the usage of the task:
+
+ ```
+
+
+
+
+
+
+ ```
+
+### The encoded runtimeconfig format
+
+The format is:
+1. There will be an (1- to 4-byte) ECMA-335 II.23.2 compressed unsigned integer count = N, indicating the number of key-value pairs.
+2. It will have 2xN ECMA-335 SerString UTF8 strings (that is, each string is preceded by its length stored in the compressed unsigned integer format): Each key followed by its value.
+
+Sample input
+```
+{
+ "runtimeOptions": {
+ "configProperties": {
+ "key1": "value1",
+ "key2": "value2"
+ }
+ }
+}
+```
+
+Sample output (as hexdump -C bytes)
+```
+00000000 02 04 6b 65 79 31 06 76 61 6c 75 65 31 04 6b 65 |..key1.value1.ke|
+00000010 79 32 06 76 61 6c 75 65 32 |y2.value2|
+00000019
+```
+
+### New embedding API entrypoint
+
+We want at least 2 ways to pass data in: either ask the runtime to open the file, or give it a pointer to the data in memory. Also, we need some way to cleanup.
+
+```
+struct MonovmRuntimeConfigArguments {
+ uint32_t kind; // 0 = Path of runtimeconfig.bin file, 1 = pointer to the blob data, >= 2 reserved
+ union {
+ struct {
+ const char *path; // null terminated absolute path
+ } name;
+ struct {
+ const char *data;
+ uint32_t data_len;
+ } data;
+ } runtimeconfig;
+};
+
+typedef void (*MonovmRuntimeConfigArgumentsCleanup)(MonovmRuntimeConfigArguments *args, void* user_data);
+
+MONO_API void
+monovm_runtimeconfig_initialize (MonovmRuntimeConfigArguments *args, MonovmRuntimeConfigArgumentsCleanup cleanup_fn, void* user_data);
+```
+
+This declaration should live in the unstable header. `monovm_runtimeconfig_initialize` should be called before `monovm_initialize`.
+
+#### Example of the usage of `monovm_runtimeconfig_initialize`
+
+```
+void
+cleanup_runtime_config (MonovmRuntimeConfigArguments *args, void *user_data)
+{
+ free (args);
+ free (user_data); // This may not be needed, depending on if there is anything needs to be freed.
+}
+
+int
+mono_droid_runtime_init (const char* executable, int managed_argc, char* managed_argv[])
+{
+
+ ......
+
+ MonovmRuntimeConfigArguments *arg = (MonovmRuntimeConfigArguments *)malloc (sizeof (MonovmRuntimeConfigArguments));
+ arg->kind = 0;
+ arg->runtimeconfig.name.path = "path_to_generated_binary_file";
+ monovm_runtimeconfig_initialize (arg, cleanup_runtime_config, NULL);
+
+ monovm_initialize(......);
+ ......
+
+}
+```
+
+### Register and install runtime properties
+
+`monovm_runtimeconfig_initialize` will register the type `MonovmRuntimeConfigArguments` variable with the runtime. If given the path of the runtimeconfig.bin file, the runtime will read the binary data from the file, otherwise, it will parse the binary data from memory. The properties will be combined with the ones registered by `monovm_initialize` and used to initialize System.AppContext.
+
+### Cleanup function
+
+The `MonovmRuntimeConfigArguments*` will be stored in the runtime between `monovm_runtimeconfig_initialize` and `mono_jit_init_version`. The embedder should not dispose of the arguments after calling `monovm_runtimeconfig_initialize`. Instead the runtime will call the `cleanup_fn` that is passed to `monovm_runtimeconfig_initialize` at soon after it has initialized the managed property list in `System.AppContext` (which happens as part of `mono_jit_init_version`).
diff --git a/docs/workflow/building/libraries/webassembly-instructions.md b/docs/workflow/building/libraries/webassembly-instructions.md
index 315611d1ded9d2..42004629c15439 100644
--- a/docs/workflow/building/libraries/webassembly-instructions.md
+++ b/docs/workflow/building/libraries/webassembly-instructions.md
@@ -4,7 +4,10 @@
If you haven't already done so, please read [this document](../../README.md#Build_Requirements) to understand the build requirements for your operating system.
-The Emscripten SDK (emsdk) needs to be installed. Follow the installation guide [here](https://emscripten.org/docs/getting_started/downloads.html#sdk-download-and-install) or run `make -C src/mono/wasm provision-wasm` to install emsdk into `src/mono/wasm/emsdk`.
+The **correct version** of Emscripten SDK (emsdk) needs to be installed.
+* Run `make -C src/mono/wasm provision-wasm` to install emsdk into `src/mono/wasm/emsdk`.
+* Alternatively follow the [installation guide](https://emscripten.org/docs/getting_started/downloads.html#sdk-download-and-install).
+Do not install `latest` but rather specific version e.g. `./emsdk install 2.0.12`. See [emscripten-version.txt](..\..\..\..\src\mono\wasm\emscripten-version.txt)
Once installed the `EMSDK_PATH` environment variable needs to be set:
diff --git a/docs/workflow/testing/libraries/filtering-tests.md b/docs/workflow/testing/libraries/filtering-tests.md
index 84fc56997b4fb6..96beabad398cd9 100644
--- a/docs/workflow/testing/libraries/filtering-tests.md
+++ b/docs/workflow/testing/libraries/filtering-tests.md
@@ -68,6 +68,24 @@ This attribute returns the 'failing' category, which is disabled by default.
```
Use this attribute over test methods to skip failing tests only on the specific platforms and the specific target frameworks.
+#### SkipOnPlatformAttribute
+This attribute is intended to disable a test permanently on a platform where an API is not available or there is an intentional difference in behavior in between the tested platform and the skipped platform.
+
+This attribute can be applied either to a test assembly/class (will disable all the tests in that assembly/class) or to a test method. It allows multiple usages on the same member.
+
+```cs
+[SkipOnPlatform(TestPlatforms platforms, string reason)]
+```
+
+Use this attribute over test methods to skip tests only on the specific target platforms. The reason parameter doesn't affect the traits but we rather always use it so that when we see this attribute we know why it is being skipped on that platform.
+
+If it needs to be skipped in multiple platforms and the reasons are different please use two attributes on the same test so that you can specify different reasons for each platform.
+
+When you add the attribute on the whole test assembly it's a good idea to also add `true ` to the test .csproj.
+That allows the CI build to skip sending this test assembly to Helix completely since it'd run zero tests anyway.
+
+**Currently these are the [Test Platforms](https://github.com/dotnet/arcade/blob/master/src/Microsoft.DotNet.XUnitExtensions/src/TestPlatforms.cs) that we support through our test execution infrastructure**
+
#### SkipOnTargetFrameworkAttribute
This attribute is intended to disable a test permanently on a framework where an API is not available or there is an intentional difference in behavior in between the tested framework and the skipped framework.
@@ -80,7 +98,7 @@ Use this attribute over test methods to skip tests only on the specific target f
If it needs to be skipped in multiple frameworks and the reasons are different please use two attributes on the same test so that you can specify different reasons for each framework.
-**Currently this are the [Framework Monikers](https://github.com/dotnet/arcade/blob/master/src/Microsoft.DotNet.XUnitExtensions/src/TargetFrameworkMonikers.cs#L23-L26) that we support through our test execution infrastructure**
+**Currently these are the [Framework Monikers](https://github.com/dotnet/arcade/blob/master/src/Microsoft.DotNet.XUnitExtensions/src/TargetFrameworkMonikers.cs#L23-L26) that we support through our test execution infrastructure**
#### ConditionalFactAttribute
Use this attribute to run the test only when a condition is `true`. This attribute is used when `ActiveIssueAttribute` or `SkipOnTargetFrameworkAttribute` are not flexible enough due to needing to run a custom logic at test time. This test behaves as a `[Fact]` test that has no test data passed in as a parameter.
diff --git a/docs/workflow/testing/libraries/testing-wasm.md b/docs/workflow/testing/libraries/testing-wasm.md
index 242e6c9cee4a90..f060a00f9b4588 100644
--- a/docs/workflow/testing/libraries/testing-wasm.md
+++ b/docs/workflow/testing/libraries/testing-wasm.md
@@ -144,6 +144,12 @@ At the moment supported values are:
By default, `chrome` browser is used.
+## Debugging
+
+### Getting more information
+
+- Line numbers: add `/p:DebuggerSupport=true` to the command line, for `Release` builds. It's enabled by default for `Debug` builds.
+
## Kicking off outer loop tests from GitHub Interface
Add the following to the comment of a PR.
diff --git a/docs/workflow/testing/libraries/testing.md b/docs/workflow/testing/libraries/testing.md
index 9ab30e12be41ad..2182a959a2f8ee 100644
--- a/docs/workflow/testing/libraries/testing.md
+++ b/docs/workflow/testing/libraries/testing.md
@@ -1,6 +1,6 @@
# Testing Libraries
-We use the OSS testing framework [xunit](http://xunit.github.io/).
+We use the OSS testing framework [xunit](https://github.com/xunit/xunit).
To build the tests and run them you can call the libraries build script.
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 33d6d5e04e6127..f3150e21229986 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -1,74 +1,74 @@
-
+
https://github.com/dotnet/icu
- 29647ace51f6bb8085326ff137525f7a6d89d726
+ 8d8a9f44bf31bc0cb039619e508e46cf85c08768
-
+
https://github.com/dotnet/arcade
- 1bfe91238cb39b9620b878b8f1bf0c789324b4cd
+ 28d9452d7e2ae4e98a1df735b90b03d3cac1f4e7
-
+
https://github.com/dotnet/arcade
- 1bfe91238cb39b9620b878b8f1bf0c789324b4cd
+ 28d9452d7e2ae4e98a1df735b90b03d3cac1f4e7
-
+
https://github.com/dotnet/arcade
- 1bfe91238cb39b9620b878b8f1bf0c789324b4cd
+ 28d9452d7e2ae4e98a1df735b90b03d3cac1f4e7
-
+
https://github.com/dotnet/arcade
- 1bfe91238cb39b9620b878b8f1bf0c789324b4cd
+ 28d9452d7e2ae4e98a1df735b90b03d3cac1f4e7
-
+
https://github.com/dotnet/arcade
- 1bfe91238cb39b9620b878b8f1bf0c789324b4cd
+ 28d9452d7e2ae4e98a1df735b90b03d3cac1f4e7
-
+
https://github.com/dotnet/arcade
- 1bfe91238cb39b9620b878b8f1bf0c789324b4cd
+ 28d9452d7e2ae4e98a1df735b90b03d3cac1f4e7
-
+
https://github.com/dotnet/arcade
- 1bfe91238cb39b9620b878b8f1bf0c789324b4cd
+ 28d9452d7e2ae4e98a1df735b90b03d3cac1f4e7
-
+
https://github.com/dotnet/arcade
- 1bfe91238cb39b9620b878b8f1bf0c789324b4cd
+ 28d9452d7e2ae4e98a1df735b90b03d3cac1f4e7
-
+
https://github.com/dotnet/arcade
- 1bfe91238cb39b9620b878b8f1bf0c789324b4cd
+ 28d9452d7e2ae4e98a1df735b90b03d3cac1f4e7
-
+
https://github.com/dotnet/arcade
- 1bfe91238cb39b9620b878b8f1bf0c789324b4cd
+ 28d9452d7e2ae4e98a1df735b90b03d3cac1f4e7
-
+
https://github.com/dotnet/arcade
- 1bfe91238cb39b9620b878b8f1bf0c789324b4cd
+ 28d9452d7e2ae4e98a1df735b90b03d3cac1f4e7
-
+
https://github.com/dotnet/arcade
- 1bfe91238cb39b9620b878b8f1bf0c789324b4cd
+ 28d9452d7e2ae4e98a1df735b90b03d3cac1f4e7
-
+
https://github.com/dotnet/arcade
- 1bfe91238cb39b9620b878b8f1bf0c789324b4cd
+ 28d9452d7e2ae4e98a1df735b90b03d3cac1f4e7
-
+
https://github.com/dotnet/arcade
- 1bfe91238cb39b9620b878b8f1bf0c789324b4cd
+ 28d9452d7e2ae4e98a1df735b90b03d3cac1f4e7
-
+
https://github.com/dotnet/arcade
- 1bfe91238cb39b9620b878b8f1bf0c789324b4cd
+ 28d9452d7e2ae4e98a1df735b90b03d3cac1f4e7
-
+
https://github.com/dotnet/arcade
- 1bfe91238cb39b9620b878b8f1bf0c789324b4cd
+ 28d9452d7e2ae4e98a1df735b90b03d3cac1f4e7
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
@@ -94,121 +94,121 @@
https://github.com/microsoft/vstest
140434f7109d357d0158ade9e5164a4861513965
-
+
https://github.com/dotnet/runtime-assets
- 055ed026132a7070e41629cfb5e410f0fcbdf948
+ f071377c4c5db727bb65abc878877ccf89f67ac1
-
+
https://github.com/dotnet/runtime-assets
- 055ed026132a7070e41629cfb5e410f0fcbdf948
+ f071377c4c5db727bb65abc878877ccf89f67ac1
-
+
https://github.com/dotnet/runtime-assets
- 055ed026132a7070e41629cfb5e410f0fcbdf948
+ f071377c4c5db727bb65abc878877ccf89f67ac1
-
+
https://github.com/dotnet/runtime-assets
- 055ed026132a7070e41629cfb5e410f0fcbdf948
+ f071377c4c5db727bb65abc878877ccf89f67ac1
-
+
https://github.com/dotnet/runtime-assets
- 055ed026132a7070e41629cfb5e410f0fcbdf948
+ f071377c4c5db727bb65abc878877ccf89f67ac1
-
+
https://github.com/dotnet/runtime-assets
- 055ed026132a7070e41629cfb5e410f0fcbdf948
+ f071377c4c5db727bb65abc878877ccf89f67ac1
-
+
https://github.com/dotnet/runtime-assets
- 055ed026132a7070e41629cfb5e410f0fcbdf948
+ f071377c4c5db727bb65abc878877ccf89f67ac1
-
+
https://github.com/dotnet/runtime-assets
- 055ed026132a7070e41629cfb5e410f0fcbdf948
+ f071377c4c5db727bb65abc878877ccf89f67ac1
-
+
https://github.com/dotnet/runtime-assets
- 055ed026132a7070e41629cfb5e410f0fcbdf948
+ f071377c4c5db727bb65abc878877ccf89f67ac1
-
+
https://github.com/dotnet/llvm-project
- a2bf9755287bdd3dcf998e41042e79dfd0136c85
+ 389fd50958bf18627d83fa63ab6d627a9fe82042
-
+
https://github.com/dotnet/llvm-project
- a2bf9755287bdd3dcf998e41042e79dfd0136c85
+ 389fd50958bf18627d83fa63ab6d627a9fe82042
-
+
https://github.com/dotnet/llvm-project
- a2bf9755287bdd3dcf998e41042e79dfd0136c85
+ 389fd50958bf18627d83fa63ab6d627a9fe82042
-
+
https://github.com/dotnet/llvm-project
- a2bf9755287bdd3dcf998e41042e79dfd0136c85
+ 389fd50958bf18627d83fa63ab6d627a9fe82042
-
+
https://github.com/dotnet/llvm-project
- a2bf9755287bdd3dcf998e41042e79dfd0136c85
+ 389fd50958bf18627d83fa63ab6d627a9fe82042
-
+
https://github.com/dotnet/llvm-project
- a2bf9755287bdd3dcf998e41042e79dfd0136c85
+ 389fd50958bf18627d83fa63ab6d627a9fe82042
-
+
https://github.com/dotnet/llvm-project
- a2bf9755287bdd3dcf998e41042e79dfd0136c85
+ 389fd50958bf18627d83fa63ab6d627a9fe82042
-
+
https://github.com/dotnet/llvm-project
- a2bf9755287bdd3dcf998e41042e79dfd0136c85
+ 389fd50958bf18627d83fa63ab6d627a9fe82042
https://github.com/dotnet/runtime
38017c3935de95d0335bac04f4901ddfc2718656
-
+
https://github.com/dotnet/runtime
- 102d1e856c7e0e553abeec937783da5debed73ad
+ 355eff52bed00e7ca9d4a6d769ddbe2bbadbea47
-
+
https://github.com/dotnet/runtime
- 102d1e856c7e0e553abeec937783da5debed73ad
+ 355eff52bed00e7ca9d4a6d769ddbe2bbadbea47
-
+
https://github.com/dotnet/runtime
- 102d1e856c7e0e553abeec937783da5debed73ad
+ 355eff52bed00e7ca9d4a6d769ddbe2bbadbea47
-
+
https://github.com/dotnet/runtime
- 102d1e856c7e0e553abeec937783da5debed73ad
+ 355eff52bed00e7ca9d4a6d769ddbe2bbadbea47
-
+
https://github.com/dotnet/runtime
- 102d1e856c7e0e553abeec937783da5debed73ad
+ 355eff52bed00e7ca9d4a6d769ddbe2bbadbea47
-
+
https://github.com/dotnet/runtime
- 102d1e856c7e0e553abeec937783da5debed73ad
+ 355eff52bed00e7ca9d4a6d769ddbe2bbadbea47
-
+
https://github.com/dotnet/runtime
- 102d1e856c7e0e553abeec937783da5debed73ad
+ 355eff52bed00e7ca9d4a6d769ddbe2bbadbea47
https://github.com/mono/linker
388fef00320370785b08bbc42dda4a87f3fa38ab
-
+
https://github.com/dotnet/xharness
- c2c34bf7fdeb5a89e83817ced9a1a2c3c4cfc15c
+ b2297d610df1ae15fc7ba8bd8c9bc0a7192aaefa
-
+
https://github.com/dotnet/xharness
- c2c34bf7fdeb5a89e83817ced9a1a2c3c4cfc15c
+ b2297d610df1ae15fc7ba8bd8c9bc0a7192aaefa
-
+
https://github.com/dotnet/arcade
- 1bfe91238cb39b9620b878b8f1bf0c789324b4cd
+ 28d9452d7e2ae4e98a1df735b90b03d3cac1f4e7
diff --git a/eng/Versions.props b/eng/Versions.props
index 16f6260879c6e3..fd8262eb0e5173 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -49,28 +49,28 @@
3.9.0-5.final
3.9.0-5.final
- 6.0.0-beta.21203.1
- 6.0.0-beta.21203.1
- 6.0.0-beta.21203.1
- 6.0.0-beta.21203.1
- 6.0.0-beta.21203.1
- 6.0.0-beta.21203.1
- 2.5.1-beta.21203.1
- 6.0.0-beta.21203.1
- 6.0.0-beta.21203.1
- 6.0.0-beta.21203.1
- 6.0.0-beta.21203.1
- 6.0.0-beta.21203.1
- 6.0.0-beta.21203.1
+ 6.0.0-beta.21209.17
+ 6.0.0-beta.21209.17
+ 6.0.0-beta.21209.17
+ 6.0.0-beta.21209.17
+ 6.0.0-beta.21209.17
+ 6.0.0-beta.21209.17
+ 2.5.1-beta.21209.17
+ 6.0.0-beta.21209.17
+ 6.0.0-beta.21209.17
+ 6.0.0-beta.21209.17
+ 6.0.0-beta.21209.17
+ 6.0.0-beta.21209.17
+ 6.0.0-beta.21209.17
5.9.0-preview.2
6.0.0-alpha.1.20612.4
- 6.0.0-preview.4.21178.6
- 6.0.0-preview.4.21178.6
+ 6.0.0-preview.4.21211.7
+ 6.0.0-preview.4.21211.7
3.1.0
- 6.0.0-preview.4.21178.6
+ 6.0.0-preview.4.21211.7
1.2.0-beta.304
4.5.1
@@ -98,24 +98,24 @@
4.7.0
4.7.0
4.7.0
- 6.0.0-preview.4.21178.6
- 6.0.0-preview.4.21178.6
+ 6.0.0-preview.4.21211.7
+ 6.0.0-preview.4.21211.7
4.3.0
4.5.4
4.5.0
1.1.1
4.3.0
- 6.0.0-preview.4.21178.6
+ 6.0.0-preview.4.21211.7
- 6.0.0-beta.21174.2
- 6.0.0-beta.21174.2
- 6.0.0-beta.21174.2
- 6.0.0-beta.21174.2
- 6.0.0-beta.21174.2
- 6.0.0-beta.21174.2
- 6.0.0-beta.21174.2
- 6.0.0-beta.21174.2
- 6.0.0-beta.21174.2
+ 6.0.0-beta.21212.1
+ 6.0.0-beta.21212.1
+ 6.0.0-beta.21212.1
+ 6.0.0-beta.21212.1
+ 6.0.0-beta.21212.1
+ 6.0.0-beta.21212.1
+ 6.0.0-beta.21212.1
+ 6.0.0-beta.21212.1
+ 6.0.0-beta.21212.1
99.99.99-master-20210317.2
99.99.99-master-20210317.2
@@ -148,8 +148,8 @@
1.0.1-prerelease-00006
16.9.0-preview-20201201-01
- 1.0.0-prerelease.21201.1
- 1.0.0-prerelease.21201.1
+ 1.0.0-prerelease.21209.2
+ 1.0.0-prerelease.21209.2
2.4.1
2.4.2
1.3.0
@@ -161,16 +161,16 @@
6.0.100-preview.2.21205.2
- 6.0.0-preview.4.21179.1
+ 6.0.0-preview.4.21205.1
- 9.0.1-alpha.1.21179.2
- 9.0.1-alpha.1.21179.2
- 9.0.1-alpha.1.21179.2
- 9.0.1-alpha.1.21179.2
- 9.0.1-alpha.1.21179.2
- 9.0.1-alpha.1.21179.2
- 9.0.1-alpha.1.21179.2
- 9.0.1-alpha.1.21179.2
+ 9.0.1-alpha.1.21205.1
+ 9.0.1-alpha.1.21205.1
+ 9.0.1-alpha.1.21205.1
+ 9.0.1-alpha.1.21205.1
+ 9.0.1-alpha.1.21205.1
+ 9.0.1-alpha.1.21205.1
+ 9.0.1-alpha.1.21205.1
+ 9.0.1-alpha.1.21205.1
diff --git a/eng/common/cross/build-android-rootfs.sh b/eng/common/cross/build-android-rootfs.sh
index 42516bbeebc3f4..c29c8267e7a4c2 100755
--- a/eng/common/cross/build-android-rootfs.sh
+++ b/eng/common/cross/build-android-rootfs.sh
@@ -106,6 +106,7 @@ __AndroidPackages+=" libandroid-glob"
__AndroidPackages+=" liblzma"
__AndroidPackages+=" krb5"
__AndroidPackages+=" openssl"
+__AndroidPackages+=" openldap"
for path in $(wget -qO- http://termux.net/dists/stable/main/binary-$__AndroidArch/Packages |\
grep -A15 "Package: \(${__AndroidPackages// /\\|}\)" | grep -v "static\|tool" | grep Filename); do
diff --git a/eng/common/cross/build-rootfs.sh b/eng/common/cross/build-rootfs.sh
index b26622444f5ba1..81e641a57b53d8 100755
--- a/eng/common/cross/build-rootfs.sh
+++ b/eng/common/cross/build-rootfs.sh
@@ -55,11 +55,13 @@ __UbuntuPackages+=" libcurl4-openssl-dev"
__UbuntuPackages+=" libkrb5-dev"
__UbuntuPackages+=" libssl-dev"
__UbuntuPackages+=" zlib1g-dev"
+__UbuntuPackages+=" libldap2-dev"
__AlpinePackages+=" curl-dev"
__AlpinePackages+=" krb5-dev"
__AlpinePackages+=" openssl-dev"
__AlpinePackages+=" zlib-dev"
+__AlpinePackages+=" openldap-dev"
__FreeBSDBase="12.1-RELEASE"
__FreeBSDPkg="1.12.0"
@@ -68,11 +70,13 @@ __FreeBSDPackages+=" icu"
__FreeBSDPackages+=" libinotify"
__FreeBSDPackages+=" lttng-ust"
__FreeBSDPackages+=" krb5"
+__FreeBSDPackages+=" libslapi-2.4"
__IllumosPackages="icu-64.2nb2"
__IllumosPackages+=" mit-krb5-1.16.2nb4"
__IllumosPackages+=" openssl-1.1.1e"
__IllumosPackages+=" zlib-1.2.11"
+__IllumosPackages+=" openldap-client-2.4.49"
__UseMirror=0
diff --git a/eng/common/templates/job/performance.yml b/eng/common/templates/job/performance.yml
deleted file mode 100644
index e6755df2234295..00000000000000
--- a/eng/common/templates/job/performance.yml
+++ /dev/null
@@ -1,95 +0,0 @@
-parameters:
- steps: [] # optional -- any additional steps that need to happen before pulling down the performance repo and sending the performance benchmarks to helix (ie building your repo)
- variables: [] # optional -- list of additional variables to send to the template
- jobName: '' # required -- job name
- displayName: '' # optional -- display name for the job. Will use jobName if not passed
- pool: '' # required -- name of the Build pool
- container: '' # required -- name of the container
- osGroup: '' # required -- operating system for the job
- extraSetupParameters: '' # optional -- extra arguments to pass to the setup script
- frameworks: ['netcoreapp3.0'] # optional -- list of frameworks to run against
- continueOnError: 'false' # optional -- determines whether to continue the build if the step errors
- dependsOn: '' # optional -- dependencies of the job
- timeoutInMinutes: 320 # optional -- timeout for the job
- enableTelemetry: false # optional -- enable for telemetry
-
-jobs:
-- template: ../jobs/jobs.yml
- parameters:
- dependsOn: ${{ parameters.dependsOn }}
- enableTelemetry: ${{ parameters.enableTelemetry }}
- enablePublishBuildArtifacts: true
- continueOnError: ${{ parameters.continueOnError }}
-
- jobs:
- - job: '${{ parameters.jobName }}'
-
- ${{ if ne(parameters.displayName, '') }}:
- displayName: '${{ parameters.displayName }}'
- ${{ if eq(parameters.displayName, '') }}:
- displayName: '${{ parameters.jobName }}'
-
- timeoutInMinutes: ${{ parameters.timeoutInMinutes }}
-
- variables:
-
- - ${{ each variable in parameters.variables }}:
- - ${{ if ne(variable.name, '') }}:
- - name: ${{ variable.name }}
- value: ${{ variable.value }}
- - ${{ if ne(variable.group, '') }}:
- - group: ${{ variable.group }}
-
- - IsInternal: ''
- - HelixApiAccessToken: ''
- - HelixPreCommand: ''
-
- - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}:
- - ${{ if eq( parameters.osGroup, 'Windows_NT') }}:
- - HelixPreCommand: 'set "PERFLAB_UPLOAD_TOKEN=$(PerfCommandUploadToken)"'
- - IsInternal: -Internal
- - ${{ if ne(parameters.osGroup, 'Windows_NT') }}:
- - HelixPreCommand: 'export PERFLAB_UPLOAD_TOKEN="$(PerfCommandUploadTokenLinux)"'
- - IsInternal: --internal
-
- - group: DotNet-HelixApi-Access
- - group: dotnet-benchview
-
- workspace:
- clean: all
- pool:
- ${{ parameters.pool }}
- container: ${{ parameters.container }}
- strategy:
- matrix:
- ${{ each framework in parameters.frameworks }}:
- ${{ framework }}:
- _Framework: ${{ framework }}
- steps:
- - checkout: self
- clean: true
- # Run all of the steps to setup repo
- - ${{ each step in parameters.steps }}:
- - ${{ step }}
- - powershell: $(Build.SourcesDirectory)\eng\testing\performance\performance-setup.ps1 $(IsInternal) -Framework $(_Framework) ${{ parameters.extraSetupParameters }}
- displayName: Performance Setup (Windows)
- condition: and(succeeded(), eq(variables['Agent.Os'], 'Windows_NT'))
- continueOnError: ${{ parameters.continueOnError }}
- - script: $(Build.SourcesDirectory)/eng/testing/performance/performance-setup.sh $(IsInternal) --framework $(_Framework) ${{ parameters.extraSetupParameters }}
- displayName: Performance Setup (Unix)
- condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT'))
- continueOnError: ${{ parameters.continueOnError }}
- - script: $(Python) $(PerformanceDirectory)/scripts/ci_setup.py $(SetupArguments)
- displayName: Run ci setup script
- # Run perf testing in helix
- - template: /eng/common/templates/steps/perf-send-to-helix.yml
- parameters:
- HelixSource: '$(HelixSourcePrefix)/$(Build.Repository.Name)/$(Build.SourceBranch)' # sources must start with pr/, official/, prodcon/, or agent/
- HelixType: 'test/performance/$(Kind)/$(_Framework)/$(Architecture)'
- HelixAccessToken: $(HelixApiAccessToken)
- HelixTargetQueues: $(Queue)
- HelixPreCommands: $(HelixPreCommand)
- Creator: $(Creator)
- WorkItemTimeout: 4:00 # 4 hours
- WorkItemDirectory: '$(WorkItemDirectory)' # WorkItemDirectory can not be empty, so we send it some docs to keep it happy
- CorrelationPayloadDirectory: '$(PayloadDirectory)' # it gets checked out to a folder with shorter path than WorkItemDirectory so we can avoid file name too long exceptions
\ No newline at end of file
diff --git a/eng/native/gen-buildsys.cmd b/eng/native/gen-buildsys.cmd
index 2d81dd174e0a00..740102f6f2d684 100644
--- a/eng/native/gen-buildsys.cmd
+++ b/eng/native/gen-buildsys.cmd
@@ -76,7 +76,7 @@ if not "%__ConfigureOnly%" == "1" (
if exist "%__CmdLineOptionsUpToDateFile%" (
set /p __CMakeCmdLineCache=<"%__CmdLineOptionsUpToDateFile%"
REM Strip the extra space from the end of the cached command line
- if [!__ExtraCmakeParams!] == [!__CMakeCmdLineCache:~0,-1!] (
+ if "!__ExtraCmakeParams!" == "!__CMakeCmdLineCache:~0,-1!" (
echo The CMake command line is the same as the last run. Skipping running CMake.
exit /B 0
) else (
diff --git a/eng/pipelines/common/global-build-job.yml b/eng/pipelines/common/global-build-job.yml
index 126cecfacaf05b..2b4b08a9d80784 100644
--- a/eng/pipelines/common/global-build-job.yml
+++ b/eng/pipelines/common/global-build-job.yml
@@ -19,6 +19,7 @@ parameters:
shouldContinueOnError: false
dependOnEvaluatePaths: false
isOfficialBuild: false
+ buildingOnSourceBuildImage: false
runtimeFlavor: 'coreclr'
helixQueues: ''
enablePublishTestResults: false
@@ -51,7 +52,7 @@ jobs:
dependsOn: ${{ parameters.dependsOn }}
${{ if eq(parameters.dependOnEvaluatePaths, true) }}:
- dependsOn:
+ dependsOn:
- evaluate_paths
- ${{ if ne(parameters.dependsOn,'') }}:
- ${{ parameters.dependsOn }}
@@ -59,7 +60,7 @@ jobs:
variables:
- name: _osParameter
value: -os ${{ parameters.osGroup }}
-
+
- ${{ if and(eq(parameters.osGroup, 'Linux'), eq(parameters.osSubGroup, '_musl')) }}:
- name: _osParameter
value: /p:RuntimeOS=linux-musl /p:OutputRid=linux-musl-${{ parameters.archType }}
@@ -79,13 +80,20 @@ jobs:
value: /p:OfficialBuildId=$(Build.BuildNumber)
${{ if ne(parameters.isOfficialBuild, true) }}:
value: ''
-
+
- name: _richCodeNavigationParam
${{ if eq(parameters.enableRichCodeNavigation, true) }}:
value: /p:EnableRichCodeNavigation=true
${{ if ne(parameters.enableRichCodeNavigation, true) }}:
value: ''
+ - name: _sclEnableCommand
+ ${{ if eq(parameters.buildingOnSourceBuildImage, true) }}:
+ value: scl enable llvm-toolset-7.0 --
+ ${{ if ne(parameters.buildingOnSourceBuildImage, true) }}:
+ value: ''
+
+
- ${{ each variable in parameters.variables }}:
- ${{ variable }}
@@ -124,7 +132,7 @@ jobs:
displayName: Install native dependencies
# Build
- - script: $(Build.SourcesDirectory)$(dir)build$(scriptExt) -ci -arch ${{ parameters.archType }} $(_osParameter) ${{ parameters.buildArgs }} $(_officialBuildParameter) $(_crossBuildPropertyArg) $(_cxx11Parameter) $(_richCodeNavigationParam)
+ - script: $(_sclEnableCommand) $(Build.SourcesDirectory)$(dir)build$(scriptExt) -ci -arch ${{ parameters.archType }} $(_osParameter) ${{ parameters.buildArgs }} $(_officialBuildParameter) $(_crossBuildPropertyArg) $(_cxx11Parameter) $(_richCodeNavigationParam)
displayName: Build product
${{ if eq(parameters.useContinueOnErrorDuringBuild, true) }}:
continueOnError: ${{ parameters.shouldContinueOnError }}
diff --git a/eng/pipelines/common/platform-matrix.yml b/eng/pipelines/common/platform-matrix.yml
index 000d1dcecdfdac..ea17c5643461f3 100644
--- a/eng/pipelines/common/platform-matrix.yml
+++ b/eng/pipelines/common/platform-matrix.yml
@@ -180,6 +180,31 @@ jobs:
helixQueueGroup: ${{ parameters.helixQueueGroup }}
${{ insert }}: ${{ parameters.jobParameters }}
+# Linux x64 Source Build
+
+- ${{ if containsValue(parameters.platforms, 'SourceBuild_Linux_x64') }}:
+ - template: xplat-setup.yml
+ parameters:
+ jobTemplate: ${{ parameters.jobTemplate }}
+ helixQueuesTemplate: ${{ parameters.helixQueuesTemplate }}
+ variables: ${{ parameters.variables }}
+ osGroup: Linux
+ archType: x64
+ targetRid: linux-x64
+ platform: Linux_x64
+ container:
+ image: centos-7-source-build-20210408124356-5d87b80
+ registry: mcr
+ jobParameters:
+ runtimeFlavor: ${{ parameters.runtimeFlavor }}
+ stagedBuild: ${{ parameters.stagedBuild }}
+ buildConfig: ${{ parameters.buildConfig }}
+ ${{ if eq(parameters.passPlatforms, true) }}:
+ platforms: ${{ parameters.platforms }}
+ helixQueueGroup: ${{ parameters.helixQueueGroup }}
+ ${{ insert }}: ${{ parameters.jobParameters }}
+ buildingOnSourceBuildImage: true
+
# WebAssembly
- ${{ if containsValue(parameters.platforms, 'Browser_wasm') }}:
diff --git a/eng/pipelines/global-build.yml b/eng/pipelines/global-build.yml
index 3a737e69c52131..b415c5e5cac57b 100644
--- a/eng/pipelines/global-build.yml
+++ b/eng/pipelines/global-build.yml
@@ -130,8 +130,8 @@ jobs:
jobTemplate: /eng/pipelines/common/global-build-job.yml
buildConfig: release
platforms:
- - Linux_x64
+ - SourceBuild_Linux_x64
jobParameters:
nameSuffix: SourceBuild
- buildArgs: /p:DotNetBuildFromSource=true
+ buildArgs: -subset clr+libs+host+packs /p:DotNetBuildFromSource=true
timeoutInMinutes: 90
diff --git a/eng/testing/AppleRunnerTemplate.sh b/eng/testing/AppleRunnerTemplate.sh
index 0f2eb7f2abed87..47352018d1ac42 100644
--- a/eng/testing/AppleRunnerTemplate.sh
+++ b/eng/testing/AppleRunnerTemplate.sh
@@ -16,17 +16,17 @@ if [ -n "$5" ]; then
ADDITIONAL_ARGS=${@:5}
fi
-if [[ "$TARGET_OS" == "MacCatalyst" ]]; then TARGET=maccatalyst; fi
+if [[ "$TARGET_OS" == "maccatalyst" ]]; then TARGET=maccatalyst; fi
-if [[ "$TARGET_OS" == "iOSSimulator" && "$TARGET_ARCH" == "x86" ]]; then TARGET=ios-simulator-32; fi
-if [[ "$TARGET_OS" == "iOSSimulator" && "$TARGET_ARCH" == "x64" ]]; then TARGET=ios-simulator-64; fi
-if [[ "$TARGET_OS" == "iOSSimulator" && "$TARGET_ARCH" == "arm64" ]]; then TARGET=ios-simulator-64; fi
-if [[ "$TARGET_OS" == "iOS" && "$TARGET_ARCH" == "arm" ]]; then TARGET=ios-device; fi
-if [[ "$TARGET_OS" == "iOS" && "$TARGET_ARCH" == "arm64" ]]; then TARGET=ios-device; fi
+if [[ "$TARGET_OS" == "iossimulator" && "$TARGET_ARCH" == "x86" ]]; then TARGET=ios-simulator-32; fi
+if [[ "$TARGET_OS" == "iossimulator" && "$TARGET_ARCH" == "x64" ]]; then TARGET=ios-simulator-64; fi
+if [[ "$TARGET_OS" == "iossimulator" && "$TARGET_ARCH" == "arm64" ]]; then TARGET=ios-simulator-64; fi
+if [[ "$TARGET_OS" == "ios" && "$TARGET_ARCH" == "arm" ]]; then TARGET=ios-device; fi
+if [[ "$TARGET_OS" == "ios" && "$TARGET_ARCH" == "arm64" ]]; then TARGET=ios-device; fi
-if [[ "$TARGET_OS" == "tvOSSimulator" && "$TARGET_ARCH" == "x64" ]]; then TARGET=tvos-simulator; fi
-if [[ "$TARGET_OS" == "tvOSSimulator" && "$TARGET_ARCH" == "arm64" ]]; then TARGET=tvos-simulator; fi
-if [[ "$TARGET_OS" == "tvOS" && "$TARGET_ARCH" == "arm64" ]]; then TARGET=tvos-device; fi
+if [[ "$TARGET_OS" == "tvossimulator" && "$TARGET_ARCH" == "x64" ]]; then TARGET=tvos-simulator; fi
+if [[ "$TARGET_OS" == "tvossimulator" && "$TARGET_ARCH" == "arm64" ]]; then TARGET=tvos-simulator; fi
+if [[ "$TARGET_OS" == "tvos" && "$TARGET_ARCH" == "arm64" ]]; then TARGET=tvos-device; fi
# "Release" in SCHEME_SDK is what xcode produces (see "bool Optimized" property in AppleAppBuilderTask)
if [[ "$TARGET" == "ios-simulator-"* ]]; then SCHEME_SDK=Release-iphonesimulator; fi
diff --git a/eng/testing/RunnerTemplate.cmd b/eng/testing/RunnerTemplate.cmd
index 9e6c6d1e7866bf..0d898b4aa182ad 100644
--- a/eng/testing/RunnerTemplate.cmd
+++ b/eng/testing/RunnerTemplate.cmd
@@ -59,10 +59,11 @@ echo ----- end %DATE% %TIME% ----- exit code %ERRORLEVEL% ----------------------
:: The helix work item should not exit with non-zero if tests ran and produced results
:: The special console runner for runtime returns 1 when tests fail
if %ERRORLEVEL%==1 (
- exit /b 0
-) else (
- exit /b %ERRORLEVEL%
+ if not "%HELIX_WORKITEM_PAYLOAD%"=="" (
+ exit /b 0
+ )
)
+exit /b %ERRORLEVEL%
:: ========================= END Test Execution =================================
:usage
diff --git a/eng/testing/RunnerTemplate.sh b/eng/testing/RunnerTemplate.sh
index a8bdcb1d478849..4770323fdc9c7d 100644
--- a/eng/testing/RunnerTemplate.sh
+++ b/eng/testing/RunnerTemplate.sh
@@ -225,8 +225,11 @@ popd >/dev/null
# The helix work item should not exit with non-zero if tests ran and produced results
# The special console runner for runtime returns 1 when tests fail
if [ "$test_exitcode" == "1" ]; then
- exit 0
-else
- exit $test_exitcode
+ if [ -n "$HELIX_WORKITEM_PAYLOAD" ]; then
+ exit 0
+ fi
+fi
+
+exit $test_exitcode
fi
diff --git a/eng/testing/tests.targets b/eng/testing/tests.targets
index 9fc08ddd6bcc70..53256725fb9594 100644
--- a/eng/testing/tests.targets
+++ b/eng/testing/tests.targets
@@ -96,7 +96,7 @@
$(RunTestsCommand) --runtime-path "$(TestHostRootPath.TrimEnd('\/'))"
$(RunTestsCommand) --rsp-file "$(TestRspFile)"
- "$(RunScriptOutputPath)" $(AssemblyName) $(TargetArchitecture) $(TargetOS) $(TestProjectName) $(AdditionalXHarnessArguments)
+ "$(RunScriptOutputPath)" $(AssemblyName) $(TargetArchitecture) $(TargetOS.ToLowerInvariant()) $(TestProjectName) $(AdditionalXHarnessArguments)
"$(RunScriptOutputPath)" $(JSEngine) $(AssemblyName).dll $(Scenario)
diff --git a/eng/testing/tests.wasm.targets b/eng/testing/tests.wasm.targets
index 505b3a8bde603a..09311ffd96ef71 100644
--- a/eng/testing/tests.wasm.targets
+++ b/eng/testing/tests.wasm.targets
@@ -2,6 +2,7 @@
$(BundleTestAppTargets);BundleTestWasmApp
+ true
@@ -27,7 +28,9 @@
true
false
false
- false
+
+
+ false
@@ -62,6 +65,9 @@
$(InvariantGlobalization)
true
false
+
+ true
+ -1
@@ -79,4 +85,17 @@
+
+
+
+
+ <_PdbFilesToCheck Include="$([System.IO.Path]::ChangeExtension('%(ResolvedFileToPublish.Identity)', '.pdb'))"
+ Condition="'%(ResolvedFileToPublish.Extension)' == '.dll'" />
+
+
+
+
diff --git a/global.json b/global.json
index f2672dc65e4f2e..6a1e4ffb48d888 100644
--- a/global.json
+++ b/global.json
@@ -12,12 +12,12 @@
"python3": "3.7.1"
},
"msbuild-sdks": {
- "Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk": "6.0.0-beta.21203.1",
- "Microsoft.DotNet.Arcade.Sdk": "6.0.0-beta.21203.1",
- "Microsoft.DotNet.Helix.Sdk": "6.0.0-beta.21203.1",
- "Microsoft.DotNet.SharedFramework.Sdk": "6.0.0-beta.21203.1",
+ "Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk": "6.0.0-beta.21209.17",
+ "Microsoft.DotNet.Arcade.Sdk": "6.0.0-beta.21209.17",
+ "Microsoft.DotNet.Helix.Sdk": "6.0.0-beta.21209.17",
+ "Microsoft.DotNet.SharedFramework.Sdk": "6.0.0-beta.21209.17",
"Microsoft.Build.NoTargets": "2.0.17",
"Microsoft.Build.Traversal": "2.1.1",
- "Microsoft.NET.Sdk.IL": "6.0.0-preview.4.21178.6"
+ "Microsoft.NET.Sdk.IL": "6.0.0-preview.4.21211.7"
}
}
diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj
index 5f0d5c2c940f87..d841ffc7287cbb 100644
--- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj
+++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj
@@ -199,6 +199,7 @@
+
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs
index 0721c3307bd186..336c1f0c986b4d 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs
@@ -458,19 +458,15 @@ internal RuntimeMethodHandle GetMethodDescriptor()
// if we are here we passed all the previous checks. Time to look at the arguments
bool wrapExceptions = (invokeAttr & BindingFlags.DoNotWrapExceptions) == 0;
- object retValue;
- if (actualCount > 0)
- {
- object[] arguments = CheckArguments(parameters!, binder, invokeAttr, culture, sig);
- retValue = RuntimeMethodHandle.InvokeMethod(null, arguments, sig, false, wrapExceptions);
- // copy out. This should be made only if ByRef are present.
- for (int index = 0; index < arguments.Length; index++)
- parameters![index] = arguments[index];
- }
- else
- {
- retValue = RuntimeMethodHandle.InvokeMethod(null, null, sig, false, wrapExceptions);
- }
+
+ StackAllocedArguments stackArgs = default;
+ Span arguments = CheckArguments(ref stackArgs, parameters, binder, invokeAttr, culture, sig);
+ object? retValue = RuntimeMethodHandle.InvokeMethod(null, arguments, sig, false, wrapExceptions);
+
+ // copy out. This should be made only if ByRef are present.
+ // n.b. cannot use Span.CopyTo, as parameters.GetType() might not actually be typeof(object[])
+ for (int index = 0; index < arguments.Length; index++)
+ parameters![index] = arguments[index];
GC.KeepAlive(this);
return retValue;
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Metadata/RuntimeTypeMetadataUpdateHandler.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Metadata/RuntimeTypeMetadataUpdateHandler.cs
new file mode 100644
index 00000000000000..25f29ed8e596eb
--- /dev/null
+++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Metadata/RuntimeTypeMetadataUpdateHandler.cs
@@ -0,0 +1,25 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Reflection.Metadata;
+
+[assembly: MetadataUpdateHandler(typeof(RuntimeTypeMetadataUpdateHandler))]
+
+namespace System.Reflection.Metadata
+{
+ /// Metadata update handler used to clear a Type's reflection cache in response to a metadata update notification.
+ internal static class RuntimeTypeMetadataUpdateHandler
+ {
+ public static void BeforeUpdate(Type? type)
+ {
+ if (type is RuntimeType rt)
+ {
+ rt.ClearCache();
+ }
+
+ // TODO: https://github.com/dotnet/runtime/issues/50938
+ // Do we need to clear the cache on other types, e.g. ones derived from this one?
+ // Do we need to clear a cache on any other kinds of types?
+ }
+ }
+}
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBase.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBase.CoreCLR.cs
index 973b8564dc2c95..532d684605b0af 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBase.CoreCLR.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBase.CoreCLR.cs
@@ -1,8 +1,11 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics;
using System.Globalization;
+using System.Runtime.InteropServices;
using System.Threading;
+using Internal.Runtime.CompilerServices;
namespace System.Reflection
{
@@ -62,30 +65,61 @@ internal virtual Type[] GetParameterTypes()
return parameterTypes;
}
- internal object[] CheckArguments(object[] parameters, Binder? binder,
+ private protected Span CheckArguments(ref StackAllocedArguments stackArgs, object?[]? parameters, Binder? binder,
BindingFlags invokeAttr, CultureInfo? culture, Signature sig)
{
- // copy the arguments in a different array so we detach from any user changes
- object[] copyOfParameters = new object[parameters.Length];
+ Debug.Assert(Unsafe.SizeOf() == StackAllocedArguments.MaxStackAllocArgCount * Unsafe.SizeOf(),
+ "MaxStackAllocArgCount not properly defined.");
- ParameterInfo[]? p = null;
- for (int i = 0; i < parameters.Length; i++)
- {
- object arg = parameters[i];
- RuntimeType argRT = sig.Arguments[i];
+ Span copyOfParameters = default;
- if (arg == Type.Missing)
+ if (parameters is not null)
+ {
+ // We need to perform type safety validation against the incoming arguments, but we also need
+ // to be resilient against the possibility that some other thread (or even the binder itself!)
+ // may mutate the array after we've validated the arguments but before we've properly invoked
+ // the method. The solution is to copy the arguments to a different, not-user-visible buffer
+ // as we validate them. n.b. This disallows use of ArrayPool, as ArrayPool-rented arrays are
+ // considered user-visible to threads which may still be holding on to returned instances.
+
+ copyOfParameters = (parameters.Length <= StackAllocedArguments.MaxStackAllocArgCount)
+ ? MemoryMarshal.CreateSpan(ref stackArgs._arg0, parameters.Length)
+ : new Span(new object?[parameters.Length]);
+
+ ParameterInfo[]? p = null;
+ for (int i = 0; i < parameters.Length; i++)
{
- p ??= GetParametersNoCopy();
- if (p[i].DefaultValue == System.DBNull.Value)
- throw new ArgumentException(SR.Arg_VarMissNull, nameof(parameters));
- arg = p[i].DefaultValue!;
+ object? arg = parameters[i];
+ RuntimeType argRT = sig.Arguments[i];
+
+ if (arg == Type.Missing)
+ {
+ p ??= GetParametersNoCopy();
+ if (p[i].DefaultValue == System.DBNull.Value)
+ throw new ArgumentException(SR.Arg_VarMissNull, nameof(parameters));
+ arg = p[i].DefaultValue!;
+ }
+ copyOfParameters[i] = argRT.CheckValue(arg, binder, culture, invokeAttr);
}
- copyOfParameters[i] = argRT.CheckValue(arg, binder, culture, invokeAttr)!;
}
return copyOfParameters;
}
+
+ // Helper struct to avoid intermediate object[] allocation in calls to the native reflection stack.
+ // Typical usage is to define a local of type default(StackAllocedArguments), then pass 'ref theLocal'
+ // as the first parameter to CheckArguments. CheckArguments will try to utilize storage within this
+ // struct instance if there's sufficient space; otherwise CheckArguments will allocate a temp array.
+ private protected struct StackAllocedArguments
+ {
+ internal const int MaxStackAllocArgCount = 4;
+ internal object? _arg0;
+#pragma warning disable CA1823, CS0169, IDE0051 // accessed via 'CheckArguments' ref arithmetic
+ private object? _arg1;
+ private object? _arg2;
+ private object? _arg3;
+#pragma warning restore CA1823, CS0169, IDE0051
+ }
#endregion
}
}
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs
index 8a02eea275ab41..c991b642cfc5ec 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs
@@ -7,6 +7,7 @@
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Text;
+using System.Threading;
using RuntimeTypeCache = System.RuntimeType.RuntimeTypeCache;
namespace System.Reflection
@@ -26,14 +27,16 @@ internal sealed class RuntimeConstructorInfo : ConstructorInfo, IRuntimeMethodIn
private IntPtr m_handle;
private MethodAttributes m_methodAttributes;
private BindingFlags m_bindingFlags;
- private volatile Signature? m_signature;
+ private Signature? m_signature;
private INVOCATION_FLAGS m_invocationFlags;
internal INVOCATION_FLAGS InvocationFlags
{
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
- if ((m_invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED) == 0)
+ [MethodImpl(MethodImplOptions.NoInlining)] // move lazy invocation flags population out of the hot path
+ INVOCATION_FLAGS LazyCreateInvocationFlags()
{
INVOCATION_FLAGS invocationFlags = INVOCATION_FLAGS.INVOCATION_FLAGS_IS_CTOR; // this is a given
@@ -68,10 +71,17 @@ internal INVOCATION_FLAGS InvocationFlags
invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_IS_DELEGATE_CTOR;
}
- m_invocationFlags = invocationFlags | INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED;
+ invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED;
+ m_invocationFlags = invocationFlags; // accesses are guaranteed atomic
+ return invocationFlags;
}
- return m_invocationFlags;
+ INVOCATION_FLAGS flags = m_invocationFlags;
+ if ((flags & INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED) == 0)
+ {
+ flags = LazyCreateInvocationFlags();
+ }
+ return flags;
}
}
#endregion
@@ -95,7 +105,22 @@ internal RuntimeConstructorInfo(
internal override bool CacheEquals(object? o) =>
o is RuntimeConstructorInfo m && m.m_handle == m_handle;
- private Signature Signature => m_signature ??= new Signature(this, m_declaringType);
+ private Signature Signature
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ [MethodImpl(MethodImplOptions.NoInlining)] // move lazy sig generation out of the hot path
+ Signature LazyCreateSignature()
+ {
+ Signature newSig = new Signature(this, m_declaringType);
+ Volatile.Write(ref m_signature, newSig);
+ return newSig;
+ }
+
+ return m_signature ?? LazyCreateSignature();
+ }
+ }
private RuntimeType ReflectedTypeInternal => m_reflectedTypeCache.GetRuntimeType();
@@ -313,16 +338,17 @@ internal void ThrowNoInvokeException()
// if we are here we passed all the previous checks. Time to look at the arguments
bool wrapExceptions = (invokeAttr & BindingFlags.DoNotWrapExceptions) == 0;
- if (actualCount > 0)
- {
- object[] arguments = CheckArguments(parameters!, binder, invokeAttr, culture, sig);
- object retValue = RuntimeMethodHandle.InvokeMethod(obj, arguments, sig, false, wrapExceptions);
- // copy out. This should be made only if ByRef are present.
- for (int index = 0; index < arguments.Length; index++)
- parameters![index] = arguments[index];
- return retValue;
- }
- return RuntimeMethodHandle.InvokeMethod(obj, null, sig, false, wrapExceptions);
+
+ StackAllocedArguments stackArgs = default;
+ Span arguments = CheckArguments(ref stackArgs, parameters, binder, invokeAttr, culture, sig);
+ object? retValue = RuntimeMethodHandle.InvokeMethod(obj, arguments, sig, false, wrapExceptions);
+
+ // copy out. This should be made only if ByRef are present.
+ // n.b. cannot use Span.CopyTo, as parameters.GetType() might not actually be typeof(object[])
+ for (int index = 0; index < arguments.Length; index++)
+ parameters![index] = arguments[index];
+
+ return retValue;
}
[RequiresUnreferencedCode("Trimming may change method bodies. For example it can change some instructions, remove branches or local variables.")]
@@ -366,16 +392,17 @@ public override object Invoke(BindingFlags invokeAttr, Binder? binder, object?[]
// if we are here we passed all the previous checks. Time to look at the arguments
bool wrapExceptions = (invokeAttr & BindingFlags.DoNotWrapExceptions) == 0;
- if (actualCount > 0)
- {
- object[] arguments = CheckArguments(parameters!, binder, invokeAttr, culture, sig);
- object retValue = RuntimeMethodHandle.InvokeMethod(null, arguments, sig, true, wrapExceptions);
- // copy out. This should be made only if ByRef are present.
- for (int index = 0; index < arguments.Length; index++)
- parameters![index] = arguments[index];
- return retValue;
- }
- return RuntimeMethodHandle.InvokeMethod(null, null, sig, true, wrapExceptions);
+
+ StackAllocedArguments stackArgs = default;
+ Span arguments = CheckArguments(ref stackArgs, parameters, binder, invokeAttr, culture, sig);
+ object retValue = RuntimeMethodHandle.InvokeMethod(null, arguments, sig, true, wrapExceptions)!; // ctor must return non-null
+
+ // copy out. This should be made only if ByRef are present.
+ // n.b. cannot use Span.CopyTo, as parameters.GetType() might not actually be typeof(object[])
+ for (int index = 0; index < arguments.Length; index++)
+ parameters![index] = arguments[index];
+
+ return retValue;
}
#endregion
}
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs
index e0d87e7821d8ed..9d1023bda3733c 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs
@@ -5,6 +5,7 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
+using System.Runtime.CompilerServices;
using System.Security;
using System.Text;
using System.Threading;
@@ -30,9 +31,11 @@ internal sealed class RuntimeMethodInfo : MethodInfo, IRuntimeMethodInfo
internal INVOCATION_FLAGS InvocationFlags
{
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
- if ((m_invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED) == 0)
+ [MethodImpl(MethodImplOptions.NoInlining)] // move lazy invocation flags population out of the hot path
+ INVOCATION_FLAGS LazyCreateInvocationFlags()
{
INVOCATION_FLAGS invocationFlags = INVOCATION_FLAGS.INVOCATION_FLAGS_UNKNOWN;
@@ -55,10 +58,17 @@ internal INVOCATION_FLAGS InvocationFlags
invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_CONTAINS_STACK_POINTERS;
}
- m_invocationFlags = invocationFlags | INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED;
+ invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED;
+ m_invocationFlags = invocationFlags; // accesses are guaranteed atomic
+ return invocationFlags;
}
- return m_invocationFlags;
+ INVOCATION_FLAGS flags = m_invocationFlags;
+ if ((flags & INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED) == 0)
+ {
+ flags = LazyCreateInvocationFlags();
+ }
+ return flags;
}
}
@@ -105,7 +115,22 @@ private ParameterInfo FetchReturnParameter() =>
internal override bool CacheEquals(object? o) =>
o is RuntimeMethodInfo m && m.m_handle == m_handle;
- internal Signature Signature => m_signature ??= new Signature(this, m_declaringType);
+ internal Signature Signature
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ [MethodImpl(MethodImplOptions.NoInlining)] // move lazy sig generation out of the hot path
+ Signature LazyCreateSignature()
+ {
+ Signature newSig = new Signature(this, m_declaringType);
+ Volatile.Write(ref m_signature, newSig);
+ return newSig;
+ }
+
+ return m_signature ?? LazyCreateSignature();
+ }
+ }
internal BindingFlags BindingFlags => m_bindingFlags;
@@ -330,10 +355,11 @@ public override MethodImplAttributes GetMethodImplementationFlags()
#endregion
#region Invocation Logic(On MemberBase)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void CheckConsistency(object? target)
{
// only test instance methods
- if ((m_methodAttributes & MethodAttributes.Static) != MethodAttributes.Static)
+ if ((m_methodAttributes & MethodAttributes.Static) == 0)
{
if (!m_declaringType.IsInstanceOfType(target))
{
@@ -384,26 +410,23 @@ private void ThrowNoInvokeException()
[Diagnostics.DebuggerHidden]
public override object? Invoke(object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture)
{
- object[]? arguments = InvokeArgumentsCheck(obj, invokeAttr, binder, parameters, culture);
+ StackAllocedArguments stackArgs = default; // try to avoid intermediate array allocation if possible
+ Span arguments = InvokeArgumentsCheck(ref stackArgs, obj, invokeAttr, binder, parameters, culture);
bool wrapExceptions = (invokeAttr & BindingFlags.DoNotWrapExceptions) == 0;
- if (arguments == null || arguments.Length == 0)
- return RuntimeMethodHandle.InvokeMethod(obj, null, Signature, false, wrapExceptions);
- else
- {
- object retValue = RuntimeMethodHandle.InvokeMethod(obj, arguments, Signature, false, wrapExceptions);
+ object? retValue = RuntimeMethodHandle.InvokeMethod(obj, arguments, Signature, false, wrapExceptions);
- // copy out. This should be made only if ByRef are present.
- for (int index = 0; index < arguments.Length; index++)
- parameters![index] = arguments[index];
+ // copy out. This should be made only if ByRef are present.
+ // n.b. cannot use Span.CopyTo, as parameters.GetType() might not actually be typeof(object[])
+ for (int index = 0; index < arguments.Length; index++)
+ parameters![index] = arguments[index];
- return retValue;
- }
+ return retValue;
}
[DebuggerStepThroughAttribute]
[Diagnostics.DebuggerHidden]
- private object[]? InvokeArgumentsCheck(object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture)
+ private Span InvokeArgumentsCheck(ref StackAllocedArguments stackArgs, object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture)
{
Signature sig = Signature;
@@ -425,10 +448,12 @@ private void ThrowNoInvokeException()
if (formalCount != actualCount)
throw new TargetParameterCountException(SR.Arg_ParmCnt);
+ Span retVal = default;
if (actualCount != 0)
- return CheckArguments(parameters!, binder, invokeAttr, culture, sig);
- else
- return null;
+ {
+ retVal = CheckArguments(ref stackArgs, parameters!, binder, invokeAttr, culture, sig);
+ }
+ return retVal;
}
#endregion
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.CoreCLR.cs
index 0187c5e29ba052..8cfaff78e938be 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.CoreCLR.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.CoreCLR.cs
@@ -26,7 +26,7 @@ public partial struct GCHandle
#endif
[MethodImpl(MethodImplOptions.InternalCall)]
- private static extern void InternalSet(IntPtr handle, object? value);
+ internal static extern void InternalSet(IntPtr handle, object? value);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern object? InternalCompareExchange(IntPtr handle, object? value, object? oldValue);
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs
index cfa743db019e29..afacc85d34c863 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs
@@ -600,37 +600,6 @@ public static TWrapper CreateWrapperOfType(T? o)
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern bool IsTypeVisibleFromCom(Type t);
- [SupportedOSPlatform("windows")]
- public static unsafe int QueryInterface(IntPtr pUnk, ref Guid iid, out IntPtr ppv)
- {
- if (pUnk == IntPtr.Zero)
- throw new ArgumentNullException(nameof(pUnk));
-
- fixed (Guid* pIID = &iid)
- fixed (IntPtr* p = &ppv)
- {
- return ((delegate* unmanaged)(*(*(void***)pUnk + 0 /* IUnknown.QueryInterface slot */)))(pUnk, pIID, p);
- }
- }
-
- [SupportedOSPlatform("windows")]
- public static unsafe int AddRef(IntPtr pUnk)
- {
- if (pUnk == IntPtr.Zero)
- throw new ArgumentNullException(nameof(pUnk));
-
- return ((delegate* unmanaged)(*(*(void***)pUnk + 1 /* IUnknown.AddRef slot */)))(pUnk);
- }
-
- [SupportedOSPlatform("windows")]
- public static unsafe int Release(IntPtr pUnk)
- {
- if (pUnk == IntPtr.Zero)
- throw new ArgumentNullException(nameof(pUnk));
-
- return ((delegate* unmanaged)(*(*(void***)pUnk + 2 /* IUnknown.Release slot */)))(pUnk);
- }
-
[SupportedOSPlatform("windows")]
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern void GetNativeVariantForObject(object? obj, /* VARIANT * */ IntPtr pDstNativeVariant);
diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs
index 6e99db321a05d1..c89801cb802510 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs
@@ -9,6 +9,7 @@
using System.Runtime.Loader;
using System.Runtime.Serialization;
using System.Threading;
+using Internal.Runtime.CompilerServices;
namespace System
{
@@ -963,7 +964,7 @@ internal static MdUtf8String GetUtf8Name(RuntimeMethodHandleInternal method)
[DebuggerStepThroughAttribute]
[Diagnostics.DebuggerHidden]
[MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern object InvokeMethod(object? target, object[]? arguments, Signature sig, bool constructor, bool wrapExceptions);
+ internal static extern object? InvokeMethod(object? target, in Span arguments, Signature sig, bool constructor, bool wrapExceptions);
[DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)]
private static extern void GetMethodInstantiation(RuntimeMethodHandleInternal method, ObjectHandleOnStack types, Interop.BOOL fAsRuntimeTypeArray);
diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs
index a1d174667db10f..78bb08345933f7 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs
@@ -2418,6 +2418,18 @@ private RuntimeTypeCache InitializeCache()
return cache;
}
+ internal void ClearCache()
+ {
+ // If there isn't a GCHandle yet, there's nothing more to do.
+ if (Volatile.Read(ref m_cache) == IntPtr.Zero)
+ {
+ return;
+ }
+
+ // Set the GCHandle to null. The cache will be re-created next time it is needed.
+ GCHandle.InternalSet(m_cache, null);
+ }
+
private string? GetDefaultMemberName()
{
return Cache.GetDefaultMemberName();
diff --git a/src/coreclr/crosscomponents.cmake b/src/coreclr/crosscomponents.cmake
index e8d51914951e33..03b076becfb6d6 100644
--- a/src/coreclr/crosscomponents.cmake
+++ b/src/coreclr/crosscomponents.cmake
@@ -1,6 +1,11 @@
# Add targets to the crosscomponents subcomponent build
if (CLR_CMAKE_HOST_OS STREQUAL CLR_CMAKE_TARGET_OS)
+ install_clr (TARGETS
+ clrjit
+ DESTINATIONS . sharedFramework
+ COMPONENT crosscomponents
+ )
install_clr (TARGETS
clrjit
jitinterface_${ARCH_HOST_NAME}
@@ -11,7 +16,7 @@ if (CLR_CMAKE_HOST_OS STREQUAL CLR_CMAKE_TARGET_OS)
if(CLR_CMAKE_HOST_LINUX OR NOT FEATURE_CROSSBITNESS)
install_clr (TARGETS
crossgen
- DESTINATIONS .
+ DESTINATIONS . sharedFramework
COMPONENT crosscomponents
)
endif()
@@ -19,7 +24,7 @@ if (CLR_CMAKE_HOST_OS STREQUAL CLR_CMAKE_TARGET_OS)
if (CLR_CMAKE_TARGET_UNIX)
install_clr (TARGETS
clrjit_unix_${ARCH_TARGET_NAME}_${ARCH_HOST_NAME}
- DESTINATIONS .
+ DESTINATIONS . sharedFramework
COMPONENT crosscomponents
)
endif(CLR_CMAKE_TARGET_UNIX)
@@ -29,7 +34,7 @@ if(NOT CLR_CMAKE_HOST_LINUX AND NOT CLR_CMAKE_HOST_OSX AND NOT FEATURE_CROSSBITN
install_clr (TARGETS
mscordaccore
mscordbi
- DESTINATIONS .
+ DESTINATIONS . sharedFramework
COMPONENT crosscomponents
)
endif()
diff --git a/src/coreclr/dlls/mscordac/CMakeLists.txt b/src/coreclr/dlls/mscordac/CMakeLists.txt
index 327560a030db20..9dd3329a230487 100644
--- a/src/coreclr/dlls/mscordac/CMakeLists.txt
+++ b/src/coreclr/dlls/mscordac/CMakeLists.txt
@@ -210,5 +210,8 @@ if(CLR_CMAKE_HOST_WIN32)
string(REGEX MATCH "#define VER_FILEVERSION[ \t]+[0-9]+(,[0-9]+)+" FILE_VERSION_LINE "${NATIVE_VERSION_HEADER}")
string(REGEX MATCHALL "[0-9]+" FILE_VERSION_COMPONENTS "${FILE_VERSION_LINE}")
list(JOIN FILE_VERSION_COMPONENTS "." FILE_VERSION)
- install(FILES $ RENAME mscordaccore_${LONG_NAME_HOST_ARCH}_${LONG_NAME_TARGET_ARCH}_${FILE_VERSION}.dll DESTINATION sharedFramework COMPONENT runtime)
+ install(PROGRAMS $ RENAME mscordaccore_${LONG_NAME_HOST_ARCH}_${LONG_NAME_TARGET_ARCH}_${FILE_VERSION}.dll DESTINATION sharedFramework COMPONENT runtime)
+ if (NOT FEATURE_CROSSBITNESS)
+ install(PROGRAMS $ RENAME mscordaccore_${LONG_NAME_HOST_ARCH}_${LONG_NAME_TARGET_ARCH}_${FILE_VERSION}.dll DESTINATION sharedFramework COMPONENT crosscomponents)
+ endif()
endif()
diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp
index 8df0a785859924..4437db322e39ea 100644
--- a/src/coreclr/gc/gc.cpp
+++ b/src/coreclr/gc/gc.cpp
@@ -4964,6 +4964,16 @@ BOOL gc_heap::reserve_initial_memory (size_t normal_size, size_t large_size, siz
}
}
+ if (reserve_success && separated_poh_p)
+ {
+ for (int heap_no = 0; (reserve_success && (heap_no < num_heaps)); heap_no++)
+ {
+ if (!GCToOSInterface::VirtualCommit(memory_details.initial_pinned_heap[heap_no].memory_base, pinned_size))
+ {
+ reserve_success = FALSE;
+ }
+ }
+ }
return reserve_success;
}
@@ -6581,7 +6591,6 @@ bool gc_heap::virtual_decommit (void* address, size_t size, gc_oh_num oh, int h_
void gc_heap::virtual_free (void* add, size_t allocated_size, heap_segment* sg)
{
- assert(!heap_hard_limit);
bool release_succeeded_p = GCToOSInterface::VirtualRelease (add, allocated_size);
if (release_succeeded_p)
{
@@ -11739,6 +11748,11 @@ HRESULT gc_heap::initialize_gc (size_t soh_segment_size,
if (!reserve_initial_memory (soh_segment_size, loh_segment_size, poh_segment_size, number_of_heaps,
use_large_pages_p, separated_poh_p, heap_no_to_numa_node))
return E_OUTOFMEMORY;
+ if (separated_poh_p)
+ {
+ heap_hard_limit_oh[poh] = min_segment_size_hard_limit * number_of_heaps;
+ heap_hard_limit += heap_hard_limit_oh[poh];
+ }
#endif //USE_REGIONS
#ifdef CARD_BUNDLE
@@ -33640,7 +33654,7 @@ bool gc_heap::find_next_chunk(card_marking_enumerator& card_mark_enumerator, hea
dprintf (3, ("No more chunks on heap %d\n", heap_number));
return false;
}
- card = card_of (chunk_low);
+ card = max(card, card_of(chunk_low));
card_word_end = (card_of(align_on_card_word(chunk_high)) / card_word_width);
dprintf (3, ("Moved to next chunk on heap %d: [%Ix,%Ix[", heap_number, (size_t)chunk_low, (size_t)chunk_high));
}
@@ -40125,6 +40139,10 @@ HRESULT GCHeap::Initialize()
{
return E_INVALIDARG;
}
+ if (!gc_heap::heap_hard_limit_oh[poh] && !GCConfig::GetGCLargePages())
+ {
+ return E_INVALIDARG;
+ }
gc_heap::heap_hard_limit = gc_heap::heap_hard_limit_oh[soh] +
gc_heap::heap_hard_limit_oh[loh] + gc_heap::heap_hard_limit_oh[poh];
}
@@ -40344,7 +40362,12 @@ HRESULT GCHeap::Initialize()
#ifdef MULTIPLE_HEAPS
gc_heap::soh_segment_size /= 4;
#endif //MULTIPLE_HEAPS
- gc_heap::min_segment_size_shr = index_of_highest_set_bit (REGION_SIZE);
+ size_t gc_region_size = (size_t)GCConfig::GetGCRegionsSize();
+ if (!power_of_two_p(gc_region_size) || ((gc_region_size * nhp * 19) > gc_heap::regions_range))
+ {
+ return E_INVALIDARG;
+ }
+ gc_heap::min_segment_size_shr = index_of_highest_set_bit (gc_region_size);
#else
gc_heap::min_segment_size_shr = index_of_highest_set_bit (gc_heap::min_segment_size);
#endif //USE_REGIONS
diff --git a/src/coreclr/gc/gcconfig.h b/src/coreclr/gc/gcconfig.h
index e7b5e1f21804de..0ab210bf48c3e0 100644
--- a/src/coreclr/gc/gcconfig.h
+++ b/src/coreclr/gc/gcconfig.h
@@ -102,7 +102,8 @@ class GCConfigStringHolder
INT_CONFIG (GCHeapHardLimit, "GCHeapHardLimit", "System.GC.HeapHardLimit", 0, "Specifies a hard limit for the GC heap") \
INT_CONFIG (GCHeapHardLimitPercent, "GCHeapHardLimitPercent", "System.GC.HeapHardLimitPercent", 0, "Specifies the GC heap usage as a percentage of the total memory") \
INT_CONFIG (GCTotalPhysicalMemory, "GCTotalPhysicalMemory", NULL, 0, "Specifies what the GC should consider to be total physical memory") \
- INT_CONFIG (GCRegionsRange, "GCRegionsRange", NULL, 0, "Specifies the range for the GC heap") \
+ INT_CONFIG (GCRegionsRange, "GCRegionsRange", NULL, 274877906944L, "Specifies the range for the GC heap") \
+ INT_CONFIG (GCRegionsSize, "GCRegionsSize", NULL, 4194304, "Specifies the size for a basic GC region") \
STRING_CONFIG(LogFile, "GCLogFile", NULL, "Specifies the name of the GC log file") \
STRING_CONFIG(ConfigLogFile, "GCConfigLogFile", NULL, "Specifies the name of the GC config log file") \
INT_CONFIG (BGCFLTuningEnabled, "BGCFLTuningEnabled", NULL, 0, "Enables FL tuning") \
diff --git a/src/coreclr/gc/gcpriv.h b/src/coreclr/gc/gcpriv.h
index f8455ac323cd0c..1cfc2f229ac089 100644
--- a/src/coreclr/gc/gcpriv.h
+++ b/src/coreclr/gc/gcpriv.h
@@ -5278,8 +5278,6 @@ class heap_segment
// and free_large_regions. These decommitted regions will be returned to region_allocator which
// mark the space as free blocks.
//
-// Make configs available to change these.
-#define REGION_SIZE ((size_t)4 * 1024 * 1024)
#define LARGE_REGION_FACTOR (8)
#define region_alloc_free_bit (1 << (sizeof (uint32_t) * 8 - 1))
diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h
index cda748635c721e..5e6a2ef98993e2 100644
--- a/src/coreclr/inc/jiteeversionguid.h
+++ b/src/coreclr/inc/jiteeversionguid.h
@@ -16,7 +16,7 @@
// Note that this file is parsed by some tools, namely superpmi.py, so make sure the first line is exactly
// of the form:
//
-// constexpr GUID JITEEVersionIdentifier = { /* a7bb194e-4e7c-4850-af12-ea9f30ea5a13 */
+// constexpr GUID JITEEVersionIdentifier = { /* 1776ab48-edfa-49be-a11f-ec216b28174c */
//
// (without the leading slashes or spaces).
//
@@ -43,11 +43,11 @@ typedef const GUID *LPCGUID;
#define GUID_DEFINED
#endif // !GUID_DEFINED
-constexpr GUID JITEEVersionIdentifier = { /* a1f5e9a1-ee44-42f9-9319-e2a2dbf8c5c9 */
- 0xa1f5e9a1,
- 0xee44,
- 0x42f9,
- {0x93, 0x19, 0xe2, 0xa2, 0xdb, 0xf8, 0xc5, 0xc9}
+constexpr GUID JITEEVersionIdentifier = { /* 1776ab48-edfa-49be-a11f-ec216b28174c */
+ 0x1776ab48,
+ 0xedfa,
+ 0x49be,
+ {0xa1, 0x1f, 0xec, 0x21, 0x6b, 0x28, 0x17, 0x4c}
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp
index 7dd138082fc564..56366cfd6d7707 100644
--- a/src/coreclr/jit/assertionprop.cpp
+++ b/src/coreclr/jit/assertionprop.cpp
@@ -541,12 +541,14 @@ void Compiler::optAssertionInit(bool isLocalProp)
if (!isLocalProp)
{
- optValueNumToAsserts = new (getAllocator()) ValueNumToAssertsMap(getAllocator());
+ optValueNumToAsserts =
+ new (getAllocator(CMK_AssertionProp)) ValueNumToAssertsMap(getAllocator(CMK_AssertionProp));
}
if (optAssertionDep == nullptr)
{
- optAssertionDep = new (this, CMK_AssertionProp) JitExpandArray(getAllocator(), max(1, lvaCount));
+ optAssertionDep =
+ new (this, CMK_AssertionProp) JitExpandArray(getAllocator(CMK_AssertionProp), max(1, lvaCount));
}
optAssertionTraitsInit(optMaxAssertionCount);
@@ -2666,12 +2668,10 @@ GenTree* Compiler::optConstantAssertionProp(AssertionDsc* curAssertion,
{
const unsigned lclNum = tree->GetLclNum();
-#if FEATURE_ANYCSE
if (lclNumIsCSE(lclNum))
{
return nullptr;
}
-#endif
GenTree* newTree = tree;
@@ -5167,13 +5167,11 @@ Compiler::fgWalkResult Compiler::optVNConstantPropCurStmt(BasicBlock* block, Sta
{
return WALK_CONTINUE;
}
-#if FEATURE_ANYCSE
// Let's not conflict with CSE (to save the movw/movt).
if (lclNumIsCSE(tree->AsLclVarCommon()->GetLclNum()))
{
return WALK_CONTINUE;
}
-#endif
break;
default:
diff --git a/src/coreclr/jit/block.h b/src/coreclr/jit/block.h
index aa15fa4f311df0..e411d6b32f9da1 100644
--- a/src/coreclr/jit/block.h
+++ b/src/coreclr/jit/block.h
@@ -537,7 +537,7 @@ struct BasicBlock : private LIR::Range
weight_t bbWeight; // The dynamic execution weight of this block
// getCalledCount -- get the value used to normalize weights for this method
- weight_t getCalledCount(Compiler* comp);
+ static weight_t getCalledCount(Compiler* comp);
// getBBWeight -- get the normalized weight of this block
weight_t getBBWeight(Compiler* comp);
@@ -647,9 +647,9 @@ struct BasicBlock : private LIR::Range
}
}
- bool isMaxBBWeight()
+ bool isMaxBBWeight() const
{
- return (bbWeight == BB_MAX_WEIGHT);
+ return (bbWeight >= BB_MAX_WEIGHT);
}
// Returns "true" if the block is empty. Empty here means there are no statement
diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp
index 0219f104b47f22..19f374ffe27e73 100644
--- a/src/coreclr/jit/compiler.cpp
+++ b/src/coreclr/jit/compiler.cpp
@@ -1830,7 +1830,7 @@ void Compiler::compInit(ArenaAllocator* pAlloc,
bRangeAllowStress = false;
#endif
-#if defined(DEBUG) || defined(LATE_DISASM)
+#if defined(DEBUG) || defined(LATE_DISASM) || DUMP_FLOWGRAPHS
// Initialize the method name and related info, as it is used early in determining whether to
// apply stress modes, and which ones to apply.
// Note that even allocating memory can invoke the stress mechanism, so ensure that both
@@ -1852,7 +1852,7 @@ void Compiler::compInit(ArenaAllocator* pAlloc,
info.compFullName = eeGetMethodFullName(methodHnd);
info.compPerfScore = 0.0;
-#endif // defined(DEBUG) || defined(LATE_DISASM)
+#endif // defined(DEBUG) || defined(LATE_DISASM) || DUMP_FLOWGRAPHS
#if defined(DEBUG) || defined(INLINE_DATA)
info.compMethodHashPrivate = 0;
@@ -5027,11 +5027,9 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
DoPhase(this, PHASE_OPTIMIZE_BRANCHES, &Compiler::optRedundantBranches);
}
-#if FEATURE_ANYCSE
// Remove common sub-expressions
//
DoPhase(this, PHASE_OPTIMIZE_VALNUM_CSES, &Compiler::optOptimizeCSEs);
-#endif // FEATURE_ANYCSE
#if ASSERTION_PROP
if (doAssertionProp)
@@ -5997,11 +5995,7 @@ void Compiler::compCompileFinish()
else
{
printf(" %3d |", optAssertionCount);
-#if FEATURE_ANYCSE
printf(" %3d |", optCSEcount);
-#else
- printf(" %3d |", 0);
-#endif // FEATURE_ANYCSE
}
if (info.compPerfScore < 9999.995)
diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h
index e3afb451f69955..584e3568f7f51a 100644
--- a/src/coreclr/jit/compiler.h
+++ b/src/coreclr/jit/compiler.h
@@ -78,9 +78,7 @@ struct InitVarDscInfo; // defined in register_arg_convention.h
class FgStack; // defined in fgbasic.cpp
class Instrumentor; // defined in fgprofile.cpp
class SpanningTreeVisitor; // defined in fgprofile.cpp
-#if FEATURE_ANYCSE
-class CSE_DataFlow; // defined in OptCSE.cpp
-#endif
+class CSE_DataFlow; // defined in OptCSE.cpp
#ifdef DEBUG
struct IndentStack;
#endif
@@ -2742,6 +2740,7 @@ class Compiler
GenTree* gtNewIconEmbFldHndNode(CORINFO_FIELD_HANDLE fldHnd);
GenTree* gtNewStringLiteralNode(InfoAccessType iat, void* pValue);
+ GenTreeIntCon* gtNewStringLiteralLength(GenTreeStrCon* node);
GenTree* gtNewLconNode(__int64 value);
@@ -5507,7 +5506,6 @@ class Compiler
const char* fgProcessEscapes(const char* nameIn, escapeMapping_t* map);
FILE* fgOpenFlowGraphFile(bool* wbDontClose, Phases phase, LPCWSTR type);
bool fgDumpFlowGraph(Phases phase);
-
#endif // DUMP_FLOWGRAPHS
#ifdef DEBUG
@@ -5850,7 +5848,6 @@ class Compiler
unsigned argIndex,
CORINFO_CLASS_HANDLE copyBlkClass);
- void fgFixupStructReturn(GenTree* call);
GenTree* fgMorphLocalVar(GenTree* tree, bool forceRemorph);
public:
@@ -6546,6 +6543,15 @@ class Compiler
}
}
+ // Struct used in optInvertWhileLoop to count interesting constructs to boost the profitability score.
+ struct OptInvertCountTreeInfoType
+ {
+ int sharedStaticHelperCount;
+ int arrayLengthCount;
+ };
+
+ static fgWalkResult optInvertCountTreeInfo(GenTree** pTree, fgWalkData* data);
+
void optInvertWhileLoop(BasicBlock* block);
bool optComputeLoopRep(int constInit,
@@ -6574,13 +6580,8 @@ class Compiler
* Optimization conditions
*************************************************************************/
- bool optFastCodeOrBlendedLoop(BasicBlock::weight_t bbWeight);
- bool optPentium4(void);
- bool optAvoidIncDec(BasicBlock::weight_t bbWeight);
bool optAvoidIntMult(void);
-#if FEATURE_ANYCSE
-
protected:
// The following is the upper limit on how many expressions we'll keep track
// of for the CSE analysis.
@@ -6740,9 +6741,6 @@ class Compiler
return (enckey & ~TARGET_SIGN_BIT) << CSE_CONST_SHARED_LOW_BITS;
}
-#endif // FEATURE_ANYCSE
-
-#if FEATURE_VALNUM_CSE
/**************************************************************************
* Value Number based CSEs
*************************************************************************/
@@ -6759,9 +6757,6 @@ class Compiler
void optValnumCSE_Availablity();
void optValnumCSE_Heuristic();
-#endif // FEATURE_VALNUM_CSE
-
-#if FEATURE_ANYCSE
bool optDoCSE; // True when we have found a duplicate CSE tree
bool optValnumCSE_phase; // True when we are executing the optValnumCSE_phase
unsigned optCSECandidateTotal; // Grand total of CSE candidates for both Lexical and ValNum
@@ -6792,8 +6787,6 @@ class Compiler
#endif
void optOptimizeCSEs();
-#endif // FEATURE_ANYCSE
-
struct isVarAssgDsc
{
GenTree* ivaSkip;
@@ -9456,12 +9449,12 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
BOOL hasCircularClassConstraints;
BOOL hasCircularMethodConstraints;
-#if defined(DEBUG) || defined(LATE_DISASM)
+#if defined(DEBUG) || defined(LATE_DISASM) || DUMP_FLOWGRAPHS
const char* compMethodName;
const char* compClassName;
const char* compFullName;
double compPerfScore;
-#endif // defined(DEBUG) || defined(LATE_DISASM)
+#endif // defined(DEBUG) || defined(LATE_DISASM) || DUMP_FLOWGRAPHS
#if defined(DEBUG) || defined(INLINE_DATA)
// Method hash is logcally const, but computed
@@ -9623,11 +9616,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#endif // TARGET_AMD64
}
- bool compDoOldStructRetyping()
- {
- return JitConfig.JitDoOldStructRetyping();
- }
-
// Returns true if the method returns a value in more than one return register
// TODO-ARM-Bug: Deal with multi-register genReturnLocaled structs?
// TODO-ARM64: Does this apply for ARM64 too?
diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp
index 9afb2b8c5baa3d..50a39a4d071f73 100644
--- a/src/coreclr/jit/compiler.hpp
+++ b/src/coreclr/jit/compiler.hpp
@@ -902,9 +902,7 @@ inline GenTree::GenTree(genTreeOps oper, var_types type DEBUGARG(bool largeNode)
#ifdef DEBUG
gtDebugFlags = 0;
#endif // DEBUG
-#if FEATURE_ANYCSE
gtCSEnum = NO_CSE;
-#endif // FEATURE_ANYCSE
#if ASSERTION_PROP
ClearAssertion();
#endif
@@ -3616,27 +3614,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
*/
-// are we compiling for fast code, or are we compiling for blended code and
-// inside a loop?
-// We return true for BLENDED_CODE if the Block executes more than BB_LOOP_WEIGHT_SCALE/2
-inline bool Compiler::optFastCodeOrBlendedLoop(BasicBlock::weight_t bbWeight)
-{
- return (compCodeOpt() == FAST_CODE) ||
- ((compCodeOpt() == BLENDED_CODE) && (bbWeight > ((BB_LOOP_WEIGHT_SCALE / 2) * BB_UNITY_WEIGHT)));
-}
-
-// are we running on a Intel Pentium 4?
-inline bool Compiler::optPentium4(void)
-{
- return (info.genCPU == CPU_X86_PENTIUM_4);
-}
-
-// should we use add/sub instead of inc/dec? (faster on P4, but increases size)
-inline bool Compiler::optAvoidIncDec(BasicBlock::weight_t bbWeight)
-{
- return optPentium4() && optFastCodeOrBlendedLoop(bbWeight);
-}
-
// should we try to replace integer multiplication with lea/add/shift sequences?
inline bool Compiler::optAvoidIntMult(void)
{
@@ -4181,7 +4158,7 @@ inline void Compiler::CLR_API_Leave(API_ICorJitInfo_Names ename)
bool Compiler::fgVarIsNeverZeroInitializedInProlog(unsigned varNum)
{
LclVarDsc* varDsc = lvaGetDesc(varNum);
- bool result = varDsc->lvIsParam || lvaIsOSRLocal(varNum) || (opts.IsOSR() && (varNum == lvaGSSecurityCookie)) ||
+ bool result = varDsc->lvIsParam || lvaIsOSRLocal(varNum) || (varNum == lvaGSSecurityCookie) ||
(varNum == lvaInlinedPInvokeFrameVar) || (varNum == lvaStubArgumentVar) || (varNum == lvaRetAddrVar);
#if FEATURE_FIXED_OUT_ARGS
diff --git a/src/coreclr/jit/compmemkind.h b/src/coreclr/jit/compmemkind.h
index 1d8e0a82fe9c82..969b0c3dc2a7b5 100644
--- a/src/coreclr/jit/compmemkind.h
+++ b/src/coreclr/jit/compmemkind.h
@@ -47,6 +47,7 @@ CompMemKindMacro(DebugInfo)
CompMemKindMacro(DebugOnly)
CompMemKindMacro(Codegen)
CompMemKindMacro(LoopOpt)
+CompMemKindMacro(LoopClone)
CompMemKindMacro(LoopHoist)
CompMemKindMacro(Unknown)
CompMemKindMacro(RangeCheck)
diff --git a/src/coreclr/jit/compphases.h b/src/coreclr/jit/compphases.h
index 49303ecbd64b9c..bb992440f8e3d4 100644
--- a/src/coreclr/jit/compphases.h
+++ b/src/coreclr/jit/compphases.h
@@ -72,16 +72,10 @@ CompPhaseNameMacro(PHASE_BUILD_SSA_LIVENESS, "SSA: liveness",
CompPhaseNameMacro(PHASE_BUILD_SSA_DF, "SSA: DF", "SSA-DF", false, PHASE_BUILD_SSA, false)
CompPhaseNameMacro(PHASE_BUILD_SSA_INSERT_PHIS, "SSA: insert phis", "SSA-PHI", false, PHASE_BUILD_SSA, false)
CompPhaseNameMacro(PHASE_BUILD_SSA_RENAME, "SSA: rename", "SSA-REN", false, PHASE_BUILD_SSA, false)
-
CompPhaseNameMacro(PHASE_EARLY_PROP, "Early Value Propagation", "ERL-PROP", false, -1, false)
CompPhaseNameMacro(PHASE_VALUE_NUMBER, "Do value numbering", "VAL-NUM", false, -1, false)
-
CompPhaseNameMacro(PHASE_OPTIMIZE_INDEX_CHECKS, "Optimize index checks", "OPT-CHK", false, -1, false)
-
-#if FEATURE_VALNUM_CSE
CompPhaseNameMacro(PHASE_OPTIMIZE_VALNUM_CSES, "Optimize Valnum CSEs", "OPT-CSE", false, -1, false)
-#endif
-
CompPhaseNameMacro(PHASE_VN_COPY_PROP, "VN based copy prop", "CP-PROP", false, -1, false)
CompPhaseNameMacro(PHASE_OPTIMIZE_BRANCHES, "Redundant branch opts", "OPT-BR", false, -1, false)
#if ASSERTION_PROP
diff --git a/src/coreclr/jit/emit.cpp b/src/coreclr/jit/emit.cpp
index 74b62dd4b208a8..6c61e7065fbc8e 100644
--- a/src/coreclr/jit/emit.cpp
+++ b/src/coreclr/jit/emit.cpp
@@ -133,7 +133,7 @@ unsigned emitter::emitTotalIGptrs;
unsigned emitter::emitTotalIGicnt;
size_t emitter::emitTotalIGsize;
unsigned emitter::emitTotalIGmcnt;
-unsigned emitter::emitTotalIGextend;
+unsigned emitter::emitTotalIGExtend;
unsigned emitter::emitTotalIDescSmallCnt;
unsigned emitter::emitTotalIDescCnt;
@@ -170,105 +170,105 @@ void emitterStaticStats(FILE* fout)
fprintf(fout, "\n");
fprintf(fout, "insGroup:\n");
- fprintf(fout, "Offset / size of igNext = %2u / %2u\n", offsetof(insGroup, igNext),
+ fprintf(fout, "Offset / size of igNext = %2zu / %2zu\n", offsetof(insGroup, igNext),
sizeof(igDummy->igNext));
#ifdef DEBUG
- fprintf(fout, "Offset / size of igSelf = %2u / %2u\n", offsetof(insGroup, igSelf),
+ fprintf(fout, "Offset / size of igSelf = %2zu / %2zu\n", offsetof(insGroup, igSelf),
sizeof(igDummy->igSelf));
#endif
- fprintf(fout, "Offset / size of igNum = %2u / %2u\n", offsetof(insGroup, igNum),
+ fprintf(fout, "Offset / size of igNum = %2zu / %2zu\n", offsetof(insGroup, igNum),
sizeof(igDummy->igNum));
- fprintf(fout, "Offset / size of igOffs = %2u / %2u\n", offsetof(insGroup, igOffs),
+ fprintf(fout, "Offset / size of igOffs = %2zu / %2zu\n", offsetof(insGroup, igOffs),
sizeof(igDummy->igOffs));
- fprintf(fout, "Offset / size of igFuncIdx = %2u / %2u\n", offsetof(insGroup, igFuncIdx),
+ fprintf(fout, "Offset / size of igFuncIdx = %2zu / %2zu\n", offsetof(insGroup, igFuncIdx),
sizeof(igDummy->igFuncIdx));
- fprintf(fout, "Offset / size of igFlags = %2u / %2u\n", offsetof(insGroup, igFlags),
+ fprintf(fout, "Offset / size of igFlags = %2zu / %2zu\n", offsetof(insGroup, igFlags),
sizeof(igDummy->igFlags));
- fprintf(fout, "Offset / size of igSize = %2u / %2u\n", offsetof(insGroup, igSize),
+ fprintf(fout, "Offset / size of igSize = %2zu / %2zu\n", offsetof(insGroup, igSize),
sizeof(igDummy->igSize));
- fprintf(fout, "Offset / size of igData = %2u / %2u\n", offsetof(insGroup, igData),
+ fprintf(fout, "Offset / size of igData = %2zu / %2zu\n", offsetof(insGroup, igData),
sizeof(igDummy->igData));
- fprintf(fout, "Offset / size of igPhData = %2u / %2u\n", offsetof(insGroup, igPhData),
+ fprintf(fout, "Offset / size of igPhData = %2zu / %2zu\n", offsetof(insGroup, igPhData),
sizeof(igDummy->igPhData));
#if EMIT_TRACK_STACK_DEPTH
- fprintf(fout, "Offset / size of igStkLvl = %2u / %2u\n", offsetof(insGroup, igStkLvl),
+ fprintf(fout, "Offset / size of igStkLvl = %2zu / %2zu\n", offsetof(insGroup, igStkLvl),
sizeof(igDummy->igStkLvl));
#endif
- fprintf(fout, "Offset / size of igGCregs = %2u / %2u\n", offsetof(insGroup, igGCregs),
+ fprintf(fout, "Offset / size of igGCregs = %2zu / %2zu\n", offsetof(insGroup, igGCregs),
sizeof(igDummy->igGCregs));
- fprintf(fout, "Offset / size of igInsCnt = %2u / %2u\n", offsetof(insGroup, igInsCnt),
+ fprintf(fout, "Offset / size of igInsCnt = %2zu / %2zu\n", offsetof(insGroup, igInsCnt),
sizeof(igDummy->igInsCnt));
fprintf(fout, "\n");
- fprintf(fout, "Size of insGroup = %u\n", sizeof(insGroup));
+ fprintf(fout, "Size of insGroup = %zu\n", sizeof(insGroup));
// insPlaceholderGroupData members
fprintf(fout, "\n");
fprintf(fout, "insPlaceholderGroupData:\n");
- fprintf(fout, "Offset of igPhNext = %2u\n", offsetof(insPlaceholderGroupData, igPhNext));
- fprintf(fout, "Offset of igPhBB = %2u\n", offsetof(insPlaceholderGroupData, igPhBB));
- fprintf(fout, "Offset of igPhInitGCrefVars = %2u\n", offsetof(insPlaceholderGroupData, igPhInitGCrefVars));
- fprintf(fout, "Offset of igPhInitGCrefRegs = %2u\n", offsetof(insPlaceholderGroupData, igPhInitGCrefRegs));
- fprintf(fout, "Offset of igPhInitByrefRegs = %2u\n", offsetof(insPlaceholderGroupData, igPhInitByrefRegs));
- fprintf(fout, "Offset of igPhPrevGCrefVars = %2u\n", offsetof(insPlaceholderGroupData, igPhPrevGCrefVars));
- fprintf(fout, "Offset of igPhPrevGCrefRegs = %2u\n", offsetof(insPlaceholderGroupData, igPhPrevGCrefRegs));
- fprintf(fout, "Offset of igPhPrevByrefRegs = %2u\n", offsetof(insPlaceholderGroupData, igPhPrevByrefRegs));
- fprintf(fout, "Offset of igPhType = %2u\n", offsetof(insPlaceholderGroupData, igPhType));
- fprintf(fout, "Size of insPlaceholderGroupData = %u\n", sizeof(insPlaceholderGroupData));
+ fprintf(fout, "Offset of igPhNext = %2zu\n", offsetof(insPlaceholderGroupData, igPhNext));
+ fprintf(fout, "Offset of igPhBB = %2zu\n", offsetof(insPlaceholderGroupData, igPhBB));
+ fprintf(fout, "Offset of igPhInitGCrefVars = %2zu\n", offsetof(insPlaceholderGroupData, igPhInitGCrefVars));
+ fprintf(fout, "Offset of igPhInitGCrefRegs = %2zu\n", offsetof(insPlaceholderGroupData, igPhInitGCrefRegs));
+ fprintf(fout, "Offset of igPhInitByrefRegs = %2zu\n", offsetof(insPlaceholderGroupData, igPhInitByrefRegs));
+ fprintf(fout, "Offset of igPhPrevGCrefVars = %2zu\n", offsetof(insPlaceholderGroupData, igPhPrevGCrefVars));
+ fprintf(fout, "Offset of igPhPrevGCrefRegs = %2zu\n", offsetof(insPlaceholderGroupData, igPhPrevGCrefRegs));
+ fprintf(fout, "Offset of igPhPrevByrefRegs = %2zu\n", offsetof(insPlaceholderGroupData, igPhPrevByrefRegs));
+ fprintf(fout, "Offset of igPhType = %2zu\n", offsetof(insPlaceholderGroupData, igPhType));
+ fprintf(fout, "Size of insPlaceholderGroupData = %zu\n", sizeof(insPlaceholderGroupData));
fprintf(fout, "\n");
fprintf(fout, "SMALL_IDSC_SIZE = %2u\n", SMALL_IDSC_SIZE);
- fprintf(fout, "Size of instrDesc = %2u\n", sizeof(emitter::instrDesc));
- // fprintf(fout, "Offset of _idIns = %2u\n", offsetof(emitter::instrDesc, _idIns ));
- // fprintf(fout, "Offset of _idInsFmt = %2u\n", offsetof(emitter::instrDesc, _idInsFmt ));
- // fprintf(fout, "Offset of _idOpSize = %2u\n", offsetof(emitter::instrDesc, _idOpSize ));
- // fprintf(fout, "Offset of idSmallCns = %2u\n", offsetof(emitter::instrDesc, idSmallCns ));
- // fprintf(fout, "Offset of _idAddrUnion= %2u\n", offsetof(emitter::instrDesc, _idAddrUnion));
+ fprintf(fout, "Size of instrDesc = %2zu\n", sizeof(emitter::instrDesc));
+ // fprintf(fout, "Offset of _idIns = %2zu\n", offsetof(emitter::instrDesc, _idIns ));
+ // fprintf(fout, "Offset of _idInsFmt = %2zu\n", offsetof(emitter::instrDesc, _idInsFmt ));
+ // fprintf(fout, "Offset of _idOpSize = %2zu\n", offsetof(emitter::instrDesc, _idOpSize ));
+ // fprintf(fout, "Offset of idSmallCns = %2zu\n", offsetof(emitter::instrDesc, idSmallCns ));
+ // fprintf(fout, "Offset of _idAddrUnion= %2zu\n", offsetof(emitter::instrDesc, _idAddrUnion));
// fprintf(fout, "\n");
- // fprintf(fout, "Size of _idAddrUnion= %2u\n", sizeof(((emitter::instrDesc*)0)->_idAddrUnion));
+ // fprintf(fout, "Size of _idAddrUnion= %2zu\n", sizeof(((emitter::instrDesc*)0)->_idAddrUnion));
- fprintf(fout, "Size of instrDescJmp = %2u\n", sizeof(emitter::instrDescJmp));
+ fprintf(fout, "Size of instrDescJmp = %2zu\n", sizeof(emitter::instrDescJmp));
#if !defined(TARGET_ARM64)
- fprintf(fout, "Size of instrDescLbl = %2u\n", sizeof(emitter::instrDescLbl));
+ fprintf(fout, "Size of instrDescLbl = %2zu\n", sizeof(emitter::instrDescLbl));
#endif // !defined(TARGET_ARM64)
- fprintf(fout, "Size of instrDescCns = %2u\n", sizeof(emitter::instrDescCns));
- fprintf(fout, "Size of instrDescDsp = %2u\n", sizeof(emitter::instrDescDsp));
- fprintf(fout, "Size of instrDescCnsDsp = %2u\n", sizeof(emitter::instrDescCnsDsp));
+ fprintf(fout, "Size of instrDescCns = %2zu\n", sizeof(emitter::instrDescCns));
+ fprintf(fout, "Size of instrDescDsp = %2zu\n", sizeof(emitter::instrDescDsp));
+ fprintf(fout, "Size of instrDescCnsDsp = %2zu\n", sizeof(emitter::instrDescCnsDsp));
#ifdef TARGET_XARCH
- fprintf(fout, "Size of instrDescAmd = %2u\n", sizeof(emitter::instrDescAmd));
- fprintf(fout, "Size of instrDescCnsAmd = %2u\n", sizeof(emitter::instrDescCnsAmd));
+ fprintf(fout, "Size of instrDescAmd = %2zu\n", sizeof(emitter::instrDescAmd));
+ fprintf(fout, "Size of instrDescCnsAmd = %2zu\n", sizeof(emitter::instrDescCnsAmd));
#endif // TARGET_XARCH
- fprintf(fout, "Size of instrDescCGCA = %2u\n", sizeof(emitter::instrDescCGCA));
+ fprintf(fout, "Size of instrDescCGCA = %2zu\n", sizeof(emitter::instrDescCGCA));
#ifdef TARGET_ARM
- fprintf(fout, "Size of instrDescReloc = %2u\n", sizeof(emitter::instrDescReloc));
+ fprintf(fout, "Size of instrDescReloc = %2zu\n", sizeof(emitter::instrDescReloc));
#endif // TARGET_ARM
fprintf(fout, "\n");
- fprintf(fout, "SC_IG_BUFFER_SIZE = %2u\n", SC_IG_BUFFER_SIZE);
- fprintf(fout, "SMALL_IDSC_SIZE per IG buffer = %2u\n", SC_IG_BUFFER_SIZE / SMALL_IDSC_SIZE);
- fprintf(fout, "instrDesc per IG buffer = %2u\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDesc));
- fprintf(fout, "instrDescJmp per IG buffer = %2u\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDescJmp));
+ fprintf(fout, "SC_IG_BUFFER_SIZE = %2zu\n", SC_IG_BUFFER_SIZE);
+ fprintf(fout, "SMALL_IDSC_SIZE per IG buffer = %2zu\n", SC_IG_BUFFER_SIZE / SMALL_IDSC_SIZE);
+ fprintf(fout, "instrDesc per IG buffer = %2zu\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDesc));
+ fprintf(fout, "instrDescJmp per IG buffer = %2zu\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDescJmp));
#if !defined(TARGET_ARM64)
- fprintf(fout, "instrDescLbl per IG buffer = %2u\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDescLbl));
+ fprintf(fout, "instrDescLbl per IG buffer = %2zu\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDescLbl));
#endif // !defined(TARGET_ARM64)
- fprintf(fout, "instrDescCns per IG buffer = %2u\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDescCns));
- fprintf(fout, "instrDescDsp per IG buffer = %2u\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDescDsp));
- fprintf(fout, "instrDescCnsDsp per IG buffer = %2u\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDescCnsDsp));
+ fprintf(fout, "instrDescCns per IG buffer = %2zu\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDescCns));
+ fprintf(fout, "instrDescDsp per IG buffer = %2zu\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDescDsp));
+ fprintf(fout, "instrDescCnsDsp per IG buffer = %2zu\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDescCnsDsp));
#ifdef TARGET_XARCH
- fprintf(fout, "instrDescAmd per IG buffer = %2u\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDescAmd));
- fprintf(fout, "instrDescCnsAmd per IG buffer = %2u\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDescCnsAmd));
+ fprintf(fout, "instrDescAmd per IG buffer = %2zu\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDescAmd));
+ fprintf(fout, "instrDescCnsAmd per IG buffer = %2zu\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDescCnsAmd));
#endif // TARGET_XARCH
- fprintf(fout, "instrDescCGCA per IG buffer = %2u\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDescCGCA));
+ fprintf(fout, "instrDescCGCA per IG buffer = %2zu\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDescCGCA));
#ifdef TARGET_ARM
- fprintf(fout, "instrDescReloc per IG buffer = %2u\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDescReloc));
+ fprintf(fout, "instrDescReloc per IG buffer = %2zu\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDescReloc));
#endif // TARGET_ARM
fprintf(fout, "\n");
fprintf(fout, "GCInfo::regPtrDsc:\n");
- fprintf(fout, "Offset of rpdNext = %2u\n", offsetof(GCInfo::regPtrDsc, rpdNext));
- fprintf(fout, "Offset of rpdOffs = %2u\n", offsetof(GCInfo::regPtrDsc, rpdOffs));
- fprintf(fout, "Offset of = %2u\n", offsetof(GCInfo::regPtrDsc, rpdPtrArg));
- fprintf(fout, "Size of GCInfo::regPtrDsc = %2u\n", sizeof(GCInfo::regPtrDsc));
+ fprintf(fout, "Offset of rpdNext = %2zu\n", offsetof(GCInfo::regPtrDsc, rpdNext));
+ fprintf(fout, "Offset of rpdOffs = %2zu\n", offsetof(GCInfo::regPtrDsc, rpdOffs));
+ fprintf(fout, "Offset of = %2zu\n", offsetof(GCInfo::regPtrDsc, rpdPtrArg));
+ fprintf(fout, "Size of GCInfo::regPtrDsc = %2zu\n", sizeof(GCInfo::regPtrDsc));
fprintf(fout, "\n");
}
@@ -324,19 +324,19 @@ void emitterStats(FILE* fout)
fprintf(fout, "Total of %8u methods\n", emitter::emitTotalIGmcnt);
fprintf(fout, "Total of %8u insGroup\n", emitter::emitTotalIGcnt);
fprintf(fout, "Total of %8u insPlaceholderGroupData\n", emitter::emitTotalPhIGcnt);
- fprintf(fout, "Total of %8u extend insGroup\n", emitter::emitTotalIGextend);
+ fprintf(fout, "Total of %8u extend insGroup\n", emitter::emitTotalIGExtend);
fprintf(fout, "Total of %8u instructions\n", emitter::emitTotalIGicnt);
fprintf(fout, "Total of %8u jumps\n", emitter::emitTotalIGjmps);
fprintf(fout, "Total of %8u GC livesets\n", emitter::emitTotalIGptrs);
fprintf(fout, "\n");
fprintf(fout, "Max prolog instrDesc count: %8u\n", emitter::emitMaxPrologInsCnt);
- fprintf(fout, "Max prolog insGroup size : %8u\n", emitter::emitMaxPrologIGSize);
+ fprintf(fout, "Max prolog insGroup size : %8zu\n", emitter::emitMaxPrologIGSize);
fprintf(fout, "\n");
fprintf(fout, "Average of %8.1lf insGroup per method\n",
(double)emitter::emitTotalIGcnt / emitter::emitTotalIGmcnt);
fprintf(fout, "Average of %8.1lf insPhGroup per method\n",
(double)emitter::emitTotalPhIGcnt / emitter::emitTotalIGmcnt);
- fprintf(fout, "Average of %8.1lf extend IG per method\n",
+ fprintf(fout, "Average of %8.1lf extend IG per method\n",
(double)emitter::emitTotalIGExtend / emitter::emitTotalIGmcnt);
fprintf(fout, "Average of %8.1lf instructions per method\n",
(double)emitter::emitTotalIGicnt / emitter::emitTotalIGmcnt);
@@ -357,7 +357,7 @@ void emitterStats(FILE* fout)
fprintf(fout, "Average of %8.1lf bytes per instrDesc\n",
(double)emitter::emitTotalIGsize / emitter::emitTotalIGicnt);
fprintf(fout, "\n");
- fprintf(fout, "A total of %8u desc. bytes\n", emitter::emitTotalIGsize);
+ fprintf(fout, "A total of %8zu desc. bytes\n", emitter::emitTotalIGsize);
fprintf(fout, "\n");
fprintf(fout, "Total instructions: %8u\n", emitter::emitTotalInsCnt);
@@ -389,7 +389,7 @@ void emitterStats(FILE* fout)
fprintf(fout, "Total instrDescReloc: %8u (%5.2f%%)\n", emitter::emitTotalIDescRelocCnt,
100.0 * emitter::emitTotalIDescRelocCnt / emitter::emitTotalInsCnt);
#endif // TARGET_ARM
- fprintf(fout, "Total emitTotalDescAlignCnt: %8u (%5.2f%%)\n", emitter::emitTotalDescAlignCnt,
+ fprintf(fout, "Total instrDescAlign: %8u (%5.2f%%)\n", emitter::emitTotalDescAlignCnt,
100.0 * emitter::emitTotalDescAlignCnt / emitter::emitTotalInsCnt);
fprintf(fout, "\n");
@@ -439,7 +439,7 @@ void emitterStats(FILE* fout)
}
}
- fprintf(fout, "%8u bytes allocated in the emitter\n", emitter::emitTotMemAlloc);
+ fprintf(fout, "%8zu bytes allocated in the emitter\n", emitter::emitTotMemAlloc);
}
#endif // EMITTER_STATS
diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h
index 50311c555c684f..0b442d16cb9f1e 100644
--- a/src/coreclr/jit/emit.h
+++ b/src/coreclr/jit/emit.h
@@ -1944,7 +1944,7 @@ class emitter
instrDescJmp* emitAllocInstrJmp()
{
#if EMITTER_STATS
- emitTotalDescAlignCnt++;
+ emitTotalIDescJmpCnt++;
#endif // EMITTER_STATS
return (instrDescJmp*)emitAllocAnyInstr(sizeof(instrDescJmp), EA_1BYTE);
}
@@ -2023,7 +2023,7 @@ class emitter
instrDescAlign* emitAllocInstrAlign()
{
#if EMITTER_STATS
- emitTotalIDescJmpCnt++;
+ emitTotalDescAlignCnt++;
#endif // EMITTER_STATS
return (instrDescAlign*)emitAllocAnyInstr(sizeof(instrDescAlign), EA_1BYTE);
}
diff --git a/src/coreclr/jit/emitarm.cpp b/src/coreclr/jit/emitarm.cpp
index a2001cf0ffcd5a..ef122d6a3166ef 100644
--- a/src/coreclr/jit/emitarm.cpp
+++ b/src/coreclr/jit/emitarm.cpp
@@ -7742,7 +7742,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR
if (addr->isContained())
{
- assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
+ assert(addr->OperIs(GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR, GT_LEA));
DWORD lsl = 0;
@@ -7827,7 +7827,21 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR
}
else // no Index
{
- if (emitIns_valid_imm_for_ldst_offset(offset, attr))
+ if (addr->OperIs(GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR))
+ {
+ GenTreeLclVarCommon* varNode = addr->AsLclVarCommon();
+ unsigned lclNum = varNode->GetLclNum();
+ unsigned offset = varNode->GetLclOffs();
+ if (emitInsIsStore(ins))
+ {
+ emitIns_S_R(ins, attr, dataReg, lclNum, offset);
+ }
+ else
+ {
+ emitIns_R_S(ins, attr, dataReg, lclNum, offset);
+ }
+ }
+ else if (emitIns_valid_imm_for_ldst_offset(offset, attr))
{
// Then load/store dataReg from/to [memBase + offset]
emitIns_R_R_I(ins, attr, dataReg, memBase->GetRegNum(), offset);
@@ -7847,6 +7861,20 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR
}
else
{
+#ifdef DEBUG
+ if (addr->OperIs(GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR))
+ {
+ // If the local var is a gcref or byref, the local var better be untracked, because we have
+ // no logic here to track local variable lifetime changes, like we do in the contained case
+ // above. E.g., for a `str r0,[r1]` for byref `r1` to local `V01`, we won't store the local
+ // `V01` and so the emitter can't update the GC lifetime for `V01` if this is a variable birth.
+ GenTreeLclVarCommon* varNode = addr->AsLclVarCommon();
+ unsigned lclNum = varNode->GetLclNum();
+ LclVarDsc* varDsc = emitComp->lvaGetDesc(lclNum);
+ assert(!varDsc->lvTracked);
+ }
+#endif // DEBUG
+
if (offset != 0)
{
assert(emitIns_valid_imm_for_add(offset, INS_FLAGS_DONT_CARE));
diff --git a/src/coreclr/jit/emitarm64.cpp b/src/coreclr/jit/emitarm64.cpp
index 7be5d50604992f..223d7b3cb4e0c4 100644
--- a/src/coreclr/jit/emitarm64.cpp
+++ b/src/coreclr/jit/emitarm64.cpp
@@ -13510,6 +13510,20 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR
}
else // addr is not contained, so we evaluate it into a register
{
+#ifdef DEBUG
+ if (addr->OperIs(GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR))
+ {
+ // If the local var is a gcref or byref, the local var better be untracked, because we have
+ // no logic here to track local variable lifetime changes, like we do in the contained case
+ // above. E.g., for a `str r0,[r1]` for byref `r1` to local `V01`, we won't store the local
+ // `V01` and so the emitter can't update the GC lifetime for `V01` if this is a variable birth.
+ GenTreeLclVarCommon* varNode = addr->AsLclVarCommon();
+ unsigned lclNum = varNode->GetLclNum();
+ LclVarDsc* varDsc = emitComp->lvaGetDesc(lclNum);
+ assert(!varDsc->lvTracked);
+ }
+#endif // DEBUG
+
// Then load/store dataReg from/to [addrReg]
emitIns_R_R(ins, attr, dataReg, addr->GetRegNum());
}
diff --git a/src/coreclr/jit/fgbasic.cpp b/src/coreclr/jit/fgbasic.cpp
index 1f8bf814185eb8..024c32c22427c7 100644
--- a/src/coreclr/jit/fgbasic.cpp
+++ b/src/coreclr/jit/fgbasic.cpp
@@ -969,7 +969,7 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed
impResolveToken(codeAddr, &resolvedToken, CORINFO_TOKENKIND_Method);
eeGetCallInfo(&resolvedToken,
(prefixFlags & PREFIX_CONSTRAINED) ? &constrainedResolvedToken : nullptr,
- combine(CORINFO_CALLINFO_KINDONLY,
+ combine(combine(CORINFO_CALLINFO_KINDONLY, CORINFO_CALLINFO_ALLOWINSTPARAM),
(opcode == CEE_CALLVIRT) ? CORINFO_CALLINFO_CALLVIRT : CORINFO_CALLINFO_NONE),
&callInfo);
@@ -2560,14 +2560,7 @@ void Compiler::fgFindBasicBlocks()
{
// The lifetime of this var might expand multiple BBs. So it is a long lifetime compiler temp.
lvaInlineeReturnSpillTemp = lvaGrabTemp(false DEBUGARG("Inline return value spill temp"));
- if (compDoOldStructRetyping())
- {
- lvaTable[lvaInlineeReturnSpillTemp].lvType = info.compRetNativeType;
- }
- else
- {
- lvaTable[lvaInlineeReturnSpillTemp].lvType = info.compRetType;
- }
+ lvaTable[lvaInlineeReturnSpillTemp].lvType = info.compRetType;
// If the method returns a ref class, set the class of the spill temp
// to the method's return value. We may update this later if it turns
diff --git a/src/coreclr/jit/fgdiagnostic.cpp b/src/coreclr/jit/fgdiagnostic.cpp
index 1ae0151a9ba27f..78648c8d3cd9aa 100644
--- a/src/coreclr/jit/fgdiagnostic.cpp
+++ b/src/coreclr/jit/fgdiagnostic.cpp
@@ -342,6 +342,20 @@ static void fprintfDouble(FILE* fgxFile, double value)
// phase - A phase identifier to indicate which phase is associated with the dump
// type - A (wide) string indicating the type of dump, "dot" or "xml"
//
+// Notes:
+// The filename to use to write the data comes from the COMPlus_JitDumpFgFile or COMPlus_NgenDumpFgFile
+// configuration. If unset, use "default". The "type" argument is used as a filename extension,
+// e.g., "default.dot".
+//
+// There are several "special" filenames recognized:
+// "profiled" -- only create graphs for methods with profile info, one file per method.
+// "hot" -- only create graphs for the hot region, one file per method.
+// "cold" -- only create graphs for the cold region, one file per method.
+// "jit" -- only create graphs for JITing, one file per method.
+// "all" -- create graphs for all regions, one file per method.
+// "stdout" -- output to stdout, not a file.
+// "stderr" -- output to stderr, not a file.
+//
// Return Value:
// Opens a file to which a flowgraph can be dumped, whose name is based on the current
// config vales.
@@ -349,44 +363,43 @@ static void fprintfDouble(FILE* fgxFile, double value)
FILE* Compiler::fgOpenFlowGraphFile(bool* wbDontClose, Phases phase, LPCWSTR type)
{
FILE* fgxFile;
- LPCWSTR pattern = nullptr;
- LPCWSTR filename = nullptr;
- LPCWSTR pathname = nullptr;
+ LPCWSTR phasePattern = W("*"); // default (used in Release) is dump all phases
+ bool dumpFunction = true; // default (used in Release) is always dump
+ LPCWSTR filename = nullptr;
+ LPCWSTR pathname = nullptr;
const char* escapedString;
bool createDuplicateFgxFiles = true;
+ if (fgBBcount <= 1)
+ {
+ return nullptr;
+ }
+
#ifdef DEBUG
if (opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT))
{
- pattern = JitConfig.NgenDumpFg();
+ dumpFunction =
+ JitConfig.NgenDumpFg().contains(info.compMethodName, info.compClassName, &info.compMethodInfo->args);
filename = JitConfig.NgenDumpFgFile();
pathname = JitConfig.NgenDumpFgDir();
}
else
{
- pattern = JitConfig.JitDumpFg();
+ dumpFunction =
+ JitConfig.JitDumpFg().contains(info.compMethodName, info.compClassName, &info.compMethodInfo->args);
filename = JitConfig.JitDumpFgFile();
pathname = JitConfig.JitDumpFgDir();
}
-#endif // DEBUG
- if (fgBBcount <= 1)
- {
- return nullptr;
- }
-
- if (pattern == nullptr)
- {
- return nullptr;
- }
+ phasePattern = JitConfig.JitDumpFgPhase();
+#endif // DEBUG
- if (wcslen(pattern) == 0)
+ if (!dumpFunction)
{
return nullptr;
}
- LPCWSTR phasePattern = JitConfig.JitDumpFgPhase();
- LPCWSTR phaseName = PhaseShortNames[phase];
+ LPCWSTR phaseName = PhaseShortNames[phase];
if (phasePattern == nullptr)
{
if (phase != PHASE_DETERMINE_FIRST_COLD_BLOCK)
@@ -402,84 +415,6 @@ FILE* Compiler::fgOpenFlowGraphFile(bool* wbDontClose, Phases phase, LPCWSTR typ
}
}
- if (*pattern != W('*'))
- {
- bool hasColon = (wcschr(pattern, W(':')) != nullptr);
-
- if (hasColon)
- {
- const char* className = info.compClassName;
- if (*pattern == W('*'))
- {
- pattern++;
- }
- else
- {
- while ((*pattern != W(':')) && (*pattern != W('*')))
- {
- if (*pattern != *className)
- {
- return nullptr;
- }
-
- pattern++;
- className++;
- }
- if (*pattern == W('*'))
- {
- pattern++;
- }
- else
- {
- if (*className != 0)
- {
- return nullptr;
- }
- }
- }
- if (*pattern != W(':'))
- {
- return nullptr;
- }
-
- pattern++;
- }
-
- const char* methodName = info.compMethodName;
- if (*pattern == W('*'))
- {
- pattern++;
- }
- else
- {
- while ((*pattern != 0) && (*pattern != W('*')))
- {
- if (*pattern != *methodName)
- {
- return nullptr;
- }
-
- pattern++;
- methodName++;
- }
- if (*pattern == W('*'))
- {
- pattern++;
- }
- else
- {
- if (*methodName != 0)
- {
- return nullptr;
- }
- }
- }
- if (*pattern != 0)
- {
- return nullptr;
- }
- }
-
if (filename == nullptr)
{
filename = W("default");
@@ -645,13 +580,15 @@ FILE* Compiler::fgOpenFlowGraphFile(bool* wbDontClose, Phases phase, LPCWSTR typ
// The xml dumps are the historical mechanism for dumping the flowgraph.
// The dot format can be viewed by:
// - Graphviz (http://www.graphviz.org/)
-// - The command "C:\Program Files (x86)\Graphviz2.38\bin\dot.exe" -Tsvg -oFoo.svg -Kdot Foo.dot
-// will produce a Foo.svg file that can be opened with any svg-capable browser (e.g. IE).
+// - The command:
+// "C:\Program Files (x86)\Graphviz2.38\bin\dot.exe" -Tsvg -oFoo.svg -Kdot Foo.dot
+// will produce a Foo.svg file that can be opened with any svg-capable browser.
+// - https://sketchviz.com/
// - http://rise4fun.com/Agl/
// - Cut and paste the graph from your .dot file, replacing the digraph on the page, and then click the play
// button.
// - It will show a rotating '/' and then render the graph in the browser.
-// MSAGL has also been open-sourced to https://github.com/Microsoft/automatic-graph-layout.git.
+// MSAGL has also been open-sourced to https://github.com/Microsoft/automatic-graph-layout.
//
// Here are the config values that control it:
// COMPlus_JitDumpFg A string (ala the COMPlus_JitDump string) indicating what methods to dump flowgraphs
@@ -659,30 +596,33 @@ FILE* Compiler::fgOpenFlowGraphFile(bool* wbDontClose, Phases phase, LPCWSTR typ
// COMPlus_JitDumpFgDir A path to a directory into which the flowgraphs will be dumped.
// COMPlus_JitDumpFgFile The filename to use. The default is "default.[xml|dot]".
// Note that the new graphs will be appended to this file if it already exists.
+// COMPlus_NgenDumpFg Same as COMPlus_JitDumpFg, but for ngen compiles.
+// COMPlus_NgenDumpFgDir Same as COMPlus_JitDumpFgDir, but for ngen compiles.
+// COMPlus_NgenDumpFgFile Same as COMPlus_JitDumpFgFile, but for ngen compiles.
// COMPlus_JitDumpFgPhase Phase(s) after which to dump the flowgraph.
// Set to the short name of a phase to see the flowgraph after that phase.
// Leave unset to dump after COLD-BLK (determine first cold block) or set to * for all
// phases.
-// COMPlus_JitDumpFgDot Set to non-zero to emit Dot instead of Xml Flowgraph dump. (Default is xml format.)
+// COMPlus_JitDumpFgDot 0 for xml format, non-zero for dot format. (Default is dot format.)
bool Compiler::fgDumpFlowGraph(Phases phase)
{
bool result = false;
bool dontClose = false;
- bool createDotFile = false;
- if (JitConfig.JitDumpFgDot())
- {
- createDotFile = true;
- }
+ bool createDotFile = true;
- FILE* fgxFile = fgOpenFlowGraphFile(&dontClose, phase, createDotFile ? W("dot") : W("fgx"));
+#ifdef DEBUG
+ createDotFile = JitConfig.JitDumpFgDot() != 0;
+#endif // DEBUG
+ FILE* fgxFile = fgOpenFlowGraphFile(&dontClose, phase, createDotFile ? W("dot") : W("fgx"));
if (fgxFile == nullptr)
{
return false;
}
+
bool validWeights = fgHaveValidEdgeWeights;
- double weightDivisor = (double)fgCalledCount;
+ double weightDivisor = (double)BasicBlock::getCalledCount(this);
const char* escapedString;
const char* regionString = "NONE";
@@ -824,14 +764,18 @@ bool Compiler::fgDumpFlowGraph(Phases phase)
}
const char* rootTreeOpName = "n/a";
- if (block->lastNode() != nullptr)
+ if (block->IsLIR() || (block->lastStmt() != nullptr))
{
- rootTreeOpName = GenTree::OpName(block->lastNode()->OperGet());
+ if (block->lastNode() != nullptr)
+ {
+ rootTreeOpName = GenTree::OpName(block->lastNode()->OperGet());
+ }
}
fprintf(fgxFile, "\n weight=");
fprintfDouble(fgxFile, ((double)block->bbWeight) / weightDivisor);
- fprintf(fgxFile, "\n codeEstimate=\"%d\"", fgGetCodeEstimate(block));
+ // fgGetCodeEstimate() will assert if the costs have not yet been initialized.
+ // fprintf(fgxFile, "\n codeEstimate=\"%d\"", fgGetCodeEstimate(block));
fprintf(fgxFile, "\n startOffset=\"%d\"", block->bbCodeOffs);
fprintf(fgxFile, "\n rootTreeOp=\"%s\"", rootTreeOpName);
fprintf(fgxFile, "\n endOffset=\"%d\"", block->bbCodeOffsEnd);
diff --git a/src/coreclr/jit/fginline.cpp b/src/coreclr/jit/fginline.cpp
index bcb03bc56e5fe7..f31218eaddfa59 100644
--- a/src/coreclr/jit/fginline.cpp
+++ b/src/coreclr/jit/fginline.cpp
@@ -618,56 +618,8 @@ Compiler::fgWalkResult Compiler::fgUpdateInlineReturnExpressionPlaceHolder(GenTr
#endif // FEATURE_MULTIREG_RET
case SPK_EnclosingType:
- {
- // For enclosing type returns, we must return the call value to a temp since
- // the return type is larger than the struct type.
- if (!tree->IsCall())
- {
- break;
- }
-
- GenTreeCall* call = tree->AsCall();
-
- assert(call->gtReturnType == TYP_STRUCT);
-
- if (call->gtReturnType != TYP_STRUCT)
- {
- break;
- }
-
- JITDUMP("\nCall returns small struct via enclosing type, retyping. Before:\n");
- DISPTREE(call);
-
- // Create new struct typed temp for return value
- const unsigned tmpNum =
- comp->lvaGrabTemp(true DEBUGARG("small struct return temp for rejected inline"));
- comp->lvaSetStruct(tmpNum, retClsHnd, false);
- GenTree* assign = comp->gtNewTempAssign(tmpNum, call);
-
- // Modify assign tree and call return types to the primitive return type
- call->gtReturnType = returnType;
- call->gtType = returnType;
- assign->gtType = returnType;
-
- // Modify the temp reference in the assign as a primitive reference via GT_LCL_FLD
- GenTree* tempAsPrimitive = assign->AsOp()->gtOp1;
- assert(tempAsPrimitive->gtOper == GT_LCL_VAR);
- tempAsPrimitive->gtType = returnType;
- tempAsPrimitive->ChangeOper(GT_LCL_FLD);
-
- // Return temp as value of call tree via comma
- GenTree* tempAsStruct = comp->gtNewLclvNode(tmpNum, TYP_STRUCT);
- GenTree* comma = comp->gtNewOperNode(GT_COMMA, TYP_STRUCT, assign, tempAsStruct);
- parent->ReplaceOperand(pTree, comma);
-
- JITDUMP("\nAfter:\n");
- DISPTREE(comma);
- }
- break;
-
case SPK_PrimitiveType:
- // We should have already retyped the call as a primitive type
- // when we first imported the call
+ // No work needs to be done, the call has struct type and should keep it.
break;
case SPK_ByReference:
diff --git a/src/coreclr/jit/flowgraph.cpp b/src/coreclr/jit/flowgraph.cpp
index 578967bac52856..3210718d041164 100644
--- a/src/coreclr/jit/flowgraph.cpp
+++ b/src/coreclr/jit/flowgraph.cpp
@@ -2317,17 +2317,10 @@ class MergedReturns
if (comp->compMethodReturnsNativeScalarType())
{
- if (!comp->compDoOldStructRetyping())
+ returnLocalDsc.lvType = genActualType(comp->info.compRetType);
+ if (varTypeIsStruct(returnLocalDsc.lvType))
{
- returnLocalDsc.lvType = genActualType(comp->info.compRetType);
- if (varTypeIsStruct(returnLocalDsc.lvType))
- {
- comp->lvaSetStruct(returnLocalNum, comp->info.compMethodInfo->args.retTypeClass, false);
- }
- }
- else
- {
- returnLocalDsc.lvType = genActualType(comp->info.compRetNativeType);
+ comp->lvaSetStruct(returnLocalNum, comp->info.compMethodInfo->args.retTypeClass, false);
}
}
else if (comp->compMethodReturnsRetBufAddr())
diff --git a/src/coreclr/jit/gcencode.cpp b/src/coreclr/jit/gcencode.cpp
index c20f7d6bd74163..3c4007c6ad10b5 100644
--- a/src/coreclr/jit/gcencode.cpp
+++ b/src/coreclr/jit/gcencode.cpp
@@ -3931,13 +3931,24 @@ void GCInfo::gcInfoBlockHdrSave(GcInfoEncoder* gcInfoEncoder, unsigned methodSiz
int offset = 0;
+ // OSR can report the root method's frame slot, if that method reported context.
+ //
+ bool isOsrAndUsingRootFrameSlot = false;
if (compiler->opts.IsOSR())
{
- PatchpointInfo* ppInfo = compiler->info.compPatchpointInfo;
- offset = ppInfo->GenericContextArgOffset();
- assert(offset != -1);
+ PatchpointInfo* const ppInfo = compiler->info.compPatchpointInfo;
+
+ if (ppInfo->HasKeptAliveThis())
+ {
+ offset = ppInfo->GenericContextArgOffset();
+ assert(offset != -1);
+ isOsrAndUsingRootFrameSlot = true;
+ }
}
- else
+
+ // If not OSR, or OSR but newly reporting context, use the current frame offset.
+ //
+ if (!isOsrAndUsingRootFrameSlot)
{
offset = compiler->lvaToCallerSPRelativeOffset(compiler->lvaCachedGenericContextArgOffset(),
compiler->isFramePointerUsed());
diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp
index ad09a52f0e157a..d4c1a188570b28 100644
--- a/src/coreclr/jit/gentree.cpp
+++ b/src/coreclr/jit/gentree.cpp
@@ -161,7 +161,7 @@ static void printIndent(IndentStack* indentStack)
#endif
-#if defined(DEBUG) || NODEBASH_STATS || MEASURE_NODE_SIZE || COUNT_AST_OPERS
+#if defined(DEBUG) || NODEBASH_STATS || MEASURE_NODE_SIZE || COUNT_AST_OPERS || DUMP_FLOWGRAPHS
static const char* opNames[] = {
#define GTNODE(en, st, cm, ok) #en,
@@ -6212,6 +6212,38 @@ GenTree* Compiler::gtNewStringLiteralNode(InfoAccessType iat, void* pValue)
return tree;
}
+//------------------------------------------------------------------------
+// gtNewStringLiteralLength: create GenTreeIntCon node for the given string
+// literal to store its length.
+//
+// Arguments:
+// node - string literal node.
+//
+// Return Value:
+// GenTreeIntCon node with string's length as a value or null.
+//
+GenTreeIntCon* Compiler::gtNewStringLiteralLength(GenTreeStrCon* node)
+{
+ int length = -1;
+ const char16_t* str = info.compCompHnd->getStringLiteral(node->gtScpHnd, node->gtSconCPX, &length);
+ if (length >= 0)
+ {
+ GenTreeIntCon* iconNode = gtNewIconNode(length);
+
+ // str can be NULL for dynamic context
+ if (str != nullptr)
+ {
+ JITDUMP("String '\"%ws\".Length' is '%d'\n", str, length)
+ }
+ else
+ {
+ JITDUMP("String 'CNS_STR.Length' is '%d'\n", length)
+ }
+ return iconNode;
+ }
+ return nullptr;
+}
+
/*****************************************************************************/
GenTree* Compiler::gtNewLconNode(__int64 value)
@@ -10773,7 +10805,6 @@ void Compiler::gtGetLclVarNameInfo(unsigned lclNum, const char** ilKindOut, cons
}
else if (ilNum == (unsigned)ICorDebugInfo::UNKNOWN_ILNUM)
{
-#if FEATURE_ANYCSE
if (lclNumIsTrueCSE(lclNum))
{
ilKind = "cse";
@@ -10787,7 +10818,6 @@ void Compiler::gtGetLclVarNameInfo(unsigned lclNum, const char** ilKindOut, cons
ilNum = lclNum - (optCSEstart + optCSEcount);
}
else
-#endif // FEATURE_ANYCSE
{
if (lclNum == info.compLvFrameListRoot)
{
@@ -15591,7 +15621,6 @@ GenTree* Compiler::gtNewTempAssign(
{
// It could come from `ASG(struct, 0)` that was propagated to `RETURN struct(0)`,
// and now it is merging to a struct again.
- assert(!compDoOldStructRetyping());
assert(tmp == genReturnLocal);
ok = true;
}
@@ -15644,7 +15673,6 @@ GenTree* Compiler::gtNewTempAssign(
// 2. we are propagation `ASG(struct V01, 0)` to `RETURN(struct V01)`, `CNT_INT` doesn't `structHnd`;
// in these cases, we can use the type of the merge return for the assignment.
assert(val->OperIs(GT_IND, GT_LCL_FLD, GT_CNS_INT));
- assert(!compDoOldStructRetyping());
assert(tmp == genReturnLocal);
valStructHnd = lvaGetStruct(genReturnLocal);
assert(valStructHnd != NO_CLASS_HANDLE);
@@ -15652,7 +15680,6 @@ GenTree* Compiler::gtNewTempAssign(
if ((valStructHnd != NO_CLASS_HANDLE) && val->IsConstInitVal())
{
- assert(!compDoOldStructRetyping());
asg = gtNewAssignNode(dest, val);
}
else if (varTypeIsStruct(varDsc) && ((valStructHnd != NO_CLASS_HANDLE) || varTypeIsSIMD(valTyp)))
diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h
index 6b3ff34518c0fe..c9ddd2cc4817f6 100644
--- a/src/coreclr/jit/gentree.h
+++ b/src/coreclr/jit/gentree.h
@@ -414,8 +414,6 @@ struct GenTree
genTreeOps gtOperSave; // Only used to save gtOper when we destroy a node, to aid debugging.
#endif
-#if FEATURE_ANYCSE
-
#define NO_CSE (0)
#define IS_CSE_INDEX(x) ((x) != 0)
@@ -427,8 +425,6 @@ struct GenTree
signed char gtCSEnum; // 0 or the CSE index (negated if def)
// valid only for CSE expressions
-#endif // FEATURE_ANYCSE
-
unsigned char gtLIRFlags; // Used for nodes that are in LIR. See LIR::Flags in lir.h for the various flags.
#if ASSERTION_PROP
@@ -1848,7 +1844,7 @@ struct GenTree
//---------------------------------------------------------------------
-#if defined(DEBUG) || NODEBASH_STATS || MEASURE_NODE_SIZE || COUNT_AST_OPERS
+#if defined(DEBUG) || NODEBASH_STATS || MEASURE_NODE_SIZE || COUNT_AST_OPERS || DUMP_FLOWGRAPHS
static const char* OpName(genTreeOps op);
#endif
diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp
index 1a1224d096d626..139d204638b9fb 100644
--- a/src/coreclr/jit/importer.cpp
+++ b/src/coreclr/jit/importer.cpp
@@ -812,11 +812,6 @@ void Compiler::impAssignTempGen(unsigned tmpNum,
// type, this would not be necessary - but that requires additional JIT/EE interface
// calls that may not actually be required - e.g. if we only access a field of a struct.
- if (compDoOldStructRetyping())
- {
- val->gtType = varType;
- }
-
GenTree* dst = gtNewLclvNode(tmpNum, varType);
asg = impAssignStruct(dst, val, structType, curLevel, pAfterStmt, ilOffset, block);
}
@@ -1389,12 +1384,6 @@ GenTree* Compiler::impAssignStructPtr(GenTree* destAddr,
var_types returnType = (var_types)srcCall->gtReturnType;
- if (compDoOldStructRetyping())
- {
- // We're not using a return buffer, so if we're retyping we'll change the type of 'src' to 'returnTYpe'.
- src->gtType = genActualType(returnType);
- }
-
// First we try to change this to "LclVar/LclFld = call"
//
if ((destAddr->gtOper == GT_ADDR) && (destAddr->AsOp()->gtOp1->gtOper == GT_LCL_VAR))
@@ -1414,14 +1403,6 @@ GenTree* Compiler::impAssignStructPtr(GenTree* destAddr,
lcl->gtFlags |= GTF_DONT_CSE;
varDsc->lvIsMultiRegRet = true;
}
- else if ((lcl->gtType != src->gtType) && compDoOldStructRetyping())
- {
- // We change this to a GT_LCL_FLD (from a GT_ADDR of a GT_LCL_VAR)
- lcl->ChangeOper(GT_LCL_FLD);
- fgLclFldAssign(lclNum);
- lcl->gtType = src->gtType;
- asgType = src->gtType;
- }
dest = lcl;
@@ -1474,17 +1455,7 @@ GenTree* Compiler::impAssignStructPtr(GenTree* destAddr,
{
// Case of inline method returning a struct in one or more registers.
// We won't need a return buffer
- if (compDoOldStructRetyping())
- {
- var_types returnType = (var_types)call->gtReturnType;
- asgType = returnType;
- src->gtType = genActualType(returnType);
- call->gtType = src->gtType;
- }
- else
- {
- asgType = src->gtType;
- }
+ asgType = src->gtType;
if ((destAddr->gtOper != GT_ADDR) || (destAddr->AsOp()->gtOp1->gtOper != GT_LCL_VAR))
{
@@ -1624,10 +1595,7 @@ GenTree* Compiler::impAssignStructPtr(GenTree* destAddr,
dest = gtNewOperNode(GT_IND, asgType, destAddr);
}
}
- else if (compDoOldStructRetyping())
- {
- dest->gtType = asgType;
- }
+
if (dest->OperIs(GT_LCL_VAR) &&
(src->IsMultiRegNode() ||
(src->OperIs(GT_RET_EXPR) && src->AsRetExpr()->gtInlineCandidate->AsCall()->HasMultiRegRetVal())))
@@ -3913,20 +3881,10 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
{
// Optimize `ldstr + String::get_Length()` to CNS_INT
// e.g. "Hello".Length => 5
- int length = -1;
- const char16_t* str = info.compCompHnd->getStringLiteral(op1->AsStrCon()->gtScpHnd,
- op1->AsStrCon()->gtSconCPX, &length);
- if (length >= 0)
+ GenTreeIntCon* iconNode = gtNewStringLiteralLength(op1->AsStrCon());
+ if (iconNode != nullptr)
{
- retNode = gtNewIconNode(length);
- if (str != nullptr) // can be NULL for dynamic context
- {
- JITDUMP("Optimizing '\"%ws\".Length' to just '%d'\n", str, length);
- }
- else
- {
- JITDUMP("Optimizing 'CNS_STR.Length' to just '%d'\n", length);
- }
+ retNode = iconNode;
break;
}
}
@@ -8504,11 +8462,6 @@ var_types Compiler::impImportCall(OPCODE opcode,
CORINFO_CLASS_HANDLE actualMethodRetTypeSigClass;
actualMethodRetTypeSigClass = sig->retTypeSigClass;
- if (varTypeIsStruct(callRetTyp) && compDoOldStructRetyping())
- {
- callRetTyp = impNormStructType(actualMethodRetTypeSigClass);
- call->gtType = callRetTyp;
- }
#if !FEATURE_VARARG
/* Check for varargs */
@@ -9485,32 +9438,7 @@ GenTree* Compiler::impFixupCallStructReturn(GenTreeCall* call, CORINFO_CLASS_HAN
}
else if (retRegCount == 1)
{
- if (!compDoOldStructRetyping())
- {
- return call;
- }
- // See if the struct size is smaller than the return
- // type size...
- if (retTypeDesc->IsEnclosingType())
- {
- // If we know for sure this call will remain a call,
- // retype and return value via a suitable temp.
- if ((!call->CanTailCall()) && (!call->IsInlineCandidate()))
- {
- call->gtReturnType = retTypeDesc->GetReturnRegType(0);
- return impAssignSmallStructTypeToVar(call, retClsHnd);
- }
- else
- {
- call->gtReturnType = call->gtType;
- }
- }
- else
- {
- // Return type is same size as struct, so we can
- // simply retype the call.
- call->gtReturnType = retTypeDesc->GetReturnRegType(0);
- }
+ return call;
}
else
{
@@ -9548,68 +9476,35 @@ GenTree* Compiler::impFixupCallStructReturn(GenTreeCall* call, CORINFO_CLASS_HAN
else
{
-#if FEATURE_MULTIREG_RET
+#if !FEATURE_MULTIREG_RET
+ return call;
+#else // FEATURE_MULTIREG_RET
const ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc();
const unsigned retRegCount = retTypeDesc->GetReturnRegCount();
assert(retRegCount != 0);
- if (!compDoOldStructRetyping() && retRegCount == 1)
+ if (retRegCount == 1)
{
return call;
}
-#else // !FEATURE_MULTIREG_RET
- if (!compDoOldStructRetyping())
- {
- return call;
- }
-#endif // !FEATURE_MULTIREG_RET
- assert(returnType != TYP_UNKNOWN);
- // See if the struct size is smaller than the return
- // type size...
- if (howToReturnStruct == SPK_EnclosingType)
- {
- // If we know for sure this call will remain a call,
- // retype and return value via a suitable temp.
- if ((!call->CanTailCall()) && (!call->IsInlineCandidate()))
- {
- call->gtReturnType = returnType;
- return impAssignSmallStructTypeToVar(call, retClsHnd);
- }
- }
- else
- {
- // Return type is same size as struct, so we can
- // simply retype the call.
- call->gtReturnType = returnType;
- }
+ assert(returnType == TYP_STRUCT);
+ assert((howToReturnStruct == SPK_ByValueAsHfa) || (howToReturnStruct == SPK_ByValue));
- // ToDo: Refactor this common code sequence into its own method as it is used 4+ times
- if ((returnType == TYP_LONG) && (compLongUsed == false))
- {
- compLongUsed = true;
- }
- else if (((returnType == TYP_FLOAT) || (returnType == TYP_DOUBLE)) && (compFloatingPointUsed == false))
- {
- compFloatingPointUsed = true;
- }
+ assert(call->gtReturnType == returnType);
-#if FEATURE_MULTIREG_RET
- if (retRegCount >= 2)
+ assert(retRegCount >= 2);
+ if ((!call->CanTailCall()) && (!call->IsInlineCandidate()))
{
- if ((!call->CanTailCall()) && (!call->IsInlineCandidate()))
- {
- // Force a call returning multi-reg struct to be always of the IR form
- // tmp = call
- //
- // No need to assign a multi-reg struct to a local var if:
- // - It is a tail call or
- // - The call is marked for in-lining later
- return impAssignMultiRegTypeToVar(call, retClsHnd DEBUGARG(call->GetUnmanagedCallConv()));
- }
+ // Force a call returning multi-reg struct to be always of the IR form
+ // tmp = call
+ //
+ // No need to assign a multi-reg struct to a local var if:
+ // - It is a tail call or
+ // - The call is marked for in-lining later
+ return impAssignMultiRegTypeToVar(call, retClsHnd DEBUGARG(call->GetUnmanagedCallConv()));
}
#endif // FEATURE_MULTIREG_RET
}
-
#endif // not UNIX_AMD64_ABI
return call;
@@ -9620,6 +9515,18 @@ GenTree* Compiler::impFixupCallStructReturn(GenTreeCall* call, CORINFO_CLASS_HAN
does not use a struct return buffer
*/
+//------------------------------------------------------------------------
+// impFixupStructReturnType: For struct return values it sets appropriate flags in MULTIREG returns case;
+// in non-multiref case it handles two special helpers: `CORINFO_HELP_GETFIELDSTRUCT`, `CORINFO_HELP_UNBOX_NULLABLE`.
+//
+// Arguments:
+// op - the return value;
+// retClsHnd - the struct handle;
+// unmgdCallConv - the calling convention of the function that returns this struct.
+//
+// Return Value:
+// the result tree that does the return.
+//
GenTree* Compiler::impFixupStructReturnType(GenTree* op,
CORINFO_CLASS_HANDLE retClsHnd,
CorInfoCallConvExtension unmgdCallConv)
@@ -9741,95 +9648,31 @@ GenTree* Compiler::impFixupStructReturnType(GenTree* op,
#endif // FEATURE_MULTIREG_RET && TARGET_ARM64
- if (!compDoOldStructRetyping() && (!op->IsCall() || !op->AsCall()->TreatAsHasRetBufArg(this)))
+ if (!op->IsCall() || !op->AsCall()->TreatAsHasRetBufArg(this))
{
// Don't retype `struct` as a primitive type in `ret` instruction.
return op;
}
-REDO_RETURN_NODE:
- // adjust the type away from struct to integral
- // and no normalizing
- if (op->gtOper == GT_LCL_VAR)
- {
- // It is possible that we now have a lclVar of scalar type.
- // If so, don't transform it to GT_LCL_FLD.
- LclVarDsc* varDsc = lvaGetDesc(op->AsLclVarCommon());
- if (genActualType(varDsc->TypeGet()) != genActualType(info.compRetNativeType))
- {
- op->ChangeOper(GT_LCL_FLD);
- }
- }
- else if (op->gtOper == GT_OBJ)
- {
- GenTree* op1 = op->AsObj()->Addr();
-
- // We will fold away OBJ/ADDR, except for OBJ/ADDR/INDEX
- //
- // In the latter case the OBJ type may have a different type
- // than the array element type, and we need to preserve the
- // array element type for now.
- //
- if ((op1->gtOper == GT_ADDR) && (op1->AsOp()->gtOp1->gtOper != GT_INDEX))
- {
- // Change '*(&X)' to 'X' and see if we can do better
- op = op1->AsOp()->gtOp1;
- goto REDO_RETURN_NODE;
- }
- op->ChangeOperUnchecked(GT_IND);
- op->gtFlags |= GTF_IND_TGTANYWHERE;
- }
- else if (op->gtOper == GT_CALL)
- {
- if (op->AsCall()->TreatAsHasRetBufArg(this))
- {
- // This must be one of those 'special' helpers that don't
- // really have a return buffer, but instead use it as a way
- // to keep the trees cleaner with fewer address-taken temps.
- //
- // Well now we have to materialize the the return buffer as
- // an address-taken temp. Then we can return the temp.
- //
- // NOTE: this code assumes that since the call directly
- // feeds the return, then the call must be returning the
- // same structure/class/type.
- //
- unsigned tmpNum = lvaGrabTemp(true DEBUGARG("pseudo return buffer"));
-
- // No need to spill anything as we're about to return.
- impAssignTempGen(tmpNum, op, info.compMethodInfo->args.retTypeClass, (unsigned)CHECK_SPILL_NONE);
-
- if (compDoOldStructRetyping())
- {
- // Don't create both a GT_ADDR & GT_OBJ just to undo all of that; instead,
- // jump directly to a GT_LCL_FLD.
- op = gtNewLclvNode(tmpNum, info.compRetNativeType);
- op->ChangeOper(GT_LCL_FLD);
- }
- else
- {
- op = gtNewLclvNode(tmpNum, info.compRetType);
- JITDUMP("\nimpFixupStructReturnType: created a pseudo-return buffer for a special helper\n");
- DISPTREE(op);
- return op;
- }
- }
- else
- {
- // Don't change the gtType of the call just yet, it will get changed later.
- return op;
- }
- }
- else if (op->gtOper == GT_COMMA)
- {
- op->AsOp()->gtOp2 = impFixupStructReturnType(op->AsOp()->gtOp2, retClsHnd, unmgdCallConv);
- }
+ // This must be one of those 'special' helpers that don't
+ // really have a return buffer, but instead use it as a way
+ // to keep the trees cleaner with fewer address-taken temps.
+ //
+ // Well now we have to materialize the the return buffer as
+ // an address-taken temp. Then we can return the temp.
+ //
+ // NOTE: this code assumes that since the call directly
+ // feeds the return, then the call must be returning the
+ // same structure/class/type.
+ //
+ unsigned tmpNum = lvaGrabTemp(true DEBUGARG("pseudo return buffer"));
- op->gtType = info.compRetNativeType;
+ // No need to spill anything as we're about to return.
+ impAssignTempGen(tmpNum, op, info.compMethodInfo->args.retTypeClass, (unsigned)CHECK_SPILL_NONE);
- JITDUMP("\nimpFixupStructReturnType: result of retyping is\n");
+ op = gtNewLclvNode(tmpNum, info.compRetType);
+ JITDUMP("\nimpFixupStructReturnType: created a pseudo-return buffer for a special helper\n");
DISPTREE(op);
-
return op;
}
@@ -15748,14 +15591,10 @@ void Compiler::impImportBlockCode(BasicBlock* block)
// The handle struct is returned in register
op1->AsCall()->gtReturnType = GetRuntimeHandleUnderlyingType();
- if (!compDoOldStructRetyping())
- {
- op1->AsCall()->gtRetClsHnd = classHandle;
+ op1->AsCall()->gtRetClsHnd = classHandle;
#if FEATURE_MULTIREG_RET
- op1->AsCall()->InitializeStructReturnType(this, classHandle,
- op1->AsCall()->GetUnmanagedCallConv());
+ op1->AsCall()->InitializeStructReturnType(this, classHandle, op1->AsCall()->GetUnmanagedCallConv());
#endif
- }
tiRetVal = typeInfo(TI_STRUCT, classHandle);
}
@@ -15797,13 +15636,10 @@ void Compiler::impImportBlockCode(BasicBlock* block)
// The handle struct is returned in register and
// it could be consumed both as `TYP_STRUCT` and `TYP_REF`.
op1->AsCall()->gtReturnType = GetRuntimeHandleUnderlyingType();
- if (!compDoOldStructRetyping())
- {
#if FEATURE_MULTIREG_RET
- op1->AsCall()->InitializeStructReturnType(this, tokenType, op1->AsCall()->GetUnmanagedCallConv());
+ op1->AsCall()->InitializeStructReturnType(this, tokenType, op1->AsCall()->GetUnmanagedCallConv());
#endif
- op1->AsCall()->gtRetClsHnd = tokenType;
- }
+ op1->AsCall()->gtRetClsHnd = tokenType;
tiRetVal = verMakeTypeInfo(tokenType);
impPushOnStack(op1, tiRetVal);
@@ -15980,12 +15816,9 @@ void Compiler::impImportBlockCode(BasicBlock* block)
op1 = gtNewHelperCallNode(helper,
(var_types)((helper == CORINFO_HELP_UNBOX) ? TYP_BYREF : TYP_STRUCT),
gtNewCallArgs(op2, op1));
- if (!compDoOldStructRetyping())
+ if (op1->gtType == TYP_STRUCT)
{
- if (op1->gtType == TYP_STRUCT)
- {
- op1->AsCall()->gtRetClsHnd = resolvedToken.hClass;
- }
+ op1->AsCall()->gtRetClsHnd = resolvedToken.hClass;
}
}
@@ -17008,9 +16841,10 @@ bool Compiler::impReturnInstruction(int prefixFlags, OPCODE& opcode)
impBashVarAddrsToI(op2);
op2 = impImplicitIorI4Cast(op2, info.compRetType);
op2 = impImplicitR4orR8Cast(op2, info.compRetType);
+ // Note that we allow TYP_I_IMPL<->TYP_BYREF transformation, but only TYP_I_IMPL<-TYP_REF.
assertImp((genActualType(op2->TypeGet()) == genActualType(info.compRetType)) ||
- ((op2->TypeGet() == TYP_I_IMPL) && (info.compRetType == TYP_BYREF)) ||
- ((op2->TypeGet() == TYP_BYREF) && (info.compRetType == TYP_I_IMPL)) ||
+ ((op2->TypeGet() == TYP_I_IMPL) && TypeIs(info.compRetType, TYP_BYREF)) ||
+ (op2->TypeIs(TYP_BYREF, TYP_REF) && (info.compRetType == TYP_I_IMPL)) ||
(varTypeIsFloating(op2->gtType) && varTypeIsFloating(info.compRetType)) ||
(varTypeIsStruct(op2) && varTypeIsStruct(info.compRetType)));
@@ -17059,9 +16893,10 @@ bool Compiler::impReturnInstruction(int prefixFlags, OPCODE& opcode)
if (returnType != originalCallType)
{
- // Allow TYP_BYREF to be returned as TYP_I_IMPL and vice versa
- if (((returnType == TYP_BYREF) && (originalCallType == TYP_I_IMPL)) ||
- ((returnType == TYP_I_IMPL) && (originalCallType == TYP_BYREF)))
+ // Allow TYP_BYREF to be returned as TYP_I_IMPL and vice versa.
+ // Allow TYP_REF to be returned as TYP_I_IMPL and NOT vice verse.
+ if ((TypeIs(returnType, TYP_BYREF, TYP_REF) && (originalCallType == TYP_I_IMPL)) ||
+ ((returnType == TYP_I_IMPL) && TypeIs(originalCallType, TYP_BYREF)))
{
JITDUMP("Allowing return type mismatch: have %s, needed %s\n", varTypeName(returnType),
varTypeName(originalCallType));
@@ -17139,68 +16974,11 @@ bool Compiler::impReturnInstruction(int prefixFlags, OPCODE& opcode)
}
}
- // This is a bit of a workaround...
- // If we are inlining a call that returns a struct, where the actual "native" return type is
- // not a struct (for example, the struct is composed of exactly one int, and the native
- // return type is thus an int), and the inlinee has multiple return blocks (thus,
- // fgNeedReturnSpillTemp() == true, and is the index of a local var that is set
- // to the *native* return type), and at least one of the return blocks is the result of
- // a call, then we have a problem. The situation is like this (from a failed test case):
- //
- // inliner:
- // // Note: valuetype plinq_devtests.LazyTests/LIX is a struct with only a single int
- // call !!0 [mscorlib]System.Threading.LazyInitializer::EnsureInitialized(!!0&, bool&, object&, class [mscorlib]System.Func`1)
- //
- // inlinee:
- // ...
- // ldobj !!T // this gets bashed to a GT_LCL_FLD, type TYP_INT
- // ret
- // ...
- // call !!0 System.Threading.LazyInitializer::EnsureInitializedCore(!!0&, bool&,
- // object&, class System.Func`1)
- // ret
- //
- // In the code above, when we call impFixupStructReturnType(), we will change the op2 return type
- // of the inlinee return node, but we don't do that for GT_CALL nodes, which we delay until
- // morphing when we call fgFixupStructReturn(). We do this, apparently, to handle nested
- // inlining properly by leaving the correct type on the GT_CALL node through importing.
- //
- // To fix this, for this case, we temporarily change the GT_CALL node type to the
- // native return type, which is what it will be set to eventually. We generate the
- // assignment to the return temp, using the correct type, and then restore the GT_CALL
- // node type. During morphing, the GT_CALL will get the correct, final, native return type.
-
- bool restoreType = false;
- if (compDoOldStructRetyping())
- {
- if ((op2->OperGet() == GT_CALL) && (info.compRetType == TYP_STRUCT))
- {
- noway_assert(op2->TypeGet() == TYP_STRUCT);
- op2->gtType = info.compRetNativeType;
- restoreType = true;
- }
- }
-
impAssignTempGen(lvaInlineeReturnSpillTemp, op2, se.seTypeInfo.GetClassHandle(),
(unsigned)CHECK_SPILL_ALL);
- var_types lclRetType = op2->TypeGet();
- if (!compDoOldStructRetyping())
- {
- LclVarDsc* varDsc = lvaGetDesc(lvaInlineeReturnSpillTemp);
- lclRetType = varDsc->lvType;
- }
-
- GenTree* tmpOp2 = gtNewLclvNode(lvaInlineeReturnSpillTemp, lclRetType);
-
- if (compDoOldStructRetyping())
- {
- if (restoreType)
- {
- op2->gtType = TYP_STRUCT; // restore it to what it was
- }
- }
+ var_types lclRetType = lvaGetDesc(lvaInlineeReturnSpillTemp)->lvType;
+ GenTree* tmpOp2 = gtNewLclvNode(lvaInlineeReturnSpillTemp, lclRetType);
op2 = tmpOp2;
#ifdef DEBUG
@@ -17469,16 +17247,8 @@ bool Compiler::impReturnInstruction(int prefixFlags, OPCODE& opcode)
#endif
op2 = impFixupStructReturnType(op2, retClsHnd, info.compCallConv);
// return op2
- var_types returnType;
- if (compDoOldStructRetyping())
- {
- returnType = info.compRetNativeType;
- }
- else
- {
- returnType = info.compRetType;
- }
- op1 = gtNewOperNode(GT_RETURN, genActualType(returnType), op2);
+ var_types returnType = info.compRetType;
+ op1 = gtNewOperNode(GT_RETURN, genActualType(returnType), op2);
}
else
{
@@ -19067,7 +18837,7 @@ void Compiler::impMakeDiscretionaryInlineObservations(InlineInfo* pInlineInfo, I
InlineCallsiteFrequency frequency = InlineCallsiteFrequency::UNUSED;
// If this is a prejit root, or a maximally hot block...
- if ((pInlineInfo == nullptr) || (pInlineInfo->iciBlock->bbWeight >= BB_MAX_WEIGHT))
+ if ((pInlineInfo == nullptr) || (pInlineInfo->iciBlock->isMaxBBWeight()))
{
frequency = InlineCallsiteFrequency::HOT;
}
diff --git a/src/coreclr/jit/jit.h b/src/coreclr/jit/jit.h
index 24fac11b945d0c..2e39bf46cc369a 100644
--- a/src/coreclr/jit/jit.h
+++ b/src/coreclr/jit/jit.h
@@ -406,11 +406,6 @@ class GlobalJitOptions
/*****************************************************************************/
-#define FEATURE_VALNUM_CSE 1 // enable the Value Number CSE optimization logic
-
-// true if Value Number CSE is enabled
-#define FEATURE_ANYCSE FEATURE_VALNUM_CSE
-
#define CSE_INTO_HANDLERS 0
#define LARGE_EXPSET 1 // Track 64 or 32 assertions/copies/consts/rangechecks
diff --git a/src/coreclr/jit/jitconfigvalues.h b/src/coreclr/jit/jitconfigvalues.h
index 055750272e335a..58156bdb04981d 100644
--- a/src/coreclr/jit/jitconfigvalues.h
+++ b/src/coreclr/jit/jitconfigvalues.h
@@ -9,10 +9,11 @@
#define OPT_CONFIG // Enable optimization level configuration.
#endif
+#if defined(DEBUG)
+
///
/// JIT
///
-#if defined(DEBUG)
CONFIG_INTEGER(AltJitLimit, W("AltJitLimit"), 0) // Max number of functions to use altjit for (decimal)
CONFIG_INTEGER(AltJitSkipOnAssert, W("AltJitSkipOnAssert"), 0) // If AltJit hits an assert, fall back to the fallback
// JIT. Useful in conjunction with
@@ -64,9 +65,8 @@ CONFIG_INTEGER(JitAlignLoopAdaptive,
CONFIG_INTEGER(JitDirectAlloc, W("JitDirectAlloc"), 0)
CONFIG_INTEGER(JitDoubleAlign, W("JitDoubleAlign"), 1)
-CONFIG_INTEGER(JitDumpASCII, W("JitDumpASCII"), 1) // Uses only ASCII characters in tree dumps
-CONFIG_INTEGER(JitDumpFgDot, W("JitDumpFgDot"), 0) // Set to non-zero to emit Dot instead of Xml Flowgraph dump
-CONFIG_INTEGER(JitDumpTerseLsra, W("JitDumpTerseLsra"), 1) // Produce terse dump output for LSRA
+CONFIG_INTEGER(JitDumpASCII, W("JitDumpASCII"), 1) // Uses only ASCII characters in tree dumps
+CONFIG_INTEGER(JitDumpTerseLsra, W("JitDumpTerseLsra"), 1) // Produce terse dump output for LSRA
CONFIG_INTEGER(JitDumpToDebugger, W("JitDumpToDebugger"), 0) // Output JitDump output to the debugger
CONFIG_INTEGER(JitDumpVerboseSsa, W("JitDumpVerboseSsa"), 0) // Produce especially verbose dump output for SSA
CONFIG_INTEGER(JitDumpVerboseTrees, W("JitDumpVerboseTrees"), 0) // Enable more verbose tree dumps
@@ -195,13 +195,14 @@ CONFIG_METHODSET(NgenUnwindDump, W("NgenUnwindDump")) // Dump the unwind codes f
///
/// JIT
///
-CONFIG_STRING(JitDumpFg, W("JitDumpFg")) // Dumps Xml/Dot Flowgraph for specified method
+CONFIG_METHODSET(JitDumpFg, W("JitDumpFg")) // Dumps Xml/Dot Flowgraph for specified method
CONFIG_STRING(JitDumpFgDir, W("JitDumpFgDir")) // Directory for Xml/Dot flowgraph dump(s)
-CONFIG_STRING(JitDumpFgFile, W("JitDumpFgFile")) // Filename for Xml/Dot flowgraph dump(s)
+CONFIG_STRING(JitDumpFgFile, W("JitDumpFgFile")) // Filename for Xml/Dot flowgraph dump(s) (default: "default")
CONFIG_STRING(JitDumpFgPhase, W("JitDumpFgPhase")) // Phase-based Xml/Dot flowgraph support. Set to the short name of a
// phase to see the flowgraph after that phase. Leave unset to dump
// after COLD-BLK (determine first cold block) or set to * for all
// phases
+CONFIG_INTEGER(JitDumpFgDot, W("JitDumpFgDot"), 1) // 0 == dump XML format; non-zero == dump DOT format
CONFIG_STRING(JitLateDisasmTo, W("JITLateDisasmTo"))
CONFIG_STRING(JitRange, W("JitRange"))
CONFIG_STRING(JitStressModeNames, W("JitStressModeNames")) // Internal Jit stress mode: stress using the given set of
@@ -213,15 +214,16 @@ CONFIG_STRING(JitStressRange, W("JitStressRange")) // Internal Jit
///
/// NGEN
///
-CONFIG_STRING(NgenDumpFg, W("NgenDumpFg")) // Ngen Xml Flowgraph support
-CONFIG_STRING(NgenDumpFgDir, W("NgenDumpFgDir")) // Ngen Xml Flowgraph support
-CONFIG_STRING(NgenDumpFgFile, W("NgenDumpFgFile")) // Ngen Xml Flowgraph support
+CONFIG_METHODSET(NgenDumpFg, W("NgenDumpFg")) // Ngen Xml/Dot flowgraph dump support
+CONFIG_STRING(NgenDumpFgDir, W("NgenDumpFgDir")) // Ngen Xml/Dot flowgraph dump support
+CONFIG_STRING(NgenDumpFgFile, W("NgenDumpFgFile")) // Ngen Xml/Dot flowgraph dump support
///
/// JIT Hardware Intrinsics
///
CONFIG_INTEGER(EnableIncompleteISAClass, W("EnableIncompleteISAClass"), 0) // Enable testing not-yet-implemented
// intrinsic classes
-#endif // defined(DEBUG)
+
+#endif // defined(DEBUG)
#if FEATURE_LOOP_ALIGN
CONFIG_INTEGER(JitAlignLoops, W("JitAlignLoops"), 1) // If set, align inner loops
@@ -372,6 +374,7 @@ CONFIG_INTEGER(JitDoAssertionProp, W("JitDoAssertionProp"), 1) // Perform assert
CONFIG_INTEGER(JitDoCopyProp, W("JitDoCopyProp"), 1) // Perform copy propagation on variables that appear redundant
CONFIG_INTEGER(JitDoEarlyProp, W("JitDoEarlyProp"), 1) // Perform Early Value Propagation
CONFIG_INTEGER(JitDoLoopHoisting, W("JitDoLoopHoisting"), 1) // Perform loop hoisting on loop invariant values
+CONFIG_INTEGER(JitDoLoopInversion, W("JitDoLoopInversion"), 1) // Perform loop inversion on "for/while" loops
CONFIG_INTEGER(JitDoRangeAnalysis, W("JitDoRangeAnalysis"), 1) // Perform range check analysis
CONFIG_INTEGER(JitDoRedundantBranchOpts, W("JitDoRedundantBranchOpts"), 1) // Perform redundant branch optimizations
CONFIG_INTEGER(JitDoSsa, W("JitDoSsa"), 1) // Perform Static Single Assignment (SSA) numbering on the variables
@@ -503,9 +506,6 @@ CONFIG_INTEGER(JitSaveFpLrWithCalleeSavedRegisters, W("JitSaveFpLrWithCalleeSave
#endif // defined(TARGET_ARM64)
#endif // DEBUG
-CONFIG_INTEGER(JitDoOldStructRetyping, W("JitDoOldStructRetyping"), 0) // Allow Jit to retype structs as primitive types
- // when possible.
-
#undef CONFIG_INTEGER
#undef CONFIG_STRING
#undef CONFIG_METHODSET
diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp
index 811cfc038060e7..ce195de08d2447 100644
--- a/src/coreclr/jit/lclmorph.cpp
+++ b/src/coreclr/jit/lclmorph.cpp
@@ -527,7 +527,7 @@ class LocalAddressVisitor final : public GenTreeVisitor
assert(TopValue(0).Node() == node->gtGetOp1());
GenTreeUnOp* ret = node->AsUnOp();
GenTree* retVal = ret->gtGetOp1();
- if (!m_compiler->compDoOldStructRetyping() && retVal->OperIs(GT_LCL_VAR))
+ if (retVal->OperIs(GT_LCL_VAR))
{
// TODO-1stClassStructs: this block is a temporary workaround to keep diffs small,
// having `doNotEnreg` affect block init and copy transformations that affect many methods.
diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp
index f3c12658ee4562..5ed85c89eeaa18 100644
--- a/src/coreclr/jit/lclvars.cpp
+++ b/src/coreclr/jit/lclvars.cpp
@@ -2102,8 +2102,7 @@ bool Compiler::StructPromotionHelper::ShouldPromoteStructVar(unsigned lclNum)
shouldPromote = false;
}
}
- else if (!compiler->compDoOldStructRetyping() && (lclNum == compiler->genReturnLocal) &&
- (structPromotionInfo.fieldCnt > 1))
+ else if ((lclNum == compiler->genReturnLocal) && (structPromotionInfo.fieldCnt > 1))
{
// TODO-1stClassStructs: a temporary solution to keep diffs small, it will be fixed later.
shouldPromote = false;
@@ -3239,6 +3238,7 @@ unsigned Compiler::lvaLclExactSize(unsigned varNum)
// if we don't have profile data then getCalledCount will return BB_UNITY_WEIGHT (100)
// otherwise it returns the number of times that profile data says the method was called.
//
+// static
BasicBlock::weight_t BasicBlock::getCalledCount(Compiler* comp)
{
// when we don't have profile data then fgCalledCount will be BB_UNITY_WEIGHT (100)
@@ -6267,19 +6267,15 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals()
}
#endif // JIT32_GCENCODER
- // OSR methods use the original method slot for the cached kept alive this,
- // so don't need to allocate a slot on the new frame.
- if (opts.IsOSR())
- {
- if (lvaKeepAliveAndReportThis())
- {
- PatchpointInfo* ppInfo = info.compPatchpointInfo;
- assert(ppInfo->HasKeptAliveThis());
- int originalOffset = ppInfo->KeptAliveThisOffset();
- lvaCachedGenericContextArgOffs = originalFrameStkOffs + originalOffset;
- }
- }
- else if (lvaReportParamTypeArg())
+ // For OSR methods, param type args are always reportable via the root method frame slot.
+ // (see gcInfoBlockHdrSave) and so do not need a new slot on the frame.
+ //
+ // OSR methods may also be able to use the root frame kept alive this, if the root
+ // method needed to report this.
+ //
+ // Inlining done under OSR may introduce new reporting, in which case the OSR frame
+ // must allocate a slot.
+ if (!opts.IsOSR() && lvaReportParamTypeArg())
{
#ifdef JIT32_GCENCODER
noway_assert(codeGen->isFramePointerUsed());
@@ -6292,10 +6288,25 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals()
#ifndef JIT32_GCENCODER
else if (lvaKeepAliveAndReportThis())
{
- // When "this" is also used as generic context arg.
- lvaIncrementFrameSize(TARGET_POINTER_SIZE);
- stkOffs -= TARGET_POINTER_SIZE;
- lvaCachedGenericContextArgOffs = stkOffs;
+ bool canUseExistingSlot = false;
+ if (opts.IsOSR())
+ {
+ PatchpointInfo* ppInfo = info.compPatchpointInfo;
+ if (ppInfo->HasKeptAliveThis())
+ {
+ int originalOffset = ppInfo->KeptAliveThisOffset();
+ lvaCachedGenericContextArgOffs = originalFrameStkOffs + originalOffset;
+ canUseExistingSlot = true;
+ }
+ }
+
+ if (!canUseExistingSlot)
+ {
+ // When "this" is also used as generic context arg.
+ lvaIncrementFrameSize(TARGET_POINTER_SIZE);
+ stkOffs -= TARGET_POINTER_SIZE;
+ lvaCachedGenericContextArgOffs = stkOffs;
+ }
}
#endif
diff --git a/src/coreclr/jit/lir.cpp b/src/coreclr/jit/lir.cpp
index 08257c022799c4..beac0b069e2142 100644
--- a/src/coreclr/jit/lir.cpp
+++ b/src/coreclr/jit/lir.cpp
@@ -1541,7 +1541,7 @@ bool LIR::Range::CheckLIR(Compiler* compiler, bool checkUnusedValues) const
slowNode = slowNode->gtNext;
}
- SmallHashTable unusedDefs(compiler->getAllocator());
+ SmallHashTable unusedDefs(compiler->getAllocatorDebugOnly());
bool pastPhis = false;
GenTree* prev = nullptr;
diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp
index 3eaaac1408bc46..1c4aac1af08cac 100644
--- a/src/coreclr/jit/lower.cpp
+++ b/src/coreclr/jit/lower.cpp
@@ -243,7 +243,6 @@ GenTree* Lowering::LowerNode(GenTree* node)
case GT_STORE_OBJ:
if (node->AsBlk()->Data()->IsCall())
{
- assert(!comp->compDoOldStructRetyping());
LowerStoreSingleRegCallStruct(node->AsBlk());
break;
}
@@ -2981,33 +2980,15 @@ void Lowering::LowerRet(GenTreeUnOp* ret)
bool doPrimitiveBitcast = false;
if (needBitcast)
{
- if (comp->compDoOldStructRetyping())
- {
- // `struct A { SIMD12/16 }` on `UNIX_AMD64_ABI` is an example when
- // `varTypeUsesFloatReg` returns different values for `ret` and `ret->gtGetOp1()`,
- // but doesn't need a primitive bitcase.
- doPrimitiveBitcast = !ret->TypeIs(TYP_STRUCT);
- }
- else
- {
- doPrimitiveBitcast = (!varTypeIsStruct(ret) && !varTypeIsStruct(retVal));
- }
+ doPrimitiveBitcast = (!varTypeIsStruct(ret) && !varTypeIsStruct(retVal));
}
if (doPrimitiveBitcast)
{
-// Add a simple bitcast for an old retyping or when both types are not structs.
-// If one type is a struct it will be handled below for !compDoOldStructRetyping.
+// Add a simple bitcast when both types are not structs.
+// If one type is a struct it will be handled below.
#if defined(DEBUG)
- if (comp->compDoOldStructRetyping())
- {
- assert(varTypeIsSIMD(ret) || !varTypeIsStruct(ret));
- assert(varTypeIsSIMD(retVal) || !varTypeIsStruct(retVal));
- }
- else
- {
- assert(!varTypeIsStruct(ret) && !varTypeIsStruct(retVal));
- }
+ assert(!varTypeIsStruct(ret) && !varTypeIsStruct(retVal));
#endif
GenTree* bitcast = comp->gtNewBitCastNode(ret->TypeGet(), retVal);
@@ -3033,9 +3014,8 @@ void Lowering::LowerRet(GenTreeUnOp* ret)
#ifdef DEBUG
if (varTypeIsStruct(ret->TypeGet()) != varTypeIsStruct(retVal->TypeGet()))
{
- if (!comp->compDoOldStructRetyping() && varTypeIsStruct(ret->TypeGet()))
+ if (varTypeIsStruct(ret->TypeGet()))
{
- assert(!comp->compDoOldStructRetyping());
assert(comp->info.compRetNativeType != TYP_STRUCT);
var_types retActualType = genActualType(comp->info.compRetNativeType);
@@ -3059,22 +3039,9 @@ void Lowering::LowerRet(GenTreeUnOp* ret)
}
else if (!ret->TypeIs(TYP_VOID) && varTypeIsStruct(retVal))
{
- if (comp->compDoOldStructRetyping())
- {
-#ifdef FEATURE_SIMD
- assert(ret->TypeIs(TYP_DOUBLE));
- assert(retVal->TypeIs(TYP_SIMD8));
-#else
- unreached();
-#endif
- }
- else
- {
- // Return struct as a primitive using Unsafe cast.
- assert(!comp->compDoOldStructRetyping());
- assert(retVal->OperIs(GT_LCL_VAR));
- LowerRetSingleRegStructLclVar(ret);
- }
+ // Return struct as a primitive using Unsafe cast.
+ assert(retVal->OperIs(GT_LCL_VAR));
+ LowerRetSingleRegStructLclVar(ret);
}
}
@@ -3111,7 +3078,6 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore)
assert(varDsc->CanBeReplacedWithItsField(comp) || varDsc->lvDoNotEnregister || !varDsc->lvPromoted);
if (varDsc->CanBeReplacedWithItsField(comp))
{
- assert(!comp->compDoOldStructRetyping());
assert(varDsc->lvFieldCnt == 1);
unsigned fldNum = varDsc->lvFieldLclStart;
LclVarDsc* fldDsc = comp->lvaGetDesc(fldNum);
@@ -3165,7 +3131,6 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore)
#if defined(TARGET_XARCH) && !defined(UNIX_AMD64_ABI)
// Windows x64 doesn't have multireg returns,
// x86 uses it only for long return type, not for structs.
- assert(!comp->compDoOldStructRetyping());
assert(slotCount == 1);
assert(regType != TYP_UNDEF);
#else // !TARGET_XARCH || UNIX_AMD64_ABI
@@ -3177,7 +3142,6 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore)
}
else
{
- assert(!comp->compDoOldStructRetyping());
unsigned size = layout->GetSize();
assert((size <= 8) || (size == 16));
bool isPowerOf2 = (((size - 1) & size) == 0);
@@ -3252,16 +3216,7 @@ void Lowering::LowerRetStruct(GenTreeUnOp* ret)
{
assert(varTypeIsSIMD(ret->gtGetOp1()));
assert(comp->compMethodReturnsMultiRegRegTypeAlternate());
- if (!comp->compDoOldStructRetyping())
- {
- ret->ChangeType(comp->info.compRetNativeType);
- }
- else
- {
- // With old struct retyping a value that is returned as HFA
- // could have both SIMD* or STRUCT types, keep it as it.
- return;
- }
+ ret->ChangeType(comp->info.compRetNativeType);
}
else
{
@@ -3270,7 +3225,6 @@ void Lowering::LowerRetStruct(GenTreeUnOp* ret)
if (retVal->TypeGet() != ret->TypeGet())
{
assert(retVal->OperIs(GT_LCL_VAR));
- assert(!comp->compDoOldStructRetyping());
LowerRetSingleRegStructLclVar(ret);
}
return;
@@ -3284,7 +3238,6 @@ void Lowering::LowerRetStruct(GenTreeUnOp* ret)
return;
}
- assert(!comp->compDoOldStructRetyping());
assert(ret->OperIs(GT_RETURN));
assert(varTypeIsStruct(ret));
@@ -3394,7 +3347,6 @@ void Lowering::LowerRetStruct(GenTreeUnOp* ret)
void Lowering::LowerRetSingleRegStructLclVar(GenTreeUnOp* ret)
{
assert(!comp->compMethodReturnsMultiRegRegTypeAlternate());
- assert(!comp->compDoOldStructRetyping());
assert(ret->OperIs(GT_RETURN));
GenTreeLclVarCommon* lclVar = ret->gtGetOp1()->AsLclVar();
assert(lclVar->OperIs(GT_LCL_VAR));
@@ -3485,7 +3437,6 @@ void Lowering::LowerCallStruct(GenTreeCall* call)
}
}
- assert(!comp->compDoOldStructRetyping());
CORINFO_CLASS_HANDLE retClsHnd = call->gtRetClsHnd;
Compiler::structPassingKind howToReturnStruct;
var_types returnType = comp->getReturnTypeForStruct(retClsHnd, call->GetUnmanagedCallConv(), &howToReturnStruct);
@@ -3546,8 +3497,6 @@ void Lowering::LowerCallStruct(GenTreeCall* call)
//
void Lowering::LowerStoreSingleRegCallStruct(GenTreeBlk* store)
{
- assert(!comp->compDoOldStructRetyping());
- assert(varTypeIsStruct(store));
assert(store->Data()->IsCall());
GenTreeCall* call = store->Data()->AsCall();
assert(!call->HasMultiRegRetVal());
diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp
index cf5d6e34b0137a..0a9c8eb7f86f55 100644
--- a/src/coreclr/jit/lowerarmarch.cpp
+++ b/src/coreclr/jit/lowerarmarch.cpp
@@ -1453,13 +1453,17 @@ void Lowering::ContainCheckIndir(GenTreeIndir* indirNode)
MakeSrcContained(indirNode, addr);
}
}
+ else if (addr->OperIs(GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR))
+ {
+ // These nodes go into an addr mode:
+ // - GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR is a stack addr mode.
+ MakeSrcContained(indirNode, addr);
+ }
#ifdef TARGET_ARM64
- else if (addr->OperIs(GT_CLS_VAR_ADDR, GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR))
+ else if (addr->OperIs(GT_CLS_VAR_ADDR))
{
// These nodes go into an addr mode:
// - GT_CLS_VAR_ADDR turns into a constant.
- // - GT_LCL_VAR_ADDR, GT_LCL_FLD_ADDR is a stack addr mode.
-
// make this contained, it turns into a constant that goes into an addr mode
MakeSrcContained(indirNode, addr);
}
diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp
index 8fbce8a586e796..7ce35872d1bc08 100644
--- a/src/coreclr/jit/morph.cpp
+++ b/src/coreclr/jit/morph.cpp
@@ -5114,7 +5114,7 @@ void Compiler::fgMakeOutgoingStructArgCopy(GenTreeCall* call,
GenTree* arg = fgMakeTmpArgNode(argEntry);
// Change the expression to "(tmp=val),tmp"
- arg = gtNewOperNode(GT_COMMA, arg->TypeGet(), copyBlk, arg);
+ arg = gtNewOperNode(GT_COMMA, arg->TypeGet(), copyBlk, arg);
#endif // FEATURE_FIXED_OUT_ARGS
@@ -5166,84 +5166,6 @@ void Compiler::fgAddSkippedRegsInPromotedStructArg(LclVarDsc* varDsc,
#endif // TARGET_ARM
-//****************************************************************************
-// fgFixupStructReturn:
-// The companion to impFixupCallStructReturn. Now that the importer is done
-// change the gtType to the precomputed native return type
-// requires that callNode currently has a struct type
-//
-void Compiler::fgFixupStructReturn(GenTree* callNode)
-{
- if (!compDoOldStructRetyping())
- {
- return;
- }
- assert(varTypeIsStruct(callNode));
-
- GenTreeCall* call = callNode->AsCall();
- bool callHasRetBuffArg = call->HasRetBufArg();
- bool isHelperCall = call->IsHelperCall();
-
- // Decide on the proper return type for this call that currently returns a struct
- //
- CORINFO_CLASS_HANDLE retClsHnd = call->gtRetClsHnd;
- Compiler::structPassingKind howToReturnStruct;
- var_types returnType;
-
- // There are a couple of Helper Calls that say they return a TYP_STRUCT but they
- // expect this method to re-type this to a TYP_REF (what is in call->gtReturnType)
- //
- // CORINFO_HELP_METHODDESC_TO_STUBRUNTIMEMETHOD
- // CORINFO_HELP_FIELDDESC_TO_STUBRUNTIMEFIELD
- // CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE_MAYBENULL
- //
- if (isHelperCall)
- {
- assert(!callHasRetBuffArg);
- assert(retClsHnd == NO_CLASS_HANDLE);
-
- // Now that we are past the importer, re-type this node
- howToReturnStruct = SPK_PrimitiveType;
- returnType = (var_types)call->gtReturnType;
- }
- else
- {
- returnType = getReturnTypeForStruct(retClsHnd, call->GetUnmanagedCallConv(), &howToReturnStruct);
- }
-
- if (howToReturnStruct == SPK_ByReference)
- {
- assert(returnType == TYP_UNKNOWN);
- assert(callHasRetBuffArg);
- }
- else
- {
- assert(returnType != TYP_UNKNOWN);
-
- if (!varTypeIsStruct(returnType))
- {
- // Widen the primitive type if necessary
- returnType = genActualType(returnType);
- }
- call->gtType = returnType;
- }
-
-#if FEATURE_MULTIREG_RET
- // Either we don't have a struct now or if struct, then it is a struct returned in regs or in return buffer.
- assert((call->gtType != TYP_STRUCT) || call->HasMultiRegRetVal() || callHasRetBuffArg);
-#else // !FEATURE_MULTIREG_RET
- // No more struct returns
- assert(call->TypeGet() != TYP_STRUCT);
-#endif
-
-#if !defined(UNIX_AMD64_ABI)
- // If it was a struct return, it has been transformed into a call
- // with a return buffer (that returns TYP_VOID) or into a return
- // of a primitive/enregisterable type
- assert(!callHasRetBuffArg || (call->TypeGet() == TYP_VOID));
-#endif
-}
-
/*****************************************************************************
*
* A little helper used to rearrange nested commutative operations. The
@@ -6893,7 +6815,7 @@ bool Compiler::fgCanFastTailCall(GenTreeCall* callee, const char** failReason)
#ifdef DEBUG
if (callee->IsTailPrefixedCall())
{
- var_types retType = (compDoOldStructRetyping() ? info.compRetNativeType : info.compRetType);
+ var_types retType = info.compRetType;
assert(impTailCallRetTypeCompatible(retType, info.compMethodInfo->args.retTypeClass, info.compCallConv,
(var_types)callee->gtReturnType, callee->gtRetClsHnd,
callee->GetUnmanagedCallConv()));
@@ -9115,10 +9037,6 @@ Statement* Compiler::fgAssignRecursiveCallArgToCallerParam(GenTree* arg,
GenTree* Compiler::fgMorphCall(GenTreeCall* call)
{
- if (varTypeIsStruct(call))
- {
- fgFixupStructReturn(call);
- }
if (call->CanTailCall())
{
GenTree* newNode = fgMorphPotentialTailCall(call);
@@ -10590,8 +10508,7 @@ GenTree* Compiler::fgMorphGetStructAddr(GenTree** pTree, CORINFO_CLASS_HANDLE cl
{
// TODO: Consider using lvaGrabTemp and gtNewTempAssign instead, since we're
// not going to use "temp"
- GenTree* temp = fgInsertCommaFormTemp(pTree, clsHnd);
- assert(!compDoOldStructRetyping());
+ GenTree* temp = fgInsertCommaFormTemp(pTree, clsHnd);
unsigned lclNum = temp->gtEffectiveVal()->AsLclVar()->GetLclNum();
lvaSetVarDoNotEnregister(lclNum DEBUG_ARG(DNER_VMNeedsStackAddr));
addr = fgMorphGetStructAddr(pTree, clsHnd, isRValue);
@@ -10938,7 +10855,7 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)
}
#endif // FEATURE_MULTIREG_RET
- if (src->IsCall() && !compDoOldStructRetyping())
+ if (src->IsCall())
{
if (dest->OperIs(GT_OBJ))
{
@@ -12512,6 +12429,20 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)
#endif // !TARGET_64BIT
break;
+ case GT_ARR_LENGTH:
+ if (op1->OperIs(GT_CNS_STR))
+ {
+ // Optimize `ldstr + String::get_Length()` to CNS_INT
+ // e.g. "Hello".Length => 5
+ GenTreeIntCon* iconNode = gtNewStringLiteralLength(op1->AsStrCon());
+ if (iconNode != nullptr)
+ {
+ INDEBUG(iconNode->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED);
+ return iconNode;
+ }
+ }
+ break;
+
case GT_DIV:
// Replace "val / dcon" with "val * (1.0 / dcon)" if dcon is a power of two.
// Powers of two within range are always exactly represented,
@@ -12843,7 +12774,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)
return tree;
}
- if (!compDoOldStructRetyping() && !tree->TypeIs(TYP_VOID))
+ if (!tree->TypeIs(TYP_VOID))
{
if (op1->OperIs(GT_OBJ, GT_BLK, GT_IND))
{
@@ -13614,14 +13545,12 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)
goto SKIP;
}
-#if FEATURE_ANYCSE
/* If the LCL_VAR is a CSE temp then bail, it could have multiple defs/uses */
// Fix 383856 X86/ARM ILGEN
if (lclNumIsCSE(lclNum))
{
goto SKIP;
}
-#endif
/* We also must be assigning the result of a RELOP */
if (asg->AsOp()->gtOp1->gtOper != GT_LCL_VAR)
@@ -15253,7 +15182,6 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)
//
GenTree* Compiler::fgMorphRetInd(GenTreeUnOp* ret)
{
- assert(!compDoOldStructRetyping());
assert(ret->OperIs(GT_RETURN));
assert(ret->gtGetOp1()->OperIs(GT_IND, GT_BLK, GT_OBJ));
GenTreeIndir* ind = ret->gtGetOp1()->AsIndir();
diff --git a/src/coreclr/jit/optcse.cpp b/src/coreclr/jit/optcse.cpp
index 2b9bebd53d5b07..c37e7207f088e4 100644
--- a/src/coreclr/jit/optcse.cpp
+++ b/src/coreclr/jit/optcse.cpp
@@ -16,10 +16,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#pragma hdrstop
#endif
-/*****************************************************************************/
-#if FEATURE_ANYCSE
-/*****************************************************************************/
-
/* static */
const size_t Compiler::s_optCSEhashSizeInitial = EXPSET_SZ * 2;
const size_t Compiler::s_optCSEhashGrowthFactor = 2;
@@ -219,7 +215,7 @@ bool Compiler::optCSE_canSwap(GenTree* op1, GenTree* op2)
// If we haven't setup cseMaskTraits, do it now
if (cseMaskTraits == nullptr)
{
- cseMaskTraits = new (getAllocator()) BitVecTraits(optCSECandidateCount, this);
+ cseMaskTraits = new (getAllocator(CMK_CSE)) BitVecTraits(optCSECandidateCount, this);
}
optCSE_MaskData op1MaskData;
@@ -338,10 +334,6 @@ bool Compiler::optCSEcostCmpSz::operator()(const CSEdsc* dsc1, const CSEdsc* dsc
return dsc1->csdIndex < dsc2->csdIndex;
}
-/*****************************************************************************/
-#if FEATURE_VALNUM_CSE
-/*****************************************************************************/
-
/*****************************************************************************
*
* Initialize the Value Number CSE tracking logic.
@@ -975,7 +967,7 @@ void Compiler::optCseUpdateCheckedBoundMap(GenTree* compare)
if (optCseCheckedBoundMap == nullptr)
{
// Allocate map on first use.
- optCseCheckedBoundMap = new (getAllocator()) NodeToNodeMap(getAllocator());
+ optCseCheckedBoundMap = new (getAllocator(CMK_CSE)) NodeToNodeMap(getAllocator());
}
optCseCheckedBoundMap->Set(bound, compare);
@@ -1005,7 +997,7 @@ void Compiler::optValnumCSE_InitDataFlow()
const unsigned bitCount = (optCSECandidateCount * 2) + 1;
// Init traits and cseCallKillsMask bitvectors.
- cseLivenessTraits = new (getAllocator()) BitVecTraits(bitCount, this);
+ cseLivenessTraits = new (getAllocator(CMK_CSE)) BitVecTraits(bitCount, this);
cseCallKillsMask = BitVecOps::MakeEmpty(cseLivenessTraits);
for (unsigned inx = 0; inx < optCSECandidateCount; inx++)
{
@@ -3471,8 +3463,6 @@ void Compiler::optOptimizeValnumCSEs()
optValnumCSE_phase = false;
}
-#endif // FEATURE_VALNUM_CSE
-
/*****************************************************************************
*
* The following determines whether the given expression is a worthy CSE
@@ -3829,11 +3819,9 @@ void Compiler::optOptimizeCSEs()
optCSECandidateCount = 0;
optCSEstart = lvaCount;
-#if FEATURE_VALNUM_CSE
INDEBUG(optEnsureClearCSEInfo());
optOptimizeValnumCSEs();
EndPhase(PHASE_OPTIMIZE_VALNUM_CSES);
-#endif // FEATURE_VALNUM_CSE
}
/*****************************************************************************
@@ -3888,7 +3876,3 @@ void Compiler::optEnsureClearCSEInfo()
}
#endif // DEBUG
-
-/*****************************************************************************/
-#endif // FEATURE_ANYCSE
-/*****************************************************************************/
diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp
index 17b4a1858cea72..6545a894c4e579 100644
--- a/src/coreclr/jit/optimizer.cpp
+++ b/src/coreclr/jit/optimizer.cpp
@@ -38,11 +38,9 @@ void Compiler::optInit()
optNativeCallCount = 0;
optAssertionCount = 0;
optAssertionDep = nullptr;
-#if FEATURE_ANYCSE
optCSECandidateTotal = 0;
optCSEstart = UINT_MAX;
optCSEcount = 0;
-#endif // FEATURE_ANYCSE
}
DataFlow::DataFlow(Compiler* pCompiler) : m_pCompiler(pCompiler)
@@ -228,17 +226,10 @@ void Compiler::optMarkLoopBlocks(BasicBlock* begBlk, BasicBlock* endBlk, bool ex
scale = scale / 2;
}
- //
- // Set the new weight
- //
curBlk->scaleBBWeight(scale);
}
-#ifdef DEBUG
- if (verbose)
- {
- printf("\n " FMT_BB "(wt=%s)", curBlk->bbNum, refCntWtd2str(curBlk->getBBWeight(this)));
- }
-#endif
+
+ JITDUMP("\n " FMT_BB "(wt=" FMT_WT ")", curBlk->bbNum, curBlk->getBBWeight(this));
}
}
@@ -347,41 +338,19 @@ void Compiler::optUnmarkLoopBlocks(BasicBlock* begBlk, BasicBlock* endBlk)
//
if (!curBlk->isMaxBBWeight() && !curBlk->hasProfileWeight())
{
- BasicBlock::weight_t weight = curBlk->bbWeight;
+ BasicBlock::weight_t scale = 1.0f / BB_LOOP_WEIGHT_SCALE;
if (!fgDominate(curBlk, endBlk))
{
- weight *= 2;
- }
- else
- {
- /* Merging of blocks can disturb the Dominates
- information (see RAID #46649) */
- if (weight < BB_LOOP_WEIGHT_SCALE)
- {
- weight *= 2;
- }
+ scale *= 2;
}
- // We can overflow here so check for it
- if (weight < curBlk->bbWeight)
- {
- weight = BB_MAX_WEIGHT;
- }
-
- assert(curBlk->bbWeight != BB_ZERO_WEIGHT);
- BasicBlock::weight_t scale = weight / curBlk->bbWeight;
-
curBlk->scaleBBWeight(scale);
}
-#ifdef DEBUG
- if (verbose)
- {
- printf("\n " FMT_BB "(wt=%s)", curBlk->bbNum, refCntWtd2str(curBlk->getBBWeight(this)));
- }
-#endif
+ JITDUMP("\n " FMT_BB "(wt=" FMT_WT ")", curBlk->bbNum, curBlk->getBBWeight(this));
}
+
/* Stop if we've reached the last block in the loop */
if (curBlk == endBlk)
@@ -1836,7 +1805,7 @@ class LoopSearch
// Seed the loop block set and worklist with the entry block.
loopBlocks.Reset(entry->bbNum);
- jitstd::list worklist(comp->getAllocator());
+ jitstd::list worklist(comp->getAllocator(CMK_LoopOpt));
worklist.push_back(entry);
while (!worklist.empty())
@@ -3812,7 +3781,7 @@ void Compiler::optUnrollLoops()
/* Create the unrolled loop statement list */
{
- BlockToBlockMap blockMap(getAllocator());
+ BlockToBlockMap blockMap(getAllocator(CMK_LoopOpt));
BasicBlock* insertAfter = bottom;
for (lval = lbeg; totalIter; totalIter--)
@@ -4068,58 +4037,78 @@ bool Compiler::optReachWithoutCall(BasicBlock* topBB, BasicBlock* botBB)
return true;
}
+// static
+Compiler::fgWalkResult Compiler::optInvertCountTreeInfo(GenTree** pTree, fgWalkData* data)
+{
+ OptInvertCountTreeInfoType* o = (OptInvertCountTreeInfoType*)data->pCallbackData;
+
+ if (Compiler::IsSharedStaticHelper(*pTree))
+ {
+ o->sharedStaticHelperCount += 1;
+ }
+
+ if ((*pTree)->OperGet() == GT_ARR_LENGTH)
+ {
+ o->arrayLengthCount += 1;
+ }
+
+ return WALK_CONTINUE;
+}
+
//-----------------------------------------------------------------------------
// optInvertWhileLoop: modify flow and duplicate code so that for/while loops are
// entered at top and tested at bottom (aka loop rotation or bottom testing).
+// Creates a "zero trip test" condition which guards entry to the loop.
+// Enables loop invariant hoisting and loop cloning, which depend on
+// `do {} while` format loops. Enables creation of a pre-header block after the
+// zero trip test to place code that only runs if the loop is guaranteed to
+// run at least once.
//
// Arguments:
// block -- block that may be the predecessor of the un-rotated loop's test block.
//
// Notes:
-// Optimizes "jmp C; do{} C:while(cond);" loops to "if (cond){ do{}while(cond}; }"
-// Does not modify every loop
+// Uses a simple lexical screen to detect likely loops.
+//
+// Specifically, we're looking for the following case:
+//
+// ...
+// jmp test // `block` argument
+// loop:
+// ...
+// ...
+// test:
+// ..stmts..
+// cond
+// jtrue loop
+//
+// If we find this, and the condition is simple enough, we change
+// the loop to the following:
+//
+// ...
+// ..stmts.. // duplicated cond block statments
+// cond // duplicated cond
+// jfalse done
+// // else fall-through
+// loop:
+// ...
+// ...
+// test:
+// ..stmts..
+// cond
+// jtrue loop
+// done:
//
// Makes no changes if the flow pattern match fails.
//
// May not modify a loop if profile is unfavorable, if the cost of duplicating
-// code is large (factoring in potential CSEs)
+// code is large (factoring in potential CSEs).
//
void Compiler::optInvertWhileLoop(BasicBlock* block)
{
assert(opts.OptimizationEnabled());
assert(compCodeOpt() != SMALL_CODE);
- /*
- Optimize while loops into do { } while loop
- Our loop hoisting logic requires do { } while loops.
- Specifically, we're looking for the following case:
-
- ...
- jmp test
- loop:
- ...
- ...
- test:
- cond
- jtrue loop
-
- If we find this, and the condition is simple enough, we change
- the loop to the following:
-
- ...
- cond
- jfalse done
- // else fall-through
- loop:
- ...
- ...
- test:
- cond
- jtrue loop
- done:
-
- */
-
/* Does the BB end with an unconditional jump? */
if (block->bbJumpKind != BBJ_ALWAYS || (block->bbFlags & BBF_KEEP_BBJ_ALWAYS))
@@ -4168,49 +4157,47 @@ void Compiler::optInvertWhileLoop(BasicBlock* block)
return;
}
- // Find the loop termination test at the bottom of the loop.
- Statement* condStmt = bTest->lastStmt();
-
- // bTest must only contain only a jtrue with no other stmts, we will only clone
- // the conditional, so any other statements will not get cloned
- // TODO-CQ: consider cloning the whole bTest block and inserting it after block.
+ // It has to be a forward jump. Defer this check until after all the cheap checks
+ // are done, since it iterates forward in the block list looking for bbJumpDest.
+ // TODO-CQ: Check if we can also optimize the backwards jump as well.
//
- if (bTest->bbStmtList != condStmt)
+ if (!fgIsForwardBranch(block))
{
return;
}
- /* Get to the condition node from the statement tree */
+ // Find the loop termination test at the bottom of the loop.
+ Statement* condStmt = bTest->lastStmt();
- GenTree* condTree = condStmt->GetRootNode();
+ // Verify the test block ends with a conditional that we can manipulate.
+ GenTree* const condTree = condStmt->GetRootNode();
noway_assert(condTree->gtOper == GT_JTRUE);
-
- condTree = condTree->AsOp()->gtOp1;
-
- // The condTree has to be a RelOp comparison
- // TODO-CQ: Check if we can also optimize the backwards jump as well.
- //
- if (condTree->OperIsCompare() == false)
+ if (!condTree->AsOp()->gtOp1->OperIsCompare())
{
return;
}
- // It has to be a forward jump. Defer this check until after all the cheap checks
- // are done, since it iterates forward in the block list looking for bbJumpDest.
- // TODO-CQ: Check if we can also optimize the backwards jump as well.
+ // Estimate the cost of cloning the entire test block.
//
- if (fgIsForwardBranch(block) == false)
- {
- return;
- }
-
- /* We call gtPrepareCost to measure the cost of duplicating this tree */
+ // Note: it would help throughput to compute the maximum cost
+ // first and early out for large bTest blocks, as we are doing two
+ // tree walks per tree. But because of this helper call scan, the
+ // maximum cost depends on the trees in the block.
+ //
+ // We might consider flagging blocks with hoistable helper calls
+ // during importation, so we can avoid the helper search and
+ // implement an early bail out for large blocks with no helper calls.
- gtPrepareCost(condTree);
- unsigned estDupCostSz = condTree->GetCostSz();
+ unsigned estDupCostSz = 0;
- BasicBlock::weight_t loopIterations = BB_LOOP_WEIGHT_SCALE;
+ for (Statement* stmt : bTest->Statements())
+ {
+ GenTree* tree = stmt->GetRootNode();
+ gtPrepareCost(tree);
+ estDupCostSz += tree->GetCostSz();
+ }
+ BasicBlock::weight_t loopIterations = BB_LOOP_WEIGHT_SCALE;
bool allProfileWeightsAreValid = false;
BasicBlock::weight_t const weightBlock = block->bbWeight;
BasicBlock::weight_t const weightTest = bTest->bbWeight;
@@ -4259,10 +4246,8 @@ void Compiler::optInvertWhileLoop(BasicBlock* block)
}
}
- unsigned maxDupCostSz = 32;
+ unsigned maxDupCostSz = 34;
- // optFastCodeOrBlendedLoop(bTest->bbWeight) does not work here as we have not
- // set loop weights yet
if ((compCodeOpt() == FAST_CODE) || compStressCompile(STRESS_DO_WHILE_LOOPS, 30))
{
maxDupCostSz *= 4;
@@ -4278,40 +4263,65 @@ void Compiler::optInvertWhileLoop(BasicBlock* block)
}
}
- // If the compare has too high cost then we don't want to dup
+ // If the compare has too high cost then we don't want to dup.
bool costIsTooHigh = (estDupCostSz > maxDupCostSz);
- int countOfHelpers = 0;
+ OptInvertCountTreeInfoType optInvertTotalInfo = {};
if (costIsTooHigh)
{
// If we already know that the cost is acceptable, then don't waste time walking the tree
- // counting shared static helpers.
+ // counting things to boost the maximum allowed cost.
//
// If the loop condition has a shared static helper, we really want this loop converted
// as not converting the loop will disable loop hoisting, meaning the shared helper will
// be executed on every loop iteration.
- fgWalkTreePre(&condTree, CountSharedStaticHelper, &countOfHelpers);
+ //
+ // If the condition has array.Length operations, also boost, as they are likely to be CSE'd.
- if (countOfHelpers > 0)
+ for (Statement* stmt : bTest->Statements())
{
- maxDupCostSz += 24 * min(countOfHelpers, (int)(loopIterations + 1.5));
+ GenTree* tree = stmt->GetRootNode();
+
+ OptInvertCountTreeInfoType optInvertInfo = {};
+ fgWalkTreePre(&tree, Compiler::optInvertCountTreeInfo, &optInvertInfo);
+ optInvertTotalInfo.sharedStaticHelperCount += optInvertInfo.sharedStaticHelperCount;
+ optInvertTotalInfo.arrayLengthCount += optInvertInfo.arrayLengthCount;
- // Is the cost too high now?
- costIsTooHigh = (estDupCostSz > maxDupCostSz);
+ if ((optInvertInfo.sharedStaticHelperCount > 0) || (optInvertInfo.arrayLengthCount > 0))
+ {
+ // Calculate a new maximum cost. We might be able to early exit.
+
+ unsigned newMaxDupCostSz =
+ maxDupCostSz + 24 * min(optInvertTotalInfo.sharedStaticHelperCount, (int)(loopIterations + 1.5)) +
+ 8 * optInvertTotalInfo.arrayLengthCount;
+
+ // Is the cost too high now?
+ costIsTooHigh = (estDupCostSz > newMaxDupCostSz);
+ if (!costIsTooHigh)
+ {
+ // No need counting any more trees; we're going to do the transformation.
+ JITDUMP("Decided to duplicate loop condition block after counting helpers in tree [%06u] in "
+ "block " FMT_BB,
+ dspTreeID(tree), bTest->bbNum);
+ maxDupCostSz = newMaxDupCostSz; // for the JitDump output below
+ break;
+ }
+ }
}
}
#ifdef DEBUG
if (verbose)
{
- // Note that `countOfHelpers = 0` means either there were zero helpers, or the tree walk to count them was not
- // done.
- printf("\nDuplication of loop condition [%06u] is %s, because the cost of duplication (%i) is %s than %i,"
- "\n loopIterations = %7.3f, countOfHelpers = %d, validProfileWeights = %s\n",
- dspTreeID(condTree), costIsTooHigh ? "not done" : "performed", estDupCostSz,
- costIsTooHigh ? "greater" : "less or equal", maxDupCostSz, loopIterations, countOfHelpers,
- dspBool(allProfileWeightsAreValid));
+ // Note that `optInvertTotalInfo.sharedStaticHelperCount = 0` means either there were zero helpers, or the
+ // tree walk to count them was not done.
+ printf(
+ "\nDuplication of loop condition [%06u] is %s, because the cost of duplication (%i) is %s than %i,"
+ "\n loopIterations = %7.3f, optInvertTotalInfo.sharedStaticHelperCount >= %d, validProfileWeights = %s\n",
+ dspTreeID(condTree), costIsTooHigh ? "not done" : "performed", estDupCostSz,
+ costIsTooHigh ? "greater" : "less or equal", maxDupCostSz, loopIterations,
+ optInvertTotalInfo.sharedStaticHelperCount, dspBool(allProfileWeightsAreValid));
}
#endif
@@ -4320,34 +4330,47 @@ void Compiler::optInvertWhileLoop(BasicBlock* block)
return;
}
- /* Looks good - duplicate the condition test */
+ bool foundCondTree = false;
- condTree->gtFlags |= GTF_RELOP_ZTT;
+ // Clone each statement in bTest and append to block.
+ for (Statement* stmt : bTest->Statements())
+ {
+ GenTree* originalTree = stmt->GetRootNode();
+ GenTree* clonedTree = gtCloneExpr(originalTree);
- condTree = gtCloneExpr(condTree);
- gtReverseCond(condTree);
+ // Special case handling needed for the conditional jump tree
+ if (originalTree == condTree)
+ {
+ foundCondTree = true;
- // Make sure clone expr copied the flag
- assert(condTree->gtFlags & GTF_RELOP_ZTT);
+ // Get the compare subtrees
+ GenTree* originalCompareTree = originalTree->AsOp()->gtOp1;
+ GenTree* clonedCompareTree = clonedTree->AsOp()->gtOp1;
+ assert(originalCompareTree->OperIsCompare());
+ assert(clonedCompareTree->OperIsCompare());
- condTree = gtNewOperNode(GT_JTRUE, TYP_VOID, condTree);
+ // Flag compare and cloned copy so later we know this loop
+ // has a proper zero trip test.
+ originalCompareTree->gtFlags |= GTF_RELOP_ZTT;
+ clonedCompareTree->gtFlags |= GTF_RELOP_ZTT;
- /* Create a statement entry out of the condition and
- append the condition test at the end of 'block' */
+ // The original test branches to remain in the loop. The
+ // new cloned test will branch to avoid the loop. So the
+ // cloned compare needs to reverse the branch condition.
+ gtReverseCond(clonedCompareTree);
+ }
- Statement* copyOfCondStmt = fgNewStmtAtEnd(block, condTree);
+ Statement* clonedStmt = fgNewStmtAtEnd(block, clonedTree);
- copyOfCondStmt->SetCompilerAdded();
+ if (opts.compDbgInfo)
+ {
+ clonedStmt->SetILOffsetX(stmt->GetILOffsetX());
+ }
- if (condTree->gtFlags & GTF_CALL)
- {
- block->bbFlags |= BBF_HAS_CALL; // Record that the block has a call
+ clonedStmt->SetCompilerAdded();
}
- if (opts.compDbgInfo)
- {
- copyOfCondStmt->SetILOffsetX(condStmt->GetILOffsetX());
- }
+ assert(foundCondTree);
// Flag the block that received the copy as potentially having an array/vtable
// reference, nullcheck, object/array allocation if the block copied from did;
@@ -4372,17 +4395,6 @@ void Compiler::optInvertWhileLoop(BasicBlock* block)
fgRemoveRefPred(bTest, block);
fgAddRefPred(bTest->bbNext, block);
-#ifdef DEBUG
- if (verbose)
- {
- printf("\nDuplicated loop condition in " FMT_BB " for loop (" FMT_BB " - " FMT_BB ")\n", block->bbNum,
- block->bbNext->bbNum, bTest->bbNum);
- printf("Estimated code size expansion is %d\n", estDupCostSz);
-
- gtDispStmt(copyOfCondStmt);
- }
-#endif // DEBUG
-
// If we have profile data for all blocks and we know that we are cloning the
// bTest block into block and thus changing the control flow from block so
// that it no longer goes directly to bTest anymore, we have to adjust
@@ -4451,6 +4463,18 @@ void Compiler::optInvertWhileLoop(BasicBlock* block)
fgDebugCheckIncomingProfileData(block->bbJumpDest);
#endif // DEBUG
}
+
+#ifdef DEBUG
+ if (verbose)
+ {
+ printf("\nDuplicated loop exit block at " FMT_BB " for loop (" FMT_BB " - " FMT_BB ")\n", block->bbNum,
+ block->bbNext->bbNum, bTest->bbNum);
+ printf("Estimated code size expansion is %d\n", estDupCostSz);
+
+ fgDumpBlock(block);
+ fgDumpBlock(bTest);
+ }
+#endif // DEBUG
}
//-----------------------------------------------------------------------------
@@ -4464,6 +4488,14 @@ PhaseStatus Compiler::optInvertLoops()
noway_assert(opts.OptimizationEnabled());
noway_assert(fgModified == false);
+#if defined(OPT_CONFIG)
+ if (!JitConfig.JitDoLoopInversion())
+ {
+ JITDUMP("Loop inversion disabled\n");
+ return PhaseStatus::MODIFIED_NOTHING;
+ }
+#endif // OPT_CONFIG
+
if (compCodeOpt() == SMALL_CODE)
{
return PhaseStatus::MODIFIED_NOTHING;
@@ -4642,6 +4674,7 @@ PhaseStatus Compiler::optFindLoops()
// Check if any of the loops need alignment
+ JITDUMP("\n");
optIdentifyLoopsForAlignment();
#if COUNT_LOOPS
@@ -4756,7 +4789,7 @@ bool Compiler::optDeriveLoopCloningConditions(unsigned loopNum, LoopCloneContext
}
else if (loop->lpFlags & LPFLG_ARRLEN_LIMIT)
{
- ArrIndex* index = new (getAllocator()) ArrIndex(getAllocator());
+ ArrIndex* index = new (getAllocator(CMK_LoopClone)) ArrIndex(getAllocator(CMK_LoopClone));
if (!loop->lpArrLenLimit(this, index))
{
JITDUMP("> ArrLen not matching");
@@ -4799,8 +4832,8 @@ bool Compiler::optDeriveLoopCloningConditions(unsigned loopNum, LoopCloneContext
// limit <= mdArrLen
LcMdArrayOptInfo* mdArrInfo = optInfo->AsLcMdArrayOptInfo();
LC_Condition cond(GT_LE, LC_Expr(ident),
- LC_Expr(LC_Ident(LC_Array(LC_Array::MdArray,
- mdArrInfo->GetArrIndexForDim(getAllocator()),
+ LC_Expr(LC_Ident(LC_Array(LC_Array::MdArray, mdArrInfo->GetArrIndexForDim(
+ getAllocator(CMK_LoopClone)),
mdArrInfo->dim, LC_Array::None))));
context->EnsureConditions(loopNum)->Push(cond);
}
@@ -4926,7 +4959,7 @@ bool Compiler::optDeriveLoopCloningConditions(unsigned loopNum, LoopCloneContext
//
bool Compiler::optComputeDerefConditions(unsigned loopNum, LoopCloneContext* context)
{
- JitExpandArrayStack nodes(getAllocator());
+ JitExpandArrayStack nodes(getAllocator(CMK_LoopClone));
int maxRank = -1;
// Get the dereference-able arrays.
@@ -4944,7 +4977,7 @@ bool Compiler::optComputeDerefConditions(unsigned loopNum, LoopCloneContext* con
LC_Deref* node = LC_Deref::Find(&nodes, array.arrIndex->arrLcl);
if (node == nullptr)
{
- node = new (getAllocator()) LC_Deref(array, 0 /*level*/);
+ node = new (getAllocator(CMK_LoopClone)) LC_Deref(array, 0 /*level*/);
nodes.Push(node);
}
@@ -4953,11 +4986,11 @@ bool Compiler::optComputeDerefConditions(unsigned loopNum, LoopCloneContext* con
unsigned rank = (unsigned)array.GetDimRank();
for (unsigned i = 0; i < rank; ++i)
{
- node->EnsureChildren(getAllocator());
+ node->EnsureChildren(getAllocator(CMK_LoopClone));
LC_Deref* tmp = node->Find(array.arrIndex->indLcls[i]);
if (tmp == nullptr)
{
- tmp = new (getAllocator()) LC_Deref(array, node->level + 1);
+ tmp = new (getAllocator(CMK_LoopClone)) LC_Deref(array, node->level + 1);
node->children->Push(tmp);
}
@@ -5300,7 +5333,7 @@ void Compiler::optCloneLoops()
unsigned optStaticallyOptimizedLoops = 0;
- LoopCloneContext context(optLoopCount, getAllocator());
+ LoopCloneContext context(optLoopCount, getAllocator(CMK_LoopClone));
// Obtain array optimization candidates in the context.
optObtainLoopCloningOpts(&context);
@@ -5508,7 +5541,7 @@ void Compiler::optCloneLoop(unsigned loopInd, LoopCloneContext* context)
BasicBlock* newFirst = nullptr;
BasicBlock* newBot = nullptr;
- BlockToBlockMap* blockMap = new (getAllocator()) BlockToBlockMap(getAllocator());
+ BlockToBlockMap* blockMap = new (getAllocator(CMK_LoopClone)) BlockToBlockMap(getAllocator(CMK_LoopClone));
for (BasicBlock* blk = loop.lpFirst; blk != loop.lpBottom->bbNext; blk = blk->bbNext)
{
BasicBlock* newBlk = fgNewBBafter(blk->bbJumpKind, newPred, /*extendRegion*/ true);
@@ -5723,7 +5756,7 @@ void Compiler::optEnsureUniqueHead(unsigned loopInd, BasicBlock::weight_t ambien
BlockSetOps::Assign(this, h2->bbReach, e->bbReach);
// Redirect paths from preds of "e" to go to "h2" instead of "e".
- BlockToBlockMap* blockMap = new (getAllocator()) BlockToBlockMap(getAllocator());
+ BlockToBlockMap* blockMap = new (getAllocator(CMK_LoopClone)) BlockToBlockMap(getAllocator(CMK_LoopClone));
blockMap->Set(e, h2);
for (flowList* predEntry = e->bbPreds; predEntry; predEntry = predEntry->flNext)
@@ -8851,7 +8884,7 @@ bool Compiler::optIsStackLocalInvariant(unsigned loopNum, unsigned lclNum)
//
Compiler::fgWalkResult Compiler::optCanOptimizeByLoopCloning(GenTree* tree, LoopCloneVisitorInfo* info)
{
- ArrIndex arrIndex(getAllocator());
+ ArrIndex arrIndex(getAllocator(CMK_LoopClone));
// Check if array index can be optimized.
if (optReconstructArrIndex(tree, &arrIndex, BAD_VAR_NUM))
diff --git a/src/coreclr/jit/phase.cpp b/src/coreclr/jit/phase.cpp
index b56d29b2b519e0..cc9d6466d73e13 100644
--- a/src/coreclr/jit/phase.cpp
+++ b/src/coreclr/jit/phase.cpp
@@ -197,10 +197,6 @@ void Phase::PostPhase(PhaseStatus status)
printf("Trees after %s\n", m_name);
comp->fgDispBasicBlocks(true);
}
-
-#if DUMP_FLOWGRAPHS
- comp->fgDumpFlowGraph(m_phase);
-#endif // DUMP_FLOWGRAPHS
}
if (doPostPhase)
@@ -230,5 +226,9 @@ void Phase::PostPhase(PhaseStatus status)
#endif // DEBUG
+#if DUMP_FLOWGRAPHS
+ comp->fgDumpFlowGraph(m_phase);
+#endif // DUMP_FLOWGRAPHS
+
comp->EndPhase(m_phase);
}
diff --git a/src/coreclr/jit/unwind.cpp b/src/coreclr/jit/unwind.cpp
index 7bbccd789d6c52..14dc49f50fac6c 100644
--- a/src/coreclr/jit/unwind.cpp
+++ b/src/coreclr/jit/unwind.cpp
@@ -178,7 +178,7 @@ void Compiler::unwindBegPrologCFI()
unwindGetFuncLocations(func, false, &func->coldStartLoc, &func->coldEndLoc);
}
- func->cfiCodes = new (getAllocator()) CFICodeVector(getAllocator());
+ func->cfiCodes = new (getAllocator(CMK_UnwindInfo)) CFICodeVector(getAllocator());
#endif // FEATURE_EH_FUNCLETS
}
diff --git a/src/coreclr/jit/utils.cpp b/src/coreclr/jit/utils.cpp
index 26914f10112f9f..1afb1e78fb0f56 100644
--- a/src/coreclr/jit/utils.cpp
+++ b/src/coreclr/jit/utils.cpp
@@ -657,7 +657,7 @@ const char* refCntWtd2str(BasicBlock::weight_t refCntWtd)
nump = (nump == num1) ? num2 : num1;
- if (refCntWtd == BB_MAX_WEIGHT)
+ if (refCntWtd >= BB_MAX_WEIGHT)
{
sprintf_s(temp, bufSize, "MAX ");
}
diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp
index 2d7e127666ba2b..3957ff13c34700 100644
--- a/src/coreclr/jit/valuenum.cpp
+++ b/src/coreclr/jit/valuenum.cpp
@@ -5847,8 +5847,8 @@ struct ValueNumberState
}
ValueNumberState(Compiler* comp)
- : m_toDoAllPredsDone(comp->getAllocator(), /*minSize*/ 4)
- , m_toDoNotAllPredsDone(comp->getAllocator(), /*minSize*/ 4)
+ : m_toDoAllPredsDone(comp->getAllocator(CMK_ValueNumber), /*minSize*/ 4)
+ , m_toDoNotAllPredsDone(comp->getAllocator(CMK_ValueNumber), /*minSize*/ 4)
, m_comp(comp)
, m_visited(new (comp, CMK_ValueNumber) BYTE[comp->fgBBNumMax + 1]())
{
diff --git a/src/coreclr/pal/src/cruntime/printf.cpp b/src/coreclr/pal/src/cruntime/printf.cpp
index 79d16e7b48f912..f08f6475daa96f 100644
--- a/src/coreclr/pal/src/cruntime/printf.cpp
+++ b/src/coreclr/pal/src/cruntime/printf.cpp
@@ -303,7 +303,7 @@ static BOOL Internal_ScanfExtractFormatW(LPCWSTR *Fmt, LPSTR Out, int iOutSize,
{
ERROR("atoi returned a negative value indicative of an overflow.\n");
SetLastError(ERROR_INTERNAL_ERROR);
- return Result;
+ goto EXIT;
}
}
@@ -401,7 +401,7 @@ static BOOL Internal_ScanfExtractFormatW(LPCWSTR *Fmt, LPSTR Out, int iOutSize,
{
ERROR("strcpy_s failed\n");
SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return FALSE;
+ goto EXIT;
}
Out += strlen(scanf_longlongfmt);
@@ -532,6 +532,8 @@ static BOOL Internal_ScanfExtractFormatW(LPCWSTR *Fmt, LPSTR Out, int iOutSize,
*Out++ = 'n';
*Out = 0; /* end the string */
+
+EXIT:
PAL_free(TempStr);
return Result;
}
diff --git a/src/coreclr/pal/src/cruntime/printfcpp.cpp b/src/coreclr/pal/src/cruntime/printfcpp.cpp
index 0f7cb682650f80..d7e992c090a00b 100644
--- a/src/coreclr/pal/src/cruntime/printfcpp.cpp
+++ b/src/coreclr/pal/src/cruntime/printfcpp.cpp
@@ -220,7 +220,7 @@ BOOL Internal_ExtractFormatA(CPalThread *pthrCurrent, LPCSTR *Fmt, LPSTR Out, LP
{
ERROR("atoi returned a negative value indicative of an overflow.\n");
pthrCurrent->SetLastError(ERROR_INTERNAL_ERROR);
- return Result;
+ goto EXIT;
}
}
else if (**Fmt == '*')
@@ -258,7 +258,7 @@ BOOL Internal_ExtractFormatA(CPalThread *pthrCurrent, LPCSTR *Fmt, LPSTR Out, LP
{
ERROR("atoi returned a negative value indicative of an overflow.\n");
pthrCurrent->SetLastError(ERROR_INTERNAL_ERROR);
- return Result;
+ goto EXIT;
}
}
else if (**Fmt == '*')
@@ -444,6 +444,8 @@ BOOL Internal_ExtractFormatA(CPalThread *pthrCurrent, LPCSTR *Fmt, LPSTR Out, LP
}
*Out = 0; /* end the string */
+
+EXIT:
free(TempStr);
return Result;
}
@@ -525,7 +527,7 @@ BOOL Internal_ExtractFormatW(CPalThread *pthrCurrent, LPCWSTR *Fmt, LPSTR Out, L
{
ERROR("atoi returned a negative value indicative of an overflow.\n");
pthrCurrent->SetLastError(ERROR_INTERNAL_ERROR);
- return Result;
+ goto EXIT;
}
}
else if (**Fmt == '*')
@@ -562,7 +564,7 @@ BOOL Internal_ExtractFormatW(CPalThread *pthrCurrent, LPCWSTR *Fmt, LPSTR Out, L
{
ERROR("atoi returned a negative value indicative of an overflow.\n");
pthrCurrent->SetLastError(ERROR_INTERNAL_ERROR);
- return Result;
+ goto EXIT;
}
}
else if (**Fmt == '*')
@@ -772,6 +774,8 @@ BOOL Internal_ExtractFormatW(CPalThread *pthrCurrent, LPCWSTR *Fmt, LPSTR Out, L
}
*Out = 0; /* end the string */
+
+EXIT:
free(TempStr);
return Result;
}
@@ -899,7 +903,7 @@ static INT Internal_AddPaddingVfwprintf(CPalThread *pthrCurrent, PAL_FILE *strea
LPWSTR OutOriginal;
INT LengthInStr;
INT Length;
- INT Written = 0;
+ INT Written = -1;
LengthInStr = PAL_wcslen(In);
Length = LengthInStr;
@@ -924,9 +928,8 @@ static INT Internal_AddPaddingVfwprintf(CPalThread *pthrCurrent, PAL_FILE *strea
if (wcscpy_s(Out, iLen, In) != SAFECRT_SUCCESS)
{
ERROR("wcscpy_s failed!\n");
- free(OutOriginal);
pthrCurrent->SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return -1;
+ goto EXIT;
}
Out += LengthInStr;
iLen -= LengthInStr;
@@ -954,9 +957,8 @@ static INT Internal_AddPaddingVfwprintf(CPalThread *pthrCurrent, PAL_FILE *strea
if (wcscpy_s(Out, iLen, In) != SAFECRT_SUCCESS)
{
ERROR("wcscpy_s failed!\n");
- free(OutOriginal);
pthrCurrent->SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return -1;
+ goto EXIT;
}
Out += LengthInStr;
@@ -971,9 +973,14 @@ static INT Internal_AddPaddingVfwprintf(CPalThread *pthrCurrent, PAL_FILE *strea
{
ERROR("fwrite() failed with errno == %d\n", errno);
}
- free(OutOriginal);
+ }
+ else
+ {
+ Written = 0;
}
+EXIT:
+ free(OutOriginal);
return Written;
}
diff --git a/src/coreclr/pal/src/cruntime/silent_printf.cpp b/src/coreclr/pal/src/cruntime/silent_printf.cpp
index bc9c718fe3ae3a..17e3007c762fc2 100644
--- a/src/coreclr/pal/src/cruntime/silent_printf.cpp
+++ b/src/coreclr/pal/src/cruntime/silent_printf.cpp
@@ -402,7 +402,7 @@ BOOL Silent_ExtractFormatA(LPCSTR *Fmt, LPSTR Out, LPINT Flags, LPINT Width, LPI
if (*Width < 0)
{
SetLastError(ERROR_INTERNAL_ERROR);
- return Result;
+ goto EXIT;
}
}
else if (**Fmt == '*')
@@ -439,7 +439,7 @@ BOOL Silent_ExtractFormatA(LPCSTR *Fmt, LPSTR Out, LPINT Flags, LPINT Width, LPI
if (*Precision < 0)
{
SetLastError(ERROR_INTERNAL_ERROR);
- return Result;
+ goto EXIT;
}
}
else if (**Fmt == '*')
@@ -595,6 +595,8 @@ BOOL Silent_ExtractFormatA(LPCSTR *Fmt, LPSTR Out, LPINT Flags, LPINT Width, LPI
}
*Out = 0; /* end the string */
+
+EXIT:
PAL_free(TempStr);
return Result;
}
diff --git a/src/coreclr/pal/src/map/virtual.cpp b/src/coreclr/pal/src/map/virtual.cpp
index 456254bdbbb9a8..cea55e86e2538f 100644
--- a/src/coreclr/pal/src/map/virtual.cpp
+++ b/src/coreclr/pal/src/map/virtual.cpp
@@ -1765,8 +1765,8 @@ bool
PAL_JITWriteEnableHolder::JITWriteEnable(bool writeEnable)
{
// Use a thread local to track per thread JIT Write enable state
- // Initialize threads to start with MAP_JIT pages readable and executable (R-X) by default.
- thread_local bool enabled = (pthread_jit_write_protect_np(1), false);
+ // Per Apple, new threads start with MAP_JIT pages readable and executable (R-X) by default.
+ thread_local bool enabled = false;
bool result = enabled;
if (enabled != writeEnable)
{
diff --git a/src/coreclr/scripts/superpmi.py b/src/coreclr/scripts/superpmi.py
index a98d3bbe0beb9c..541db5696271e1 100755
--- a/src/coreclr/scripts/superpmi.py
+++ b/src/coreclr/scripts/superpmi.py
@@ -2595,7 +2595,7 @@ def process_mch_files_arg(coreclr_args):
# See if the cache directory already exists. If so, we just use it (unless `--force_download` is passed).
if os.path.isdir(mch_cache_dir) and not coreclr_args.force_download:
- # The cache directory is already there, and "--force_download" was passed, so just
+ # The cache directory is already there, and "--force_download" was not passed, so just
# assume it's got what we want.
# NOTE: a different solution might be to verify that everything we would download is
# already in the cache, and simply not download if it is. However, that would
@@ -2608,7 +2608,12 @@ def process_mch_files_arg(coreclr_args):
# Add the private store files
if coreclr_args.private_store is not None:
- local_mch_paths += process_local_mch_files(coreclr_args, coreclr_args.private_store, mch_cache_dir)
+ # Only include the directories corresponding to the current JIT/EE version, target OS, and MCH architecture (this is the
+ # same filtering done for Azure storage). Only include them if they actually exist (e.g., the private store might have
+ # windows x64 but not Linux arm).
+ target_specific_stores = [ os.path.abspath(os.path.join(store, coreclr_args.jit_ee_version, coreclr_args.target_os, coreclr_args.mch_arch)) for store in coreclr_args.private_store ]
+ filtered_stores = [ s for s in target_specific_stores if os.path.isdir(s) ]
+ local_mch_paths += process_local_mch_files(coreclr_args, filtered_stores, mch_cache_dir)
return local_mch_paths
diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
index d99c51d236950c..c138b9500c8822 100644
--- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
+++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
@@ -654,6 +654,7 @@ private bool TryGetUnmanagedCallingConventionFromModOpt(MethodSignature signatur
if (memberFunctionVariant)
{
callConv = GetMemberFunctionCallingConventionVariant(found ? callConv : (CorInfoCallConvExtension)PlatformDefaultUnmanagedCallingConvention());
+ found = true;
}
return found;
@@ -1579,8 +1580,7 @@ private int appendClassName(char** ppBuf, ref int pnBufLen, CORINFO_CLASS_STRUCT
private bool isValueClass(CORINFO_CLASS_STRUCT_* cls)
{
- TypeDesc type = HandleToObject(cls);
- return type.IsValueType || type.IsPointer || type.IsFunctionPointer;
+ return HandleToObject(cls).IsValueType;
}
private CorInfoInlineTypeCheck canInlineTypeCheck(CORINFO_CLASS_STRUCT_* cls, CorInfoInlineTypeCheckSource source)
@@ -1602,10 +1602,6 @@ private uint getClassAttribsInternal(TypeDesc type)
CorInfoFlag result = (CorInfoFlag)0;
- // CoreCLR uses UIntPtr in place of pointers here
- if (type.IsPointer || type.IsFunctionPointer)
- type = _compilation.TypeSystemContext.GetWellKnownType(WellKnownType.UIntPtr);
-
var metadataType = type as MetadataType;
// The array flag is used to identify the faked-up methods on
diff --git a/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaModule.cs b/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaModule.cs
index 737b266b9b6e62..1e923b2d23fe1f 100644
--- a/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaModule.cs
+++ b/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaModule.cs
@@ -595,7 +595,10 @@ private Object ResolveExportedType(ExportedTypeHandle handle)
var module = (ModuleDesc)implementation;
string nameSpace = _metadataReader.GetString(exportedType.Namespace);
string name = _metadataReader.GetString(exportedType.Name);
- return module.GetType(nameSpace, name, NotFoundBehavior.ReturnResolutionFailure);
+ MetadataType resolvedType = module.GetType(nameSpace, name, NotFoundBehavior.ReturnResolutionFailure);
+ if (resolvedType == null)
+ return ModuleDesc.GetTypeResolutionFailure;
+ return resolvedType;
}
else
if (implementation is MetadataType)
diff --git a/src/coreclr/vm/assemblyloadcontext.cpp b/src/coreclr/vm/assemblyloadcontext.cpp
index 1ec1a1eeeb6c85..565292d7fb3d9f 100644
--- a/src/coreclr/vm/assemblyloadcontext.cpp
+++ b/src/coreclr/vm/assemblyloadcontext.cpp
@@ -24,12 +24,17 @@ NativeImage *AssemblyLoadContext::LoadNativeImage(Module *componentModule, LPCUT
AssemblyLoadContext *loadContext = componentModule->GetFile()->GetAssemblyLoadContext();
PTR_LoaderAllocator moduleLoaderAllocator = componentModule->GetLoaderAllocator();
- NativeImage *nativeImage = NativeImage::Open(componentModule, nativeImageName, loadContext, moduleLoaderAllocator);
- m_nativeImages.Append(nativeImage);
+ bool isNewNativeImage;
+ NativeImage *nativeImage = NativeImage::Open(componentModule, nativeImageName, loadContext, moduleLoaderAllocator, &isNewNativeImage);
- for (COUNT_T assemblyIndex = 0; assemblyIndex < m_loadedAssemblies.GetCount(); assemblyIndex++)
+ if (isNewNativeImage && nativeImage != nullptr)
{
- nativeImage->CheckAssemblyMvid(m_loadedAssemblies[assemblyIndex]);
+ m_nativeImages.Append(nativeImage);
+
+ for (COUNT_T assemblyIndex = 0; assemblyIndex < m_loadedAssemblies.GetCount(); assemblyIndex++)
+ {
+ nativeImage->CheckAssemblyMvid(m_loadedAssemblies[assemblyIndex]);
+ }
}
return nativeImage;
diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp
index 2423c4887d61e5..dc8bdb96db7c94 100644
--- a/src/coreclr/vm/jitinterface.cpp
+++ b/src/coreclr/vm/jitinterface.cpp
@@ -3772,11 +3772,7 @@ bool CEEInfo::isValueClass(CORINFO_CLASS_HANDLE clsHnd)
_ASSERTE(clsHnd);
- // Note that clsHnd.IsValueType() would not return what the JIT expects
- // for corner cases like ELEMENT_TYPE_FNPTR
- TypeHandle VMClsHnd(clsHnd);
- MethodTable * pMT = VMClsHnd.GetMethodTable();
- ret = (pMT != NULL) ? pMT->IsValueType() : false;
+ ret = TypeHandle(clsHnd).IsValueType();
EE_TO_JIT_TRANSITION_LEAF();
@@ -3888,7 +3884,7 @@ uint32_t CEEInfo::getClassAttribsInternal (CORINFO_CLASS_HANDLE clsHnd)
if (pMT->HasComponentSize())
ret |= CORINFO_FLG_VAROBJSIZE;
- if (pMT->IsValueType())
+ if (VMClsHnd.IsValueType())
{
ret |= CORINFO_FLG_VALUECLASS;
diff --git a/src/coreclr/vm/nativeimage.cpp b/src/coreclr/vm/nativeimage.cpp
index 9067273ed2ec28..5500da1acc8726 100644
--- a/src/coreclr/vm/nativeimage.cpp
+++ b/src/coreclr/vm/nativeimage.cpp
@@ -114,13 +114,15 @@ NativeImage *NativeImage::Open(
Module *componentModule,
LPCUTF8 nativeImageFileName,
AssemblyLoadContext *pAssemblyLoadContext,
- LoaderAllocator *pLoaderAllocator)
+ LoaderAllocator *pLoaderAllocator,
+ /* out */ bool *isNewNativeImage)
{
STANDARD_VM_CONTRACT;
NativeImage *pExistingImage = AppDomain::GetCurrentDomain()->GetNativeImage(nativeImageFileName);
if (pExistingImage != nullptr)
{
+ *isNewNativeImage = false;
return pExistingImage->GetAssemblyLoadContext() == pAssemblyLoadContext ? pExistingImage : nullptr;
}
@@ -216,10 +218,12 @@ NativeImage *NativeImage::Open(
if (pExistingImage == nullptr)
{
// No pre-existing image, new image has been stored in the map
+ *isNewNativeImage = true;
amTracker.SuppressRelease();
return image.Extract();
}
// Return pre-existing image if it was loaded into the same ALC, null otherwise
+ *isNewNativeImage = false;
return (pExistingImage->GetAssemblyLoadContext() == pAssemblyLoadContext ? pExistingImage : nullptr);
}
#endif
diff --git a/src/coreclr/vm/nativeimage.h b/src/coreclr/vm/nativeimage.h
index 8ce2c43fe7fd11..447e600297ae3e 100644
--- a/src/coreclr/vm/nativeimage.h
+++ b/src/coreclr/vm/nativeimage.h
@@ -105,7 +105,8 @@ class NativeImage
Module *componentModule,
LPCUTF8 nativeImageFileName,
AssemblyLoadContext *pAssemblyLoadContext,
- LoaderAllocator *pLoaderAllocator);
+ LoaderAllocator *pLoaderAllocator,
+ /* out */ bool *isNewNativeImage);
Crst *EagerFixupsLock() { return &m_eagerFixupsLock; }
bool EagerFixupsHaveRun() const { return m_eagerFixupsHaveRun; }
diff --git a/src/coreclr/vm/object.h b/src/coreclr/vm/object.h
index c53ce1e88a1af3..5cad6621e4f4ca 100644
--- a/src/coreclr/vm/object.h
+++ b/src/coreclr/vm/object.h
@@ -739,6 +739,39 @@ class PtrArray : public ArrayBase
#define OFFSETOF__PtrArray__m_Array_ ARRAYBASE_SIZE
+/* Corresponds to the managed Span and ReadOnlySpan types.
+ This should only ever be passed from the managed to the unmanaged world byref,
+ as any copies of this struct made within the unmanaged world will not observe
+ potential GC relocations of the source data. */
+template < class KIND >
+class Span
+{
+private:
+ /* Keep fields below in sync with managed Span / ReadOnlySpan layout. */
+ KIND* _pointer;
+ unsigned int _length;
+
+public:
+ // !! CAUTION !!
+ // Caller must take care not to reassign returned reference if this span corresponds
+ // to a managed ReadOnlySpan. If KIND is a reference type, caller must use a
+ // helper like SetObjectReference instead of assigning values directly to the
+ // reference location.
+ KIND& GetAt(SIZE_T index)
+ {
+ LIMITED_METHOD_CONTRACT;
+ SUPPORTS_DAC;
+ _ASSERTE(index < GetLength());
+ return _pointer[index];
+ }
+
+ // Gets the length (in elements) of this span.
+ __inline SIZE_T GetLength() const
+ {
+ return _length;
+ }
+};
+
/* a TypedByRef is a structure that is used to implement VB's BYREF variants.
it is basically a tuple of an address of some data along with a TypeHandle
that indicates the type of the address */
diff --git a/src/coreclr/vm/reflectioninvocation.cpp b/src/coreclr/vm/reflectioninvocation.cpp
index 3491dcb3489445..8a92ce9d7d9336 100644
--- a/src/coreclr/vm/reflectioninvocation.cpp
+++ b/src/coreclr/vm/reflectioninvocation.cpp
@@ -478,7 +478,7 @@ void CallDescrWorkerReflectionWrapper(CallDescrData * pCallDescrData, Frame * pF
PAL_ENDTRY
} // CallDescrWorkerReflectionWrapper
-OBJECTREF InvokeArrayConstructor(TypeHandle th, MethodDesc* pMeth, PTRARRAYREF* objs, int argCnt)
+OBJECTREF InvokeArrayConstructor(TypeHandle th, MethodDesc* pMeth, Span* objs, int argCnt)
{
CONTRACTL {
THROWS;
@@ -501,16 +501,16 @@ OBJECTREF InvokeArrayConstructor(TypeHandle th, MethodDesc* pMeth, PTRARRAYREF*
for (DWORD i=0; i<(DWORD)argCnt; i++)
{
- if (!(*objs)->m_Array[i])
+ if (!objs->GetAt(i))
COMPlusThrowArgumentException(W("parameters"), W("Arg_NullIndex"));
- MethodTable* pMT = ((*objs)->m_Array[i])->GetMethodTable();
+ MethodTable* pMT = objs->GetAt(i)->GetMethodTable();
CorElementType oType = TypeHandle(pMT).GetVerifierCorElementType();
if (!InvokeUtil::IsPrimitiveType(oType) || !InvokeUtil::CanPrimitiveWiden(ELEMENT_TYPE_I4,oType))
COMPlusThrow(kArgumentException,W("Arg_PrimWiden"));
- memcpy(&indexes[i],(*objs)->m_Array[i]->UnBox(),pMT->GetNumInstanceFieldBytes());
+ memcpy(&indexes[i], objs->GetAt(i)->UnBox(),pMT->GetNumInstanceFieldBytes());
}
return AllocateArrayEx(th, indexes, argCnt);
@@ -749,20 +749,18 @@ void DECLSPEC_NORETURN ThrowInvokeMethodException(MethodDesc * pMethod, OBJECTRE
}
FCIMPL5(Object*, RuntimeMethodHandle::InvokeMethod,
- Object *target, PTRArray *objs, SignatureNative* pSigUNSAFE,
+ Object *target, Span* objs, SignatureNative* pSigUNSAFE,
CLR_BOOL fConstructor, CLR_BOOL fWrapExceptions)
{
FCALL_CONTRACT;
struct {
OBJECTREF target;
- PTRARRAYREF args;
SIGNATURENATIVEREF pSig;
OBJECTREF retVal;
} gc;
gc.target = ObjectToOBJECTREF(target);
- gc.args = (PTRARRAYREF)objs;
gc.pSig = (SIGNATURENATIVEREF)pSigUNSAFE;
gc.retVal = NULL;
@@ -793,7 +791,7 @@ FCIMPL5(Object*, RuntimeMethodHandle::InvokeMethod,
if (ownerType.IsArray()) {
gc.retVal = InvokeArrayConstructor(ownerType,
pMeth,
- &gc.args,
+ objs,
gc.pSig->NumFixedArgs());
goto Done;
}
@@ -1044,7 +1042,7 @@ FCIMPL5(Object*, RuntimeMethodHandle::InvokeMethod,
argDest = ArgDestination(pStackCopy, 0, NULL);
}
- InvokeUtil::CopyArg(th, &(gc.args->m_Array[i]), &argDest);
+ InvokeUtil::CopyArg(th, &objs->GetAt(i), &argDest);
}
ENDFORBIDGC();
@@ -1159,7 +1157,7 @@ FCIMPL5(Object*, RuntimeMethodHandle::InvokeMethod,
while (byRefToNullables != NULL) {
OBJECTREF obj = Nullable::Box(byRefToNullables->data, byRefToNullables->type.GetMethodTable());
- SetObjectReference(&gc.args->m_Array[byRefToNullables->argNum], obj);
+ SetObjectReference(&objs->GetAt(byRefToNullables->argNum), obj);
byRefToNullables = byRefToNullables->next;
}
diff --git a/src/coreclr/vm/runtimehandles.h b/src/coreclr/vm/runtimehandles.h
index 7675d1b3bcac9f..be3b2637e32366 100644
--- a/src/coreclr/vm/runtimehandles.h
+++ b/src/coreclr/vm/runtimehandles.h
@@ -270,7 +270,7 @@ class RuntimeMethodHandle {
public:
static FCDECL1(ReflectMethodObject*, GetCurrentMethod, StackCrawlMark* stackMark);
- static FCDECL5(Object*, InvokeMethod, Object *target, PTRArray *objs, SignatureNative* pSig, CLR_BOOL fConstructor, CLR_BOOL fWrapExceptions);
+ static FCDECL5(Object*, InvokeMethod, Object *target, Span* objs, SignatureNative* pSig, CLR_BOOL fConstructor, CLR_BOOL fWrapExceptions);
struct StreamingContextData {
Object * additionalContext; // additionalContex was changed from OBJECTREF to Object to avoid having a
diff --git a/src/installer/managed/Microsoft.NET.HostModel/ComHost/ComHost.cs b/src/installer/managed/Microsoft.NET.HostModel/ComHost/ComHost.cs
index 2e1d8a949efb6e..3cf9cbf4e1004d 100644
--- a/src/installer/managed/Microsoft.NET.HostModel/ComHost/ComHost.cs
+++ b/src/installer/managed/Microsoft.NET.HostModel/ComHost/ComHost.cs
@@ -2,7 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Collections.Generic;
using System.IO;
+using System.Runtime.InteropServices;
using System.Text;
namespace Microsoft.NET.HostModel.ComHost
@@ -19,10 +21,12 @@ public class ComHost
/// The path of Apphost template, which has the place holder
/// The destination path for desired location to place, including the file name
/// The path to the *.clsidmap file.
+ /// Resource ids for tlbs and paths to the tlb files to be embedded.
public static void Create(
string comHostSourceFilePath,
string comHostDestinationFilePath,
- string clsidmapFilePath)
+ string clsidmapFilePath,
+ IReadOnlyDictionary typeLibraries = null)
{
var destinationDirectory = new FileInfo(comHostDestinationFilePath).Directory.FullName;
if (!Directory.Exists(destinationDirectory))
@@ -44,6 +48,26 @@ public static void Create(
using (ResourceUpdater updater = new ResourceUpdater(comHostDestinationFilePath))
{
updater.AddResource(clsidMapBytes, (IntPtr)ClsidmapResourceType, (IntPtr)ClsidmapResourceId);
+ if (typeLibraries is not null)
+ {
+ foreach (var typeLibrary in typeLibraries)
+ {
+ if (!ResourceUpdater.IsIntResource((IntPtr)typeLibrary.Key))
+ {
+ throw new InvalidTypeLibraryIdException(typeLibrary.Value, typeLibrary.Key);
+ }
+
+ try
+ {
+ byte[] tlbFileBytes = File.ReadAllBytes(typeLibrary.Value);
+ updater.AddResource(tlbFileBytes, "typelib", (IntPtr)typeLibrary.Key);
+ }
+ catch (FileNotFoundException ex)
+ {
+ throw new TypeLibraryDoesNotExistException(typeLibrary.Value, ex);
+ }
+ }
+ }
updater.Update();
}
}
diff --git a/src/installer/managed/Microsoft.NET.HostModel/ComHost/InvalidTypeLibraryIdException.cs b/src/installer/managed/Microsoft.NET.HostModel/ComHost/InvalidTypeLibraryIdException.cs
new file mode 100644
index 00000000000000..4bb1a85d4d42fc
--- /dev/null
+++ b/src/installer/managed/Microsoft.NET.HostModel/ComHost/InvalidTypeLibraryIdException.cs
@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+
+namespace Microsoft.NET.HostModel.ComHost
+{
+ ///
+ /// The provided resource id for the type library is unsupported.
+ ///
+ public class InvalidTypeLibraryIdException : Exception
+ {
+ public InvalidTypeLibraryIdException(string path, int id)
+ {
+ Path = path;
+ Id = id;
+ }
+
+ public string Path { get; }
+
+ public int Id { get; }
+ }
+}
diff --git a/src/installer/managed/Microsoft.NET.HostModel/ComHost/TypeLibraryDoesNotExistException.cs b/src/installer/managed/Microsoft.NET.HostModel/ComHost/TypeLibraryDoesNotExistException.cs
new file mode 100644
index 00000000000000..28d20b547d4dd0
--- /dev/null
+++ b/src/installer/managed/Microsoft.NET.HostModel/ComHost/TypeLibraryDoesNotExistException.cs
@@ -0,0 +1,21 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+
+namespace Microsoft.NET.HostModel.ComHost
+{
+ ///
+ /// The specified type library path does not exist.
+ ///
+ public class TypeLibraryDoesNotExistException : Exception
+ {
+ public TypeLibraryDoesNotExistException(string path, Exception innerException)
+ :base($"Type library '{path}' does not exist.", innerException)
+ {
+ Path = path;
+ }
+
+ public string Path { get; }
+ }
+}
diff --git a/src/installer/managed/Microsoft.NET.HostModel/ResourceUpdater.cs b/src/installer/managed/Microsoft.NET.HostModel/ResourceUpdater.cs
index e18eedf9804d28..bf1c0c489a93aa 100644
--- a/src/installer/managed/Microsoft.NET.HostModel/ResourceUpdater.cs
+++ b/src/installer/managed/Microsoft.NET.HostModel/ResourceUpdater.cs
@@ -44,6 +44,16 @@ public static extern bool UpdateResource(SafeUpdateHandle hUpdate,
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex=5)] byte[] lpData,
uint cbData);
+ // Update a resource with data from a managed byte[]
+ [DllImport(nameof(Kernel32), SetLastError=true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool UpdateResource(SafeUpdateHandle hUpdate,
+ string lpType,
+ IntPtr lpName,
+ ushort wLanguage,
+ [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=5)] byte[] lpData,
+ uint cbData);
+
[DllImport(nameof(Kernel32), SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EndUpdateResource(SafeUpdateHandle hUpdate,
@@ -277,7 +287,7 @@ public ResourceUpdater AddResourcesFromPEImage(string peFile)
return this;
}
- private static bool IsIntResource(IntPtr lpType)
+ internal static bool IsIntResource(IntPtr lpType)
{
return ((uint)lpType >> 16) == 0;
}
@@ -308,6 +318,32 @@ public ResourceUpdater AddResource(byte[] data, IntPtr lpType, IntPtr lpName)
return this;
}
+ ///
+ /// Add a language-neutral integer resource from a byte[] with
+ /// a particular type and name. This will not modify the
+ /// target until Update() is called.
+ /// Throws an InvalidOperationException if Update() was already called.
+ ///
+ public ResourceUpdater AddResource(byte[] data, string lpType, IntPtr lpName)
+ {
+ if (hUpdate.IsInvalid)
+ {
+ ThrowExceptionForInvalidUpdate();
+ }
+
+ if (!IsIntResource(lpName))
+ {
+ throw new ArgumentException("AddResource can only be used with integer resource names");
+ }
+
+ if (!Kernel32.UpdateResource(hUpdate, lpType, lpName, Kernel32.LangID_LangNeutral_SublangNeutral, data, (uint)data.Length))
+ {
+ ThrowExceptionForLastWin32Error();
+ }
+
+ return this;
+ }
+
///
/// Write the pending resource updates to the target PE
/// file. After this, the ResourceUpdater no longer maintains
diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props
index bc114a7ec5c1bb..b2c903cb38dd06 100644
--- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props
+++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props
@@ -18,6 +18,9 @@
-->
+
+
+
diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.sfxproj
index 153612f0e2bad8..6ab3f0743c9452 100644
--- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.sfxproj
+++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.sfxproj
@@ -27,7 +27,7 @@
The .NET Shared Framework
-
+
Mono
diff --git a/src/installer/tests/Assets/TestProjects/ComLibrary/ComLibrary.cs b/src/installer/tests/Assets/TestProjects/ComLibrary/ComLibrary.cs
index d5eb1adadae24a..cf4418acd27448 100644
--- a/src/installer/tests/Assets/TestProjects/ComLibrary/ComLibrary.cs
+++ b/src/installer/tests/Assets/TestProjects/ComLibrary/ComLibrary.cs
@@ -12,10 +12,16 @@ public class UserDefinedAttribute : Attribute
{
}
+ [ComVisible(true)]
+ [Guid("27293cc8-7933-4fdf-9fde-653cbf9b55df")]
+ public interface IServer
+ {
+ }
+
[UserDefined]
[ComVisible(true)]
[Guid("438968CE-5950-4FBC-90B0-E64691350DF5")]
- public class Server
+ public class Server : IServer
{
public Server()
{
@@ -28,6 +34,12 @@ public class NotComVisible
{
}
+ [ComVisible(true)]
+ [Guid("f7199267-9821-4f5b-924b-ab5246b455cd")]
+ public interface INested
+ {
+ }
+
[ComVisible(true)]
[Guid("36e75747-aecd-43bf-9082-1a605889c762")]
public class ComVisible
@@ -35,7 +47,7 @@ public class ComVisible
[UserDefined]
[ComVisible(true)]
[Guid("c82e4585-58bd-46e0-a76d-c0b6975e5984")]
- public class Nested
+ public class Nested : INested
{
}
}
@@ -46,7 +58,7 @@ internal class ComVisibleNonPublic
{
[ComVisible(true)]
[Guid("8a0a7085-aca4-4651-9878-ca42747e2206")]
- public class Nested
+ public class Nested : INested
{
}
}
diff --git a/src/installer/tests/HostActivation.Tests/NativeHosting/Comhost.cs b/src/installer/tests/HostActivation.Tests/NativeHosting/Comhost.cs
index 505b0c00c6c59f..4b693e371f1079 100644
--- a/src/installer/tests/HostActivation.Tests/NativeHosting/Comhost.cs
+++ b/src/installer/tests/HostActivation.Tests/NativeHosting/Comhost.cs
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Collections.Generic;
using System.IO;
using System.Reflection.Metadata;
using System.Runtime.InteropServices;
@@ -119,6 +120,38 @@ public void ActivateClass_ValidateIErrorInfoResult()
}
}
+ [Fact]
+ public void LoadTypeLibraries()
+ {
+ if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ // COM activation is only supported on Windows
+ return;
+ }
+
+ using (var fixture = sharedState.ComLibraryFixture.Copy())
+ {
+ var comHost = Path.Combine(
+ fixture.TestProject.BuiltApp.Location,
+ $"{ fixture.TestProject.AssemblyName }.comhost.dll");
+
+ string[] args = {
+ "comhost",
+ "typelib",
+ "2",
+ comHost,
+ sharedState.ClsidString
+ };
+ CommandResult result = sharedState.CreateNativeHostCommand(args, fixture.BuiltDotnet.BinPath)
+ .Execute();
+
+ result.Should().Pass()
+ .And.HaveStdOutContaining("Loading default type library succeeded.")
+ .And.HaveStdOutContaining("Loading type library 1 succeeded.")
+ .And.HaveStdOutContaining("Loading type library 2 succeeded.");
+ }
+ }
+
public class SharedTestState : SharedTestStateBase
{
public string ComHostPath { get; }
@@ -150,14 +183,23 @@ public SharedTestState()
}
}
- // Use the locally built comhost to create a comhost with the embedded .clsidmap
+ // Use the locally built comhost to create a comhost with the embedded .clsidmap
ComHostPath = Path.Combine(
ComLibraryFixture.TestProject.BuiltApp.Location,
$"{ ComLibraryFixture.TestProject.AssemblyName }.comhost.dll");
+
+ // Include the test type libraries in the ComHost tests.
+ var typeLibraries = new Dictionary
+ {
+ { 1, Path.Combine(RepoDirectories.Artifacts, "corehost_test", "Server.tlb") },
+ { 2, Path.Combine(RepoDirectories.Artifacts, "corehost_test", "Nested.tlb") }
+ };
+
ComHost.Create(
Path.Combine(RepoDirectories.HostArtifacts, "comhost.dll"),
ComHostPath,
- clsidMapPath);
+ clsidMapPath,
+ typeLibraries);
}
protected override void Dispose(bool disposing)
diff --git a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Ssl.ProtocolSupport.cs b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Ssl.ProtocolSupport.cs
new file mode 100644
index 00000000000000..65981eccfb3aba
--- /dev/null
+++ b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Ssl.ProtocolSupport.cs
@@ -0,0 +1,14 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Runtime.InteropServices;
+using System.Security.Authentication;
+
+internal static partial class Interop
+{
+ internal static partial class AndroidCrypto
+ {
+ [DllImport(Interop.Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_SSLGetSupportedProtocols")]
+ internal static extern SslProtocols SSLGetSupportedProtocols();
+ }
+}
diff --git a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Ssl.cs b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Ssl.cs
index 133dc3ec445d13..fcd6cab6fcaf12 100644
--- a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Ssl.cs
+++ b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Ssl.cs
@@ -2,13 +2,144 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Buffers;
using System.Runtime.InteropServices;
+using System.Security.Authentication;
+using System.Security.Cryptography.X509Certificates;
+
using Microsoft.Win32.SafeHandles;
+using SafeSslHandle = System.Net.SafeSslHandle;
+
internal static partial class Interop
{
internal static partial class AndroidCrypto
{
+ internal unsafe delegate PAL_SSLStreamStatus SSLReadCallback(byte* data, int* length);
+ internal unsafe delegate void SSLWriteCallback(byte* data, int length);
+
+ internal enum PAL_SSLStreamStatus
+ {
+ OK = 0,
+ NeedData = 1,
+ Error = 2,
+ Renegotiate = 3,
+ Closed = 4,
+ };
+
+ [DllImport(Interop.Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_SSLStreamCreate")]
+ internal static extern SafeSslHandle SSLStreamCreate();
+
+ [DllImport(Interop.Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_SSLStreamCreateWithCertificates")]
+ private static extern SafeSslHandle SSLStreamCreateWithCertificates(
+ ref byte pkcs8PrivateKey,
+ int pkcs8PrivateKeyLen,
+ PAL_KeyAlgorithm algorithm,
+ IntPtr[] certs,
+ int certsLen);
+ internal static SafeSslHandle SSLStreamCreateWithCertificates(ReadOnlySpan pkcs8PrivateKey, PAL_KeyAlgorithm algorithm, IntPtr[] certificates)
+ {
+ return SSLStreamCreateWithCertificates(
+ ref MemoryMarshal.GetReference(pkcs8PrivateKey),
+ pkcs8PrivateKey.Length,
+ algorithm,
+ certificates,
+ certificates.Length);
+ }
+
+ [DllImport(Interop.Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_SSLStreamInitialize")]
+ private static extern int SSLStreamInitializeImpl(
+ SafeSslHandle sslHandle,
+ [MarshalAs(UnmanagedType.U1)] bool isServer,
+ SSLReadCallback streamRead,
+ SSLWriteCallback streamWrite,
+ int appBufferSize);
+ internal static void SSLStreamInitialize(
+ SafeSslHandle sslHandle,
+ bool isServer,
+ SSLReadCallback streamRead,
+ SSLWriteCallback streamWrite,
+ int appBufferSize)
+ {
+ int ret = SSLStreamInitializeImpl(sslHandle, isServer, streamRead, streamWrite, appBufferSize);
+ if (ret != SUCCESS)
+ throw new SslException();
+ }
+
+ [DllImport(Interop.Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_SSLStreamConfigureParameters")]
+ private static extern int SSLStreamConfigureParametersImpl(
+ SafeSslHandle sslHandle,
+ [MarshalAs(UnmanagedType.LPUTF8Str)] string targetHost);
+ internal static void SSLStreamConfigureParameters(
+ SafeSslHandle sslHandle,
+ string targetHost)
+ {
+ int ret = SSLStreamConfigureParametersImpl(sslHandle, targetHost);
+ if (ret != SUCCESS)
+ throw new SslException();
+ }
+
+ [DllImport(Interop.Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_SSLStreamSetEnabledProtocols")]
+ private static extern int SSLStreamSetEnabledProtocols(SafeSslHandle sslHandle, ref SslProtocols protocols, int length);
+ internal static void SSLStreamSetEnabledProtocols(SafeSslHandle sslHandle, ReadOnlySpan protocols)
+ {
+ int ret = SSLStreamSetEnabledProtocols(sslHandle, ref MemoryMarshal.GetReference(protocols), protocols.Length);
+ if (ret != SUCCESS)
+ throw new SslException();
+ }
+
+ [DllImport(Interop.Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_SSLStreamHandshake")]
+ internal static extern PAL_SSLStreamStatus SSLStreamHandshake(SafeSslHandle sslHandle);
+
+ [DllImport(Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_SSLStreamGetApplicationProtocol")]
+ private static extern int SSLStreamGetApplicationProtocol(SafeSslHandle ssl, [Out] byte[]? buf, ref int len);
+ internal static byte[]? SSLStreamGetApplicationProtocol(SafeSslHandle ssl)
+ {
+ int len = 0;
+ int ret = SSLStreamGetApplicationProtocol(ssl, null, ref len);
+ if (ret != INSUFFICIENT_BUFFER)
+ return null;
+
+ byte[] bytes = new byte[len];
+ ret = SSLStreamGetApplicationProtocol(ssl, bytes, ref len);
+ if (ret != SUCCESS)
+ return null;
+
+ return bytes;
+ }
+
+ [DllImport(Interop.Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_SSLStreamRead")]
+ private static unsafe extern PAL_SSLStreamStatus SSLStreamRead(
+ SafeSslHandle sslHandle,
+ byte* buffer,
+ int length,
+ out int bytesRead);
+ internal static unsafe PAL_SSLStreamStatus SSLStreamRead(
+ SafeSslHandle sslHandle,
+ Span buffer,
+ out int bytesRead)
+ {
+ fixed (byte* bufferPtr = buffer)
+ {
+ return SSLStreamRead(sslHandle, bufferPtr, buffer.Length, out bytesRead);
+ }
+ }
+
+ [DllImport(Interop.Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_SSLStreamWrite")]
+ private static unsafe extern PAL_SSLStreamStatus SSLStreamWrite(
+ SafeSslHandle sslHandle,
+ byte* buffer,
+ int length);
+ internal static unsafe PAL_SSLStreamStatus SSLStreamWrite(
+ SafeSslHandle sslHandle,
+ ReadOnlyMemory buffer)
+ {
+ using (MemoryHandle memHandle = buffer.Pin())
+ {
+ return SSLStreamWrite(sslHandle, (byte*)memHandle.Pointer, buffer.Length);
+ }
+ }
+
[DllImport(Interop.Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_SSLStreamRelease")]
internal static extern void SSLStreamRelease(IntPtr ptr);
@@ -23,6 +154,78 @@ internal SslException(int errorCode)
HResult = errorCode;
}
}
+
+ [DllImport(Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_SSLStreamGetProtocol")]
+ private static extern int SSLStreamGetProtocol(SafeSslHandle ssl, out IntPtr protocol);
+ internal static string SSLStreamGetProtocol(SafeSslHandle ssl)
+ {
+ IntPtr protocolPtr;
+ int ret = SSLStreamGetProtocol(ssl, out protocolPtr);
+ if (ret != SUCCESS)
+ throw new SslException();
+
+ if (protocolPtr == IntPtr.Zero)
+ return string.Empty;
+
+ string protocol = Marshal.PtrToStringUni(protocolPtr)!;
+ Marshal.FreeHGlobal(protocolPtr);
+ return protocol;
+ }
+
+ [DllImport(Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_SSLStreamGetPeerCertificate")]
+ private static extern int SSLStreamGetPeerCertificate(SafeSslHandle ssl, out SafeX509Handle cert);
+ internal static SafeX509Handle SSLStreamGetPeerCertificate(SafeSslHandle ssl)
+ {
+ SafeX509Handle cert;
+ int ret = Interop.AndroidCrypto.SSLStreamGetPeerCertificate(ssl, out cert);
+ if (ret != SUCCESS)
+ throw new SslException();
+
+ return cert;
+ }
+
+ [DllImport(Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_SSLStreamGetPeerCertificates")]
+ private static extern int SSLStreamGetPeerCertificates(
+ SafeSslHandle ssl,
+ [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] out IntPtr[] certs,
+ out int count);
+ internal static IntPtr[] SSLStreamGetPeerCertificates(SafeSslHandle ssl)
+ {
+ IntPtr[] ptrs;
+ int count;
+ int ret = Interop.AndroidCrypto.SSLStreamGetPeerCertificates(ssl, out ptrs, out count);
+ if (ret != SUCCESS)
+ throw new SslException();
+
+ return ptrs;
+ }
+
+ [DllImport(Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_SSLStreamGetCipherSuite")]
+ private static extern int SSLStreamGetCipherSuite(SafeSslHandle ssl, out IntPtr cipherSuite);
+ internal static string SSLStreamGetCipherSuite(SafeSslHandle ssl)
+ {
+ IntPtr cipherSuitePtr;
+ int ret = SSLStreamGetCipherSuite(ssl, out cipherSuitePtr);
+ if (ret != SUCCESS)
+ throw new SslException();
+
+ if (cipherSuitePtr == IntPtr.Zero)
+ return string.Empty;
+
+ string cipherSuite = Marshal.PtrToStringUni(cipherSuitePtr)!;
+ Marshal.FreeHGlobal(cipherSuitePtr);
+ return cipherSuite;
+ }
+
+ [DllImport(Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_SSLStreamShutdown")]
+ [return: MarshalAs(UnmanagedType.U1)]
+ internal static extern bool SSLStreamShutdown(SafeSslHandle ssl);
+
+ [DllImport(Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_SSLStreamVerifyHostname")]
+ [return: MarshalAs(UnmanagedType.U1)]
+ internal static extern bool SSLStreamVerifyHostname(
+ SafeSslHandle ssl,
+ [MarshalAs(UnmanagedType.LPUTF8Str)] string hostname);
}
}
diff --git a/src/libraries/Common/src/Interop/OSX/System.Native/Interop.iOSSupportVersion.cs b/src/libraries/Common/src/Interop/OSX/System.Native/Interop.iOSSupportVersion.cs
new file mode 100644
index 00000000000000..adffe6b4600791
--- /dev/null
+++ b/src/libraries/Common/src/Interop/OSX/System.Native/Interop.iOSSupportVersion.cs
@@ -0,0 +1,14 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal static partial class Interop
+{
+ internal static partial class Sys
+ {
+ [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_iOSSupportVersion")]
+ internal static extern string iOSSupportVersion();
+ }
+}
diff --git a/src/libraries/Common/src/System/SR.cs b/src/libraries/Common/src/System/SR.cs
index 6d116dd9a4fcb4..84da3bc46878a2 100644
--- a/src/libraries/Common/src/System/SR.cs
+++ b/src/libraries/Common/src/System/SR.cs
@@ -23,11 +23,11 @@ private static bool UsingResourceKeys() =>
false;
#endif
- internal static string GetResourceString(string resourceKey, string? defaultString = null)
+ internal static string GetResourceString(string resourceKey)
{
if (UsingResourceKeys())
{
- return defaultString ?? resourceKey;
+ return resourceKey;
}
string? resourceString = null;
@@ -42,14 +42,16 @@ internal static string GetResourceString(string resourceKey, string? defaultStri
}
catch (MissingManifestResourceException) { }
- if (defaultString != null && resourceKey.Equals(resourceString))
- {
- return defaultString;
- }
-
return resourceString!; // only null if missing resources
}
+ internal static string GetResourceString(string resourceKey, string defaultString)
+ {
+ string resourceString = GetResourceString(resourceKey);
+
+ return resourceKey == resourceString || resourceString == null ? defaultString : resourceString;
+ }
+
internal static string Format(string resourceFormat, object? p1)
{
if (UsingResourceKeys())
diff --git a/src/libraries/Common/src/System/Text/ValueStringBuilder.cs b/src/libraries/Common/src/System/Text/ValueStringBuilder.cs
index c4c4ea1ba478da..fbba96711347e1 100644
--- a/src/libraries/Common/src/System/Text/ValueStringBuilder.cs
+++ b/src/libraries/Common/src/System/Text/ValueStringBuilder.cs
@@ -158,7 +158,12 @@ public void Insert(int index, string? s)
int remaining = _pos - index;
_chars.Slice(index, remaining).CopyTo(_chars.Slice(index + count));
- s.AsSpan().CopyTo(_chars.Slice(index));
+#if SYSTEM_PRIVATE_CORELIB
+ s
+#else
+ s.AsSpan()
+#endif
+ .CopyTo(_chars.Slice(index));
_pos += count;
}
@@ -205,7 +210,12 @@ private void AppendSlow(string s)
Grow(s.Length);
}
- s.AsSpan().CopyTo(_chars.Slice(pos));
+#if SYSTEM_PRIVATE_CORELIB
+ s
+#else
+ s.AsSpan()
+#endif
+ .CopyTo(_chars.Slice(pos));
_pos += s.Length;
}
diff --git a/src/libraries/Common/tests/StreamConformanceTests/System/IO/StreamConformanceTests.cs b/src/libraries/Common/tests/StreamConformanceTests/System/IO/StreamConformanceTests.cs
index b6ba47288f47eb..edd51b148cf0ff 100644
--- a/src/libraries/Common/tests/StreamConformanceTests/System/IO/StreamConformanceTests.cs
+++ b/src/libraries/Common/tests/StreamConformanceTests/System/IO/StreamConformanceTests.cs
@@ -18,7 +18,7 @@
namespace System.IO.Tests
{
/// Base class providing tests for any Stream-derived type.
- [PlatformSpecific(~TestPlatforms.Browser)] // lots of operations aren't supported on browser
+ [SkipOnPlatform(TestPlatforms.Browser, "lots of operations aren't supported on browser")]
public abstract class StreamConformanceTests : FileCleanupTestBase
{
/// Gets the name of the byte[] argument to Read/Write methods.
diff --git a/src/libraries/Common/tests/System/Net/Configuration.Certificates.cs b/src/libraries/Common/tests/System/Net/Configuration.Certificates.cs
index 27f81002f5f1cb..d3b0cf224dae30 100644
--- a/src/libraries/Common/tests/System/Net/Configuration.Certificates.cs
+++ b/src/libraries/Common/tests/System/Net/Configuration.Certificates.cs
@@ -37,10 +37,9 @@ static Certificates()
{
try
{
- string contosoPfxSuffix = PlatformSupport.IsRC2Supported ? ".pfx" : ".noRC2.pfx";
- byte[] serverCertificateBytes = File.ReadAllBytes(Path.Combine(TestDataFolder, $"testservereku.contoso.com{contosoPfxSuffix}"));
- byte[] clientCertificateBytes = File.ReadAllBytes(Path.Combine(TestDataFolder, $"testclienteku.contoso.com{contosoPfxSuffix}"));
- byte[] noEKUCertificateBytes = File.ReadAllBytes(Path.Combine(TestDataFolder, $"testnoeku.contoso.com{contosoPfxSuffix}"));
+ byte[] serverCertificateBytes = File.ReadAllBytes(Path.Combine(TestDataFolder, "testservereku.contoso.com.pfx"));
+ byte[] clientCertificateBytes = File.ReadAllBytes(Path.Combine(TestDataFolder, "testclienteku.contoso.com.pfx"));
+ byte[] noEKUCertificateBytes = File.ReadAllBytes(Path.Combine(TestDataFolder, "testnoeku.contoso.com.pfx"));
byte[] selfSignedServerCertificateBytes = File.ReadAllBytes(Path.Combine(TestDataFolder, "testselfsignedservereku.contoso.com.pfx"));
byte[] selfSignedClientCertificateBytes = File.ReadAllBytes(Path.Combine(TestDataFolder, "testselfsignedclienteku.contoso.com.pfx"));
@@ -64,7 +63,7 @@ static Certificates()
}
}
}
-
+
// These Get* methods make a copy of the certificates so that consumers own the lifetime of the
// certificates handed back. Consumers are expected to dispose of their certs when done with them.
diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Proxy.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Proxy.cs
index 208ac1ad2916ca..c4beb328d6ea8d 100644
--- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Proxy.cs
+++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Proxy.cs
@@ -320,21 +320,129 @@ public async Task Proxy_SslProxyUnsupported_Throws()
}
}
- [OuterLoop("Uses external server")]
[Fact]
- public async Task Proxy_SendSecureRequestThruProxy_ConnectTunnelUsed()
+ public async Task ProxyTunnelRequest_GetAsync_Success()
{
+ if (IsWinHttpHandler)
+ {
+ return;
+ }
+
+ const string Content = "Hello world";
+
using (LoopbackProxyServer proxyServer = LoopbackProxyServer.Create())
{
HttpClientHandler handler = CreateHttpClientHandler();
handler.Proxy = new WebProxy(proxyServer.Uri);
+ handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates;
using (HttpClient client = CreateHttpClient(handler))
- using (HttpResponseMessage response = await client.GetAsync(Configuration.Http.SecureRemoteEchoServer))
{
- Assert.Equal(HttpStatusCode.OK, response.StatusCode);
- _output.WriteLine($"Proxy request line: {proxyServer.Requests[0].RequestLine}");
- Assert.Contains("CONNECT", proxyServer.Requests[0].RequestLine);
+ var options = new LoopbackServer.Options { UseSsl = true };
+ await LoopbackServer.CreateServerAsync(async (server, uri) =>
+ {
+ Assert.Equal(proxyServer.Uri, handler.Proxy.GetProxy(uri));
+
+ Task clientTask = client.GetAsync(uri);
+ await server.AcceptConnectionSendResponseAndCloseAsync(content: Content);
+ using (var response = await clientTask)
+ {
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ Assert.Equal(Content, await response.Content.ReadAsStringAsync());
+ }
+ }, options);
+ }
+
+ Assert.Contains("CONNECT", proxyServer.Requests[0].RequestLine);
+ }
+ }
+
+ [Fact]
+ public async Task ProxyTunnelRequest_MaxConnectionsSetButDoesNotApplyToProxyConnect_Success()
+ {
+ if (IsWinHttpHandler)
+ {
+ return;
+ }
+
+ const string Content = "Hello world";
+
+ using (LoopbackProxyServer proxyServer = LoopbackProxyServer.Create())
+ {
+ HttpClientHandler handler = CreateHttpClientHandler();
+ handler.Proxy = new WebProxy(proxyServer.Uri);
+ handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates;
+ handler.MaxConnectionsPerServer = 1;
+ using (HttpClient client = CreateHttpClient(handler))
+ {
+ var options = new LoopbackServer.Options { UseSsl = true };
+ await LoopbackServer.CreateServerAsync(async (server1, uri1) =>
+ {
+ await LoopbackServer.CreateServerAsync(async (server2, uri2) =>
+ {
+ Assert.Equal(proxyServer.Uri, handler.Proxy.GetProxy(uri1));
+ Assert.Equal(proxyServer.Uri, handler.Proxy.GetProxy(uri2));
+
+ Task clientTask1 = client.GetAsync(uri1);
+ Task clientTask2 = client.GetAsync(uri2);
+ await server1.AcceptConnectionAsync(async connection1 =>
+ {
+ await server2.AcceptConnectionAsync(async connection2 =>
+ {
+ await connection1.HandleRequestAsync(content: Content);
+ await connection2.HandleRequestAsync(content: Content);
+ });
+ });
+
+ using (var response1 = await clientTask1)
+ {
+ Assert.Equal(HttpStatusCode.OK, response1.StatusCode);
+ Assert.Equal(Content, await response1.Content.ReadAsStringAsync());
+ }
+
+ using (var response2 = await clientTask2)
+ {
+ Assert.Equal(HttpStatusCode.OK, response2.StatusCode);
+ Assert.Equal(Content, await response2.Content.ReadAsStringAsync());
+ }
+ }, options);
+ }, options);
+ }
+
+ Assert.Contains("CONNECT", proxyServer.Requests[0].RequestLine);
+ Assert.Contains("CONNECT", proxyServer.Requests[1].RequestLine);
+ }
+ }
+
+ [Fact]
+ public async Task ProxyTunnelRequest_OriginServerSendsProxyAuthChallenge_NoProxyAuthPerformed()
+ {
+ if (IsWinHttpHandler)
+ {
+ return;
+ }
+
+ using (LoopbackProxyServer proxyServer = LoopbackProxyServer.Create())
+ {
+ HttpClientHandler handler = CreateHttpClientHandler();
+ handler.Proxy = new WebProxy(proxyServer.Uri) { Credentials = ConstructCredentials(new NetworkCredential("username", "password"), proxyServer.Uri, BasicAuth, true) };
+ handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates;
+ using (HttpClient client = CreateHttpClient(handler))
+ {
+ var options = new LoopbackServer.Options { UseSsl = true };
+ await LoopbackServer.CreateServerAsync(async (server, uri) =>
+ {
+ Assert.Equal(proxyServer.Uri, handler.Proxy.GetProxy(uri));
+
+ Task clientTask = client.GetAsync(uri);
+ await server.AcceptConnectionSendResponseAndCloseAsync(statusCode: HttpStatusCode.ProxyAuthenticationRequired, additionalHeaders: "Proxy-Authenticate: Basic");
+ using (var response = await clientTask)
+ {
+ Assert.Equal(HttpStatusCode.ProxyAuthenticationRequired, response.StatusCode);
+ }
+ }, options);
}
+
+ Assert.Contains("CONNECT", proxyServer.Requests[0].RequestLine);
}
}
@@ -373,7 +481,6 @@ await LoopbackServer.CreateServerAsync(async (proxyServer, proxyUrl) =>
Assert.Equal(HttpStatusCode.OK, clientTask.Result.StatusCode);
}
}, options);
-
}
[Fact]
diff --git a/src/libraries/Common/tests/System/Net/Http/LoopbackProxyServer.cs b/src/libraries/Common/tests/System/Net/Http/LoopbackProxyServer.cs
index 2429e0302d9ff9..0f4999b703497d 100644
--- a/src/libraries/Common/tests/System/Net/Http/LoopbackProxyServer.cs
+++ b/src/libraries/Common/tests/System/Net/Http/LoopbackProxyServer.cs
@@ -143,7 +143,12 @@ private async Task ProcessRequest(Socket clientSocket, StreamReader reader
}
var request = new ReceivedRequest();
- _requests.Add(request);
+
+ // Avoid concurrent writes to the request list
+ lock (_requests)
+ {
+ _requests.Add(request);
+ }
request.RequestLine = line;
string[] requestTokens = request.RequestLine.Split(' ');
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCipherTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCipherTests.cs
index d3fbeb7628d015..e1f5da5f40f9ef 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCipherTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCipherTests.cs
@@ -11,7 +11,7 @@ namespace System.Security.Cryptography.Encryption.Aes.Tests
{
using Aes = System.Security.Cryptography.Aes;
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public partial class AesCipherTests
{
[Fact]
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesContractTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesContractTests.cs
index 8c0c79da25cc28..89e3ebbe61f3a8 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesContractTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesContractTests.cs
@@ -7,7 +7,7 @@ namespace System.Security.Cryptography.Encryption.Aes.Tests
{
using Aes = System.Security.Cryptography.Aes;
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public class AesContractTests
{
[Fact]
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCornerTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCornerTests.cs
index f98b8a9ce688df..9716824ba2bbc9 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCornerTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCornerTests.cs
@@ -12,7 +12,7 @@ namespace System.Security.Cryptography.Encryption.Aes.Tests
{
using Aes = System.Security.Cryptography.Aes;
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static class AesCornerTests
{
[Fact]
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesModeTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesModeTests.cs
index 6be8a5f9ef57fc..1a496a505c6660 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesModeTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesModeTests.cs
@@ -7,7 +7,7 @@ namespace System.Security.Cryptography.Encryption.Aes.Tests
{
using Aes = System.Security.Cryptography.Aes;
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public class AesModeTests
{
[Fact]
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/DecryptorReusability.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/DecryptorReusability.cs
index 76d1bc5359bb57..99e03904aef915 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/DecryptorReusability.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/DecryptorReusability.cs
@@ -7,7 +7,7 @@ namespace System.Security.Cryptography.Encryption.Aes.Tests
{
using Aes = System.Security.Cryptography.Aes;
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static class DecryptorReusabilty
{
// See https://github.com/dotnet/runtime/issues/21354 for details
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DES/DESCipherTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DES/DESCipherTests.cs
index 82b076821f4691..d007a41167e180 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DES/DESCipherTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DES/DESCipherTests.cs
@@ -9,7 +9,7 @@
namespace System.Security.Cryptography.Encryption.Des.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static class DesCipherTests
{
// These are the expected output of many decryptions. Changing these values requires re-generating test input.
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DES/DESContractTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DES/DESContractTests.cs
index 34eed4dad5850d..145351ac24a2dd 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DES/DESContractTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DES/DESContractTests.cs
@@ -9,7 +9,7 @@
namespace System.Security.Cryptography.Encryption.Des.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static class DesContractTests
{
// cfb not available on windows 7
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DES/DesTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DES/DesTests.cs
index b906485fc4d723..71f41c685a8117 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DES/DesTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DES/DesTests.cs
@@ -7,7 +7,7 @@
namespace System.Security.Cryptography.Encryption.Des.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static partial class DesTests
{
private static readonly byte[] KnownWeakKey = "e0e0e0e0f1f1f1f1".HexToByteArray();
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAImportExport.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAImportExport.cs
index fc75cc836957d4..6962ab68e6cecd 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAImportExport.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAImportExport.cs
@@ -5,7 +5,7 @@
namespace System.Security.Cryptography.Dsa.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public partial class DSAImportExport
{
public static bool SupportsFips186_3 => DSAFactory.SupportsFips186_3;
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyFileTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyFileTests.cs
index 885c9a075261fd..90a5d0b1c70915 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyFileTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyFileTests.cs
@@ -8,7 +8,7 @@
namespace System.Security.Cryptography.Dsa.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static class DSAKeyFileTests
{
public static bool SupportsFips186_3 => DSAFactory.SupportsFips186_3;
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyGeneration.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyGeneration.cs
index 3c2b5974684f59..3d1d3ea6d476ca 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyGeneration.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyGeneration.cs
@@ -5,7 +5,7 @@
namespace System.Security.Cryptography.Dsa.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public partial class DSAKeyGeneration
{
public static bool SupportsKeyGeneration => DSAFactory.SupportsKeyGeneration;
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyPemTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyPemTests.cs
index 199135a4b58f33..b862e26a122fd5 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyPemTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyPemTests.cs
@@ -7,7 +7,7 @@
namespace System.Security.Cryptography.Dsa.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static class DSAKeyPemTests
{
private const string AmbiguousExceptionMarker = "multiple keys";
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignVerify.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignVerify.cs
index b1a8c9e48fa26a..0354fa28f2d100 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignVerify.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignVerify.cs
@@ -7,7 +7,7 @@
namespace System.Security.Cryptography.Dsa.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public sealed class DSASignVerify_Array : DSASignVerify
{
public override byte[] SignData(DSA dsa, byte[] data, HashAlgorithmName hashAlgorithm) =>
@@ -54,7 +54,7 @@ public void InvalidStreamArrayArguments_Throws()
}
}
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public sealed class DSASignVerify_Stream : DSASignVerify
{
public override byte[] SignData(DSA dsa, byte[] data, HashAlgorithmName hashAlgorithm) =>
@@ -76,7 +76,7 @@ public void InvalidArrayArguments_Throws()
}
#if NETCOREAPP
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public sealed class DSASignVerify_Span : DSASignVerify
{
public override byte[] SignData(DSA dsa, byte[] data, HashAlgorithmName hashAlgorithm) =>
@@ -109,7 +109,7 @@ private static byte[] TryWithOutputArray(Func func)
}
}
#endif
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public abstract partial class DSASignVerify
{
public abstract byte[] SignData(DSA dsa, byte[] data, HashAlgorithmName hashAlgorithm);
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignatureFormatTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignatureFormatTests.cs
index 6b9eab6279f105..764254cd31c9ec 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignatureFormatTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignatureFormatTests.cs
@@ -8,7 +8,7 @@
namespace System.Security.Cryptography.Dsa.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public abstract class DSASignatureFormatTests : DsaFamilySignatureFormatTests
{
protected override bool SupportsSha2 => DSAFactory.SupportsFips186_3;
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignatureFormatter.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignatureFormatter.cs
index 22c3a02648a576..3aea7c0bcf2db3 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignatureFormatter.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSASignatureFormatter.cs
@@ -6,7 +6,7 @@
namespace System.Security.Cryptography.Dsa.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public partial class DSASignatureFormatterTests : AsymmetricSignatureFormatterTests
{
[Fact]
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAXml.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAXml.cs
index 1a742d38f6069c..6f19dd555adcbe 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAXml.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAXml.cs
@@ -7,7 +7,7 @@
namespace System.Security.Cryptography.Dsa.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static class DSAXml
{
[Fact]
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DsaFamilySignatureFormatTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DsaFamilySignatureFormatTests.cs
index d55b5a794bebdc..fde2f717f0be3f 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DsaFamilySignatureFormatTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DsaFamilySignatureFormatTests.cs
@@ -8,7 +8,7 @@
namespace System.Security.Cryptography.Algorithms.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public abstract class DsaFamilySignatureFormatTests
{
protected readonly struct KeyDescription
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyFileTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyFileTests.cs
index 66b80c93380e9b..407ad99a41e3d1 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyFileTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyFileTests.cs
@@ -8,7 +8,7 @@
namespace System.Security.Cryptography.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public abstract partial class ECKeyFileTests where T : AsymmetricAlgorithm
{
protected abstract T CreateKey();
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs
index 1593a5df2f4b09..be7670c006da64 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs
@@ -7,7 +7,7 @@
namespace System.Security.Cryptography.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public abstract class ECKeyPemTests where TAlg : AsymmetricAlgorithm
{
private const string AmbiguousExceptionMarker = "multiple keys";
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDhKeyFileTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDhKeyFileTests.cs
index 6fb60fb9596122..2b814f581f90d5 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDhKeyFileTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDhKeyFileTests.cs
@@ -6,7 +6,7 @@
namespace System.Security.Cryptography.EcDiffieHellman.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public class ECDhKeyFileTests : ECKeyFileTests
{
protected override ECDiffieHellman CreateKey()
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanKeyPemTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanKeyPemTests.cs
index 78bc9a300a4e8c..a03cdb0c766d0e 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanKeyPemTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanKeyPemTests.cs
@@ -6,7 +6,7 @@
namespace System.Security.Cryptography.EcDsa.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public sealed class ECDiffieHellmanKeyPemTests : ECKeyPemTests
{
protected override ECDiffieHellman CreateKey() => ECDiffieHellman.Create();
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.ImportExport.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.ImportExport.cs
index 4992fc7ef86cd6..7ee472cf247f2e 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.ImportExport.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.ImportExport.cs
@@ -154,7 +154,7 @@ public static void TestKeySizeCreateKey()
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Android)] // Android does not validate curve parameters
+ [SkipOnPlatform(TestPlatforms.Android, "Android does not validate curve parameters")]
public static void TestExplicitImportValidationNegative()
{
if (!ECDiffieHellmanFactory.ExplicitCurvesSupported)
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.cs
index 920b5b25a3a304..412b48e47502aa 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanTests.cs
@@ -9,7 +9,7 @@
namespace System.Security.Cryptography.EcDiffieHellman.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public partial class ECDiffieHellmanTests : EccTestBase
{
private static List s_everyKeysize;
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaImportExport.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaImportExport.cs
index 777b217be37b10..adb9732c1477a0 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaImportExport.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaImportExport.cs
@@ -7,7 +7,7 @@
namespace System.Security.Cryptography.EcDsa.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public class ECDsaImportExportTests : ECDsaTestsBase
{
internal static bool CanDeriveNewPublicKey { get; }
@@ -188,7 +188,7 @@ public static void TestKeySizeCreateKey()
}
[ConditionalFact(nameof(ECExplicitCurvesSupported))]
- [PlatformSpecific(~TestPlatforms.Android)] // Android does not validate curve parameters
+ [SkipOnPlatform(TestPlatforms.Android, "Android does not validate curve parameters")]
public static void TestExplicitImportValidationNegative()
{
unchecked
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaKeyFileTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaKeyFileTests.cs
index 61419f5f658102..46f88abb735a0d 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaKeyFileTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaKeyFileTests.cs
@@ -6,7 +6,7 @@
namespace System.Security.Cryptography.EcDsa.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public class ECDsaKeyFileTests : ECKeyFileTests
{
protected override ECDsa CreateKey()
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaKeyPemTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaKeyPemTests.cs
index a4e4e25763f077..b969afa0fe4550 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaKeyPemTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaKeyPemTests.cs
@@ -6,7 +6,7 @@
namespace System.Security.Cryptography.EcDsa.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public sealed class ECDsaKeyPemTests : ECKeyPemTests
{
protected override ECDsa CreateKey() => ECDsa.Create();
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaSignatureFormatTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaSignatureFormatTests.cs
index 9d55ebc1bbe06a..c783d71be18812 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaSignatureFormatTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaSignatureFormatTests.cs
@@ -9,7 +9,7 @@
namespace System.Security.Cryptography.EcDsa.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public abstract class ECDsaSignatureFormatTests : DsaFamilySignatureFormatTests
{
protected override bool SupportsSha2 => true;
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.cs
index 530027e87466b6..d747aec14e5517 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.cs
@@ -11,7 +11,7 @@
namespace System.Security.Cryptography.EcDsa.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public sealed class ECDsaTests_Array : ECDsaTests
{
protected override bool VerifyData(ECDsa ecdsa, byte[] data, int offset, int count, byte[] signature, HashAlgorithmName hashAlgorithm) =>
@@ -87,7 +87,7 @@ public void VerifyHash_InvalidArguments_Throws(ECDsa ecdsa)
}
}
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public sealed class ECDsaTests_Stream : ECDsaTests
{
protected override bool VerifyData(ECDsa ecdsa, byte[] data, int offset, int count, byte[] signature, HashAlgorithmName hashAlgorithm)
@@ -125,7 +125,7 @@ public void VerifyData_InvalidArguments_Throws(ECDsa ecdsa)
}
}
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public abstract partial class ECDsaTests : ECDsaTestsBase
{
protected bool VerifyData(ECDsa ecdsa, byte[] data, byte[] signature, HashAlgorithmName hashAlgorithm) =>
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.netcoreapp.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.netcoreapp.cs
index 391bfaec06ad62..ab36bacd98d4eb 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.netcoreapp.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTests.netcoreapp.cs
@@ -6,7 +6,7 @@
namespace System.Security.Cryptography.EcDsa.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public sealed class ECDsaTests_Span : ECDsaTests
{
protected override bool VerifyData(ECDsa ecdsa, byte[] data, int offset, int count, byte[] signature, HashAlgorithmName hashAlgorithm) =>
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTestsBase.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTestsBase.cs
index af03c8cecb7fcd..9da985adfd21fb 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTestsBase.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaTestsBase.cs
@@ -12,7 +12,7 @@ namespace System.Security.Cryptography.EcDsa.Tests
///
/// Input and helper methods for ECDsa
///
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public abstract class ECDsaTestsBase : EccTestBase
{
#if NETCOREAPP
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaXml.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaXml.cs
index dc8ab6a14d4fe4..6ac3ed634e5683 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaXml.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaXml.cs
@@ -5,7 +5,7 @@
namespace System.Security.Cryptography.EcDsa.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public partial class ECDsaXml : ECDsaTestsBase
{
[Fact]
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RC2/RC2CipherTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RC2/RC2CipherTests.cs
index 35fa8c9ecae6ad..7823cc8b1c58c9 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RC2/RC2CipherTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RC2/RC2CipherTests.cs
@@ -10,7 +10,7 @@ namespace System.Security.Cryptography.Encryption.RC2.Tests
{
using RC2 = System.Security.Cryptography.RC2;
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
[ConditionalClass(typeof(RC2Factory), nameof(RC2Factory.IsSupported))]
public static class RC2CipherTests
{
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RC2/RC2ContractTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RC2/RC2ContractTests.cs
index 85000abda615e9..91460058bd21bb 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RC2/RC2ContractTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RC2/RC2ContractTests.cs
@@ -11,7 +11,7 @@ namespace System.Security.Cryptography.Encryption.RC2.Tests
{
using RC2 = System.Security.Cryptography.RC2;
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static class RC2ContractTests
{
[Theory]
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RC2/RC2Tests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RC2/RC2Tests.cs
index 98573f6a822394..b66501a2088614 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RC2/RC2Tests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RC2/RC2Tests.cs
@@ -7,7 +7,7 @@ namespace System.Security.Cryptography.Encryption.RC2.Tests
{
using RC2 = System.Security.Cryptography.RC2;
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static partial class RC2Tests
{
[Fact]
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.cs
index 5cb0d6408f2e5d..96d9b51372847f 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.cs
@@ -24,7 +24,7 @@ public void NullArray_Throws()
}
}
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public abstract class EncryptDecrypt
{
public static bool SupportsSha2Oaep => RSAFactory.SupportsSha2Oaep;
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.netcoreapp.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.netcoreapp.cs
index cf5a46e9d8dec0..d4055512834477 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.netcoreapp.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.netcoreapp.cs
@@ -6,7 +6,7 @@
namespace System.Security.Cryptography.Rsa.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public sealed class EncryptDecrypt_Span : EncryptDecrypt
{
protected override byte[] Encrypt(RSA rsa, byte[] data, RSAEncryptionPadding padding) =>
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/ImportExport.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/ImportExport.cs
index 7f2b093d302f16..ee608a62a30750 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/ImportExport.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/ImportExport.cs
@@ -7,7 +7,7 @@
namespace System.Security.Cryptography.Rsa.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public partial class ImportExport
{
public static bool Supports16384 { get; } = TestRsa16384();
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/KeyGeneration.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/KeyGeneration.cs
index bc559c392a134e..ea13e350b977f9 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/KeyGeneration.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/KeyGeneration.cs
@@ -5,7 +5,7 @@
namespace System.Security.Cryptography.Rsa.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public class KeyGeneration
{
[Fact]
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyExchangeFormatter.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyExchangeFormatter.cs
index 0f95d2621b54e1..3e9071c25c8bea 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyExchangeFormatter.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyExchangeFormatter.cs
@@ -7,7 +7,7 @@
namespace System.Security.Cryptography.Rsa.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public partial class RSAKeyExchangeFormatterTests
{
[Fact]
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyFileTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyFileTests.cs
index 92d5b21e10433e..f3f9b1b85e8c04 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyFileTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyFileTests.cs
@@ -8,7 +8,7 @@
namespace System.Security.Cryptography.Rsa.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static class RSAKeyFileTests
{
public static bool Supports384BitPrivateKeyAndRC2 { get; } = RSAFactory.Supports384PrivateKey && RC2Factory.IsSupported;
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyPemTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyPemTests.cs
index c76ab44a8d3226..806e996cf3a7c1 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyPemTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyPemTests.cs
@@ -7,7 +7,7 @@
namespace System.Security.Cryptography.Rsa.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static class RSAKeyPemTests
{
private const string AmbiguousExceptionMarker = "multiple keys";
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSASignatureFormatter.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSASignatureFormatter.cs
index d93f794ef1e47d..d58ac86a4cbebe 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSASignatureFormatter.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSASignatureFormatter.cs
@@ -7,7 +7,7 @@
namespace System.Security.Cryptography.Rsa.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public partial class RSASignatureFormatterTests : AsymmetricSignatureFormatterTests
{
[Fact]
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAXml.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAXml.cs
index a0ef210d47e80b..0427e190772b54 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAXml.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAXml.cs
@@ -7,7 +7,7 @@
namespace System.Security.Cryptography.Rsa.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static class RSAXml
{
[Fact]
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/SignVerify.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/SignVerify.cs
index afeddd9be65de6..4a7dace2695205 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/SignVerify.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/SignVerify.cs
@@ -9,7 +9,7 @@
namespace System.Security.Cryptography.Rsa.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public sealed class SignVerify_Array : SignVerify
{
protected override byte[] SignData(RSA rsa, byte[] data, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) =>
@@ -38,7 +38,7 @@ public void NullArray_Throws()
}
}
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public abstract class SignVerify
{
public static bool SupportsPss => RSAFactory.SupportsPss;
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/TripleDES/TripleDESCipherTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/TripleDES/TripleDESCipherTests.cs
index e46e8a2514f03b..ce92a62f029b4f 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/TripleDES/TripleDESCipherTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/TripleDES/TripleDESCipherTests.cs
@@ -8,7 +8,7 @@
namespace System.Security.Cryptography.Encryption.TripleDes.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static class TripleDESCipherTests
{
[Fact]
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/TripleDES/TripleDESContractTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/TripleDES/TripleDESContractTests.cs
index 43c6de567bcb16..e12aa7196c8473 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/TripleDES/TripleDESContractTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/TripleDES/TripleDESContractTests.cs
@@ -7,7 +7,7 @@
namespace System.Security.Cryptography.Encryption.TripleDes.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static class TripleDESContractTests
{
diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/TripleDES/TripleDESReusabilityTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/TripleDES/TripleDESReusabilityTests.cs
index cb14fb90859853..4360b70332218d 100644
--- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/TripleDES/TripleDESReusabilityTests.cs
+++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/TripleDES/TripleDESReusabilityTests.cs
@@ -6,7 +6,7 @@
namespace System.Security.Cryptography.Encryption.TripleDes.Tests
{
- [SkipOnMono("Not supported on Browser", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")]
public static class TripleDESReusabilityTests
{
[Fact]
diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs
index c9603889017322..73dff40f517dce 100644
--- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs
+++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs
@@ -52,7 +52,7 @@ public static partial class PlatformDetection
public static bool IsSuperUser => IsBrowser || IsWindows ? false : libc.geteuid() == 0;
- public static Version OpenSslVersion => !IsOSXLike && !IsWindows ?
+ public static Version OpenSslVersion => !IsOSXLike && !IsWindows && !IsAndroid ?
GetOpenSslVersion() :
throw new PlatformNotSupportedException();
diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs
index 75879136f3291a..57b2df23622ce2 100644
--- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs
+++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs
@@ -85,7 +85,7 @@ public static bool IsDrawingSupported
}
}
-
+
public static bool IsLineNumbersSupported => true;
public static bool IsInContainer => GetIsInContainer();
@@ -293,6 +293,13 @@ private static bool OpenSslGetTlsSupport(SslProtocols protocol)
return ret == 1;
}
+ private static readonly Lazy s_androidSupportedSslProtocols = new Lazy(Interop.AndroidCrypto.SSLGetSupportedProtocols);
+ private static bool AndroidGetSslProtocolSupport(SslProtocols protocol)
+ {
+ Debug.Assert(IsAndroid);
+ return (protocol & s_androidSupportedSslProtocols.Value) == protocol;
+ }
+
private static bool GetTls10Support()
{
// on Windows, macOS, and Android TLS1.0/1.1 are supported.
@@ -359,6 +366,14 @@ private static bool GetTls13Support()
// [ActiveIssue("https://github.com/dotnet/runtime/issues/1979")]
return false;
}
+ else if (IsAndroid)
+ {
+#if NETFRAMEWORK
+ return false;
+#else
+ return AndroidGetSslProtocolSupport(SslProtocols.Tls13);
+#endif
+ }
else if (IsOpenSslSupported)
{
// Covers Linux, FreeBSD, illumos and Solaris
diff --git a/src/libraries/Common/tests/TestUtilities/TestUtilities.csproj b/src/libraries/Common/tests/TestUtilities/TestUtilities.csproj
index 3e6464239d718c..f0b1b772e27771 100644
--- a/src/libraries/Common/tests/TestUtilities/TestUtilities.csproj
+++ b/src/libraries/Common/tests/TestUtilities/TestUtilities.csproj
@@ -28,7 +28,7 @@
-
@@ -66,6 +66,11 @@
+
+
+
+
diff --git a/src/libraries/Common/tests/Tests/System/Security/IdentityHelperTests.cs b/src/libraries/Common/tests/Tests/System/Security/IdentityHelperTests.cs
index 1847a2e17ca5e3..a482693370dba3 100644
--- a/src/libraries/Common/tests/Tests/System/Security/IdentityHelperTests.cs
+++ b/src/libraries/Common/tests/Tests/System/Security/IdentityHelperTests.cs
@@ -28,7 +28,7 @@ public void ToBase32StringSuitableForDirName(byte[] buff, string expected)
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public void GetNormalizedStrongNameHash()
{
// Validating that we match the exact hash the .NET Framework IsolatedStorage implementation would create.
@@ -36,7 +36,7 @@ public void GetNormalizedStrongNameHash()
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public void GetNormalizedUrlHash()
{
// Validating that we match the exact hash the .NET Framework IsolatedStorage implementation would create.
diff --git a/src/libraries/Microsoft.CSharp/ref/Microsoft.CSharp.cs b/src/libraries/Microsoft.CSharp/ref/Microsoft.CSharp.cs
index 720a654cdd5574..38ddafe717632e 100644
--- a/src/libraries/Microsoft.CSharp/ref/Microsoft.CSharp.cs
+++ b/src/libraries/Microsoft.CSharp/ref/Microsoft.CSharp.cs
@@ -9,16 +9,27 @@ namespace Microsoft.CSharp.RuntimeBinder
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
public static partial class Binder
{
+ [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Using dynamic types might cause types or members to be removed by trimmer.")]
public static System.Runtime.CompilerServices.CallSiteBinder BinaryOperation(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags flags, System.Linq.Expressions.ExpressionType operation, System.Type? context, System.Collections.Generic.IEnumerable? argumentInfo) { throw null; }
+ [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Using dynamic types might cause types or members to be removed by trimmer.")]
public static System.Runtime.CompilerServices.CallSiteBinder Convert(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags flags, System.Type type, System.Type? context) { throw null; }
+ [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Using dynamic types might cause types or members to be removed by trimmer.")]
public static System.Runtime.CompilerServices.CallSiteBinder GetIndex(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags flags, System.Type? context, System.Collections.Generic.IEnumerable? argumentInfo) { throw null; }
+ [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Using dynamic types might cause types or members to be removed by trimmer.")]
public static System.Runtime.CompilerServices.CallSiteBinder GetMember(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags flags, string name, System.Type? context, System.Collections.Generic.IEnumerable? argumentInfo) { throw null; }
+ [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Using dynamic types might cause types or members to be removed by trimmer.")]
public static System.Runtime.CompilerServices.CallSiteBinder Invoke(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags flags, System.Type? context, System.Collections.Generic.IEnumerable? argumentInfo) { throw null; }
+ [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Using dynamic types might cause types or members to be removed by trimmer.")]
public static System.Runtime.CompilerServices.CallSiteBinder InvokeConstructor(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags flags, System.Type? context, System.Collections.Generic.IEnumerable? argumentInfo) { throw null; }
+ [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Using dynamic types might cause types or members to be removed by trimmer.")]
public static System.Runtime.CompilerServices.CallSiteBinder InvokeMember(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags flags, string name, System.Collections.Generic.IEnumerable? typeArguments, System.Type? context, System.Collections.Generic.IEnumerable? argumentInfo) { throw null; }
+ [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Using dynamic types might cause types or members to be removed by trimmer.")]
public static System.Runtime.CompilerServices.CallSiteBinder IsEvent(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags flags, string name, System.Type? context) { throw null; }
+ [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Using dynamic types might cause types or members to be removed by trimmer.")]
public static System.Runtime.CompilerServices.CallSiteBinder SetIndex(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags flags, System.Type? context, System.Collections.Generic.IEnumerable? argumentInfo) { throw null; }
+ [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Using dynamic types might cause types or members to be removed by trimmer.")]
public static System.Runtime.CompilerServices.CallSiteBinder SetMember(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags flags, string name, System.Type? context, System.Collections.Generic.IEnumerable? argumentInfo) { throw null; }
+ [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Using dynamic types might cause types or members to be removed by trimmer.")]
public static System.Runtime.CompilerServices.CallSiteBinder UnaryOperation(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags flags, System.Linq.Expressions.ExpressionType operation, System.Type? context, System.Collections.Generic.IEnumerable? argumentInfo) { throw null; }
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
diff --git a/src/libraries/Microsoft.CSharp/src/ILLink/ILLink.Suppressions.xml b/src/libraries/Microsoft.CSharp/src/ILLink/ILLink.Suppressions.xml
deleted file mode 100644
index 5c72e2df533ef7..00000000000000
--- a/src/libraries/Microsoft.CSharp/src/ILLink/ILLink.Suppressions.xml
+++ /dev/null
@@ -1,167 +0,0 @@
-
-
-
-
- ILLink
- IL2026
- member
- M:Microsoft.CSharp.RuntimeBinder.DynamicMetaObjectProviderDebugView.#cctor
-
-
- ILLink
- IL2055
- member
- M:Microsoft.CSharp.RuntimeBinder.ComInterop.VariantArray.GetStructType(System.Int32)
-
-
- ILLink
- IL2055
- member
- M:Microsoft.CSharp.RuntimeBinder.Semantics.AggregateType.CalculateAssociatedSystemType
-
-
- ILLink
- IL2060
- member
- M:Microsoft.CSharp.RuntimeBinder.Semantics.ExprMethodInfo.get_MethodInfo
-
-
- ILLink
- IL2070
- member
- M:Microsoft.CSharp.RuntimeBinder.RuntimeBinderExtensions.GetTypeIndexerName(System.Type)
-
-
- ILLink
- IL2070
- member
- M:Microsoft.CSharp.RuntimeBinder.SymbolTable.AddAggregateToSymbolTable(Microsoft.CSharp.RuntimeBinder.Semantics.NamespaceOrAggregateSymbol,System.Type)
-
-
- ILLink
- IL2070
- member
- M:Microsoft.CSharp.RuntimeBinder.SymbolTable.AddConversionsForOneType(System.Type)
-
-
- ILLink
- IL2072
- member
- M:Microsoft.CSharp.RuntimeBinder.ComInterop.ComTypeClassDesc.CreateInstance
-
-
- ILLink
- IL2072
- member
- M:Microsoft.CSharp.RuntimeBinder.Semantics.ExprFactory.CreateZeroInit(Microsoft.CSharp.RuntimeBinder.Semantics.CType)
-
-
- ILLink
- IL2072
- member
- M:Microsoft.CSharp.RuntimeBinder.Semantics.ExprZeroInit.get_Object
-
-
- ILLink
- IL2075
- member
- M:Microsoft.CSharp.RuntimeBinder.ComInterop.ComBinderHelpers.ProcessArgumentsForCom(System.Dynamic.DynamicMetaObject[]@)
-
-
- ILLink
- IL2075
- member
- M:Microsoft.CSharp.RuntimeBinder.ComInterop.ExcepInfo.GetException
-
-
- ILLink
- IL2075
- member
- M:Microsoft.CSharp.RuntimeBinder.ComInterop.IDispatchComObject.GetMembers(System.Collections.Generic.IEnumerable{System.String})
-
-
- ILLink
- IL2075
- member
- M:Microsoft.CSharp.RuntimeBinder.ComInterop.TypeUtils.GetUserDefinedCoercionMethod(System.Type,System.Type,System.Boolean)
-
-
- ILLink
- IL2075
- member
- M:Microsoft.CSharp.RuntimeBinder.DynamicMetaObjectProviderDebugView.CreateDelegateAndInvoke(System.Type[],System.Runtime.CompilerServices.CallSiteBinder,System.Object[])
-
-
- ILLink
- IL2075
- member
- M:Microsoft.CSharp.RuntimeBinder.ExpressionTreeCallRewriter.GenerateField(Microsoft.CSharp.RuntimeBinder.Semantics.ExprCall)
-
-
- ILLink
- IL2075
- member
- M:Microsoft.CSharp.RuntimeBinder.Semantics.ExprMethodInfo.get_ConstructorInfo
-
-
- ILLink
- IL2075
- member
- M:Microsoft.CSharp.RuntimeBinder.Semantics.ExprMethodInfo.get_MethodInfo
-
-
- ILLink
- IL2075
- member
- M:Microsoft.CSharp.RuntimeBinder.Semantics.ExprPropertyInfo.get_PropertyInfo
-
-
- ILLink
- IL2075
- member
- M:Microsoft.CSharp.RuntimeBinder.SymbolTable.AddPredefinedMethodToSymbolTable(Microsoft.CSharp.RuntimeBinder.Semantics.AggregateSymbol,Microsoft.CSharp.RuntimeBinder.Syntax.Name)
-
-
- ILLink
- IL2075
- member
- M:Microsoft.CSharp.RuntimeBinder.SymbolTable.AddPredefinedPropertyToSymbolTable(Microsoft.CSharp.RuntimeBinder.Semantics.AggregateSymbol,Microsoft.CSharp.RuntimeBinder.Syntax.Name)
-
-
- ILLink
- IL2075
- member
- M:Microsoft.CSharp.RuntimeBinder.SymbolTable.BuildDeclarationChain(System.Type)
-
-
- ILLink
- IL2080
- member
- M:Microsoft.CSharp.RuntimeBinder.SymbolTable.AddNamesInInheritanceHierarchy(System.String,System.Collections.Generic.List{System.Type})
-
-
- ILLink
- IL2026
- member
- M:Microsoft.CSharp.RuntimeBinder.ComInterop.CurrencyArgBuilder.Marshal(System.Linq.Expressions.Expression)
-
-
- ILLink
- IL2026
- member
- M:Microsoft.CSharp.RuntimeBinder.ComInterop.ErrorArgBuilder.Marshal(System.Linq.Expressions.Expression)
-
-
- ILLink
- IL2026
- member
- M:Microsoft.CSharp.RuntimeBinder.ComInterop.VariantArray.GetStructField(System.Linq.Expressions.ParameterExpression,System.Int32)
-
-
- ILLink
- IL2026
- member
- M:Microsoft.CSharp.RuntimeBinder.ExpressionTreeCallRewriter.GenerateConvert(Microsoft.CSharp.RuntimeBinder.Semantics.ExprCall)
-
-
-
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Binder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Binder.cs
index 0f51633431f562..beec176cb19c60 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Binder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Binder.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
+using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
@@ -15,6 +16,7 @@ namespace Microsoft.CSharp.RuntimeBinder
[EditorBrowsable(EditorBrowsableState.Never)]
public static class Binder
{
+ internal const string TrimmerWarning = "Using dynamic types might cause types or members to be removed by trimmer.";
//////////////////////////////////////////////////////////////////////
///
@@ -25,6 +27,7 @@ public static class Binder
/// The that indicates where this operation is used.
/// The sequence of instances for the arguments to this operation.
/// Returns a new CSharp binary operation binder.
+ [RequiresUnreferencedCode(TrimmerWarning)]
public static CallSiteBinder BinaryOperation(
CSharpBinderFlags flags,
ExpressionType operation,
@@ -50,8 +53,9 @@ public static CallSiteBinder BinaryOperation(
///
/// The flags with which to initialize the binder.
/// The type to convert to.
- /// The that indicates where this operation is used.
+ /// The that indicates where this operation is used.
/// Returns a new CSharp convert binder.
+ [RequiresUnreferencedCode(TrimmerWarning)]
public static CallSiteBinder Convert(
CSharpBinderFlags flags,
Type type,
@@ -78,6 +82,7 @@ public static CallSiteBinder Convert(
/// The that indicates where this operation is used.
/// The sequence of instances for the arguments to this operation.
/// Returns a new CSharp get index binder.
+ [RequiresUnreferencedCode(TrimmerWarning)]
public static CallSiteBinder GetIndex(
CSharpBinderFlags flags,
Type? context,
@@ -96,6 +101,7 @@ public static CallSiteBinder GetIndex(
/// The that indicates where this operation is used.
/// The sequence of instances for the arguments to this operation.
/// Returns a new CSharp get member binder.
+ [RequiresUnreferencedCode(TrimmerWarning)]
public static CallSiteBinder GetMember(
CSharpBinderFlags flags,
string name,
@@ -112,9 +118,10 @@ public static CallSiteBinder GetMember(
/// Initializes a new CSharp invoke binder.
///
/// The flags with which to initialize the binder.
- /// The that indicates where this operation is used.
+ /// The that indicates where this operation is used.
/// The sequence of instances for the arguments to this operation.
/// Returns a new CSharp invoke binder.
+ [RequiresUnreferencedCode(TrimmerWarning)]
public static CallSiteBinder Invoke(
CSharpBinderFlags flags,
Type? context,
@@ -142,6 +149,7 @@ public static CallSiteBinder Invoke(
/// The that indicates where this operation is used.
/// The sequence of instances for the arguments to this operation.
/// Returns a new CSharp invoke member binder.
+ [RequiresUnreferencedCode(TrimmerWarning)]
public static CallSiteBinder InvokeMember(
CSharpBinderFlags flags,
string name,
@@ -179,6 +187,7 @@ public static CallSiteBinder InvokeMember(
/// The that indicates where this operation is used.
/// The sequence of instances for the arguments to this operation.
/// Returns a new CSharp invoke constructor binder.
+ [RequiresUnreferencedCode(TrimmerWarning)]
public static CallSiteBinder InvokeConstructor(
CSharpBinderFlags flags,
Type? context,
@@ -196,6 +205,7 @@ public static CallSiteBinder InvokeConstructor(
/// The name of the event to look for.
/// The that indicates where this operation is used.
/// Returns a new CSharp is event binder.
+ [RequiresUnreferencedCode(TrimmerWarning)]
public static CallSiteBinder IsEvent(
CSharpBinderFlags flags,
string name,
@@ -213,6 +223,7 @@ public static CallSiteBinder IsEvent(
/// The that indicates where this operation is used.
/// The sequence of instances for the arguments to this operation.
/// Returns a new CSharp set index binder.
+ [RequiresUnreferencedCode(TrimmerWarning)]
public static CallSiteBinder SetIndex(
CSharpBinderFlags flags,
Type? context,
@@ -233,6 +244,7 @@ public static CallSiteBinder SetIndex(
/// The that indicates where this operation is used.
/// The sequence of instances for the arguments to this operation.
/// Returns a new CSharp set member binder.
+ [RequiresUnreferencedCode(TrimmerWarning)]
public static CallSiteBinder SetMember(
CSharpBinderFlags flags,
string name,
@@ -254,6 +266,7 @@ public static CallSiteBinder SetMember(
/// The that indicates where this operation is used.
/// The sequence of instances for the arguments to this operation.
/// Returns a new CSharp unary operation binder.
+ [RequiresUnreferencedCode(TrimmerWarning)]
public static CallSiteBinder UnaryOperation(
CSharpBinderFlags flags,
ExpressionType operation,
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/BinderHelper.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/BinderHelper.cs
index 60b1c044f208a2..405c87e1df93ea 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/BinderHelper.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/BinderHelper.cs
@@ -11,6 +11,7 @@
using System.Reflection;
using System.Numerics.Hashing;
using Microsoft.CSharp.RuntimeBinder.Errors;
+using System.Diagnostics.CodeAnalysis;
namespace Microsoft.CSharp.RuntimeBinder
{
@@ -19,6 +20,7 @@ internal static class BinderHelper
private static MethodInfo s_DoubleIsNaN;
private static MethodInfo s_SingleIsNaN;
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal static DynamicMetaObject Bind(
ICSharpBinder action,
RuntimeBinder binder,
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpBinaryOperationBinder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpBinaryOperationBinder.cs
index 91104f1c0240d5..b9387f9d8e6b50 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpBinaryOperationBinder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpBinaryOperationBinder.cs
@@ -30,9 +30,11 @@ public string Name
public BindingFlag BindingFlags => 0;
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public Expr DispatchPayload(RuntimeBinder runtimeBinder, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
=> runtimeBinder.BindBinaryOperation(this, arguments, locals);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] arguments)
{
string name = Operation.GetCLROperatorName();
@@ -67,6 +69,7 @@ public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] argum
/// The flags associated with this binary operation.
/// The that indicates where this operation is defined.
/// The sequence of instances for the arguments to this operation.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public CSharpBinaryOperationBinder(
ExpressionType operation,
bool isChecked,
@@ -122,6 +125,8 @@ public bool IsEquivalentTo(ICSharpBinder other)
/// The right hand side operand of the dynamic binary operation.
/// The binding result in case the binding fails, or null.
/// The representing the result of the binding.
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "This whole class is unsafe. Constructors are marked as such.")]
public override DynamicMetaObject FallbackBinaryOperation(DynamicMetaObject target, DynamicMetaObject arg, DynamicMetaObject errorSuggestion)
{
BinderHelper.ValidateBindArgument(target, nameof(target));
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpConvertBinder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpConvertBinder.cs
index f69364fd2602e9..db5e69f3a68a4b 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpConvertBinder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpConvertBinder.cs
@@ -29,6 +29,7 @@ public string Name
public BindingFlag BindingFlags => 0;
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public Expr DispatchPayload(RuntimeBinder runtimeBinder, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
{
Debug.Assert(arguments.Length == 1);
@@ -37,6 +38,7 @@ public Expr DispatchPayload(RuntimeBinder runtimeBinder, ArgumentObject[] argume
: runtimeBinder.BindImplicitConversion(arguments, Type, locals, ConversionKind == CSharpConversionKind.ArrayCreationConversion);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] arguments)
{
// Conversions don't need to do anything, since they're just conversions!
@@ -63,6 +65,7 @@ public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] argum
/// The kind of conversion for this operation.
/// True if the operation is defined in a checked context; otherwise, false.
/// The that indicates where this operation is defined.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public CSharpConvertBinder(
Type type,
CSharpConversionKind conversionKind,
@@ -113,6 +116,8 @@ public bool IsEquivalentTo(ICSharpBinder other)
/// The target of the dynamic convert operation.
/// The binding result to use if binding fails, or null.
/// The representing the result of the binding.
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "This whole class is unsafe. Constructors are marked as such.")]
public override DynamicMetaObject FallbackConvert(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
{
#if ENABLECOMBINDER
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpGetIndexBinder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpGetIndexBinder.cs
index b2b793afd79777..e15308e950e1c1 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpGetIndexBinder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpGetIndexBinder.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using Microsoft.CSharp.RuntimeBinder.Errors;
using Microsoft.CSharp.RuntimeBinder.Semantics;
@@ -19,12 +20,14 @@ internal sealed class CSharpGetIndexBinder : GetIndexBinder, ICSharpBinder
public BindingFlag BindingFlags => BindingFlag.BIND_RVALUEREQUIRED;
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public Expr DispatchPayload(RuntimeBinder runtimeBinder, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
{
Expr indexerArguments = runtimeBinder.CreateArgumentListEXPR(arguments, locals, 1, arguments.Length);
return runtimeBinder.BindProperty(this, arguments[0], locals[0], indexerArguments);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] arguments)
=> SymbolTable.PopulateSymbolTableWithName(SpecialNames.Indexer, null, arguments[0].Type);
@@ -43,6 +46,7 @@ public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] argum
///
/// The that indicates where this operation is defined.
/// The sequence of instances for the arguments to this operation.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public CSharpGetIndexBinder(
Type callingContext,
IEnumerable argumentInfo) :
@@ -85,6 +89,8 @@ public bool IsEquivalentTo(ICSharpBinder other)
/// The arguments of the dynamic get index operation.
/// The binding result to use if binding fails, or null.
/// The representing the result of the binding.
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "This whole class is unsafe. Constructors are marked as such.")]
public override DynamicMetaObject FallbackGetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject errorSuggestion)
{
#if ENABLECOMBINDER
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpGetMemberBinder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpGetMemberBinder.cs
index a0a59d1046bd65..cdfe66e1c553ad 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpGetMemberBinder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpGetMemberBinder.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Numerics.Hashing;
using Microsoft.CSharp.RuntimeBinder.Errors;
@@ -19,12 +20,14 @@ internal sealed class CSharpGetMemberBinder : GetMemberBinder, IInvokeOnGetBinde
{
public BindingFlag BindingFlags => BindingFlag.BIND_RVALUEREQUIRED;
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public Expr DispatchPayload(RuntimeBinder runtimeBinder, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
{
Debug.Assert(arguments.Length == 1);
return runtimeBinder.BindProperty(this, arguments[0], locals[0], null);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] arguments)
=> SymbolTable.PopulateSymbolTableWithName(Name, null, arguments[0].Type);
@@ -49,6 +52,7 @@ public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] argum
/// Determines if COM binder should return a callable object.
/// The that indicates where this operation is defined.
/// The sequence of instances for the arguments to this operation.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public CSharpGetMemberBinder(
string name,
bool resultIndexed,
@@ -100,6 +104,8 @@ public bool IsEquivalentTo(ICSharpBinder other)
/// The target of the dynamic get member operation.
/// The binding result to use if binding fails, or null.
/// The representing the result of the binding.
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "This whole class is unsafe. Constructors are marked as such.")]
public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
{
#if ENABLECOMBINDER
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpInvokeBinder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpInvokeBinder.cs
index dd25a30c4dbcd4..db5ed08951c367 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpInvokeBinder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpInvokeBinder.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Numerics.Hashing;
using Microsoft.CSharp.RuntimeBinder.Errors;
@@ -18,9 +19,11 @@ internal sealed class CSharpInvokeBinder : InvokeBinder, ICSharpInvokeOrInvokeMe
{
public BindingFlag BindingFlags => 0;
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public Expr DispatchPayload(RuntimeBinder runtimeBinder, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
=> runtimeBinder.DispatchPayload(this, arguments, locals);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] arguments)
=> RuntimeBinder.PopulateSymbolTableWithPayloadInformation(this, callingType, arguments);
@@ -52,6 +55,7 @@ public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] argum
/// Extra information about this operation that is not specific to any particular argument.
/// The that indicates where this operation is defined.
/// The sequence of instances for the arguments to this operation.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public CSharpInvokeBinder(
CSharpCallFlags flags,
Type callingContext,
@@ -98,6 +102,8 @@ public bool IsEquivalentTo(ICSharpBinder other)
/// The arguments of the dynamic invoke operation.
/// The binding result to use if binding fails, or null.
/// The representing the result of the binding.
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "This whole class is unsafe. Constructors are marked as such.")]
public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion)
{
#if ENABLECOMBINDER
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpInvokeConstructorBinder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpInvokeConstructorBinder.cs
index f4c1d1cacc918b..1b827363eb4f43 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpInvokeConstructorBinder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpInvokeConstructorBinder.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Numerics.Hashing;
using Microsoft.CSharp.RuntimeBinder.Semantics;
@@ -13,9 +14,11 @@ internal sealed class CSharpInvokeConstructorBinder : DynamicMetaObjectBinder, I
{
public BindingFlag BindingFlags => 0;
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public Expr DispatchPayload(RuntimeBinder runtimeBinder, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
=> runtimeBinder.DispatchPayload(this, arguments, locals);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] arguments)
=> RuntimeBinder.PopulateSymbolTableWithPayloadInformation(this, callingType, arguments);
@@ -39,6 +42,7 @@ public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] argum
private readonly Type _callingContext;
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public CSharpInvokeConstructorBinder(
CSharpCallFlags flags,
Type callingContext,
@@ -81,6 +85,8 @@ public bool IsEquivalentTo(ICSharpBinder other)
return BinderHelper.CompareArgInfos(TypeArguments, otherBinder.TypeArguments, _argumentInfo, otherBinder._argumentInfo);
}
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "This whole class is unsafe. Constructors are marked as such.")]
public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args)
{
BinderHelper.ValidateBindArgument(target, nameof(target));
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpInvokeMemberBinder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpInvokeMemberBinder.cs
index 839be81cd4500a..b48409abc186c9 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpInvokeMemberBinder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpInvokeMemberBinder.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Numerics.Hashing;
using Microsoft.CSharp.RuntimeBinder.Errors;
@@ -19,9 +20,11 @@ internal sealed class CSharpInvokeMemberBinder : InvokeMemberBinder, ICSharpInvo
{
public BindingFlag BindingFlags => 0;
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public Expr DispatchPayload(RuntimeBinder runtimeBinder, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
=> runtimeBinder.DispatchPayload(this, arguments, locals);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] arguments)
=> RuntimeBinder.PopulateSymbolTableWithPayloadInformation(this, callingType, arguments);
@@ -58,6 +61,7 @@ public CSharpArgumentInfo[] ArgumentInfoArray()
/// The that indicates where this operation is defined.
/// The list of user-specified type arguments to this call.
/// The sequence of instances for the arguments to this operation.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public CSharpInvokeMemberBinder(
CSharpCallFlags flags,
string name,
@@ -111,6 +115,8 @@ public bool IsEquivalentTo(ICSharpBinder other)
/// The arguments of the dynamic invoke member operation.
/// The binding result to use if binding fails, or null.
/// The representing the result of the binding.
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "This whole class is unsafe. Constructors are marked as such.")]
public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion)
{
#if ENABLECOMBINDER
@@ -135,6 +141,8 @@ public override DynamicMetaObject FallbackInvokeMember(DynamicMetaObject target,
/// The arguments of the dynamic invoke operation.
/// The binding result to use if binding fails, or null.
/// The representing the result of the binding.
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "This whole class is unsafe. Constructors are marked as such.")]
public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion)
{
CSharpInvokeBinder c = new CSharpInvokeBinder(Flags, CallingContext, _argumentInfo).TryGetExisting();
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpIsEventBinder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpIsEventBinder.cs
index 3faaa5323667db..83c8ad8703067a 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpIsEventBinder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpIsEventBinder.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Numerics.Hashing;
using Microsoft.CSharp.RuntimeBinder.Semantics;
@@ -15,9 +16,11 @@ internal sealed class CSharpIsEventBinder : DynamicMetaObjectBinder, ICSharpBind
{
public BindingFlag BindingFlags => 0;
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public Expr DispatchPayload(RuntimeBinder runtimeBinder, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
=> runtimeBinder.BindIsEvent(this, arguments, locals);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] arguments)
=> SymbolTable.PopulateSymbolTableWithName(Name, null, arguments[0].Info.IsStaticType ? arguments[0].Value as Type : arguments[0].Type);
@@ -36,6 +39,7 @@ public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] argum
///
/// The name of the member to test.
/// The that indicates where this operation is defined.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public CSharpIsEventBinder(
string name,
Type callingContext)
@@ -80,6 +84,8 @@ public bool IsEquivalentTo(ICSharpBinder other)
/// The target of the dynamic binary operation.
/// The arguments to the dynamic event test.
/// The representing the result of the binding.
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "This whole class is unsafe. Constructors are marked as such.")]
public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args)
{
BinderHelper.ValidateBindArgument(target, nameof(target));
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpSetIndexBinder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpSetIndexBinder.cs
index 5c6d3dc98b72af..ef53ab6f4ccf09 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpSetIndexBinder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpSetIndexBinder.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Numerics.Hashing;
using Microsoft.CSharp.RuntimeBinder.Errors;
@@ -20,9 +21,11 @@ internal sealed class CSharpSetIndexBinder : SetIndexBinder, ICSharpBinder
public BindingFlag BindingFlags => 0;
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public Expr DispatchPayload(RuntimeBinder runtimeBinder, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
=> runtimeBinder.BindAssignment(this, arguments, locals);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] arguments)
=> SymbolTable.PopulateSymbolTableWithName(SpecialNames.Indexer, null, arguments[0].Type);
@@ -49,6 +52,7 @@ public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] argum
/// True if the operation is defined in a checked context; otherwise, false.
/// The that indicates where this operation is defined.
/// The sequence of instances for the arguments to this operation.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public CSharpSetIndexBinder(
bool isCompoundAssignment,
bool isChecked,
@@ -105,6 +109,8 @@ public bool IsEquivalentTo(ICSharpBinder other)
/// The value to set to the collection.
/// The binding result to use if binding fails, or null.
/// The representing the result of the binding.
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "This whole class is unsafe. Constructors are marked as such.")]
public override DynamicMetaObject FallbackSetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject value, DynamicMetaObject errorSuggestion)
{
#if ENABLECOMBINDER
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpSetMemberBinder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpSetMemberBinder.cs
index 3ae5888c9e0ca2..4dff5e5ba1ed86 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpSetMemberBinder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpSetMemberBinder.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Numerics.Hashing;
using Microsoft.CSharp.RuntimeBinder.Errors;
@@ -18,9 +19,11 @@ internal sealed class CSharpSetMemberBinder : SetMemberBinder, ICSharpBinder
{
public BindingFlag BindingFlags => 0;
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public Expr DispatchPayload(RuntimeBinder runtimeBinder, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
=> runtimeBinder.BindAssignment(this, arguments, locals);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] arguments)
=> SymbolTable.PopulateSymbolTableWithName(Name, null, arguments[0].Type);
@@ -47,6 +50,7 @@ public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] argum
/// True if the operation is defined in a checked context; otherwise, false.
/// The that indicates where this operation is defined.
/// The sequence of instances for the arguments to this operation.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public CSharpSetMemberBinder(
string name,
bool isCompoundAssignment,
@@ -105,6 +109,8 @@ public bool IsEquivalentTo(ICSharpBinder other)
/// The value to set to the member.
/// The binding result to use if binding fails, or null.
/// The representing the result of the binding.
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "This whole class is unsafe. Constructors are marked as such.")]
public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion)
{
#if ENABLECOMBINDER
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpUnaryOperationBinder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpUnaryOperationBinder.cs
index 04c6918d221147..b86a6994e51667 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpUnaryOperationBinder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/CSharpUnaryOperationBinder.cs
@@ -31,9 +31,11 @@ public string Name
public BindingFlag BindingFlags => 0;
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public Expr DispatchPayload(RuntimeBinder runtimeBinder, ArgumentObject[] arguments, LocalVariableSymbol[] locals)
=> runtimeBinder.BindUnaryOperation(this, arguments, locals);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] arguments)
=> SymbolTable.PopulateSymbolTableWithName(Operation.GetCLROperatorName(), null, arguments[0].Type);
@@ -56,6 +58,7 @@ public void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] argum
/// True if the operation is defined in a checked context; otherwise, false.
/// The that indicates where this operation is defined.
/// The sequence of instances for the arguments to this operation.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public CSharpUnaryOperationBinder(
ExpressionType operation,
bool isChecked,
@@ -106,6 +109,8 @@ public bool IsEquivalentTo(ICSharpBinder other)
/// The target of the dynamic unary operation.
/// The binding result in case the binding fails, or null.
/// The representing the result of the binding.
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "This whole class is unsafe. Constructors are marked as such.")]
public override DynamicMetaObject FallbackUnaryOperation(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
{
BinderHelper.ValidateBindArgument(target, nameof(target));
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ArgBuilder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ArgBuilder.cs
index cffbc296e5242c..33cb94053f1074 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ArgBuilder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ArgBuilder.cs
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
namespace Microsoft.CSharp.RuntimeBinder.ComInterop
@@ -16,12 +17,14 @@ internal abstract class ArgBuilder
///
/// Provides the Expression which provides the value to be passed to the argument.
///
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal abstract Expression Marshal(Expression parameter);
///
/// Provides the Expression which provides the value to be passed to the argument.
/// This method is called when result is intended to be used ByRef.
///
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal virtual Expression MarshalToRef(Expression parameter)
{
return Marshal(parameter);
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/BoolArgBuilder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/BoolArgBuilder.cs
index f217f47e4f6720..ab7564c02cac5e 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/BoolArgBuilder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/BoolArgBuilder.cs
@@ -3,6 +3,7 @@
using System;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
namespace Microsoft.CSharp.RuntimeBinder.ComInterop
@@ -15,6 +16,7 @@ internal BoolArgBuilder(Type parameterType)
Debug.Assert(parameterType == typeof(bool));
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal override Expression MarshalToRef(Expression parameter)
{
// parameter ? -1 : 0
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/BoundDispEvent.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/BoundDispEvent.cs
index 8333155e80000d..354dcc7f9aaba0 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/BoundDispEvent.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/BoundDispEvent.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Linq.Expressions;
using System.Runtime.InteropServices;
@@ -14,6 +15,7 @@ internal sealed class BoundDispEvent : DynamicObject
private readonly Guid _sourceIid;
private readonly int _dispid;
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal BoundDispEvent(object rcw, Guid sourceIid, int dispid)
{
_rcw = rcw;
@@ -28,6 +30,8 @@ internal BoundDispEvent(object rcw, Guid sourceIid, int dispid)
/// The handler for the operation.
/// The result of the operation.
/// true if the operation is complete, false if the call site should determine behavior.
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "This whole class is unsafe. Constructors are marked as such.")]
public override bool TryBinaryOperation(BinaryOperationBinder binder, object handler, out object result)
{
if (binder.Operation == ExpressionType.AddAssign)
@@ -71,6 +75,7 @@ private static void VerifyHandler(object handler)
///
/// The handler to be added.
/// The original event with handler added.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private object InPlaceAdd(object handler)
{
Requires.NotNull(handler, nameof(handler));
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComBinder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComBinder.cs
index e8d9ec19aedce3..26588e6a4093ae 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComBinder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComBinder.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Linq.Expressions;
using System.Runtime.InteropServices;
@@ -31,6 +32,7 @@ public static bool IsComObject(object value)
/// The new representing the result of the binding.
/// true if member evaluation may be delayed.
/// true if operation was bound successfully; otherwise, false.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static bool TryBindGetMember(GetMemberBinder binder, DynamicMetaObject instance, out DynamicMetaObject result, bool delayInvocation)
{
Requires.NotNull(binder, nameof(binder));
@@ -62,6 +64,7 @@ public static bool TryBindGetMember(GetMemberBinder binder, DynamicMetaObject in
/// The representing the value for the set member operation.
/// The new representing the result of the binding.
/// true if operation was bound successfully; otherwise, false.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static bool TryBindSetMember(SetMemberBinder binder, DynamicMetaObject instance, DynamicMetaObject value, out DynamicMetaObject result)
{
Requires.NotNull(binder, nameof(binder));
@@ -86,6 +89,7 @@ public static bool TryBindSetMember(SetMemberBinder binder, DynamicMetaObject in
/// An array of instances - arguments to the invoke member operation.
/// The new representing the result of the binding.
/// true if operation was bound successfully; otherwise, false.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static bool TryBindInvoke(InvokeBinder binder, DynamicMetaObject instance, DynamicMetaObject[] args, out DynamicMetaObject result)
{
Requires.NotNull(binder, nameof(binder));
@@ -110,6 +114,7 @@ public static bool TryBindInvoke(InvokeBinder binder, DynamicMetaObject instance
/// An array of instances - arguments to the invoke member operation.
/// The new representing the result of the binding.
/// true if operation was bound successfully; otherwise, false.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static bool TryBindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject instance, DynamicMetaObject[] args, out DynamicMetaObject result)
{
Requires.NotNull(binder, nameof(binder));
@@ -134,6 +139,7 @@ public static bool TryBindInvokeMember(InvokeMemberBinder binder, DynamicMetaObj
/// An array of instances - arguments to the invoke member operation.
/// The new representing the result of the binding.
/// true if operation was bound successfully; otherwise, false.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static bool TryBindGetIndex(GetIndexBinder binder, DynamicMetaObject instance, DynamicMetaObject[] args, out DynamicMetaObject result)
{
Requires.NotNull(binder, nameof(binder));
@@ -159,6 +165,7 @@ public static bool TryBindGetIndex(GetIndexBinder binder, DynamicMetaObject inst
/// The representing the value for the set index operation.
/// The new representing the result of the binding.
/// true if operation was bound successfully; otherwise, false.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static bool TryBindSetIndex(SetIndexBinder binder, DynamicMetaObject instance, DynamicMetaObject[] args, DynamicMetaObject value, out DynamicMetaObject result)
{
Requires.NotNull(binder, nameof(binder));
@@ -220,6 +227,7 @@ public static bool TryConvert(ConvertBinder binder, DynamicMetaObject instance,
///
/// The object for which member names are requested.
/// The collection of member names.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal static IList GetDynamicDataMemberNames(object value)
{
Requires.NotNull(value, nameof(value));
@@ -235,6 +243,7 @@ internal static IList GetDynamicDataMemberNames(object value)
/// The object for which data members are requested.
/// The enumeration of names of data members for which to retrieve values.
/// The collection of pairs that represent data member's names and their data.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal static IList> GetDynamicDataMembers(object value, IEnumerable names)
{
Requires.NotNull(value, nameof(value));
@@ -243,6 +252,7 @@ internal static IList> GetDynamicDataMembers(object
return ComObject.ObjectToComObject(value).GetMembers(names);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static bool TryGetMetaObject(ref DynamicMetaObject instance)
{
// If we're already a COM MO don't make a new one
@@ -261,6 +271,7 @@ private static bool TryGetMetaObject(ref DynamicMetaObject instance)
return false;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static bool TryGetMetaObjectInvoke(ref DynamicMetaObject instance)
{
// If we're already a COM MO don't make a new one
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComBinderHelpers.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComBinderHelpers.cs
index 1ce21e788fb0a5..f1b73bd86e970c 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComBinderHelpers.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComBinderHelpers.cs
@@ -5,6 +5,7 @@
using System;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
@@ -37,6 +38,7 @@ internal static bool IsByRef(DynamicMetaObject mo)
return mo.Expression is ParameterExpression pe && pe.IsByRef;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal static bool IsStrongBoxArg(DynamicMetaObject o)
{
Type t = o.LimitType;
@@ -45,6 +47,7 @@ internal static bool IsStrongBoxArg(DynamicMetaObject o)
// This helper prepares arguments for COM binding by transforming ByVal StrongBox arguments
// into ByRef expressions that represent the argument's Value fields.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal static bool[] ProcessArgumentsForCom(ref DynamicMetaObject[] args)
{
Debug.Assert(args != null);
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComClassMetaObject.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComClassMetaObject.cs
index c61fc467d991ab..ee0e2f5b75b312 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComClassMetaObject.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComClassMetaObject.cs
@@ -2,17 +2,21 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Dynamic;
+using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
namespace Microsoft.CSharp.RuntimeBinder.ComInterop
{
internal sealed class ComClassMetaObject : DynamicMetaObject
{
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal ComClassMetaObject(Expression expression, ComTypeClassDesc cls)
: base(expression, BindingRestrictions.Empty, cls)
{
}
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "This whole class is unsafe. Constructors are marked as such.")]
public override DynamicMetaObject BindCreateInstance(CreateInstanceBinder binder, DynamicMetaObject[] args)
{
return new DynamicMetaObject(
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComEventsSink.Extended.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComEventsSink.Extended.cs
index c6bd8a9c459c39..b68929a5fa2161 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComEventsSink.Extended.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComEventsSink.Extended.cs
@@ -2,7 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using Microsoft.CSharp.RuntimeBinder;
using Microsoft.CSharp.RuntimeBinder.ComInterop;
namespace System.Runtime.InteropServices
@@ -15,6 +17,7 @@ private void Initialize(object rcw, Guid iid)
Advise(rcw);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public void AddHandler(int dispid, object func)
{
ComEventsMethod method = FindMethod(dispid);
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComInvokeAction.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComInvokeAction.cs
index 62f2685e5a2d1b..e804bbaabe8d50 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComInvokeAction.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComInvokeAction.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.ObjectModel;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
@@ -15,11 +16,14 @@ namespace Microsoft.CSharp.RuntimeBinder.ComInterop
///
internal sealed class ComInvokeAction : InvokeBinder
{
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal ComInvokeAction(CallInfo callInfo)
: base(callInfo)
{
}
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "This whole class is unsafe. Constructors are marked as such.")]
public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion)
{
if (ComBinder.TryBindInvoke(this, target, args, out DynamicMetaObject res))
@@ -46,9 +50,19 @@ public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, Dynam
///
internal sealed class SplatInvokeBinder : CallSiteBinder
{
- internal static readonly SplatInvokeBinder s_instance = new SplatInvokeBinder();
+ private static readonly SplatInvokeBinder s_instance = new SplatInvokeBinder();
+
+ internal static SplatInvokeBinder Instance
+ {
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
+ get => s_instance;
+ }
+
+ private SplatInvokeBinder() { }
// Just splat the args and dispatch through a nested site
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "This whole class is unsafe. The only entry-point to this class is through Instance property which is marked as unsafe.")]
public override Expression Bind(object[] args, ReadOnlyCollection parameters, LabelTarget returnLabel)
{
Debug.Assert(args.Length == 2);
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComInvokeBinder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComInvokeBinder.cs
index 1c7737801ecbb8..343684efe133b2 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComInvokeBinder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComInvokeBinder.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Linq.Expressions;
using System.Runtime.InteropServices;
@@ -148,6 +149,7 @@ private static Type MarshalType(DynamicMetaObject mo, bool isByRef)
return marshalType;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal DynamicMetaObject Invoke()
{
_keywordArgNames = _callInfo.ArgumentNames.ToArray();
@@ -191,6 +193,7 @@ private Expression CreateScope(Expression expression)
return vars.Count > 0 ? Expression.Block(vars, expression) : expression;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expression GenerateTryBlock()
{
//
@@ -395,6 +398,7 @@ private Expression GenerateFinallyBlock()
/// Create a stub for the target of the optimized lopop.
///
///
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expression MakeIDispatchInvokeTarget()
{
Debug.Assert(_varEnumSelector.VariantBuilders.Length == _totalExplicitArgs);
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComMetaObject.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComMetaObject.cs
index e27839d60935b5..7ae60b32a645e6 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComMetaObject.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComMetaObject.cs
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Linq.Expressions;
@@ -9,6 +10,7 @@ namespace Microsoft.CSharp.RuntimeBinder.ComInterop
// Note: we only need to support the operations used by ComBinder
internal sealed class ComMetaObject : DynamicMetaObject
{
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal ComMetaObject(Expression expression, BindingRestrictions restrictions, object arg)
: base(expression, restrictions, arg)
{
@@ -50,6 +52,8 @@ public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMet
return binder.Defer(WrapSelf(), indexes.AddLast(value));
}
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "This whole class is unsafe. Constructors are marked as such.")]
private DynamicMetaObject WrapSelf()
{
return new DynamicMetaObject(
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComObject.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComObject.cs
index b4724ca2fccdce..fd4aa80ca23a7f 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComObject.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComObject.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Linq.Expressions;
using System.Reflection;
@@ -30,6 +31,7 @@ internal ComObject(object rcw)
/// Gets a that wraps the runtime-callable-wrapper, or creates one if none currently exists.
///
///
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static ComObject ObjectToComObject(object rcw)
{
Debug.Assert(ComBinder.IsComObject(rcw));
@@ -70,6 +72,7 @@ internal static MemberExpression RcwFromComObject(Expression comObject)
}
// Expression that finds or creates a ComObject that corresponds to given Rcw
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal static MethodCallExpression RcwToComObject(Expression rcw)
{
return Expression.Call(
@@ -78,6 +81,7 @@ internal static MethodCallExpression RcwToComObject(Expression rcw)
);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static ComObject CreateComObject(object rcw)
{
if (rcw is IDispatch dispatchObject)
@@ -90,11 +94,13 @@ private static ComObject CreateComObject(object rcw)
return new ComObject(rcw);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal virtual IList GetMemberNames(bool dataOnly)
{
return Array.Empty();
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal virtual IList> GetMembers(IEnumerable names)
{
return Array.Empty>();
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComRuntimeHelpers.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComRuntimeHelpers.cs
index 77363c66ba54d5..62ff9e0023fff9 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComRuntimeHelpers.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComRuntimeHelpers.cs
@@ -3,6 +3,7 @@
using System;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
@@ -14,6 +15,7 @@ namespace Microsoft.CSharp.RuntimeBinder.ComInterop
{
internal static class ComRuntimeHelpers
{
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static void CheckThrowException(int hresult, ref ExcepInfo excepInfo, uint argErr, string message)
{
if (ComHresults.IsSuccess(hresult))
@@ -205,6 +207,7 @@ internal static ComTypes.TYPELIBATTR GetTypeAttrForTypeLib(ComTypes.ITypeLib typ
}
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static BoundDispEvent CreateComEvent(object rcw, Guid sourceIid, int dispid)
{
return new BoundDispEvent(rcw, sourceIid, dispid);
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComTypeClassDesc.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComTypeClassDesc.cs
index 3fa5ca8c7c754b..6b71421d75f35e 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComTypeClassDesc.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComTypeClassDesc.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Linq.Expressions;
using ComTypes = System.Runtime.InteropServices.ComTypes;
@@ -15,6 +16,7 @@ internal sealed class ComTypeClassDesc : ComTypeDesc, IDynamicMetaObjectProvider
private LinkedList _sourceItfs; // source interfaces supported by this coclass
private Type _typeObj;
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public object CreateInstance()
{
if (_typeObj == null)
@@ -24,6 +26,7 @@ public object CreateInstance()
return Activator.CreateInstance(Type.GetTypeFromCLSID(Guid));
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal ComTypeClassDesc(ComTypes.ITypeInfo typeInfo, ComTypeLibDesc typeLibDesc) :
base(typeInfo, typeLibDesc)
{
@@ -74,6 +77,8 @@ internal bool Implements(string itfName, bool isSourceItf)
#region IDynamicMetaObjectProvider Members
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "This whole class is unsafe. Constructors are marked as such.")]
public DynamicMetaObject GetMetaObject(Expression parameter)
{
return new ComClassMetaObject(parameter, this);
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComTypeDesc.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComTypeDesc.cs
index ac92ab9104f542..e426dfc344b7ac 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComTypeDesc.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComTypeDesc.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices.ComTypes;
using System.Threading;
@@ -25,6 +26,7 @@ internal ComTypeDesc(ITypeInfo typeInfo, ComTypeLibDesc typeLibDesc)
TypeLib = typeLibDesc;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal static ComTypeDesc FromITypeInfo(ITypeInfo typeInfo, TYPEATTR typeAttr)
{
switch (typeAttr.typekind)
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComTypeLibDesc.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComTypeLibDesc.cs
index 522ce0135eafcd..591d8c59309d6e 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComTypeLibDesc.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComTypeLibDesc.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Dynamic;
+using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq.Expressions;
using System.Runtime.InteropServices;
@@ -48,6 +49,7 @@ DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter)
#endregion
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal static ComTypeLibDesc GetFromTypeLib(ComTypes.ITypeLib typeLib)
{
// check whether we have already loaded this type library
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ConversionArgBuilder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ConversionArgBuilder.cs
index 6958c6a0223c8e..2c7f85db3b9e95 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ConversionArgBuilder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ConversionArgBuilder.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
namespace Microsoft.CSharp.RuntimeBinder.ComInterop
@@ -17,11 +18,13 @@ internal ConversionArgBuilder(Type parameterType, SimpleArgBuilder innerBuilder)
_innerBuilder = innerBuilder;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal override Expression Marshal(Expression parameter)
{
return _innerBuilder.Marshal(Helpers.Convert(parameter, _parameterType));
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal override Expression MarshalToRef(Expression parameter)
{
//we are not supporting conversion InOut
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ConvertArgBuilder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ConvertArgBuilder.cs
index 668d269ba2ed41..15357e4f4fe0ec 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ConvertArgBuilder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ConvertArgBuilder.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
namespace Microsoft.CSharp.RuntimeBinder.ComInterop
@@ -16,6 +17,7 @@ internal ConvertArgBuilder(Type parameterType, Type marshalType)
_marshalType = marshalType;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal override Expression Marshal(Expression parameter)
{
parameter = base.Marshal(parameter);
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ConvertibleArgBuilder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ConvertibleArgBuilder.cs
index 7e18343a4eaf48..69c95e0d2799c7 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ConvertibleArgBuilder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ConvertibleArgBuilder.cs
@@ -2,17 +2,20 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
namespace Microsoft.CSharp.RuntimeBinder.ComInterop
{
internal sealed class ConvertibleArgBuilder : ArgBuilder
{
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal override Expression Marshal(Expression parameter)
{
return Helpers.Convert(parameter, typeof(IConvertible));
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal override Expression MarshalToRef(Expression parameter)
{
//we are not supporting convertible InOut
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/CurrencyArgBuilder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/CurrencyArgBuilder.cs
index 9422fee88eecc8..dd864e1ac5d88b 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/CurrencyArgBuilder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/CurrencyArgBuilder.cs
@@ -5,6 +5,7 @@
using System;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Runtime.InteropServices;
@@ -18,6 +19,7 @@ internal CurrencyArgBuilder(Type parameterType)
Debug.Assert(parameterType == typeof(CurrencyWrapper));
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal override Expression Marshal(Expression parameter)
{
// parameter.WrappedObject
@@ -27,6 +29,7 @@ internal override Expression Marshal(Expression parameter)
);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal override Expression MarshalToRef(Expression parameter)
{
// Decimal.ToOACurrency(parameter.WrappedObject)
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/DateTimeArgBuilder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/DateTimeArgBuilder.cs
index 124ba097e83acd..f130b237bf0efe 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/DateTimeArgBuilder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/DateTimeArgBuilder.cs
@@ -3,6 +3,7 @@
using System;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
namespace Microsoft.CSharp.RuntimeBinder.ComInterop
@@ -15,6 +16,7 @@ internal DateTimeArgBuilder(Type parameterType)
Debug.Assert(parameterType == typeof(DateTime));
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal override Expression MarshalToRef(Expression parameter)
{
// parameter.ToOADate()
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/DispCallable.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/DispCallable.cs
index d4ec6cb6b168e8..3a0b4678f4ebab 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/DispCallable.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/DispCallable.cs
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Globalization;
using System.Linq.Expressions;
@@ -29,6 +30,7 @@ internal DispCallable(IDispatchComObject dispatch, string memberName, int dispId
public int DispId { get; }
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public DynamicMetaObject GetMetaObject(Expression parameter)
{
return new DispCallableMetaObject(parameter, this);
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/DispCallableMetaObject.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/DispCallableMetaObject.cs
index 57ad83ac75f92b..6d8f38598a0eb3 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/DispCallableMetaObject.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/DispCallableMetaObject.cs
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Linq.Expressions;
@@ -10,6 +11,7 @@ internal sealed class DispCallableMetaObject : DynamicMetaObject
{
private readonly DispCallable _callable;
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal DispCallableMetaObject(Expression expression, DispCallable callable)
: base(expression, BindingRestrictions.Empty, callable)
{
@@ -28,6 +30,8 @@ public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObj
base.BindInvoke(binder, args);
}
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "This whole class is unsafe. Constructors are marked as such.")]
private DynamicMetaObject BindGetOrInvoke(DynamicMetaObject[] args, CallInfo callInfo)
{
IDispatchComObject target = _callable.DispatchComObject;
@@ -43,6 +47,8 @@ private DynamicMetaObject BindGetOrInvoke(DynamicMetaObject[] args, CallInfo cal
return null;
}
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "This whole class is unsafe. Constructors are marked as such.")]
public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value)
{
IDispatchComObject target = _callable.DispatchComObject;
@@ -67,6 +73,7 @@ public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMet
return base.BindSetIndex(binder, indexes, value);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private DynamicMetaObject BindComInvoke(ComMethodDesc method, DynamicMetaObject[] indexes, CallInfo callInfo, bool[] isByRef)
{
Expression callable = Expression;
@@ -86,6 +93,7 @@ private DynamicMetaObject BindComInvoke(ComMethodDesc method, DynamicMetaObject[
).Invoke();
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private BindingRestrictions DispCallableRestrictions()
{
Expression callable = Expression;
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/DispatchArgBuilder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/DispatchArgBuilder.cs
index a44fe5799a8788..6d2bcdf4475453 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/DispatchArgBuilder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/DispatchArgBuilder.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Runtime.InteropServices;
@@ -17,6 +18,7 @@ internal DispatchArgBuilder(Type parameterType)
_isWrapper = parameterType == typeof(DispatchWrapper);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal override Expression Marshal(Expression parameter)
{
parameter = base.Marshal(parameter);
@@ -33,6 +35,7 @@ internal override Expression Marshal(Expression parameter)
return Helpers.Convert(parameter, typeof(object));
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal override Expression MarshalToRef(Expression parameter)
{
parameter = Marshal(parameter);
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ErrorArgBuilder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ErrorArgBuilder.cs
index a82f7099439571..5a5cdbd7540c52 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ErrorArgBuilder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ErrorArgBuilder.cs
@@ -3,6 +3,7 @@
using System;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Runtime.InteropServices;
@@ -16,6 +17,7 @@ internal ErrorArgBuilder(Type parameterType)
Debug.Assert(parameterType == typeof(ErrorWrapper));
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal override Expression Marshal(Expression parameter)
{
// parameter.ErrorCode
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ExcepInfo.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ExcepInfo.cs
index 9f9276291ad482..0426df6712f4d1 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ExcepInfo.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ExcepInfo.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Diagnostics.CodeAnalysis;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
@@ -45,6 +46,7 @@ private static string ConvertAndFreeBstr(ref IntPtr bstr)
return result;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal Exception GetException()
{
Debug.Assert(pfnDeferredFillIn == IntPtr.Zero);
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/IDispatchComObject.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/IDispatchComObject.cs
index 3d8371d0d5188d..cc7f6cece9ddcc 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/IDispatchComObject.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/IDispatchComObject.cs
@@ -5,6 +5,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Linq.Expressions;
using System.Globalization;
@@ -78,6 +79,7 @@ internal sealed class IDispatchComObject : ComObject, IDynamicMetaObjectProvider
private ComTypeDesc _comTypeDesc;
private static readonly Dictionary s_cacheComTypeDesc = new Dictionary();
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal IDispatchComObject(IDispatch rcw)
: base(rcw)
{
@@ -128,6 +130,7 @@ private static int GetIDsOfNames(IDispatch dispatch, string name, out int dispId
return hresult;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal bool TryGetGetItem(out ComMethodDesc value)
{
ComMethodDesc methodDesc = _comTypeDesc.GetItem;
@@ -140,6 +143,7 @@ internal bool TryGetGetItem(out ComMethodDesc value)
return SlowTryGetGetItem(out value);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool SlowTryGetGetItem(out ComMethodDesc value)
{
EnsureScanDefinedMethods();
@@ -159,6 +163,7 @@ private bool SlowTryGetGetItem(out ComMethodDesc value)
return true;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal bool TryGetSetItem(out ComMethodDesc value)
{
ComMethodDesc methodDesc = _comTypeDesc.SetItem;
@@ -171,6 +176,7 @@ internal bool TryGetSetItem(out ComMethodDesc value)
return SlowTryGetSetItem(out value);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool SlowTryGetSetItem(out ComMethodDesc value)
{
EnsureScanDefinedMethods();
@@ -190,6 +196,7 @@ private bool SlowTryGetSetItem(out ComMethodDesc value)
return true;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal bool TryGetMemberMethod(string name, out ComMethodDesc method)
{
EnsureScanDefinedMethods();
@@ -202,6 +209,7 @@ internal bool TryGetMemberEvent(string name, out ComEventDesc @event)
return _comTypeDesc.TryGetEvent(name, out @event);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal bool TryGetMemberMethodExplicit(string name, out ComMethodDesc method)
{
EnsureScanDefinedMethods();
@@ -225,6 +233,7 @@ internal bool TryGetMemberMethodExplicit(string name, out ComMethodDesc method)
throw Error.CouldNotGetDispId(name, string.Format(CultureInfo.InvariantCulture, "0x{0:X})", hresult));
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal bool TryGetPropertySetterExplicit(string name, out ComMethodDesc method, Type limitType, bool holdsNull)
{
EnsureScanDefinedMethods();
@@ -261,6 +270,7 @@ internal bool TryGetPropertySetterExplicit(string name, out ComMethodDesc method
throw Error.CouldNotGetDispId(name, string.Format(CultureInfo.InvariantCulture, "0x{0:X})", hresult));
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal override IList GetMemberNames(bool dataOnly)
{
EnsureScanDefinedMethods();
@@ -269,6 +279,7 @@ internal override IList GetMemberNames(bool dataOnly)
return ComTypeDesc.GetMemberNames(dataOnly);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal override IList> GetMembers(IEnumerable names)
{
if (names == null)
@@ -312,6 +323,8 @@ internal override IList> GetMembers(IEnumerable>.Create(SplatInvokeBinder.s_instance);
+ _site = CallSite>.Create(SplatInvokeBinder.Instance);
}
return _site.Target(_site, _callable, args);
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/StringArgBuilder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/StringArgBuilder.cs
index 2eaace50234056..b4654e0c72c9f0 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/StringArgBuilder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/StringArgBuilder.cs
@@ -3,6 +3,7 @@
using System;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Runtime.InteropServices;
@@ -19,6 +20,7 @@ internal StringArgBuilder(Type parameterType)
_isWrapper = parameterType == typeof(BStrWrapper);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal override Expression Marshal(Expression parameter)
{
parameter = base.Marshal(parameter);
@@ -35,6 +37,7 @@ internal override Expression Marshal(Expression parameter)
return parameter;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal override Expression MarshalToRef(Expression parameter)
{
parameter = Marshal(parameter);
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/TypeUtils.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/TypeUtils.cs
index c5221aa6d36c96..6bd081d3784a64 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/TypeUtils.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/TypeUtils.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Diagnostics.CodeAnalysis;
using System.Reflection;
namespace Microsoft.CSharp.RuntimeBinder.ComInterop
@@ -73,6 +74,7 @@ internal static bool IsImplicitlyConvertible(Type source, Type destination)
IsImplicitBoxingConversion(source, destination);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal static bool IsImplicitlyConvertible(Type source, Type destination, bool considerUserDefined)
{
return IsImplicitlyConvertible(source, destination) ||
@@ -80,6 +82,7 @@ internal static bool IsImplicitlyConvertible(Type source, Type destination, bool
}
//CONFORMING
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal static MethodInfo GetUserDefinedCoercionMethod(Type convertFrom, Type convertToType, bool implicitOnly)
{
// check for implicit coercions first
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/UnknownArgBuilder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/UnknownArgBuilder.cs
index 9c0dd4c5c7bcc9..b0c19d50f299b0 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/UnknownArgBuilder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/UnknownArgBuilder.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Runtime.InteropServices;
@@ -17,6 +18,7 @@ internal UnknownArgBuilder(Type parameterType)
_isWrapper = parameterType == typeof(UnknownWrapper);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal override Expression Marshal(Expression parameter)
{
parameter = base.Marshal(parameter);
@@ -33,6 +35,7 @@ internal override Expression Marshal(Expression parameter)
return Helpers.Convert(parameter, typeof(object));
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal override Expression MarshalToRef(Expression parameter)
{
parameter = Marshal(parameter);
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VarEnumSelector.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VarEnumSelector.cs
index 40d36cae21e7f3..6e6535371c82e1 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VarEnumSelector.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VarEnumSelector.cs
@@ -6,6 +6,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.InteropServices;
@@ -30,6 +31,7 @@ internal sealed class VarEnumSelector
private static readonly Dictionary s_comToManagedPrimitiveTypes = CreateComToManagedPrimitiveTypes();
private static readonly IList> s_comPrimitiveTypeFamilies = CreateComPrimitiveTypeFamilies();
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal VarEnumSelector(Type[] explicitArgTypes)
{
VariantBuilders = new VariantBuilder[explicitArgTypes.Length];
@@ -141,6 +143,7 @@ private static IList> CreateComPrimitiveTypeFamilies()
///
/// Get the (one representative type for each) primitive type families that the argument can be converted to
///
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static List GetConversionsToComPrimitiveTypeFamilies(Type argumentType)
{
List compatibleComTypes = new List();
@@ -272,6 +275,7 @@ private static bool TryGetPrimitiveComType(Type argumentType, out VarEnum primit
///
/// Is there a unique primitive type that has the best conversion for the argument
///
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static bool TryGetPrimitiveComTypeViaConversion(Type argumentType, out VarEnum primitiveVarEnum)
{
// Look for a unique type family that the argument can be converted to.
@@ -373,6 +377,7 @@ private VarEnum GetComType(ref Type argumentType)
///
/// Get the COM Variant type that argument should be marshaled as for a call to COM
///
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private VariantBuilder GetVariantBuilder(Type argumentType)
{
//argumentType is coming from MarshalType, null means the dynamic object holds
@@ -419,6 +424,7 @@ private VariantBuilder GetVariantBuilder(Type argumentType)
// This helper is called when we are looking for a ByVal marshalling
// In a ByVal case we can take into account conversions or IConvertible if all other
// attempts to find marshalling type failed
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static ArgBuilder GetByValArgBuilder(Type elementType, ref VarEnum elementVarEnum)
{
// If VT indicates that marshalling type is unknown.
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VariantArgBuilder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VariantArgBuilder.cs
index de0493a771c56a..d2b5b149fe1663 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VariantArgBuilder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VariantArgBuilder.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.InteropServices;
@@ -18,6 +19,7 @@ internal VariantArgBuilder(Type parameterType)
_isWrapper = parameterType == typeof(VariantWrapper);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal override Expression Marshal(Expression parameter)
{
parameter = base.Marshal(parameter);
@@ -34,6 +36,7 @@ internal override Expression Marshal(Expression parameter)
return Helpers.Convert(parameter, typeof(object));
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal override Expression MarshalToRef(Expression parameter)
{
parameter = Marshal(parameter);
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VariantArray.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VariantArray.cs
index 620cc299c083c3..289a0531458459 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VariantArray.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VariantArray.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq.Expressions;
using System.Reflection;
@@ -49,11 +50,19 @@ internal static class VariantArray
// (guarenteed less than 28, in practice 0-2)
private static readonly List s_generatedTypes = new List(0);
+ [DynamicDependency(DynamicallyAccessedMemberTypes.PublicFields, typeof(VariantArray1))]
+ [DynamicDependency(DynamicallyAccessedMemberTypes.PublicFields, typeof(VariantArray2))]
+ [DynamicDependency(DynamicallyAccessedMemberTypes.PublicFields, typeof(VariantArray4))]
+ [DynamicDependency(DynamicallyAccessedMemberTypes.PublicFields, typeof(VariantArray8))]
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "Types are either dynamically created or have dynamic dependency.")]
internal static MemberExpression GetStructField(ParameterExpression variantArray, int field)
{
return Expression.Field(variantArray, "Element" + field);
}
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2055:UnrecognizedReflectionPattern",
+ Justification = "MakeGenericType is called on a dynamically created type that doesn't contain trimming annotations.")]
internal static Type GetStructType(int args)
{
Debug.Assert(args >= 0);
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VariantBuilder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VariantBuilder.cs
index 5d3da6f009c12f..4fdb65bbd1aefb 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VariantBuilder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VariantBuilder.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Runtime.InteropServices;
@@ -28,6 +29,7 @@ internal bool IsByRef
get { return (_targetComType & VarEnum.VT_BYREF) != 0; }
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal Expression InitializeArgumentVariant(MemberExpression variant, Expression parameter)
{
//NOTE: we must remember our variant
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/DynamicDebuggerProxy.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/DynamicDebuggerProxy.cs
index 5f0438a8ecc41d..c04fa1735478e2 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/DynamicDebuggerProxy.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/DynamicDebuggerProxy.cs
@@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Linq;
using System.Linq.Expressions;
@@ -79,6 +80,7 @@ public DynamicProperty(string name, object value)
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.RootHidden)]
internal DynamicProperty[] Items
{
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
get
{
if (results == null || results.Count == 0)
@@ -106,6 +108,7 @@ public DynamicMetaObjectProviderDebugView(object arg)
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
private static readonly ParameterExpression parameter = Expression.Parameter(typeof(object), "debug");
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static object TryEvalBinaryOperators(
T1 arg1,
T2 arg2,
@@ -128,6 +131,7 @@ public static object TryEvalBinaryOperators(
return site.Target(site, arg1, arg2);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static object TryEvalUnaryOperators(T obj, ExpressionType oper, Type accessibilityContext)
{
if (oper == ExpressionType.IsTrue || oper == ExpressionType.IsFalse)
@@ -148,6 +152,7 @@ public static object TryEvalUnaryOperators(T obj, ExpressionType oper, Type a
return site.Target(site, obj);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static K TryEvalCast(T obj, Type type, CSharpBinderFlags kind, Type accessibilityContext)
{
var site = CallSite>.Create(Binder.Convert(kind, type, accessibilityContext));
@@ -198,6 +203,7 @@ private static void CreateDelegateSignatureAndArgumentInfos(
/// Creates a delegate based on type array that describe its signature and invokes it.
///
/// Result of invoking the delegate.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static object CreateDelegateAndInvoke(Type[] delegateSignatureTypes, CallSiteBinder binder, object[] args)
{
Type delegateType = Expression.GetDelegateType(delegateSignatureTypes);
@@ -223,6 +229,7 @@ private static object CreateDelegateAndInvoke(Type[] delegateSignatureTypes, Cal
/// Type that determines context in which method should be called.
/// Generic type arguments if there are any.
/// Result of method invocation.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static object TryEvalMethodVarArgs(
object[] methodArgs,
Type[] argTypes,
@@ -273,6 +280,7 @@ public static object TryEvalMethodVarArgs(
/// Type that determines context in which method should be called.
/// Determines if COM binder should return a callable object.
/// Result of property invocation.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static object TryGetMemberValue(T obj, string propName, Type accessibilityContext, bool isResultIndexed)
{
// In most cases it's ok to use CSharpArgumentInfoFlags.None since target of property call is dynamic.
@@ -300,6 +308,7 @@ public static object TryGetMemberValue(T obj, string propName, Type accessibi
/// Flags describing each argument.
/// Type that determines context in which method should be called.
/// Result of property invocation.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static object TryGetMemberValueVarArgs(
object[] propArgs,
Type[] argTypes,
@@ -333,6 +342,7 @@ public static object TryGetMemberValueVarArgs(
///
/// Type that determines context in which method should be called.
/// Result of property invocation.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static object TrySetMemberValue(
TObject obj,
string propName,
@@ -364,6 +374,7 @@ public static object TrySetMemberValue(
/// Flags describing each argument.
/// Type that determines context in which method should be called.
/// Result of property invocation.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static object TrySetMemberValueVarArgs(
object[] propArgs,
Type[] argTypes,
@@ -417,9 +428,10 @@ internal static object TryGetMemberValue(object obj, string name, bool ignoreExc
#if ENABLECOMBINDER
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
- private static readonly Type ComObjectType = typeof(object).Assembly.GetType("System.__ComObject");
+ private static readonly Type ComObjectType = Type.GetType("System.__ComObject, System.Private.CoreLib");
#endif
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static IList> QueryDynamicObject(object obj)
{
IDynamicMetaObjectProvider ido = obj as IDynamicMetaObjectProvider;
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ExpressionTreeCallRewriter.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ExpressionTreeCallRewriter.cs
index 380d9d1e4053b5..b9f3fab762f382 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ExpressionTreeCallRewriter.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ExpressionTreeCallRewriter.cs
@@ -42,6 +42,7 @@ private ExpressionTreeCallRewriter(Expression[] listOfParameters)
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static Expression Rewrite(ExprBinOp binOp, Expression[] listOfParameters)
{
ExpressionTreeCallRewriter rewriter = new ExpressionTreeCallRewriter(listOfParameters);
@@ -67,6 +68,7 @@ public static Expression Rewrite(ExprBinOp binOp, Expression[] listOfParameters)
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected override Expr VisitSAVE(ExprBinOp pExpr)
{
// Saves should have a LHS that is a CALL to PM_EXPRESSION_PARAMETER
@@ -83,6 +85,7 @@ protected override Expr VisitSAVE(ExprBinOp pExpr)
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected override Expr VisitCALL(ExprCall pExpr)
{
if (pExpr.PredefinedMethod == PREDEFMETH.PM_COUNT)
@@ -209,11 +212,13 @@ protected override Expr VisitCALL(ExprCall pExpr)
// ExpressionTreeRewriter has optimized away identity or up-cast conversions, leaving us with a bare parameter
// access. Just get the expression for that parameter so the lambda produced can be p0 => p0
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected override Expr VisitWRAP(ExprWrap pExpr) => new ExpressionExpr(GetExpression(pExpr));
#region Generators
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr GenerateLambda(ExprCall pExpr)
{
// We always call Lambda(body, arrayinit) where the arrayinit
@@ -235,6 +240,7 @@ private Expr GenerateLambda(ExprCall pExpr)
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expression GenerateCall(ExprCall pExpr)
{
// Our arguments are: object, methodinfo, parameters.
@@ -278,6 +284,7 @@ private Expression GenerateCall(ExprCall pExpr)
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expression GenerateArrayIndex(ExprCall pExpr)
{
// We have two possibilities here - we're either a single index array, in which
@@ -304,6 +311,7 @@ private Expression GenerateArrayIndex(ExprCall pExpr)
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expression GenerateConvert(ExprCall pExpr)
{
PREDEFMETH pm = pExpr.PredefinedMethod;
@@ -373,6 +381,7 @@ private Expression GenerateConvert(ExprCall pExpr)
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expression GenerateProperty(ExprCall pExpr)
{
ExprList list = (ExprList)pExpr.OptionalArguments;
@@ -410,6 +419,7 @@ private Expression GenerateProperty(ExprCall pExpr)
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expression GenerateField(ExprCall pExpr)
{
ExprList list = (ExprList)pExpr.OptionalArguments;
@@ -437,6 +447,7 @@ private Expression GenerateField(ExprCall pExpr)
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expression GenerateInvoke(ExprCall pExpr)
{
ExprList list = (ExprList)pExpr.OptionalArguments;
@@ -448,6 +459,7 @@ private Expression GenerateInvoke(ExprCall pExpr)
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expression GenerateNew(ExprCall pExpr)
{
ExprList list = (ExprList)pExpr.OptionalArguments;
@@ -459,6 +471,7 @@ private Expression GenerateNew(ExprCall pExpr)
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static Expression GenerateConstantType(ExprCall pExpr)
{
ExprList list = (ExprList)pExpr.OptionalArguments;
@@ -469,6 +482,7 @@ private static Expression GenerateConstantType(ExprCall pExpr)
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expression GenerateAssignment(ExprCall pExpr)
{
ExprList list = (ExprList)pExpr.OptionalArguments;
@@ -480,6 +494,7 @@ private Expression GenerateAssignment(ExprCall pExpr)
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expression GenerateBinaryOperator(ExprCall pExpr)
{
ExprList list = (ExprList)pExpr.OptionalArguments;
@@ -542,6 +557,7 @@ private Expression GenerateBinaryOperator(ExprCall pExpr)
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expression GenerateUserDefinedBinaryOperator(ExprCall pExpr)
{
ExprList list = (ExprList)pExpr.OptionalArguments;
@@ -618,6 +634,7 @@ private Expression GenerateUserDefinedBinaryOperator(ExprCall pExpr)
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expression GenerateUnaryOperator(ExprCall pExpr)
{
PREDEFMETH pm = pExpr.PredefinedMethod;
@@ -642,6 +659,7 @@ private Expression GenerateUnaryOperator(ExprCall pExpr)
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expression GenerateUserDefinedUnaryOperator(ExprCall pExpr)
{
PREDEFMETH pm = pExpr.PredefinedMethod;
@@ -673,6 +691,7 @@ private Expression GenerateUserDefinedUnaryOperator(ExprCall pExpr)
#region Helpers
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expression GetExpression(Expr pExpr)
{
if (pExpr is ExprWrap wrap)
@@ -865,6 +884,7 @@ private Expression GetExpression(Expr pExpr)
}
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expression[] GetArgumentsFromArrayInit(ExprArrayInit arrinit)
{
List expressions = new List();
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ICSharpBinder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ICSharpBinder.cs
index dd08d83583fab9..3df4472e94bf94 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ICSharpBinder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ICSharpBinder.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Diagnostics.CodeAnalysis;
using Microsoft.CSharp.RuntimeBinder.Semantics;
namespace Microsoft.CSharp.RuntimeBinder
@@ -16,8 +17,10 @@ internal interface ICSharpBinder
// are only dispatched dynamically when the receiver is dynamic, and hence boxed.
bool IsBinderThatCanHaveRefReceiver { get; }
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
void PopulateSymbolTableWithName(Type callingType, ArgumentObject[] arguments);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
Expr DispatchPayload(RuntimeBinder runtimeBinder, ArgumentObject[] arguments, LocalVariableSymbol[] locals);
BindingFlag BindingFlags { get; }
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/RuntimeBinder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/RuntimeBinder.cs
index 5ddca856693125..ffc141a89d4f73 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/RuntimeBinder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/RuntimeBinder.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Linq.Expressions;
using Microsoft.CSharp.RuntimeBinder.Errors;
@@ -20,6 +21,7 @@ internal readonly struct RuntimeBinder
internal bool IsChecked => _binder.Context.Checked;
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public RuntimeBinder(Type contextType, bool isChecked = false)
{
AggregateSymbol context;
@@ -38,6 +40,7 @@ public RuntimeBinder(Type contextType, bool isChecked = false)
_binder = new ExpressionBinder(new BindingContext(context, isChecked));
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public Expression Bind(ICSharpBinder payload, Expression[] parameters, DynamicMetaObject[] args, out DynamicMetaObject deferredBinding)
{
// The lock is here to protect this instance of the binder from itself
@@ -63,6 +66,7 @@ public Expression Bind(ICSharpBinder payload, Expression[] parameters, DynamicMe
}
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expression BindCore(
ICSharpBinder payload,
Expression[] parameters,
@@ -125,6 +129,7 @@ internal static void EnsureLockIsTaken()
Debug.Assert(System.Threading.Monitor.IsEntered(s_bindLock));
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool DeferBinding(
ICSharpBinder payload,
ArgumentObject[] arguments,
@@ -180,6 +185,7 @@ private bool DeferBinding(
return false;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static Expression CreateExpressionTreeFromResult(Expression[] parameters, Scope pScope, Expr pResult)
{
// (3) - Place the result in a return statement and create the ExprBoundLambda.
@@ -193,6 +199,7 @@ private static Expression CreateExpressionTreeFromResult(Expression[] parameters
return e;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Type GetArgumentType(ICSharpBinder p, CSharpArgumentInfo argInfo, Expression param, DynamicMetaObject arg, int index)
{
Type t = argInfo.UseCompileTimeType ? param.Type : arg.LimitType;
@@ -232,6 +239,7 @@ private Type GetArgumentType(ICSharpBinder p, CSharpArgumentInfo argInfo, Expres
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private ArgumentObject[] CreateArgumentArray(
ICSharpBinder payload,
Expression[] parameters,
@@ -254,6 +262,7 @@ private ArgumentObject[] CreateArgumentArray(
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal static void PopulateSymbolTableWithPayloadInformation(
ICSharpInvokeOrInvokeMemberBinder callOrInvoke, Type callingType, ArgumentObject[] arguments)
{
@@ -292,6 +301,7 @@ internal static void PopulateSymbolTableWithPayloadInformation(
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static void AddConversionsForArguments(ArgumentObject[] arguments)
{
foreach (ArgumentObject arg in arguments)
@@ -302,6 +312,7 @@ private static void AddConversionsForArguments(ArgumentObject[] arguments)
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal ExprWithArgs DispatchPayload(ICSharpInvokeOrInvokeMemberBinder payload, ArgumentObject[] arguments, LocalVariableSymbol[] locals) =>
BindCall(payload, CreateCallingObjectForCall(payload, arguments, locals), arguments, locals);
@@ -312,6 +323,7 @@ internal ExprWithArgs DispatchPayload(ICSharpInvokeOrInvokeMemberBinder payload,
// we have a call off of a struct for example. If thats the case, don't treat the
// local as a ref type.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static LocalVariableSymbol[] PopulateLocalScope(
ICSharpBinder payload,
Scope pScope,
@@ -355,6 +367,7 @@ private static LocalVariableSymbol[] PopulateLocalScope(
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static ExprBoundLambda GenerateBoundLambda(Scope pScope, Expr call)
{
// We don't actually need the real delegate type here - we just need SOME delegate type.
@@ -367,6 +380,7 @@ private static ExprBoundLambda GenerateBoundLambda(Scope pScope, Expr call)
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr CreateLocal(Type type, bool isOut, LocalVariableSymbol local)
{
CType ctype;
@@ -393,6 +407,7 @@ private Expr CreateLocal(Type type, bool isOut, LocalVariableSymbol local)
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal Expr CreateArgumentListEXPR(
ArgumentObject[] arguments,
LocalVariableSymbol[] locals,
@@ -426,6 +441,7 @@ internal Expr CreateArgumentListEXPR(
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr CreateArgumentEXPR(ArgumentObject argument, LocalVariableSymbol local)
{
Expr arg;
@@ -495,6 +511,7 @@ private Expr CreateArgumentEXPR(ArgumentObject argument, LocalVariableSymbol loc
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static ExprMemberGroup CreateMemberGroupExpr(
string Name,
Type[] typeArguments,
@@ -597,6 +614,7 @@ private static ExprMemberGroup CreateMemberGroupExpr(
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr CreateProperty(
SymWithType swt,
Expr callingObject,
@@ -616,6 +634,7 @@ private Expr CreateProperty(
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private ExprWithArgs CreateIndexer(SymWithType swt, Expr callingObject, Expr arguments, BindingFlag bindFlags)
{
IndexerSymbol index = swt.Sym as IndexerSymbol;
@@ -627,6 +646,7 @@ private ExprWithArgs CreateIndexer(SymWithType swt, Expr callingObject, Expr arg
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr CreateArray(Expr callingObject, Expr optionalIndexerArguments)
{
return _binder.BindArrayIndexCore(callingObject, optionalIndexerArguments);
@@ -634,6 +654,7 @@ private Expr CreateArray(Expr callingObject, Expr optionalIndexerArguments)
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr CreateField(
SymWithType swt,
Expr callingObject)
@@ -657,6 +678,7 @@ private Expr CreateField(
#region Calls
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr CreateCallingObjectForCall(
ICSharpInvokeOrInvokeMemberBinder payload,
ArgumentObject[] arguments,
@@ -695,6 +717,7 @@ private Expr CreateCallingObjectForCall(
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private ExprWithArgs BindCall(
ICSharpInvokeOrInvokeMemberBinder payload,
Expr callingObject,
@@ -812,6 +835,7 @@ private static void CheckForConditionalMethodError(ExprCall call)
}
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private void ReorderArgumentsForNamedAndOptional(Expr callingObject, ExprWithArgs result)
{
Expr arguments = result.OptionalArguments;
@@ -912,6 +936,7 @@ private Expr StripNamedArguments(Expr pArg)
#region UnaryOperators
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal Expr BindUnaryOperation(
CSharpUnaryOperationBinder payload,
ArgumentObject[] arguments,
@@ -951,6 +976,7 @@ internal Expr BindUnaryOperation(
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal Expr BindBinaryOperation(
CSharpBinaryOperationBinder payload,
ArgumentObject[] arguments,
@@ -1073,6 +1099,7 @@ private static OperatorKind GetOperatorKind(ExpressionType p, bool bIsLogical)
#region Properties
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal Expr BindProperty(
ICSharpBinder payload,
ArgumentObject argument,
@@ -1156,6 +1183,7 @@ internal Expr BindProperty(
#region Casts
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal Expr BindImplicitConversion(
ArgumentObject[] arguments,
Type returnType,
@@ -1194,6 +1222,7 @@ internal Expr BindImplicitConversion(
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal Expr BindExplicitConversion(ArgumentObject[] arguments, Type returnType, LocalVariableSymbol[] locals)
{
Debug.Assert(arguments.Length == 1);
@@ -1213,6 +1242,7 @@ internal Expr BindExplicitConversion(ArgumentObject[] arguments, Type returnType
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal Expr BindAssignment(
ICSharpBinder payload,
ArgumentObject[] arguments,
@@ -1252,6 +1282,7 @@ internal Expr BindAssignment(
#region Events
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal Expr BindIsEvent(
CSharpIsEventBinder binder,
ArgumentObject[] arguments,
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/RuntimeBinderExtensions.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/RuntimeBinderExtensions.cs
index 1323e2c24bb29f..27731058c76c7c 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/RuntimeBinderExtensions.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/RuntimeBinderExtensions.cs
@@ -3,6 +3,7 @@
using System;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Reflection;
@@ -315,6 +316,7 @@ public static bool HasSameMetadataDefinitionAs(this MemberInfo mi1, MemberInfo m
return mi1.Module.Equals(mi2.Module) && s_MemberEquivalence(mi1, mi2);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static string GetIndexerName(this Type type)
{
Debug.Assert(type != null);
@@ -334,6 +336,7 @@ public static string GetIndexerName(this Type type)
return name;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static string GetTypeIndexerName(Type type)
{
Debug.Assert(type != null);
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/BinOpSig.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/BinOpSig.cs
index 9874eaef5647c2..2f9825d586c27b 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/BinOpSig.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/BinOpSig.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using Microsoft.CSharp.RuntimeBinder.Syntax;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
@@ -74,6 +75,7 @@ public BinOpFullSig(CType type1, CType type2, PfnBindBinOp pfn, OpSigFlags grfos
Set the values of the BinOpFullSig from the given BinOpSig. The ExpressionBinder is needed to get
the predefined types. Returns true iff the predef types are found.
***************************************************************************************************/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public BinOpFullSig(ExpressionBinder fnc, BinOpSig bos)
{
this.pt1 = bos.pt1;
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Binding/Better.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Binding/Better.cs
index 22e754f4e00ca1..c064a0f4170d82 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Binding/Better.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Binding/Better.cs
@@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using Microsoft.CSharp.RuntimeBinder.Syntax;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
@@ -275,6 +276,7 @@ private static TypeArray RearrangeNamedArguments(TypeArray pta, MethPropWithInst
//
// Returns Left if m1 is better, Right if m2 is better, or Neither/Same
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private BetterType WhichMethodIsBetter(
CandidateFunctionMember node1,
CandidateFunctionMember node2,
@@ -392,6 +394,7 @@ private BetterType WhichMethodIsBetter(
return betterMethod;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private BetterType WhichConversionIsBetter(CType argType, CType p1, CType p2)
{
Debug.Assert(argType != null);
@@ -475,6 +478,7 @@ private BetterType WhichConversionIsBetter(CType argType, CType p1, CType p2)
////////////////////////////////////////////////////////////////////////////////
// Determine best method for overload resolution. Returns null if no best
// method, in which case two tying methods are returned for error reporting.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private CandidateFunctionMember FindBestMethod(
List list,
CType pTypeThrough,
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Conversion.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Conversion.cs
index cdee4bc4154f92..cb2dd20c9bce04 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Conversion.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Conversion.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using Microsoft.CSharp.RuntimeBinder.Errors;
using Microsoft.CSharp.RuntimeBinder.Syntax;
@@ -208,6 +209,8 @@ private static bool isUserDefinedConversion(PredefinedType ptSrc, PredefinedType
};
#if DEBUG
private static volatile bool s_fCheckedBetter;
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private void CheckBetterTable()
{
if (s_fCheckedBetter)
@@ -235,6 +238,7 @@ private void CheckBetterTable()
}
#endif // DEBUG
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private BetterType WhichSimpleConversionIsBetter(PredefinedType pt1, PredefinedType pt2)
{
#if DEBUG
@@ -252,6 +256,7 @@ Determined which conversion to a predefined type is better relative to a given t
assumed that the given type is implicitly convertible to both of the predefined types
(possibly via a user defined conversion, method group conversion, etc).
***************************************************************************************************/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private BetterType WhichTypeIsBetter(PredefinedType pt1, PredefinedType pt2, CType typeGiven)
{
if (pt1 == pt2)
@@ -287,6 +292,7 @@ Determined which conversion is better relative to a given type. It is assumed th
(or its associated expression) is implicitly convertible to both of the types (possibly via
a user defined conversion, method group conversion, etc).
***************************************************************************************************/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private BetterType WhichTypeIsBetter(CType type1, CType type2, CType typeGiven)
{
Debug.Assert(type1 != null && type2 != null);
@@ -329,20 +335,26 @@ private BetterType WhichTypeIsBetter(CType type1, CType type2, CType typeGiven)
}
// returns true if an implicit conversion exists from source type to dest type. flags is an optional parameter.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool canConvert(CType src, CType dest, CONVERTTYPE flags) => BindImplicitConversion(null, src, dest, flags);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public bool canConvert(CType src, CType dest) => canConvert(src, dest, 0);
// returns true if a implicit conversion exists from source expr to dest type. flags is an optional parameter.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool canConvert(Expr expr, CType dest) => canConvert(expr, dest, 0);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool canConvert(Expr expr, CType dest, CONVERTTYPE flags) =>
BindImplicitConversion(expr, expr.Type, dest, flags);
// performs an implicit conversion if it's possible. otherwise displays an error. flags is an optional parameter.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr mustConvertCore(Expr expr, CType destExpr) => mustConvertCore(expr, destExpr, 0);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr mustConvertCore(Expr expr, CType dest, CONVERTTYPE flags)
{
Debug.Assert(!(expr is ExprMemberGroup));
@@ -390,11 +402,13 @@ private Expr mustConvertCore(Expr expr, CType dest, CONVERTTYPE flags)
// If the conversion is possible it will modify an Anonymous Method expr thus changing results of
// future conversions. It will also produce possible binding errors for method groups.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public Expr tryConvert(Expr expr, CType dest)
{
return tryConvert(expr, dest, 0);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr tryConvert(Expr expr, CType dest, CONVERTTYPE flags)
{
if (BindImplicitConversion(expr, expr.Type, dest, out Expr exprResult, flags))
@@ -408,8 +422,10 @@ private Expr tryConvert(Expr expr, CType dest, CONVERTTYPE flags)
return null;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public Expr mustConvert(Expr expr, CType dest) => mustConvert(expr, dest, (CONVERTTYPE)0);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr mustConvert(Expr expr, CType dest, CONVERTTYPE flags) => mustConvertCore(expr, dest, flags);
// public bool canCast(Expr expr, CType dest)
@@ -419,6 +435,7 @@ private Expr tryConvert(Expr expr, CType dest, CONVERTTYPE flags)
// }
// performs an explicit conversion if its possible. otherwise displays an error.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr mustCastCore(Expr expr, CType dest, CONVERTTYPE flags)
{
Debug.Assert(!(expr is ExprMemberGroup));
@@ -501,21 +518,28 @@ private static RuntimeBinderException CantConvert(Expr expr, CType dest)
return ErrorHandling.Error(ErrorCode.ERR_NoExplicitConv, new ErrArg(expr.Type, ErrArgFlags.Unique), new ErrArg(dest, ErrArgFlags.Unique));
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public Expr mustCast(Expr expr, CType dest) => mustCast(expr, dest, 0);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public Expr mustCast(Expr expr, CType dest, CONVERTTYPE flags) => mustCastCore(expr, dest, flags);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr MustCastInUncheckedContext(Expr expr, CType dest, CONVERTTYPE flags) =>
new ExpressionBinder(new BindingContext(Context)).mustCast(expr, dest, flags);
// returns true if an explicit conversion exists from source type to dest type. flags is an optional parameter.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool canCast(CType src, CType dest, CONVERTTYPE flags) => BindExplicitConversion(null, src, dest, flags);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool BindImplicitConversion(Expr pSourceExpr, CType pSourceType, CType destinationType, CONVERTTYPE flags)
{
ImplicitConversion binder = new ImplicitConversion(this, pSourceExpr, pSourceType, destinationType, false, flags);
return binder.Bind();
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool BindImplicitConversion(Expr pSourceExpr, CType pSourceType, CType destinationType, out Expr ppDestinationExpr, CONVERTTYPE flags)
{
ImplicitConversion binder = new ImplicitConversion(this, pSourceExpr, pSourceType, destinationType, true, flags);
@@ -524,6 +548,7 @@ private bool BindImplicitConversion(Expr pSourceExpr, CType pSourceType, CType d
return result;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool BindImplicitConversion(Expr pSourceExpr, CType pSourceType, CType destinationType, bool needsExprDest, out Expr ppDestinationExpr, CONVERTTYPE flags)
{
ImplicitConversion binder = new ImplicitConversion(this, pSourceExpr, pSourceType, destinationType, needsExprDest, flags);
@@ -532,6 +557,7 @@ private bool BindImplicitConversion(Expr pSourceExpr, CType pSourceType, CType d
return result;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool BindExplicitConversion(Expr pSourceExpr, CType pSourceType, CType destinationType, bool needsExprDest, out Expr ppDestinationExpr, CONVERTTYPE flags)
{
ExplicitConversion binder = new ExplicitConversion(this, pSourceExpr, pSourceType, destinationType, needsExprDest, flags);
@@ -540,6 +566,7 @@ private bool BindExplicitConversion(Expr pSourceExpr, CType pSourceType, CType d
return result;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool BindExplicitConversion(Expr pSourceExpr, CType pSourceType, CType destinationType, out Expr ppDestinationExpr, CONVERTTYPE flags)
{
ExplicitConversion binder = new ExplicitConversion(this, pSourceExpr, pSourceType, destinationType, true, flags);
@@ -548,6 +575,7 @@ private bool BindExplicitConversion(Expr pSourceExpr, CType pSourceType, CType d
return result;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool BindExplicitConversion(Expr pSourceExpr, CType pSourceType, CType destinationType, CONVERTTYPE flags)
{
ExplicitConversion binder = new ExplicitConversion(this, pSourceExpr, pSourceType, destinationType, false, flags);
@@ -594,6 +622,7 @@ or output of the conversion is not a nullable.
A conversion that needs fewer lifts is better than one that requires more (if the lifted
forms have identical signatures).
***************************************************************************************************/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool bindUserDefinedConversion(Expr exprSrc, CType typeSrc, CType typeDst, bool needExprDest, out Expr pexprDst, bool fImplicitOnly)
{
pexprDst = null;
@@ -1060,12 +1089,14 @@ private static void MarkAsIntermediateConversion(Expr pExpr)
}
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr BindUDConversionCore(Expr pFrom, CType pTypeFrom, CType pTypeTo, CType pTypeDestination, MethWithInst mwiBest)
{
Expr ppTransformedArgument;
return BindUDConversionCore(pFrom, pTypeFrom, pTypeTo, pTypeDestination, mwiBest, out ppTransformedArgument);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr BindUDConversionCore(Expr pFrom, CType pTypeFrom, CType pTypeTo, CType pTypeDestination, MethWithInst mwiBest, out Expr ppTransformedArgument)
{
Expr pTransformedArgument = mustCastCore(pFrom, pTypeFrom, CONVERTTYPE.NOUDC);
@@ -1081,6 +1112,7 @@ private Expr BindUDConversionCore(Expr pFrom, CType pTypeFrom, CType pTypeTo, CT
/*
* Fold a constant cast. Returns true if the constant could be folded.
*/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private ConstCastResult bindConstantCast(Expr exprSrc, CType typeDest, bool needExprDest, out Expr pexprDest, bool explicitConversion)
{
pexprDest = null;
@@ -1291,6 +1323,7 @@ is closer.
The return value is -1 if type1 is closer, +1 if type2 is closer and 0 if neither is closer.
***************************************************************************************************/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private int CompareSrcTypesBased(CType type1, bool fImplicit1, CType type2, bool fImplicit2)
{
Debug.Assert(type1 != type2);
@@ -1324,6 +1357,7 @@ is closer.
The return value is -1 if type1 is closer, +1 if type2 is closer and 0 if neither is closer.
***************************************************************************************************/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private int CompareDstTypesBased(CType type1, bool fImplicit1, CType type2, bool fImplicit2)
{
Debug.Assert(type1 != type2);
@@ -1335,9 +1369,11 @@ private int CompareDstTypesBased(CType type1, bool fImplicit1, CType type2, bool
return 0;
return (fImplicit1 == fCon1) ? +1 : -1;
}
+
/*
* Bind a constant cast to or from decimal. Return null if cast can't be done.
*/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static Expr BindDecimalConstCast(CType destType, CType srcType, ExprConstant src)
{
CType typeDecimal = SymbolLoader.GetPredefindType(PredefinedType.PT_DECIMAL);
@@ -1447,6 +1483,7 @@ private static Expr BindDecimalConstCast(CType destType, CType srcType, ExprCons
return null;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool CanExplicitConversionBeBoundInUncheckedContext(Expr exprSrc, CType typeSrc, CType typeDest, CONVERTTYPE flags)
{
Debug.Assert(typeDest != null);
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Conversions.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Conversions.cs
index 670bda77d40f8c..8e6519fbfffca3 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Conversions.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Conversions.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using Microsoft.CSharp.RuntimeBinder.Syntax;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
@@ -23,6 +24,7 @@ Determine whether there is an implicit reference conversion from typeSrc to type
when the source is a reference type and the destination is a base type of the source. Note
that typeDst.IsRefType() may still return false (when both are type parameters).
***************************************************************************************************/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static bool FImpRefConv(CType typeSrc, CType typeDst) =>
typeSrc.IsReferenceType && SymbolLoader.HasIdentityOrImplicitReferenceConversion(typeSrc, typeDst);
@@ -70,6 +72,7 @@ src to dst.
The latter two cases can happen with type variables even though the other type variable is not
a reference type.
***************************************************************************************************/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static bool FExpRefConv(CType typeSrc, CType typeDst)
{
Debug.Assert(typeSrc != null);
@@ -215,9 +218,11 @@ o If type parameter Xi is declared to be covariant ("out") then Si must be conve
o If type parameter Xi is declared to be contravariant ("in") then either Si must be identical to Ti,
or Si and Ti must both be reference types.
***************************************************************************************************/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static bool HasGenericDelegateExplicitReferenceConversion(CType source, CType target) =>
target is AggregateType aggTarget && HasGenericDelegateExplicitReferenceConversion(source, aggTarget);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static bool HasGenericDelegateExplicitReferenceConversion(CType pSource, AggregateType pTarget)
{
if (!(pSource is AggregateType aggSrc) ||
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExplicitConversion.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExplicitConversion.cs
index f51d12b4e9a517..620206fb6d99fa 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExplicitConversion.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExplicitConversion.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using Microsoft.CSharp.RuntimeBinder.Syntax;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
@@ -65,6 +66,7 @@ public ExplicitConversion(ExpressionBinder binder, Expr exprSrc, CType typeSrc,
* logic is only concerned with conversions that can be made explicitly, but
* not implicitly.
*/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public bool Bind()
{
// To test for a standard conversion, call canConvert(exprSrc, typeDest, STANDARDANDCONVERTTYPE.NOUDC) and
@@ -181,6 +183,7 @@ public bool Bind()
return false;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool bindExplicitConversionFromNub()
{
Debug.Assert(_typeSrc != null);
@@ -219,6 +222,7 @@ private bool bindExplicitConversionFromNub()
return false;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool bindExplicitConversionFromArrayToIList()
{
// 13.2.2
@@ -261,6 +265,7 @@ private bool bindExplicitConversionFromArrayToIList()
return true;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool bindExplicitConversionFromIListToArray(ArrayType arrayDest)
{
// 13.2.2
@@ -301,6 +306,7 @@ private bool bindExplicitConversionFromIListToArray(ArrayType arrayDest)
return true;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool bindExplicitConversionFromArrayToArray(ArrayType arraySrc, ArrayType arrayDest)
{
// 13.2.2
@@ -333,6 +339,7 @@ private bool bindExplicitConversionFromArrayToArray(ArrayType arraySrc, ArrayTyp
return false;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool bindExplicitConversionToArray(ArrayType arrayDest)
{
Debug.Assert(_typeSrc != null);
@@ -363,6 +370,7 @@ private bool bindExplicitConversionToArray(ArrayType arrayDest)
return false;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool bindExplicitConversionToPointer()
{
// 27.4 Pointer conversions
@@ -398,6 +406,7 @@ private bool bindExplicitConversionToPointer()
// participating enum-type as the underlying type of that enum-type, and then performing
// an implicit or explicit numeric conversion between the resulting types.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private AggCastResult bindExplicitConversionFromEnumToAggregate(AggregateType aggTypeDest)
{
Debug.Assert(_typeSrc != null);
@@ -440,6 +449,7 @@ private AggCastResult bindExplicitConversionFromEnumToAggregate(AggregateType ag
return AggCastResult.Success;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private AggCastResult bindExplicitConversionFromDecimalToEnum(AggregateType aggTypeDest)
{
Debug.Assert(_typeSrc != null);
@@ -481,6 +491,7 @@ private AggCastResult bindExplicitConversionFromDecimalToEnum(AggregateType aggT
return bIsConversionOK ? AggCastResult.Success : AggCastResult.Failure;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private AggCastResult bindExplicitConversionFromEnumToDecimal(AggregateType aggTypeDest)
{
Debug.Assert(_typeSrc != null);
@@ -534,6 +545,7 @@ private AggCastResult bindExplicitConversionFromEnumToDecimal(AggregateType aggT
return AggCastResult.Success;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private AggCastResult bindExplicitConversionToEnum(AggregateType aggTypeDest)
{
Debug.Assert(_typeSrc != null);
@@ -579,6 +591,7 @@ private AggCastResult bindExplicitConversionToEnum(AggregateType aggTypeDest)
return AggCastResult.Failure;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private AggCastResult bindExplicitConversionBetweenSimpleTypes(AggregateType aggTypeDest)
{
// 13.2.1
@@ -647,6 +660,7 @@ private AggCastResult bindExplicitConversionBetweenSimpleTypes(AggregateType agg
return bConversionOk ? AggCastResult.Success : AggCastResult.Failure;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private AggCastResult bindExplicitConversionBetweenAggregates(AggregateType aggTypeDest)
{
// 13.2.3
@@ -698,6 +712,7 @@ private AggCastResult bindExplicitConversionBetweenAggregates(AggregateType aggT
return AggCastResult.Failure;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private AggCastResult bindExplicitConversionFromPointerToInt(AggregateType aggTypeDest)
{
// 27.4 Pointer conversions
@@ -715,6 +730,7 @@ private AggCastResult bindExplicitConversionFromPointerToInt(AggregateType aggTy
return AggCastResult.Success;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private AggCastResult bindExplicitConversionToAggregate(AggregateType aggTypeDest)
{
Debug.Assert(_typeSrc != null);
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExprFactory.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExprFactory.cs
index 1d83a5c20147a9..a9eb6ee419931b 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExprFactory.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExprFactory.cs
@@ -3,6 +3,7 @@
using System;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using Microsoft.CSharp.RuntimeBinder.Syntax;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
@@ -32,46 +33,61 @@ public static ExprMemberGroup CreateMemGroup(Expr obj, MethPropWithInst method)
obj, new CMemberLookupResults(TypeArray.Allocate((CType)method.GetType()), name));
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static ExprUserDefinedConversion CreateUserDefinedConversion(Expr arg, Expr call, MethWithInst method) =>
new ExprUserDefinedConversion(arg, call, method);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static ExprCast CreateCast(CType type, Expr argument) => CreateCast(0, type, argument);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static ExprCast CreateCast(EXPRFLAG flags, CType type, Expr argument) => new ExprCast(flags, type, argument);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static ExprLocal CreateLocal(LocalVariableSymbol local) => new ExprLocal(local);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static ExprBoundLambda CreateAnonymousMethod(AggregateType delegateType, Scope argumentScope, Expr expression) =>
new ExprBoundLambda(delegateType, argumentScope, expression);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static ExprMethodInfo CreateMethodInfo(MethPropWithInst mwi) =>
CreateMethodInfo(mwi.Meth(), mwi.GetType(), mwi.TypeArgs);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static ExprMethodInfo CreateMethodInfo(MethodSymbol method, AggregateType methodType, TypeArray methodParameters) =>
new ExprMethodInfo(
TypeManager.GetPredefAgg(method.IsConstructor() ? PredefinedType.PT_CONSTRUCTORINFO : PredefinedType.PT_METHODINFO).getThisType(),
method, methodType, methodParameters);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static ExprPropertyInfo CreatePropertyInfo(PropertySymbol prop, AggregateType propertyType) =>
new ExprPropertyInfo(TypeManager.GetPredefAgg(PredefinedType.PT_PROPERTYINFO).getThisType(), prop, propertyType);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static ExprFieldInfo CreateFieldInfo(FieldSymbol field, AggregateType fieldType) =>
new ExprFieldInfo(field, fieldType, TypeManager.GetPredefAgg(PredefinedType.PT_FIELDINFO).getThisType());
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static ExprTypeOf CreateTypeOf(CType sourceType) =>
new ExprTypeOf(TypeManager.GetPredefAgg(PredefinedType.PT_TYPE).getThisType(), sourceType);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static ExprUserLogicalOp CreateUserLogOp(CType type, Expr trueFalseCall, ExprCall operatorCall) =>
new ExprUserLogicalOp(type, trueFalseCall, operatorCall);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static ExprConcat CreateConcat(Expr first, Expr second) => new ExprConcat(first, second);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static ExprConstant CreateStringConstant(string str) =>
CreateConstant(TypeManager.GetPredefAgg(PredefinedType.PT_STRING).getThisType(), ConstVal.Get(str));
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static ExprMultiGet CreateMultiGet(EXPRFLAG flags, CType type, ExprMulti multi) =>
new ExprMultiGet(type, flags, multi);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static ExprMulti CreateMulti(EXPRFLAG flags, CType type, Expr left, Expr op) =>
new ExprMulti(type, flags, left, op);
@@ -82,7 +98,7 @@ public static ExprMulti CreateMulti(EXPRFLAG flags, CType type, Expr left, Expr
// type - Non-null
//
// This returns a null for reference types and an EXPRZEROINIT for all others.
-
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static Expr CreateZeroInit(CType type)
{
Debug.Assert(type != null);
@@ -122,9 +138,11 @@ public static Expr CreateZeroInit(CType type)
public static ExprConstant CreateConstant(CType type, ConstVal constVal) => new ExprConstant(type, constVal);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static ExprConstant CreateIntegerConstant(int x) =>
CreateConstant(TypeManager.GetPredefAgg(PredefinedType.PT_INT).getThisType(), ConstVal.Get(x));
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static ExprConstant CreateBoolConstant(bool b) =>
CreateConstant(TypeManager.GetPredefAgg(PredefinedType.PT_BOOL).getThisType(), ConstVal.Get(b));
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExpressionBinder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExpressionBinder.cs
index 9af97dddaf3ad2..f0a34542abef79 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExpressionBinder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExpressionBinder.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using Microsoft.CSharp.RuntimeBinder.Errors;
using Microsoft.CSharp.RuntimeBinder.Syntax;
@@ -268,6 +269,7 @@ public ExpressionBinder(BindingContext context)
Context = context;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static AggregateType GetPredefindType(PredefinedType pt)
{
Debug.Assert(pt != PredefinedType.PT_VOID); // use getVoidType()
@@ -275,12 +277,14 @@ private static AggregateType GetPredefindType(PredefinedType pt)
return SymbolLoader.GetPredefindType(pt);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr GenerateAssignmentConversion(Expr op1, Expr op2, bool allowExplicit) =>
allowExplicit ? mustCastCore(op2, op1.Type, 0) : mustConvertCore(op2, op1.Type);
////////////////////////////////////////////////////////////////////////////////
// Bind the simple assignment operator =.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public Expr BindAssignment(Expr op1, Expr op2, bool allowExplicit)
{
Debug.Assert(op1 is ExprCast
@@ -295,6 +299,7 @@ public Expr BindAssignment(Expr op1, Expr op2, bool allowExplicit)
return GenerateOptimizedAssignment(op1, op2);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal Expr BindArrayIndexCore(Expr pOp1, Expr pOp2)
{
CType pIntType = GetPredefindType(PredefinedType.PT_INT);
@@ -311,10 +316,10 @@ internal Expr BindArrayIndexCore(Expr pOp1, Expr pOp2)
Expr transformedIndices = pOp2.Map(
x =>
{
- Expr pTemp = binder.mustConvert(x, pDestType);
+ Expr pTemp = binder.MustConvertWithSuppressedMessage(x, pDestType);
return pDestType == pIntType
? pTemp
- : ExprFactory.CreateCast(EXPRFLAG.EXF_INDEXEXPR, pDestType, pTemp);
+ : ExprFactoryCreateCastWithSuppressedMessage(EXPRFLAG.EXF_INDEXEXPR, pDestType, pTemp);
});
// Allocate a new expression, the type is the element type of the array.
@@ -322,11 +327,23 @@ internal Expr BindArrayIndexCore(Expr pOp1, Expr pOp2)
return ExprFactory.CreateArrayIndex(elementType, pOp1, transformedIndices);
}
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "Workarounds https://github.com/mono/linker/issues/1416. All usages are marked as unsafe.")]
+ private Expr MustConvertWithSuppressedMessage(Expr x, CType pDestType)
+ => mustConvert(x, pDestType);
+
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "Workarounds https://github.com/mono/linker/issues/1416. All usages are marked as unsafe.")]
+ private static ExprCast ExprFactoryCreateCastWithSuppressedMessage(EXPRFLAG flags, CType type, Expr argument)
+ => ExprFactory.CreateCast(flags, type, argument);
+
////////////////////////////////////////////////////////////////////////////////
// Create a cast node with the given expression flags.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private void bindSimpleCast(Expr exprSrc, CType typeDest, out Expr pexprDest) =>
bindSimpleCast(exprSrc, typeDest, out pexprDest, 0);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private void bindSimpleCast(Expr exprSrc, CType typeDest, out Expr pexprDest, EXPRFLAG exprFlags)
{
Debug.Assert(typeDest != null);
@@ -369,6 +386,7 @@ private void bindSimpleCast(Expr exprSrc, CType typeDest, out Expr pexprDest, EX
// args - arguments
// exprFlags - Flags to put on the generated expr
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private ExprCall BindToMethod(MethWithInst mwi, Expr pArguments, ExprMemberGroup pMemGroup, MemLookFlags flags)
{
Debug.Assert(mwi.Sym is MethodSymbol && (!mwi.Meth().isOverride || mwi.Meth().isHideByName));
@@ -413,6 +431,7 @@ private ExprCall BindToMethod(MethWithInst mwi, Expr pArguments, ExprMemberGroup
// Construct the Expr node which corresponds to a field expression
// for a given field and pObject pointer.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal Expr BindToField(Expr pOptionalObject, FieldWithType fwt, BindingFlag bindFlags)
{
Debug.Assert(fwt.GetType() != null && fwt.Field().getClass() == fwt.GetType().OwningAggregate);
@@ -438,6 +457,7 @@ internal Expr BindToField(Expr pOptionalObject, FieldWithType fwt, BindingFlag b
////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal ExprProperty BindToProperty(Expr pObject, PropWithType pwt, BindingFlag bindFlags, Expr args, ExprMemberGroup pMemGroup)
{
Debug.Assert(pwt.Sym is PropertySymbol &&
@@ -513,6 +533,7 @@ internal ExprProperty BindToProperty(Expr pObject, PropWithType pwt, BindingFlag
return result;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal Expr bindUDUnop(ExpressionKind ek, Expr arg)
{
Name pName = ExpressionKindName(ek);
@@ -627,6 +648,7 @@ internal Expr bindUDUnop(ExpressionKind ek, Expr arg)
return ExprFactory.CreateUserDefinedUnaryOperator(ek, call.Type, arg, call, pmethBest.mpwi);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private ExprCall BindLiftedUDUnop(Expr arg, CType typeArg, MethPropWithInst mpwi)
{
CType typeRaw = typeArg.StripNubs();
@@ -655,6 +677,7 @@ private ExprCall BindLiftedUDUnop(Expr arg, CType typeArg, MethPropWithInst mpwi
return call;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private ExprCall BindUDUnopCall(Expr arg, CType typeArg, MethPropWithInst mpwi)
{
CType typeRet = TypeManager.SubstType(mpwi.Meth().RetType, mpwi.GetType());
@@ -669,6 +692,7 @@ private ExprCall BindUDUnopCall(Expr arg, CType typeArg, MethPropWithInst mpwi)
////////////////////////////////////////////////////////////////////////////////
// Given a method group or indexer group, bind it to the arguments for an
// invocation.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private GroupToArgsBinderResult BindMethodGroupToArgumentsCore(BindingFlag bindFlags, ExprMemberGroup grp, Expr args, int carg, NamedArgumentsKind namedArgumentsKind)
{
ArgInfos pargInfo = new ArgInfos { carg = carg };
@@ -686,6 +710,7 @@ private GroupToArgsBinderResult BindMethodGroupToArgumentsCore(BindingFlag bindF
////////////////////////////////////////////////////////////////////////////////
// Given a method group or indexer group, bind it to the arguments for an
// invocation.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal ExprWithArgs BindMethodGroupToArguments(BindingFlag bindFlags, ExprMemberGroup grp, Expr args)
{
Debug.Assert(grp.SymKind == SYMKIND.SK_MethodSymbol || grp.SymKind == SYMKIND.SK_PropertySymbol && ((grp.Flags & EXPRFLAG.EXF_INDEXER) != 0));
@@ -792,6 +817,7 @@ private static ErrorCode GetStandardLvalueError(CheckLvalueKind kind)
: ErrorCode.ERR_AssgLvalueExpected;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private void CheckLvalueProp(ExprProperty prop)
{
Debug.Assert(prop != null);
@@ -808,6 +834,7 @@ private void CheckLvalueProp(ExprProperty prop)
CheckPropertyAccess(prop.MethWithTypeSet, prop.PropWithTypeSlot, type);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private void CheckPropertyAccess(MethWithType mwt, PropWithType pwtSlot, CType type)
{
switch (CSemanticChecker.CheckAccess2(mwt.Meth(), mwt.GetType(), ContextForMemberLookup, type))
@@ -822,6 +849,7 @@ private void CheckPropertyAccess(MethWithType mwt, PropWithType pwtSlot, CType t
////////////////////////////////////////////////////////////////////////////////
// A false return means not to process the expr any further - it's totally out
// of place. For example - a method group or an anonymous method.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private void CheckLvalue(Expr expr, CheckLvalueKind kind)
{
if (expr.isLvalue())
@@ -913,6 +941,7 @@ private static void PostBindProperty(PropWithType pwt, out MethWithType pmwtGet,
}
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr AdjustMemberObject(SymWithType swt, Expr pObject)
{
// Assert that the type is present and is an instantiation of the member's parent.
@@ -1029,6 +1058,7 @@ private static void AssertObjectIsLvalue(Expr pObject)
);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private void verifyMethodArgs(ExprWithArgs call, CType callingObjectType)
{
Debug.Assert(call != null);
@@ -1041,6 +1071,7 @@ private void verifyMethodArgs(ExprWithArgs call, CType callingObjectType)
call.OptionalArguments = newArgs;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private void AdjustCallArgumentsForParams(CType callingObjectType, CType type, MethodOrPropertySymbol mp, TypeArray pTypeArgs, Expr argsPtr, out Expr newArgs)
{
Debug.Assert(mp != null);
@@ -1252,6 +1283,7 @@ private void AdjustCallArgumentsForParams(CType callingObjectType, CType type, M
PredefinedType.PT_ULONG
};
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal CType ChooseArrayIndexType(Expr args)
{
// first, select the allowable types
@@ -1373,11 +1405,13 @@ private static bool IsConvInTable(List convTable, MethodSymbol meth,
////////////////////////////////////////////////////////////////////////////////
// Check to see if an integral constant is within range of a integral
// destination type.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static bool isConstantInRange(ExprConstant exprSrc, CType typeDest)
{
return isConstantInRange(exprSrc, typeDest, false);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static bool isConstantInRange(ExprConstant exprSrc, CType typeDest, bool realsOk)
{
FUNDTYPE ftSrc = exprSrc.Type.FundamentalType;
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/GroupToArgsBinder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/GroupToArgsBinder.cs
index 71412c94c56986..e637e236a7cc86 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/GroupToArgsBinder.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/GroupToArgsBinder.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using Microsoft.CSharp.RuntimeBinder.Errors;
using Microsoft.CSharp.RuntimeBinder.Syntax;
@@ -86,6 +87,7 @@ public GroupToArgsBinder(ExpressionBinder exprBinder, BindingFlag bindFlags, Exp
// This method does the actual binding.
// ----------------------------------------------------------------------------
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public void Bind()
{
Debug.Assert(_pGroup.SymKind == SYMKIND.SK_MethodSymbol || _pGroup.SymKind == SYMKIND.SK_PropertySymbol && 0 != (_pGroup.Flags & EXPRFLAG.EXF_INDEXER));
@@ -106,6 +108,7 @@ private static CType GetTypeQualifier(ExprMemberGroup pGroup)
return (pGroup.Flags & EXPRFLAG.EXF_CTOR) != 0 ? pGroup.ParentType : pGroup.OptionalObject?.Type;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private void LookForCandidates()
{
bool fExpanded = false;
@@ -303,6 +306,7 @@ private static void CopyArgInfos(ArgInfos src, ArgInfos dst)
}
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool GetResultOfBind()
{
// We looked at all the evidence, and we come to render the verdict:
@@ -363,6 +367,7 @@ private bool GetResultOfBind()
// we can find matching parameters for each named arguments, and all parameters
// that do not have a matching argument are optional parameters.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool ReOrderArgsForNamedArguments()
{
// First we need to find the method that we're actually trying to call.
@@ -391,6 +396,7 @@ private bool ReOrderArgsForNamedArguments()
return _bArgumentsChangedForNamedOrOptionalArguments;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal static bool ReOrderArgsForNamedArguments(
MethodOrPropertySymbol methprop, TypeArray pCurrentParameters, AggregateType pCurrentType, ExprMemberGroup pGroup, ArgInfos pArguments)
{
@@ -480,6 +486,7 @@ internal static bool ReOrderArgsForNamedArguments(
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static Expr GenerateOptionalArgument(MethodOrPropertySymbol methprop, CType type, int index)
{
CType pParamType = type;
@@ -657,6 +664,7 @@ private bool HasOptionalParameters()
// Returns true if we can either add enough optional parameters to make the
// argument list match, or if we don't need to at all.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool AddArgumentsForOptionalParameters()
{
if (_pCurrentParameters.Count <= _pArguments.carg)
@@ -858,6 +866,7 @@ private bool ConstructExpandedParameters()
return TryGetExpandedParams(_pCurrentSym.Params, _pArguments.carg, out _pCurrentParameters);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Result DetermineCurrentTypeArgs()
{
TypeArray typeArgs = _pGroup.TypeArgs;
@@ -908,6 +917,7 @@ private Result DetermineCurrentTypeArgs()
return Result.Success;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool ArgumentsAreConvertible()
{
bool containsErrorSym = false;
@@ -992,6 +1002,7 @@ private bool ArgumentsAreConvertible()
return true;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private void UpdateArguments()
{
// Parameter types might have changed as a result of
@@ -1070,6 +1081,7 @@ private static bool DoesTypeArgumentsContainErrorSym(CType var)
// ----------------------------------------------------------------------------
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private void ReportErrorsOnSuccess()
{
// used for Methods and Indexers
@@ -1089,6 +1101,7 @@ private void ReportErrorsOnSuccess()
}
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private RuntimeBinderException ReportErrorsOnFailure()
{
// First and foremost, report if the user specified a name more than once.
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ImplicitConversion.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ImplicitConversion.cs
index d6746409ebfbd0..3b0523d62ddbe9 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ImplicitConversion.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ImplicitConversion.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using Microsoft.CSharp.RuntimeBinder.Syntax;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
@@ -53,6 +54,7 @@ public ImplicitConversion(ExpressionBinder binder, Expr exprSrc, CType typeSrc,
*
* returns true if the conversion can be made, false if not.
*/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public bool Bind()
{
// 13.1 Implicit conversions
@@ -258,6 +260,7 @@ of times. (Handled by BindExplicitConversion.)
Some nullable conversion are NOT standard conversions. In particular, if S => T is implicit
then S? => T is not standard. Similarly if S => T is not implicit then S => T? is not standard.
***************************************************************************************************/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool BindNubConversion(NullableType nubDst)
{
// This code assumes that STANDARD and ISEXPLICIT are never both set.
@@ -389,6 +392,7 @@ private bool BindNubConversion(NullableType nubDst)
return true;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool bindImplicitConversionFromNull()
{
// null type can be implicitly converted to any reference type or pointer type or type
@@ -413,6 +417,7 @@ private bool bindImplicitConversionFromNull()
return true;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool bindImplicitConversionFromNullable(NullableType nubSrc)
{
// We can convert T? using a boxing conversion, we can convert it to ValueType, and
@@ -457,6 +462,7 @@ private bool bindImplicitConversionFromNullable(NullableType nubSrc)
return 0 == (_flags & CONVERTTYPE.NOUDC) && _binder.bindUserDefinedConversion(_exprSrc, nubSrc, _typeDest, _needsExprDest, out _exprDest, true);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool bindImplicitConversionFromArray()
{
// 13.1.4
@@ -503,6 +509,7 @@ private bool bindImplicitConversionFromArray()
return true;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool bindImplicitConversionFromPointer()
{
// 27.4 Pointer conversions
@@ -525,6 +532,7 @@ private bool bindImplicitConversionFromPointer()
return false;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool bindImplicitConversionFromAgg(AggregateType aggTypeSrc)
{
// GENERICS: The case for constructed types is very similar to types with
@@ -559,6 +567,7 @@ private bool bindImplicitConversionFromAgg(AggregateType aggTypeSrc)
return bindImplicitConversionToBase(aggTypeSrc);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool bindImplicitConversionToBase(AggregateType pSource)
{
// 13.1.4 Implicit reference conversions
@@ -588,6 +597,7 @@ private bool bindImplicitConversionToBase(AggregateType pSource)
return true;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool bindImplicitConversionFromEnum(AggregateType aggTypeSrc)
{
// 13.1.5 Boxing conversions
@@ -654,6 +664,7 @@ private bool bindImplicitConversionToEnum(AggregateType aggTypeSrc)
return false;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool bindImplicitConversionBetweenSimpleTypes(AggregateType aggTypeSrc)
{
AggregateSymbol aggSrc = aggTypeSrc.OwningAggregate;
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MemberLookup.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MemberLookup.cs
index ba90b4d88a42e0..b27c38fc9ba9c9 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MemberLookup.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MemberLookup.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using Microsoft.CSharp.RuntimeBinder.Errors;
using Microsoft.CSharp.RuntimeBinder.Syntax;
@@ -94,6 +95,7 @@ Search just the given type (not any bases). Returns true iff it finds
pfHideByName is set to true iff something was found that hides all
members of base types (eg, a hidebyname method).
******************************************************************************/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool SearchSingleType(AggregateType typeCur, out bool pfHideByName)
{
bool fFoundSome = false;
@@ -352,6 +354,7 @@ to null.
Returns true when searching should continue to the interfaces.
******************************************************************************/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool LookupInClass(AggregateType typeStart, ref AggregateType ptypeEnd)
{
Debug.Assert(!_swtFirst || _fMulti);
@@ -396,6 +399,7 @@ private bool LookupInClass(AggregateType typeStart, ref AggregateType ptypeEnd)
/******************************************************************************
Returns true if searching should continue to object.
******************************************************************************/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool LookupInInterfaces(AggregateType typeStart, TypeArray types)
{
Debug.Assert(!_swtFirst || _fMulti);
@@ -516,6 +520,7 @@ public MemberLookup()
flags - See MemLookFlags.
TypeVarsAllowed only applies to the most derived type (not base types).
***************************************************************************************************/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public bool Lookup(CType typeSrc, Expr obj, ParentSymbol symWhere, Name name, int arity, MemLookFlags flags)
{
Debug.Assert((flags & ~MemLookFlags.All) == 0);
@@ -588,6 +593,7 @@ public SymWithType SwtFirst()
/******************************************************************************
Reports errors. Only call this if FError() is true.
******************************************************************************/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public Exception ReportErrors()
{
Debug.Assert(FError());
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MethodIterator.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MethodIterator.cs
index 764189e8174083..17243de306540a 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MethodIterator.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MethodIterator.cs
@@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using Microsoft.CSharp.RuntimeBinder.Syntax;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
@@ -55,6 +56,7 @@ public CMethodIterator(Name name, TypeArray containingTypes, CType qualifyingTyp
public bool CanUseCurrentSymbol
{
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
get
{
// Make sure that whether we're seeing a ctor is consistent with the flag.
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MethodTypeInferrer.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MethodTypeInferrer.cs
index ce8902226a542b..39cbc4479a66a7 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MethodTypeInferrer.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/MethodTypeInferrer.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using Microsoft.CSharp.RuntimeBinder.Syntax;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
@@ -78,6 +79,7 @@ Initially each CType variable Xi is unfixed with an empty set of bounds.
////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static bool Infer(
ExpressionBinder binder,
MethodSymbol pMethod,
@@ -224,6 +226,7 @@ private bool HasBound(int iParam)
// Phases
//
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool InferTypeArgs()
{
// SPEC: CType inference takes place in phases. Each phase will try to infer CType
@@ -245,6 +248,7 @@ private static bool IsReallyAType(CType pType) =>
// The first phase
//
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private void InferTypeArgsFirstPhase()
{
Debug.Assert(_pMethodFormalParameterTypes != null);
@@ -353,6 +357,7 @@ private void InferTypeArgsFirstPhase()
// The second phase
//
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool InferTypeArgsSecondPhase()
{
// SPEC: The second phase proceeds as follows:
@@ -406,6 +411,7 @@ private bool InferTypeArgsSecondPhase()
////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private NewInferenceResult DoSecondPhase()
{
// SPEC: If no unfixed CType parameters exist then CType inference succeeds.
@@ -455,6 +461,7 @@ private NewInferenceResult DoSecondPhase()
////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private NewInferenceResult FixNondependentParameters()
{
// SPEC: Otherwise, if there exists one or more CType parameters Xi such that
@@ -496,6 +503,7 @@ private NewInferenceResult FixNondependentParameters()
////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private NewInferenceResult FixDependentParameters()
{
// SPEC: All unfixed CType parameters Xi are fixed for which all of the following hold:
@@ -881,6 +889,7 @@ private void ExactTypeArgumentInference(
//
// Lower-bound inferences
//
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private void LowerBoundInference(CType pSource, CType pDest)
{
// SPEC: A lower-bound inference from a CType U to a CType V is made as follows:
@@ -968,6 +977,7 @@ private bool LowerBoundTypeParameterInference(CType pSource, CType pDest)
////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool LowerBoundArrayInference(CType pSource, CType pDest)
{
// SPEC: Otherwise, if U is an array CType Ue[...] and V is either an array
@@ -1056,6 +1066,7 @@ bool LowerBoundNullableInference(CType pSource, CType pDest)
////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool LowerBoundConstructedInference(CType pSource, CType pDest)
{
if (!(pDest is AggregateType pConstructedDest))
@@ -1118,6 +1129,7 @@ private bool LowerBoundConstructedInference(CType pSource, CType pDest)
////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool LowerBoundClassInference(CType pSource, AggregateType pDest)
{
if (!pDest.IsClassType)
@@ -1159,6 +1171,7 @@ private bool LowerBoundClassInference(CType pSource, AggregateType pDest)
////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool LowerBoundInterfaceInference(CType pSource, AggregateType pDest)
{
if (!pDest.IsInterfaceType)
@@ -1204,6 +1217,7 @@ private bool LowerBoundInterfaceInference(CType pSource, AggregateType pDest)
return false;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private void LowerBoundTypeArgumentInference(
AggregateType pSource, AggregateType pDest)
{
@@ -1260,6 +1274,7 @@ private void LowerBoundTypeArgumentInference(
//
// Upper-bound inferences
//
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private void UpperBoundInference(CType pSource, CType pDest)
{
// SPEC: An upper-bound inference from a CType U to a CType V is made as follows:
@@ -1321,6 +1336,7 @@ private bool UpperBoundTypeParameterInference(CType pSource, CType pDest)
////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool UpperBoundArrayInference(CType pSource, CType pDest)
{
// SPEC: Otherwise, if V is an array CType Ve[...] and U is an array
@@ -1380,6 +1396,7 @@ private bool UpperBoundArrayInference(CType pSource, CType pDest)
////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool UpperBoundConstructedInference(CType pSource, CType pDest)
{
if (!(pSource is AggregateType pConstructedSource))
@@ -1435,6 +1452,7 @@ private bool UpperBoundConstructedInference(CType pSource, CType pDest)
////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool UpperBoundClassInference(AggregateType pSource, CType pDest)
{
if (!pSource.IsClassType || !pDest.IsClassType)
@@ -1464,6 +1482,7 @@ private bool UpperBoundClassInference(AggregateType pSource, CType pDest)
////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool UpperBoundInterfaceInference(AggregateType pSource, CType pDest)
{
if (!pSource.IsInterfaceType)
@@ -1505,6 +1524,7 @@ private bool UpperBoundInterfaceInference(AggregateType pSource, CType pDest)
return false;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private void UpperBoundTypeArgumentInference(
AggregateType pSource, AggregateType pDest)
{
@@ -1561,6 +1581,8 @@ private void UpperBoundTypeArgumentInference(
//
// Fixing
//
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool Fix(int iParam)
{
Debug.Assert(IsUnfixed(iParam));
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Nullable.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Nullable.cs
index 39c1ddfcec4726..ccdd55c5d632e0 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Nullable.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Nullable.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
{
@@ -34,6 +35,7 @@ private static Expr StripNullableConstructor(Expr pExpr)
}
// Create an expr for exprSrc.Value where exprSrc.type is a NullableType.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static Expr BindNubValue(Expr exprSrc)
{
Debug.Assert(exprSrc != null && exprSrc.Type is NullableType);
@@ -57,6 +59,7 @@ private static Expr BindNubValue(Expr exprSrc)
}
// Create an expr for new T?(exprSrc) where T is exprSrc.type.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static ExprCall BindNubNew(Expr exprSrc)
{
Debug.Assert(exprSrc != null);
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Operators.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Operators.cs
index 6aad1a081daefd..d11df5adba186c 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Operators.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Operators.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using Microsoft.CSharp.RuntimeBinder.Errors;
using Microsoft.CSharp.RuntimeBinder.Syntax;
@@ -133,7 +134,7 @@ Note that pointer operators cannot be lifted over nullable and are not callable
new UnaOpSig( PredefinedType.PT_DECIMAL, UnaOpMask.IncDec, 0, null, UnaOpFuncKind.None ),
};
-
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private ExprBinOp BindUserDefinedBinOp(ExpressionKind ek, BinOpArgInfo info)
{
MethPropWithInst pmpwi;
@@ -170,6 +171,7 @@ private ExprBinOp BindUserDefinedBinOp(ExpressionKind ek, BinOpArgInfo info)
// Adds special signatures to the candidate list. If we find an exact match
// then it will be the last item on the list and we return true.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool GetSpecialBinopSignatures(List prgbofs, BinOpArgInfo info)
{
Debug.Assert(prgbofs != null);
@@ -185,6 +187,7 @@ private bool GetSpecialBinopSignatures(List prgbofs, BinOpArgInfo
// Adds standard and lifted signatures to the candidate list. If we find an exact match
// then it will be the last item on the list and we return true.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool GetStandardAndLiftedBinopSignatures(List rgbofs, BinOpArgInfo info)
{
Debug.Assert(rgbofs != null);
@@ -388,6 +391,7 @@ private bool GetStandardAndLiftedBinopSignatures(List rgbofs, BinO
}
// Returns the index of the best match, or -1 if there is no best match.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private int FindBestSignatureInList(
List binopSignatures,
BinOpArgInfo info)
@@ -444,6 +448,7 @@ private int FindBestSignatureInList(
return bestSignature;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static ExprBinOp BindNullEqualityComparison(ExpressionKind ek, BinOpArgInfo info)
{
Expr arg1 = info.arg1;
@@ -476,6 +481,8 @@ private static ExprBinOp BindNullEqualityComparison(ExpressionKind ek, BinOpArgI
This handles binding binary operators by first checking for user defined operators, then
applying overload resolution to the predefined operators. It handles lifting over nullable.
*/
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public Expr BindStandardBinop(ExpressionKind ek, Expr arg1, Expr arg2)
{
Debug.Assert(arg1 != null);
@@ -550,6 +557,7 @@ public Expr BindStandardBinop(ExpressionKind ek, Expr arg1, Expr arg2)
return BindStandardBinopCore(info, binopSignatures[bestBinopSignature], ek, flags);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr BindStandardBinopCore(BinOpArgInfo info, BinOpFullSig bofs, ExpressionKind ek, EXPRFLAG flags)
{
if (bofs.pfn == null)
@@ -591,6 +599,7 @@ private Expr BindStandardBinopCore(BinOpArgInfo info, BinOpFullSig bofs, Express
return BindLiftedStandardBinOp(info, bofs, ek, flags);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private ExprBinOp BindLiftedStandardBinOp(BinOpArgInfo info, BinOpFullSig bofs, ExpressionKind ek, EXPRFLAG flags)
{
Debug.Assert(bofs.Type1() is NullableType || bofs.Type2() is NullableType);
@@ -644,6 +653,7 @@ private ExprBinOp BindLiftedStandardBinOp(BinOpArgInfo info, BinOpFullSig bofs,
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private void LiftArgument(Expr pArgument, CType pParameterType, bool bConvertBeforeLift,
out Expr ppLiftedArgument, out Expr ppNonLiftedArgument)
{
@@ -678,6 +688,7 @@ private void LiftArgument(Expr pArgument, CType pParameterType, bool bConvertBef
Get the special signatures when at least one of the args is a delegate instance.
Returns true iff an exact signature match is found.
*/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool GetDelBinOpSigs(List prgbofs, BinOpArgInfo info)
{
if (!info.ValidForDelegate() || !info.type1.IsDelegateType && !info.type2.IsDelegateType)
@@ -717,6 +728,7 @@ private bool GetDelBinOpSigs(List prgbofs, BinOpArgInfo info)
Utility method to determine whether arg1 is convertible to typeDst, either in a regular
scenario or lifted scenario. Sets pgrflt, ptypeSig1 and ptypeSig2 accordingly.
*/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool CanConvertArg1(BinOpArgInfo info, CType typeDst, out LiftFlags pgrflt,
out CType ptypeSig1, out CType ptypeSig2)
{
@@ -751,6 +763,7 @@ private bool CanConvertArg1(BinOpArgInfo info, CType typeDst, out LiftFlags pgrf
/*
Same as CanConvertArg1 but with the indices interchanged!
*/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool CanConvertArg2(BinOpArgInfo info, CType typeDst, out LiftFlags pgrflt,
out CType ptypeSig1, out CType ptypeSig2)
{
@@ -786,6 +799,7 @@ private bool CanConvertArg2(BinOpArgInfo info, CType typeDst, out LiftFlags pgrf
Record the appropriate binary operator full signature from the given BinOpArgInfo. This assumes
that any NullableType valued args should be lifted.
*/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static void RecordBinOpSigFromArgs(List prgbofs, BinOpArgInfo info)
{
LiftFlags grflt = LiftFlags.None;
@@ -821,6 +835,7 @@ private static void RecordBinOpSigFromArgs(List prgbofs, BinOpArgI
Get the special signatures when at least one of the args is an enum. Return true if
we find an exact match.
*/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool GetEnumBinOpSigs(List prgbofs, BinOpArgInfo info)
{
if (!info.typeRaw1.IsEnumType && !info.typeRaw2.IsEnumType)
@@ -892,6 +907,7 @@ private static bool IsEnumArithmeticBinOp(ExpressionKind ek, BinOpArgInfo info)
may be applicable and better (or ambiguous)! This also handles == on System.Delegate, since
it has special rules as well.
*/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool GetRefEqualSigs(List prgbofs, BinOpArgInfo info)
{
if (info.mask != BinOpMask.Equal)
@@ -1012,6 +1028,7 @@ Because of user defined conversion operators this relation is not transitive.
Returns negative if ibos1 is better, positive if ibos2 is better, 0 if neither.
*/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private int WhichBofsIsBetter(BinOpFullSig bofs1, BinOpFullSig bofs2, CType type1, CType type2)
{
BetterType bt1;
@@ -1133,6 +1150,7 @@ private static (ExpressionKind, UnaOpKind, EXPRFLAG) CalculateExprAndUnaryOpKind
return (ek, uok, flags);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public Expr BindStandardUnaryOperator(OperatorKind op, Expr pArgument)
{
Debug.Assert(pArgument != null);
@@ -1276,6 +1294,7 @@ public Expr BindStandardUnaryOperator(OperatorKind op, Expr pArgument)
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private UnaryOperatorSignatureFindResult PopulateSignatureList(Expr pArgument, UnaOpKind unaryOpKind, UnaOpMask unaryOpMask, ExpressionKind exprKind, EXPRFLAG flags, List pSignatures, out Expr ppResult)
{
// We should have already checked argument != null and argument.type != null.
@@ -1366,6 +1385,7 @@ private UnaryOperatorSignatureFindResult PopulateSignatureList(Expr pArgument, U
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool FindApplicableSignatures(
Expr pArgument,
UnaOpMask unaryOpMask,
@@ -1491,6 +1511,7 @@ private bool FindApplicableSignatures(
return false;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private ExprOperator BindLiftedStandardUnop(ExpressionKind ek, EXPRFLAG flags, Expr arg, UnaOpFullSig uofs)
{
NullableType type = uofs.GetType() as NullableType;
@@ -1516,6 +1537,7 @@ private ExprOperator BindLiftedStandardUnop(ExpressionKind ek, EXPRFLAG flags, E
Determine which UnaOpSig is better for overload resolution.
Returns negative if iuos1 is better, positive if iuos2 is better, 0 if neither.
*/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private int WhichUofsIsBetter(UnaOpFullSig uofs1, UnaOpFullSig uofs2, CType typeArg)
{
BetterType bt;
@@ -1582,6 +1604,7 @@ private static ExprOperator BindRealUnaOp(ExpressionBinder binder, ExpressionKin
/*
Handles standard increment and decrement operators.
*/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr BindIncOp(ExpressionKind ek, EXPRFLAG flags, Expr arg, UnaOpFullSig uofs)
{
Debug.Assert(ek == ExpressionKind.Add || ek == ExpressionKind.Subtract);
@@ -1605,6 +1628,7 @@ private Expr BindIncOp(ExpressionKind ek, EXPRFLAG flags, Expr arg, UnaOpFullSig
}
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr BindIncOpCore(ExpressionKind ek, EXPRFLAG flags, Expr exprVal, CType type)
{
Debug.Assert(ek == ExpressionKind.Add || ek == ExpressionKind.Subtract);
@@ -1662,6 +1686,7 @@ private Expr BindIncOpCore(ExpressionKind ek, EXPRFLAG flags, Expr exprVal, CTyp
return LScalar(ek, flags, exprVal, type, cv, type);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr LScalar(ExpressionKind ek, EXPRFLAG flags, Expr exprVal, CType type, ConstVal cv, CType typeTmp)
{
CType typeOne = type;
@@ -1675,6 +1700,7 @@ private Expr LScalar(ExpressionKind ek, EXPRFLAG flags, Expr exprVal, CType type
return typeTmp != type ? mustCast(pExprResult, type, CONVERTTYPE.NOUDC) : pExprResult;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private ExprMulti BindNonliftedIncOp(ExpressionKind ek, EXPRFLAG flags, Expr arg, UnaOpFullSig uofs)
{
Debug.Assert(ek == ExpressionKind.Add || ek == ExpressionKind.Subtract);
@@ -1701,6 +1727,7 @@ private ExprMulti BindNonliftedIncOp(ExpressionKind ek, EXPRFLAG flags, Expr arg
return exprMulti;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private ExprMulti BindLiftedIncOp(ExpressionKind ek, EXPRFLAG flags, Expr arg, UnaOpFullSig uofs)
{
Debug.Assert(ek == ExpressionKind.Add || ek == ExpressionKind.Subtract);
@@ -1733,6 +1760,8 @@ Handles standard binary decimal based operators.
This function is called twice by the EE for every binary operator it evaluates
Here is how it works.
*/
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "All types used here are builtin and will not be trimmed.")]
private static ExprBinOp BindDecBinOp(ExpressionBinder _, ExpressionKind ek, EXPRFLAG flags, Expr arg1, Expr arg2)
{
Debug.Assert(arg1.Type.IsPredefType(PredefinedType.PT_DECIMAL) && arg2.Type.IsPredefType(PredefinedType.PT_DECIMAL));
@@ -1772,6 +1801,9 @@ private static ExprBinOp BindDecBinOp(ExpressionBinder _, ExpressionKind ek, EXP
/*
Handles standard unary decimal based operators.
*/
+
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "All types used here are builtin and will not be trimmed.")]
private static ExprUnaryOp BindDecUnaOp(ExpressionBinder _, ExpressionKind ek, EXPRFLAG flags, Expr arg)
{
Debug.Assert(arg.Type.IsPredefType(PredefinedType.PT_DECIMAL));
@@ -1804,6 +1836,8 @@ private static Expr BindStrBinOp(ExpressionBinder _, ExpressionKind ek, EXPRFLAG
Bind a shift operator: <<, >>. These can have integer or long first operands,
and second operand must be int.
*/
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "All types used here are builtin and will not be trimmed.")]
private static ExprBinOp BindShiftOp(ExpressionBinder _, ExpressionKind ek, EXPRFLAG flags, Expr arg1, Expr arg2)
{
Debug.Assert(ek == ExpressionKind.LeftShirt || ek == ExpressionKind.RightShift);
@@ -1820,6 +1854,8 @@ private static ExprBinOp BindShiftOp(ExpressionBinder _, ExpressionKind ek, EXPR
Bind a bool binary operator: ==, !=, &&, ||, , |, ^. If both operands are constant, the
result will be a constant also.
*/
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "All types used here are builtin and will not be trimmed.")]
private static ExprBinOp BindBoolBinOp(ExpressionBinder _, ExpressionKind ek, EXPRFLAG flags, Expr arg1, Expr arg2)
{
Debug.Assert(arg1 != null);
@@ -1830,6 +1866,7 @@ private static ExprBinOp BindBoolBinOp(ExpressionBinder _, ExpressionKind ek, EX
return ExprFactory.CreateBinop(ek, GetPredefindType(PredefinedType.PT_BOOL), arg1, arg2);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private ExprOperator BindBoolBitwiseOp(ExpressionKind ek, EXPRFLAG flags, Expr expr1, Expr expr2)
{
Debug.Assert(ek == ExpressionKind.BitwiseAnd || ek == ExpressionKind.BitwiseOr);
@@ -1867,11 +1904,15 @@ private ExprOperator BindBoolBitwiseOp(ExpressionKind ek, EXPRFLAG flags, Expr e
return BindBoolBinOp(this, ek, flags, expr1, expr2);
}
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "All types used here are builtin and will not be trimmed.")]
private static Expr BindLiftedBoolBitwiseOp(ExpressionBinder _, ExpressionKind ek, EXPRFLAG flags, Expr expr1, Expr expr2) => null;
/*
Handles boolean unary operator (!).
*/
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "All types used here are builtin and will not be trimmed.")]
private static Expr BindBoolUnaOp(ExpressionBinder _, ExpressionKind ek, EXPRFLAG flags, Expr arg)
{
Debug.Assert(arg.Type.IsPredefType(PredefinedType.PT_BOOL));
@@ -1895,6 +1936,8 @@ private static Expr BindBoolUnaOp(ExpressionBinder _, ExpressionKind ek, EXPRFLA
/*
Handles string equality.
*/
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "All types used here are builtin and will not be trimmed.")]
private static ExprBinOp BindStrCmpOp(ExpressionBinder _, ExpressionKind ek, EXPRFLAG flags, Expr arg1, Expr arg2)
{
Debug.Assert(ek == ExpressionKind.Eq || ek == ExpressionKind.NotEq);
@@ -1912,6 +1955,7 @@ private static ExprBinOp BindStrCmpOp(ExpressionBinder _, ExpressionKind ek, EXP
/*
Handles reference equality operators. Type variables come through here.
*/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static ExprBinOp BindRefCmpOp(ExpressionBinder binder, ExpressionKind ek, EXPRFLAG flags, Expr arg1, Expr arg2)
{
Debug.Assert(ek == ExpressionKind.Eq || ek == ExpressionKind.NotEq);
@@ -1927,6 +1971,7 @@ private static ExprBinOp BindRefCmpOp(ExpressionBinder binder, ExpressionKind ek
/*
Handles delegate binary operators.
*/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static Expr BindDelBinOp(ExpressionBinder _, ExpressionKind ek, EXPRFLAG flags, Expr arg1, Expr arg2)
{
Debug.Assert(ek == ExpressionKind.Add || ek == ExpressionKind.Subtract || ek == ExpressionKind.Eq || ek == ExpressionKind.NotEq);
@@ -1967,6 +2012,7 @@ private static Expr BindDelBinOp(ExpressionBinder _, ExpressionKind ek, EXPRFLAG
/*
Handles enum binary operators.
*/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static Expr BindEnumBinOp(ExpressionBinder binder, ExpressionKind ek, EXPRFLAG flags, Expr arg1, Expr arg2)
{
AggregateType typeDst = GetEnumBinOpType(ek, arg1.Type, arg2.Type, out AggregateType typeEnum);
@@ -1995,6 +2041,7 @@ private static Expr BindEnumBinOp(ExpressionBinder binder, ExpressionKind ek, EX
return exprRes;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr BindLiftedEnumArithmeticBinOp(ExpressionKind ek, EXPRFLAG flags, Expr arg1, Expr arg2)
{
Debug.Assert(ek == ExpressionKind.Add || ek == ExpressionKind.Subtract);
@@ -2041,6 +2088,7 @@ private Expr BindLiftedEnumArithmeticBinOp(ExpressionKind ek, EXPRFLAG flags, Ex
/*
Handles enum unary operator (~).
*/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static Expr BindEnumUnaOp(ExpressionBinder binder, ExpressionKind ek, EXPRFLAG flags, Expr arg)
{
Debug.Assert(ek == ExpressionKind.BitwiseNot);
@@ -2140,6 +2188,8 @@ private static Expr BindEnumUnaOp(ExpressionBinder binder, ExpressionKind ek, EX
Convert an expression involving I4, U4, I8 or U8 operands. The operands are
assumed to be already converted to the correct types.
*/
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "All types used here are builtin and will not be trimmed.")]
private ExprOperator BindIntOp(ExpressionKind kind, EXPRFLAG flags, Expr op1, Expr op2, PredefinedType ptOp)
{
//Debug.Assert(kind.isRelational() || kind.isArithmetic() || kind.isBitwise());
@@ -2163,6 +2213,8 @@ private ExprOperator BindIntOp(ExpressionKind kind, EXPRFLAG flags, Expr op1, Ex
return exprRes;
}
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "All types used here are builtin and will not be trimmed.")]
private ExprOperator BindIntegerNeg(EXPRFLAG flags, Expr op, PredefinedType ptOp)
{
// 14.6.2 Unary minus operator
@@ -2220,6 +2272,9 @@ private ExprOperator BindIntegerNeg(EXPRFLAG flags, Expr op, PredefinedType ptOp
will be a constant also. op2 can be null for a unary operator. The operands are assumed
to be already converted to the correct type.
*/
+
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "All types used here are builtin and will not be trimmed.")]
private static ExprOperator BindFloatOp(ExpressionKind kind, Expr op1, Expr op2)
{
//Debug.Assert(kind.isRelational() || kind.isArithmetic());
@@ -2235,6 +2290,8 @@ private static ExprOperator BindFloatOp(ExpressionKind kind, Expr op1, Expr op2)
return exprRes;
}
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "All types used here are builtin and will not be trimmed.")]
private static ExprConcat BindStringConcat(Expr op1, Expr op2)
{
// If the concatenation consists solely of two constants then we must
@@ -2275,6 +2332,7 @@ private static RuntimeBinderException AmbiguousOperatorError(Expr op1, Expr op2)
: ErrorHandling.Error(ErrorCode.ERR_AmbigUnaryOp, strOp, op1.Type);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr BindUserBoolOp(ExpressionKind kind, ExprCall pCall)
{
Debug.Assert(pCall != null);
@@ -2394,6 +2452,7 @@ private static bool UserDefinedBinaryOperatorCanBeLifted(ExpressionKind ek, Meth
// If the operator is applicable in either its regular or lifted forms,
// add it to the candidate set and return true, otherwise return false.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool UserDefinedBinaryOperatorIsApplicable(List candidateList,
ExpressionKind ek, MethodSymbol method, AggregateType ats, Expr arg1, Expr arg2, bool fDontLift)
{
@@ -2431,6 +2490,7 @@ private bool UserDefinedBinaryOperatorIsApplicable(List
return true;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private bool GetApplicableUserDefinedBinaryOperatorCandidates(
List candidateList, ExpressionKind ek, AggregateType type,
Expr arg1, Expr arg2, bool fDontLift)
@@ -2450,6 +2510,7 @@ private bool GetApplicableUserDefinedBinaryOperatorCandidates(
return foundSome;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private AggregateType GetApplicableUserDefinedBinaryOperatorCandidatesInBaseTypes(
List candidateList, ExpressionKind ek, AggregateType type,
Expr arg1, Expr arg2, bool fDontLift, AggregateType atsStop)
@@ -2465,6 +2526,7 @@ private AggregateType GetApplicableUserDefinedBinaryOperatorCandidatesInBaseType
return null;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private ExprCall BindUDBinop(ExpressionKind ek, Expr arg1, Expr arg2, bool fDontLift, out MethPropWithInst ppmpwi)
{
List methFirst = new List();
@@ -2523,6 +2585,7 @@ private ExprCall BindUDBinop(ExpressionKind ek, Expr arg1, Expr arg2, bool fDont
return BindUDBinopCall(arg1, arg2, pmethBest.@params, typeRetRaw, pmethBest.mpwi);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private ExprCall BindUDBinopCall(Expr arg1, Expr arg2, TypeArray Params, CType typeRet, MethPropWithInst mpwi)
{
arg1 = mustConvert(arg1, Params[0]);
@@ -2541,6 +2604,7 @@ private ExprCall BindUDBinopCall(Expr arg1, Expr arg2, TypeArray Params, CType t
return call;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private ExprCall BindLiftedUDBinop(ExpressionKind ek, Expr arg1, Expr arg2, TypeArray Params, MethPropWithInst mpwi)
{
Expr exprVal1 = arg1;
@@ -2618,6 +2682,7 @@ private ExprCall BindLiftedUDBinop(ExpressionKind ek, Expr arg1, Expr arg2, Type
return call;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static AggregateType GetEnumBinOpType(ExpressionKind ek, CType argType1, CType argType2, out AggregateType ppEnumType)
{
Debug.Assert(argType1.IsEnumType || argType2.IsEnumType);
@@ -2659,6 +2724,7 @@ private static AggregateType GetEnumBinOpType(ExpressionKind ek, CType argType1,
return typeDst;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static ExprBinOp CreateBinopForPredefMethodCall(ExpressionKind ek, PREDEFMETH predefMeth, CType RetType, Expr arg1, Expr arg2)
{
MethodSymbol methSym = PredefinedMembers.GetMethod(predefMeth);
@@ -2673,6 +2739,7 @@ private static ExprBinOp CreateBinopForPredefMethodCall(ExpressionKind ek, PREDE
return binop;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static ExprUnaryOp CreateUnaryOpForPredefMethodCall(ExpressionKind ek, PREDEFMETH predefMeth, CType pRetType, Expr pArg)
{
MethodSymbol methSym = PredefinedMembers.GetMethod(predefMeth);
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/PredefinedMembers.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/PredefinedMembers.cs
index ee501afe1ac057..a6f8b265502441 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/PredefinedMembers.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/PredefinedMembers.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using Microsoft.CSharp.RuntimeBinder.Syntax;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
@@ -197,12 +198,14 @@ internal static class PredefinedMembers
private static readonly MethodSymbol[] _methods = new MethodSymbol[(int)PREDEFMETH.PM_COUNT];
private static readonly PropertySymbol[] _properties = new PropertySymbol[(int)PREDEFPROP.PP_COUNT];
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static PropertySymbol LoadProperty(PREDEFPROP property)
{
PredefinedPropertyInfo info = GetPropInfo(property);
return LoadProperty(property, NameManager.GetPredefinedName(info.name), info.getter);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static PropertySymbol LoadProperty(
PREDEFPROP predefProp,
Name propertyName,
@@ -221,8 +224,10 @@ private static PropertySymbol LoadProperty(
return property;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static AggregateSymbol GetPredefAgg(PredefinedType pt) => SymbolLoader.GetPredefAgg(pt);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static CType LoadTypeFromSignature(int[] signature, ref int indexIntoSignatures, TypeArray classTyVars)
{
Debug.Assert(signature != null);
@@ -263,6 +268,7 @@ private static CType LoadTypeFromSignature(int[] signature, ref int indexIntoSig
}
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static TypeArray LoadTypeArrayFromSignature(int[] signature, ref int indexIntoSignatures, TypeArray classTyVars)
{
Debug.Assert(signature != null);
@@ -296,18 +302,21 @@ static PredefinedMembers()
}
#endif
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static PropertySymbol GetProperty(PREDEFPROP property)
{
Debug.Assert(property >= 0 && property < PREDEFPROP.PP_COUNT);
return _properties[(int)property] ?? (_properties[(int)property] = LoadProperty(property));
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static MethodSymbol GetMethod(PREDEFMETH method)
{
Debug.Assert(method >= 0 && method < PREDEFMETH.PM_COUNT);
return _methods[(int)method] ?? (_methods[(int)method] = LoadMethod(method));
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static MethodSymbol LoadMethod(
AggregateSymbol type,
int[] signature,
@@ -363,6 +372,7 @@ private static MethodSymbol LookupMethodWhileLoading(AggregateSymbol type, int c
return null;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static MethodSymbol LoadMethod(PREDEFMETH method)
{
PredefinedMethodInfo info = GetMethInfo(method);
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/SemanticChecker.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/SemanticChecker.cs
index e90e98f880e587..620094db1ef9f9 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/SemanticChecker.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/SemanticChecker.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using Microsoft.CSharp.RuntimeBinder.Errors;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
@@ -28,6 +29,7 @@ public static void CheckForStaticClass(CType type)
}
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static ACCESSERROR CheckAccess2(Symbol symCheck, AggregateType atsCheck, Symbol symWhere, CType typeThru)
{
Debug.Assert(symCheck != null);
@@ -77,6 +79,7 @@ typeThru is ArrayType ||
return CheckTypeAccess(type, symWhere) ? ACCESSERROR.ACCESSERROR_NOERROR : ACCESSERROR.ACCESSERROR_NOACCESS;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static bool CheckTypeAccess(CType type, Symbol symWhere)
{
Debug.Assert(type != null);
@@ -110,6 +113,7 @@ public static bool CheckTypeAccess(CType type, Symbol symWhere)
return true;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static ACCESSERROR CheckAccessCore(Symbol symCheck, AggregateType atsCheck, Symbol symWhere, CType typeThru)
{
Debug.Assert(symCheck != null);
@@ -246,6 +250,7 @@ typeThru is ArrayType ||
public static bool CheckBogus(Symbol sym) => (sym as PropertySymbol)?.Bogus ?? false;
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static RuntimeBinderException ReportAccessError(SymWithType swtBad, Symbol symWhere, CType typeQual)
{
Debug.Assert(!CheckAccess(swtBad.Sym, swtBad.GetType(), symWhere, typeQual) ||
@@ -257,6 +262,7 @@ public static RuntimeBinderException ReportAccessError(SymWithType swtBad, Symbo
: ErrorHandling.Error(ErrorCode.ERR_BadAccess, swtBad);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static bool CheckAccess(Symbol symCheck, AggregateType atsCheck, Symbol symWhere, CType typeThru) =>
CheckAccess2(symCheck, atsCheck, symWhere, typeThru) == ACCESSERROR.ACCESSERROR_NOERROR;
}
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/AggregateSymbol.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/AggregateSymbol.cs
index 7076d277fbbd35..a7bee97dda34ca 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/AggregateSymbol.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/AggregateSymbol.cs
@@ -3,6 +3,7 @@
using System;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using Microsoft.CSharp.RuntimeBinder.Syntax;
@@ -220,6 +221,7 @@ public void SetSealed(bool @sealed)
////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public bool HasConversion()
{
SymbolTable.AddConversionsForType(AssociatedSystemType);
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/SymbolLoader.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/SymbolLoader.cs
index 3fa95f2ba33979..7899c66348f63c 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/SymbolLoader.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Symbols/SymbolLoader.cs
@@ -2,18 +2,22 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using Microsoft.CSharp.RuntimeBinder.Syntax;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
{
internal static class SymbolLoader
{
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static AggregateSymbol GetPredefAgg(PredefinedType pt) => TypeManager.GetPredefAgg(pt);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static AggregateType GetPredefindType(PredefinedType pt) => GetPredefAgg(pt).getThisType();
public static Symbol LookupAggMember(Name name, AggregateSymbol agg, symbmask_t mask) => SymbolStore.LookupSym(name, agg, mask);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static bool IsBaseInterface(AggregateType atsDer, AggregateType pBase)
{
Debug.Assert(atsDer != null);
@@ -37,6 +41,7 @@ private static bool IsBaseInterface(AggregateType atsDer, AggregateType pBase)
return false;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static bool IsBaseClassOfClass(CType pDerived, CType pBase)
{
Debug.Assert(pDerived != null);
@@ -47,6 +52,7 @@ public static bool IsBaseClassOfClass(CType pDerived, CType pBase)
return pDerived.IsClassType && IsBaseClass(pDerived, pBase);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static bool IsBaseClass(CType pDerived, CType pBase)
{
Debug.Assert(pDerived != null);
@@ -84,6 +90,7 @@ private static bool IsBaseClass(CType pDerived, CType pBase)
return false;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static bool HasCovariantArrayConversion(ArrayType pSource, ArrayType pDest)
{
Debug.Assert(pSource != null);
@@ -95,6 +102,7 @@ private static bool HasCovariantArrayConversion(ArrayType pSource, ArrayType pDe
HasImplicitReferenceConversion(pSource.ElementType, pDest.ElementType);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static bool HasIdentityOrImplicitReferenceConversion(CType pSource, CType pDest)
{
Debug.Assert(pSource != null);
@@ -109,6 +117,7 @@ public static bool HasIdentityOrImplicitReferenceConversion(CType pSource, CType
private static bool AreTypesEqualForConversion(CType pType1, CType pType2) => pType1.Equals(pType2);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static bool HasArrayConversionToInterface(ArrayType pSource, CType pDest)
{
Debug.Assert(pSource != null);
@@ -150,6 +159,7 @@ private static bool HasArrayConversionToInterface(ArrayType pSource, CType pDest
return HasIdentityOrImplicitReferenceConversion(pSource.ElementType, atsDest.TypeArgsAll[0]);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static bool HasImplicitReferenceConversion(CType pSource, CType pDest)
{
Debug.Assert(pSource != null);
@@ -276,6 +286,7 @@ private static bool HasImplicitReferenceConversion(CType pSource, CType pDest)
return false;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static bool HasAnyBaseInterfaceConversion(CType pDerived, CType pBase)
{
if (!pBase.IsInterfaceType || !(pDerived is AggregateType atsDer))
@@ -313,6 +324,7 @@ private static bool HasAnyBaseInterfaceConversion(CType pDerived, CType pBase)
// * if the ith parameter of U is contravariant then either Si is exactly
// equal to Ti, or there is an implicit reference conversion from Ti to Si.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static bool HasInterfaceConversion(AggregateType pSource, AggregateType pDest)
{
Debug.Assert(pSource != null && pSource.IsInterfaceType);
@@ -322,6 +334,7 @@ private static bool HasInterfaceConversion(AggregateType pSource, AggregateType
//////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static bool HasDelegateConversion(AggregateType pSource, AggregateType pDest)
{
Debug.Assert(pSource != null && pSource.IsDelegateType);
@@ -331,6 +344,7 @@ private static bool HasDelegateConversion(AggregateType pSource, AggregateType p
//////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static bool HasVariantConversion(AggregateType pSource, AggregateType pDest)
{
Debug.Assert(pSource != null);
@@ -385,6 +399,7 @@ private static bool HasVariantConversion(AggregateType pSource, AggregateType pD
return true;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static bool HasImplicitBoxingConversion(CType pSource, CType pDest)
{
Debug.Assert(pSource != null);
@@ -422,6 +437,7 @@ private static bool HasImplicitBoxingConversion(CType pSource, CType pDest)
return IsBaseClass(pSource, pDest) || HasAnyBaseInterfaceConversion(pSource, pDest);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static bool HasBaseConversion(CType pSource, CType pDest)
{
// By a "base conversion" we mean:
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/Cast.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/Cast.cs
index 5270033d5ef021..72a6b74534caa0 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/Cast.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/Cast.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
{
@@ -22,6 +23,7 @@ public ExprCast(EXPRFLAG flags, CType type, Expr argument)
public override object Object
{
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
get
{
Expr arg = Argument;
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/Constant.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/Constant.cs
index 20d33816622c6f..4b27fa0280c3e0 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/Constant.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/Constant.cs
@@ -3,6 +3,7 @@
using System;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
{
@@ -47,6 +48,7 @@ public long Int64Value
public override object Object
{
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
get
{
if (Type is NullType)
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/EXPR.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/EXPR.cs
index 4f4de917eb46a9..f60ef0a6e68966 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/EXPR.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/EXPR.cs
@@ -41,6 +41,7 @@ public CType Type
[ExcludeFromCodeCoverage(Justification = "Should only be called through override")]
public virtual object Object
{
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
get
{
Debug.Fail("Invalid Expr in GetObject");
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/MethodInfo.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/MethodInfo.cs
index 600a4dde3eb6d1..ae36dd5e67d9fe 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/MethodInfo.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/MethodInfo.cs
@@ -3,6 +3,7 @@
using System;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Reflection;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
@@ -21,6 +22,7 @@ public ExprMethodInfo(CType type, MethodSymbol method, AggregateType methodType,
public MethodInfo MethodInfo
{
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
get
{
// To do this, we need to construct a type array of the parameter types,
@@ -93,6 +95,7 @@ public MethodInfo MethodInfo
public ConstructorInfo ConstructorInfo
{
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
get
{
// To do this, we need to construct a type array of the parameter types,
@@ -142,6 +145,10 @@ public ConstructorInfo ConstructorInfo
}
}
- public override object Object => MethodInfo;
+ public override object Object
+ {
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
+ get => MethodInfo;
+ }
}
}
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/PropertyInfo.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/PropertyInfo.cs
index 8d0b33c178eb5e..5e1170bd080d98 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/PropertyInfo.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/PropertyInfo.cs
@@ -3,6 +3,7 @@
using System;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Reflection;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
@@ -21,6 +22,7 @@ public ExprPropertyInfo(CType type, PropertySymbol propertySymbol, AggregateType
public PropertyInfo PropertyInfo
{
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
get
{
// To do this, we need to construct a type array of the parameter types,
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/TypeOf.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/TypeOf.cs
index 537c510750da1d..2225a397ce87ff 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/TypeOf.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/TypeOf.cs
@@ -1,6 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
+
namespace Microsoft.CSharp.RuntimeBinder.Semantics
{
internal sealed class ExprTypeOf : ExprWithType
@@ -14,6 +16,10 @@ public ExprTypeOf(CType type, CType sourceType)
public CType SourceType { get; }
- public override object Object => SourceType.AssociatedSystemType;
+ public override object Object
+ {
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
+ get => SourceType.AssociatedSystemType;
+ }
}
}
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/Visitors/ExprVisitorBase.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/Visitors/ExprVisitorBase.cs
index c722ffa2be79f2..0799ada9e0f904 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/Visitors/ExprVisitorBase.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/Visitors/ExprVisitorBase.cs
@@ -2,13 +2,16 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
{
internal abstract class ExprVisitorBase
{
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected Expr Visit(Expr pExpr) => pExpr == null ? null : Dispatch(pExpr);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr Dispatch(Expr pExpr) =>
pExpr.Kind switch
{
@@ -85,6 +88,7 @@ protected virtual Expr Dispatch(Expr pExpr) =>
_ => throw Error.InternalCompilerError(),
};
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private void VisitChildren(Expr pExpr)
{
Debug.Assert(pExpr != null);
@@ -289,271 +293,398 @@ a qualified name.
}
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitEXPR(Expr pExpr)
{
VisitChildren(pExpr);
return pExpr;
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitBINOP(ExprBinOp pExpr)
{
return VisitEXPR(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitLIST(ExprList pExpr)
{
return VisitEXPR(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitASSIGNMENT(ExprAssignment pExpr)
{
return VisitEXPR(pExpr);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitARRAYINDEX(ExprArrayIndex pExpr)
{
return VisitEXPR(pExpr);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitUNARYOP(ExprUnaryOp pExpr)
{
return VisitEXPR(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitUSERLOGOP(ExprUserLogicalOp pExpr)
{
return VisitEXPR(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitTYPEOF(ExprTypeOf pExpr)
{
return VisitEXPR(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitCAST(ExprCast pExpr)
{
return VisitEXPR(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitUSERDEFINEDCONVERSION(ExprUserDefinedConversion pExpr)
{
return VisitEXPR(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitZEROINIT(ExprZeroInit pExpr)
{
return VisitEXPR(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitMEMGRP(ExprMemberGroup pExpr)
{
return VisitEXPR(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitCALL(ExprCall pExpr)
{
return VisitEXPR(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitPROP(ExprProperty pExpr)
{
return VisitEXPR(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitFIELD(ExprField pExpr)
{
return VisitEXPR(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitLOCAL(ExprLocal pExpr)
{
return VisitEXPR(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitCONSTANT(ExprConstant pExpr)
{
return VisitEXPR(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitMULTIGET(ExprMultiGet pExpr)
{
return VisitEXPR(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitMULTI(ExprMulti pExpr)
{
return VisitEXPR(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitWRAP(ExprWrap pExpr)
{
return VisitEXPR(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitCONCAT(ExprConcat pExpr)
{
return VisitEXPR(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitARRINIT(ExprArrayInit pExpr)
{
return VisitEXPR(pExpr);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitFIELDINFO(ExprFieldInfo pExpr)
{
return VisitEXPR(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitMETHODINFO(ExprMethodInfo pExpr)
{
return VisitEXPR(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitEQUALS(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitCOMPARE(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitEQ(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitNE(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitLE(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitGE(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitADD(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitSUB(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitDIV(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitBITAND(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitBITOR(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitLSHIFT(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitLOGAND(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitSEQUENCE(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitSAVE(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitINDIR(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitSTRINGEQ(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitDELEGATEEQ(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitDELEGATEADD(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitLT(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitMUL(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitBITXOR(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitRSHIFT(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitLOGOR(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitSTRINGNE(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitDELEGATENE(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitGT(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitMOD(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitSWAP(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitDELEGATESUB(ExprBinOp pExpr)
{
return VisitBINOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitTRUE(ExprUnaryOp pExpr)
{
return VisitUNARYOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitINC(ExprUnaryOp pExpr)
{
return VisitUNARYOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitLOGNOT(ExprUnaryOp pExpr)
{
return VisitUNARYOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitNEG(ExprUnaryOp pExpr)
{
return VisitUNARYOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitBITNOT(ExprUnaryOp pExpr)
{
return VisitUNARYOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitADDR(ExprUnaryOp pExpr)
{
return VisitUNARYOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitDECIMALNEG(ExprUnaryOp pExpr)
{
return VisitUNARYOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitDECIMALDEC(ExprUnaryOp pExpr)
{
return VisitUNARYOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitFALSE(ExprUnaryOp pExpr)
{
return VisitUNARYOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitDEC(ExprUnaryOp pExpr)
{
return VisitUNARYOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitUPLUS(ExprUnaryOp pExpr)
{
return VisitUNARYOP(pExpr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected virtual Expr VisitDECIMALINC(ExprUnaryOp pExpr)
{
return VisitUNARYOP(pExpr);
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/Visitors/ExpressionTreeRewriter.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/Visitors/ExpressionTreeRewriter.cs
index de14ce440bed50..8ca065a59748fc 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/Visitors/ExpressionTreeRewriter.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/Visitors/ExpressionTreeRewriter.cs
@@ -2,14 +2,17 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using Microsoft.CSharp.RuntimeBinder.Syntax;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
{
internal sealed class ExpressionTreeRewriter : ExprVisitorBase
{
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static ExprBinOp Rewrite(ExprBoundLambda expr) => new ExpressionTreeRewriter().VisitBoundLambda(expr);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected override Expr Dispatch(Expr expr)
{
Debug.Assert(expr != null);
@@ -24,6 +27,7 @@ protected override Expr Dispatch(Expr expr)
/////////////////////////////////////////////////////////////////////////////////
// Statement types.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected override Expr VisitASSIGNMENT(ExprAssignment assignment)
{
Debug.Assert(assignment != null);
@@ -61,10 +65,14 @@ protected override Expr VisitASSIGNMENT(ExprAssignment assignment)
Expr rhs = Visit(assignment.RHS);
return GenerateCall(PREDEFMETH.PM_EXPRESSION_ASSIGN, lhs, rhs);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected override Expr VisitMULTIGET(ExprMultiGet pExpr)
{
return Visit(pExpr.OptionalMulti.Left);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected override Expr VisitMULTI(ExprMulti pExpr)
{
Expr rhs = Visit(pExpr.Operator);
@@ -75,6 +83,7 @@ protected override Expr VisitMULTI(ExprMulti pExpr)
/////////////////////////////////////////////////////////////////////////////////
// Expression types.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private ExprBinOp VisitBoundLambda(ExprBoundLambda anonmeth)
{
Debug.Assert(anonmeth != null);
@@ -97,17 +106,23 @@ private ExprBinOp VisitBoundLambda(ExprBoundLambda anonmeth)
call.PredefinedMethod = PREDEFMETH.PM_EXPRESSION_LAMBDA;
return ExprFactory.CreateSequence(createParameters, call);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected override Expr VisitCONSTANT(ExprConstant expr)
{
Debug.Assert(expr != null);
return GenerateConstant(expr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected override Expr VisitLOCAL(ExprLocal local)
{
Debug.Assert(local != null);
Debug.Assert(local.Local.wrap != null);
return local.Local.wrap;
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected override Expr VisitFIELD(ExprField expr)
{
Debug.Assert(expr != null);
@@ -123,11 +138,15 @@ protected override Expr VisitFIELD(ExprField expr)
ExprFieldInfo pFieldInfo = ExprFactory.CreateFieldInfo(expr.FieldWithType.Field(), expr.FieldWithType.GetType());
return GenerateCall(PREDEFMETH.PM_EXPRESSION_FIELD, pObject, pFieldInfo);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected override Expr VisitUSERDEFINEDCONVERSION(ExprUserDefinedConversion expr)
{
Debug.Assert(expr != null);
return GenerateUserDefinedConversion(expr, expr.Argument);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected override Expr VisitCAST(ExprCast pExpr)
{
Debug.Assert(pExpr != null);
@@ -160,6 +179,8 @@ protected override Expr VisitCAST(ExprCast pExpr)
}
return result;
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected override Expr VisitCONCAT(ExprConcat expr)
{
Debug.Assert(expr != null);
@@ -178,6 +199,8 @@ protected override Expr VisitCONCAT(ExprConcat expr)
Expr methodInfo = ExprFactory.CreateMethodInfo(method, SymbolLoader.GetPredefindType(PredefinedType.PT_STRING), null);
return GenerateCall(PREDEFMETH.PM_EXPRESSION_ADD_USER_DEFINED, p1, p2, methodInfo);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected override Expr VisitBINOP(ExprBinOp expr)
{
Debug.Assert(expr != null);
@@ -190,6 +213,8 @@ protected override Expr VisitBINOP(ExprBinOp expr)
return GenerateBuiltInBinaryOperator(expr);
}
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected override Expr VisitUNARYOP(ExprUnaryOp pExpr)
{
Debug.Assert(pExpr != null);
@@ -202,6 +227,8 @@ protected override Expr VisitUNARYOP(ExprUnaryOp pExpr)
return GenerateBuiltInUnaryOperator(pExpr);
}
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected override Expr VisitARRAYINDEX(ExprArrayIndex pExpr)
{
Debug.Assert(pExpr != null);
@@ -215,6 +242,7 @@ protected override Expr VisitARRAYINDEX(ExprArrayIndex pExpr)
return GenerateCall(PREDEFMETH.PM_EXPRESSION_ARRAYINDEX, arr, args);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected override Expr VisitCALL(ExprCall expr)
{
Debug.Assert(expr != null);
@@ -278,6 +306,8 @@ protected override Expr VisitCALL(ExprCall expr)
return GenerateCall(pdm, pObject, methodInfo, Params);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected override Expr VisitPROP(ExprProperty expr)
{
Debug.Assert(expr != null);
@@ -300,6 +330,8 @@ protected override Expr VisitPROP(ExprProperty expr)
}
return GenerateCall(PREDEFMETH.PM_EXPRESSION_PROPERTY, pObject, propInfo);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected override Expr VisitARRINIT(ExprArrayInit expr)
{
Debug.Assert(expr != null);
@@ -309,17 +341,22 @@ protected override Expr VisitARRINIT(ExprArrayInit expr)
Expr Params = GenerateParamsArray(args, PredefinedType.PT_EXPRESSION);
return GenerateCall(PREDEFMETH.PM_EXPRESSION_NEWARRAYINIT, pTypeOf, Params);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected override Expr VisitZEROINIT(ExprZeroInit expr)
{
Debug.Assert(expr != null);
return GenerateConstant(expr);
}
+
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
protected override Expr VisitTYPEOF(ExprTypeOf expr)
{
Debug.Assert(expr != null);
return GenerateConstant(expr);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr GenerateDelegateInvoke(ExprCall expr)
{
Debug.Assert(expr != null);
@@ -333,6 +370,7 @@ private Expr GenerateDelegateInvoke(ExprCall expr)
return GenerateCall(PREDEFMETH.PM_EXPRESSION_INVOKE, pObject, Params);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr GenerateBuiltInBinaryOperator(ExprBinOp expr)
{
Debug.Assert(expr != null);
@@ -433,6 +471,7 @@ private Expr GenerateBuiltInBinaryOperator(ExprBinOp expr)
return call;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr GenerateBuiltInUnaryOperator(ExprUnaryOp expr)
{
Debug.Assert(expr != null);
@@ -456,6 +495,7 @@ private Expr GenerateBuiltInUnaryOperator(ExprUnaryOp expr)
return GenerateCall(pdm, Visit(origOp));
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr GenerateUserDefinedBinaryOperator(ExprBinOp expr)
{
Debug.Assert(expr != null);
@@ -535,6 +575,7 @@ private Expr GenerateUserDefinedBinaryOperator(ExprBinOp expr)
return call;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr GenerateUserDefinedUnaryOperator(ExprUnaryOp expr)
{
Debug.Assert(expr != null);
@@ -585,6 +626,7 @@ private Expr GenerateUserDefinedUnaryOperator(ExprUnaryOp expr)
return GenerateCall(pdm, op, methodInfo);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr GenerateUserDefinedComparisonOperator(ExprBinOp expr)
{
Debug.Assert(expr != null);
@@ -622,9 +664,11 @@ private Expr GenerateUserDefinedComparisonOperator(ExprBinOp expr)
return GenerateCall(pdm, p1, p2, lift, methodInfo);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr GenerateConversion(Expr arg, CType CType, bool bChecked) =>
GenerateConversionWithSource(Visit(arg), CType, bChecked || arg.isChecked());
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static Expr GenerateConversionWithSource(Expr pTarget, CType pType, bool bChecked)
{
PREDEFMETH pdm = bChecked ? PREDEFMETH.PM_EXPRESSION_CONVERTCHECKED : PREDEFMETH.PM_EXPRESSION_CONVERT;
@@ -632,6 +676,7 @@ private static Expr GenerateConversionWithSource(Expr pTarget, CType pType, bool
return GenerateCall(pdm, pTarget, pTypeOf);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr GenerateValueAccessConversion(Expr pArgument)
{
Debug.Assert(pArgument != null);
@@ -640,12 +685,14 @@ private Expr GenerateValueAccessConversion(Expr pArgument)
return GenerateCall(PREDEFMETH.PM_EXPRESSION_CONVERT, Visit(pArgument), pStrippedTypeExpr);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr GenerateUserDefinedConversion(Expr arg, CType type, MethWithInst method)
{
Expr target = Visit(arg);
return GenerateUserDefinedConversion(arg, type, target, method);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static Expr GenerateUserDefinedConversion(Expr arg, CType CType, Expr target, MethWithInst method)
{
// The user-defined explicit conversion from enum? to decimal or decimal? requires
@@ -688,6 +735,7 @@ private static Expr GenerateUserDefinedConversion(Expr arg, CType CType, Expr ta
return GenerateCall(pdmOuter, callUserDefinedConversion, typeofOuter);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr GenerateUserDefinedConversion(ExprUserDefinedConversion pExpr, Expr pArgument)
{
Expr pCastCall = pExpr.UserDefinedCall;
@@ -736,6 +784,7 @@ private Expr GenerateUserDefinedConversion(ExprUserDefinedConversion pExpr, Expr
return GenerateUserDefinedConversion(pCastArgument, pExpr.Type, pConversionSource, pExpr.UserDefinedCallMethod);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static Expr GenerateParameter(string name, CType CType)
{
SymbolLoader.GetPredefindType(PredefinedType.PT_STRING); // force an ensure state
@@ -744,10 +793,13 @@ private static Expr GenerateParameter(string name, CType CType)
return GenerateCall(PREDEFMETH.PM_EXPRESSION_PARAMETER, pTypeOf, nameString);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static MethodSymbol GetPreDefMethod(PREDEFMETH pdm) => PredefinedMembers.GetMethod(pdm);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static ExprTypeOf CreateTypeOf(CType type) => ExprFactory.CreateTypeOf(type);
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static Expr CreateWraps(ExprBoundLambda anonmeth)
{
Expr sequence = null;
@@ -775,6 +827,7 @@ private static Expr CreateWraps(ExprBoundLambda anonmeth)
return sequence;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr GenerateConstructor(ExprCall expr)
{
Debug.Assert(expr != null);
@@ -785,6 +838,7 @@ private Expr GenerateConstructor(ExprCall expr)
return GenerateCall(PREDEFMETH.PM_EXPRESSION_NEW, constructorInfo, Params);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr GenerateArgsList(Expr oldArgs)
{
Expr newArgs = null;
@@ -797,6 +851,7 @@ private Expr GenerateArgsList(Expr oldArgs)
return newArgs;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Expr GenerateIndexList(Expr oldIndices)
{
CType intType = SymbolLoader.GetPredefindType(PredefinedType.PT_INT);
@@ -817,6 +872,7 @@ private Expr GenerateIndexList(Expr oldIndices)
return newIndices;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static Expr GenerateConstant(Expr expr)
{
EXPRFLAG flags = 0;
@@ -841,6 +897,7 @@ private static Expr GenerateConstant(Expr expr)
return GenerateCall(PREDEFMETH.PM_EXPRESSION_CONSTANT_OBJECT_TYPE, cast, pTypeOf2);
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static ExprCall GenerateCall(PREDEFMETH pdm, Expr arg1)
{
MethodSymbol method = GetPreDefMethod(pdm);
@@ -856,6 +913,7 @@ private static ExprCall GenerateCall(PREDEFMETH pdm, Expr arg1)
return call;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static ExprCall GenerateCall(PREDEFMETH pdm, Expr arg1, Expr arg2)
{
MethodSymbol method = GetPreDefMethod(pdm);
@@ -870,6 +928,7 @@ private static ExprCall GenerateCall(PREDEFMETH pdm, Expr arg1, Expr arg2)
return call;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static ExprCall GenerateCall(PREDEFMETH pdm, Expr arg1, Expr arg2, Expr arg3)
{
MethodSymbol method = GetPreDefMethod(pdm);
@@ -884,6 +943,7 @@ private static ExprCall GenerateCall(PREDEFMETH pdm, Expr arg1, Expr arg2, Expr
return call;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static ExprCall GenerateCall(PREDEFMETH pdm, Expr arg1, Expr arg2, Expr arg3, Expr arg4)
{
MethodSymbol method = GetPreDefMethod(pdm);
@@ -898,6 +958,7 @@ private static ExprCall GenerateCall(PREDEFMETH pdm, Expr arg1, Expr arg2, Expr
return call;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static ExprArrayInit GenerateParamsArray(Expr args, PredefinedType pt)
{
int parameterCount = ExpressionIterator.Count(args);
@@ -907,6 +968,7 @@ private static ExprArrayInit GenerateParamsArray(Expr args, PredefinedType pt)
return ExprFactory.CreateArrayInit(paramsArrayType, args, paramsArrayArg, new int[] { parameterCount });
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static void FixLiftedUserDefinedBinaryOperators(ExprBinOp expr, ref Expr pp1, ref Expr pp2)
{
// If we have lifted T1 op T2 to T1? op T2?, and we have an expression T1 op T2? or T1? op T2 then
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/ZeroInitialize.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/ZeroInitialize.cs
index 1201a30fe38b9e..ec92bf378ca66d 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/ZeroInitialize.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Tree/ZeroInitialize.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Diagnostics.CodeAnalysis;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
{
@@ -12,6 +13,10 @@ public ExprZeroInit(CType type)
{
}
- public override object Object => Activator.CreateInstance(Type.AssociatedSystemType);
+ public override object Object
+ {
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
+ get => Activator.CreateInstance(Type.AssociatedSystemType);
+ }
}
}
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/TypeBind.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/TypeBind.cs
index b46d45fb199291..664705753b75a6 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/TypeBind.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/TypeBind.cs
@@ -3,6 +3,7 @@
using System;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using Microsoft.CSharp.RuntimeBinder.Errors;
using Microsoft.CSharp.RuntimeBinder.Syntax;
@@ -31,6 +32,7 @@ internal enum CheckConstraintsFlags
internal static class TypeBind
{
// Check the constraints of any type arguments in the given Type.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static bool CheckConstraints(CType type, CheckConstraintsFlags flags)
{
type = type.GetNakedType(false);
@@ -117,6 +119,7 @@ public static bool CheckConstraints(CType type, CheckConstraintsFlags flags)
////////////////////////////////////////////////////////////////////////////////
// Check the constraints on the method instantiation.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static void CheckMethConstraints(MethWithInst mwi)
{
Debug.Assert(mwi.Meth() != null && mwi.GetType() != null && mwi.TypeArgs != null);
@@ -133,6 +136,7 @@ public static void CheckMethConstraints(MethWithInst mwi)
// Check whether typeArgs satisfies the constraints of typeVars. The
// typeArgsCls and typeArgsMeth are used for substitution on the bounds. The
// tree and symErr are used for error reporting.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static bool CheckConstraintsCore(Symbol symErr, TypeArray typeVars, TypeArray typeArgs, TypeArray typeArgsCls, TypeArray typeArgsMeth, CheckConstraintsFlags flags)
{
Debug.Assert(typeVars.Count == typeArgs.Count);
@@ -154,6 +158,7 @@ private static bool CheckConstraintsCore(Symbol symErr, TypeArray typeVars, Type
return true;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static bool CheckSingleConstraint(Symbol symErr, TypeParameterType var, CType arg, TypeArray typeArgsCls, TypeArray typeArgsMeth, CheckConstraintsFlags flags)
{
Debug.Assert(!(arg is PointerType));
@@ -298,6 +303,7 @@ private static bool CheckSingleConstraint(Symbol symErr, TypeParameterType var,
// typeBnd could be just about any type (since we added naked type parameter
// constraints).
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static bool SatisfiesBound(CType arg, CType typeBnd)
{
if (typeBnd == arg)
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/AggregateType.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/AggregateType.cs
index 87d4bd745df57a..7eaf5d18a336eb 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/AggregateType.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/AggregateType.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using Microsoft.CSharp.RuntimeBinder.Syntax;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
@@ -75,6 +76,7 @@ public AggregateType(AggregateSymbol parent, TypeArray typeArgsThis, AggregateTy
public AggregateType BaseClass
{
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
get
{
if (_baseType == null)
@@ -110,6 +112,7 @@ public AggregateType BaseClass
public IEnumerable TypeHierarchy
{
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
get
{
if (IsInterfaceType)
@@ -120,11 +123,11 @@ public IEnumerable TypeHierarchy
yield return iface;
}
- yield return PredefinedTypes.GetPredefinedAggregate(PredefinedType.PT_OBJECT).getThisType();
+ yield return GetPredefinedAggregateGetThisTypeWithSuppressedMessage();
}
else
{
- for (AggregateType agg = this; agg != null; agg = agg.BaseClass)
+ for (AggregateType agg = this; agg != null; agg = agg.BaseClassWithSuppressedMessage)
{
yield return agg;
}
@@ -132,6 +135,20 @@ public IEnumerable TypeHierarchy
}
}
+ private AggregateType BaseClassWithSuppressedMessage
+ {
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "Workarounds https://github.com/mono/linker/issues/1906. All usages are marked as unsafe.")]
+ get => BaseClass;
+ }
+
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
+ Justification = "Workarounds https://github.com/mono/linker/issues/1906. All usages are marked as unsafe.")]
+ private static AggregateType GetPredefinedAggregateGetThisTypeWithSuppressedMessage()
+ {
+ return PredefinedTypes.GetPredefinedAggregate(PredefinedType.PT_OBJECT).getThisType();
+ }
+
public TypeArray TypeArgsThis { get; }
public TypeArray TypeArgsAll { get; }
@@ -140,6 +157,7 @@ public IEnumerable TypeHierarchy
private bool IsCollectionType
{
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
get
{
Type sysType = AssociatedSystemType;
@@ -165,6 +183,7 @@ private bool IsCollectionType
public TypeArray WinRTCollectionIfacesAll
{
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
get
{
if (_winrtifacesAll == null)
@@ -281,8 +300,13 @@ public override AggregateType UnderlyingEnumType
}
}
- public override Type AssociatedSystemType => _associatedSystemType ?? (_associatedSystemType = CalculateAssociatedSystemType());
+ public override Type AssociatedSystemType
+ {
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
+ get => _associatedSystemType ?? (_associatedSystemType = CalculateAssociatedSystemType());
+ }
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private Type CalculateAssociatedSystemType()
{
Type uninstantiatedType = OwningAggregate.AssociatedSystemType;
@@ -385,6 +409,7 @@ public override ConstValKind ConstValKind
}
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public override AggregateType GetAts() => this;
}
}
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/ArrayType.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/ArrayType.cs
index ddd5b04e06d824..e4a81400708a87 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/ArrayType.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/ArrayType.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Diagnostics.CodeAnalysis;
using Microsoft.CSharp.RuntimeBinder.Syntax;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
@@ -47,6 +48,7 @@ public CType BaseElementType
public override Type AssociatedSystemType
{
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
get
{
Type elementType = ElementType.AssociatedSystemType;
@@ -60,6 +62,7 @@ public override Type AssociatedSystemType
public override ConstValKind ConstValKind => ConstValKind.IntPtr;
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public override AggregateType GetAts() => SymbolLoader.GetPredefindType(PredefinedType.PT_ARRAY);
}
}
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/NullableType.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/NullableType.cs
index 749ea49018d195..e3ed75d96e9904 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/NullableType.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/NullableType.cs
@@ -25,6 +25,7 @@ public NullableType(CType underlyingType)
UnderlyingType = underlyingType;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public override AggregateType GetAts() =>
_ats ?? (_ats = TypeManager.GetAggregate(TypeManager.GetNullable(), TypeArray.Allocate(UnderlyingType)));
@@ -44,7 +45,11 @@ public override CType StripNubs(out bool wasNullable)
public override bool IsStructType => true;
- public override Type AssociatedSystemType => typeof(Nullable<>).MakeGenericType(UnderlyingType.AssociatedSystemType);
+ public override Type AssociatedSystemType
+ {
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
+ get => typeof(Nullable<>).MakeGenericType(UnderlyingType.AssociatedSystemType);
+ }
public override CType BaseOrParameterOrElementType => UnderlyingType;
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/ParameterModifierType.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/ParameterModifierType.cs
index 655efd160abc29..fdb144ea2fe5f6 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/ParameterModifierType.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/ParameterModifierType.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Diagnostics.CodeAnalysis;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
{
@@ -27,7 +28,11 @@ public ParameterModifierType(CType parameterType, bool isOut)
public CType ParameterType { get; }
- public override Type AssociatedSystemType => ParameterType.AssociatedSystemType.MakeByRefType();
+ public override Type AssociatedSystemType
+ {
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
+ get => ParameterType.AssociatedSystemType.MakeByRefType();
+ }
public override CType BaseOrParameterOrElementType => ParameterType;
}
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/PointerType.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/PointerType.cs
index a216a85f252995..2af60e2197a0a1 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/PointerType.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/PointerType.cs
@@ -19,7 +19,11 @@ public PointerType(CType referentType)
public override bool IsUnsafe() => true;
- public override Type AssociatedSystemType => ReferentType.AssociatedSystemType.MakePointerType();
+ public override Type AssociatedSystemType
+ {
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
+ get => ReferentType.AssociatedSystemType.MakePointerType();
+ }
public override CType BaseOrParameterOrElementType => ReferentType;
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/PredefinedTypes.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/PredefinedTypes.cs
index d8e0b2fc1d92d1..291a1fa7990d9b 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/PredefinedTypes.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/PredefinedTypes.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using Microsoft.CSharp.RuntimeBinder.Syntax;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
@@ -13,6 +14,7 @@ internal static class PredefinedTypes
private static readonly AggregateSymbol[] s_predefSymbols = new AggregateSymbol[(int)PredefinedType.PT_COUNT];
// We want to delay load the predefined symbols as needed.
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static AggregateSymbol DelayLoadPredefSym(PredefinedType pt)
{
AggregateType type = (AggregateType)SymbolTable.GetCTypeFromType(PredefinedTypeFacts.GetAssociatedSystemType(pt));
@@ -29,6 +31,7 @@ internal static AggregateSymbol InitializePredefinedType(AggregateSymbol sym, Pr
return sym;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static AggregateSymbol GetPredefinedAggregate(PredefinedType pt) =>
s_predefSymbols[(int)pt] ?? (s_predefSymbols[(int)pt] = DelayLoadPredefSym(pt));
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/Type.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/Type.cs
index 6023fd80ab1990..9bcc90478d2ea1 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/Type.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/Type.cs
@@ -17,7 +17,11 @@ private protected CType(TypeKind kind)
}
[ExcludeFromCodeCoverage(Justification = "Should only be called through override")]
- public virtual Type AssociatedSystemType => throw Error.InternalCompilerError();
+ public virtual Type AssociatedSystemType
+ {
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
+ get => throw Error.InternalCompilerError();
+ }
public TypeKind TypeKind { get; }
@@ -122,6 +126,7 @@ public virtual CType StripNubs(out bool wasNullable)
public virtual bool IsReferenceType => false;
[ExcludeFromCodeCoverage(Justification = "Should only be called through override")]
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public virtual AggregateType GetAts()
{
Debug.Fail("Bad type for AsAggregateType");
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/TypeManager.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/TypeManager.cs
index d77a6e12d9dc03..539221af9cdc40 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/TypeManager.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/TypeManager.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
@@ -178,6 +179,7 @@ public static ParameterModifierType GetParameterModifier(CType paramType, bool i
return pParamModifier;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static AggregateSymbol GetNullable() => GetPredefAgg(PredefinedType.PT_G_OPTIONAL);
private static CType SubstType(CType typeSrc, TypeArray typeArgsCls, TypeArray typeArgsMeth, bool denormMeth)
@@ -544,6 +546,7 @@ public static bool TypeContainsTyVars(CType type, TypeArray typeVars)
}
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public static AggregateSymbol GetPredefAgg(PredefinedType pt) => PredefinedTypes.GetPredefinedAggregate(pt);
public static AggregateType SubstType(AggregateType typeSrc, SubstContext ctx) =>
@@ -583,6 +586,7 @@ public static TypeParameterType GetTypeParameter(TypeParameterSymbol pSymbol)
// RUNTIME BINDER ONLY CHANGE
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal static CType GetBestAccessibleType(AggregateSymbol context, CType typeSrc)
{
// This method implements the "best accessible type" algorithm for determining the type
@@ -659,6 +663,7 @@ internal static CType GetBestAccessibleType(AggregateSymbol context, CType typeS
return GetPredefAgg(PredefinedType.PT_VALUE).getThisType();
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static bool TryVarianceAdjustmentToGetAccessibleType(AggregateSymbol context, AggregateType typeSrc, out CType typeDst)
{
Debug.Assert(typeSrc != null);
@@ -719,6 +724,7 @@ private static bool TryVarianceAdjustmentToGetAccessibleType(AggregateSymbol con
return true;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static bool TryArrayVarianceAdjustmentToGetAccessibleType(AggregateSymbol context, ArrayType typeSrc, out CType typeDst)
{
Debug.Assert(typeSrc != null);
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/TypeParameterType.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/TypeParameterType.cs
index 51c71edee567b7..9dd7de1f3d4f61 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/TypeParameterType.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/Types/TypeParameterType.cs
@@ -3,6 +3,7 @@
using System;
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using Microsoft.CSharp.RuntimeBinder.Syntax;
@@ -54,11 +55,15 @@ public TypeParameterType(TypeParameterSymbol symbol)
public TypeArray Bounds => Symbol.GetBounds();
- public override Type AssociatedSystemType =>
- (IsMethodTypeParameter
- ? ((MethodInfo)((MethodSymbol)OwningSymbol).AssociatedMemberInfo).GetGenericArguments()
- : ((AggregateSymbol)OwningSymbol).AssociatedSystemType.GetGenericArguments()
- )[IndexInOwnParameters];
+ public override Type AssociatedSystemType
+ {
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
+ get =>
+ (IsMethodTypeParameter
+ ? ((MethodInfo)((MethodSymbol)OwningSymbol).AssociatedMemberInfo).GetGenericArguments()
+ : ((AggregateSymbol)OwningSymbol).AssociatedSystemType.GetGenericArguments()
+ )[IndexInOwnParameters];
+ }
public override FUNDTYPE FundamentalType => FUNDTYPE.FT_VAR;
}
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/UnaOpSig.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/UnaOpSig.cs
index ea31650cb3ebb9..37db7d2722701f 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/UnaOpSig.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/UnaOpSig.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using Microsoft.CSharp.RuntimeBinder.Syntax;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
@@ -49,6 +50,7 @@ public UnaOpFullSig(CType type, PfnBindUnaOp pfn, LiftFlags grflt, UnaOpFuncKind
Set the values of the UnaOpFullSig from the given UnaOpSig. The ExpressionBinder is needed to get
the predefined type. Returns true iff the predef type is found.
***************************************************************************************************/
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
public UnaOpFullSig(ExpressionBinder fnc, UnaOpSig uos)
{
this.pt = uos.pt;
diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/SymbolTable.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/SymbolTable.cs
index a742cc7740ffb5..c2056e5b0d2c32 100644
--- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/SymbolTable.cs
+++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/SymbolTable.cs
@@ -45,6 +45,7 @@ public override bool Equals(object obj)
public override int GetHashCode() => Type.GetHashCode() ^ Name.GetHashCode();
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal static void PopulateSymbolTableWithName(
string name,
IEnumerable typeArguments,
@@ -86,6 +87,7 @@ internal static void PopulateSymbolTableWithName(
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal static SymWithType LookupMember(
string name,
Expr callingObject,
@@ -122,6 +124,7 @@ internal static SymWithType LookupMember(
return mem.SwtFirst();
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static void AddParameterConversions(MethodBase method)
{
foreach (ParameterInfo param in method.GetParameters())
@@ -131,6 +134,7 @@ private static void AddParameterConversions(MethodBase method)
}
#region InheritanceHierarchy
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static void AddNamesOnType(NameHashKey key)
{
Debug.Assert(!s_namesLoadedForEachType.Contains(key));
@@ -144,6 +148,7 @@ private static void AddNamesOnType(NameHashKey key)
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static void AddNamesInInheritanceHierarchy(string name, List inheritance)
{
for (int i = inheritance.Count - 1; i >= 0; --i)
@@ -225,6 +230,7 @@ private static void AddNamesInInheritanceHierarchy(string name, List inher
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static List CreateInheritanceHierarchyList(Type type)
{
List list;
@@ -289,6 +295,7 @@ private static Name GetName(Type type)
#region TypeParameters
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static TypeArray GetMethodTypeParameters(MethodInfo method, MethodSymbol parent)
{
if (method.IsGenericMethod)
@@ -316,6 +323,7 @@ private static TypeArray GetMethodTypeParameters(MethodInfo method, MethodSymbol
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static TypeArray GetAggregateTypeParameters(Type type, AggregateSymbol agg)
{
if (type.IsGenericType)
@@ -373,6 +381,7 @@ private static TypeArray GetAggregateTypeParameters(Type type, AggregateSymbol a
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static TypeParameterType LoadClassTypeParameter(AggregateSymbol parent, Type t)
{
for (AggregateSymbol p = parent; p != null; p = p.parent as AggregateSymbol)
@@ -486,6 +495,7 @@ private static Type GetOriginalTypeParameterType(Type t)
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static TypeParameterType LoadMethodTypeParameter(MethodSymbol parent, Type t)
{
for (Symbol sym = parent.firstChild; sym != null; sym = sym.nextChild)
@@ -567,6 +577,7 @@ private static TypeParameterType AddTypeParameterToSymbolTable(
#region LoadTypeChain
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static CType LoadSymbolsFromType(Type type)
{
List declarationChain = BuildDeclarationChain(type);
@@ -631,6 +642,7 @@ private static CType LoadSymbolsFromType(Type type)
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static TypeParameterType ProcessMethodTypeParameter(MethodInfo methinfo, Type t, AggregateSymbol parent)
{
MethodSymbol meth = FindMatchingMethod(methinfo, parent);
@@ -650,6 +662,7 @@ private static TypeParameterType ProcessMethodTypeParameter(MethodInfo methinfo,
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static CType GetConstructedType(Type type, AggregateSymbol agg)
{
// We've found the one we want, so return it.
@@ -672,7 +685,7 @@ private static CType GetConstructedType(Type type, AggregateSymbol agg)
}
/////////////////////////////////////////////////////////////////////////////////
-
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static CType ProcessSpecialTypeInChain(NamespaceOrAggregateSymbol parent, Type t)
{
if (t.IsGenericParameter)
@@ -703,6 +716,7 @@ private static CType ProcessSpecialTypeInChain(NamespaceOrAggregateSymbol parent
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static List BuildDeclarationChain(Type callingType)
{
// We need to build the parent chain of the calling type. Since we only
@@ -791,6 +805,7 @@ private static NamespaceSymbol AddNamespaceToSymbolTable(NamespaceOrAggregateSym
#region CTypeFromType
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal static CType[] GetCTypeArrayFromTypes(Type[] types)
{
Debug.Assert(types != null);
@@ -813,7 +828,7 @@ internal static CType[] GetCTypeArrayFromTypes(Type[] types)
}
/////////////////////////////////////////////////////////////////////////////////
-
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal static CType GetCTypeFromType(Type type) => type.IsByRef
? TypeManager.GetParameterModifier(LoadSymbolsFromType(type.GetElementType()), false)
: LoadSymbolsFromType(type);
@@ -823,6 +838,7 @@ internal static CType GetCTypeFromType(Type type) => type.IsByRef
#region Aggregates
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static AggregateSymbol AddAggregateToSymbolTable(
NamespaceOrAggregateSymbol parent,
Type type)
@@ -975,6 +991,7 @@ private static AggregateSymbol AddAggregateToSymbolTable(
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static void SetInterfacesOnAggregate(AggregateSymbol aggregate, Type type)
{
if (type.IsGenericType)
@@ -999,6 +1016,7 @@ private static void SetInterfacesOnAggregate(AggregateSymbol aggregate, Type typ
#region Field
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static FieldSymbol AddFieldToSymbolTable(FieldInfo fieldInfo, AggregateSymbol aggregate)
{
FieldSymbol field = SymbolStore.LookupSym(
@@ -1053,6 +1071,7 @@ private static FieldSymbol AddFieldToSymbolTable(FieldInfo fieldInfo, AggregateS
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static void AddEventToSymbolTable(EventInfo eventInfo, AggregateSymbol aggregate, FieldSymbol addedField)
{
EventSymbol ev = SymbolStore.LookupSym(
@@ -1110,6 +1129,7 @@ private static void AddEventToSymbolTable(EventInfo eventInfo, AggregateSymbol a
#region Properties
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal static void AddPredefinedPropertyToSymbolTable(AggregateSymbol type, Name property)
{
AggregateType aggtype = type.getThisType();
@@ -1126,6 +1146,7 @@ internal static void AddPredefinedPropertyToSymbolTable(AggregateSymbol type, Na
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static void AddPropertyToSymbolTable(PropertyInfo property, AggregateSymbol aggregate)
{
Name name;
@@ -1275,6 +1296,7 @@ private static void AddPropertyToSymbolTable(PropertyInfo property, AggregateSym
#region Methods
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal static void AddPredefinedMethodToSymbolTable(AggregateSymbol type, Name methodName)
{
Type t = type.getThisType().AssociatedSystemType;
@@ -1309,6 +1331,7 @@ internal static void AddPredefinedMethodToSymbolTable(AggregateSymbol type, Name
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static MethodSymbol AddMethodToSymbolTable(MethodBase member, AggregateSymbol callingAggregate, MethodKindEnum kind)
{
MethodInfo method = member as MethodInfo;
@@ -1410,6 +1433,7 @@ private static MethodSymbol AddMethodToSymbolTable(MethodBase member, AggregateS
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static void SetParameterDataForMethProp(MethodOrPropertySymbol methProp, ParameterInfo[] parameters)
{
if (parameters.Length > 0)
@@ -1433,6 +1457,7 @@ private static void SetParameterDataForMethProp(MethodOrPropertySymbol methProp,
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static void SetParameterAttributes(MethodOrPropertySymbol methProp, ParameterInfo[] parameters, int i)
{
ParameterInfo parameter = parameters[i];
@@ -1580,6 +1605,7 @@ private static MethodSymbol FindMatchingMethod(MemberInfo method, AggregateSymbo
return null;
}
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static TypeArray CreateParameterArray(MemberInfo associatedInfo, ParameterInfo[] parameters)
{
bool isVarArg = associatedInfo is MethodBase mb && (mb.CallingConvention & CallingConventions.VarArgs) != 0;
@@ -1600,6 +1626,7 @@ private static TypeArray CreateParameterArray(MemberInfo associatedInfo, Paramet
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static CType GetTypeOfParameter(ParameterInfo p, MemberInfo m)
{
Type t = p.ParameterType;
@@ -1648,6 +1675,7 @@ private static bool DoesMethodHaveParameterArray(ParameterInfo[] parameters)
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static SymWithType GetSlotForOverride(MethodInfo method)
{
if (method.IsVirtual && method.IsHideBySig)
@@ -1675,6 +1703,7 @@ private static SymWithType GetSlotForOverride(MethodInfo method)
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static MethodSymbol FindMethodFromMemberInfo(MemberInfo baseMemberInfo)
{
CType t = GetCTypeFromType(baseMemberInfo.DeclaringType);
@@ -1704,6 +1733,7 @@ internal static bool AggregateContainsMethod(AggregateSymbol agg, string szName,
#region Conversions
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
internal static void AddConversionsForType(Type type)
{
if (type.IsInterface)
@@ -1718,6 +1748,7 @@ internal static void AddConversionsForType(Type type)
/////////////////////////////////////////////////////////////////////////////////
+ [RequiresUnreferencedCode(Binder.TrimmerWarning)]
private static void AddConversionsForOneType(Type type)
{
if (type.IsGenericType)
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Abstractions/ref/Microsoft.Extensions.Configuration.Abstractions.cs b/src/libraries/Microsoft.Extensions.Configuration.Abstractions/ref/Microsoft.Extensions.Configuration.Abstractions.cs
index c743a37346c22f..6c83ffe225776b 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Abstractions/ref/Microsoft.Extensions.Configuration.Abstractions.cs
+++ b/src/libraries/Microsoft.Extensions.Configuration.Abstractions/ref/Microsoft.Extensions.Configuration.Abstractions.cs
@@ -15,6 +15,12 @@ public static partial class ConfigurationExtensions
public static string GetConnectionString(this Microsoft.Extensions.Configuration.IConfiguration configuration, string name) { throw null; }
public static Microsoft.Extensions.Configuration.IConfigurationSection GetRequiredSection(this Microsoft.Extensions.Configuration.IConfiguration configuration, string key) { throw null; }
}
+ [System.AttributeUsageAttribute(System.AttributeTargets.Property)]
+ public sealed partial class ConfigurationKeyNameAttribute : System.Attribute
+ {
+ public ConfigurationKeyNameAttribute(string name) { }
+ public string Name { get { throw null; } }
+ }
public static partial class ConfigurationPath
{
public static readonly string KeyDelimiter;
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Abstractions/src/ConfigurationKeyNameAttribute.cs b/src/libraries/Microsoft.Extensions.Configuration.Abstractions/src/ConfigurationKeyNameAttribute.cs
new file mode 100644
index 00000000000000..d9aeb155804f1c
--- /dev/null
+++ b/src/libraries/Microsoft.Extensions.Configuration.Abstractions/src/ConfigurationKeyNameAttribute.cs
@@ -0,0 +1,15 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+
+namespace Microsoft.Extensions.Configuration
+{
+ [AttributeUsage(AttributeTargets.Property)]
+ public sealed class ConfigurationKeyNameAttribute : Attribute
+ {
+ public ConfigurationKeyNameAttribute(string name) => Name = name;
+
+ public string Name { get; }
+ }
+}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs
index 4d2e5cf4889a9a..33aa11eaed985d 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs
@@ -208,7 +208,7 @@ private static void BindProperty(PropertyInfo property, object instance, IConfig
return;
}
- propertyValue = BindInstance(property.PropertyType, propertyValue, config.GetSection(property.Name), options);
+ propertyValue = GetPropertyValue(property, instance, config, options);
if (propertyValue != null && hasSetter)
{
@@ -575,5 +575,48 @@ private static IEnumerable GetAllProperties(Type type)
return allProperties;
}
+
+ private static object GetPropertyValue(PropertyInfo property, object instance, IConfiguration config, BinderOptions options)
+ {
+ string propertyName = GetPropertyName(property);
+ return BindInstance(
+ property.PropertyType,
+ property.GetValue(instance),
+ config.GetSection(propertyName),
+ options);
+ }
+
+ private static string GetPropertyName(MemberInfo property)
+ {
+ if (property == null)
+ {
+ throw new ArgumentNullException(nameof(property));
+ }
+
+ // Check for a custom property name used for configuration key binding
+ foreach (var attributeData in property.GetCustomAttributesData())
+ {
+ if (attributeData.AttributeType != typeof(ConfigurationKeyNameAttribute))
+ {
+ continue;
+ }
+
+ // Ensure ConfigurationKeyName constructor signature matches expectations
+ if (attributeData.ConstructorArguments.Count != 1)
+ {
+ break;
+ }
+
+ // Assumes ConfigurationKeyName constructor first arg is the string key name
+ string name = attributeData
+ .ConstructorArguments[0]
+ .Value?
+ .ToString();
+
+ return !string.IsNullOrWhiteSpace(name) ? name : property.Name;
+ }
+
+ return property.Name;
+ }
}
}
diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationBinderTests.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationBinderTests.cs
index 2195e56c596d8a..734bcf3ed4aca5 100644
--- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationBinderTests.cs
+++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationBinderTests.cs
@@ -34,6 +34,9 @@ public ComplexOptions()
internal string InternalProperty { get; set; }
protected string ProtectedProperty { get; set; }
+ [ConfigurationKeyName("Named_Property")]
+ public string NamedProperty { get; set; }
+
protected string ProtectedPrivateSet { get; private set; }
private string PrivateReadOnly { get; }
@@ -201,6 +204,22 @@ public void CanBindIConfigurationSectionWithDerivedOptionsSection()
Assert.Null(options.Section.Value);
}
+ [Fact]
+ public void CanBindConfigurationKeyNameAttributes()
+ {
+ var dic = new Dictionary
+ {
+ {"Named_Property", "Yo"},
+ };
+ var configurationBuilder = new ConfigurationBuilder();
+ configurationBuilder.AddInMemoryCollection(dic);
+ var config = configurationBuilder.Build();
+
+ var options = config.Get();
+
+ Assert.Equal("Yo", options.NamedProperty);
+ }
+
[Fact]
public void EmptyStringIsNullable()
{
diff --git a/src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/ConfigurationTests.cs b/src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/ConfigurationTests.cs
index 62b2589ad1660f..ac38456fdfb4b7 100644
--- a/src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/ConfigurationTests.cs
+++ b/src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/ConfigurationTests.cs
@@ -901,7 +901,7 @@ public void GetDefaultBasePathForSources()
[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)]
- [SkipOnMono("System.IO.FileSystem.Watcher is not supported on wasm", TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")]
public void CanEnumerateProviders()
{
var config = CreateBuilder()
diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderEngineScope.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderEngineScope.cs
index 656cf9b10c4f1f..b29b4016bc0f5b 100644
--- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderEngineScope.cs
+++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderEngineScope.cs
@@ -176,6 +176,12 @@ private void ClearState()
// try to return to the pool while somebody is trying to access ResolvedServices.
lock (_scopeLock)
{
+ // Don't attempt to dispose if we're already disposed
+ if (_state == null)
+ {
+ return;
+ }
+
// ResolvedServices is never cleared for singletons because there might be a compilation running in background
// trying to get a cached singleton service. If it doesn't find it
// it will try to create a new one which will result in an ObjectDisposedException.
diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceProviderEngineScopeTests.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceProviderEngineScopeTests.cs
index ae36f2e1d64bba..223c6bfd7bc8a9 100644
--- a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceProviderEngineScopeTests.cs
+++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceProviderEngineScopeTests.cs
@@ -21,6 +21,16 @@ public void ResolvedServicesAfterDispose_ThrowsObjectDispose()
Assert.Throws(() => serviceProviderEngineScope.ResolvedServices);
}
+ [Fact]
+ public void DoubleDisposeWorks()
+ {
+ var engine = new FakeEngine();
+ var serviceProviderEngineScope = new ServiceProviderEngineScope(engine);
+ serviceProviderEngineScope.ResolvedServices.Add(new ServiceCacheKey(typeof(IFakeService), 0), null);
+ serviceProviderEngineScope.Dispose();
+ serviceProviderEngineScope.Dispose();
+ }
+
private class FakeEngine : ServiceProviderEngine
{
public FakeEngine() :
diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/tests/AssemblyInfo.cs b/src/libraries/Microsoft.Extensions.DependencyModel/tests/AssemblyInfo.cs
deleted file mode 100644
index 3a74f33d7aa32e..00000000000000
--- a/src/libraries/Microsoft.Extensions.DependencyModel/tests/AssemblyInfo.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using Xunit;
-
-[assembly: ActiveIssue("https://github.com/dotnet/runtime/issues/37669", TestPlatforms.Browser)]
diff --git a/src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/AssemblyInfo.cs b/src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/AssemblyInfo.cs
index 99de9b16c5dfad..b95172c7efbafa 100644
--- a/src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/AssemblyInfo.cs
+++ b/src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/AssemblyInfo.cs
@@ -4,4 +4,4 @@
using System;
using Xunit;
-[assembly: SkipOnMono("Microsoft.Extensions.FileProviders.Physical is not supported on wasm", TestPlatforms.Browser)]
+[assembly: SkipOnPlatform(TestPlatforms.Browser, "Microsoft.Extensions.FileProviders.Physical is not supported on Browser")]
diff --git a/src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/Microsoft.Extensions.FileProviders.Physical.Tests.csproj b/src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/Microsoft.Extensions.FileProviders.Physical.Tests.csproj
index 2f22d08400baa6..d57fed0ca59497 100644
--- a/src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/Microsoft.Extensions.FileProviders.Physical.Tests.csproj
+++ b/src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/Microsoft.Extensions.FileProviders.Physical.Tests.csproj
@@ -4,6 +4,7 @@
Microsoft.Extensions.FileProviders.Physical
$(NetCoreAppCurrent);net461
true
+ true
diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/AssemblyInfo.cs b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/AssemblyInfo.cs
index 51acee789dcde1..aa3d381acc7547 100644
--- a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/AssemblyInfo.cs
+++ b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/AssemblyInfo.cs
@@ -5,5 +5,4 @@
using Microsoft.Extensions.Configuration.UserSecrets;
using Xunit;
-[assembly: ActiveIssue("https://github.com/dotnet/runtime/issues/37669", TestPlatforms.Browser)]
[assembly: UserSecretsId("Microsoft.Extensions.Hosting.Unit.Tests")]
diff --git a/src/libraries/Microsoft.Extensions.Options/src/OptionsFactory.cs b/src/libraries/Microsoft.Extensions.Options/src/OptionsFactory.cs
index f2dcad253fc1c6..f14e2b1e28b1c8 100644
--- a/src/libraries/Microsoft.Extensions.Options/src/OptionsFactory.cs
+++ b/src/libraries/Microsoft.Extensions.Options/src/OptionsFactory.cs
@@ -25,7 +25,7 @@ public class OptionsFactory<[DynamicallyAccessedMembers(Options.DynamicallyAcces
///
/// The configuration actions to run.
/// The initialization actions to run.
- public OptionsFactory(IEnumerable> setups, IEnumerable> postConfigures) : this(setups, postConfigures, validations: null)
+ public OptionsFactory(IEnumerable> setups, IEnumerable> postConfigures) : this(setups, postConfigures, validations: Array.Empty>())
{ }
///
diff --git a/src/libraries/Microsoft.Extensions.Options/tests/Microsoft.Extensions.Options.Tests/OptionsFactoryTests.cs b/src/libraries/Microsoft.Extensions.Options/tests/Microsoft.Extensions.Options.Tests/OptionsFactoryTests.cs
index 061388035ebc95..b89752f4ce0dac 100644
--- a/src/libraries/Microsoft.Extensions.Options/tests/Microsoft.Extensions.Options.Tests/OptionsFactoryTests.cs
+++ b/src/libraries/Microsoft.Extensions.Options/tests/Microsoft.Extensions.Options.Tests/OptionsFactoryTests.cs
@@ -168,6 +168,15 @@ public void CanPostConfigureAllDefaultAndNamedOptions()
Assert.Equal("Default1", factory.Create("1").Message);
}
+ [Fact]
+ public void CanCreateOptionsFactory()
+ {
+ var factory = new OptionsFactory(new IConfigureOptions[0],
+ new IPostConfigureOptions[] { });
+
+ Assert.Equal("", factory.Create("").Message);
+ }
+
public class FakeOptionsSetupA : ConfigureOptions
{
public FakeOptionsSetupA() : base(o => o.Message += "A") { }
diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json
index a740ab7324fbc5..bf3295d6351e2f 100644
--- a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json
+++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json
@@ -2707,8 +2707,6 @@
],
"ios.10": [
"ios.10",
- "ios.9",
- "ios.8",
"ios",
"unix",
"any",
@@ -2717,10 +2715,6 @@
"ios.10-arm": [
"ios.10-arm",
"ios.10",
- "ios.9-arm",
- "ios.9",
- "ios.8-arm",
- "ios.8",
"ios-arm",
"ios",
"unix-arm",
@@ -2731,10 +2725,6 @@
"ios.10-arm64": [
"ios.10-arm64",
"ios.10",
- "ios.9-arm64",
- "ios.9",
- "ios.8-arm64",
- "ios.8",
"ios-arm64",
"ios",
"unix-arm64",
@@ -2745,10 +2735,6 @@
"ios.10-x64": [
"ios.10-x64",
"ios.10",
- "ios.9-x64",
- "ios.9",
- "ios.8-x64",
- "ios.8",
"ios-x64",
"ios",
"unix-x64",
@@ -2759,10 +2745,6 @@
"ios.10-x86": [
"ios.10-x86",
"ios.10",
- "ios.9-x86",
- "ios.9",
- "ios.8-x86",
- "ios.8",
"ios-x86",
"ios",
"unix-x86",
@@ -2773,8 +2755,6 @@
"ios.11": [
"ios.11",
"ios.10",
- "ios.9",
- "ios.8",
"ios",
"unix",
"any",
@@ -2785,10 +2765,6 @@
"ios.11",
"ios.10-arm64",
"ios.10",
- "ios.9-arm64",
- "ios.9",
- "ios.8-arm64",
- "ios.8",
"ios-arm64",
"ios",
"unix-arm64",
@@ -2801,10 +2777,6 @@
"ios.11",
"ios.10-x64",
"ios.10",
- "ios.9-x64",
- "ios.9",
- "ios.8-x64",
- "ios.8",
"ios-x64",
"ios",
"unix-x64",
@@ -2816,8 +2788,6 @@
"ios.12",
"ios.11",
"ios.10",
- "ios.9",
- "ios.8",
"ios",
"unix",
"any",
@@ -2830,10 +2800,6 @@
"ios.11",
"ios.10-arm64",
"ios.10",
- "ios.9-arm64",
- "ios.9",
- "ios.8-arm64",
- "ios.8",
"ios-arm64",
"ios",
"unix-arm64",
@@ -2848,10 +2814,6 @@
"ios.11",
"ios.10-x64",
"ios.10",
- "ios.9-x64",
- "ios.9",
- "ios.8-x64",
- "ios.8",
"ios-x64",
"ios",
"unix-x64",
@@ -2864,8 +2826,6 @@
"ios.12",
"ios.11",
"ios.10",
- "ios.9",
- "ios.8",
"ios",
"unix",
"any",
@@ -2880,10 +2840,6 @@
"ios.11",
"ios.10-arm64",
"ios.10",
- "ios.9-arm64",
- "ios.9",
- "ios.8-arm64",
- "ios.8",
"ios-arm64",
"ios",
"unix-arm64",
@@ -2900,10 +2856,6 @@
"ios.11",
"ios.10-x64",
"ios.10",
- "ios.9-x64",
- "ios.9",
- "ios.8-x64",
- "ios.8",
"ios-x64",
"ios",
"unix-x64",
@@ -2911,78 +2863,28 @@
"any",
"base"
],
- "ios.8": [
- "ios.8",
- "ios",
- "unix",
- "any",
- "base"
- ],
- "ios.8-arm": [
- "ios.8-arm",
- "ios.8",
- "ios-arm",
- "ios",
- "unix-arm",
- "unix",
- "any",
- "base"
- ],
- "ios.8-arm64": [
- "ios.8-arm64",
- "ios.8",
- "ios-arm64",
- "ios",
- "unix-arm64",
- "unix",
- "any",
- "base"
- ],
- "ios.8-x64": [
- "ios.8-x64",
- "ios.8",
- "ios-x64",
- "ios",
- "unix-x64",
- "unix",
- "any",
- "base"
- ],
- "ios.8-x86": [
- "ios.8-x86",
- "ios.8",
- "ios-x86",
- "ios",
- "unix-x86",
- "unix",
- "any",
- "base"
- ],
- "ios.9": [
- "ios.9",
- "ios.8",
- "ios",
- "unix",
- "any",
- "base"
- ],
- "ios.9-arm": [
- "ios.9-arm",
- "ios.9",
- "ios.8-arm",
- "ios.8",
- "ios-arm",
+ "ios.14": [
+ "ios.14",
+ "ios.13",
+ "ios.12",
+ "ios.11",
+ "ios.10",
"ios",
- "unix-arm",
"unix",
"any",
"base"
],
- "ios.9-arm64": [
- "ios.9-arm64",
- "ios.9",
- "ios.8-arm64",
- "ios.8",
+ "ios.14-arm64": [
+ "ios.14-arm64",
+ "ios.14",
+ "ios.13-arm64",
+ "ios.13",
+ "ios.12-arm64",
+ "ios.12",
+ "ios.11-arm64",
+ "ios.11",
+ "ios.10-arm64",
+ "ios.10",
"ios-arm64",
"ios",
"unix-arm64",
@@ -2990,11 +2892,17 @@
"any",
"base"
],
- "ios.9-x64": [
- "ios.9-x64",
- "ios.9",
- "ios.8-x64",
- "ios.8",
+ "ios.14-x64": [
+ "ios.14-x64",
+ "ios.14",
+ "ios.13-x64",
+ "ios.13",
+ "ios.12-x64",
+ "ios.12",
+ "ios.11-x64",
+ "ios.11",
+ "ios.10-x64",
+ "ios.10",
"ios-x64",
"ios",
"unix-x64",
@@ -3002,18 +2910,6 @@
"any",
"base"
],
- "ios.9-x86": [
- "ios.9-x86",
- "ios.9",
- "ios.8-x86",
- "ios.8",
- "ios-x86",
- "ios",
- "unix-x86",
- "unix",
- "any",
- "base"
- ],
"iossimulator": [
"iossimulator",
"ios",
@@ -3053,8 +2949,6 @@
],
"iossimulator.10": [
"iossimulator.10",
- "iossimulator.9",
- "iossimulator.8",
"iossimulator",
"ios",
"unix",
@@ -3064,10 +2958,6 @@
"iossimulator.10-arm64": [
"iossimulator.10-arm64",
"iossimulator.10",
- "iossimulator.9-arm64",
- "iossimulator.9",
- "iossimulator.8-arm64",
- "iossimulator.8",
"iossimulator-arm64",
"iossimulator",
"ios-arm64",
@@ -3080,10 +2970,6 @@
"iossimulator.10-x64": [
"iossimulator.10-x64",
"iossimulator.10",
- "iossimulator.9-x64",
- "iossimulator.9",
- "iossimulator.8-x64",
- "iossimulator.8",
"iossimulator-x64",
"iossimulator",
"ios-x64",
@@ -3096,10 +2982,6 @@
"iossimulator.10-x86": [
"iossimulator.10-x86",
"iossimulator.10",
- "iossimulator.9-x86",
- "iossimulator.9",
- "iossimulator.8-x86",
- "iossimulator.8",
"iossimulator-x86",
"iossimulator",
"ios-x86",
@@ -3112,8 +2994,6 @@
"iossimulator.11": [
"iossimulator.11",
"iossimulator.10",
- "iossimulator.9",
- "iossimulator.8",
"iossimulator",
"ios",
"unix",
@@ -3125,10 +3005,6 @@
"iossimulator.11",
"iossimulator.10-arm64",
"iossimulator.10",
- "iossimulator.9-arm64",
- "iossimulator.9",
- "iossimulator.8-arm64",
- "iossimulator.8",
"iossimulator-arm64",
"iossimulator",
"ios-arm64",
@@ -3143,10 +3019,6 @@
"iossimulator.11",
"iossimulator.10-x64",
"iossimulator.10",
- "iossimulator.9-x64",
- "iossimulator.9",
- "iossimulator.8-x64",
- "iossimulator.8",
"iossimulator-x64",
"iossimulator",
"ios-x64",
@@ -3160,8 +3032,6 @@
"iossimulator.12",
"iossimulator.11",
"iossimulator.10",
- "iossimulator.9",
- "iossimulator.8",
"iossimulator",
"ios",
"unix",
@@ -3175,10 +3045,6 @@
"iossimulator.11",
"iossimulator.10-arm64",
"iossimulator.10",
- "iossimulator.9-arm64",
- "iossimulator.9",
- "iossimulator.8-arm64",
- "iossimulator.8",
"iossimulator-arm64",
"iossimulator",
"ios-arm64",
@@ -3195,10 +3061,6 @@
"iossimulator.11",
"iossimulator.10-x64",
"iossimulator.10",
- "iossimulator.9-x64",
- "iossimulator.9",
- "iossimulator.8-x64",
- "iossimulator.8",
"iossimulator-x64",
"iossimulator",
"ios-x64",
@@ -3213,8 +3075,6 @@
"iossimulator.12",
"iossimulator.11",
"iossimulator.10",
- "iossimulator.9",
- "iossimulator.8",
"iossimulator",
"ios",
"unix",
@@ -3230,10 +3090,6 @@
"iossimulator.11",
"iossimulator.10-arm64",
"iossimulator.10",
- "iossimulator.9-arm64",
- "iossimulator.9",
- "iossimulator.8-arm64",
- "iossimulator.8",
"iossimulator-arm64",
"iossimulator",
"ios-arm64",
@@ -3252,42 +3108,6 @@
"iossimulator.11",
"iossimulator.10-x64",
"iossimulator.10",
- "iossimulator.9-x64",
- "iossimulator.9",
- "iossimulator.8-x64",
- "iossimulator.8",
- "iossimulator-x64",
- "iossimulator",
- "ios-x64",
- "ios",
- "unix-x64",
- "unix",
- "any",
- "base"
- ],
- "iossimulator.8": [
- "iossimulator.8",
- "iossimulator",
- "ios",
- "unix",
- "any",
- "base"
- ],
- "iossimulator.8-arm64": [
- "iossimulator.8-arm64",
- "iossimulator.8",
- "iossimulator-arm64",
- "iossimulator",
- "ios-arm64",
- "ios",
- "unix-arm64",
- "unix",
- "any",
- "base"
- ],
- "iossimulator.8-x64": [
- "iossimulator.8-x64",
- "iossimulator.8",
"iossimulator-x64",
"iossimulator",
"ios-x64",
@@ -3297,32 +3117,29 @@
"any",
"base"
],
- "iossimulator.8-x86": [
- "iossimulator.8-x86",
- "iossimulator.8",
- "iossimulator-x86",
- "iossimulator",
- "ios-x86",
- "ios",
- "unix-x86",
- "unix",
- "any",
- "base"
- ],
- "iossimulator.9": [
- "iossimulator.9",
- "iossimulator.8",
+ "iossimulator.14": [
+ "iossimulator.14",
+ "iossimulator.13",
+ "iossimulator.12",
+ "iossimulator.11",
+ "iossimulator.10",
"iossimulator",
"ios",
"unix",
"any",
"base"
],
- "iossimulator.9-arm64": [
- "iossimulator.9-arm64",
- "iossimulator.9",
- "iossimulator.8-arm64",
- "iossimulator.8",
+ "iossimulator.14-arm64": [
+ "iossimulator.14-arm64",
+ "iossimulator.14",
+ "iossimulator.13-arm64",
+ "iossimulator.13",
+ "iossimulator.12-arm64",
+ "iossimulator.12",
+ "iossimulator.11-arm64",
+ "iossimulator.11",
+ "iossimulator.10-arm64",
+ "iossimulator.10",
"iossimulator-arm64",
"iossimulator",
"ios-arm64",
@@ -3332,11 +3149,17 @@
"any",
"base"
],
- "iossimulator.9-x64": [
- "iossimulator.9-x64",
- "iossimulator.9",
- "iossimulator.8-x64",
- "iossimulator.8",
+ "iossimulator.14-x64": [
+ "iossimulator.14-x64",
+ "iossimulator.14",
+ "iossimulator.13-x64",
+ "iossimulator.13",
+ "iossimulator.12-x64",
+ "iossimulator.12",
+ "iossimulator.11-x64",
+ "iossimulator.11",
+ "iossimulator.10-x64",
+ "iossimulator.10",
"iossimulator-x64",
"iossimulator",
"ios-x64",
@@ -3346,20 +3169,6 @@
"any",
"base"
],
- "iossimulator.9-x86": [
- "iossimulator.9-x86",
- "iossimulator.9",
- "iossimulator.8-x86",
- "iossimulator.8",
- "iossimulator-x86",
- "iossimulator",
- "ios-x86",
- "ios",
- "unix-x86",
- "unix",
- "any",
- "base"
- ],
"linux": [
"linux",
"unix",
diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json
index 9ce5b6033f61e6..ee7d87d932971c 100644
--- a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json
+++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json
@@ -1116,31 +1116,31 @@
},
"ios.10": {
"#import": [
- "ios.9"
+ "ios"
]
},
"ios.10-arm": {
"#import": [
"ios.10",
- "ios.9-arm"
+ "ios-arm"
]
},
"ios.10-arm64": {
"#import": [
"ios.10",
- "ios.9-arm64"
+ "ios-arm64"
]
},
"ios.10-x64": {
"#import": [
"ios.10",
- "ios.9-x64"
+ "ios-x64"
]
},
"ios.10-x86": {
"#import": [
"ios.10",
- "ios.9-x86"
+ "ios-x86"
]
},
"ios.11": {
@@ -1194,62 +1194,21 @@
"ios.12-x64"
]
},
- "ios.8": {
- "#import": [
- "ios"
- ]
- },
- "ios.8-arm": {
- "#import": [
- "ios.8",
- "ios-arm"
- ]
- },
- "ios.8-arm64": {
- "#import": [
- "ios.8",
- "ios-arm64"
- ]
- },
- "ios.8-x64": {
- "#import": [
- "ios.8",
- "ios-x64"
- ]
- },
- "ios.8-x86": {
- "#import": [
- "ios.8",
- "ios-x86"
- ]
- },
- "ios.9": {
- "#import": [
- "ios.8"
- ]
- },
- "ios.9-arm": {
- "#import": [
- "ios.9",
- "ios.8-arm"
- ]
- },
- "ios.9-arm64": {
+ "ios.14": {
"#import": [
- "ios.9",
- "ios.8-arm64"
+ "ios.13"
]
},
- "ios.9-x64": {
+ "ios.14-arm64": {
"#import": [
- "ios.9",
- "ios.8-x64"
+ "ios.14",
+ "ios.13-arm64"
]
},
- "ios.9-x86": {
+ "ios.14-x64": {
"#import": [
- "ios.9",
- "ios.8-x86"
+ "ios.14",
+ "ios.13-x64"
]
},
"iossimulator": {
@@ -1277,25 +1236,25 @@
},
"iossimulator.10": {
"#import": [
- "iossimulator.9"
+ "iossimulator"
]
},
"iossimulator.10-arm64": {
"#import": [
"iossimulator.10",
- "iossimulator.9-arm64"
+ "iossimulator-arm64"
]
},
"iossimulator.10-x64": {
"#import": [
"iossimulator.10",
- "iossimulator.9-x64"
+ "iossimulator-x64"
]
},
"iossimulator.10-x86": {
"#import": [
"iossimulator.10",
- "iossimulator.9-x86"
+ "iossimulator-x86"
]
},
"iossimulator.11": {
@@ -1349,50 +1308,21 @@
"iossimulator.12-x64"
]
},
- "iossimulator.8": {
- "#import": [
- "iossimulator"
- ]
- },
- "iossimulator.8-arm64": {
- "#import": [
- "iossimulator.8",
- "iossimulator-arm64"
- ]
- },
- "iossimulator.8-x64": {
- "#import": [
- "iossimulator.8",
- "iossimulator-x64"
- ]
- },
- "iossimulator.8-x86": {
- "#import": [
- "iossimulator.8",
- "iossimulator-x86"
- ]
- },
- "iossimulator.9": {
- "#import": [
- "iossimulator.8"
- ]
- },
- "iossimulator.9-arm64": {
+ "iossimulator.14": {
"#import": [
- "iossimulator.9",
- "iossimulator.8-arm64"
+ "iossimulator.13"
]
},
- "iossimulator.9-x64": {
+ "iossimulator.14-arm64": {
"#import": [
- "iossimulator.9",
- "iossimulator.8-x64"
+ "iossimulator.14",
+ "iossimulator.13-arm64"
]
},
- "iossimulator.9-x86": {
+ "iossimulator.14-x64": {
"#import": [
- "iossimulator.9",
- "iossimulator.8-x86"
+ "iossimulator.14",
+ "iossimulator.13-x64"
]
},
"linux": {
diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props b/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props
index 75f41db11693e4..16394756f92db7 100644
--- a/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props
+++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props
@@ -83,23 +83,23 @@
unix
arm;x86
- 8;9;10
+ 10
unix
arm64;x64
- 8;9;10;11;12;13
+ 10;11;12;13;14
ios
x86
- 8;9;10
+ 10
ios
arm64;x64
- 8;9;10;11;12;13
+ 10;11;12;13;14
diff --git a/src/libraries/Microsoft.NETCore.Platforms/tests/AssemblyInfo.cs b/src/libraries/Microsoft.NETCore.Platforms/tests/AssemblyInfo.cs
index baad52408c410d..f5a33895866d57 100644
--- a/src/libraries/Microsoft.NETCore.Platforms/tests/AssemblyInfo.cs
+++ b/src/libraries/Microsoft.NETCore.Platforms/tests/AssemblyInfo.cs
@@ -3,4 +3,4 @@
using Xunit;
-[assembly: SkipOnMono("MSBuild is not supported on Browser", TestPlatforms.Browser)]
\ No newline at end of file
+[assembly: SkipOnPlatform(TestPlatforms.Browser, "MSBuild is not supported on Browser")]
\ No newline at end of file
diff --git a/src/libraries/Microsoft.XmlSerializer.Generator/pkg/Microsoft.XmlSerializer.Generator.pkgproj b/src/libraries/Microsoft.XmlSerializer.Generator/pkg/Microsoft.XmlSerializer.Generator.pkgproj
index 8d86c1f65763fc..9dacf5487dad23 100644
--- a/src/libraries/Microsoft.XmlSerializer.Generator/pkg/Microsoft.XmlSerializer.Generator.pkgproj
+++ b/src/libraries/Microsoft.XmlSerializer.Generator/pkg/Microsoft.XmlSerializer.Generator.pkgproj
@@ -4,8 +4,8 @@
- https://go.microsoft.com/fwlink/?LinkID=863421
- https://go.microsoft.com/fwlink/?linkid=858594
+ https://go.microsoft.com/fwlink/?LinkID=863421
+ https://go.microsoft.com/fwlink/?linkid=858594
true
false
@@ -20,4 +20,4 @@
-
\ No newline at end of file
+
diff --git a/src/libraries/Native/Unix/Common/pal_ssl_types.h b/src/libraries/Native/Unix/Common/pal_ssl_types.h
new file mode 100644
index 00000000000000..67e8b6e382ba0c
--- /dev/null
+++ b/src/libraries/Native/Unix/Common/pal_ssl_types.h
@@ -0,0 +1,19 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#pragma once
+
+#include
+
+// Matches managed System.Security.Authentication.SslProtocols
+enum
+{
+ PAL_SslProtocol_None = 0,
+ PAL_SslProtocol_Ssl2 = 12,
+ PAL_SslProtocol_Ssl3 = 48,
+ PAL_SslProtocol_Tls10 = 192,
+ PAL_SslProtocol_Tls11 = 768,
+ PAL_SslProtocol_Tls12 = 3072,
+ PAL_SslProtocol_Tls13 = 12288,
+};
+typedef int32_t PAL_SslProtocol;
diff --git a/src/libraries/Native/Unix/System.Native/CMakeLists.txt b/src/libraries/Native/Unix/System.Native/CMakeLists.txt
index 12245f802024fb..d21e27a561b0f4 100644
--- a/src/libraries/Native/Unix/System.Native/CMakeLists.txt
+++ b/src/libraries/Native/Unix/System.Native/CMakeLists.txt
@@ -47,6 +47,14 @@ else ()
pal_log.c)
endif ()
+if (CLR_CMAKE_TARGET_MACCATALYST)
+ set(NATIVE_SOURCES ${NATIVE_SOURCES}
+ pal_iossupportversion.m)
+else ()
+ list (APPEND NATIVE_SOURCES
+ pal_iossupportversion.c)
+endif ()
+
if (NOT CLR_CMAKE_TARGET_BROWSER)
list (APPEND NATIVE_SOURCES pal_networkchange.c)
endif ()
diff --git a/src/libraries/Native/Unix/System.Native/entrypoints.c b/src/libraries/Native/Unix/System.Native/entrypoints.c
index 5abcf2a91074dd..53e30315ea0c19 100644
--- a/src/libraries/Native/Unix/System.Native/entrypoints.c
+++ b/src/libraries/Native/Unix/System.Native/entrypoints.c
@@ -10,6 +10,7 @@
#include "pal_errno.h"
#include "pal_interfaceaddresses.h"
#include "pal_io.h"
+#include "pal_iossupportversion.h"
#include "pal_log.h"
#include "pal_memory.h"
#include "pal_mount.h"
@@ -237,6 +238,7 @@ static const Entry s_sysNative[] =
DllImportEntry(SystemNative_LowLevelMonitor_Create)
DllImportEntry(SystemNative_CreateAutoreleasePool)
DllImportEntry(SystemNative_DrainAutoreleasePool)
+ DllImportEntry(SystemNative_iOSSupportVersion)
};
EXTERN_C const void* SystemResolveDllImport(const char* name);
diff --git a/src/libraries/Native/Unix/System.Native/pal_autoreleasepool.h b/src/libraries/Native/Unix/System.Native/pal_autoreleasepool.h
index 75d367084666f1..450b51822ffdb4 100644
--- a/src/libraries/Native/Unix/System.Native/pal_autoreleasepool.h
+++ b/src/libraries/Native/Unix/System.Native/pal_autoreleasepool.h
@@ -15,3 +15,9 @@ PALEXPORT void* SystemNative_CreateAutoreleasePool(void);
* Drains and releases a pool created by SystemNative_CreateAutoreleasePool.
*/
PALEXPORT void SystemNative_DrainAutoreleasePool(void* pool);
+
+/**
+ * Ensure that NSThread is in multi-threading mode when POSIX APIs are used to
+ * start new threads.
+ */
+void EnsureNSThreadIsMultiThreaded(void);
diff --git a/src/libraries/Native/Unix/System.Native/pal_autoreleasepool.m b/src/libraries/Native/Unix/System.Native/pal_autoreleasepool.m
index 77030b07bf381c..e5ebd4d247c599 100644
--- a/src/libraries/Native/Unix/System.Native/pal_autoreleasepool.m
+++ b/src/libraries/Native/Unix/System.Native/pal_autoreleasepool.m
@@ -15,7 +15,7 @@ - (void)noop:(id)_
}
@end
-void* SystemNative_CreateAutoreleasePool(void)
+void EnsureNSThreadIsMultiThreaded(void)
{
if (![NSThread isMultiThreaded])
{
@@ -30,7 +30,11 @@ - (void)noop:(id)_
[NSThread detachNewThreadSelector:@selector(noop:) toTarget:placeholderObject withObject:nil];
}
assert([NSThread isMultiThreaded]);
+}
+void* SystemNative_CreateAutoreleasePool(void)
+{
+ EnsureNSThreadIsMultiThreaded();
return [[NSAutoreleasePool alloc] init];
}
diff --git a/src/libraries/Native/Unix/System.Native/pal_iossupportversion.c b/src/libraries/Native/Unix/System.Native/pal_iossupportversion.c
new file mode 100644
index 00000000000000..f338c8ff3acc06
--- /dev/null
+++ b/src/libraries/Native/Unix/System.Native/pal_iossupportversion.c
@@ -0,0 +1,15 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#include "pal_iossupportversion.h"
+#include
+#include "pal_utilities.h"
+
+// These functions should not be used, but they need to be defined
+// to satisfy the tooling we used to enable redirecting P/Invokes
+// for the single file scenario.
+const char* SystemNative_iOSSupportVersion(void)
+{
+ assert_err(false, "iOS support not available on this platform.", EINVAL);
+ return NULL;
+}
diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/TestWithConfigSwitches/AssemblyInfo.cs b/src/libraries/Native/Unix/System.Native/pal_iossupportversion.h
similarity index 53%
rename from src/libraries/System.Diagnostics.DiagnosticSource/tests/TestWithConfigSwitches/AssemblyInfo.cs
rename to src/libraries/Native/Unix/System.Native/pal_iossupportversion.h
index 7fe77fb2043e78..06ca3e1a666f0b 100644
--- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/TestWithConfigSwitches/AssemblyInfo.cs
+++ b/src/libraries/Native/Unix/System.Native/pal_iossupportversion.h
@@ -1,6 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using Xunit;
+#pragma once
-[assembly: ActiveIssue("https://github.com/dotnet/runtime/issues/38433", TestPlatforms.Browser)]
\ No newline at end of file
+#include "pal_compiler.h"
+#include "pal_types.h"
+
+PALEXPORT const char* SystemNative_iOSSupportVersion(void);
diff --git a/src/libraries/Native/Unix/System.Native/pal_iossupportversion.m b/src/libraries/Native/Unix/System.Native/pal_iossupportversion.m
new file mode 100644
index 00000000000000..8199b9822e84ec
--- /dev/null
+++ b/src/libraries/Native/Unix/System.Native/pal_iossupportversion.m
@@ -0,0 +1,18 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#include "pal_iossupportversion.h"
+#include "pal_autoreleasepool.h"
+#import
+
+const char* SystemNative_iOSSupportVersion()
+{
+ EnsureNSThreadIsMultiThreaded();
+
+ @autoreleasepool
+ {
+ NSDictionary *plist = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"];
+ NSString *iOSSupportVersion = (NSString *)[plist objectForKey:@"iOSSupportVersion"];
+ return strdup([iOSSupportVersion UTF8String]);
+ }
+}
diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.c
index d166c23dd86456..280ef1dfbabd02 100644
--- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.c
+++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.c
@@ -15,6 +15,10 @@ jmethodID g_ByteArrayInputStreamReset;
jclass g_Enum;
jmethodID g_EnumOrdinal;
+// java/lang/String
+jclass g_String;
+jmethodID g_StringGetBytes;
+
// java/lang/Throwable
jclass g_ThrowableClass;
jmethodID g_ThrowableGetCause;
@@ -74,8 +78,10 @@ jmethodID g_bitLengthMethod;
jmethodID g_sigNumMethod;
// javax/net/ssl/SSLParameters
-jclass g_sslParamsClass;
-jmethodID g_sslParamsGetProtocolsMethod;
+jclass g_SSLParametersClass;
+jmethodID g_SSLParametersCtor;
+jmethodID g_SSLParametersGetProtocols;
+jmethodID g_SSLParametersSetServerNames;
// javax/net/ssl/SSLContext
jclass g_sslCtxClass;
@@ -115,6 +121,7 @@ jmethodID g_keyPairGenGenKeyPairMethod;
// java/security/KeyStore
jclass g_KeyStoreClass;
+jmethodID g_KeyStoreGetDefaultType;
jmethodID g_KeyStoreGetInstance;
jmethodID g_KeyStoreAliases;
jmethodID g_KeyStoreContainsAlias;
@@ -323,6 +330,10 @@ jmethodID g_EllipticCurveGetB;
jmethodID g_EllipticCurveGetField;
jmethodID g_EllipticCurveGetSeed;
+// java/security/spec/PKCS8EncodedKeySpec
+jclass g_PKCS8EncodedKeySpec;
+jmethodID g_PKCS8EncodedKeySpecCtor;
+
// java/security/spec/X509EncodedKeySpec
jclass g_X509EncodedKeySpecClass;
jmethodID g_X509EncodedKeySpecCtor;
@@ -366,49 +377,70 @@ jmethodID g_IteratorNext;
jclass g_ListClass;
jmethodID g_ListGet;
+// javax/net/ssl/HostnameVerifier
+jclass g_HostnameVerifier;
+jmethodID g_HostnameVerifierVerify;
+
+// javax/net/ssl/HttpsURLConnection
+jclass g_HttpsURLConnection;
+jmethodID g_HttpsURLConnectionGetDefaultHostnameVerifier;
+
+// javax/net/ssl/KeyManagerFactory
+jclass g_KeyManagerFactory;
+jmethodID g_KeyManagerFactoryGetInstance;
+jmethodID g_KeyManagerFactoryInit;
+jmethodID g_KeyManagerFactoryGetKeyManagers;
+
+// javax/net/ssl/SNIHostName
+jclass g_SNIHostName;
+jmethodID g_SNIHostNameCtor;
+
// javax/net/ssl/SSLEngine
jclass g_SSLEngine;
-jmethodID g_SSLEngineSetUseClientModeMethod;
-jmethodID g_SSLEngineGetSessionMethod;
-jmethodID g_SSLEngineBeginHandshakeMethod;
-jmethodID g_SSLEngineWrapMethod;
-jmethodID g_SSLEngineUnwrapMethod;
-jmethodID g_SSLEngineCloseInboundMethod;
-jmethodID g_SSLEngineCloseOutboundMethod;
-jmethodID g_SSLEngineGetHandshakeStatusMethod;
+jmethodID g_SSLEngineGetApplicationProtocol;
+jmethodID g_SSLEngineSetUseClientMode;
+jmethodID g_SSLEngineGetSession;
+jmethodID g_SSLEngineBeginHandshake;
+jmethodID g_SSLEngineWrap;
+jmethodID g_SSLEngineUnwrap;
+jmethodID g_SSLEngineCloseOutbound;
+jmethodID g_SSLEngineGetHandshakeStatus;
+jmethodID g_SSLEngineGetSupportedProtocols;
+jmethodID g_SSLEngineSetEnabledProtocols;
+jmethodID g_SSLEngineSetSSLParameters;
// java/nio/ByteBuffer
jclass g_ByteBuffer;
-jmethodID g_ByteBufferAllocateMethod;
-jmethodID g_ByteBufferPutMethod;
-jmethodID g_ByteBufferPut2Method;
-jmethodID g_ByteBufferPut3Method;
-jmethodID g_ByteBufferFlipMethod;
-jmethodID g_ByteBufferGetMethod;
-jmethodID g_ByteBufferPutBufferMethod;
-jmethodID g_ByteBufferLimitMethod;
-jmethodID g_ByteBufferRemainingMethod;
-jmethodID g_ByteBufferCompactMethod;
-jmethodID g_ByteBufferPositionMethod;
+jmethodID g_ByteBufferAllocate;
+jmethodID g_ByteBufferCompact;
+jmethodID g_ByteBufferFlip;
+jmethodID g_ByteBufferGet;
+jmethodID g_ByteBufferLimit;
+jmethodID g_ByteBufferPosition;
+jmethodID g_ByteBufferPutBuffer;
+jmethodID g_ByteBufferPutByteArray;
+jmethodID g_ByteBufferPutByteArrayWithLength;
+jmethodID g_ByteBufferRemaining;
// javax/net/ssl/SSLContext
jclass g_SSLContext;
+jmethodID g_SSLContextGetDefault;
jmethodID g_SSLContextGetInstanceMethod;
jmethodID g_SSLContextInitMethod;
jmethodID g_SSLContextCreateSSLEngineMethod;
// javax/net/ssl/SSLSession
jclass g_SSLSession;
-jmethodID g_SSLSessionGetApplicationBufferSizeMethod;
-jmethodID g_SSLSessionGetPacketBufferSizeMethod;
+jmethodID g_SSLSessionGetApplicationBufferSize;
+jmethodID g_SSLSessionGetCipherSuite;
+jmethodID g_SSLSessionGetPacketBufferSize;
+jmethodID g_SSLSessionGetPeerCertificates;
+jmethodID g_SSLSessionGetProtocol;
// javax/net/ssl/SSLEngineResult
jclass g_SSLEngineResult;
-jmethodID g_SSLEngineResultGetStatusMethod;
-jmethodID g_SSLEngineResultGetHandshakeStatusMethod;
-
-// javax/net/ssl/TrustManager
-jclass g_TrustManager;
+jmethodID g_SSLEngineResultGetStatus;
+jmethodID g_SSLEngineResultGetHandshakeStatus;
// javax/crypto/KeyAgreement
jclass g_KeyAgreementClass;
@@ -521,11 +553,6 @@ bool TryGetJNIException(JNIEnv* env, jthrowable *ex, bool printException)
return true;
}
-void AssertOnJNIExceptions(JNIEnv* env)
-{
- assert(!CheckJNIExceptions(env));
-}
-
void SaveTo(uint8_t* src, uint8_t** dst, size_t len, bool overwrite)
{
assert(overwrite || !(*dst));
@@ -628,6 +655,9 @@ JNI_OnLoad(JavaVM *vm, void *reserved)
g_Enum = GetClassGRef(env, "java/lang/Enum");
g_EnumOrdinal = GetMethod(env, false, g_Enum, "ordinal", "()I");
+ g_String = GetClassGRef(env, "java/lang/String");
+ g_StringGetBytes = GetMethod(env, false, g_String, "getBytes", "()[B");
+
g_ThrowableClass = GetClassGRef(env, "java/lang/Throwable");
g_ThrowableGetCause = GetMethod(env, false, g_ThrowableClass, "getCause", "()Ljava/lang/Throwable;");
g_ThrowableGetMessage = GetMethod(env, false, g_ThrowableClass, "getMessage", "()Ljava/lang/String;");
@@ -681,8 +711,10 @@ JNI_OnLoad(JavaVM *vm, void *reserved)
g_bitLengthMethod = GetMethod(env, false, g_bigNumClass, "bitLength", "()I");
g_sigNumMethod = GetMethod(env, false, g_bigNumClass, "signum", "()I");
- g_sslParamsClass = GetClassGRef(env, "javax/net/ssl/SSLParameters");
- g_sslParamsGetProtocolsMethod = GetMethod(env, false, g_sslParamsClass, "getProtocols", "()[Ljava/lang/String;");
+ g_SSLParametersClass = GetClassGRef(env, "javax/net/ssl/SSLParameters");
+ g_SSLParametersCtor = GetMethod(env, false, g_SSLParametersClass, "", "()V");
+ g_SSLParametersGetProtocols = GetMethod(env, false, g_SSLParametersClass, "getProtocols", "()[Ljava/lang/String;");
+ g_SSLParametersSetServerNames = GetMethod(env, false, g_SSLParametersClass, "setServerNames", "(Ljava/util/List;)V");
g_sslCtxClass = GetClassGRef(env, "javax/net/ssl/SSLContext");
g_sslCtxGetDefaultMethod = GetMethod(env, true, g_sslCtxClass, "getDefault", "()Ljavax/net/ssl/SSLContext;");
@@ -778,6 +810,7 @@ JNI_OnLoad(JavaVM *vm, void *reserved)
g_keyPairGenGenKeyPairMethod = GetMethod(env, false, g_keyPairGenClass, "genKeyPair", "()Ljava/security/KeyPair;");
g_KeyStoreClass = GetClassGRef(env, "java/security/KeyStore");
+ g_KeyStoreGetDefaultType = GetMethod(env, true, g_KeyStoreClass, "getDefaultType", "()Ljava/lang/String;");
g_KeyStoreGetInstance = GetMethod(env, true, g_KeyStoreClass, "getInstance", "(Ljava/lang/String;)Ljava/security/KeyStore;");
g_KeyStoreAliases = GetMethod(env, false, g_KeyStoreClass, "aliases", "()Ljava/util/Enumeration;");
g_KeyStoreContainsAlias = GetMethod(env, false, g_KeyStoreClass, "containsAlias", "(Ljava/lang/String;)Z");
@@ -885,6 +918,9 @@ JNI_OnLoad(JavaVM *vm, void *reserved)
g_EllipticCurveGetField = GetMethod(env, false, g_EllipticCurveClass, "getField", "()Ljava/security/spec/ECField;");
g_EllipticCurveGetSeed = GetMethod(env, false, g_EllipticCurveClass, "getSeed", "()[B");
+ g_PKCS8EncodedKeySpec = GetClassGRef(env, "java/security/spec/PKCS8EncodedKeySpec");
+ g_PKCS8EncodedKeySpecCtor = GetMethod(env, false, g_PKCS8EncodedKeySpec, "", "([B)V");
+
g_X509EncodedKeySpecClass = GetClassGRef(env, "java/security/spec/X509EncodedKeySpec");
g_X509EncodedKeySpecCtor = GetMethod(env, false, g_X509EncodedKeySpecClass, "", "([B)V");
@@ -919,43 +955,61 @@ JNI_OnLoad(JavaVM *vm, void *reserved)
g_ListClass = GetClassGRef(env, "java/util/List");
g_ListGet = GetMethod(env, false, g_ListClass, "get", "(I)Ljava/lang/Object;");
- g_SSLEngine = GetClassGRef(env, "javax/net/ssl/SSLEngine");
- g_SSLEngineSetUseClientModeMethod = GetMethod(env, false, g_SSLEngine, "setUseClientMode", "(Z)V");
- g_SSLEngineGetSessionMethod = GetMethod(env, false, g_SSLEngine, "getSession", "()Ljavax/net/ssl/SSLSession;");
- g_SSLEngineBeginHandshakeMethod = GetMethod(env, false, g_SSLEngine, "beginHandshake", "()V");
- g_SSLEngineWrapMethod = GetMethod(env, false, g_SSLEngine, "wrap", "(Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;)Ljavax/net/ssl/SSLEngineResult;");
- g_SSLEngineUnwrapMethod = GetMethod(env, false, g_SSLEngine, "unwrap", "(Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;)Ljavax/net/ssl/SSLEngineResult;");
- g_SSLEngineGetHandshakeStatusMethod = GetMethod(env, false, g_SSLEngine, "getHandshakeStatus", "()Ljavax/net/ssl/SSLEngineResult$HandshakeStatus;");
- g_SSLEngineCloseInboundMethod = GetMethod(env, false, g_SSLEngine, "closeInbound", "()V");
- g_SSLEngineCloseOutboundMethod = GetMethod(env, false, g_SSLEngine, "closeOutbound", "()V");
-
- g_ByteBuffer = GetClassGRef(env, "java/nio/ByteBuffer");
- g_ByteBufferAllocateMethod = GetMethod(env, true, g_ByteBuffer, "allocate", "(I)Ljava/nio/ByteBuffer;");
- g_ByteBufferPutMethod = GetMethod(env, false, g_ByteBuffer, "put", "(Ljava/nio/ByteBuffer;)Ljava/nio/ByteBuffer;");
- g_ByteBufferPut2Method = GetMethod(env, false, g_ByteBuffer, "put", "([B)Ljava/nio/ByteBuffer;");
- g_ByteBufferPut3Method = GetMethod(env, false, g_ByteBuffer, "put", "([BII)Ljava/nio/ByteBuffer;");
- g_ByteBufferFlipMethod = GetMethod(env, false, g_ByteBuffer, "flip", "()Ljava/nio/Buffer;");
- g_ByteBufferLimitMethod = GetMethod(env, false, g_ByteBuffer, "limit", "()I");
- g_ByteBufferGetMethod = GetMethod(env, false, g_ByteBuffer, "get", "([B)Ljava/nio/ByteBuffer;");
- g_ByteBufferPutBufferMethod = GetMethod(env, false, g_ByteBuffer, "put", "(Ljava/nio/ByteBuffer;)Ljava/nio/ByteBuffer;");
- g_ByteBufferRemainingMethod = GetMethod(env, false, g_ByteBuffer, "remaining", "()I");
- g_ByteBufferCompactMethod = GetMethod(env, false, g_ByteBuffer, "compact", "()Ljava/nio/ByteBuffer;");
- g_ByteBufferPositionMethod = GetMethod(env, false, g_ByteBuffer, "position", "()I");
+ g_HostnameVerifier = GetClassGRef(env, "javax/net/ssl/HostnameVerifier");
+ g_HostnameVerifierVerify = GetMethod(env, false, g_HostnameVerifier, "verify", "(Ljava/lang/String;Ljavax/net/ssl/SSLSession;)Z");
+
+ g_HttpsURLConnection = GetClassGRef(env, "javax/net/ssl/HttpsURLConnection");
+ g_HttpsURLConnectionGetDefaultHostnameVerifier = GetMethod(env, true, g_HttpsURLConnection, "getDefaultHostnameVerifier", "()Ljavax/net/ssl/HostnameVerifier;");
+
+ g_KeyManagerFactory = GetClassGRef(env, "javax/net/ssl/KeyManagerFactory");
+ g_KeyManagerFactoryGetInstance = GetMethod(env, true, g_KeyManagerFactory, "getInstance", "(Ljava/lang/String;)Ljavax/net/ssl/KeyManagerFactory;");
+ g_KeyManagerFactoryInit = GetMethod(env, false, g_KeyManagerFactory, "init", "(Ljava/security/KeyStore;[C)V");
+ g_KeyManagerFactoryGetKeyManagers = GetMethod(env, false, g_KeyManagerFactory, "getKeyManagers", "()[Ljavax/net/ssl/KeyManager;");
+
+ g_SNIHostName = GetClassGRef(env, "javax/net/ssl/SNIHostName");
+ g_SNIHostNameCtor = GetMethod(env, false, g_SNIHostName, "", "(Ljava/lang/String;)V");
+
+ g_SSLEngine = GetClassGRef(env, "javax/net/ssl/SSLEngine");
+ g_SSLEngineGetApplicationProtocol = GetMethod(env, false, g_SSLEngine, "getApplicationProtocol", "()Ljava/lang/String;");
+ g_SSLEngineSetUseClientMode = GetMethod(env, false, g_SSLEngine, "setUseClientMode", "(Z)V");
+ g_SSLEngineGetSession = GetMethod(env, false, g_SSLEngine, "getSession", "()Ljavax/net/ssl/SSLSession;");
+ g_SSLEngineBeginHandshake = GetMethod(env, false, g_SSLEngine, "beginHandshake", "()V");
+ g_SSLEngineWrap = GetMethod(env, false, g_SSLEngine, "wrap", "(Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;)Ljavax/net/ssl/SSLEngineResult;");
+ g_SSLEngineUnwrap = GetMethod(env, false, g_SSLEngine, "unwrap", "(Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;)Ljavax/net/ssl/SSLEngineResult;");
+ g_SSLEngineGetHandshakeStatus = GetMethod(env, false, g_SSLEngine, "getHandshakeStatus", "()Ljavax/net/ssl/SSLEngineResult$HandshakeStatus;");
+ g_SSLEngineCloseOutbound = GetMethod(env, false, g_SSLEngine, "closeOutbound", "()V");
+ g_SSLEngineGetSupportedProtocols = GetMethod(env, false, g_SSLEngine, "getSupportedProtocols", "()[Ljava/lang/String;");
+ g_SSLEngineSetEnabledProtocols = GetMethod(env, false, g_SSLEngine, "setEnabledProtocols", "([Ljava/lang/String;)V");
+ g_SSLEngineSetSSLParameters = GetMethod(env, false, g_SSLEngine, "setSSLParameters", "(Ljavax/net/ssl/SSLParameters;)V");
+
+ g_ByteBuffer = GetClassGRef(env, "java/nio/ByteBuffer");
+ g_ByteBufferAllocate = GetMethod(env, true, g_ByteBuffer, "allocate", "(I)Ljava/nio/ByteBuffer;");
+ g_ByteBufferCompact = GetMethod(env, false, g_ByteBuffer, "compact", "()Ljava/nio/ByteBuffer;");
+ g_ByteBufferFlip = GetMethod(env, false, g_ByteBuffer, "flip", "()Ljava/nio/Buffer;");
+ g_ByteBufferGet = GetMethod(env, false, g_ByteBuffer, "get", "([B)Ljava/nio/ByteBuffer;");
+ g_ByteBufferLimit = GetMethod(env, false, g_ByteBuffer, "limit", "()I");
+ g_ByteBufferPosition = GetMethod(env, false, g_ByteBuffer, "position", "()I");
+ g_ByteBufferPutBuffer = GetMethod(env, false, g_ByteBuffer, "put", "(Ljava/nio/ByteBuffer;)Ljava/nio/ByteBuffer;");
+ g_ByteBufferPutByteArray = GetMethod(env, false, g_ByteBuffer, "put", "([B)Ljava/nio/ByteBuffer;");
+ g_ByteBufferPutByteArrayWithLength = GetMethod(env, false, g_ByteBuffer, "put", "([BII)Ljava/nio/ByteBuffer;");
+ g_ByteBufferRemaining = GetMethod(env, false, g_ByteBuffer, "remaining", "()I");
g_SSLContext = GetClassGRef(env, "javax/net/ssl/SSLContext");
+ g_SSLContextGetDefault = GetMethod(env, true, g_SSLContext, "getDefault", "()Ljavax/net/ssl/SSLContext;");
g_SSLContextGetInstanceMethod = GetMethod(env, true, g_SSLContext, "getInstance", "(Ljava/lang/String;)Ljavax/net/ssl/SSLContext;");
g_SSLContextInitMethod = GetMethod(env, false, g_SSLContext, "init", "([Ljavax/net/ssl/KeyManager;[Ljavax/net/ssl/TrustManager;Ljava/security/SecureRandom;)V");
g_SSLContextCreateSSLEngineMethod = GetMethod(env, false, g_SSLContext, "createSSLEngine", "()Ljavax/net/ssl/SSLEngine;");
- g_SSLSession = GetClassGRef(env, "javax/net/ssl/SSLSession");
- g_SSLSessionGetApplicationBufferSizeMethod = GetMethod(env, false, g_SSLSession, "getApplicationBufferSize", "()I");
- g_SSLSessionGetPacketBufferSizeMethod = GetMethod(env, false, g_SSLSession, "getPacketBufferSize", "()I");
-
- g_SSLEngineResult = GetClassGRef(env, "javax/net/ssl/SSLEngineResult");
- g_SSLEngineResultGetStatusMethod = GetMethod(env, false, g_SSLEngineResult, "getStatus", "()Ljavax/net/ssl/SSLEngineResult$Status;");
- g_SSLEngineResultGetHandshakeStatusMethod = GetMethod(env, false, g_SSLEngineResult, "getHandshakeStatus", "()Ljavax/net/ssl/SSLEngineResult$HandshakeStatus;");
+ g_SSLSession = GetClassGRef(env, "javax/net/ssl/SSLSession");
+ g_SSLSessionGetApplicationBufferSize = GetMethod(env, false, g_SSLSession, "getApplicationBufferSize", "()I");
+ g_SSLSessionGetCipherSuite = GetMethod(env, false, g_SSLSession, "getCipherSuite", "()Ljava/lang/String;");
+ g_SSLSessionGetPacketBufferSize = GetMethod(env, false, g_SSLSession, "getPacketBufferSize", "()I");
+ g_SSLSessionGetPeerCertificates = GetMethod(env, false, g_SSLSession, "getPeerCertificates", "()[Ljava/security/cert/Certificate;");
+ g_SSLSessionGetProtocol = GetMethod(env, false, g_SSLSession, "getProtocol", "()Ljava/lang/String;");
- g_TrustManager = GetClassGRef(env, "javax/net/ssl/TrustManager");
+ g_SSLEngineResult = GetClassGRef(env, "javax/net/ssl/SSLEngineResult");
+ g_SSLEngineResultGetStatus = GetMethod(env, false, g_SSLEngineResult, "getStatus", "()Ljavax/net/ssl/SSLEngineResult$Status;");
+ g_SSLEngineResultGetHandshakeStatus = GetMethod(env, false, g_SSLEngineResult, "getHandshakeStatus", "()Ljavax/net/ssl/SSLEngineResult$HandshakeStatus;");
g_KeyAgreementClass = GetClassGRef(env, "javax/crypto/KeyAgreement");
g_KeyAgreementGetInstance = GetMethod(env, true, g_KeyAgreementClass, "getInstance", "(Ljava/lang/String;)Ljavax/crypto/KeyAgreement;");
diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.h b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.h
index 1414e740ad3af5..9d6f7199376d0d 100644
--- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.h
+++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.h
@@ -11,6 +11,7 @@
#define FAIL 0
#define SUCCESS 1
+#define INSUFFICIENT_BUFFER -1
extern JavaVM* gJvm;
@@ -23,6 +24,10 @@ extern jmethodID g_ByteArrayInputStreamReset;
extern jclass g_Enum;
extern jmethodID g_EnumOrdinal;
+// java/lang/String
+extern jclass g_String;
+extern jmethodID g_StringGetBytes;
+
// java/lang/Throwable
extern jclass g_ThrowableClass;
extern jmethodID g_ThrowableGetCause;
@@ -82,8 +87,10 @@ extern jmethodID g_bitLengthMethod;
extern jmethodID g_sigNumMethod;
// javax/net/ssl/SSLParameters
-extern jclass g_sslParamsClass;
-extern jmethodID g_sslParamsGetProtocolsMethod;
+extern jclass g_SSLParametersClass;
+extern jmethodID g_SSLParametersCtor;
+extern jmethodID g_SSLParametersGetProtocols;
+extern jmethodID g_SSLParametersSetServerNames;
// javax/net/ssl/SSLContext
extern jclass g_sslCtxClass;
@@ -204,6 +211,7 @@ extern jmethodID g_keyPairGenGenKeyPairMethod;
// java/security/KeyStore
extern jclass g_KeyStoreClass;
+extern jmethodID g_KeyStoreGetDefaultType;
extern jmethodID g_KeyStoreGetInstance;
extern jmethodID g_KeyStoreAliases;
extern jmethodID g_KeyStoreContainsAlias;
@@ -331,6 +339,10 @@ extern jmethodID g_EllipticCurveGetB;
extern jmethodID g_EllipticCurveGetField;
extern jmethodID g_EllipticCurveGetSeed;
+// java/security/spec/PKCS8EncodedKeySpec
+extern jclass g_PKCS8EncodedKeySpec;
+extern jmethodID g_PKCS8EncodedKeySpecCtor;
+
// java/security/spec/X509EncodedKeySpec
extern jclass g_X509EncodedKeySpecClass;
extern jmethodID g_X509EncodedKeySpecCtor;
@@ -351,6 +363,11 @@ extern jclass g_CollectionClass;
extern jmethodID g_CollectionIterator;
extern jmethodID g_CollectionSize;
+// java/util/ArrayList
+extern jclass g_ArrayList;
+extern jmethodID g_ArrayListCtor;
+extern jmethodID g_ArrayListAdd;
+
// java/util/Date
extern jclass g_DateClass;
extern jmethodID g_DateCtor;
@@ -374,49 +391,71 @@ extern jmethodID g_IteratorNext;
extern jclass g_ListClass;
extern jmethodID g_ListGet;
+// javax/net/ssl/HostnameVerifier
+extern jclass g_HostnameVerifier;
+extern jmethodID g_HostnameVerifierVerify;
+
+// javax/net/ssl/HttpsURLConnection
+extern jclass g_HttpsURLConnection;
+extern jmethodID g_HttpsURLConnectionGetDefaultHostnameVerifier;
+
+// javax/net/ssl/KeyManagerFactory
+extern jclass g_KeyManagerFactory;
+extern jmethodID g_KeyManagerFactoryGetInstance;
+extern jmethodID g_KeyManagerFactoryInit;
+extern jmethodID g_KeyManagerFactoryGetKeyManagers;
+
+// javax/net/ssl/SNIHostName
+extern jclass g_SNIHostName;
+extern jmethodID g_SNIHostNameCtor;
+
// javax/net/ssl/SSLEngine
extern jclass g_SSLEngine;
-extern jmethodID g_SSLEngineSetUseClientModeMethod;
-extern jmethodID g_SSLEngineGetSessionMethod;
-extern jmethodID g_SSLEngineBeginHandshakeMethod;
-extern jmethodID g_SSLEngineWrapMethod;
-extern jmethodID g_SSLEngineUnwrapMethod;
-extern jmethodID g_SSLEngineCloseInboundMethod;
-extern jmethodID g_SSLEngineCloseOutboundMethod;
-extern jmethodID g_SSLEngineGetHandshakeStatusMethod;
+extern jmethodID g_SSLEngineGetApplicationProtocol;
+extern jmethodID g_SSLEngineSetUseClientMode;
+extern jmethodID g_SSLEngineGetSession;
+extern jmethodID g_SSLEngineBeginHandshake;
+extern jmethodID g_SSLEngineWrap;
+extern jmethodID g_SSLEngineUnwrap;
+extern jmethodID g_SSLEngineCloseOutbound;
+extern jmethodID g_SSLEngineGetHandshakeStatus;
+extern jmethodID g_SSLEngineGetSupportedProtocols;
+extern jmethodID g_SSLEngineSetEnabledProtocols;
+extern jmethodID g_SSLEngineSetSSLParameters;
// java/nio/ByteBuffer
extern jclass g_ByteBuffer;
-extern jmethodID g_ByteBufferAllocateMethod;
-extern jmethodID g_ByteBufferPutMethod;
-extern jmethodID g_ByteBufferPut2Method;
-extern jmethodID g_ByteBufferPut3Method;
-extern jmethodID g_ByteBufferFlipMethod;
-extern jmethodID g_ByteBufferGetMethod;
-extern jmethodID g_ByteBufferLimitMethod;
-extern jmethodID g_ByteBufferRemainingMethod;
-extern jmethodID g_ByteBufferPutBufferMethod;
-extern jmethodID g_ByteBufferCompactMethod;
-extern jmethodID g_ByteBufferPositionMethod;
+extern jmethodID g_ByteBufferAllocate;
+extern jmethodID g_ByteBufferCompact;
+extern jmethodID g_ByteBufferFlip;
+extern jmethodID g_ByteBufferGet;
+extern jmethodID g_ByteBufferLimit;
+extern jmethodID g_ByteBufferPosition;
+extern jmethodID g_ByteBufferPutBuffer;
+extern jmethodID g_ByteBufferPutByteArray;
+extern jmethodID g_ByteBufferPutByteArrayWithLength;
+extern jmethodID g_ByteBufferRemaining;
// javax/net/ssl/SSLContext
extern jclass g_SSLContext;
+extern jmethodID g_SSLContextGetDefault;
extern jmethodID g_SSLContextGetInstanceMethod;
extern jmethodID g_SSLContextInitMethod;
extern jmethodID g_SSLContextCreateSSLEngineMethod;
+extern jmethodID g_SSLContextCreateSSLEngineWithPeer;
// javax/net/ssl/SSLSession
extern jclass g_SSLSession;
-extern jmethodID g_SSLSessionGetApplicationBufferSizeMethod;
-extern jmethodID g_SSLSessionGetPacketBufferSizeMethod;
+extern jmethodID g_SSLSessionGetApplicationBufferSize;
+extern jmethodID g_SSLSessionGetCipherSuite;
+extern jmethodID g_SSLSessionGetPacketBufferSize;
+extern jmethodID g_SSLSessionGetPeerCertificates;
+extern jmethodID g_SSLSessionGetProtocol;
// javax/net/ssl/SSLEngineResult
extern jclass g_SSLEngineResult;
-extern jmethodID g_SSLEngineResultGetStatusMethod;
-extern jmethodID g_SSLEngineResultGetHandshakeStatusMethod;
-
-// javax/net/ssl/TrustManager
-extern jclass g_TrustManager;
+extern jmethodID g_SSLEngineResultGetStatus;
+extern jmethodID g_SSLEngineResultGetHandshakeStatus;
// javax/crypto/KeyAgreement
extern jclass g_KeyAgreementClass;
@@ -425,13 +464,18 @@ extern jmethodID g_KeyAgreementInit;
extern jmethodID g_KeyAgreementDoPhase;
extern jmethodID g_KeyAgreementGenerateSecret;
-// JNI helpers
+// Logging helpers
#define LOG_DEBUG(fmt, ...) ((void)__android_log_print(ANDROID_LOG_DEBUG, "DOTNET", "%s: " fmt, __FUNCTION__, ## __VA_ARGS__))
#define LOG_INFO(fmt, ...) ((void)__android_log_print(ANDROID_LOG_INFO, "DOTNET", "%s: " fmt, __FUNCTION__, ## __VA_ARGS__))
#define LOG_ERROR(fmt, ...) ((void)__android_log_print(ANDROID_LOG_ERROR, "DOTNET", "%s: " fmt, __FUNCTION__, ## __VA_ARGS__))
+
+// JNI helpers - assume there is a JNIEnv* variable named env
#define JSTRING(str) ((jstring)(*env)->NewStringUTF(env, str))
#define ON_EXCEPTION_PRINT_AND_GOTO(label) if (CheckJNIExceptions(env)) goto label
+// Explicitly ignore jobject return value
+#define IGNORE_RETURN(retval) (*env)->DeleteLocalRef(env, retval)
+
#define INIT_LOCALS(name, ...) \
enum { __VA_ARGS__, count_##name }; \
jobject name[count_##name] = { 0 } \
@@ -470,9 +514,6 @@ bool TryClearJNIExceptions(JNIEnv* env);
// Get any pending JNI exception. Returns true if there was an exception, false otherwise.
bool TryGetJNIException(JNIEnv* env, jthrowable *ex, bool printException);
-// Assert on any JNI exceptions. Prints the exception before asserting.
-void AssertOnJNIExceptions(JNIEnv* env);
-
jmethodID GetMethod(JNIEnv *env, bool isStatic, jclass klass, const char* name, const char* sig);
jmethodID GetOptionalMethod(JNIEnv *env, bool isStatic, jclass klass, const char* name, const char* sig);
jfieldID GetField(JNIEnv *env, bool isStatic, jclass klass, const char* name, const char* sig);
diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_ssl.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_ssl.c
index fb7eac36c0b6f6..e512c77ae66f6b 100644
--- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_ssl.c
+++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_ssl.c
@@ -3,34 +3,51 @@
#include "pal_ssl.h"
-int32_t CryptoNative_OpenSslGetProtocolSupport(SslProtocols protocol)
+PAL_SslProtocol AndroidCryptoNative_SSLGetSupportedProtocols(void)
{
JNIEnv* env = GetJNIEnv();
- jobject sslCtxObj = (*env)->CallStaticObjectMethod(env, g_sslCtxClass, g_sslCtxGetDefaultMethod);
- jobject sslParametersObj = (*env)->CallObjectMethod(env, sslCtxObj, g_sslCtxGetDefaultSslParamsMethod);
- jobjectArray protocols = (jobjectArray)(*env)->CallObjectMethod(env, sslParametersObj, g_sslParamsGetProtocolsMethod);
+ PAL_SslProtocol supported = 0;
+ INIT_LOCALS(loc, context, params, protocols);
- int protocolsCount = (*env)->GetArrayLength(env, protocols);
- int supported = 0;
- for (int i = 0; i < protocolsCount; i++)
+ // SSLContext context = SSLContext.getDefault();
+ // SSLParameters params = context.getDefaultSSLParameters();
+ // String[] protocols = params.getProtocols();
+ loc[context] = (*env)->CallStaticObjectMethod(env, g_sslCtxClass, g_sslCtxGetDefaultMethod);
+ loc[params] = (*env)->CallObjectMethod(env, loc[context], g_sslCtxGetDefaultSslParamsMethod);
+ loc[protocols] = (*env)->CallObjectMethod(env, loc[params], g_SSLParametersGetProtocols);
+
+ const char tlsv1[] = "TLSv1";
+ size_t tlsv1Len = (sizeof(tlsv1) / sizeof(*tlsv1)) - 1;
+
+ jsize count = (*env)->GetArrayLength(env, loc[protocols]);
+ for (int32_t i = 0; i < count; i++)
{
- jstring protocolStr = (jstring) ((*env)->GetObjectArrayElement(env, protocols, i));
- const char* protocolStrPtr = (*env)->GetStringUTFChars(env, protocolStr, NULL);
- if ((!strcmp(protocolStrPtr, "TLSv1") && protocol == PAL_SSL_TLS) ||
- (!strcmp(protocolStrPtr, "TLSv1.1") && protocol == PAL_SSL_TLS11) ||
- (!strcmp(protocolStrPtr, "TLSv1.2") && protocol == PAL_SSL_TLS12) ||
- (!strcmp(protocolStrPtr, "TLSv1.3") && protocol == PAL_SSL_TLS13))
+ jstring protocol = (*env)->GetObjectArrayElement(env, loc[protocols], i);
+ const char* protocolStr = (*env)->GetStringUTFChars(env, protocol, NULL);
+ if (strncmp(protocolStr, tlsv1, tlsv1Len) == 0)
{
- supported = 1;
- (*env)->ReleaseStringUTFChars(env, protocolStr, protocolStrPtr);
- (*env)->DeleteLocalRef(env, protocolStr);
- break;
+ if (strlen(protocolStr) == tlsv1Len)
+ {
+ supported |= PAL_SslProtocol_Tls10;
+ }
+ else if (strcmp(protocolStr + tlsv1Len, ".1") == 0)
+ {
+ supported |= PAL_SslProtocol_Tls11;
+ }
+ else if (strcmp(protocolStr + tlsv1Len, ".2") == 0)
+ {
+ supported |= PAL_SslProtocol_Tls12;
+ }
+ else if (strcmp(protocolStr + tlsv1Len, ".3") == 0)
+ {
+ supported |= PAL_SslProtocol_Tls13;
+ }
}
- (*env)->ReleaseStringUTFChars(env, protocolStr, protocolStrPtr);
- (*env)->DeleteLocalRef(env, protocolStr);
+
+ (*env)->ReleaseStringUTFChars(env, protocol, protocolStr);
+ (*env)->DeleteLocalRef(env, protocol);
}
- (*env)->DeleteLocalRef(env, sslCtxObj);
- (*env)->DeleteLocalRef(env, sslParametersObj);
- (*env)->DeleteLocalRef(env, protocols);
+
+ RELEASE_LOCALS(loc, env);
return supported;
}
diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_ssl.h b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_ssl.h
index 04227972f8175c..d4f1dcd23bd8c8 100644
--- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_ssl.h
+++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_ssl.h
@@ -4,16 +4,9 @@
#pragma once
#include "pal_jni.h"
+#include
-typedef enum
-{
- PAL_SSL_NONE = 0,
- PAL_SSL_SSL2 = 12,
- PAL_SSL_SSL3 = 48,
- PAL_SSL_TLS = 192,
- PAL_SSL_TLS11 = 768,
- PAL_SSL_TLS12 = 3072,
- PAL_SSL_TLS13 = 12288,
-} SslProtocols;
-
-PALEXPORT int32_t CryptoNative_OpenSslGetProtocolSupport(SslProtocols protocol);
+/*
+Get the supported protocols
+*/
+PALEXPORT PAL_SslProtocol AndroidCryptoNative_SSLGetSupportedProtocols(void);
diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_sslstream.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_sslstream.c
index b8ac3849ad6bc7..be336f291b05b5 100644
--- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_sslstream.c
+++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_sslstream.c
@@ -3,97 +3,99 @@
#include "pal_sslstream.h"
-void checkHandshakeStatus(JNIEnv* env, SSLStream* sslStream, int handshakeStatus);
-
-static int getHandshakeStatus(JNIEnv* env, SSLStream* sslStream, jobject engineResult)
+// javax/net/ssl/SSLEngineResult$HandshakeStatus
+enum
{
- AssertOnJNIExceptions(env);
- int status = -1;
- if (engineResult)
- status = GetEnumAsInt(env, (*env)->CallObjectMethod(env, engineResult, g_SSLEngineResultGetHandshakeStatusMethod));
- else
- status = GetEnumAsInt(env, (*env)->CallObjectMethod(env, sslStream->sslEngine, g_SSLEngineGetHandshakeStatusMethod));
- AssertOnJNIExceptions(env);
- return status;
-}
+ HANDSHAKE_STATUS__NOT_HANDSHAKING = 0,
+ HANDSHAKE_STATUS__FINISHED = 1,
+ HANDSHAKE_STATUS__NEED_TASK = 2,
+ HANDSHAKE_STATUS__NEED_WRAP = 3,
+ HANDSHAKE_STATUS__NEED_UNWRAP = 4,
+};
+
+// javax/net/ssl/SSLEngineResult$Status
+enum
+{
+ STATUS__BUFFER_UNDERFLOW = 0,
+ STATUS__BUFFER_OVERFLOW = 1,
+ STATUS__OK = 2,
+ STATUS__CLOSED = 3,
+};
-static void close(JNIEnv* env, SSLStream* sslStream) {
- /*
- sslEngine.closeOutbound();
- checkHandshakeStatus();
- */
+static uint16_t* AllocateString(JNIEnv* env, jstring source);
+
+static PAL_SSLStreamStatus DoHandshake(JNIEnv* env, SSLStream* sslStream);
+static PAL_SSLStreamStatus DoWrap(JNIEnv* env, SSLStream* sslStream, int* handshakeStatus);
+static PAL_SSLStreamStatus DoUnwrap(JNIEnv* env, SSLStream* sslStream, int* handshakeStatus);
- AssertOnJNIExceptions(env);
- (*env)->CallVoidMethod(env, sslStream->sslEngine, g_SSLEngineCloseOutboundMethod);
- checkHandshakeStatus(env, sslStream, getHandshakeStatus(env, sslStream, NULL));
+static bool IsHandshaking(int handshakeStatus)
+{
+ return handshakeStatus != HANDSHAKE_STATUS__NOT_HANDSHAKING && handshakeStatus != HANDSHAKE_STATUS__FINISHED;
}
-static void handleEndOfStream(JNIEnv* env, SSLStream* sslStream) {
- /*
- sslEngine.closeInbound();
- close();
- */
+static PAL_SSLStreamStatus Close(JNIEnv* env, SSLStream* sslStream)
+{
+ // sslEngine.closeOutbound();
+ (*env)->CallVoidMethod(env, sslStream->sslEngine, g_SSLEngineCloseOutbound);
- AssertOnJNIExceptions(env);
- (*env)->CallVoidMethod(env, sslStream->sslEngine, g_SSLEngineCloseInboundMethod);
- close(env, sslStream);
- AssertOnJNIExceptions(env);
+ // Call wrap to clear any remaining data
+ int unused;
+ return DoWrap(env, sslStream, &unused);
}
-static void flush(JNIEnv* env, SSLStream* sslStream)
+static PAL_SSLStreamStatus Flush(JNIEnv* env, SSLStream* sslStream)
{
/*
netOutBuffer.flip();
byte[] data = new byte[netOutBuffer.limit()];
netOutBuffer.get(data);
- WriteToOutputStream(data, 0, data.length);
+ streamWriter(data, 0, data.length);
netOutBuffer.compact();
*/
- AssertOnJNIExceptions(env);
+ PAL_SSLStreamStatus ret = SSLStreamStatus_Error;
- // DeleteLocalRef because we don't need the return value (Buffer)
- (*env)->DeleteLocalRef(env, (*env)->CallObjectMethod(env, sslStream->netOutBuffer, g_ByteBufferFlipMethod));
- int bufferLimit = (*env)->CallIntMethod(env, sslStream->netOutBuffer, g_ByteBufferLimitMethod);
+ IGNORE_RETURN((*env)->CallObjectMethod(env, sslStream->netOutBuffer, g_ByteBufferFlip));
+ int32_t bufferLimit = (*env)->CallIntMethod(env, sslStream->netOutBuffer, g_ByteBufferLimit);
jbyteArray data = (*env)->NewByteArray(env, bufferLimit);
- // DeleteLocalRef because we don't need the return value (Buffer)
- (*env)->DeleteLocalRef(env, (*env)->CallObjectMethod(env, sslStream->netOutBuffer, g_ByteBufferGetMethod, data));
+ IGNORE_RETURN((*env)->CallObjectMethod(env, sslStream->netOutBuffer, g_ByteBufferGet, data));
+ ON_EXCEPTION_PRINT_AND_GOTO(cleanup);
uint8_t* dataPtr = (uint8_t*)malloc((size_t)bufferLimit);
- (*env)->GetByteArrayRegion(env, data, 0, bufferLimit, (jbyte*) dataPtr);
- sslStream->streamWriter(dataPtr, 0, (uint32_t)bufferLimit);
+ (*env)->GetByteArrayRegion(env, data, 0, bufferLimit, (jbyte*)dataPtr);
+ sslStream->streamWriter(dataPtr, bufferLimit);
free(dataPtr);
- // DeleteLocalRef because we don't need the return value (Buffer)
- (*env)->DeleteLocalRef(env, (*env)->CallObjectMethod(env, sslStream->netOutBuffer, g_ByteBufferCompactMethod));
- AssertOnJNIExceptions(env);
+
+ IGNORE_RETURN((*env)->CallObjectMethod(env, sslStream->netOutBuffer, g_ByteBufferCompact));
+ ON_EXCEPTION_PRINT_AND_GOTO(cleanup);
+
+ ret = SSLStreamStatus_OK;
+
+cleanup:
+ (*env)->DeleteLocalRef(env, data);
+ return ret;
}
-static jobject ensureRemaining(JNIEnv* env, SSLStream* sslStream, jobject oldBuffer, int newRemaining)
+static jobject ExpandBuffer(JNIEnv* env, jobject oldBuffer, int32_t newCapacity)
{
- /*
- if (oldBuffer.remaining() < newRemaining) {
- oldBuffer.flip();
- final ByteBuffer newBuffer = ByteBuffer.allocate(oldBuffer.remaining() + newRemaining);
- newBuffer.put(oldBuffer);
- return newBuffer;
- } else {
- return oldBuffer;
- }
- */
-
- AssertOnJNIExceptions(env);
+ // oldBuffer.flip();
+ // ByteBuffer newBuffer = ByteBuffer.allocate(newCapacity);
+ // newBuffer.put(oldBuffer);
+ IGNORE_RETURN((*env)->CallObjectMethod(env, oldBuffer, g_ByteBufferFlip));
+ jobject newBuffer =
+ ToGRef(env, (*env)->CallStaticObjectMethod(env, g_ByteBuffer, g_ByteBufferAllocate, newCapacity));
+ IGNORE_RETURN((*env)->CallObjectMethod(env, newBuffer, g_ByteBufferPutBuffer, oldBuffer));
+ ReleaseGRef(env, oldBuffer);
+ return newBuffer;
+}
- int oldRemaining = (*env)->CallIntMethod(env, oldBuffer, g_ByteBufferRemainingMethod);
+static jobject EnsureRemaining(JNIEnv* env, jobject oldBuffer, int32_t newRemaining)
+{
+ int32_t oldRemaining = (*env)->CallIntMethod(env, oldBuffer, g_ByteBufferRemaining);
if (oldRemaining < newRemaining)
{
- // DeleteLocalRef because we don't need the return value (Buffer)
- (*env)->DeleteLocalRef(env, (*env)->CallObjectMethod(env, oldBuffer, g_ByteBufferFlipMethod));
- jobject newBuffer = ToGRef(env, (*env)->CallStaticObjectMethod(env, g_ByteBuffer, g_ByteBufferAllocateMethod, oldRemaining + newRemaining));
- // DeleteLocalRef because we don't need the return value (Buffer)
- (*env)->DeleteLocalRef(env, (*env)->CallObjectMethod(env, newBuffer, g_ByteBufferPutBufferMethod, oldBuffer));
- ReleaseGRef(env, oldBuffer);
- return newBuffer;
+ return ExpandBuffer(env, oldBuffer, oldRemaining + newRemaining);
}
else
{
@@ -101,314 +103,751 @@ static jobject ensureRemaining(JNIEnv* env, SSLStream* sslStream, jobject oldBuf
}
}
-static void doWrap(JNIEnv* env, SSLStream* sslStream)
+static PAL_SSLStreamStatus DoWrap(JNIEnv* env, SSLStream* sslStream, int* handshakeStatus)
{
- /*
- appOutBuffer.flip();
- final SSLEngineResult result;
- try {
- result = sslEngine.wrap(appOutBuffer, netOutBuffer);
- } catch (SSLException e) {
- return;
- }
- appOutBuffer.compact();
-
- final SSLEngineResult.Status status = result.getStatus();
- switch (status) {
- case OK:
- flush();
- checkHandshakeStatus(result.getHandshakeStatus());
- if (appOutBuffer.position() > 0) doWrap();
- break;
- case CLOSED:
- flush();
- checkHandshakeStatus(result.getHandshakeStatus());
- close();
- break;
- case BUFFER_OVERFLOW:
- netOutBuffer = ensureRemaining(netOutBuffer, sslEngine.getSession().getPacketBufferSize());
- doWrap();
- break;
- }
- */
-
- AssertOnJNIExceptions(env);
+ // appOutBuffer.flip();
+ // SSLEngineResult result = sslEngine.wrap(appOutBuffer, netOutBuffer);
+ IGNORE_RETURN((*env)->CallObjectMethod(env, sslStream->appOutBuffer, g_ByteBufferFlip));
+ jobject result = (*env)->CallObjectMethod(
+ env, sslStream->sslEngine, g_SSLEngineWrap, sslStream->appOutBuffer, sslStream->netOutBuffer);
+ if (CheckJNIExceptions(env))
+ return SSLStreamStatus_Error;
+
+ // appOutBuffer.compact();
+ IGNORE_RETURN((*env)->CallObjectMethod(env, sslStream->appOutBuffer, g_ByteBufferCompact));
+
+ // handshakeStatus = result.getHandshakeStatus();
+ // SSLEngineResult.Status status = result.getStatus();
+ *handshakeStatus = GetEnumAsInt(env, (*env)->CallObjectMethod(env, result, g_SSLEngineResultGetHandshakeStatus));
+ int status = GetEnumAsInt(env, (*env)->CallObjectMethod(env, result, g_SSLEngineResultGetStatus));
+ (*env)->DeleteLocalRef(env, result);
- (*env)->DeleteLocalRef(env, (*env)->CallObjectMethod(env, sslStream->appOutBuffer, g_ByteBufferFlipMethod));
- jobject sslEngineResult = (*env)->CallObjectMethod(env, sslStream->sslEngine, g_SSLEngineWrapMethod, sslStream->appOutBuffer, sslStream->netOutBuffer);
- (*env)->DeleteLocalRef(env, (*env)->CallObjectMethod(env, sslStream->appOutBuffer, g_ByteBufferCompactMethod));
-
- int status = GetEnumAsInt(env, (*env)->CallObjectMethod(env, sslEngineResult, g_SSLEngineResultGetStatusMethod));
switch (status)
{
case STATUS__OK:
- flush(env, sslStream);
- checkHandshakeStatus(env, sslStream, getHandshakeStatus(env, sslStream, sslEngineResult));
- if ((*env)->CallIntMethod(env, sslStream->appOutBuffer, g_ByteBufferPositionMethod) > 0)
- doWrap(env, sslStream);
- break;
+ {
+ return Flush(env, sslStream);
+ }
case STATUS__CLOSED:
- flush(env, sslStream);
- checkHandshakeStatus(env, sslStream, getHandshakeStatus(env, sslStream, sslEngineResult));
- close(env, sslStream);
- break;
- case STATUS__BUFFER_OVERFLOW:
- sslStream->netOutBuffer = ensureRemaining(env, sslStream, sslStream->netOutBuffer, (*env)->CallIntMethod(env, sslStream->sslSession, g_SSLSessionGetPacketBufferSizeMethod));
- doWrap(env, sslStream);
- break;
- }
-}
-
-static void doUnwrap(JNIEnv* env, SSLStream* sslStream)
-{
- /*
- if (netInBuffer.position() == 0)
{
- byte[] tmp = new byte[netInBuffer.limit()];
-
- int count = ReadFromInputStream(tmp, 0, tmp.length);
- if (count == -1) {
- handleEndOfStream();
- return;
- }
- netInBuffer.put(tmp, 0, count);
+ (void)Flush(env, sslStream);
+ (*env)->CallVoidMethod(env, sslStream->sslEngine, g_SSLEngineCloseOutbound);
+ return SSLStreamStatus_Closed;
}
-
- netInBuffer.flip();
- final SSLEngineResult result;
- try {
- result = sslEngine.unwrap(netInBuffer, appInBuffer);
- } catch (SSLException e) {
- return;
+ case STATUS__BUFFER_OVERFLOW:
+ {
+ // Expand buffer
+ // int newCapacity = sslSession.getPacketBufferSize() + netOutBuffer.remaining();
+ int32_t newCapacity = (*env)->CallIntMethod(env, sslStream->sslSession, g_SSLSessionGetPacketBufferSize) +
+ (*env)->CallIntMethod(env, sslStream->netOutBuffer, g_ByteBufferRemaining);
+ sslStream->netOutBuffer = ExpandBuffer(env, sslStream->netOutBuffer, newCapacity);
+ return SSLStreamStatus_OK;
}
- netInBuffer.compact();
- final SSLEngineResult.Status status = result.getStatus();
- switch (status) {
- case OK:
- checkHandshakeStatus(result.getHandshakeStatus());
- break;
- case CLOSED:
- checkHandshakeStatus(result.getHandshakeStatus());
- close();
- break;
- case BUFFER_UNDERFLOW:
- netInBuffer = ensureRemaining(netInBuffer, sslEngine.getSession().getPacketBufferSize());
- doUnwrap();
- break;
- case BUFFER_OVERFLOW:
- appInBuffer = ensureRemaining(appInBuffer, sslEngine.getSession().getApplicationBufferSize());
- doUnwrap();
- break;
+ default:
+ {
+ LOG_ERROR("Unknown SSLEngineResult status: %d", status);
+ return SSLStreamStatus_Error;
}
- */
-
- AssertOnJNIExceptions(env);
+ }
+}
- if ((*env)->CallIntMethod(env, sslStream->netInBuffer, g_ByteBufferPositionMethod) == 0)
+static PAL_SSLStreamStatus DoUnwrap(JNIEnv* env, SSLStream* sslStream, int* handshakeStatus)
+{
+ // if (netInBuffer.position() == 0)
+ // {
+ // byte[] tmp = new byte[netInBuffer.limit()];
+ // int count = streamReader(tmp, 0, tmp.length);
+ // netInBuffer.put(tmp, 0, count);
+ // }
+ if ((*env)->CallIntMethod(env, sslStream->netInBuffer, g_ByteBufferPosition) == 0)
{
- int netInBufferLimit = (*env)->CallIntMethod(env, sslStream->netInBuffer, g_ByteBufferLimitMethod);
+ int netInBufferLimit = (*env)->CallIntMethod(env, sslStream->netInBuffer, g_ByteBufferLimit);
jbyteArray tmp = (*env)->NewByteArray(env, netInBufferLimit);
uint8_t* tmpNative = (uint8_t*)malloc((size_t)netInBufferLimit);
- int count = sslStream->streamReader(tmpNative, 0, (uint32_t)netInBufferLimit);
- if (count == -1)
+ int count = netInBufferLimit;
+ PAL_SSLStreamStatus status = sslStream->streamReader(tmpNative, &count);
+ if (status != SSLStreamStatus_OK)
{
- handleEndOfStream(env, sslStream);
- return;
+ (*env)->DeleteLocalRef(env, tmp);
+ return status;
}
+
(*env)->SetByteArrayRegion(env, tmp, 0, count, (jbyte*)(tmpNative));
- (*env)->DeleteLocalRef(env, (*env)->CallObjectMethod(env, sslStream->netInBuffer, g_ByteBufferPut3Method, tmp, 0, count));
+ IGNORE_RETURN(
+ (*env)->CallObjectMethod(env, sslStream->netInBuffer, g_ByteBufferPutByteArrayWithLength, tmp, 0, count));
free(tmpNative);
(*env)->DeleteLocalRef(env, tmp);
}
- (*env)->DeleteLocalRef(env, (*env)->CallObjectMethod(env, sslStream->netInBuffer, g_ByteBufferFlipMethod));
- jobject sslEngineResult = (*env)->CallObjectMethod(env, sslStream->sslEngine, g_SSLEngineUnwrapMethod, sslStream->netInBuffer, sslStream->appInBuffer);
- (*env)->DeleteLocalRef(env, (*env)->CallObjectMethod(env, sslStream->netInBuffer, g_ByteBufferCompactMethod));
-
- int status = GetEnumAsInt(env, (*env)->CallObjectMethod(env, sslEngineResult, g_SSLEngineResultGetStatusMethod));
+ // netInBuffer.flip();
+ // SSLEngineResult result = sslEngine.unwrap(netInBuffer, appInBuffer);
+ IGNORE_RETURN((*env)->CallObjectMethod(env, sslStream->netInBuffer, g_ByteBufferFlip));
+ jobject result = (*env)->CallObjectMethod(
+ env, sslStream->sslEngine, g_SSLEngineUnwrap, sslStream->netInBuffer, sslStream->appInBuffer);
+ if (CheckJNIExceptions(env))
+ return SSLStreamStatus_Error;
+
+ // netInBuffer.compact();
+ IGNORE_RETURN((*env)->CallObjectMethod(env, sslStream->netInBuffer, g_ByteBufferCompact));
+
+ // handshakeStatus = result.getHandshakeStatus();
+ // SSLEngineResult.Status status = result.getStatus();
+ *handshakeStatus = GetEnumAsInt(env, (*env)->CallObjectMethod(env, result, g_SSLEngineResultGetHandshakeStatus));
+ int status = GetEnumAsInt(env, (*env)->CallObjectMethod(env, result, g_SSLEngineResultGetStatus));
+ (*env)->DeleteLocalRef(env, result);
switch (status)
{
case STATUS__OK:
- checkHandshakeStatus(env, sslStream, getHandshakeStatus(env, sslStream, sslEngineResult));
- break;
+ {
+ return SSLStreamStatus_OK;
+ }
case STATUS__CLOSED:
- checkHandshakeStatus(env, sslStream, getHandshakeStatus(env, sslStream, sslEngineResult));
- close(env, sslStream);
- break;
+ {
+ return Close(env, sslStream);
+ }
case STATUS__BUFFER_UNDERFLOW:
- sslStream->netInBuffer = ensureRemaining(env, sslStream, sslStream->netInBuffer, (*env)->CallIntMethod(env, sslStream->sslSession, g_SSLSessionGetPacketBufferSizeMethod));
- doUnwrap(env, sslStream);
- break;
+ {
+ // Expand buffer
+ // int newRemaining = sslSession.getPacketBufferSize();
+ int32_t newRemaining = (*env)->CallIntMethod(env, sslStream->sslSession, g_SSLSessionGetPacketBufferSize);
+ sslStream->netInBuffer = EnsureRemaining(env, sslStream->netInBuffer, newRemaining);
+ return SSLStreamStatus_OK;
+ }
case STATUS__BUFFER_OVERFLOW:
- sslStream->appInBuffer = ensureRemaining(env, sslStream, sslStream->appInBuffer, (*env)->CallIntMethod(env, sslStream->sslSession, g_SSLSessionGetApplicationBufferSizeMethod));
- doUnwrap(env, sslStream);
- break;
+ {
+ // Expand buffer
+ // int newCapacity = sslSession.getApplicationBufferSize() + appInBuffer.remaining();
+ int32_t newCapacity =
+ (*env)->CallIntMethod(env, sslStream->sslSession, g_SSLSessionGetApplicationBufferSize) +
+ (*env)->CallIntMethod(env, sslStream->appInBuffer, g_ByteBufferRemaining);
+ sslStream->appInBuffer = ExpandBuffer(env, sslStream->appInBuffer, newCapacity);
+ return SSLStreamStatus_OK;
+ }
+ default:
+ {
+ LOG_ERROR("Unknown SSLEngineResult status: %d", status);
+ return SSLStreamStatus_Error;
+ }
}
}
-void checkHandshakeStatus(JNIEnv* env, SSLStream* sslStream, int handshakeStatus)
+static PAL_SSLStreamStatus DoHandshake(JNIEnv* env, SSLStream* sslStream)
{
- /*
- switch (handshakeStatus) {
- case NEED_WRAP:
- doWrap();
+ assert(env != NULL);
+ assert(sslStream != NULL);
+
+ PAL_SSLStreamStatus status = SSLStreamStatus_OK;
+ int handshakeStatus =
+ GetEnumAsInt(env, (*env)->CallObjectMethod(env, sslStream->sslEngine, g_SSLEngineGetHandshakeStatus));
+ while (IsHandshaking(handshakeStatus) && status == SSLStreamStatus_OK)
+ {
+ switch (handshakeStatus)
+ {
+ case HANDSHAKE_STATUS__NEED_WRAP:
+ status = DoWrap(env, sslStream, &handshakeStatus);
break;
- case NEED_UNWRAP:
- doUnwrap();
+ case HANDSHAKE_STATUS__NEED_UNWRAP:
+ status = DoUnwrap(env, sslStream, &handshakeStatus);
break;
- case NEED_TASK:
- Runnable task;
- while ((task = sslEngine.getDelegatedTask()) != null) task.run();
- checkHandshakeStatus();
+ case HANDSHAKE_STATUS__NOT_HANDSHAKING:
+ case HANDSHAKE_STATUS__FINISHED:
+ status = SSLStreamStatus_OK;
break;
+ case HANDSHAKE_STATUS__NEED_TASK:
+ assert(0 && "unexpected NEED_TASK handshake status");
}
- */
+ }
+
+ return status;
+}
+
+static void FreeSSLStream(JNIEnv* env, SSLStream* sslStream)
+{
+ assert(sslStream != NULL);
+ ReleaseGRef(env, sslStream->sslContext);
+ ReleaseGRef(env, sslStream->sslEngine);
+ ReleaseGRef(env, sslStream->sslSession);
+ ReleaseGRef(env, sslStream->appOutBuffer);
+ ReleaseGRef(env, sslStream->netOutBuffer);
+ ReleaseGRef(env, sslStream->netInBuffer);
+ ReleaseGRef(env, sslStream->appInBuffer);
+ free(sslStream);
+}
+
+SSLStream* AndroidCryptoNative_SSLStreamCreate(void)
+{
+ JNIEnv* env = GetJNIEnv();
+
+ // TODO: [AndroidCrypto] If we have certificates, get an SSLContext instance with the highest available
+ // protocol - TLSv1.2 (API level 16+) or TLSv1.3 (API level 29+), use KeyManagerFactory to create key
+ // managers that will return the certificates, and initialize the SSLContext with the key managers.
+
+ // SSLContext sslContext = SSLContext.getDefault();
+ jobject sslContext = (*env)->CallStaticObjectMethod(env, g_SSLContext, g_SSLContextGetDefault);
+ if (CheckJNIExceptions(env))
+ return NULL;
+
+ SSLStream* sslStream = malloc(sizeof(SSLStream));
+ memset(sslStream, 0, sizeof(SSLStream));
+ sslStream->sslContext = ToGRef(env, sslContext);
+ return sslStream;
+}
- AssertOnJNIExceptions(env);
- switch (handshakeStatus)
+static int32_t AddCertChainToStore(JNIEnv* env,
+ jobject store,
+ uint8_t* pkcs8PrivateKey,
+ int32_t pkcs8PrivateKeyLen,
+ PAL_KeyAlgorithm algorithm,
+ jobject* /*X509Certificate[]*/ certs,
+ int32_t certsLen)
+{
+ int32_t ret = FAIL;
+ INIT_LOCALS(loc, keyBytes, keySpec, algorithmName, keyFactory, privateKey, certArray, alias);
+
+ // byte[] keyBytes = new byte[] { };
+ // PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
+ loc[keyBytes] = (*env)->NewByteArray(env, pkcs8PrivateKeyLen);
+ (*env)->SetByteArrayRegion(env, loc[keyBytes], 0, pkcs8PrivateKeyLen, (jbyte*)pkcs8PrivateKey);
+ loc[keySpec] = (*env)->NewObject(env, g_PKCS8EncodedKeySpec, g_PKCS8EncodedKeySpecCtor, loc[keyBytes]);
+
+ switch (algorithm)
{
- case HANDSHAKE_STATUS__NEED_WRAP:
- doWrap(env, sslStream);
+ case PAL_DSA:
+ loc[algorithmName] = JSTRING("DSA");
+ break;
+ case PAL_EC:
+ loc[algorithmName] = JSTRING("EC");
break;
- case HANDSHAKE_STATUS__NEED_UNWRAP:
- doUnwrap(env, sslStream);
+ case PAL_RSA:
+ loc[algorithmName] = JSTRING("RSA");
break;
- case HANDSHAKE_STATUS__NEED_TASK:
- assert(0 && "unexpected NEED_TASK handshake status");
+ default:
+ LOG_ERROR("Unknown key algorithm: %d", algorithm);
+ goto cleanup;
+ }
+
+ // KeyFactory keyFactory = KeyFactory.getInstance(algorithmName);
+ // PrivateKey privateKey = keyFactory.generatePrivate(spec);
+ loc[keyFactory] =
+ (*env)->CallStaticObjectMethod(env, g_KeyFactoryClass, g_KeyFactoryGetInstanceMethod, loc[algorithmName]);
+ loc[privateKey] = (*env)->CallObjectMethod(env, loc[keyFactory], g_KeyFactoryGenPrivateMethod, loc[keySpec]);
+
+ // X509Certificate[] certArray = new X509Certificate[certsLen];
+ loc[certArray] = (*env)->NewObjectArray(env, certsLen, g_X509CertClass, NULL);
+ for (int32_t i = 0; i < certsLen; ++i)
+ {
+ (*env)->SetObjectArrayElement(env, loc[certArray], i, certs[i]);
+ ON_EXCEPTION_PRINT_AND_GOTO(cleanup);
}
+
+ // store.setKeyEntry("SSLCertificateContext", privateKey, null, certArray);
+ loc[alias] = JSTRING("SSLCertificateContext");
+ (*env)->CallVoidMethod(env, store, g_KeyStoreSetKeyEntry, loc[alias], loc[privateKey], NULL, loc[certArray]);
+ ON_EXCEPTION_PRINT_AND_GOTO(cleanup);
+
+ ret = SUCCESS;
+
+cleanup:
+ RELEASE_LOCALS(loc, env);
+ return ret;
}
-SSLStream* AndroidCryptoNative_SSLStreamCreateAndStartHandshake(
- STREAM_READER streamReader,
- STREAM_WRITER streamWriter,
- int tlsVersion,
- int appOutBufferSize,
- int appInBufferSize)
+SSLStream* AndroidCryptoNative_SSLStreamCreateWithCertificates(uint8_t* pkcs8PrivateKey,
+ int32_t pkcs8PrivateKeyLen,
+ PAL_KeyAlgorithm algorithm,
+ jobject* /*X509Certificate[]*/ certs,
+ int32_t certsLen)
{
+ SSLStream* sslStream = NULL;
JNIEnv* env = GetJNIEnv();
- /*
- SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
- sslContext.init(null, new TrustManage r[]{trustAllCerts}, null);
- this.sslEngine = sslContext.createSSLEngine();
- this.sslEngine.setUseClientMode(true);
- SSLSession sslSession = sslEngine.getSession();
- final int applicationBufferSize = sslSession.getApplicationBufferSize();
- final int packetBufferSize = sslSession.getPacketBufferSize();
- this.appOutBuffer = ByteBuffer.allocate(appOutBufferSize);
- this.netOutBuffer = ByteBuffer.allocate(packetBufferSize);
- this.netInBuffer = ByteBuffer.allocate(packetBufferSize);
- this.appInBuffer = ByteBuffer.allocate(Math.max(applicationBufferSize, appInBufferSize));
- sslEngine.beginHandshake();
- */
-
- SSLStream* sslStream = malloc(sizeof(SSLStream));
- jobject tlsVerStr = NULL;
- if (tlsVersion == 11)
- tlsVerStr = JSTRING("TLSv1.1");
- else if (tlsVersion == 12)
- tlsVerStr = JSTRING("TLSv1.2");
- else if (tlsVersion == 13)
- tlsVerStr = JSTRING("TLSv1.3");
- else
- assert(0 && "unknown tlsVersion");
+ INIT_LOCALS(loc, tls13, sslContext, ksType, keyStore, kmfType, kmf, keyManagers);
- sslStream->sslContext = ToGRef(env, (*env)->CallStaticObjectMethod(env, g_SSLContext, g_SSLContextGetInstanceMethod, tlsVerStr));
+ // SSLContext sslContext = SSLContext.getInstance("TLSv1.3");
+ loc[tls13] = JSTRING("TLSv1.3");
+ loc[sslContext] = (*env)->CallStaticObjectMethod(env, g_SSLContext, g_SSLContextGetInstanceMethod, loc[tls13]);
+ if (TryClearJNIExceptions(env))
+ {
+ // TLSv1.3 is only supported on API level 29+ - fall back to TLSv1.2 (which is supported on API level 16+)
+ // sslContext = SSLContext.getInstance("TLSv1.2");
+ jobject tls12 = JSTRING("TLSv1.2");
+ loc[sslContext] = (*env)->CallStaticObjectMethod(env, g_SSLContext, g_SSLContextGetInstanceMethod, tls12);
+ ReleaseLRef(env, tls12);
+ ON_EXCEPTION_PRINT_AND_GOTO(cleanup);
+ }
- // TODO: set TrustManager[] argument to be able to intercept cert validation process (and callback to C#).
- (*env)->CallVoidMethod(env, sslStream->sslContext, g_SSLContextInitMethod, NULL, NULL, NULL);
- sslStream->sslEngine = ToGRef(env, (*env)->CallObjectMethod(env, sslStream->sslContext, g_SSLContextCreateSSLEngineMethod));
- sslStream->sslSession = ToGRef(env, (*env)->CallObjectMethod(env, sslStream->sslEngine, g_SSLEngineGetSessionMethod));
+ // String ksType = KeyStore.getDefaultType();
+ // KeyStore keyStore = KeyStore.getInstance(ksType);
+ // keyStore.load(null, null);
+ loc[ksType] = (*env)->CallStaticObjectMethod(env, g_KeyStoreClass, g_KeyStoreGetDefaultType);
+ loc[keyStore] = (*env)->CallStaticObjectMethod(env, g_KeyStoreClass, g_KeyStoreGetInstance, loc[ksType]);
+ ON_EXCEPTION_PRINT_AND_GOTO(cleanup);
+ (*env)->CallVoidMethod(env, loc[keyStore], g_KeyStoreLoad, NULL, NULL);
+ ON_EXCEPTION_PRINT_AND_GOTO(cleanup);
+
+ int32_t status =
+ AddCertChainToStore(env, loc[keyStore], pkcs8PrivateKey, pkcs8PrivateKeyLen, algorithm, certs, certsLen);
+ if (status != SUCCESS)
+ goto cleanup;
+
+ // String kmfType = "PKIX";
+ // KeyManagerFactory kmf = KeyManagerFactory.getInstance(kmfType);
+ loc[kmfType] = JSTRING("PKIX");
+ loc[kmf] = (*env)->CallStaticObjectMethod(env, g_KeyManagerFactory, g_KeyManagerFactoryGetInstance, loc[kmfType]);
+ ON_EXCEPTION_PRINT_AND_GOTO(cleanup);
+
+ // kmf.init(keyStore, null);
+ (*env)->CallVoidMethod(env, loc[kmf], g_KeyManagerFactoryInit, loc[keyStore], NULL);
+ ON_EXCEPTION_PRINT_AND_GOTO(cleanup);
+
+ // KeyManager[] keyManagers = kmf.getKeyManagers();
+ // sslContext.init(keyManagers, null, null);
+ loc[keyManagers] = (*env)->CallObjectMethod(env, loc[kmf], g_KeyManagerFactoryGetKeyManagers);
+ ON_EXCEPTION_PRINT_AND_GOTO(cleanup);
+ (*env)->CallVoidMethod(env, loc[sslContext], g_SSLContextInitMethod, loc[keyManagers], NULL, NULL);
+ ON_EXCEPTION_PRINT_AND_GOTO(cleanup);
+
+ sslStream = malloc(sizeof(SSLStream));
+ memset(sslStream, 0, sizeof(SSLStream));
+ sslStream->sslContext = ToGRef(env, loc[sslContext]);
+ loc[sslContext] = NULL;
+
+cleanup:
+ RELEASE_LOCALS(loc, env);
+ return sslStream;
+}
- int applicationBufferSize = (*env)->CallIntMethod(env, sslStream->sslSession, g_SSLSessionGetApplicationBufferSizeMethod);
- int packetBufferSize = (*env)->CallIntMethod(env, sslStream->sslSession, g_SSLSessionGetPacketBufferSizeMethod);
+int32_t AndroidCryptoNative_SSLStreamInitialize(
+ SSLStream* sslStream, bool isServer, STREAM_READER streamReader, STREAM_WRITER streamWriter, int32_t appBufferSize)
+{
+ assert(sslStream != NULL);
+ assert(sslStream->sslContext != NULL);
+ assert(sslStream->sslEngine == NULL);
+ assert(sslStream->sslSession == NULL);
- (*env)->CallVoidMethod(env, sslStream->sslEngine, g_SSLEngineSetUseClientModeMethod, true);
+ int32_t ret = FAIL;
+ JNIEnv* env = GetJNIEnv();
- sslStream->appOutBuffer = ToGRef(env, (*env)->CallStaticObjectMethod(env, g_ByteBuffer, g_ByteBufferAllocateMethod, appOutBufferSize));
- sslStream->netOutBuffer = ToGRef(env, (*env)->CallStaticObjectMethod(env, g_ByteBuffer, g_ByteBufferAllocateMethod, packetBufferSize));
- sslStream->appInBuffer = ToGRef(env, (*env)->CallStaticObjectMethod(env, g_ByteBuffer, g_ByteBufferAllocateMethod,
- applicationBufferSize > appInBufferSize ? applicationBufferSize : appInBufferSize));
- sslStream->netInBuffer = ToGRef(env, (*env)->CallStaticObjectMethod(env, g_ByteBuffer, g_ByteBufferAllocateMethod, packetBufferSize));
+ // SSLEngine sslEngine = sslContext.createSSLEngine();
+ // sslEngine.setUseClientMode(!isServer);
+ jobject sslEngine = (*env)->CallObjectMethod(env, sslStream->sslContext, g_SSLContextCreateSSLEngineMethod);
+ ON_EXCEPTION_PRINT_AND_GOTO(exit);
+ sslStream->sslEngine = ToGRef(env, sslEngine);
+ (*env)->CallVoidMethod(env, sslStream->sslEngine, g_SSLEngineSetUseClientMode, !isServer);
+ ON_EXCEPTION_PRINT_AND_GOTO(exit);
+
+ // SSLSession sslSession = sslEngine.getSession();
+ sslStream->sslSession = ToGRef(env, (*env)->CallObjectMethod(env, sslStream->sslEngine, g_SSLEngineGetSession));
+
+ // int applicationBufferSize = sslSession.getApplicationBufferSize();
+ // int packetBufferSize = sslSession.getPacketBufferSize();
+ int32_t applicationBufferSize =
+ (*env)->CallIntMethod(env, sslStream->sslSession, g_SSLSessionGetApplicationBufferSize);
+ int32_t packetBufferSize = (*env)->CallIntMethod(env, sslStream->sslSession, g_SSLSessionGetPacketBufferSize);
+
+ // ByteBuffer appInBuffer = ByteBuffer.allocate(Math.max(applicationBufferSize, appBufferSize));
+ // ByteBuffer appOutBuffer = ByteBuffer.allocate(appBufferSize);
+ // ByteBuffer netOutBuffer = ByteBuffer.allocate(packetBufferSize);
+ // ByteBuffer netInBuffer = ByteBuffer.allocate(packetBufferSize);
+ int32_t appInBufferSize = applicationBufferSize > appBufferSize ? applicationBufferSize : appBufferSize;
+ sslStream->appInBuffer =
+ ToGRef(env, (*env)->CallStaticObjectMethod(env, g_ByteBuffer, g_ByteBufferAllocate, appInBufferSize));
+ sslStream->appOutBuffer =
+ ToGRef(env, (*env)->CallStaticObjectMethod(env, g_ByteBuffer, g_ByteBufferAllocate, appBufferSize));
+ sslStream->netOutBuffer =
+ ToGRef(env, (*env)->CallStaticObjectMethod(env, g_ByteBuffer, g_ByteBufferAllocate, packetBufferSize));
+ sslStream->netInBuffer =
+ ToGRef(env, (*env)->CallStaticObjectMethod(env, g_ByteBuffer, g_ByteBufferAllocate, packetBufferSize));
sslStream->streamReader = streamReader;
sslStream->streamWriter = streamWriter;
- (*env)->CallVoidMethod(env, sslStream->sslEngine, g_SSLEngineBeginHandshakeMethod);
+ ret = SUCCESS;
- checkHandshakeStatus(env, sslStream, getHandshakeStatus(env, sslStream, NULL));
- (*env)->DeleteLocalRef(env, tlsVerStr);
- AssertOnJNIExceptions(env);
- return sslStream;
+exit:
+ return ret;
}
-int AndroidCryptoNative_SSLStreamRead(SSLStream* sslStream, uint8_t* buffer, int offset, int length)
+int32_t AndroidCryptoNative_SSLStreamConfigureParameters(SSLStream* sslStream, char* targetHost)
{
+ assert(sslStream != NULL);
+ assert(targetHost != NULL);
+
+ JNIEnv* env = GetJNIEnv();
+
+ int32_t ret = FAIL;
+ INIT_LOCALS(loc, hostStr, nameList, hostName, params);
+
+ // ArrayList nameList = new ArrayList();
+ // SNIHostName hostName = new SNIHostName(targetHost);
+ // nameList.add(hostName);
+ loc[hostStr] = JSTRING(targetHost);
+ loc[nameList] = (*env)->NewObject(env, g_ArrayListClass, g_ArrayListCtor);
+ ON_EXCEPTION_PRINT_AND_GOTO(cleanup);
+ loc[hostName] = (*env)->NewObject(env, g_SNIHostName, g_SNIHostNameCtor, loc[hostStr]);
+ ON_EXCEPTION_PRINT_AND_GOTO(cleanup);
+ (*env)->CallBooleanMethod(env, loc[nameList], g_ArrayListAdd, loc[hostName]);
+ ON_EXCEPTION_PRINT_AND_GOTO(cleanup);
+
+ // SSLParameters params = new SSLParameters();
+ // params.setServerNames(nameList);
+ // sslEngine.setSSLParameters(params);
+ loc[params] = (*env)->NewObject(env, g_SSLParametersClass, g_SSLParametersCtor);
+ ON_EXCEPTION_PRINT_AND_GOTO(cleanup);
+ (*env)->CallVoidMethod(env, loc[params], g_SSLParametersSetServerNames, loc[nameList]);
+ (*env)->CallVoidMethod(env, sslStream->sslEngine, g_SSLEngineSetSSLParameters, loc[params]);
+
+ ret = SUCCESS;
+
+cleanup:
+ RELEASE_LOCALS(loc, env);
+ return ret;
+}
+
+PAL_SSLStreamStatus AndroidCryptoNative_SSLStreamHandshake(SSLStream* sslStream)
+{
+ assert(sslStream != NULL);
+ JNIEnv* env = GetJNIEnv();
+
+ // sslEngine.beginHandshake();
+ (*env)->CallVoidMethod(env, sslStream->sslEngine, g_SSLEngineBeginHandshake);
+ if (CheckJNIExceptions(env))
+ return SSLStreamStatus_Error;
+
+ return DoHandshake(env, sslStream);
+}
+
+PAL_SSLStreamStatus
+AndroidCryptoNative_SSLStreamRead(SSLStream* sslStream, uint8_t* buffer, int32_t length, int32_t* read)
+{
+ assert(sslStream != NULL);
+ assert(read != NULL);
+
+ jbyteArray data = NULL;
JNIEnv* env = GetJNIEnv();
+ PAL_SSLStreamStatus ret = SSLStreamStatus_Error;
+ *read = 0;
/*
- while (true) {
+ appInBuffer.flip();
+ if (appInBuffer.remaining() == 0) {
+ appInBuffer.compact();
+ DoUnwrap();
appInBuffer.flip();
- try {
- if (appInBuffer.remaining() > 0) {
- byte[] data = new byte[appInBuffer.remaining()];
- appInBuffer.get(data);
- return data;
- }
- } finally {
- appInBuffer.compact();
- }
- doUnwrap();
+ }
+ if (appInBuffer.remaining() > 0) {
+ byte[] data = new byte[appInBuffer.remaining()];
+ appInBuffer.get(data);
+ appInBuffer.compact();
+ return SSLStreamStatus_OK;
+ } else {
+ return SSLStreamStatus_NeedData;
}
*/
- AssertOnJNIExceptions(env);
- (*env)->DeleteLocalRef(env, (*env)->CallObjectMethod(env, sslStream->appInBuffer, g_ByteBufferFlipMethod));
- int rem = (*env)->CallIntMethod(env, sslStream->appInBuffer, g_ByteBufferRemainingMethod);
+ IGNORE_RETURN((*env)->CallObjectMethod(env, sslStream->appInBuffer, g_ByteBufferFlip));
+ int32_t rem = (*env)->CallIntMethod(env, sslStream->appInBuffer, g_ByteBufferRemaining);
+ if (rem == 0)
+ {
+ IGNORE_RETURN((*env)->CallObjectMethod(env, sslStream->appInBuffer, g_ByteBufferCompact));
+ ON_EXCEPTION_PRINT_AND_GOTO(cleanup);
+
+ int handshakeStatus;
+ PAL_SSLStreamStatus unwrapStatus = DoUnwrap(env, sslStream, &handshakeStatus);
+ if (unwrapStatus != SSLStreamStatus_OK)
+ {
+ ret = unwrapStatus;
+ goto cleanup;
+ }
+
+ IGNORE_RETURN((*env)->CallObjectMethod(env, sslStream->appInBuffer, g_ByteBufferFlip));
+
+ if (IsHandshaking(handshakeStatus))
+ {
+ ret = SSLStreamStatus_Renegotiate;
+ goto cleanup;
+ }
+
+ rem = (*env)->CallIntMethod(env, sslStream->appInBuffer, g_ByteBufferRemaining);
+ }
+
if (rem > 0)
{
- jbyteArray data = (*env)->NewByteArray(env, rem);
- (*env)->DeleteLocalRef(env, (*env)->CallObjectMethod(env, sslStream->appInBuffer, g_ByteBufferGetMethod, data));
- (*env)->DeleteLocalRef(env, (*env)->CallObjectMethod(env, sslStream->appInBuffer, g_ByteBufferCompactMethod));
- (*env)->GetByteArrayRegion(env, data, 0, rem, (jbyte*) buffer);
- AssertOnJNIExceptions(env);
- return rem;
+ data = (*env)->NewByteArray(env, rem);
+ IGNORE_RETURN((*env)->CallObjectMethod(env, sslStream->appInBuffer, g_ByteBufferGet, data));
+ ON_EXCEPTION_PRINT_AND_GOTO(cleanup);
+ IGNORE_RETURN((*env)->CallObjectMethod(env, sslStream->appInBuffer, g_ByteBufferCompact));
+ ON_EXCEPTION_PRINT_AND_GOTO(cleanup);
+ (*env)->GetByteArrayRegion(env, data, 0, rem, (jbyte*)buffer);
+ *read = rem;
+ ret = SSLStreamStatus_OK;
}
else
{
- (*env)->DeleteLocalRef(env, (*env)->CallObjectMethod(env, sslStream->appInBuffer, g_ByteBufferCompactMethod));
- doUnwrap(env, sslStream);
- AssertOnJNIExceptions(env);
- return AndroidCryptoNative_SSLStreamRead(sslStream, buffer, offset, length);
+ ret = SSLStreamStatus_NeedData;
}
+
+cleanup:
+ ReleaseLRef(env, data);
+ return ret;
}
-void AndroidCryptoNative_SSLStreamWrite(SSLStream* sslStream, uint8_t* buffer, int offset, int length)
+PAL_SSLStreamStatus AndroidCryptoNative_SSLStreamWrite(SSLStream* sslStream, uint8_t* buffer, int32_t length)
{
- /*
- appOutBuffer.put(message);
- doWrap();
- */
+ assert(sslStream != NULL);
JNIEnv* env = GetJNIEnv();
+ PAL_SSLStreamStatus ret = SSLStreamStatus_Error;
+
+ // byte[] data = new byte[] { }
+ // appOutBuffer.put(data);
jbyteArray data = (*env)->NewByteArray(env, length);
- (*env)->SetByteArrayRegion(env, data, 0, length, (jbyte*)(buffer + offset));
- (*env)->DeleteLocalRef(env, (*env)->CallObjectMethod(env, sslStream->appOutBuffer, g_ByteBufferPut2Method, data));
+ (*env)->SetByteArrayRegion(env, data, 0, length, (jbyte*)buffer);
+ IGNORE_RETURN((*env)->CallObjectMethod(env, sslStream->appOutBuffer, g_ByteBufferPutByteArray, data));
+ ON_EXCEPTION_PRINT_AND_GOTO(cleanup);
+
+ int handshakeStatus;
+ ret = DoWrap(env, sslStream, &handshakeStatus);
+ if (ret == SSLStreamStatus_OK && IsHandshaking(handshakeStatus))
+ {
+ ret = SSLStreamStatus_Renegotiate;
+ }
+
+cleanup:
(*env)->DeleteLocalRef(env, data);
- doWrap(env, sslStream);
- AssertOnJNIExceptions(env);
+ return ret;
}
void AndroidCryptoNative_SSLStreamRelease(SSLStream* sslStream)
{
+ if (sslStream == NULL)
+ return;
+
JNIEnv* env = GetJNIEnv();
- ReleaseGRef(env, sslStream->sslContext);
- ReleaseGRef(env, sslStream->sslEngine);
- ReleaseGRef(env, sslStream->sslSession);
- ReleaseGRef(env, sslStream->appOutBuffer);
- ReleaseGRef(env, sslStream->netOutBuffer);
- ReleaseGRef(env, sslStream->netInBuffer);
- ReleaseGRef(env, sslStream->appInBuffer);
- free(sslStream);
- AssertOnJNIExceptions(env);
+ FreeSSLStream(env, sslStream);
+}
+
+int32_t AndroidCryptoNative_SSLStreamGetApplicationProtocol(SSLStream* sslStream, uint8_t* out, int32_t* outLen)
+{
+ assert(sslStream != NULL);
+
+ JNIEnv* env = GetJNIEnv();
+ int32_t ret = FAIL;
+
+ // String protocol = sslEngine.getApplicationProtocol();
+ jstring protocol = (*env)->CallObjectMethod(env, sslStream->sslEngine, g_SSLEngineGetApplicationProtocol);
+ ON_EXCEPTION_PRINT_AND_GOTO(cleanup);
+ if (protocol == NULL)
+ goto cleanup;
+
+ jsize len = (*env)->GetStringUTFLength(env, protocol);
+ bool insufficientBuffer = *outLen < len;
+ *outLen = len;
+ if (insufficientBuffer)
+ return INSUFFICIENT_BUFFER;
+
+ (*env)->GetStringUTFRegion(env, protocol, 0, len, (char*)out);
+ ON_EXCEPTION_PRINT_AND_GOTO(cleanup);
+
+ ret = SUCCESS;
+
+cleanup:
+ (*env)->DeleteLocalRef(env, protocol);
+ return ret;
+}
+
+int32_t AndroidCryptoNative_SSLStreamGetCipherSuite(SSLStream* sslStream, uint16_t** out)
+{
+ assert(sslStream != NULL);
+ assert(out != NULL);
+
+ JNIEnv* env = GetJNIEnv();
+ int32_t ret = FAIL;
+ *out = NULL;
+
+ // String cipherSuite = sslSession.getCipherSuite();
+ jstring cipherSuite = (*env)->CallObjectMethod(env, sslStream->sslSession, g_SSLSessionGetCipherSuite);
+ ON_EXCEPTION_PRINT_AND_GOTO(cleanup);
+ *out = AllocateString(env, cipherSuite);
+
+ ret = SUCCESS;
+
+cleanup:
+ (*env)->DeleteLocalRef(env, cipherSuite);
+ return ret;
+}
+
+int32_t AndroidCryptoNative_SSLStreamGetProtocol(SSLStream* sslStream, uint16_t** out)
+{
+ assert(sslStream != NULL);
+ assert(out != NULL);
+
+ JNIEnv* env = GetJNIEnv();
+ int32_t ret = FAIL;
+ *out = NULL;
+
+ // String protocol = sslSession.getProtocol();
+ jstring protocol = (*env)->CallObjectMethod(env, sslStream->sslSession, g_SSLSessionGetProtocol);
+ ON_EXCEPTION_PRINT_AND_GOTO(cleanup);
+ *out = AllocateString(env, protocol);
+
+ ret = SUCCESS;
+
+cleanup:
+ (*env)->DeleteLocalRef(env, protocol);
+ return ret;
+}
+
+int32_t AndroidCryptoNative_SSLStreamGetPeerCertificate(SSLStream* sslStream, jobject* out)
+{
+ assert(sslStream != NULL);
+ assert(out != NULL);
+
+ JNIEnv* env = GetJNIEnv();
+ int32_t ret = FAIL;
+ *out = NULL;
+
+ // Certificate[] certs = sslSession.getPeerCertificates();
+ // out = certs[0];
+ jobjectArray certs = (*env)->CallObjectMethod(env, sslStream->sslSession, g_SSLSessionGetPeerCertificates);
+ ON_EXCEPTION_PRINT_AND_GOTO(cleanup);
+ jsize len = (*env)->GetArrayLength(env, certs);
+ if (len > 0)
+ {
+ // First element is the peer's own certificate
+ jobject cert = (*env)->GetObjectArrayElement(env, certs, 0);
+ *out = ToGRef(env, cert);
+ }
+
+ ret = SUCCESS;
+
+cleanup:
+ (*env)->DeleteLocalRef(env, certs);
+ return ret;
+}
+
+int32_t AndroidCryptoNative_SSLStreamGetPeerCertificates(SSLStream* sslStream, jobject** out, int32_t* outLen)
+{
+ assert(sslStream != NULL);
+ assert(out != NULL);
+
+ JNIEnv* env = GetJNIEnv();
+ int32_t ret = FAIL;
+ *out = NULL;
+ *outLen = 0;
+
+ // Certificate[] certs = sslSession.getPeerCertificates();
+ // for (int i = 0; i < certs.length; i++) {
+ // out[i] = certs[i];
+ // }
+ jobjectArray certs = (*env)->CallObjectMethod(env, sslStream->sslSession, g_SSLSessionGetPeerCertificates);
+ ON_EXCEPTION_PRINT_AND_GOTO(cleanup);
+ jsize len = (*env)->GetArrayLength(env, certs);
+ *outLen = len;
+ if (len > 0)
+ {
+ *out = malloc(sizeof(jobject) * (size_t)len);
+ for (int32_t i = 0; i < len; i++)
+ {
+ jobject cert = (*env)->GetObjectArrayElement(env, certs, i);
+ (*out)[i] = ToGRef(env, cert);
+ }
+ }
+
+ ret = SUCCESS;
+
+cleanup:
+ (*env)->DeleteLocalRef(env, certs);
+ return ret;
+}
+
+static jstring GetSslProtocolAsString(JNIEnv* env, PAL_SslProtocol protocol)
+{
+ switch (protocol)
+ {
+ case PAL_SslProtocol_Tls10:
+ return JSTRING("TLSv1");
+ case PAL_SslProtocol_Tls11:
+ return JSTRING("TLSv1.1");
+ case PAL_SslProtocol_Tls12:
+ return JSTRING("TLSv1.2");
+ case PAL_SslProtocol_Tls13:
+ return JSTRING("TLSv1.3");
+ default:
+ LOG_ERROR("Unsupported SslProtocols value: %d", protocol);
+ return NULL;
+ }
+}
+
+int32_t
+AndroidCryptoNative_SSLStreamSetEnabledProtocols(SSLStream* sslStream, PAL_SslProtocol* protocols, int32_t count)
+{
+ assert(sslStream != NULL);
+
+ JNIEnv* env = GetJNIEnv();
+ int32_t ret = FAIL;
+
+ // String[] protocolsArray = new String[count];
+ jobjectArray protocolsArray = (*env)->NewObjectArray(env, count, g_String, NULL);
+ for (int32_t i = 0; i < count; ++i)
+ {
+ jstring protocol = GetSslProtocolAsString(env, protocols[i]);
+ (*env)->SetObjectArrayElement(env, protocolsArray, i, protocol);
+ (*env)->DeleteLocalRef(env, protocol);
+ }
+
+ // sslEngine.setEnabledProtocols(protocolsArray);
+ (*env)->CallVoidMethod(env, sslStream->sslEngine, g_SSLEngineSetEnabledProtocols, protocolsArray);
+ ON_EXCEPTION_PRINT_AND_GOTO(cleanup);
+
+ ret = SUCCESS;
+
+cleanup:
+ (*env)->DeleteLocalRef(env, protocolsArray);
+ return ret;
+}
+
+bool AndroidCryptoNative_SSLStreamVerifyHostname(SSLStream* sslStream, char* hostname)
+{
+ assert(sslStream != NULL);
+ assert(hostname != NULL);
+ JNIEnv* env = GetJNIEnv();
+
+ bool ret = false;
+ INIT_LOCALS(loc, name, verifier);
+
+ // HostnameVerifier verifier = HttpsURLConnection.getDefaultHostnameVerifier();
+ // return verifier.verify(hostname, sslSession);
+ loc[name] = JSTRING(hostname);
+ loc[verifier] =
+ (*env)->CallStaticObjectMethod(env, g_HttpsURLConnection, g_HttpsURLConnectionGetDefaultHostnameVerifier);
+ ret = (*env)->CallBooleanMethod(env, loc[verifier], g_HostnameVerifierVerify, loc[name], sslStream->sslSession);
+
+ RELEASE_LOCALS(loc, env);
+ return ret;
+}
+
+bool AndroidCryptoNative_SSLStreamShutdown(SSLStream* sslStream)
+{
+ assert(sslStream != NULL);
+ JNIEnv* env = GetJNIEnv();
+
+ PAL_SSLStreamStatus status = Close(env, sslStream);
+ return status == SSLStreamStatus_Closed;
+}
+
+static uint16_t* AllocateString(JNIEnv* env, jstring source)
+{
+ if (source == NULL)
+ return NULL;
+
+ // Length with null terminator
+ jsize len = (*env)->GetStringLength(env, source);
+
+ // +1 for null terminator.
+ uint16_t* buffer = malloc(sizeof(uint16_t) * (size_t)(len + 1));
+ buffer[len] = '\0';
+
+ (*env)->GetStringRegion(env, source, 0, len, (jchar*)buffer);
+ return buffer;
}
diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_sslstream.h b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_sslstream.h
index 348760cfdc0a0a..fadd70ae15577c 100644
--- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_sslstream.h
+++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_sslstream.h
@@ -4,9 +4,12 @@
#pragma once
#include "pal_jni.h"
+#include "pal_x509.h"
-typedef void (*STREAM_WRITER)(uint8_t*, uint32_t, uint32_t);
-typedef int (*STREAM_READER)(uint8_t*, uint32_t, uint32_t);
+#include
+
+typedef void (*STREAM_WRITER)(uint8_t*, int32_t);
+typedef int32_t (*STREAM_READER)(uint8_t*, int32_t*);
typedef struct SSLStream
{
@@ -21,24 +24,147 @@ typedef struct SSLStream
STREAM_WRITER streamWriter;
} SSLStream;
-#define TLS11 11
-#define TLS12 12
-#define TLS13 13
-
-// javax/net/ssl/SSLEngineResult$HandshakeStatus
-#define HANDSHAKE_STATUS__NOT_HANDSHAKING 0
-#define HANDSHAKE_STATUS__FINISHED 1
-#define HANDSHAKE_STATUS__NEED_TASK 2
-#define HANDSHAKE_STATUS__NEED_WRAP 3
-#define HANDSHAKE_STATUS__NEED_UNWRAP 4
-
-// javax/net/ssl/SSLEngineResult$Status
-#define STATUS__BUFFER_UNDERFLOW 0
-#define STATUS__BUFFER_OVERFLOW 1
-#define STATUS__OK 2
-#define STATUS__CLOSED 3
-
-PALEXPORT SSLStream* AndroidCryptoNative_SSLStreamCreateAndStartHandshake(STREAM_READER streamReader, STREAM_WRITER streamWriter, int tlsVersion, int appOutBufferSize, int appInBufferSize);
-PALEXPORT int AndroidCryptoNative_SSLStreamRead(SSLStream* sslStream, uint8_t* buffer, int offset, int length);
-PALEXPORT void AndroidCryptoNative_SSLStreamWrite(SSLStream* sslStream, uint8_t* buffer, int offset, int length);
+// Matches managed PAL_SSLStreamStatus enum
+enum
+{
+ SSLStreamStatus_OK = 0,
+ SSLStreamStatus_NeedData = 1,
+ SSLStreamStatus_Error = 2,
+ SSLStreamStatus_Renegotiate = 3,
+ SSLStreamStatus_Closed = 4,
+};
+typedef int32_t PAL_SSLStreamStatus;
+
+/*
+Create an SSL context
+
+Returns NULL on failure
+*/
+PALEXPORT SSLStream* AndroidCryptoNative_SSLStreamCreate(void);
+
+/*
+Create an SSL context with the specified certificates
+
+Returns NULL on failure
+*/
+PALEXPORT SSLStream* AndroidCryptoNative_SSLStreamCreateWithCertificates(uint8_t* pkcs8PrivateKey,
+ int32_t pkcs8PrivateKeyLen,
+ PAL_KeyAlgorithm algorithm,
+ jobject* /*X509Certificate[]*/ certs,
+ int32_t certsLen);
+
+/*
+Initialize an SSL context
+ - isServer : true if the context should be created in server mode
+ - streamReader : callback for reading data from the connection
+ - streamWriter : callback for writing data to the connection
+ - appBufferSize : initial buffer size for applicaiton data
+
+Returns 1 on success, 0 otherwise
+*/
+PALEXPORT int32_t AndroidCryptoNative_SSLStreamInitialize(
+ SSLStream* sslStream, bool isServer, STREAM_READER streamReader, STREAM_WRITER streamWriter, int32_t appBufferSize);
+
+/*
+Set configuration parameters
+ - targetHost : SNI host name
+
+Returns 1 on success, 0 otherwise
+*/
+PALEXPORT int32_t AndroidCryptoNative_SSLStreamConfigureParameters(SSLStream* sslStream, char* targetHost);
+
+/*
+Start or continue the TLS handshake
+*/
+PALEXPORT PAL_SSLStreamStatus AndroidCryptoNative_SSLStreamHandshake(SSLStream* sslStream);
+
+/*
+Read bytes from the connection into a buffer
+ - buffer : buffer to populate with the bytes read from the connection
+ - length : maximum number of bytes to read
+ - read : [out] number of bytes read from the connection and written into the buffer
+
+Unless data from a previous incomplete read is present, this will invoke the STREAM_READER callback.
+*/
+PALEXPORT PAL_SSLStreamStatus AndroidCryptoNative_SSLStreamRead(SSLStream* sslStream,
+ uint8_t* buffer,
+ int32_t length,
+ int32_t* read);
+/*
+Encodes bytes from a buffer
+ - buffer : data to encode
+ - length : length of buffer
+
+This will invoke the STREAM_WRITER callback with the processed data.
+*/
+PALEXPORT PAL_SSLStreamStatus AndroidCryptoNative_SSLStreamWrite(SSLStream* sslStream, uint8_t* buffer, int32_t length);
+
+/*
+Release the SSL context
+*/
PALEXPORT void AndroidCryptoNative_SSLStreamRelease(SSLStream* sslStream);
+
+/*
+Get the negotiated application protocol for the current session
+
+Returns 1 on success, 0 otherwise
+*/
+PALEXPORT int32_t AndroidCryptoNative_SSLStreamGetApplicationProtocol(SSLStream* sslStream,
+ uint8_t* out,
+ int32_t* outLen);
+
+/*
+Get the name of the cipher suite for the current session
+
+Returns 1 on success, 0 otherwise
+*/
+PALEXPORT int32_t AndroidCryptoNative_SSLStreamGetCipherSuite(SSLStream* sslStream, uint16_t** out);
+
+/*
+Get the standard name of the protocol for the current session (e.g. TLSv1.2)
+
+Returns 1 on success, 0 otherwise
+*/
+PALEXPORT int32_t AndroidCryptoNative_SSLStreamGetProtocol(SSLStream* sslStream, uint16_t** out);
+
+/*
+Get the peer certificate for the current session
+
+Returns 1 on success, 0 otherwise
+*/
+PALEXPORT int32_t AndroidCryptoNative_SSLStreamGetPeerCertificate(SSLStream* sslStream,
+ jobject* /*X509Certificate*/ out);
+
+/*
+Get the peer certificates for the current session
+
+The peer's own certificate will be first, followed by any certificate authorities.
+
+Returns 1 on success, 0 otherwise
+*/
+PALEXPORT int32_t AndroidCryptoNative_SSLStreamGetPeerCertificates(SSLStream* sslStream,
+ jobject** /*X509Certificate[]*/ out,
+ int32_t* outLen);
+
+/*
+Set enabled protocols
+ - protocols : array of protocols to enable
+ - count : number of elements in protocols
+
+Returns 1 on success, 0 otherwise
+*/
+PALEXPORT int32_t AndroidCryptoNative_SSLStreamSetEnabledProtocols(SSLStream* sslStream,
+ PAL_SslProtocol* protocols,
+ int32_t count);
+
+/*
+Verify hostname using the peer certificate for the current session
+
+Returns true if hostname matches, false otherwise
+*/
+PALEXPORT bool AndroidCryptoNative_SSLStreamVerifyHostname(SSLStream* sslStream, char* hostname);
+
+/*
+Shut down the session
+*/
+PALEXPORT bool AndroidCryptoNative_SSLStreamShutdown(SSLStream* sslStream);
diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_x509.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_x509.c
index dfa72406a6c5ed..f7dc194895b955 100644
--- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_x509.c
+++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_x509.c
@@ -12,8 +12,6 @@
#include
#include
-#define INSUFFICIENT_BUFFER -1
-
static int32_t PopulateByteArray(JNIEnv* env, jbyteArray source, uint8_t* dest, int32_t* len);
static void FindCertStart(const uint8_t** buffer, int32_t* len);
diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_x509store.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_x509store.c
index 64b839d2018d3b..9724e8af2f4afa 100644
--- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_x509store.c
+++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_x509store.c
@@ -329,7 +329,7 @@ int32_t AndroidCryptoNative_X509StoreEnumerateCertificates(jobject /*KeyStore*/
static bool SystemAliasFilter(JNIEnv* env, jstring alias)
{
const char systemPrefix[] = "system:";
- size_t prefixLen = (sizeof(systemPrefix) - 1) / sizeof(char);
+ size_t prefixLen = (sizeof(systemPrefix) / sizeof(*systemPrefix)) - 1;
const char* aliasPtr = (*env)->GetStringUTFChars(env, alias, NULL);
bool isSystem = (strncmp(aliasPtr, systemPrefix, prefixLen) == 0);
diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_ssl.h b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_ssl.h
index 518ef35c67f388..8c3b61d530f833 100644
--- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_ssl.h
+++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_ssl.h
@@ -4,6 +4,7 @@
#pragma once
#include "pal_compiler.h"
+#include
#include
#include
@@ -27,18 +28,6 @@ enum
};
typedef int32_t PAL_TlsIo;
-enum
-{
- PAL_SslProtocol_None = 0,
- PAL_SslProtocol_Ssl2 = 12,
- PAL_SslProtocol_Ssl3 = 48,
- PAL_SslProtocol_Tls10 = 192,
- PAL_SslProtocol_Tls11 = 768,
- PAL_SslProtocol_Tls12 = 3072,
- PAL_SslProtocol_Tls13 = 12288,
-};
-typedef int32_t PAL_SslProtocol;
-
/*
Create an SSL context, for the Server or Client role as determined by isServer.
diff --git a/src/libraries/Native/build-native.sh b/src/libraries/Native/build-native.sh
index 55d56a7099c353..f95f1f622f0e41 100755
--- a/src/libraries/Native/build-native.sh
+++ b/src/libraries/Native/build-native.sh
@@ -104,57 +104,49 @@ elif [[ "$__TargetOS" == Android && -z "$ROOTFS_DIR" ]]; then
exit 1
fi
elif [[ "$__TargetOS" == iOSSimulator ]]; then
- __CMakeArgs="-DCMAKE_SYSTEM_NAME=iOS $__CMakeArgs"
+ # set default iOS simulator deployment target
+ # keep in sync with src/mono/Directory.Build.props
+ __CMakeArgs="-DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=10.0 $__CMakeArgs"
if [[ "$__BuildArch" == x64 ]]; then
- # set default iOS simulator deployment target (8.0 is the minimum supported by Xcode 11)
- # keep in sync with src/mono/Directory.Build.props
- __CMakeArgs="-DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=8.0 -DCMAKE_OSX_ARCHITECTURES=\"x86_64\" $__CMakeArgs"
+ __CMakeArgs="-DCMAKE_OSX_ARCHITECTURES=\"x86_64\" $__CMakeArgs"
elif [[ "$__BuildArch" == x86 ]]; then
- # set default iOS simulator deployment target (8.0 is the minimum supported by Xcode 11)
- # keep in sync with src/mono/Directory.Build.props
- __CMakeArgs="-DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=8.0 -DCMAKE_OSX_ARCHITECTURES=\"i386\" $__CMakeArgs"
+ __CMakeArgs="-DCMAKE_OSX_ARCHITECTURES=\"i386\" $__CMakeArgs"
elif [[ "$__BuildArch" == arm64 ]]; then
- # set default iOS device deployment target
- # keep in sync with src/mono/Directory.Build.props
- __CMakeArgs="-DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=8.0 -DCMAKE_OSX_ARCHITECTURES=\"arm64\" $__CMakeArgs"
+ __CMakeArgs="-DCMAKE_OSX_ARCHITECTURES=\"arm64\" $__CMakeArgs"
else
echo "Error: Unknown iOSSimulator architecture $__BuildArch."
exit 1
fi
elif [[ "$__TargetOS" == iOS ]]; then
- __CMakeArgs="-DCMAKE_SYSTEM_NAME=iOS $__CMakeArgs"
+ # set default iOS device deployment target
+ # keep in sync with src/mono/Directory.Build.props
+ __CMakeArgs="-DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos -DCMAKE_OSX_DEPLOYMENT_TARGET=10.0 $__CMakeArgs"
if [[ "$__BuildArch" == arm64 ]]; then
- # set default iOS device deployment target
- # keep in sync with src/mono/Directory.Build.props
- __CMakeArgs="-DCMAKE_OSX_SYSROOT=iphoneos -DCMAKE_OSX_DEPLOYMENT_TARGET=8.0 -DCMAKE_OSX_ARCHITECTURES=\"arm64\" $__CMakeArgs"
+ __CMakeArgs="-DCMAKE_OSX_ARCHITECTURES=\"arm64\" $__CMakeArgs"
elif [[ "$__BuildArch" == arm ]]; then
- # set default iOS device deployment target
- # keep in sync with src/mono/Directory.Build.props
- __CMakeArgs="-DCMAKE_OSX_SYSROOT=iphoneos -DCMAKE_OSX_DEPLOYMENT_TARGET=8.0 -DCMAKE_OSX_ARCHITECTURES=\"armv7;armv7s\" $__CMakeArgs"
+ __CMakeArgs="-DCMAKE_OSX_ARCHITECTURES=\"armv7;armv7s\" $__CMakeArgs"
else
echo "Error: Unknown iOS architecture $__BuildArch."
exit 1
fi
elif [[ "$__TargetOS" == tvOSSimulator ]]; then
- __CMakeArgs="-DCMAKE_SYSTEM_NAME=tvOS $__CMakeArgs"
- # set default tvOS device deployment target
- # keep in sync with tvOSVersionMin in src/mono/Directory.Build.props
- __CMakeArgs="-DCMAKE_OSX_DEPLOYMENT_TARGET=9.0 $__CMakeArgs"
+ # set default tvOS simulator deployment target
+ # keep in sync with src/mono/Directory.Build.props
+ __CMakeArgs="-DCMAKE_SYSTEM_NAME=tvOS -DCMAKE_OSX_SYSROOT=appletvsimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=10.0 $__CMakeArgs"
if [[ "$__BuildArch" == x64 ]]; then
- __CMakeArgs="-DCMAKE_OSX_SYSROOT=appletvsimulator -DCMAKE_OSX_ARCHITECTURES=\"x86_64\" $__CMakeArgs"
+ __CMakeArgs="-DCMAKE_OSX_ARCHITECTURES=\"x86_64\" $__CMakeArgs"
elif [[ "$__BuildArch" == arm64 ]]; then
- __CMakeArgs="-DCMAKE_OSX_SYSROOT=appletvsimulator -DCMAKE_OSX_ARCHITECTURES=\"arm64\" $__CMakeArgs"
+ __CMakeArgs="-DCMAKE_OSX_ARCHITECTURES=\"arm64\" $__CMakeArgs"
else
echo "Error: Unknown tvOSSimulator architecture $__BuildArch."
exit 1
fi
elif [[ "$__TargetOS" == tvOS ]]; then
- __CMakeArgs="-DCMAKE_SYSTEM_NAME=tvOS $__CMakeArgs"
- # set default tvOS device deployment target
- # keep in sync with tvOSVersionMin in src/mono/Directory.Build.props
- __CMakeArgs="-DCMAKE_OSX_DEPLOYMENT_TARGET=9.0 $__CMakeArgs"
+ # set default tvOS device deployment target
+ # keep in sync with src/mono/Directory.Build.props
+ __CMakeArgs="-DCMAKE_SYSTEM_NAME=tvOS -DCMAKE_OSX_SYSROOT=appletvos -DCMAKE_OSX_DEPLOYMENT_TARGET=10.0 $__CMakeArgs"
if [[ "$__BuildArch" == arm64 ]]; then
- __CMakeArgs="-DCMAKE_OSX_SYSROOT=appletvos -DCMAKE_OSX_ARCHITECTURES=\"arm64\" $__CMakeArgs"
+ __CMakeArgs="-DCMAKE_OSX_ARCHITECTURES=\"arm64\" $__CMakeArgs"
else
echo "Error: Unknown tvOS architecture $__BuildArch."
exit 1
diff --git a/src/libraries/System.ComponentModel.Composition/tests/System/ComponentModel/Composition/Hosting/DirectoryCatalogDebuggerProxyTests.cs b/src/libraries/System.ComponentModel.Composition/tests/System/ComponentModel/Composition/Hosting/DirectoryCatalogDebuggerProxyTests.cs
index 71b71ec0a749b5..c24674d7212a54 100644
--- a/src/libraries/System.ComponentModel.Composition/tests/System/ComponentModel/Composition/Hosting/DirectoryCatalogDebuggerProxyTests.cs
+++ b/src/libraries/System.ComponentModel.Composition/tests/System/ComponentModel/Composition/Hosting/DirectoryCatalogDebuggerProxyTests.cs
@@ -126,7 +126,7 @@ public void LoadedFiles_EmptyDirectory_ShouldBeFine()
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public void LoadedFiles_ContainsMultipleDllsAndSomeNonDll_ShouldOnlyContainDlls()
{
string directoryPath = GetTemporaryDirectory();
diff --git a/src/libraries/System.ComponentModel.Composition/tests/System/ComponentModel/Composition/Hosting/DirectoryCatalogTests.cs b/src/libraries/System.ComponentModel.Composition/tests/System/ComponentModel/Composition/Hosting/DirectoryCatalogTests.cs
index ec9821debf3891..342d8412347ef6 100644
--- a/src/libraries/System.ComponentModel.Composition/tests/System/ComponentModel/Composition/Hosting/DirectoryCatalogTests.cs
+++ b/src/libraries/System.ComponentModel.Composition/tests/System/ComponentModel/Composition/Hosting/DirectoryCatalogTests.cs
@@ -325,7 +325,7 @@ public void LoadedFiles_EmptyDirectory_ShouldBeFine()
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public void LoadedFiles_ContainsMultipleDllsAndSomeNonDll_ShouldOnlyContainDlls()
{
// Add one text file
diff --git a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/CategoryAttribute.cs b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/CategoryAttribute.cs
index 976155e8336b5e..e9c6414aaf311d 100644
--- a/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/CategoryAttribute.cs
+++ b/src/libraries/System.ComponentModel.Primitives/src/System/ComponentModel/CategoryAttribute.cs
@@ -197,7 +197,7 @@ public override bool Equals(object? obj) =>
///
/// Looks up the localized name of a given category.
///
- protected virtual string? GetLocalizedString(string value) => SR.GetResourceString("PropertyCategory" + value, null);
+ protected virtual string? GetLocalizedString(string value) => SR.GetResourceString("PropertyCategory" + value);
public override bool IsDefaultAttribute() => Category == Default.Category;
}
diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/Timers/TimersDescriptionAttribute.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/Timers/TimersDescriptionAttribute.cs
index 331abf43119536..1f991215906416 100644
--- a/src/libraries/System.ComponentModel.TypeConverter/src/System/Timers/TimersDescriptionAttribute.cs
+++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/Timers/TimersDescriptionAttribute.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.ComponentModel;
+using System.Diagnostics;
namespace System.Timers
{
@@ -23,7 +24,11 @@ public TimersDescriptionAttribute(string description) : base(description) { }
///
/// Constructs a new localized sys description.
///
- internal TimersDescriptionAttribute(string description, string defaultValue) : base(SR.GetResourceString(description, defaultValue)) { }
+ internal TimersDescriptionAttribute(string description, string unused) : base(SR.GetResourceString(description))
+ {
+ // Needed for overload resolution
+ Debug.Assert(unused == null);
+ }
///
/// Retrieves the description text.
diff --git a/src/libraries/System.ComponentModel.TypeConverter/tests/Security/Authentication/ExtendedProtection/ExtendedProtectionPolicyTypeConverterTests.cs b/src/libraries/System.ComponentModel.TypeConverter/tests/Security/Authentication/ExtendedProtection/ExtendedProtectionPolicyTypeConverterTests.cs
index a09110342ff6d3..82676a7f3f6e89 100644
--- a/src/libraries/System.ComponentModel.TypeConverter/tests/Security/Authentication/ExtendedProtection/ExtendedProtectionPolicyTypeConverterTests.cs
+++ b/src/libraries/System.ComponentModel.TypeConverter/tests/Security/Authentication/ExtendedProtection/ExtendedProtectionPolicyTypeConverterTests.cs
@@ -30,14 +30,14 @@ public void CanConvertTo_PositiveTests()
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)] // System.Net.Security is not supported on this platform.
+ [SkipOnPlatform(TestPlatforms.Browser, "System.Net.Security is not supported on this platform.")]
public void ConvertTo_NullTypeTests()
{
Assert.Throws(() => converter.ConvertTo(null, CultureInfo.InvariantCulture, new ExtendedProtectionPolicy(PolicyEnforcement.Never), null));
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)] // System.Net.Security is not supported on this platform.
+ [SkipOnPlatform(TestPlatforms.Browser, "System.Net.Security is not supported on this platform.")]
public void ConvertTo_PositiveTests()
{
ExtendedProtectionPolicy policy = new ExtendedProtectionPolicy(PolicyEnforcement.Never);
@@ -57,7 +57,7 @@ public void ConvertTo_PositiveTests()
}
[Theory]
- [PlatformSpecific(~TestPlatforms.Browser)] // System.Net.Security is not supported on this platform.
+ [SkipOnPlatform(TestPlatforms.Browser, "System.Net.Security is not supported on this platform.")]
[InlineData(typeof(int))]
[InlineData(typeof(ExtendedProtectionPolicy))]
[InlineData(typeof(bool))]
diff --git a/src/libraries/System.Configuration.ConfigurationManager/tests/AssemblyInfo.cs b/src/libraries/System.Configuration.ConfigurationManager/tests/AssemblyInfo.cs
index cd9251d1f14500..024dadef049771 100644
--- a/src/libraries/System.Configuration.ConfigurationManager/tests/AssemblyInfo.cs
+++ b/src/libraries/System.Configuration.ConfigurationManager/tests/AssemblyInfo.cs
@@ -4,4 +4,4 @@
using System;
using Xunit;
-[assembly: SkipOnMono("System.Configuration.ConfigurationManager is not supported on WASM", TestPlatforms.Browser)]
+[assembly: SkipOnPlatform(TestPlatforms.Browser, "System.Configuration.ConfigurationManager is not supported on Browser")]
diff --git a/src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj b/src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj
index 94b27837000fbb..7c5067757fddd5 100644
--- a/src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj
+++ b/src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj
@@ -5,6 +5,7 @@
true
true
$(NetCoreAppCurrent)-windows;net461
+ true
diff --git a/src/libraries/System.Console/tests/Color.cs b/src/libraries/System.Console/tests/Color.cs
index 5ad7a05593aede..2cc8c585140928 100644
--- a/src/libraries/System.Console/tests/Color.cs
+++ b/src/libraries/System.Console/tests/Color.cs
@@ -12,7 +12,7 @@
public class Color
{
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public static void InvalidColors()
{
AssertExtensions.Throws(null, () => Console.BackgroundColor = (ConsoleColor)42);
@@ -20,7 +20,7 @@ public static void InvalidColors()
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public static void RoundtrippingColor()
{
Console.BackgroundColor = Console.BackgroundColor;
@@ -49,7 +49,7 @@ public static void BackgroundColor_Throws_PlatformNotSupportedException()
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public static void RedirectedOutputDoesNotUseAnsiSequences()
{
// Make sure that redirecting to a memory stream causes Console not to write out the ANSI sequences
diff --git a/src/libraries/System.Console/tests/ConsoleEncoding.cs b/src/libraries/System.Console/tests/ConsoleEncoding.cs
index 99ec36447f59c2..d52d93c9282201 100644
--- a/src/libraries/System.Console/tests/ConsoleEncoding.cs
+++ b/src/libraries/System.Console/tests/ConsoleEncoding.cs
@@ -22,7 +22,7 @@ public static IEnumerable InputData()
[Theory]
[MemberData(nameof(InputData))]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public void TestEncoding(string inputString)
{
TextWriter outConsoleStream = Console.Out;
@@ -79,7 +79,7 @@ public void TestEncoding(string inputString)
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public void TestValidEncodings()
{
Action check = encoding =>
diff --git a/src/libraries/System.Console/tests/ReadAndWrite.cs b/src/libraries/System.Console/tests/ReadAndWrite.cs
index 7076c46edd9547..c4a13b21b644e0 100644
--- a/src/libraries/System.Console/tests/ReadAndWrite.cs
+++ b/src/libraries/System.Console/tests/ReadAndWrite.cs
@@ -258,7 +258,7 @@ private static unsafe void ValidateConsoleEncoding(Encoding encoding)
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public static unsafe void OutputEncodingPreamble()
{
Encoding curEncoding = Console.OutputEncoding;
@@ -281,7 +281,7 @@ public static unsafe void OutputEncodingPreamble()
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public static unsafe void OutputEncoding()
{
Encoding curEncoding = Console.OutputEncoding;
@@ -349,7 +349,7 @@ public static void InputEncoding_Getter_Throws_PlatformNotSupportedException()
};
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public static void ReadAndReadLine()
{
TextWriter savedStandardOutput = Console.Out;
diff --git a/src/libraries/System.Console/tests/SetIn.cs b/src/libraries/System.Console/tests/SetIn.cs
index 3531a7ec29ed32..46780d62e428e6 100644
--- a/src/libraries/System.Console/tests/SetIn.cs
+++ b/src/libraries/System.Console/tests/SetIn.cs
@@ -11,7 +11,7 @@
public class SetIn
{
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public static void SetInThrowsOnNull()
{
TextReader savedIn = Console.In;
@@ -26,7 +26,7 @@ public static void SetInThrowsOnNull()
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public static void SetInReadLine()
{
const string TextStringFormat = "Test {0}";
diff --git a/src/libraries/System.Console/tests/SyncTextReader.cs b/src/libraries/System.Console/tests/SyncTextReader.cs
index 699bda4948db10..3a5c0b5617b17f 100644
--- a/src/libraries/System.Console/tests/SyncTextReader.cs
+++ b/src/libraries/System.Console/tests/SyncTextReader.cs
@@ -78,7 +78,7 @@ private static void Test(string content, Action action)
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public void ReadToEnd()
{
var expected = string.Join(Environment.NewLine, s_testLines);
@@ -93,7 +93,7 @@ public void ReadToEnd()
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public void ReadBlock()
{
var expected = new[] { 'H', 'e', 'l', 'l', 'o' };
@@ -112,7 +112,7 @@ public void ReadBlock()
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public void Read()
{
var expected = new[] { 'H', 'e', 'l', 'l', 'o' };
@@ -131,7 +131,7 @@ public void Read()
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public void Peek()
{
const string expected = "ABC";
@@ -145,7 +145,7 @@ public void Peek()
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public void ReadToEndAsync()
{
var expected = string.Join(Environment.NewLine, s_testLines);
@@ -160,7 +160,7 @@ public void ReadToEndAsync()
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public void ReadBlockAsync()
{
var expected = new[] { 'H', 'e', 'l', 'l', 'o' };
@@ -185,7 +185,7 @@ public void ReadBlockAsync()
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public void ReadAsync()
{
var expected = new[] { 'H', 'e', 'l', 'l', 'o' };
@@ -210,7 +210,7 @@ public void ReadAsync()
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public void ReadLineAsync()
{
var expected = string.Join(Environment.NewLine, s_testLines);
diff --git a/src/libraries/System.Console/tests/TermInfo.cs b/src/libraries/System.Console/tests/TermInfo.cs
index b798f61da3d578..57962fc199b6ff 100644
--- a/src/libraries/System.Console/tests/TermInfo.cs
+++ b/src/libraries/System.Console/tests/TermInfo.cs
@@ -7,7 +7,7 @@
using System.Reflection;
using Xunit;
-[PlatformSpecific(~TestPlatforms.Browser)]
+[SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public class TermInfo
{
// Names of internal members accessed via reflection
diff --git a/src/libraries/System.Console/tests/ThreadSafety.cs b/src/libraries/System.Console/tests/ThreadSafety.cs
index e64e39235d68d3..ddc074760701e8 100644
--- a/src/libraries/System.Console/tests/ThreadSafety.cs
+++ b/src/libraries/System.Console/tests/ThreadSafety.cs
@@ -12,7 +12,7 @@ public class ThreadSafety
const int NumberOfIterations = 100;
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public static void OpenStandardXXXCanBeCalledConcurrently()
{
Parallel.For(0, NumberOfIterations, i =>
@@ -41,7 +41,7 @@ public static void OpenStandardXXXCanBeCalledConcurrently()
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public static void SetStandardXXXCanBeCalledConcurrently()
{
TextReader savedStandardInput = Console.In;
@@ -84,7 +84,7 @@ public static void SetStandardXXXCanBeCalledConcurrently()
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public static void ReadMayBeCalledConcurrently()
{
const char TestChar = '+';
diff --git a/src/libraries/System.Console/tests/Timeout.cs b/src/libraries/System.Console/tests/Timeout.cs
index cac8723a22febd..f8630073ed55ff 100644
--- a/src/libraries/System.Console/tests/Timeout.cs
+++ b/src/libraries/System.Console/tests/Timeout.cs
@@ -11,7 +11,7 @@
public class TimeOut
{
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public static void OpenStandardXXX_WriteTimeOut()
{
using (Stream standardOut = Console.OpenStandardOutput(), standardIn = Console.OpenStandardInput(), standardError = Console.OpenStandardError())
@@ -27,7 +27,7 @@ public static void OpenStandardXXX_WriteTimeOut()
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public static void OpenStandardXXX_ReadTimeOut()
{
using (Stream standardOut = Console.OpenStandardOutput(), standardIn = Console.OpenStandardInput(), standardError = Console.OpenStandardError())
@@ -43,7 +43,7 @@ public static void OpenStandardXXX_ReadTimeOut()
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public static void OpenStandardXXX_CanTimeOut()
{
using (Stream standardOut = Console.OpenStandardOutput(), standardIn = Console.OpenStandardInput(), standardError = Console.OpenStandardError())
diff --git a/src/libraries/System.Console/tests/WindowAndCursorProps.cs b/src/libraries/System.Console/tests/WindowAndCursorProps.cs
index 1da4ce47340ab6..32df8909e11b64 100644
--- a/src/libraries/System.Console/tests/WindowAndCursorProps.cs
+++ b/src/libraries/System.Console/tests/WindowAndCursorProps.cs
@@ -337,7 +337,7 @@ public static void SetCursorPosition_Throws_PlatformNotSupportedException()
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public static void SetCursorPosition_Invoke_Success()
{
if (!OperatingSystem.IsWindows() || (!Console.IsInputRedirected && !Console.IsOutputRedirected))
@@ -364,7 +364,7 @@ public void SetCursorPosition_InvalidPosition_ThrowsArgumentOutOfRangeException(
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public static void GetCursorPosition_Invoke_ReturnsExpected()
{
if (!Console.IsInputRedirected && !Console.IsOutputRedirected)
@@ -391,7 +391,7 @@ public static void GetCursorPosition_Invoke_ReturnsExpected()
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public void CursorLeft_Set_GetReturnsExpected()
{
if (!Console.IsInputRedirected && !Console.IsOutputRedirected)
@@ -413,7 +413,7 @@ public void CursorLeft_Set_GetReturnsExpected()
[Theory]
[InlineData(-1)]
[InlineData(short.MaxValue + 1)]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public void CursorLeft_SetInvalid_ThrowsArgumentOutOfRangeException(int value)
{
if (PlatformDetection.IsWindows && Console.IsOutputRedirected)
@@ -434,7 +434,7 @@ public void CursorLeft_Setter_Throws_PlatformNotSupportedException()
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public void CursorTop_Set_GetReturnsExpected()
{
if (!Console.IsInputRedirected && !Console.IsOutputRedirected)
@@ -456,7 +456,7 @@ public void CursorTop_Set_GetReturnsExpected()
[Theory]
[InlineData(-1)]
[InlineData(short.MaxValue + 1)]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public void CursorTop_SetInvalid_ThrowsArgumentOutOfRangeException(int value)
{
if (PlatformDetection.IsWindows & Console.IsOutputRedirected)
diff --git a/src/libraries/System.Data.Common/tests/System/Data/Common/DbProviderFactoriesTests.cs b/src/libraries/System.Data.Common/tests/System/Data/Common/DbProviderFactoriesTests.cs
index 2537fb30e95dba..b758b3967c62ee 100644
--- a/src/libraries/System.Data.Common/tests/System/Data/Common/DbProviderFactoriesTests.cs
+++ b/src/libraries/System.Data.Common/tests/System/Data/Common/DbProviderFactoriesTests.cs
@@ -15,7 +15,7 @@ public sealed class TestProviderFactory : DbProviderFactory
private TestProviderFactory() { }
}
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public class DbProviderFactoriesTests
{
[Fact]
diff --git a/src/libraries/System.Data.Common/tests/System/Data/Common/DbProviderFactoryTest.cs b/src/libraries/System.Data.Common/tests/System/Data/Common/DbProviderFactoryTest.cs
index b810686ab4f72d..92f2cb69b0bfae 100644
--- a/src/libraries/System.Data.Common/tests/System/Data/Common/DbProviderFactoryTest.cs
+++ b/src/libraries/System.Data.Common/tests/System/Data/Common/DbProviderFactoryTest.cs
@@ -6,7 +6,7 @@
namespace System.Data.Tests.Common
{
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public class DbProviderFactoryTest
{
[Fact]
diff --git a/src/libraries/System.Data.Common/tests/System/Data/DataTableExtensionsTest.cs b/src/libraries/System.Data.Common/tests/System/Data/DataTableExtensionsTest.cs
index 8608ba7bd645de..9d73511e9b07a9 100644
--- a/src/libraries/System.Data.Common/tests/System/Data/DataTableExtensionsTest.cs
+++ b/src/libraries/System.Data.Common/tests/System/Data/DataTableExtensionsTest.cs
@@ -5,7 +5,7 @@
namespace System.Data.Tests
{
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public class DataTableExtensionsTest
{
private DataTable _dt;
diff --git a/src/libraries/System.Data.Common/tests/System/Data/FacadeTest.cs b/src/libraries/System.Data.Common/tests/System/Data/FacadeTest.cs
index f8eba45d7f5c48..de9ce64a4c1ade 100644
--- a/src/libraries/System.Data.Common/tests/System/Data/FacadeTest.cs
+++ b/src/libraries/System.Data.Common/tests/System/Data/FacadeTest.cs
@@ -10,7 +10,7 @@ public class FacadeTest
[Theory]
[InlineData("Microsoft.SqlServer.Server.SqlMetaData")] // Type from System.Data.SqlClient
[InlineData("System.Data.SqlTypes.SqlBytes")] // Type from System.Data.Common
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public void TestSystemData(string typeName)
{
// Verify that the type can be loaded via .NET Framework compat facade
diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/TestWithConfigSwitches/System.Diagnostics.DiagnosticSource.Switches.Tests.csproj b/src/libraries/System.Diagnostics.DiagnosticSource/tests/TestWithConfigSwitches/System.Diagnostics.DiagnosticSource.Switches.Tests.csproj
index 1d596d074a3ad4..ea4a7ff67293d5 100644
--- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/TestWithConfigSwitches/System.Diagnostics.DiagnosticSource.Switches.Tests.csproj
+++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/TestWithConfigSwitches/System.Diagnostics.DiagnosticSource.Switches.Tests.csproj
@@ -2,10 +2,9 @@
$(NetCoreAppCurrent)
true
- true
+ true
-
-
\ No newline at end of file
+
diff --git a/src/libraries/System.Diagnostics.FileVersionInfo/src/System/Diagnostics/FileVersionInfo.Unix.cs b/src/libraries/System.Diagnostics.FileVersionInfo/src/System/Diagnostics/FileVersionInfo.Unix.cs
index bf7eb505001380..f666e971e3f8ed 100644
--- a/src/libraries/System.Diagnostics.FileVersionInfo/src/System/Diagnostics/FileVersionInfo.Unix.cs
+++ b/src/libraries/System.Diagnostics.FileVersionInfo/src/System/Diagnostics/FileVersionInfo.Unix.cs
@@ -1,7 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using System.Collections.Generic;
using System.IO;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
@@ -14,6 +13,15 @@ private FileVersionInfo(string fileName)
{
_fileName = fileName;
+ // First make sure it's a file we can actually read from. Only regular files are relevant,
+ // and attempting to open and read from a file such as a named pipe file could cause us to
+ // stop responding (waiting for someone else to open and write to the file).
+ if (Interop.Sys.Stat(_fileName, out Interop.Sys.FileStatus fileStatus) != 0 ||
+ (fileStatus.Mode & Interop.Sys.FileTypes.S_IFMT) != Interop.Sys.FileTypes.S_IFREG)
+ {
+ throw new FileNotFoundException(SR.Format(SR.IO_FileNotFound_FileName, _fileName), _fileName);
+ }
+
// For managed assemblies, read the file version information from the assembly's metadata.
// This isn't quite what's done on Windows, which uses the Win32 GetFileVersionInfo to read
// the Win32 resource information from the file, and the managed compiler uses these attributes
@@ -36,20 +44,10 @@ private FileVersionInfo(string fileName)
/// true if the file is a managed assembly; otherwise, false.
private bool TryLoadManagedAssemblyMetadata()
{
- // First make sure it's a file we can actually read from. Only regular files are relevant,
- // and attempting to open and read from a file such as a named pipe file could cause us to
- // stop responding (waiting for someone else to open and write to the file).
- Interop.Sys.FileStatus fileStatus;
- if (Interop.Sys.Stat(_fileName, out fileStatus) != 0 ||
- (fileStatus.Mode & Interop.Sys.FileTypes.S_IFMT) != Interop.Sys.FileTypes.S_IFREG)
- {
- throw new FileNotFoundException(SR.Format(SR.IO_FileNotFound_FileName, _fileName), _fileName);
- }
-
try
{
// Try to load the file using the managed metadata reader
- using (FileStream assemblyStream = new FileStream(_fileName, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 0x1000, useAsync: false))
+ using (FileStream assemblyStream = File.OpenRead(_fileName))
using (PEReader peReader = new PEReader(assemblyStream))
{
if (peReader.HasMetadata)
@@ -63,7 +61,14 @@ private bool TryLoadManagedAssemblyMetadata()
}
}
}
- catch (BadImageFormatException) { }
+ catch
+ {
+ // Obtaining this information is best effort and should not throw.
+ // Possible exceptions include BadImageFormatException if the file isn't an assembly,
+ // UnauthorizedAccessException if the caller doesn't have permissions to read the file,
+ // and other potential exceptions thrown by the FileStream ctor.
+ }
+
return false;
}
diff --git a/src/libraries/System.Diagnostics.FileVersionInfo/tests/System.Diagnostics.FileVersionInfo.Tests/AssemblyInfo.cs b/src/libraries/System.Diagnostics.FileVersionInfo/tests/System.Diagnostics.FileVersionInfo.Tests/AssemblyInfo.cs
index 85b21b953764df..d96dcc30ef2bbe 100644
--- a/src/libraries/System.Diagnostics.FileVersionInfo/tests/System.Diagnostics.FileVersionInfo.Tests/AssemblyInfo.cs
+++ b/src/libraries/System.Diagnostics.FileVersionInfo/tests/System.Diagnostics.FileVersionInfo.Tests/AssemblyInfo.cs
@@ -3,4 +3,4 @@
using Xunit;
-[assembly: SkipOnMono("System.Diagnostics.FileVersionInfo is not supported on wasm.", TestPlatforms.Browser)]
+[assembly: SkipOnPlatform(TestPlatforms.Browser, "System.Diagnostics.FileVersionInfo is not supported on Browser.")]
diff --git a/src/libraries/System.Diagnostics.Process/tests/AssemblyInfo.cs b/src/libraries/System.Diagnostics.Process/tests/AssemblyInfo.cs
index ae8def55d925a3..80471364814581 100644
--- a/src/libraries/System.Diagnostics.Process/tests/AssemblyInfo.cs
+++ b/src/libraries/System.Diagnostics.Process/tests/AssemblyInfo.cs
@@ -7,4 +7,4 @@
// like the console code page and environment variables
[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly)]
-[assembly: SkipOnMono("System.Diagnostics.Process is not supported on wasm.", TestPlatforms.Browser)]
+[assembly: SkipOnPlatform(TestPlatforms.Browser, "System.Diagnostics.Process is not supported on Browser.")]
diff --git a/src/libraries/System.Diagnostics.Process/tests/ProcessStreamReadTests.cs b/src/libraries/System.Diagnostics.Process/tests/ProcessStreamReadTests.cs
index 1f1027a58573ff..2620f965411e0c 100644
--- a/src/libraries/System.Diagnostics.Process/tests/ProcessStreamReadTests.cs
+++ b/src/libraries/System.Diagnostics.Process/tests/ProcessStreamReadTests.cs
@@ -345,7 +345,7 @@ async private Task WaitPipeSignal(PipeStream pipe, int millisecond)
}
}
- [PlatformSpecific(~TestPlatforms.Windows)] // currently on Windows these operations async-over-sync on Windows
+ [SkipOnPlatform(TestPlatforms.Windows, "currently on Windows these operations async-over-sync on Windows")]
[ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
public async Task ReadAsync_OutputStreams_Cancel_RespondsQuickly()
{
diff --git a/src/libraries/System.Diagnostics.Process/tests/ProcessTests.Unix.cs b/src/libraries/System.Diagnostics.Process/tests/ProcessTests.Unix.cs
index e64153fe1e1a0b..dccedb7e01dc5d 100644
--- a/src/libraries/System.Diagnostics.Process/tests/ProcessTests.Unix.cs
+++ b/src/libraries/System.Diagnostics.Process/tests/ProcessTests.Unix.cs
@@ -157,7 +157,7 @@ public void ProcessStart_UseShellExecute_OnUnix_SuccessWhenProgramInstalled(bool
}
[Fact]
- [PlatformSpecific(~TestPlatforms.OSX)] // On OSX, ProcessName returns the script interpreter.
+ [SkipOnPlatform(TestPlatforms.OSX, "On OSX, ProcessName returns the script interpreter.")]
public void ProcessNameMatchesScriptName()
{
string scriptName = GetTestFileName();
diff --git a/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs b/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs
index 2e206aa77d2545..8ece605da6f1cc 100644
--- a/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs
+++ b/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs
@@ -190,7 +190,7 @@ public void ProcessStart_TryOpenFolder_UseShellExecuteIsFalse_ThrowsWin32Excepti
}
[Fact]
- [PlatformSpecific(~TestPlatforms.OSX)] // OSX doesn't support throwing on Process.Start
+ [SkipOnPlatform(TestPlatforms.OSX, "OSX doesn't support throwing on Process.Start")]
public void TestStartWithBadWorkingDirectory()
{
string program;
@@ -542,7 +542,7 @@ public void TestMaxWorkingSet()
}
[Fact]
- [PlatformSpecific(~(TestPlatforms.OSX | TestPlatforms.FreeBSD))] // Getting MaxWorkingSet is not supported on OSX and BSD.
+ [SkipOnPlatform(TestPlatforms.OSX | TestPlatforms.FreeBSD, "Getting MaxWorkingSet is not supported on OSX and BSD.")]
public void MaxWorkingSet_GetNotStarted_ThrowsInvalidOperationException()
{
var process = new Process();
@@ -597,7 +597,7 @@ public void TestMinWorkingSet()
}
[Fact]
- [PlatformSpecific(~(TestPlatforms.OSX | TestPlatforms.FreeBSD))] // Getting MinWorkingSet is not supported on OSX and BSD.
+ [SkipOnPlatform(TestPlatforms.OSX | TestPlatforms.FreeBSD, "Getting MinWorkingSet is not supported on OSX and BSD.")]
public void MinWorkingSet_GetNotStarted_ThrowsInvalidOperationException()
{
var process = new Process();
@@ -896,7 +896,7 @@ public void ExitTime_GetNotStarted_ThrowsInvalidOperationException()
}
[ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
- [PlatformSpecific(~(TestPlatforms.OSX | TestPlatforms.FreeBSD))] // getting/setting affinity not supported on OSX and BSD
+ [SkipOnPlatform(TestPlatforms.OSX | TestPlatforms.FreeBSD, "getting/setting affinity not supported on OSX and BSD")]
public void TestProcessorAffinity()
{
CreateDefaultProcess();
diff --git a/src/libraries/System.Security.Cryptography.Csp/tests/AssemblyInfo.cs b/src/libraries/System.Diagnostics.StackTrace/tests/ExceptionTestAssembly/ExceptionTestAssembly.cs
similarity index 58%
rename from src/libraries/System.Security.Cryptography.Csp/tests/AssemblyInfo.cs
rename to src/libraries/System.Diagnostics.StackTrace/tests/ExceptionTestAssembly/ExceptionTestAssembly.cs
index 3a74f33d7aa32e..49902b1000c024 100644
--- a/src/libraries/System.Security.Cryptography.Csp/tests/AssemblyInfo.cs
+++ b/src/libraries/System.Diagnostics.StackTrace/tests/ExceptionTestAssembly/ExceptionTestAssembly.cs
@@ -2,6 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
-using Xunit;
-[assembly: ActiveIssue("https://github.com/dotnet/runtime/issues/37669", TestPlatforms.Browser)]
+class Program
+{
+ public static void Foo()
+ {
+ throw new NullReferenceException();
+ }
+}
diff --git a/src/libraries/System.Diagnostics.StackTrace/tests/ExceptionTestAssembly/ExceptionTestAssembly.csproj b/src/libraries/System.Diagnostics.StackTrace/tests/ExceptionTestAssembly/ExceptionTestAssembly.csproj
new file mode 100644
index 00000000000000..d7b60a977d7ced
--- /dev/null
+++ b/src/libraries/System.Diagnostics.StackTrace/tests/ExceptionTestAssembly/ExceptionTestAssembly.csproj
@@ -0,0 +1,10 @@
+
+
+ true
+ netstandard2.0
+ None
+
+
+
+
+
diff --git a/src/libraries/System.Diagnostics.StackTrace/tests/StackTraceTests.cs b/src/libraries/System.Diagnostics.StackTrace/tests/StackTraceTests.cs
index 894374ba29b4dc..0464a22a44014c 100644
--- a/src/libraries/System.Diagnostics.StackTrace/tests/StackTraceTests.cs
+++ b/src/libraries/System.Diagnostics.StackTrace/tests/StackTraceTests.cs
@@ -3,9 +3,13 @@
using System.Collections.Generic;
using System.Globalization;
+using System.IO;
using System.Linq;
using System.Reflection;
+using System.Reflection.Emit;
using System.Runtime.CompilerServices;
+using System.Text.RegularExpressions;
+using Microsoft.DotNet.RemoteExecutor;
using Xunit;
namespace System.Diagnostics
@@ -300,6 +304,72 @@ public void ToString_NullFrame_ThrowsNullReferenceException()
Assert.Equal(Environment.NewLine, stackTrace.ToString());
}
+ [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
+ [ActiveIssue("https://github.com/dotnet/runtime/issues/51096", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoInterpreter))]
+ public void ToString_ShowILOffset()
+ {
+ string AssemblyName = "ExceptionTestAssembly.dll";
+ string SourceTestAssemblyPath = Path.Combine(Environment.CurrentDirectory, AssemblyName);
+ string regPattern = @":token 0x([a-f0-9]*)\+0x([a-f0-9]*)";
+
+ // Normal loading case
+ RemoteExecutor.Invoke((asmPath, asmName, p) =>
+ {
+ AppContext.SetSwitch("Switch.System.Diagnostics.StackTrace.ShowILOffsets", true);
+ var asm = Assembly.LoadFrom(asmPath);
+ try
+ {
+ asm.GetType("Program").GetMethod("Foo").Invoke(null, null);
+ }
+ catch (Exception e)
+ {
+ Assert.Contains(asmName, e.InnerException.StackTrace);
+ Assert.True(Regex.Match(e.InnerException.StackTrace, p).Success);
+ }
+ }, SourceTestAssemblyPath, AssemblyName, regPattern).Dispose();
+
+ // Assembly.Load(Byte[]) case
+ RemoteExecutor.Invoke((asmPath, asmName, p) =>
+ {
+ AppContext.SetSwitch("Switch.System.Diagnostics.StackTrace.ShowILOffsets", true);
+ var inMemBlob = File.ReadAllBytes(asmPath);
+ var asm2 = Assembly.Load(inMemBlob);
+ try
+ {
+ asm2.GetType("Program").GetMethod("Foo").Invoke(null, null);
+ }
+ catch (Exception e)
+ {
+ Assert.Contains(asmName, e.InnerException.StackTrace);
+ Assert.True(Regex.Match(e.InnerException.StackTrace, p).Success);
+ }
+ }, SourceTestAssemblyPath, AssemblyName, regPattern).Dispose();
+
+ // AssmblyBuilder.DefineDynamicAssembly() case
+ RemoteExecutor.Invoke((p) =>
+ {
+ AppContext.SetSwitch("Switch.System.Diagnostics.StackTrace.ShowILOffsets", true);
+ AssemblyName asmName = new AssemblyName("ExceptionTestAssembly");
+ AssemblyBuilder asmBldr = AssemblyBuilder.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.Run);
+ ModuleBuilder modBldr = asmBldr.DefineDynamicModule(asmName.Name);
+ TypeBuilder tBldr = modBldr.DefineType("Program");
+ MethodBuilder mBldr = tBldr.DefineMethod("Foo", MethodAttributes.Public | MethodAttributes.Static, null, null);
+ ILGenerator ilGen = mBldr.GetILGenerator();
+ ilGen.ThrowException(typeof(NullReferenceException));
+ ilGen.Emit(OpCodes.Ret);
+ Type t = tBldr.CreateType();
+ try
+ {
+ t.InvokeMember("Foo", BindingFlags.InvokeMethod, null, null, null);
+ }
+ catch (Exception e)
+ {
+ Assert.Contains("RefEmit_InMemoryManifestModule", e.InnerException.StackTrace);
+ Assert.True(Regex.Match(e.InnerException.StackTrace, p).Success);
+ }
+ }, regPattern).Dispose();
+ }
+
[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
private static StackTrace NoParameters() => new StackTrace();
[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
diff --git a/src/libraries/System.Diagnostics.StackTrace/tests/System.Diagnostics.StackTrace.Tests.csproj b/src/libraries/System.Diagnostics.StackTrace/tests/System.Diagnostics.StackTrace.Tests.csproj
index b112648c183634..93673781e705f4 100644
--- a/src/libraries/System.Diagnostics.StackTrace/tests/System.Diagnostics.StackTrace.Tests.csproj
+++ b/src/libraries/System.Diagnostics.StackTrace/tests/System.Diagnostics.StackTrace.Tests.csproj
@@ -2,6 +2,7 @@
$(NetCoreAppCurrent)
true
+ true
@@ -17,4 +18,7 @@
-
\ No newline at end of file
+
+
+
+
diff --git a/src/libraries/System.Drawing.Common/tests/AssemblyInfo.cs b/src/libraries/System.Drawing.Common/tests/AssemblyInfo.cs
index 17f46496f4fcef..b1abf9bdf2391f 100644
--- a/src/libraries/System.Drawing.Common/tests/AssemblyInfo.cs
+++ b/src/libraries/System.Drawing.Common/tests/AssemblyInfo.cs
@@ -5,4 +5,4 @@
using Xunit;
[assembly: ActiveIssue("https://github.com/dotnet/runtime/issues/35917", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoInterpreter))]
-[assembly: SkipOnMono("System.Drawing.Common is not supported on Browser", TestPlatforms.Browser)]
+[assembly: SkipOnPlatform(TestPlatforms.Browser, "System.Drawing.Common is not supported on Browser")]
diff --git a/src/libraries/System.Drawing.Common/tests/System.Drawing.Common.Tests.csproj b/src/libraries/System.Drawing.Common/tests/System.Drawing.Common.Tests.csproj
index 9dfd74f0454a21..9d0c15dec7797b 100644
--- a/src/libraries/System.Drawing.Common/tests/System.Drawing.Common.Tests.csproj
+++ b/src/libraries/System.Drawing.Common/tests/System.Drawing.Common.Tests.csproj
@@ -3,6 +3,7 @@
true
true
$(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;net48
+ true
diff --git a/src/libraries/System.IO.Compression.Brotli/tests/AssemblyInfo.cs b/src/libraries/System.IO.Compression.Brotli/tests/AssemblyInfo.cs
index 1038dc251cb5b3..7f8b8095c28136 100644
--- a/src/libraries/System.IO.Compression.Brotli/tests/AssemblyInfo.cs
+++ b/src/libraries/System.IO.Compression.Brotli/tests/AssemblyInfo.cs
@@ -4,4 +4,4 @@
using System;
using Xunit;
-[assembly: SkipOnMono("System.IO.Compression.Brotli is not supported on Browser", TestPlatforms.Browser)]
+[assembly: SkipOnPlatform(TestPlatforms.Browser, "System.IO.Compression.Brotli is not supported on Browser")]
diff --git a/src/libraries/System.IO.Compression.Brotli/tests/System.IO.Compression.Brotli.Tests.csproj b/src/libraries/System.IO.Compression.Brotli/tests/System.IO.Compression.Brotli.Tests.csproj
index 60afa44f33d27f..d68a7be37b621e 100644
--- a/src/libraries/System.IO.Compression.Brotli/tests/System.IO.Compression.Brotli.Tests.csproj
+++ b/src/libraries/System.IO.Compression.Brotli/tests/System.IO.Compression.Brotli.Tests.csproj
@@ -2,6 +2,7 @@
$(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Browser
true
+ true
diff --git a/src/libraries/System.IO.FileSystem.Watcher/tests/AssemblyInfo.cs b/src/libraries/System.IO.FileSystem.Watcher/tests/AssemblyInfo.cs
index e5921a9bc9b3f9..94b42c5041cc9f 100644
--- a/src/libraries/System.IO.FileSystem.Watcher/tests/AssemblyInfo.cs
+++ b/src/libraries/System.IO.FileSystem.Watcher/tests/AssemblyInfo.cs
@@ -4,4 +4,4 @@
using System;
using Xunit;
-[assembly: SkipOnMono("System.IO.FileSystem.Watcher is not supported on wasm", TestPlatforms.Browser)]
+[assembly: SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")]
diff --git a/src/libraries/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.Directory.Move.cs b/src/libraries/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.Directory.Move.cs
index 2f2230c7b89d79..b40fac4e7602f5 100644
--- a/src/libraries/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.Directory.Move.cs
+++ b/src/libraries/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.Directory.Move.cs
@@ -39,7 +39,7 @@ public void Directory_Move_Multiple_From_Watched_To_Unwatched_Mac(int filesCount
}
[Theory]
- [PlatformSpecific(~TestPlatforms.OSX)]
+ [SkipOnPlatform(TestPlatforms.OSX, "Not supported on OSX.")]
[InlineData(1)]
[InlineData(2)]
[InlineData(3)]
@@ -49,7 +49,7 @@ public void Directory_Move_Multiple_From_Watched_To_Unwatched(int filesCount)
}
[Theory]
- [PlatformSpecific(~TestPlatforms.FreeBSD)]
+ [SkipOnPlatform(TestPlatforms.FreeBSD, "Not supported on FreeBSD.")]
[InlineData(1)]
[InlineData(2)]
[InlineData(3)]
diff --git a/src/libraries/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.File.Move.cs b/src/libraries/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.File.Move.cs
index 2af77eb827a273..05ba2620929768 100644
--- a/src/libraries/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.File.Move.cs
+++ b/src/libraries/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.File.Move.cs
@@ -43,7 +43,7 @@ public void File_Move_Multiple_From_Watched_To_Unwatched_Mac(int filesCount)
}
[Theory]
- [PlatformSpecific(~TestPlatforms.OSX)]
+ [SkipOnPlatform(TestPlatforms.OSX, "Not supported on OSX.")]
[InlineData(1)]
[InlineData(2)]
[InlineData(3)]
diff --git a/src/libraries/System.IO.FileSystem.Watcher/tests/System.IO.FileSystem.Watcher.Tests.csproj b/src/libraries/System.IO.FileSystem.Watcher/tests/System.IO.FileSystem.Watcher.Tests.csproj
index 6198325a2dfb7a..4c7b2edca0e061 100644
--- a/src/libraries/System.IO.FileSystem.Watcher/tests/System.IO.FileSystem.Watcher.Tests.csproj
+++ b/src/libraries/System.IO.FileSystem.Watcher/tests/System.IO.FileSystem.Watcher.Tests.csproj
@@ -2,6 +2,7 @@
true
$(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Linux;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-tvOS;$(NetCoreAppCurrent)-FreeBSD
+ true
diff --git a/src/libraries/System.IO.FileSystem/tests/Directory/CreateDirectory.cs b/src/libraries/System.IO.FileSystem/tests/Directory/CreateDirectory.cs
index 78c234d5627cd5..ed833bbc89212d 100644
--- a/src/libraries/System.IO.FileSystem/tests/Directory/CreateDirectory.cs
+++ b/src/libraries/System.IO.FileSystem/tests/Directory/CreateDirectory.cs
@@ -216,7 +216,7 @@ public void DirectoryEqualToMaxDirectory_CanBeCreatedAllAtOnce()
[Theory,
MemberData(nameof(PathsWithComponentLongerThanMaxComponent))]
- [PlatformSpecific(~TestPlatforms.Browser)] // Browser does not have a limit on the maximum component length
+ [SkipOnPlatform(TestPlatforms.Browser, "Browser does not have a limit on the maximum component length")]
public void DirectoryWithComponentLongerThanMaxComponentAsPath_ThrowsException(string path)
{
AssertExtensions.ThrowsAny(() => Create(path));
diff --git a/src/libraries/System.IO.FileSystem/tests/File/Copy.cs b/src/libraries/System.IO.FileSystem/tests/File/Copy.cs
index aa3c929bad1c84..0654f99dc9ce32 100644
--- a/src/libraries/System.IO.FileSystem/tests/File/Copy.cs
+++ b/src/libraries/System.IO.FileSystem/tests/File/Copy.cs
@@ -343,7 +343,7 @@ public void WindowsAlternateDataStreamOverwrite(string defaultStream, string alt
///
/// Single tests that shouldn't be duplicated by inheritance.
///
- [PlatformSpecific(~TestPlatforms.Browser)] // https://github.com/dotnet/runtime/issues/40867 - flock not supported
+ [SkipOnPlatform(TestPlatforms.Browser, "https://github.com/dotnet/runtime/issues/40867 - flock not supported")]
public sealed class File_Copy_Single : FileSystemTest
{
[Fact]
diff --git a/src/libraries/System.IO.FileSystem/tests/File/Create.cs b/src/libraries/System.IO.FileSystem/tests/File/Create.cs
index 447bb323baffd0..d89fcd26a5b9c2 100644
--- a/src/libraries/System.IO.FileSystem/tests/File/Create.cs
+++ b/src/libraries/System.IO.FileSystem/tests/File/Create.cs
@@ -150,7 +150,7 @@ public void OverwriteReadOnly()
#region PlatformSpecific
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)] // Browser platform volume does not limit segments
+ [SkipOnPlatform(TestPlatforms.Browser, "Browser platform volume does not limit segments")]
public void LongPathSegment()
{
DirectoryInfo testDir = Directory.CreateDirectory(GetTestFilePath());
diff --git a/src/libraries/System.IO.FileSystem/tests/FileInfo/Exists.cs b/src/libraries/System.IO.FileSystem/tests/FileInfo/Exists.cs
index b0f1779745f613..72b8ba48ba3ab2 100644
--- a/src/libraries/System.IO.FileSystem/tests/FileInfo/Exists.cs
+++ b/src/libraries/System.IO.FileSystem/tests/FileInfo/Exists.cs
@@ -146,7 +146,7 @@ public void UnsharedFileExists()
}
[ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
- [PlatformSpecific(~TestPlatforms.OSX)]
+ [SkipOnPlatform(TestPlatforms.OSX, "Not supported on OSX.")]
public void LockedFileExists()
{
string path = GetTestFilePath();
diff --git a/src/libraries/System.IO.FileSystem/tests/FileStream/FileStreamConformanceTests.cs b/src/libraries/System.IO.FileSystem/tests/FileStream/FileStreamConformanceTests.cs
index 82b10a882c3d38..f086c2cc23609f 100644
--- a/src/libraries/System.IO.FileSystem/tests/FileStream/FileStreamConformanceTests.cs
+++ b/src/libraries/System.IO.FileSystem/tests/FileStream/FileStreamConformanceTests.cs
@@ -161,6 +161,31 @@ public async Task LengthIsNotCachedAfterHandleHasBeenExposed(FileAccess fileAcce
Assert.Equal(2, stream.Length);
Assert.Equal(2, createdFromHandle.Length);
}
+
+ [Fact]
+ public async Task WriteByteFlushesTheBufferWhenItBecomesFull()
+ {
+ string filePath;
+ List writtenBytes = new List();
+
+ using (FileStream stream = (FileStream)await CreateWriteOnlyStreamCore(Array.Empty()))
+ {
+ filePath = stream.Name;
+
+ stream.WriteByte(0);
+ writtenBytes.Add(0);
+
+ byte[] bytes = new byte[BufferSize - 1];
+ stream.Write(bytes.AsSpan());
+ writtenBytes.AddRange(bytes);
+
+ stream.WriteByte(1);
+ writtenBytes.Add(1);
+ }
+
+ byte[] allBytes = File.ReadAllBytes(filePath);
+ Assert.Equal(writtenBytes.ToArray(), allBytes);
+ }
}
public class UnbufferedSyncFileStreamStandaloneConformanceTests : FileStreamStandaloneConformanceTests
@@ -176,7 +201,7 @@ public class BufferedSyncFileStreamStandaloneConformanceTests : FileStreamStanda
}
[ActiveIssue("https://github.com/dotnet/runtime/issues/34583", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)]
- [PlatformSpecific(~TestPlatforms.Browser)] // copied from base class due to https://github.com/xunit/xunit/issues/2186
+ [SkipOnPlatform(TestPlatforms.Browser, "lots of operations aren't supported on browser")] // copied from StreamConformanceTests base class due to https://github.com/xunit/xunit/issues/2186
public class UnbufferedAsyncFileStreamStandaloneConformanceTests : FileStreamStandaloneConformanceTests
{
protected override FileOptions Options => FileOptions.Asynchronous;
@@ -184,7 +209,7 @@ public class UnbufferedAsyncFileStreamStandaloneConformanceTests : FileStreamSta
}
[ActiveIssue("https://github.com/dotnet/runtime/issues/34583", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)]
- [PlatformSpecific(~TestPlatforms.Browser)] // copied from base class due to https://github.com/xunit/xunit/issues/2186
+ [SkipOnPlatform(TestPlatforms.Browser, "lots of operations aren't supported on browser")] // copied from StreamConformanceTests base class due to https://github.com/xunit/xunit/issues/2186
public class BufferedAsyncFileStreamStandaloneConformanceTests : FileStreamStandaloneConformanceTests
{
protected override FileOptions Options => FileOptions.Asynchronous;
diff --git a/src/libraries/System.IO.FileSystem/tests/FileStream/Flush.cs b/src/libraries/System.IO.FileSystem/tests/FileStream/Flush.cs
index 10e522185726ee..25dd6422410aa5 100644
--- a/src/libraries/System.IO.FileSystem/tests/FileStream/Flush.cs
+++ b/src/libraries/System.IO.FileSystem/tests/FileStream/Flush.cs
@@ -147,7 +147,7 @@ public void SafeFileHandleCallsFlush_flushToDisk_False()
[InlineData(null)]
[InlineData(false)]
[InlineData(true)]
- [PlatformSpecific(~TestPlatforms.Browser)] // IO.Pipes not supported
+ [SkipOnPlatform(TestPlatforms.Browser, "IO.Pipes not supported")]
public void FlushCanBeUsedOnPipes_Success(bool? flushToDisk)
{
using (var pipeStream = new AnonymousPipeServerStream(PipeDirection.In))
diff --git a/src/libraries/System.IO.FileSystem/tests/FileStream/LockUnlock.cs b/src/libraries/System.IO.FileSystem/tests/FileStream/LockUnlock.cs
index 1da23bf4c08258..d2f7bf7ec62c15 100644
--- a/src/libraries/System.IO.FileSystem/tests/FileStream/LockUnlock.cs
+++ b/src/libraries/System.IO.FileSystem/tests/FileStream/LockUnlock.cs
@@ -58,7 +58,7 @@ public void LockUnlock_Unsupported_OSX()
[InlineData(200, 50, 150)]
[InlineData(200, 100, 100)]
[InlineData(20, 2000, 1000)]
- [PlatformSpecific(~TestPlatforms.OSX)]
+ [SkipOnPlatform(TestPlatforms.OSX, "Not supported on OSX.")]
public void Lock_Unlock_Successful(long fileLength, long position, long length)
{
string path = GetTestFilePath();
@@ -75,7 +75,7 @@ public void Lock_Unlock_Successful(long fileLength, long position, long length)
[InlineData(FileAccess.Read)]
[InlineData(FileAccess.Write)]
[InlineData(FileAccess.ReadWrite)]
- [PlatformSpecific(~TestPlatforms.OSX)]
+ [SkipOnPlatform(TestPlatforms.OSX, "Not supported on OSX.")]
public void Lock_Unlock_Successful_AlternateFileAccess(FileAccess fileAccess)
{
string path = GetTestFilePath();
@@ -89,7 +89,7 @@ public void Lock_Unlock_Successful_AlternateFileAccess(FileAccess fileAccess)
[Theory]
[InlineData(10, 0, 2, 3, 5)]
- [PlatformSpecific(~TestPlatforms.OSX)]
+ [SkipOnPlatform(TestPlatforms.OSX, "Not supported on OSX.")]
public void NonOverlappingRegions_Success(long fileLength, long firstPosition, long firstLength, long secondPosition, long secondLength)
{
string path = GetTestFilePath();
@@ -176,7 +176,7 @@ public void OverlappingRegionsFromSameProcess_AllowedOnUnix(long fileLength, lon
[InlineData(10, 3, 5, 2, 6)]
[InlineData(10, 3, 5, 2, 4)]
[InlineData(10, 3, 5, 4, 6)]
- [PlatformSpecific(~TestPlatforms.OSX)]
+ [SkipOnPlatform(TestPlatforms.OSX, "Not supported on OSX.")]
public void OverlappingRegionsFromOtherProcess_ThrowsException(long fileLength, long firstPosition, long firstLength, long secondPosition, long secondLength)
{
string path = GetTestFilePath();
@@ -231,7 +231,7 @@ public void OverlappingRegionsFromOtherProcess_With_ReadLock_AllowedOnLinux()
[InlineData(FileAccess.Read)]
[InlineData(FileAccess.Write)]
[InlineData(FileAccess.ReadWrite)]
- [PlatformSpecific(~TestPlatforms.OSX)]
+ [SkipOnPlatform(TestPlatforms.OSX, "Not supported on OSX.")]
public void OverlappingRegionsFromOtherProcess_With_WriteLock_ThrowsException(FileAccess fileAccess)
{
string path = GetTestFilePath();
diff --git a/src/libraries/System.IO.FileSystem/tests/Net5CompatTests/Net5CompatSwitchTests.cs b/src/libraries/System.IO.FileSystem/tests/Net5CompatTests/Net5CompatSwitchTests.cs
index bb2d05086cf0ad..24f9026b54dfff 100644
--- a/src/libraries/System.IO.FileSystem/tests/Net5CompatTests/Net5CompatSwitchTests.cs
+++ b/src/libraries/System.IO.FileSystem/tests/Net5CompatTests/Net5CompatSwitchTests.cs
@@ -20,7 +20,7 @@ public static void LegacySwitchIsHonored()
.GetField("_strategy", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(fileStream);
- Assert.DoesNotContain("Net5Compat", strategy.GetType().FullName);
+ Assert.Contains("Net5Compat", strategy.GetType().FullName);
}
File.Delete(filePath);
diff --git a/src/libraries/System.IO.FileSystem/tests/Net5CompatTests/runtimeconfig.template.json b/src/libraries/System.IO.FileSystem/tests/Net5CompatTests/runtimeconfig.template.json
index 0c1a3482aba4f8..6e843517fe47af 100644
--- a/src/libraries/System.IO.FileSystem/tests/Net5CompatTests/runtimeconfig.template.json
+++ b/src/libraries/System.IO.FileSystem/tests/Net5CompatTests/runtimeconfig.template.json
@@ -1,5 +1,5 @@
{
"configProperties": {
- "System.IO.UseNet5CompatFileStream": false
+ "System.IO.UseNet5CompatFileStream": true
}
}
diff --git a/src/libraries/System.IO.IsolatedStorage/tests/AssemblyInfo.cs b/src/libraries/System.IO.IsolatedStorage/tests/AssemblyInfo.cs
index dadc27e2fbf2b3..2e17f1038062cf 100644
--- a/src/libraries/System.IO.IsolatedStorage/tests/AssemblyInfo.cs
+++ b/src/libraries/System.IO.IsolatedStorage/tests/AssemblyInfo.cs
@@ -9,4 +9,4 @@
// it's own store.
[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly, DisableTestParallelization = true)]
[assembly: ActiveIssue("https://github.com/dotnet/runtime/issues/48720", TestPlatforms.AnyUnix, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)]
-[assembly: SkipOnMono("System.IO.IsolatedStorage is not supported on Browser", TestPlatforms.Browser)]
+[assembly: SkipOnPlatform(TestPlatforms.Browser, "System.IO.IsolatedStorage is not supported on Browser")]
diff --git a/src/libraries/System.IO.IsolatedStorage/tests/System.IO.IsolatedStorage.Tests.csproj b/src/libraries/System.IO.IsolatedStorage/tests/System.IO.IsolatedStorage.Tests.csproj
index b37dff5c1d8974..5765f53e6056ec 100644
--- a/src/libraries/System.IO.IsolatedStorage/tests/System.IO.IsolatedStorage.Tests.csproj
+++ b/src/libraries/System.IO.IsolatedStorage/tests/System.IO.IsolatedStorage.Tests.csproj
@@ -1,6 +1,7 @@
$(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Browser
+ true
diff --git a/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedFile.CreateFromFile.Tests.cs b/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedFile.CreateFromFile.Tests.cs
index 4a08c3f7e3a80c..1df45e91bf5522 100644
--- a/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedFile.CreateFromFile.Tests.cs
+++ b/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedFile.CreateFromFile.Tests.cs
@@ -613,7 +613,7 @@ public void FileInUse_CreateFromFile_FailsWithExistingReadWriteMap()
/// Test exceptional behavior when trying to create a map for a non-shared file that's currently in use.
///
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)] // the emscripten implementation ignores FileShare.None
+ [SkipOnPlatform(TestPlatforms.Browser, "the emscripten implementation ignores FileShare.None")]
public void FileInUse_CreateFromFile_FailsWithExistingNoShareFile()
{
// Already opened with a FileStream
@@ -768,7 +768,7 @@ public void LeaveOpenRespected_OutstandingViews(bool leaveOpen)
/// Test to validate we can create multiple maps from the same FileStream.
///
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)] // the emscripten implementation doesn't share data
+ [SkipOnPlatform(TestPlatforms.Browser, "the emscripten implementation doesn't share data")]
public void MultipleMapsForTheSameFileStream()
{
const int Capacity = 4096;
@@ -829,7 +829,7 @@ public void FileSizeExpandsToCapacity()
///
/// Test the exceptional behavior when attempting to create a map so large it's not supported.
///
- [PlatformSpecific(~TestPlatforms.OSX)] // Because of the file-based backing, OS X pops up a warning dialog about being out-of-space (even though we clean up immediately)
+ [SkipOnPlatform(TestPlatforms.OSX, "Because of the file-based backing, OS X pops up a warning dialog about being out-of-space (even though we clean up immediately)")]
[Fact]
public void TooLargeCapacity()
{
diff --git a/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewAccessor.Tests.cs b/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewAccessor.Tests.cs
index 0e0f76284dfeb8..3193942d2fafd8 100644
--- a/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewAccessor.Tests.cs
+++ b/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewAccessor.Tests.cs
@@ -347,7 +347,7 @@ public void FlushSupportedOnBothReadAndWriteAccessors(MemoryMappedFileAccess acc
/// Test to validate that multiple accessors over the same map share data appropriately.
///
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)] // the emscripten implementation doesn't share data
+ [SkipOnPlatform(TestPlatforms.Browser, "the emscripten implementation doesn't share data")]
public void ViewsShareData()
{
const int MapLength = 256;
diff --git a/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewStream.Tests.cs b/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewStream.Tests.cs
index f8c073d86a269a..b1b4b1a610ee5a 100644
--- a/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewStream.Tests.cs
+++ b/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewStream.Tests.cs
@@ -221,7 +221,7 @@ public void AllReadWriteMethods(long offset, long size)
/// Test to validate that multiple accessors over the same map share data appropriately.
///
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)] // the emscripten implementation doesn't share data
+ [SkipOnPlatform(TestPlatforms.Browser, "the emscripten implementation doesn't share data")]
public void ViewsShareData()
{
const int MapLength = 256;
diff --git a/src/libraries/System.IO.Pipelines/tests/PipeWriterTests.cs b/src/libraries/System.IO.Pipelines/tests/PipeWriterTests.cs
index e6a64d47f28be6..0abdfa252da78d 100644
--- a/src/libraries/System.IO.Pipelines/tests/PipeWriterTests.cs
+++ b/src/libraries/System.IO.Pipelines/tests/PipeWriterTests.cs
@@ -229,7 +229,7 @@ public async Task WritesUsingGetMemoryWorks()
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Browser)] // allocates too much memory
+ [SkipOnPlatform(TestPlatforms.Browser, "allocates too much memory")]
public async Task CompleteWithLargeWriteThrows()
{
var pipe = new Pipe();
diff --git a/src/libraries/System.IO.Pipes/tests/AssemblyInfo.cs b/src/libraries/System.IO.Pipes/tests/AssemblyInfo.cs
index 394d602401c8c2..806ccf216126e3 100644
--- a/src/libraries/System.IO.Pipes/tests/AssemblyInfo.cs
+++ b/src/libraries/System.IO.Pipes/tests/AssemblyInfo.cs
@@ -4,4 +4,4 @@
using Xunit;
[assembly: ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)]
-[assembly: SkipOnMono("System.IO.Pipes is not supported on Browser", TestPlatforms.Browser)]
+[assembly: SkipOnPlatform(TestPlatforms.Browser, "System.IO.Pipes is not supported on Browser")]
diff --git a/src/libraries/System.IO/tests/BinaryWriter/BinaryWriter.EncodingTests.cs b/src/libraries/System.IO/tests/BinaryWriter/BinaryWriter.EncodingTests.cs
index b22020a36dc4f2..6a41e67c0e8086 100644
--- a/src/libraries/System.IO/tests/BinaryWriter/BinaryWriter.EncodingTests.cs
+++ b/src/libraries/System.IO/tests/BinaryWriter/BinaryWriter.EncodingTests.cs
@@ -188,7 +188,7 @@ public void WriteString_NotUtf8(int stringLengthInChars)
}
[Fact]
- [PlatformSpecific(~TestPlatforms.Android)] // OOM on Android could be uncatchable & kill the test runner
+ [SkipOnPlatform(TestPlatforms.Android, "OOM on Android could be uncatchable & kill the test runner")]
public unsafe void WriteChars_VeryLargeArray_DoesNotOverflow()
{
const nuint INPUT_LEN_IN_CHARS = 1_500_000_000;
diff --git a/src/libraries/System.IO/tests/Net5CompatTests/runtimeconfig.template.json b/src/libraries/System.IO/tests/Net5CompatTests/runtimeconfig.template.json
index 0c1a3482aba4f8..6e843517fe47af 100644
--- a/src/libraries/System.IO/tests/Net5CompatTests/runtimeconfig.template.json
+++ b/src/libraries/System.IO/tests/Net5CompatTests/runtimeconfig.template.json
@@ -1,5 +1,5 @@
{
"configProperties": {
- "System.IO.UseNet5CompatFileStream": false
+ "System.IO.UseNet5CompatFileStream": true
}
}
diff --git a/src/libraries/System.IO/tests/StreamReader/StreamReaderTests.cs b/src/libraries/System.IO/tests/StreamReader/StreamReaderTests.cs
index a16321c03f087e..4e4bb14d233e4a 100644
--- a/src/libraries/System.IO/tests/StreamReader/StreamReaderTests.cs
+++ b/src/libraries/System.IO/tests/StreamReader/StreamReaderTests.cs
@@ -512,7 +512,7 @@ public async Task ReadBlockAsync_RepeatsReadsUntilReadDesiredAmount()
[InlineData(0, true)]
[InlineData(1, false)]
[InlineData(1, true)]
- [PlatformSpecific(~TestPlatforms.Browser)]
+ [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser.")]
public async Task ReadAsync_Canceled_ThrowsException(int method, bool precanceled)
{
Func> func = method switch
diff --git a/src/libraries/System.Linq.Queryable/ref/System.Linq.Queryable.cs b/src/libraries/System.Linq.Queryable/ref/System.Linq.Queryable.cs
index bd3497d53c6580..a6ae3b48620a9c 100644
--- a/src/libraries/System.Linq.Queryable/ref/System.Linq.Queryable.cs
+++ b/src/libraries/System.Linq.Queryable/ref/System.Linq.Queryable.cs
@@ -77,18 +77,22 @@ public static partial class Queryable
public static int Count(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate) { throw null; }
public static System.Linq.IQueryable DefaultIfEmpty(this System.Linq.IQueryable source) { throw null; }
public static System.Linq.IQueryable DefaultIfEmpty(this System.Linq.IQueryable source, TSource defaultValue) { throw null; }
+ public static System.Linq.IQueryable DistinctBy(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector) { throw null; }
+ public static System.Linq.IQueryable DistinctBy(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector, System.Collections.Generic.IEqualityComparer? comparer) { throw null; }
public static System.Linq.IQueryable Distinct(this System.Linq.IQueryable source) { throw null; }
public static System.Linq.IQueryable Distinct(this System.Linq.IQueryable source, System.Collections.Generic.IEqualityComparer? comparer) { throw null; }
- public static TSource? ElementAtOrDefault(this System.Linq.IQueryable source, int index) { throw null; }
public static TSource? ElementAtOrDefault(this System.Linq.IQueryable source, System.Index index) { throw null; }
- public static TSource ElementAt(this System.Linq.IQueryable source, int index) { throw null; }
+ public static TSource? ElementAtOrDefault(this System.Linq.IQueryable source, int index) { throw null; }
public static TSource ElementAt(this System.Linq.IQueryable source, System.Index index) { throw null; }
+ public static TSource ElementAt(this System.Linq.IQueryable source, int index) { throw null; }
+ public static System.Linq.IQueryable ExceptBy(this System.Linq.IQueryable source1, System.Collections.Generic.IEnumerable source2, System.Linq.Expressions.Expression> keySelector) { throw null; }
+ public static System.Linq.IQueryable ExceptBy(this System.Linq.IQueryable source1, System.Collections.Generic.IEnumerable source2, System.Linq.Expressions.Expression> keySelector, System.Collections.Generic.IEqualityComparer? comparer) { throw null; }
public static System.Linq.IQueryable Except(this System.Linq.IQueryable source1, System.Collections.Generic.IEnumerable source2) { throw null; }
public static System.Linq.IQueryable Except(this System.Linq.IQueryable source1, System.Collections.Generic.IEnumerable source2, System.Collections.Generic.IEqualityComparer? comparer) { throw null; }
public static TSource? FirstOrDefault(this System.Linq.IQueryable source) { throw null; }
- public static TSource FirstOrDefault(this System.Linq.IQueryable source, TSource defaultValue) { throw null; }
public static TSource? FirstOrDefault(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate) { throw null; }
public static TSource FirstOrDefault(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate, TSource defaultValue) { throw null; }
+ public static TSource FirstOrDefault(this System.Linq.IQueryable source, TSource defaultValue) { throw null; }
public static TSource First(this System.Linq.IQueryable source) { throw null; }
public static TSource First(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate) { throw null; }
public static System.Linq.IQueryable> GroupBy(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector) { throw null; }
@@ -101,21 +105,29 @@ public static partial class Queryable
public static System.Linq.IQueryable GroupBy(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector, System.Linq.Expressions.Expression> elementSelector, System.Linq.Expressions.Expression, TResult>> resultSelector, System.Collections.Generic.IEqualityComparer? comparer) { throw null; }
public static System.Linq.IQueryable GroupJoin(this System.Linq.IQueryable outer, System.Collections.Generic.IEnumerable inner, System.Linq.Expressions.Expression> outerKeySelector, System.Linq.Expressions.Expression> innerKeySelector, System.Linq.Expressions.Expression, TResult>> resultSelector) { throw null; }
public static System.Linq.IQueryable GroupJoin(this System.Linq.IQueryable outer, System.Collections.Generic.IEnumerable inner, System.Linq.Expressions.Expression> outerKeySelector, System.Linq.Expressions.Expression> innerKeySelector, System.Linq.Expressions.Expression, TResult>> resultSelector, System.Collections.Generic.IEqualityComparer? comparer) { throw null; }
+ public static System.Linq.IQueryable IntersectBy(this System.Linq.IQueryable source1, System.Collections.Generic.IEnumerable source2, System.Linq.Expressions.Expression> keySelector) { throw null; }
+ public static System.Linq.IQueryable IntersectBy(this System.Linq.IQueryable source1, System.Collections.Generic.IEnumerable source2, System.Linq.Expressions.Expression> keySelector, System.Collections.Generic.IEqualityComparer? comparer) { throw null; }
public static System.Linq.IQueryable Intersect(this System.Linq.IQueryable source1, System.Collections.Generic.IEnumerable source2) { throw null; }
public static System.Linq.IQueryable