Welcome to mirror list, hosted at ThFree Co, Russian Federation.

VirtualMethodHierarchyDataflowAnnotationValidation.cs « DataFlow « Mono.Linker.Tests.Cases « test - github.com/mono/linker.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 10b0695437eeda7841161d8d6b8efb8ca7704a88 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
// 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.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using Mono.Linker.Tests.Cases.Expectations.Assertions;
using Mono.Linker.Tests.Cases.Expectations.Metadata;

namespace Mono.Linker.Tests.Cases.DataFlow
{
	[SkipKeptItemsValidation]
	[SandboxDependency ("Dependencies/TestSystemTypeBase.cs")]

	// Suppress warnings about accessing methods with annotations via reflection - the test below does that a LOT
	// (The test accessed these methods through DynamicallyAccessedMembers annotations which is effectively the same reflection access)
	[UnconditionalSuppressMessage ("test", "IL2111")]

	[ExpectedNoWarnings]
	class VirtualMethodHierarchyDataflowAnnotationValidation
	{
		// The code below marks methods which have RUC on them, it's not the point of this test to validate these here
		[UnconditionalSuppressMessage ("test", "IL2026")]
		public static void Main ()
		{
			// The test uses data flow annotation to mark all public methods on the specified types
			// which in turn will trigger querying the annotations on those methods and thus the validation.

			RequirePublicMethods (typeof (BaseClass));
			RequirePublicMethods (typeof (DerivedClass));
			RequirePublicMethods (typeof (SuperDerivedClass));
			RequirePublicMethods (typeof (DerivedOverNoAnnotations));
			RequirePublicMethods (typeof (DerivedWithNoAnnotations));
			RequirePublicMethods (typeof (IBase));
			RequirePublicMethods (typeof (IDerived));
			RequirePublicMethods (typeof (ImplementationClass));
			RequirePublicMethods (typeof (IBaseImplementedInterface));
			RequirePublicMethods (typeof (BaseImplementsInterfaceViaDerived));
			RequirePublicMethods (typeof (DerivedWithInterfaceImplementedByBase));
			RequirePublicMethods (typeof (VirtualMethodHierarchyDataflowAnnotationValidationTypeTestBase));
			RequirePublicMethods (typeof (VirtualMethodHierarchyDataflowAnnotationValidationTypeTestDerived));
			RequirePublicMethods (typeof (ITwoInterfacesImplementedByOneMethod_One));
			RequirePublicMethods (typeof (ITwoInterfacesImplementedByOneMethod_Two));
			RequirePublicMethods (typeof (ImplementationOfTwoInterfacesWithOneMethod));
		}

		static void RequirePublicMethods ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type)
		{
		}

		class BaseClass
		{
			// === Return values ===
			// Other than the basics, the return value also checks all of the inheritance cases - we omit those for the other tests
			public virtual Type ReturnValueBaseWithoutDerivedWithout () => null;
			public virtual Type ReturnValueBaseWithoutDerivedWith () => null;
			[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
			public virtual Type ReturnValueBaseWithDerivedWithout () => null;
			[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
			public virtual Type ReturnValueBaseWithDerivedWith () => null;

			[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
			public virtual Type ReturnValueBaseWithSuperDerivedWithout () => null;

			// === Method parameters ===
			// This does not check complicated inheritance cases as that is already validated by the return values
			public virtual void SingleParameterBaseWithDerivedWithout (
				[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
				Type p)
			{ }

			public virtual void SingleParameterBaseWithDerivedWith_ (
				[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
				Type p)
			{ }

			public virtual void SingleParameterBaseWithoutDerivedWith_ (Type p) { }

			public virtual void SingleParameterBaseWithoutDerivedWithout (Type p) { }

			public virtual void SingleParameterBaseWithDerivedWithDifferent (
				[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
				Type p)
			{ }

			public virtual void MultipleParametersBaseWithDerivedWithout (
				[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
				Type p1BaseWithDerivedWithout,
				Type p2BaseWithoutDerivedWithout,
				[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
				Type p3BaseWithDerivedWithout)
			{ }

			public virtual void MultipleParametersBaseWithoutDerivedWith (
				Type p1BaseWithoutDerivedWith,
				Type p2BaseWithoutDerivedWithout,
				Type p3BaseWithoutDerivedWith)
			{ }

			public virtual void MultipleParametersBaseWithDerivedWithMatch (
				[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
				Type p1BaseWithDerivedWith,
				Type p2BaseWithoutDerivedWithout,
				[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)]
				Type p3BaseWithDerivedWith)
			{ }

			public virtual void MultipleParametersBaseWithDerivedWithMismatch (
				[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
				Type p1BaseWithDerivedWithMismatch,
				Type p2BaseWithoutDerivedWith,
				[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)]
				Type p3BaseWithDerivedWithMatch,
				Type p4NoAnnotations)
			{ }

			// === Generic methods ===
			public virtual void GenericBaseWithDerivedWithout<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)] T> () { }
			public virtual void GenericBaseWithoutDerivedWith<T> () { }
			public virtual void GenericBaseWithDerivedWith_<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)] T> () { }
			public virtual void GenericBaseWithoutDerivedWithout<T> () { }

			// === Properties ===
			[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
			public virtual Type PropertyBaseWithDerivedWithout { get; }
			[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
			public virtual Type PropertyBaseWithDerivedWith_ { get; set; }
			[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
			public virtual Type PropertyBaseWithDerivedOnGetterWith { get; }

			// === RequiresUnreferencedCode ===
			[RequiresUnreferencedCode ("")]
			public virtual void RequiresUnreferencedCodeBaseWithDerivedWithout () { }
			public virtual void RequiresUnreferencedCodeBaseWithoutDerivedWith_ () { }
			[RequiresUnreferencedCode ("")]
			public virtual void RequiresUnreferencedCodeBaseWithDerivedWith_ () { }
			public virtual void RequiresUnreferencedCodeBaseWithoutDerivedWithout () { }

			public virtual void RequiresUnreferencedCodeBaseWithoutSuperDerivedWith_ () { }
		}

		class DerivedClass : BaseClass
		{
			// === Return values ===
			[LogDoesNotContain ("DerivedClass.ReturnValueBaseWithoutDerivedWithout")]
			public override Type ReturnValueBaseWithoutDerivedWithout () => null;

			[ExpectedWarning ("IL2093", "BaseClass.ReturnValueBaseWithoutDerivedWith", "DerivedClass.ReturnValueBaseWithoutDerivedWith")]
			[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
			public override Type ReturnValueBaseWithoutDerivedWith () => null;

			[LogContains ("DerivedClass.ReturnValueBaseWithDerivedWithout")]
			public override Type ReturnValueBaseWithDerivedWithout () => null;

			[LogDoesNotContain ("DerivedClass.ReturnValueBaseWithDerivedWitht")]
			[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
			public override Type ReturnValueBaseWithDerivedWith () => null;


			// === Method parameters ===
			[ExpectedWarning ("IL2092",
				"p", "Mono.Linker.Tests.Cases.DataFlow.VirtualMethodHierarchyDataflowAnnotationValidation.DerivedClass.SingleParameterBaseWithDerivedWithout(Type)",
				"p", "Mono.Linker.Tests.Cases.DataFlow.VirtualMethodHierarchyDataflowAnnotationValidation.BaseClass.SingleParameterBaseWithDerivedWithout(Type)")]
			public override void SingleParameterBaseWithDerivedWithout (Type p) { }

			[LogDoesNotContain ("DerivedClass.SingleParameterBaseWithDerivedWith_")]
			public override void SingleParameterBaseWithDerivedWith_ (
				[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
				Type p)
			{ }

			[LogContains (
				"'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the parameter 'p' of method 'Mono.Linker.Tests.Cases.DataFlow.VirtualMethodHierarchyDataflowAnnotationValidation.DerivedClass.SingleParameterBaseWithoutDerivedWith_(Type)' " +
				"don't match overridden parameter 'p' of method 'Mono.Linker.Tests.Cases.DataFlow.VirtualMethodHierarchyDataflowAnnotationValidation.BaseClass.SingleParameterBaseWithoutDerivedWith_(Type)'. " +
				"All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage.")]
			public override void SingleParameterBaseWithoutDerivedWith_ (
				[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
				Type p)
			{ }

			[LogDoesNotContain ("DerivedClass.SingleParameterBaseWithoutDerivedWithout")]
			public override void SingleParameterBaseWithoutDerivedWithout (Type p) { }

			[LogContains (
				"'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the parameter 'p' of method 'Mono.Linker.Tests.Cases.DataFlow.VirtualMethodHierarchyDataflowAnnotationValidation.DerivedClass.SingleParameterBaseWithDerivedWithDifferent(Type)' " +
				"don't match overridden parameter 'p' of method 'Mono.Linker.Tests.Cases.DataFlow.VirtualMethodHierarchyDataflowAnnotationValidation.BaseClass.SingleParameterBaseWithDerivedWithDifferent(Type)'. " +
				"All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage.")]
			public override void SingleParameterBaseWithDerivedWithDifferent (
				[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)]
				Type p)
			{ }


			[LogContains (".*'p1BaseWithDerivedWithout'.*DerivedClass.*MultipleParametersBaseWithDerivedWithout.*", regexMatch: true)]
			[LogDoesNotContain (".*'p2BaseWithoutDerivedWithout'.*DerivedClass.*MultipleParametersBaseWithDerivedWithout.*", regexMatch: true)]
			[LogContains (".*'p3BaseWithDerivedWithout'.*DerivedClass.*MultipleParametersBaseWithDerivedWithout.*", regexMatch: true)]
			public override void MultipleParametersBaseWithDerivedWithout (
				Type p1BaseWithDerivedWithout,
				Type p2BaseWithoutDerivedWithout,
				Type p3BaseWithDerivedWithout)
			{ }

			[LogContains (".*'p1BaseWithoutDerivedWith'.*DerivedClass.*MultipleParametersBaseWithoutDerivedWith.*", regexMatch: true)]
			[LogDoesNotContain (".*'p2BaseWithoutDerivedWithout'.*DerivedClass.*MultipleParametersBaseWithoutDerivedWith.*", regexMatch: true)]
			[LogContains (".*'p3BaseWithoutDerivedWith'.*DerivedClass.*MultipleParametersBaseWithoutDerivedWith.*", regexMatch: true)]
			public override void MultipleParametersBaseWithoutDerivedWith (
				[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)]
				Type p1BaseWithoutDerivedWith,
				Type p2BaseWithoutDerivedWithout,
				[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)]
				Type p3BaseWithoutDerivedWith)
			{ }

			[LogDoesNotContain ("DerivedClass.MultipleParametersBaseWithDerivedWithMatch")]
			public override void MultipleParametersBaseWithDerivedWithMatch (
				[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
				Type p1BaseWithDerivedWith,
				Type p2BaseWithoutDerivedWithout,
				[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)]
				Type p3BaseWithDerivedWith)
			{ }

			[LogContains (".*'p1BaseWithDerivedWithMismatch'.*DerivedClass.*MultipleParametersBaseWithDerivedWithMismatch.*", regexMatch: true)]
			[LogContains (".*'p2BaseWithoutDerivedWith'.*DerivedClass.*MultipleParametersBaseWithDerivedWithMismatch.*", regexMatch: true)]
			[LogDoesNotContain (".*'p3BaseWithDerivedWithMatch'.*DerivedClass.*MultipleParametersBaseWithDerivedWithMismatch.*", regexMatch: true)]
			[LogDoesNotContain (".*'p4NoAnnotations'.*DerivedClass.*MultipleParametersBaseWithDerivedWithMismatch.*", regexMatch: true)]
			public override void MultipleParametersBaseWithDerivedWithMismatch (
				[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)]
				Type p1BaseWithDerivedWithMismatch,
				[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)]
				Type p2BaseWithoutDerivedWith,
				[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)]
				Type p3BaseWithDerivedWithMatch,
				Type p4NoAnnotations)
			{ }

			// === Generic methods ===
			[ExpectedWarning ("IL2095",
				"T", "Mono.Linker.Tests.Cases.DataFlow.VirtualMethodHierarchyDataflowAnnotationValidation.DerivedClass.GenericBaseWithDerivedWithout<T>()",
				"T", "Mono.Linker.Tests.Cases.DataFlow.VirtualMethodHierarchyDataflowAnnotationValidation.BaseClass.GenericBaseWithDerivedWithout<T>()")]
			public override void GenericBaseWithDerivedWithout<T> () { }

			[LogContains (
				"'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the generic parameter 'T' of 'Mono.Linker.Tests.Cases.DataFlow.VirtualMethodHierarchyDataflowAnnotationValidation.DerivedClass.GenericBaseWithoutDerivedWith<T>()' " +
				"don't match overridden generic parameter 'T' of 'Mono.Linker.Tests.Cases.DataFlow.VirtualMethodHierarchyDataflowAnnotationValidation.BaseClass.GenericBaseWithoutDerivedWith<T>()'. " +
				"All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage.")]
			public override void GenericBaseWithoutDerivedWith<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)]T> () { }

			[LogDoesNotContain ("DerivedClass.GenericBaseWithDerivedWith_")]
			public override void GenericBaseWithDerivedWith_<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)] T> () { }

			[LogDoesNotContain ("DerivedClass.GenericBaseWithoutDerivedWithout")]
			public override void GenericBaseWithoutDerivedWithout<T> () { }


			// === Properties ===
			// The warning is reported on the getter (or setter), which is not ideal, but it's probably good enough for now (we don't internally track annotations
			// on properties themselves, only on methods).
			[LogContains (
				"'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the return value of method 'Mono.Linker.Tests.Cases.DataFlow.VirtualMethodHierarchyDataflowAnnotationValidation.DerivedClass.PropertyBaseWithDerivedWithout.get' " +
				"don't match overridden return value of method 'Mono.Linker.Tests.Cases.DataFlow.VirtualMethodHierarchyDataflowAnnotationValidation.BaseClass.PropertyBaseWithDerivedWithout.get'. " +
				"All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage.")]
			public override Type PropertyBaseWithDerivedWithout { get; }

			[LogDoesNotContain ("DerivedClass.PropertyBaseWithDerivedWith_.get")]
			[LogDoesNotContain ("DerivedClass.PropertyBaseWithDerivedWith_.set")]
			[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
			public override Type PropertyBaseWithDerivedWith_ { get; set; }

			[LogDoesNotContain ("PropertyBaseWithDerivedOnGetterWith")]
			[field: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
			public override Type PropertyBaseWithDerivedOnGetterWith { [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] get; }


			// === RequiresUnreferencedCode ===
			[ExpectedWarning ("IL2046", "DerivedClass.RequiresUnreferencedCodeBaseWithDerivedWithout()",
				"BaseClass.RequiresUnreferencedCodeBaseWithDerivedWithout()",
				"'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides")]
			public override void RequiresUnreferencedCodeBaseWithDerivedWithout () { }
			[ExpectedWarning ("IL2046", "DerivedClass.RequiresUnreferencedCodeBaseWithoutDerivedWith_()",
				"BaseClass.RequiresUnreferencedCodeBaseWithoutDerivedWith_()",
				"'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides")]
			[RequiresUnreferencedCode ("")]
			public override void RequiresUnreferencedCodeBaseWithoutDerivedWith_ () { }
			[LogDoesNotContain ("DerivedClass.RequiresUnreferencedCodeBaseWithDerivedWith_")]
			[RequiresUnreferencedCode ("")]
			public override void RequiresUnreferencedCodeBaseWithDerivedWith_ () { }
			[LogDoesNotContain ("DerivedClass.RequiresUnreferencedCodeBaseWithoutDerivedWithout")]
			public override void RequiresUnreferencedCodeBaseWithoutDerivedWithout () { }
		}

		class InBetweenDerived : DerivedClass
		{
			// This is intentionally left empty to validate that the logic can skip over to deeper base classes correctly
		}

		class SuperDerivedClass : InBetweenDerived
		{
			// === Return values ===
			[LogContains (
				"'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the return value of method 'Mono.Linker.Tests.Cases.DataFlow.VirtualMethodHierarchyDataflowAnnotationValidation.SuperDerivedClass.ReturnValueBaseWithSuperDerivedWithout()' " +
				"don't match overridden return value of method 'Mono.Linker.Tests.Cases.DataFlow.VirtualMethodHierarchyDataflowAnnotationValidation.BaseClass.ReturnValueBaseWithSuperDerivedWithout()'. " +
				"All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage.")]
			public override Type ReturnValueBaseWithSuperDerivedWithout () => null;

			// === RequiresUnreferencedCode ===
			[LogContains ("SuperDerivedClass.RequiresUnreferencedCodeBaseWithoutSuperDerivedWith_")]
			[RequiresUnreferencedCode ("")]
			public override void RequiresUnreferencedCodeBaseWithoutSuperDerivedWith_ () { }
		}


		abstract class BaseWithNoAnnotations
		{
			// This class must not have ANY annotations anywhere on it.
			// It's here to test that the optimization works (as most classes won't have any annotations, so we shortcut that path).

			// === Return values ===
			public abstract Type ReturnValueBaseWithoutDerivedWith ();

			public abstract Type ReturnValueBaseWithoutDerivedWithout ();

			// === Method parameters ===
			public virtual void SingleParameterBaseWithoutDerivedWith_ (Type p) { }

			public virtual void SingleParameterBaseWithoutDerivedWithout (Type p) { }

			// === Generic methods ===
			public virtual void GenericBaseWithoutDerivedWith_<T> () { }

			public virtual void GenericBaseWithoutDerivedWithout<T> () { }

			// === RequiresUnreferencedCode ===
			public virtual void RequiresUnreferencedCodeBaseWithoutDerivedWith_ () { }
			public virtual void RequiresUnreferencedCodeBaseWithoutDerivedWithout () { }
		}

		class DerivedOverNoAnnotations : BaseWithNoAnnotations
		{
			// === Return values ===
			[LogContains ("DerivedOverNoAnnotations.ReturnValueBaseWithoutDerivedWith")]
			[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
			public override Type ReturnValueBaseWithoutDerivedWith () => null;

			[LogDoesNotContain ("DerivedOverNoAnnotations.ReturnValueBaseWithoutDerivedWithout")]
			public override Type ReturnValueBaseWithoutDerivedWithout () => null;

			// === Method parameters ===
			[LogContains ("DerivedOverNoAnnotations.SingleParameterBaseWithoutDerivedWith_")]
			public override void SingleParameterBaseWithoutDerivedWith_ (
				[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
				Type p)
			{ }

			[LogDoesNotContain ("DerivedOverNoAnnotations.SingleParameterBaseWithoutDerivedWithout")]
			public override void SingleParameterBaseWithoutDerivedWithout (Type p) { }

			// === Generic methods ===
			[LogContains ("DerivedOverNoAnnotations.GenericBaseWithoutDerivedWith_")]
			public override void GenericBaseWithoutDerivedWith_<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)] T> () { }

			[LogDoesNotContain ("DerivedOverNoAnnotations.GenericBaseWithoutDerivedWithout")]
			public override void GenericBaseWithoutDerivedWithout<T> () { }


			// === RequiresUnreferencedCode ===
			[LogContains ("DerivedOverNoAnnotations.RequiresUnreferencedCodeBaseWithoutDerivedWith_")]
			[RequiresUnreferencedCode ("")]
			public override void RequiresUnreferencedCodeBaseWithoutDerivedWith_ () { }
			[LogDoesNotContain ("DerivedOverNoAnnotations.RequiresUnreferencedCodeBaseWithoutDerivedWithout")]
			public override void RequiresUnreferencedCodeBaseWithoutDerivedWithout () { }
		}


		abstract class BaseWithAnnotations
		{
			// === Return values ===
			[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
			public abstract Type ReturnValueBaseWithDerivedWithout ();

			public abstract Type ReturnValueBaseWithoutDerivedWithout ();

			// === Method parameters ===
			public virtual void SingleParameterBaseWithDerivedWithout (
				[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
				Type p)
			{ }

			public virtual void SingleParameterBaseWithDerivedWith_ (
				[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
				Type p)
			{ }

			// === Generic methods ===
			public virtual void GenericBaseWithDerivedWithout<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)] T> () { }

			public virtual void GenericBaseWithoutDerivedWithout<T> () { }


			// === RequiresUnreferencedCode ===
			[RequiresUnreferencedCode ("")]
			public virtual void RequiresUnreferencedCodeBaseWithDerivedWith_ () { }
			[RequiresUnreferencedCode ("")]
			public virtual void RequiresUnreferencedCodeBaseWithDerivedWithout () { }
		}

		class DerivedWithNoAnnotations : BaseWithAnnotations
		{
			// This class must not have ANY annotations anywhere on it.
			// It's here to test that the optimization works (as most classes won't have any annotations, so we shortcut that path).

			// === Return values ===
			[LogContains ("DerivedWithNoAnnotations.ReturnValueBaseWithDerivedWithout")]
			public override Type ReturnValueBaseWithDerivedWithout () => null;

			[LogDoesNotContain ("DerivedWithNoAnnotations.ReturnValueBaseWithoutDerivedWithout")]
			public override Type ReturnValueBaseWithoutDerivedWithout () => null;

			// === Method parameters ===
			[LogContains ("DerivedWithNoAnnotations.SingleParameterBaseWithDerivedWithout")]
			public override void SingleParameterBaseWithDerivedWithout (Type p) { }

			[LogDoesNotContain ("DerivedWithNoAnnotations.SingleParameterBaseWithDerivedWith_")]
			public override void SingleParameterBaseWithDerivedWith_ (
				[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
				Type p)
			{ }

			// === Generic methods ===
			[LogContains ("DerivedWithNoAnnotations.GenericBaseWithDerivedWithout")]
			public override void GenericBaseWithDerivedWithout<T> () { }

			[LogDoesNotContain ("DerivedWithNoAnnotations.GenericBaseWithoutDerivedWithout")]
			public override void GenericBaseWithoutDerivedWithout<T> () { }


			// === RequiresUnreferencedCode ===
			[LogDoesNotContain ("DerivedWithNoAnnotations.RequiresUnreferencedCodeBaseWithDerivedWith_")]
			[RequiresUnreferencedCode ("")]
			public override void RequiresUnreferencedCodeBaseWithDerivedWith_ () { }
			[LogContains ("DerivedWithNoAnnotations.RequiresUnreferencedCodeBaseWithDerivedWithout")]
			public override void RequiresUnreferencedCodeBaseWithDerivedWithout () { }
		}


		interface IBase
		{
			// === Return values ===
			[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
			Type ReturnValueInterfaceBaseWithImplementationWithout ();

			Type ReturnValueInterfaceBaseWithoutImplementationWith_ ();

			[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
			Type ReturnValueInterfaceBaseWithImplementationWith_ ();


			// === Method parameters ===
			void SingleParameterBaseWithImplementationWith_ (
				[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
				Type p);

			void SingleParameterBaseWithoutImplementationWith_ (Type p);

			void SingleParameterBaseWithImplementationWithout (
				[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
				Type p);

			void SingleParameterBaseWithoutImplementationWithout (Type p);


			// === Generic methods ===
			void GenericInterfaceBaseWithoutImplementationWith_<T> ();

			void GenericInterfaceBaseWithImplementationWithout<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)] T> ();

			// === Properties ===
			Type PropertyInterfaceBaseWithoutImplementationWith { get; set; }


			// === RequiresUnreferencedCode ===
			[RequiresUnreferencedCode ("")]
			void RequiresUnreferencedCodeInterfaceBaseWithImplementationWith_ ();
			void RequiresUnreferencedCodeInterfaceBaseWithoutImplementationWith_ ();
		}

		interface IDerived : IBase
		{
			// === Return values ===
			[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
			Type ReturnTypeInterfaceDerivedWithImplementationWithout ();


			// === Method parameters ===
		}

		abstract class ImplementationClass : IDerived
		{
			// === Return values ===
			[LogContains ("ImplementationClass.ReturnValueInterfaceBaseWithImplementationWithout")]
			public Type ReturnValueInterfaceBaseWithImplementationWithout () => null;

			[LogContains ("ImplementationClass.ReturnValueInterfaceBaseWithoutImplementationWith_")]
			[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
			public Type ReturnValueInterfaceBaseWithoutImplementationWith_ () => null;

			[LogDoesNotContain ("ImplementationClass.ReturnValueInterfaceBaseWithImplementationWith_")]
			[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
			public Type ReturnValueInterfaceBaseWithImplementationWith_ () => null;

			[LogContains ("ImplementationClass.ReturnTypeInterfaceDerivedWithImplementationWithout")]
			public Type ReturnTypeInterfaceDerivedWithImplementationWithout () => null;


			// === Method parameters ===
			[LogDoesNotContain ("ImplementationClass.SingleParameterBaseWithImplementationWith_")]
			public void SingleParameterBaseWithImplementationWith_ (
				[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
				Type p)
			{ }

			[LogContains ("ImplementationClass.SingleParameterBaseWithImplementationWithout")]
			public void SingleParameterBaseWithImplementationWithout (Type p) { }

			[LogContains ("ImplementationClass.SingleParameterBaseWithoutImplementationWith_")]
			public void SingleParameterBaseWithoutImplementationWith_ (
				[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
				Type p)
			{ }

			[LogDoesNotContain ("ImplementationClass.SingleParameterBaseWithoutImplementationWithout")]
			public void SingleParameterBaseWithoutImplementationWithout (Type p) { }


			// === Generic methods ===
			[LogContains ("ImplementationClass.GenericInterfaceBaseWithoutImplementationWith_")]
			public void GenericInterfaceBaseWithoutImplementationWith_<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)] T> () { }

			[LogContains ("ImplementationClass.GenericInterfaceBaseWithImplementationWithout")]
			public void GenericInterfaceBaseWithImplementationWithout<T> () { }

			// === Properties ===
			[LogContains ("ImplementationClass.PropertyInterfaceBaseWithoutImplementationWith.get")]
			[LogContains ("ImplementationClass.PropertyInterfaceBaseWithoutImplementationWith.set")]
			[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
			public Type PropertyInterfaceBaseWithoutImplementationWith { get; set; }


			// === RequiresUnreferencedCode ===
			[LogDoesNotContain ("ImplementationClass.RequiresUnreferencedCodeInterfaceBaseWithImplementationWith_")]
			[RequiresUnreferencedCode ("")]
			public void RequiresUnreferencedCodeInterfaceBaseWithImplementationWith_ () { }
			[ExpectedWarning ("IL2046", "ImplementationClass.RequiresUnreferencedCodeInterfaceBaseWithoutImplementationWith_")]
			[RequiresUnreferencedCode ("")]
			public void RequiresUnreferencedCodeInterfaceBaseWithoutImplementationWith_ () { }
		}


		interface IBaseImplementedInterface
		{
			Type ReturnValueBaseWithInterfaceWithout ();

			[RequiresUnreferencedCode ("")]
			void RequiresUnreferencedCodeBaseWithoutInterfaceWith ();
		}

		class BaseImplementsInterfaceViaDerived
		{
			[LogContains (
				"'DynamicallyAccessedMemberTypes' in 'DynamicallyAccessedMembersAttribute' on the return value of method 'Mono.Linker.Tests.Cases.DataFlow.VirtualMethodHierarchyDataflowAnnotationValidation.BaseImplementsInterfaceViaDerived.ReturnValueBaseWithInterfaceWithout()' " +
				"don't match overridden return value of method 'Mono.Linker.Tests.Cases.DataFlow.VirtualMethodHierarchyDataflowAnnotationValidation.IBaseImplementedInterface.ReturnValueBaseWithInterfaceWithout()'. " +
				"All overridden members must have the same 'DynamicallyAccessedMembersAttribute' usage.")]
			[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
			public virtual Type ReturnValueBaseWithInterfaceWithout () => null;

			[ExpectedWarning ("IL2046", "BaseImplementsInterfaceViaDerived.RequiresUnreferencedCodeBaseWithoutInterfaceWith")]
			public virtual void RequiresUnreferencedCodeBaseWithoutInterfaceWith () { }
		}

		class DerivedWithInterfaceImplementedByBase : BaseImplementsInterfaceViaDerived, IBaseImplementedInterface
		{
		}


		interface ITwoInterfacesImplementedByOneMethod_One
		{
			Type ReturnValueInterfaceWithoutImplementationWith ();
		}

		interface ITwoInterfacesImplementedByOneMethod_Two
		{
			Type ReturnValueInterfaceWithoutImplementationWith ();
		}

		class ImplementationOfTwoInterfacesWithOneMethod : ITwoInterfacesImplementedByOneMethod_One, ITwoInterfacesImplementedByOneMethod_Two
		{
			[LogContains ("ITwoInterfacesImplementedByOneMethod_One.ReturnValueInterfaceWithoutImplementationWith")]
			[LogContains ("ITwoInterfacesImplementedByOneMethod_Two.ReturnValueInterfaceWithoutImplementationWith")]
			[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
			public virtual Type ReturnValueInterfaceWithoutImplementationWith () => null;
		}
	}
}

namespace System
{
	// This verifies correct validation of the "this" parameter annotations
	class VirtualMethodHierarchyDataflowAnnotationValidationTypeTestBase : TestSystemTypeBase
	{
		[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)]
		public virtual void ThisBaseWithDerivedWithout () { }
		[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)]
		public virtual void ThisBaseWithDerivedWith_ () { }
		public virtual void ThisBaseWithoutDerivedWith () { }
	}

	class VirtualMethodHierarchyDataflowAnnotationValidationTypeTestDerived : VirtualMethodHierarchyDataflowAnnotationValidationTypeTestBase
	{
		[ExpectedWarning ("IL2094",
			"System.VirtualMethodHierarchyDataflowAnnotationValidationTypeTestDerived.ThisBaseWithDerivedWithout()",
			"System.VirtualMethodHierarchyDataflowAnnotationValidationTypeTestBase.ThisBaseWithDerivedWithout()")]
		public override void ThisBaseWithDerivedWithout () { }

		[LogDoesNotContain ("VirtualMethodHierarchyDataflowAnnotationValidationTypeTestDerived.ThisBaseWithDerivedWith_")]
		[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)]
		public override void ThisBaseWithDerivedWith_ () { }

		[LogContains ("VirtualMethodHierarchyDataflowAnnotationValidationTypeTestDerived.ThisBaseWithoutDerivedWith")]
		[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)]
		public override void ThisBaseWithoutDerivedWith () { }
	}
}