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

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Arzt <arzt.samuel@live.de>2017-10-18 07:18:24 +0300
committerJan Kotas <jkotas@microsoft.com>2017-10-18 07:18:24 +0300
commit77022feb4c9c4a4c51ec2d4c72c7b036b8f1f918 (patch)
tree33217ba7a65bed9354e89209301db189edac12d4 /src/ILVerify
parent3523960fbcdd8ae85712a87a58ed4b38c0d08e10 (diff)
[ILVerify] Implement delegate creation checks (#4733)
* Implemented verification of delegate creation. * Added test cases for delegate creation pattern. * Implemented delegate compatibility check. * Added tests for delegate compatibility checks. * Added checks for call to non-final virtual methods. * Fixed using call on sealed type methods reporting this mismatch. * Added tests for this mismatch verification. * Added additional tests for modifying this pointer after base call.
Diffstat (limited to 'src/ILVerify')
-rw-r--r--src/ILVerify/src/ILImporter.StackValue.cs5
-rw-r--r--src/ILVerify/src/ILImporter.Verify.cs300
-rw-r--r--src/ILVerify/src/Resources/Strings.resx9
-rw-r--r--src/ILVerify/src/VerifierError.cs308
-rw-r--r--src/ILVerify/tests/ILTests/CallTests.il133
-rw-r--r--src/ILVerify/tests/ILTests/CastingTests.il2
-rw-r--r--src/ILVerify/tests/ILTests/FtnTests.il95
7 files changed, 649 insertions, 203 deletions
diff --git a/src/ILVerify/src/ILImporter.StackValue.cs b/src/ILVerify/src/ILImporter.StackValue.cs
index f7ce9e1bc..30f4c7f32 100644
--- a/src/ILVerify/src/ILImporter.StackValue.cs
+++ b/src/ILVerify/src/ILImporter.StackValue.cs
@@ -76,6 +76,11 @@ namespace Internal.IL
get { return Kind == StackValueKind.NativeInt && Method != null; }
}
+ public bool IsBoxedValueType
+ {
+ get { return Kind == StackValueKind.ObjRef && Type.IsValueType; }
+ }
+
public StackValue DereferenceByRef()
{
Debug.Assert(Kind == StackValueKind.ByRef && Type != null, "Cannot dereference");
diff --git a/src/ILVerify/src/ILImporter.Verify.cs b/src/ILVerify/src/ILImporter.Verify.cs
index c45ab1541..980f718c7 100644
--- a/src/ILVerify/src/ILImporter.Verify.cs
+++ b/src/ILVerify/src/ILImporter.Verify.cs
@@ -58,8 +58,11 @@ namespace Internal.IL
int _stackTop = 0;
bool _isThisInitialized;
+ bool _modifiesThisPtr;
bool _trackObjCtorState;
+ int? _delegateCreateStart;
+
class ExceptionRegion
{
public ILExceptionRegion ILRegion;
@@ -204,6 +207,7 @@ namespace Internal.IL
FindBasicBlocks();
FindEnclosingExceptionRegions();
+ FindThisPtrModification();
ImportBasicBlocks();
}
@@ -270,6 +274,137 @@ namespace Internal.IL
}
}
+ private void FindThisPtrModification()
+ {
+ _modifiesThisPtr = false;
+
+ if (_thisType == null)
+ return; // Early exit: no this pointer in this method
+
+ _currentOffset = 0;
+
+ while (_currentOffset < _ilBytes.Length)
+ {
+ ILOpcode opCode = (ILOpcode)ReadILByte();
+
+again:
+ switch (opCode)
+ {
+ case ILOpcode.starg_s:
+ case ILOpcode.ldarga_s:
+ if (ReadILByte() == 0)
+ {
+ _modifiesThisPtr = true;
+ return;
+ }
+ break;
+ case ILOpcode.starg:
+ case ILOpcode.ldarga:
+ if (ReadILUInt16() == 0)
+ {
+ _modifiesThisPtr = true;
+ return;
+ }
+ break;
+ // Skip all other Opcodes
+ case ILOpcode.ldarg_s:
+ case ILOpcode.ldloc_s:
+ case ILOpcode.ldloca_s:
+ case ILOpcode.stloc_s:
+ case ILOpcode.ldc_i4_s:
+ case ILOpcode.unaligned:
+ case ILOpcode.br_s:
+ case ILOpcode.leave_s:
+ case ILOpcode.brfalse_s:
+ case ILOpcode.brtrue_s:
+ case ILOpcode.beq_s:
+ case ILOpcode.bge_s:
+ case ILOpcode.bgt_s:
+ case ILOpcode.ble_s:
+ case ILOpcode.blt_s:
+ case ILOpcode.bne_un_s:
+ case ILOpcode.bge_un_s:
+ case ILOpcode.bgt_un_s:
+ case ILOpcode.ble_un_s:
+ case ILOpcode.blt_un_s:
+ SkipIL(1);
+ break;
+ case ILOpcode.ldarg:
+ case ILOpcode.ldloc:
+ case ILOpcode.ldloca:
+ case ILOpcode.stloc:
+ SkipIL(2);
+ break;
+ case ILOpcode.ldc_i4:
+ case ILOpcode.ldc_r4:
+ case ILOpcode.jmp:
+ case ILOpcode.call:
+ case ILOpcode.calli:
+ case ILOpcode.callvirt:
+ case ILOpcode.cpobj:
+ case ILOpcode.ldobj:
+ case ILOpcode.ldstr:
+ case ILOpcode.newobj:
+ case ILOpcode.castclass:
+ case ILOpcode.isinst:
+ case ILOpcode.unbox:
+ case ILOpcode.ldfld:
+ case ILOpcode.ldflda:
+ case ILOpcode.stfld:
+ case ILOpcode.ldsfld:
+ case ILOpcode.ldsflda:
+ case ILOpcode.stsfld:
+ case ILOpcode.stobj:
+ case ILOpcode.box:
+ case ILOpcode.newarr:
+ case ILOpcode.ldelema:
+ case ILOpcode.ldelem:
+ case ILOpcode.stelem:
+ case ILOpcode.unbox_any:
+ case ILOpcode.refanyval:
+ case ILOpcode.mkrefany:
+ case ILOpcode.ldtoken:
+ case ILOpcode.ldftn:
+ case ILOpcode.ldvirtftn:
+ case ILOpcode.initobj:
+ case ILOpcode.constrained:
+ case ILOpcode.sizeof_:
+ case ILOpcode.br:
+ case ILOpcode.leave:
+ case ILOpcode.brfalse:
+ case ILOpcode.brtrue:
+ case ILOpcode.beq:
+ case ILOpcode.bge:
+ case ILOpcode.bgt:
+ case ILOpcode.ble:
+ case ILOpcode.blt:
+ case ILOpcode.bne_un:
+ case ILOpcode.bge_un:
+ case ILOpcode.bgt_un:
+ case ILOpcode.ble_un:
+ case ILOpcode.blt_un:
+ SkipIL(4);
+ break;
+ case ILOpcode.ldc_i8:
+ case ILOpcode.ldc_r8:
+ SkipIL(8);
+ break;
+ case ILOpcode.prefix1:
+ opCode = (ILOpcode)(0x100 + ReadILByte());
+ goto again;
+ case ILOpcode.switch_:
+ {
+ uint count = ReadILUInt32();
+ for (uint i = 0; i < count; i++)
+ SkipIL(4);
+ }
+ break;
+ default:
+ continue;
+ }
+ }
+ }
+
void AbortBasicBlockVerification()
{
throw new LocalVerificationException();
@@ -635,6 +770,87 @@ namespace Internal.IL
}
}
+ void CheckDelegateCreation(StackValue ftn, StackValue obj)
+ {
+ if (!_delegateCreateStart.HasValue)
+ {
+ VerificationError(VerifierError.DelegatePattern);
+ return;
+ }
+
+ int delegateStart = _delegateCreateStart.Value;
+
+ if (_currentInstructionOffset - delegateStart == 6) // ldftn <tok> takes 6 bytes
+ {
+ if (GetOpcodeAt(delegateStart) != ILOpcode.ldftn)
+ {
+ VerificationError(VerifierError.DelegatePattern);
+ return;
+ }
+ else
+ {
+ // See "Rules for non-virtual call to a non-final virtual method" in ImportCall
+ var owningTypeDef = (MetadataType)ftn.Method.OwningType.GetTypeDefinition();
+
+ if (ftn.Method.IsVirtual && !(ftn.Method.IsFinal || owningTypeDef.IsSealed) && !obj.IsBoxedValueType)
+ Check(obj.IsThisPtr && !_modifiesThisPtr, VerifierError.LdftnNonFinalVirtual);
+ }
+ }
+ else if (_currentInstructionOffset - _delegateCreateStart == 7) // dup, ldvirtftn <tok> takes 7 bytes
+ {
+ if (GetOpcodeAt(delegateStart) != ILOpcode.dup ||
+ GetOpcodeAt(delegateStart + 1) != ILOpcode.ldvirtftn)
+ {
+ VerificationError(VerifierError.DelegatePattern);
+ return;
+ }
+ }
+ else
+ VerificationError(VerifierError.DelegatePattern);
+ }
+
+ void CheckIsDelegateAssignable(MethodDesc ftn, TypeDesc delegateType)
+ {
+ if (!IsDelegateAssignable(ftn, delegateType))
+ VerificationError(VerifierError.DelegateCtor);
+ }
+
+ bool IsDelegateAssignable(MethodDesc ftn, TypeDesc delegateType)
+ {
+ var invokeMethod = delegateType.GetMethod("Invoke", null);
+ if (invokeMethod == null)
+ return false;
+
+ var ftnSignature = ftn.Signature;
+ var delegateSignature = invokeMethod.Signature;
+
+ // Compare calling convention ignoring distinction between static and instance
+ if ((ftnSignature.Flags & ~MethodSignatureFlags.Static) != (delegateSignature.Flags & ~MethodSignatureFlags.Static))
+ return false;
+
+ // Compare signature parameters
+ if (ftnSignature.Length != delegateSignature.Length)
+ return false;
+
+ for (int i = 0; i < ftnSignature.Length; i++)
+ {
+ if (!IsAssignable(ftnSignature[i], delegateSignature[i]))
+ return false;
+ }
+
+ // Compare return type
+ return IsAssignable(delegateSignature.ReturnType, ftnSignature.ReturnType);
+ }
+
+ ILOpcode GetOpcodeAt(int instructionOffset)
+ {
+ var opCode = (ILOpcode)_ilBytes[instructionOffset];
+ if (opCode == ILOpcode.prefix1)
+ opCode = (ILOpcode)(0x100 + _ilBytes[instructionOffset + 1]);
+
+ return opCode;
+ }
+
void Unverifiable()
{
VerificationError(VerifierError.Unverifiable);
@@ -714,6 +930,7 @@ namespace Internal.IL
void StartImportingBasicBlock(BasicBlock basicBlock)
{
+ _delegateCreateStart = null;
_isThisInitialized = basicBlock.IsThisInitialized;
if (basicBlock.TryStart)
@@ -831,8 +1048,11 @@ namespace Internal.IL
CheckIsNotPointer(varType);
var stackValue = StackValue.CreateFromType(varType);
- if (index == 0 && argument)
+ if (index == 0 && argument && _thisType != null)
+ {
+ Debug.Assert(varType == _thisType);
stackValue.SetIsThisPtr();
+ }
Push(stackValue);
}
@@ -859,8 +1079,9 @@ namespace Internal.IL
Check(!varType.IsByRef, VerifierError.ByrefOfByref);
var stackValue = StackValue.CreateByRef(varType);
- if (index == 0 && argument)
+ if (index == 0 && argument && _thisType != null)
{
+ Debug.Assert(varType == _thisType);
stackValue.SetIsThisPtr();
Check(!_trackObjCtorState || _isThisInitialized, VerifierError.ThisUninitStore);
@@ -873,6 +1094,9 @@ namespace Internal.IL
{
var value = Pop(allowUninitThis: true);
+ // this could be the beginning of a delegate create
+ _delegateCreateStart = _currentInstructionOffset;
+
Push(value);
Push(value);
}
@@ -964,20 +1188,9 @@ namespace Internal.IL
CheckIsAssignable(actualObj, declaredObj);
Check(actualObj.Kind == StackValueKind.ObjRef, VerifierError.DelegateCtorSigO, actualObj);
-#if false
- Verify(verCheckDelegateCreation(opcode, vstate, codeAddr, delegateMethodRef,
- tiActualFtn, tiActualObj),
- MVER_E_DLGT_PATTERN);
-
- Verify(m_jitInfo->isCompatibleDelegate(objTypeHandle,
- parentTypeHandle,
- tiActualFtn.GetMethod(),
- methodClassHnd,
- getCurrentModuleHandle(),
- delegateMethodRef,
- memberRef),
- MVER_E_DLGT_CTOR);
-#endif
+ CheckDelegateCreation(actualFtn, actualObj);
+
+ CheckIsDelegateAssignable(actualFtn.Method, methodType);
}
else
{
@@ -1039,36 +1252,31 @@ namespace Internal.IL
}
CheckIsAssignable(actualThis, declaredThis);
-#if false
- // Rules for non-virtual call to a non-final virtual method:
-
- // Define:
- // The "this" pointer is considered to be "possibly written" if
- // 1. Its address have been taken (LDARGA 0) anywhere in the method.
- // (or)
- // 2. It has been stored to (STARG.0) anywhere in the method.
-
- // A non-virtual call to a non-final virtual method is only allowed if
- // 1. The this pointer passed to the callee is an instance of a boxed value type.
- // (or)
- // 2. The this pointer passed to the callee is the current method's this pointer.
- // (and) The current method's this pointer is not "possibly written".
-
- // Thus the rule is that if you assign to this ANYWHERE you can't make "base" calls to
- // virtual methods. (Luckily this does affect .ctors, since they are not virtual).
- // This is stronger that is strictly needed, but implementing a laxer rule is significantly
- // hard and more error prone.
-
- if (opcode == ReaderBaseNS::CEE_CALL
- && (mflags & CORINFO_FLG_VIRTUAL)
- && ((mflags & CORINFO_FLG_FINAL) == 0)
- && (!verIsBoxedValueType(tiThis)))
+ if (opcode == ILOpcode.call)
{
- // always enforce for peverify
- Verify(tiThis.IsThisPtr() && !thisPossiblyModified,
- MVER_E_THIS_MISMATCH);
+ // Rules for non-virtual call to a non-final virtual method (ECMA III.3.19: Verifiability of 'call'):
+
+ // Define:
+ // The "this" pointer is considered to be "possibly written" if
+ // 1. Its address have been taken (LDARGA 0) anywhere in the method.
+ // (or)
+ // 2. It has been stored to (STARG.0) anywhere in the method.
+
+ // A non-virtual call to a non-final virtual method is only allowed if
+ // 1. The this pointer passed to the callee is an instance of a boxed value type.
+ // (or)
+ // 2. The this pointer passed to the callee is the current method's this pointer.
+ // (and) The current method's this pointer is not "possibly written".
+
+ // Thus the rule is that if you assign to this ANYWHERE you can't make "base" calls to
+ // virtual methods. (Luckily this does not affect .ctors, since they are not virtual).
+ // This is stronger than is strictly needed, but implementing a laxer rule is significantly
+ // harder and more error prone.
+ var methodTypeDef = (MetadataType)methodType.GetTypeDefinition(); // Method is always considered final if owning type is sealed
+
+ if (method.IsVirtual && !(method.IsFinal || methodTypeDef.IsSealed) && !actualThis.IsBoxedValueType)
+ Check(actualThis.IsThisPtr && !_modifiesThisPtr, VerifierError.ThisMismatch);
}
-#endif
if (tailCall)
{
@@ -1169,9 +1377,7 @@ namespace Internal.IL
if (opCode == ILOpcode.ldftn)
{
-#if false
- vstate->delegateCreateStart = codeAddr;
-#endif
+ _delegateCreateStart = _currentInstructionOffset;
}
else if (opCode == ILOpcode.ldvirtftn)
{
diff --git a/src/ILVerify/src/Resources/Strings.resx b/src/ILVerify/src/Resources/Strings.resx
index 065e2e5a1..868a917fb 100644
--- a/src/ILVerify/src/Resources/Strings.resx
+++ b/src/ILVerify/src/Resources/Strings.resx
@@ -168,6 +168,9 @@
<data name="DelegateCtorSigO" xml:space="preserve">
<value>Unrecognized delegate .ctor signature; expected Object.</value>
</data>
+ <data name="DelegatePattern" xml:space="preserve">
+ <value>Dup, ldvirtftn, newobj delegate::.ctor() pattern expected (in the same basic block).</value>
+ </data>
<data name="Endfilter" xml:space="preserve">
<value>Endfilter from outside an exception filter block.</value>
</data>
@@ -210,6 +213,9 @@
<data name="LdftnConstructor" xml:space="preserve">
<value>ldftn/ldvirtftn not allowed on .ctor.</value>
</data>
+ <data name="LdftnNonFinalVirtual" xml:space="preserve">
+ <value>Cannot LDFTN a non-final virtual method for delegate creation if target object is potentially not the same type as the method class.</value>
+ </data>
<data name="LdvirtftnOnStatic" xml:space="preserve">
<value>ldvirtftn on static.</value>
</data>
@@ -285,6 +291,9 @@
<data name="TailRetVoid" xml:space="preserve">
<value>Void ret type expected for tail call.</value>
</data>
+ <data name="ThisMismatch" xml:space="preserve">
+ <value>The 'this' parameter to the call must be the calling method's 'this' parameter.</value>
+ </data>
<data name="ThisUninitReturn" xml:space="preserve">
<value>Return from .ctor when this is uninitialized.</value>
</data>
diff --git a/src/ILVerify/src/VerifierError.cs b/src/ILVerify/src/VerifierError.cs
index 0c599c5f5..33862ef92 100644
--- a/src/ILVerify/src/VerifierError.cs
+++ b/src/ILVerify/src/VerifierError.cs
@@ -36,187 +36,187 @@ namespace ILVerify
//E_STACK_TOO_LARGE "Stack is too large."
//E_ARRAY_NAME_LONG "Array name is too long."
- //E_FALLTHRU "fall through end of the method without returning."
- //E_TRY_GTEQ_END "try start >= try end."
- //E_TRYEND_GT_CS "try end > code size."
- //E_HND_GTEQ_END "handler start >= handler end."
- //E_HNDEND_GT_CS "handler end > code size."
- //E_TRY_START "Try starts in the middle of an instruction."
- //E_HND_START "Handler starts in the middle of an instruction."
- //E_TRY_OVERLAP "Try block overlap with another block."
- //E_TRY_EQ_HND_FIL "Try and filter/handler blocks are equivalent."
- //E_TRY_SHARE_FIN_FAL "Shared try has finally or fault handler."
- //E_HND_OVERLAP "Handler block overlaps with another block."
- //E_HND_EQ "Handler block is the same as another block."
- //E_FIL_OVERLAP "Filter block overlaps with another block."
- //E_FIL_EQ "Filter block is the same as another block."
- //E_FIL_CONT_TRY "Filter contains try."
- //E_FIL_CONT_HND "Filter contains handler."
- //E_FIL_CONT_FIL "Nested filters."
- //E_FIL_GTEQ_CS "filter >= code size."
- //E_FIL_START "Filter starts in the middle of an instruction."
- //E_FALLTHRU_EXCEP "fallthru the end of an exception block."
- //E_FALLTHRU_INTO_HND "fallthru into an exception handler."
- //E_FALLTHRU_INTO_FIL "fallthru into an exception filter."
- //E_LEAVE "Leave from outside a try or catch block."
- Rethrow, //"Rethrow from outside a catch handler."
- Endfinally, //"Endfinally from outside a finally handler."
- Endfilter, //"Endfilter from outside an exception filter block."
- //E_ENDFILTER_MISSING "Missing Endfilter."
- BranchIntoTry, //"Branch into try block."
- BranchIntoHandler, //"Branch into exception handler block."
- BranchIntoFilter, //"Branch into exception filter block."
- BranchOutOfTry, //"Branch out of try block."
- BranchOutOfHandler, //"Branch out of exception handler block."
- BranchOutOfFilter, //"Branch out of exception filter block."
- //E_BR_OUTOF_FIN "Branch out of finally block."
- ReturnFromTry, //"Return out of try block."
- ReturnFromHandler, //"Return out of exception handler block."
- ReturnFromFilter, //"Return out of exception filter block."
- //E_BAD_JMP_TARGET "jmp / exception into the middle of an instruction."
- //E_PATH_LOC "Non-compatible types depending on path."
- //E_PATH_THIS "Init state for this differs depending on path."
- PathStackUnexpected, //"Non-compatible types on stack depending on path."
- PathStackDepth, //"Stack depth differs depending on path."
- //E_THIS "Instance variable (this) missing."
- //E_THIS_UNINIT_EXCEP "Uninitialized this on entering a try block."
- ThisUninitStore, // Store into this when it is uninitialized.
- ThisUninitReturn, // Return from .ctor when this is uninitialized.
- //E_THIS_UNINIT_V_RET "Return from .ctor before all fields are initialized."
- //E_THIS_UNINIT_BR "Branch back when this is uninitialized."
- LdftnCtor, //"ldftn/ldvirtftn not allowed on .ctor."
- //StackNotEq, // "Non-compatible types on the stack."
+ //E_FALLTHRU "fall through end of the method without returning."
+ //E_TRY_GTEQ_END "try start >= try end."
+ //E_TRYEND_GT_CS "try end > code size."
+ //E_HND_GTEQ_END "handler start >= handler end."
+ //E_HNDEND_GT_CS "handler end > code size."
+ //E_TRY_START "Try starts in the middle of an instruction."
+ //E_HND_START "Handler starts in the middle of an instruction."
+ //E_TRY_OVERLAP "Try block overlap with another block."
+ //E_TRY_EQ_HND_FIL "Try and filter/handler blocks are equivalent."
+ //E_TRY_SHARE_FIN_FAL "Shared try has finally or fault handler."
+ //E_HND_OVERLAP "Handler block overlaps with another block."
+ //E_HND_EQ "Handler block is the same as another block."
+ //E_FIL_OVERLAP "Filter block overlaps with another block."
+ //E_FIL_EQ "Filter block is the same as another block."
+ //E_FIL_CONT_TRY "Filter contains try."
+ //E_FIL_CONT_HND "Filter contains handler."
+ //E_FIL_CONT_FIL "Nested filters."
+ //E_FIL_GTEQ_CS "filter >= code size."
+ //E_FIL_START "Filter starts in the middle of an instruction."
+ //E_FALLTHRU_EXCEP "fallthru the end of an exception block."
+ //E_FALLTHRU_INTO_HND "fallthru into an exception handler."
+ //E_FALLTHRU_INTO_FIL "fallthru into an exception filter."
+ //E_LEAVE "Leave from outside a try or catch block."
+ Rethrow, // Rethrow from outside a catch handler.
+ Endfinally, // Endfinally from outside a finally handler.
+ Endfilter, // Endfilter from outside an exception filter block.
+ //E_ENDFILTER_MISSING "Missing Endfilter."
+ BranchIntoTry, // Branch into try block.
+ BranchIntoHandler, // Branch into exception handler block.
+ BranchIntoFilter, // Branch into exception filter block.
+ BranchOutOfTry, // Branch out of try block.
+ BranchOutOfHandler, // Branch out of exception handler block.
+ BranchOutOfFilter, // Branch out of exception filter block.
+ //E_BR_OUTOF_FIN "Branch out of finally block."
+ ReturnFromTry, // Return out of try block.
+ ReturnFromHandler, // Return out of exception handler block.
+ ReturnFromFilter, // Return out of exception filter block.
+ //E_BAD_JMP_TARGET "jmp / exception into the middle of an instruction."
+ //E_PATH_LOC "Non-compatible types depending on path."
+ //E_PATH_THIS "Init state for this differs depending on path."
+ PathStackUnexpected, // Non-compatible types on stack depending on path.
+ PathStackDepth, // Stack depth differs depending on path.
+ //E_THIS "Instance variable (this) missing."
+ //E_THIS_UNINIT_EXCEP "Uninitialized this on entering a try block."
+ ThisUninitStore, // Store into this when it is uninitialized.
+ ThisUninitReturn, // Return from .ctor when this is uninitialized.
+ //E_THIS_UNINIT_V_RET "Return from .ctor before all fields are initialized."
+ //E_THIS_UNINIT_BR "Branch back when this is uninitialized."
+ LdftnCtor, // ldftn/ldvirtftn not allowed on .ctor.
+ //StackNotEq, // Non-compatible types on the stack.
StackUnexpected, // Unexpected type on the stack.
StackUnexpectedArrayType, // Unexpected array type on the stack.
- //E_STACK_EXCEPTION "Missing stack slot for exception."
+ //E_STACK_EXCEPTION "Missing stack slot for exception."
StackOverflow, // Stack overflow.
StackUnderflow, // Stack underflow.
- //E_STACK_EMPTY "Stack empty."
+ //E_STACK_EMPTY "Stack empty."
UninitStack, // Uninitialized item on stack.
ExpectedIntegerType, // Expected I, I4, or I8 on the stack.
ExpectedFloatType, // Expected R, R4, or R8 on the stack.
- //E_STACK_NO_R_I8 "unexpected R, R4, R8, or I8 on the stack."
+ //E_STACK_NO_R_I8 "unexpected R, R4, R8, or I8 on the stack."
ExpectedNumericType, // Expected numeric type on the stack.
- StackObjRef, // "Expected an ObjRef on the stack."
- //E_STACK_P_OBJREF "Expected address of an ObjRef on the stack."
+ StackObjRef, // Expected an ObjRef on the stack.
+ //E_STACK_P_OBJREF "Expected address of an ObjRef on the stack."
StackByRef, // Expected ByRef on the stack.
- StackMethod, // Expected pointer to function on the stack.
- //E_STACK_ARRAY_SD "Expected single dimension array on the stack."
- //E_STACK_VALCLASS "Expected value type instance on the stack."
- //E_STACK_P_VALCLASS "Expected address of value type on the stack."
- //E_STACK_NO_VALCLASS "Unexpected value type instance on the stack."
- //E_LOC_DEAD "Local variable is unusable at this point."
+ StackMethod, // Expected pointer to function on the stack.
+ //E_STACK_ARRAY_SD "Expected single dimension array on the stack."
+ //E_STACK_VALCLASS "Expected value type instance on the stack."
+ //E_STACK_P_VALCLASS "Expected address of value type on the stack."
+ //E_STACK_NO_VALCLASS "Unexpected value type instance on the stack."
+ //E_LOC_DEAD "Local variable is unusable at this point."
UnrecognizedLocalNumber, // Unrecognized local variable number.
UnrecognizedArgumentNumber, // Unrecognized argument number.
ExpectedTypeToken, // Expected type token.
TokenResolve, // Unable to resolve token.
- //E_TOKEN_TYPE "Unable to resolve type of the token."
+ //E_TOKEN_TYPE "Unable to resolve type of the token."
ExpectedMethodToken, // Expected memberRef, memberDef or methodSpec token.
- //E_TOKEN_TYPE_FIELD "Expected memberRef or fieldDef token."
- //E_TOKEN_TYPE_SIG "Expected signature token."
+ //E_TOKEN_TYPE_FIELD "Expected memberRef or fieldDef token."
+ //E_TOKEN_TYPE_SIG "Expected signature token."
ExpectedFieldToken, // Expected field token.
- // E_TOKEN_TYPE_SIG "Expected signature token."
+ //E_TOKEN_TYPE_SIG "Expected signature token."
Unverifiable, // Instruction can not be verified.
StringOperand, // Operand does not point to a valid string ref.
ReturnPtrToStack, // Return type is ByRef, TypedReference, ArgHandle, or ArgIterator.
ReturnVoid, // Stack must be empty on return from a void function.
ReturnMissing, // Return value missing on the stack.
ReturnEmpty, // Stack must contain only the return value.
- //E_RET_UNINIT "Return uninitialized data."
- //E_ARRAY_ACCESS "Illegal array access."
- //E_ARRAY_V_STORE "Store non Object type into Object array."
+ //E_RET_UNINIT "Return uninitialized data."
+ //E_ARRAY_ACCESS "Illegal array access."
+ //E_ARRAY_V_STORE "Store non Object type into Object array."
ExpectedArray, // Expected single-dimension zero-based array.
- //E_ARRAY_SD_PTR "Expected single dimension array of pointer types."
- //E_ARRAY_FIELD "Array field access is denied."
- //E_ARGLIST "Allowed only in vararg methods."
+ //E_ARRAY_SD_PTR "Expected single dimension array of pointer types."
+ //E_ARRAY_FIELD "Array field access is denied."
+ //E_ARGLIST "Allowed only in vararg methods."
ValueTypeExpected, // Value type expected.
- //E_OPEN_DLGT_PROT_ACC "Protected method access through an open instance delegate is not verifiable."
- //E_METHOD_ACCESS "Method is not visible."
- //E_FIELD_ACCESS "Field is not visible."
- //E_DEAD "Item is unusable at this point."
+ //E_OPEN_DLGT_PROT_ACC "Protected method access through an open instance delegate is not verifiable."
+ //E_METHOD_ACCESS "Method is not visible."
+ //E_FIELD_ACCESS "Field is not visible."
+ //E_DEAD "Item is unusable at this point."
ExpectedStaticField, // Expected static field.
- //E_FIELD_NO_STATIC "Expected non-static field."
- //E_ADDR "Address of not allowed for this item."
- //E_ADDR_BYREF "Address of not allowed for ByRef."
- //E_ADDR_LITERAL "Address of not allowed for literal field."
- //E_INITONLY "Cannot change initonly field outside its .ctor."
- //E_WRITE_RVA_STATIC "Cannot modify an imaged based (RVA) static"
- //E_THROW "Cannot throw this object."
- CallVirtOnValueType, // Callvirt on a value type method.
- //E_CALL_SIG "Call signature mismatch."
- //E_CALL_STATIC "Static function expected."
- //E_CTOR ".ctor expected."
- //E_CTOR_VIRT "Cannot use callvirt on .ctor."
- //E_CTOR_OR_SUPER "Only super::ctor or typeof(this)::ctor allowed here."
- //E_CTOR_MUL_INIT "Possible call to .ctor more than once."
- //E_SIG "Unrecognized signature."
- //E_SIG_ARRAY "Cannot resolve Array type."
- //E_SIG_ARRAY_PTR "Array of ELEMENT_TYPE_PTR."
+ //E_FIELD_NO_STATIC "Expected non-static field."
+ //E_ADDR "Address of not allowed for this item."
+ //E_ADDR_BYREF "Address of not allowed for ByRef."
+ //E_ADDR_LITERAL "Address of not allowed for literal field."
+ //E_INITONLY "Cannot change initonly field outside its .ctor."
+ //E_WRITE_RVA_STATIC "Cannot modify an imaged based (RVA) static"
+ //E_THROW "Cannot throw this object."
+ CallVirtOnValueType, // Callvirt on a value type method.
+ //E_CALL_SIG "Call signature mismatch."
+ //E_CALL_STATIC "Static function expected."
+ //E_CTOR ".ctor expected."
+ //E_CTOR_VIRT "Cannot use callvirt on .ctor."
+ //E_CTOR_OR_SUPER "Only super::ctor or typeof(this)::ctor allowed here."
+ //E_CTOR_MUL_INIT "Possible call to .ctor more than once."
+ //E_SIG "Unrecognized signature."
+ //E_SIG_ARRAY "Cannot resolve Array type."
+ //E_SIG_ARRAY_PTR "Array of ELEMENT_TYPE_PTR."
ArrayByRef, // Array of ELEMENT_TYPE_BYREF or ELEMENT_TYPE_TYPEDBYREF.
- //E_SIG_ELEM_PTR "ELEMENT_TYPE_PTR cannot be verified."
- //E_SIG_VARARG "Unexpected vararg."
- //E_SIG_VOID "Unexpected Void."
+ //E_SIG_ELEM_PTR "ELEMENT_TYPE_PTR cannot be verified."
+ //E_SIG_VARARG "Unexpected vararg."
+ //E_SIG_VOID "Unexpected Void."
ByrefOfByref, // ByRef of ByRef.
- //E_CODE_SIZE_ZERO "Code size is zero."
- //E_BAD_VARARG "Unrecognized use of vararg."
+ //E_CODE_SIZE_ZERO "Code size is zero."
+ //E_BAD_VARARG "Unrecognized use of vararg."
TailCall, // Missing call/callvirt/calli.
TailByRef, // Cannot pass ByRef to a tail call.
- //E_TAIL_RET "Missing ret."
+ //E_TAIL_RET "Missing ret."
TailRetVoid, // Void ret type expected for tail call.
- //E_TAIL_RET_TYPE "Tail call return type not compatible."
+ //E_TAIL_RET_TYPE "Tail call return type not compatible."
TailStackEmpty, // Stack not empty after tail call.
- //E_METHOD_END "Method ends in the middle of an instruction."
- //E_BAD_BRANCH "Branch out of the method."
- //E_FIN_OVERLAP "Finally handler blocks overlap."
- //E_LEXICAL_NESTING "Lexical nesting."
+ //E_METHOD_END "Method ends in the middle of an instruction."
+ //E_BAD_BRANCH "Branch out of the method."
+ //E_FIN_OVERLAP "Finally handler blocks overlap."
+ //E_LEXICAL_NESTING "Lexical nesting."
Volatile, // Missing ldsfld, stsfld, ldind, stind, ldfld, stfld, ldobj, stobj, initblk, or cpblk.
Unaligned, // Missing ldind, stind, ldfld, stfld, ldobj, stobj, initblk, cpblk.
- //E_INNERMOST_FIRST "Innermost exception blocks should be declared first."
- //E_CALLI_VIRTUAL "Calli not allowed on virtual methods."
- CallAbstract, // Call not allowed on abstract methods.
- //E_NOT_IN_GC_HEAP "Value type with NotInGCHeap attribute being created on the GC heap."
- TryNonEmptyStack, // Attempt to enter a try block with nonempty stack.
- DelegateCtor, // Unrecognized arguments for delegate .ctor.
- //E_DLGT_BB "Delegate .ctor not allowed at the start of a basic block when the function pointer argument is a virtual method."
- //E_DLGT_PATTERN "Dup, ldvirtftn, newobj delegate::.ctor() pattern expected (in the same basic block)."
- //E_DLGT_LDFTN "Ldftn or ldvirtftn instruction required before call to a delegate .ctor."
- //E_FTN_ABSTRACT "Attempt to load address of an abstract method."
- //E_SIG_C_VC "ELEMENT_TYPE_CLASS ValueClass in signature."
- //E_SIG_VC_C "ELEMENT_TYPE_VALUETYPE non-ValueClass in signature."
- //E_BOX_PTR_TO_STACK "Box operation on TypedReference, ArgHandle, or ArgIterator."
- //E_SIG_BYREF_TB_AH "ByRef of TypedReference, ArgHandle, or ArgIterator."
- //E_SIG_ARRAY_TB_AH "Array of TypedReference, ArgHandle, or ArgIterator."
- EndfilterStack, //"Stack not empty when leaving an exception filter."
- DelegateCtorSigI, // Unrecognized delegate .ctor signature; expected Native Int.
- DelegateCtorSigO, // Unrecognized delegate .ctor signature; expected Object.
- //E_RA_PTR_TO_STACK "Mkrefany on TypedReference, ArgHandle, or ArgIterator."
- //E_CATCH_VALUE_TYPE "Value type not allowed as catch type."
- //E_CATCH_BYREF "ByRef not allowed as catch type."
- //E_FIL_PRECEED_HND "filter block should immediately precede handler block"
- LdvirtftnOnStatic, // ldvirtftn on static.
- CallVirtOnStatic, // callvirt on static.
- InitLocals, // initlocals must be set for verifiable methods with one or more local variables.
- //E_BR_TO_EXCEPTION "branch/leave to the beginning of a catch/filter handler"
- CallCtor, // call to .ctor only allowed to initialize this pointer from within a .ctor. Try newobj.
-
+ //E_INNERMOST_FIRST "Innermost exception blocks should be declared first."
+ //E_CALLI_VIRTUAL "Calli not allowed on virtual methods."
+ CallAbstract, // Call not allowed on abstract methods.
+ //E_NOT_IN_GC_HEAP "Value type with NotInGCHeap attribute being created on the GC heap."
+ TryNonEmptyStack, // Attempt to enter a try block with nonempty stack.
+ DelegateCtor, // Unrecognized arguments for delegate .ctor.
+ //E_DLGT_BB "Delegate .ctor not allowed at the start of a basic block when the function pointer argument is a virtual method."
+ DelegatePattern, // Dup, ldvirtftn, newobj delegate::.ctor() pattern expected (in the same basic block).
+ //E_DLGT_LDFTN "Ldftn or ldvirtftn instruction required before call to a delegate .ctor."
+ //E_FTN_ABSTRACT "Attempt to load address of an abstract method."
+ //E_SIG_C_VC "ELEMENT_TYPE_CLASS ValueClass in signature."
+ //E_SIG_VC_C "ELEMENT_TYPE_VALUETYPE non-ValueClass in signature."
+ //E_BOX_PTR_TO_STACK "Box operation on TypedReference, ArgHandle, or ArgIterator."
+ //E_SIG_BYREF_TB_AH "ByRef of TypedReference, ArgHandle, or ArgIterator."
+ //E_SIG_ARRAY_TB_AH "Array of TypedReference, ArgHandle, or ArgIterator."
+ EndfilterStack, // Stack not empty when leaving an exception filter.
+ DelegateCtorSigI, // Unrecognized delegate .ctor signature; expected Native Int.
+ DelegateCtorSigO, // Unrecognized delegate .ctor signature; expected Object.
+ //E_RA_PTR_TO_STACK "Mkrefany on TypedReference, ArgHandle, or ArgIterator."
+ //E_CATCH_VALUE_TYPE "Value type not allowed as catch type."
+ //E_CATCH_BYREF "ByRef not allowed as catch type."
+ //E_FIL_PRECEED_HND "filter block should immediately precede handler block"
+ LdvirtftnOnStatic, // ldvirtftn on static.
+ CallVirtOnStatic, // callvirt on static.
+ InitLocals, // initlocals must be set for verifiable methods with one or more local variables.
+ //E_BR_TO_EXCEPTION "branch/leave to the beginning of a catch/filter handler"
+ CallCtor, // call to .ctor only allowed to initialize this pointer from within a .ctor. Try newobj.
+
////@GENERICSVER: new generics related error messages
ExpectedValClassObjRefVariable, // Value type, ObjRef type or variable type expected.
- //E_STACK_P_VALCLASS_OBJREF_VAR "Expected address of value type, ObjRef type or variable type on the stack."
- //E_SIG_VAR_PARAM "Unrecognized type parameter of enclosing class."
- //E_SIG_MVAR_PARAM "Unrecognized type parameter of enclosing method."
- //E_SIG_VAR_ARG "Unrecognized type argument of referenced class instantiation."
- //E_SIG_MVAR_ARG "Unrecognized type argument of referenced method instantiation."
- //E_SIG_GENERICINST "Cannot resolve generic type."
- //E_SIG_METHOD_INST "Method instantiation contains non boxable type arguments."
- //E_SIG_METHOD_PARENT_INST "Method parent instantiation contains non boxable type arguments."
- //E_SIG_FIELD_PARENT_INST "Field parent instantiation contains non boxable type arguments."
- //E_CALLCONV_NOT_GENERICINST "Unrecognized calling convention for an instantiated generic method."
- //E_TOKEN_BAD_METHOD_SPEC "Unrecognized generic method in method instantiation."
+ //E_STACK_P_VALCLASS_OBJREF_VAR "Expected address of value type, ObjRef type or variable type on the stack."
+ //E_SIG_VAR_PARAM "Unrecognized type parameter of enclosing class."
+ //E_SIG_MVAR_PARAM "Unrecognized type parameter of enclosing method."
+ //E_SIG_VAR_ARG "Unrecognized type argument of referenced class instantiation."
+ //E_SIG_MVAR_ARG "Unrecognized type argument of referenced method instantiation."
+ //E_SIG_GENERICINST "Cannot resolve generic type."
+ //E_SIG_METHOD_INST "Method instantiation contains non boxable type arguments."
+ //E_SIG_METHOD_PARENT_INST "Method parent instantiation contains non boxable type arguments."
+ //E_SIG_FIELD_PARENT_INST "Field parent instantiation contains non boxable type arguments."
+ //E_CALLCONV_NOT_GENERICINST "Unrecognized calling convention for an instantiated generic method."
+ //E_TOKEN_BAD_METHOD_SPEC "Unrecognized generic method in method instantiation."
ReadOnly, // Missing ldelema or call following readonly prefix.
Constrained, // Missing callvirt following constrained prefix.
- //E_CIRCULAR_VAR_CONSTRAINTS "Method parent has circular class type parameter constraints."
- //E_CIRCULAR_MVAR_CONSTRAINTS "Method has circular method type parameter constraints."
+ //E_CIRCULAR_VAR_CONSTRAINTS "Method parent has circular class type parameter constraints."
+ //E_CIRCULAR_MVAR_CONSTRAINTS "Method has circular method type parameter constraints."
UnsatisfiedMethodInst, // Method instantiation has unsatisfied method type parameter constraints.
UnsatisfiedMethodParentInst, // Method parent instantiation has unsatisfied class type parameter constraints.
@@ -225,18 +225,18 @@ namespace ILVerify
ConstrainedCallWithNonByRefThis, // The 'this' argument to a constrained call must have ByRef type.
//E_CONSTRAINED_OF_NON_VARIABLE_TYPE "The operand to a constrained prefix instruction must be a type parameter."
//E_READONLY_UNEXPECTED_CALLEE "The readonly prefix may only be applied to calls to array methods returning ByRefs."
- ReadOnlyIllegalWrite, // "Illegal write to readonly ByRef."
+ ReadOnlyIllegalWrite, // Illegal write to readonly ByRef.
//E_READONLY_IN_MKREFANY "A readonly ByRef cannot be used with mkrefany."
- //E_UNALIGNED_ALIGNMENT "Alignment specified for 'unaligned' prefix must be 1, 2, or 4."
- //E_TAILCALL_INSIDE_EH "The tail.call (or calli or callvirt) instruction cannot be used to transfer control out of a try, filter, catch, or finally block."
- //E_BACKWARD_BRANCH "Stack height at all points must be determinable in a single forward scan of IL."
- //E_CALL_TO_VTYPE_BASE "Call to base type of valuetype."
- //E_NEWOBJ_OF_ABSTRACT_CLASS "Cannot construct an instance of abstract class."
+ //E_UNALIGNED_ALIGNMENT "Alignment specified for 'unaligned' prefix must be 1, 2, or 4."
+ //E_TAILCALL_INSIDE_EH "The tail.call (or calli or callvirt) instruction cannot be used to transfer control out of a try, filter, catch, or finally block."
+ //E_BACKWARD_BRANCH "Stack height at all points must be determinable in a single forward scan of IL."
+ //E_CALL_TO_VTYPE_BASE "Call to base type of valuetype."
+ //E_NEWOBJ_OF_ABSTRACT_CLASS "Cannot construct an instance of abstract class."
UnmanagedPointer, // Unmanaged pointers are not a verifiable type.
- //E_LDFTN_NON_FINAL_VIRTUAL "Cannot LDFTN a non-final virtual method for delegate creation if target object is potentially not the same type as the method class."
- //E_FIELD_OVERLAP "Accessing type with overlapping fields."
- //E_THIS_MISMATCH "The 'this' parameter to the call must be the calling method's 'this' parameter."
- //E_STACK_I_I4 "Expected I4 on the stack."
+ LdftnNonFinalVirtual, // Cannot LDFTN a non-final virtual method for delegate creation if target object is potentially not the same type as the method class.
+ //E_FIELD_OVERLAP "Accessing type with overlapping fields."
+ ThisMismatch, // The 'this' parameter to the call must be the calling method's 'this' parameter.
+ //E_STACK_I_I4 "Expected I4 on the stack."
//E_BAD_PE "Unverifiable PE Header/native stub."
//E_BAD_MD "Unrecognized metadata, unable to verify IL."
diff --git a/src/ILVerify/tests/ILTests/CallTests.il b/src/ILVerify/tests/ILTests/CallTests.il
new file mode 100644
index 000000000..e39ce22ff
--- /dev/null
+++ b/src/ILVerify/tests/ILTests/CallTests.il
@@ -0,0 +1,133 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly extern System.Runtime
+{
+}
+
+.assembly CallTests
+{
+}
+
+.class public auto ansi beforefieldinit SimpleClass
+ extends [System.Runtime]System.Object
+{
+ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
+ {
+ ldarg.0
+ call instance void [System.Runtime]System.Object::.ctor()
+ ret
+ }
+
+ .method public hidebysig newslot virtual instance void VirtualMethod() cil managed
+ {
+ ret
+ }
+}
+
+.class public auto ansi beforefieldinit DerivedClass
+ extends SimpleClass
+{
+ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
+ {
+ ldarg.0
+ call instance void SimpleClass::.ctor()
+ ret
+ }
+
+ .method public hidebysig virtual instance void VirtualMethod() cil managed
+ {
+ ldarg.0
+ call instance void SimpleClass::VirtualMethod()
+ ret
+ }
+
+ .method public hidebysig instance void Call.BaseMethod_Valid() cil managed
+ {
+ ldarg.0
+ call instance void SimpleClass::VirtualMethod()
+ ret
+ }
+
+ .method public hidebysig instance void Call.BaseMethodModThisLdarga_Invalid_ThisMismatch() cil managed
+ {
+ ldarg.0
+ call instance void SimpleClass::VirtualMethod()
+ ldarga 0
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Call.BaseMethodModThisStarg_Invalid_ThisMismatch() cil managed
+ {
+ ldarg.0
+ call instance void SimpleClass::VirtualMethod()
+ ldarg.0
+ starg 0
+ ret
+ }
+}
+
+.class public auto ansi beforefieldinit CallTestsType
+ extends [System.Runtime]System.Object
+{
+ .method public hidebysig instance void Call.IntToStringManagedPtr_Valid() cil managed
+ {
+ .locals init (
+ [0] int32
+ )
+
+ ldc.i4.0
+ stloc.0
+ ldloca.s 0
+ call instance string [System.Runtime]System.Int32::ToString()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Call.IntToStringBoxed_Valid() cil managed
+ {
+ .locals init (
+ [0] int32
+ )
+
+ ldc.i4.0
+ box [System.Runtime]System.Int32
+ call instance string [System.Runtime]System.Object::ToString()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Callvirt.IntToStringBoxed_Valid() cil managed
+ {
+ .locals init (
+ [0] int32
+ )
+
+ ldc.i4.0
+ box [System.Runtime]System.Int32
+ callvirt instance string [System.Runtime]System.Object::ToString()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Call.IntToStringUnboxed_Invalid_StackUnexpected() cil managed
+ {
+ .locals init (
+ [0] int32
+ )
+
+ ldc.i4.0
+ call instance string [System.Runtime]System.Int32::ToString()
+ pop
+ ret
+ }
+
+ .method public hidebysig instance void Call.ExternBaseMethod_Invalid_ThisMismatch(class DerivedClass c) cil managed
+ {
+ ldarg.1
+ call instance void SimpleClass::VirtualMethod()
+ ret
+ }
+}
diff --git a/src/ILVerify/tests/ILTests/CastingTests.il b/src/ILVerify/tests/ILTests/CastingTests.il
index bddd3bcd3..8387ea85f 100644
--- a/src/ILVerify/tests/ILTests/CastingTests.il
+++ b/src/ILVerify/tests/ILTests/CastingTests.il
@@ -106,7 +106,7 @@
}
}
-.class public sequential ansi beforefieldinit GenericOtherFieldsType`1<T>
+.class public sequential ansi sealed beforefieldinit GenericOtherFieldsType`1<T>
extends [System.Runtime]System.ValueType
{
.field public !T GenericField;
diff --git a/src/ILVerify/tests/ILTests/FtnTests.il b/src/ILVerify/tests/ILTests/FtnTests.il
index 5384d7b38..cb76a104f 100644
--- a/src/ILVerify/tests/ILTests/FtnTests.il
+++ b/src/ILVerify/tests/ILTests/FtnTests.il
@@ -94,6 +94,12 @@
ret
}
+ .method public hidebysig static int32 StaticIntMethod() cil managed
+ {
+ ldc.i4.0
+ ret
+ }
+
.method public hidebysig static void StaticMethodRefConstr<class T>() cil managed
{
ret
@@ -223,7 +229,7 @@
ret
}
- .method static public hidebysig void LdvirtFtn.ValueTypeWrongBox_Invalid_StackUnexpected.DelegateCtorSigO(int32 i) cil managed
+ .method static public hidebysig void LdvirtFtn.ValueTypeWrongBox_Invalid_StackUnexpected.DelegateCtorSigO.DelegatePattern(int32 i) cil managed
{
// (int i)
// var f = new System.Func<int, int>(i.CompareTo);
@@ -270,4 +276,91 @@
pop
ret
}
+
+ .method static public hidebysig void LdFtn.NopInDelegatePattern_Invalid_DelegatePattern() cil managed
+ {
+ // var a = new System.Action(TestClass.StaticMethod);
+ // a();
+
+ ldnull
+ ldftn void TestClass::StaticMethod()
+ nop
+ newobj instance void [System.Runtime]System.Action::.ctor(object, native int)
+ callvirt instance void [System.Runtime]System.Action::Invoke()
+ ret
+ }
+
+ .method static public hidebysig void LdvirtFtn.NopInDelegatePattern_Invalid_DelegatePattern(class TestClass c) cil managed
+ {
+ // (TestClass c)
+ // var a = new System.Action(c.InstanceMethod);
+ // a();
+
+ ldarg.0
+ dup
+ nop
+ ldvirtftn instance void TestClass::InstanceMethod()
+ newobj instance void [System.Runtime]System.Action::.ctor(object, native int)
+ callvirt instance void [System.Runtime]System.Action::Invoke()
+ ret
+ }
+
+ .method static public hidebysig void LdFtn.BranchIntoDelegatePattern_Invalid_DelegatePattern() cil managed
+ {
+ ldnull
+ ldftn void TestClass::StaticMethod()
+ br lbl_newobj
+
+ ldnull
+ ldftn void TestClass::StaticMethod()
+
+ lbl_newobj:
+ newobj instance void [System.Runtime]System.Action::.ctor(object, native int)
+ callvirt instance void [System.Runtime]System.Action::Invoke()
+ ret
+ }
+
+ .method static public hidebysig void LdvirtFtn.BranchIntoDelegatePattern_Invalid_DelegatePattern(class TestClass t) cil managed
+ {
+ ldarg.0
+ dup
+ br lbl_ldvirt
+
+ ldarg.0
+ dup
+
+ lbl_ldvirt:
+ ldvirtftn instance void TestClass::InstanceMethod()
+ newobj instance void [System.Runtime]System.Action::.ctor(object, native int)
+ callvirt instance void [System.Runtime]System.Action::Invoke()
+ ret
+ }
+
+ .method static public hidebysig void LdFtn.DelegateMissingArgument_Invalid_DelegateCtor() cil managed
+ {
+ ldnull
+ ldftn void TestClass::StaticMethod()
+ newobj instance void class [System.Runtime]System.Action`1<int32>::.ctor(object, native int)
+ ldc.i4.0
+ callvirt instance void class [System.Runtime]System.Action`1<int32>::Invoke(!0)
+ ret
+ }
+
+ .method static public hidebysig void LdFtn.DelegateWrongReturnType_Invalid_DelegateCtor() cil managed
+ {
+ ldnull
+ ldftn int32 TestClass::StaticIntMethod()
+ newobj instance void [System.Runtime]System.Action::.ctor(object, native int)
+ callvirt instance void [System.Runtime]System.Action::Invoke()
+ ret
+ }
+
+ .method static public hidebysig void LdFtn.VirtualMethodNonThisPtr_Invalid_LdftnNonFinalVirtual(class TestClass c) cil managed
+ {
+ ldarg.0
+ ldftn instance void TestClass::VirtInstanceMethod()
+ newobj instance void [System.Runtime]System.Action::.ctor(object, native int)
+ callvirt instance void [System.Runtime]System.Action::Invoke()
+ ret
+ }
}