summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt4
-rw-r--r--src/dlls/mscorrc/mscorrc.rc2
-rw-r--r--src/dlls/mscorrc/resource.h2
-rw-r--r--src/vm/methodimpl.cpp14
-rw-r--r--src/vm/methodimpl.h5
-rw-r--r--src/vm/methodtable.cpp177
-rw-r--r--src/vm/methodtable.h2
-rw-r--r--src/vm/methodtablebuilder.cpp201
-rw-r--r--src/vm/methodtablebuilder.h27
-rw-r--r--tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.cs167
-rw-r--r--tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.il699
-rwxr-xr-xtests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.cs279
-rw-r--r--tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.il1514
13 files changed, 2908 insertions, 185 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 38461acaee..ff21c69f43 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -344,6 +344,10 @@ if (WIN32)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUG /PDBCOMPRESS")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:1572864")
+ # Temporarily disable incremental link due to incremental linking CFG bug crashing crossgen.
+ # See https://github.com/dotnet/coreclr/issues/12592
+ set(NO_INCREMENTAL_LINKER_FLAGS "/INCREMENTAL:NO")
+
# Debug build specific flags
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "/NOVCFEATURE ${NO_INCREMENTAL_LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${NO_INCREMENTAL_LINKER_FLAGS}")
diff --git a/src/dlls/mscorrc/mscorrc.rc b/src/dlls/mscorrc/mscorrc.rc
index 8dd29ae75f..7049c42bf8 100644
--- a/src/dlls/mscorrc/mscorrc.rc
+++ b/src/dlls/mscorrc/mscorrc.rc
@@ -1252,6 +1252,8 @@ BEGIN
IDS_CLASSLOAD_MI_VIRTUALMISMATCH "Method '%3' on type '%1' from assembly '%2' tried to implement a method declaration with a different virtual state."
IDS_CLASSLOAD_MI_MUSTBEVIRTUAL "Method '%3' on type '%1' from assembly '%2' must be virtual to implement a method on an interface or super type."
IDS_CLASSLOAD_MI_BAD_SIG "Type '%1' from assembly '%2' contains an invalid method implementation signature."
+ IDS_CLASSLOAD_MI_FINAL_IMPL "Method implementation on an interface '%1' from assembly '%2' must be a final method."
+ IDS_CLASSLOAD_AMBIGUOUS_OVERRIDE "Could not call method '%1' on interface '%2' with type '%3' from assembly '%4' because there are more than one incompatible interface method overriding this method."
IDS_CLASSLOAD_MISSINGMETHODRVA "Could not load type '%1' from assembly '%2' because the method '%3' has no implementation (no RVA)."
SECURITY_E_INCOMPATIBLE_EVIDENCE "Assembly '%1' already loaded without additional security evidence."
diff --git a/src/dlls/mscorrc/resource.h b/src/dlls/mscorrc/resource.h
index 205445acbe..39bc8fa9f1 100644
--- a/src/dlls/mscorrc/resource.h
+++ b/src/dlls/mscorrc/resource.h
@@ -613,6 +613,8 @@
#define IDS_EE_SIMD_PARTIAL_TRUST_DISALLOWED 0x1ac4
#define IDS_IBC_MISSING_EXTERNAL_TYPE 0x1ac5
#define IDS_IBC_MISSING_EXTERNAL_METHOD 0x1ac6
+#define IDS_CLASSLOAD_MI_FINAL_IMPL 0x1ac7
+#define IDS_CLASSLOAD_AMBIGUOUS_OVERRIDE 0x1ac8
#define BFA_INVALID_FILE_TOKEN 0x2000
#define BFA_INVALID_TOKEN_TYPE 0x2001
diff --git a/src/vm/methodimpl.cpp b/src/vm/methodimpl.cpp
index c685e1c8a5..b3f8451e22 100644
--- a/src/vm/methodimpl.cpp
+++ b/src/vm/methodimpl.cpp
@@ -72,6 +72,20 @@ PTR_MethodDesc MethodImpl::FindMethodDesc(DWORD slot, PTR_MethodDesc defaultRetu
return defaultReturn;
}
+ return GetMethodDesc(slotIndex, defaultReturn);
+}
+
+PTR_MethodDesc MethodImpl::GetMethodDesc(DWORD slotIndex, PTR_MethodDesc defaultReturn)
+{
+ CONTRACTL
+ {
+ if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
+ if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
+ if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else { INJECT_FAULT(COMPlusThrowOM()); }
+ MODE_ANY;
+ }
+ CONTRACTL_END
+
DPTR(RelativePointer<PTR_MethodDesc>) pRelPtrForSlot = GetImpMDsNonNull();
// The method descs are not offset by one
TADDR base = dac_cast<TADDR>(pRelPtrForSlot) + slotIndex * sizeof(RelativePointer<MethodDesc *>);
diff --git a/src/vm/methodimpl.h b/src/vm/methodimpl.h
index 453f4ccd4d..ce915eaf9d 100644
--- a/src/vm/methodimpl.h
+++ b/src/vm/methodimpl.h
@@ -47,7 +47,7 @@ public:
inline WORD GetSlot()
{ WRAPPER_NO_CONTRACT; CONSISTENCY_CHECK(IsValid()); _ASSERTE(FitsIn<WORD>(m_pImpl->GetSlots()[m_iCur])); return static_cast<WORD>(m_pImpl->GetSlots()[m_iCur]); }
inline MethodDesc *GetMethodDesc()
- { WRAPPER_NO_CONTRACT; return m_pImpl->FindMethodDesc(GetSlot(), (PTR_MethodDesc) m_pMD); }
+ { WRAPPER_NO_CONTRACT; return m_pImpl->GetMethodDesc(m_iCur, (PTR_MethodDesc) m_pMD); }
};
#endif // !DACCESS_COMPILE
@@ -129,6 +129,9 @@ public:
// Returns the method desc for the replaced slot;
PTR_MethodDesc FindMethodDesc(DWORD slot, PTR_MethodDesc defaultReturn);
+ // Returns the method desc for the slot index;
+ PTR_MethodDesc GetMethodDesc(DWORD slotIndex, PTR_MethodDesc defaultReturn);
+
private:
static const DWORD INVALID_INDEX = (DWORD)(-1);
DWORD FindSlotIndex(DWORD slot);
diff --git a/src/vm/methodtable.cpp b/src/vm/methodtable.cpp
index 404d90317c..e27d7641c0 100644
--- a/src/vm/methodtable.cpp
+++ b/src/vm/methodtable.cpp
@@ -6903,7 +6903,7 @@ MethodTable::FindDispatchImpl(
// See if we can find a default method from one of the implemented interfaces
//
MethodDesc *pDefaultMethod = NULL;
- if (FindDefaultMethod(
+ if (FindDefaultInterfaceImplementation(
pIfcMD, // the interface method being resolved
pIfcMT, // the interface being resolved
&pDefaultMethod))
@@ -6943,7 +6943,46 @@ MethodTable::FindDispatchImpl(
}
#ifndef DACCESS_COMPILE
-BOOL MethodTable::FindDefaultMethod(
+
+struct MatchCandidate
+{
+ MethodTable *pMT;
+ MethodDesc *pMD;
+};
+
+void ThrowExceptionForConflictingOverride(
+ MethodTable *pTargetClass,
+ MethodTable *pInterfaceMT,
+ MethodDesc *pInterfaceMD)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ SString assemblyName;
+
+ pTargetClass->GetAssembly()->GetDisplayName(assemblyName);
+
+ SString strInterfaceName;
+ TypeString::AppendType(strInterfaceName, TypeHandle(pInterfaceMT));
+
+ SString strMethodName;
+ TypeString::AppendMethod(strMethodName, pInterfaceMD, pInterfaceMD->GetMethodInstantiation());
+
+ SString strTargetClassName;
+ TypeString::AppendType(strTargetClassName, pTargetClass);
+
+ COMPlusThrow(
+ kNotSupportedException,
+ IDS_CLASSLOAD_AMBIGUOUS_OVERRIDE,
+ strInterfaceName,
+ strMethodName,
+ strTargetClassName,
+ assemblyName);
+}
+
+// Find the default interface implementation method for interface dispatch
+// It is either the interface method with default interface method implementation,
+// or an most specific interface with an explicit methodimpl overriding the method
+BOOL MethodTable::FindDefaultInterfaceImplementation(
MethodDesc *pInterfaceMD,
MethodTable *pInterfaceMT,
MethodDesc **ppDefaultMethod
@@ -6960,20 +6999,17 @@ BOOL MethodTable::FindDefaultMethod(
POSTCONDITION(!RETVAL || (*ppDefaultMethod) != nullptr);
} CONTRACT_END;
- //
- // Find best candidate
- //
InterfaceMapIterator it = this->IterateInterfaceMap();
- MethodTable *pBestCandidateMT = NULL;
- MethodDesc *pBestCandidateMD = NULL;
-
+ CQuickArray<MatchCandidate> candidates;
+ int candidatesCount = 0;
+ candidates.AllocThrows(this->GetNumInterfaces());
+
//
// Walk interface from derived class to parent class
- //
- // @DIM_TODO - This is a first cut naive implementation for prototyping and flush out other
- // implementation issues without worrying too much about ordering/checks
- // Once CLR/C# team has agreed on the right order, we'll replace this with the real deal
+ // We went with a straight-forward implementation as in most cases the number of interfaces are small
+ // and the result of the interface dispatch are already cached. If there are significant usage of default
+ // interface methods in highly complex interface hierarchies we can revisit this
//
MethodTable *pMT = this;
while (pMT != NULL)
@@ -7006,31 +7042,52 @@ BOOL MethodTable::FindDefaultMethod(
{
if (pCurMT->HasSameTypeDefAs(pInterfaceMT))
{
- // Generic variance match
+ // Generic variance match - we'll instantiate pCurMD with the right type arguments later
pCurMD = pInterfaceMD;
}
else
{
//
- // Parent interface - search for an methodimpl for explicit override
+ // A more specific interface - search for an methodimpl for explicit override
// Implicit override in default interface methods are not allowed
//
MethodIterator methodIt(pCurMT);
for (; methodIt.IsValid(); methodIt.Next())
{
MethodDesc *pMD = methodIt.GetMethodDesc();
- if (pMD->IsVirtual() && !pMD->IsAbstract() && pMD->IsMethodImpl())
+ int targetSlot = pInterfaceMD->GetSlot();
+
+ if (pMD->IsMethodImpl())
{
MethodImpl::Iterator it(pMD);
- while (it.IsValid())
+ for (; it.IsValid(); it.Next())
{
- if (it.GetMethodDesc() == pInterfaceMD)
+ MethodDesc *pDeclMD = it.GetMethodDesc();
+
+ if (pDeclMD->GetSlot() != targetSlot)
+ continue;
+
+ MethodTable *pDeclMT = pDeclMD->GetMethodTable();
+ if (pDeclMT->ContainsGenericVariables())
{
+ TypeHandle thInstDeclMT = ClassLoader::LoadGenericInstantiationThrowing(
+ pDeclMT->GetModule(),
+ pDeclMT->GetCl(),
+ pCurMT->GetInstantiation());
+ MethodTable *pInstDeclMT = thInstDeclMT.GetMethodTable();
+ if (pInstDeclMT == pInterfaceMT)
+ {
+ // This is a matching override. We'll instantiate pCurMD later
+ pCurMD = pMD;
+ break;
+ }
+ }
+ else if (pDeclMD == pInterfaceMD)
+ {
+ // Exact match override
pCurMD = pMD;
break;
}
-
- it.Next();
}
}
}
@@ -7059,24 +7116,65 @@ BOOL MethodTable::FindDefaultMethod(
);
}
- if (pBestCandidateMT != pCurMT)
- {
- if (pBestCandidateMT == NULL || // first time
- pCurMT->CanCastToInterface(pBestCandidateMT)) // Prefer "more specific"" interface
+ bool needToInsert = true;
+ bool seenMoreSpecific = false;
+
+ // We need to maintain the invariant that the candidates are always the most specific
+ // in all path scaned so far. There might be multiple incompatible candidates
+ for (int i = 0; i < candidatesCount; ++i)
+ {
+ MethodTable *pCandidateMT = candidates[i].pMT;
+ if (pCandidateMT == NULL)
+ continue;
+
+ if (pCandidateMT == pCurMT)
{
- // This is a better match
- pBestCandidateMT = pCurMT;
- pBestCandidateMD = pCurMD;
+ // A dup - we are done
+ needToInsert = false;
+ break;
}
- else
+
+ if (pCurMT->CanCastToInterface(pCandidateMT))
{
- if (!pBestCandidateMT->CanCastToInterface(pCurMT))
+ // pCurMT is a more specific choice than IFoo/IBar both overrides IBlah :
+ // /--> IFoo ---\
+ // pCurMT - -->IBlah
+ // \--> IBar ---/
+ // Only update first entry IFoo and null out IBar
+ if (!seenMoreSpecific)
+ {
+ seenMoreSpecific = true;
+ candidates[i].pMT = pCurMT;
+ candidates[i].pMD = pCurMD;
+ }
+ else
{
- // not good. we have a conflict
- COMPlusThrow(kNotSupportedException);
+ candidates[i].pMT = NULL;
+ candidates[i].pMD = NULL;
}
+
+ needToInsert = false;
+ }
+ else if (pCandidateMT->CanCastToInterface(pCurMT))
+ {
+ // pCurMT is less specific - we don't need to scan more entries as this entry can
+ // represent pCurMT (other entries are incompatible with pCurMT)
+ needToInsert = false;
+ break;
+ }
+ else
+ {
+ // pCurMT is incompatible - keep scanning
}
}
+
+ if (needToInsert)
+ {
+ ASSERT(candidatesCount < candidates.Size());
+ candidates[candidatesCount].pMT = pCurMT;
+ candidates[candidatesCount].pMD = pCurMD;
+ candidatesCount++;
+ }
}
it.Next();
@@ -7086,6 +7184,25 @@ BOOL MethodTable::FindDefaultMethod(
pMT = pParentMT;
}
+ // scan to see if there are any conflicts
+ MethodTable *pBestCandidateMT = NULL;
+ MethodDesc *pBestCandidateMD = NULL;
+ for (int i = 0; i < candidatesCount; ++i)
+ {
+ if (candidates[i].pMT == NULL)
+ continue;
+
+ if (pBestCandidateMT == NULL)
+ {
+ pBestCandidateMT = candidates[i].pMT;
+ pBestCandidateMD = candidates[i].pMD;
+ }
+ else if (pBestCandidateMT != candidates[i].pMT)
+ {
+ ThrowExceptionForConflictingOverride(this, pInterfaceMT, pInterfaceMD);
+ }
+ }
+
if (pBestCandidateMD != NULL)
{
*ppDefaultMethod = pBestCandidateMD;
diff --git a/src/vm/methodtable.h b/src/vm/methodtable.h
index 11296b09d6..118a883b6e 100644
--- a/src/vm/methodtable.h
+++ b/src/vm/methodtable.h
@@ -2487,7 +2487,7 @@ public:
#ifndef DACCESS_COMPILE
- BOOL FindDefaultMethod(
+ BOOL FindDefaultInterfaceImplementation(
MethodDesc *pInterfaceMD,
MethodTable *pObjectMT,
MethodDesc **ppDefaultMethod);
diff --git a/src/vm/methodtablebuilder.cpp b/src/vm/methodtablebuilder.cpp
index 2f76d7f795..3a738df496 100644
--- a/src/vm/methodtablebuilder.cpp
+++ b/src/vm/methodtablebuilder.cpp
@@ -1622,6 +1622,10 @@ MethodTableBuilder::BuildMethodTableThrowing(
if (IsInterface())
{
+ //
+ // We need to process/place method impls for default interface method overrides.
+ // We won't build dispatch map for interfaces, though.
+ //
ProcessMethodImpls();
PlaceMethodImpls();
}
@@ -4786,6 +4790,12 @@ VOID MethodTableBuilder::TestMethodImpl(
BuildMethodTableThrowException(IDS_CLASSLOAD_MI_FINAL_DECL);
}
+ // Interface method body that has methodimpl should always be final
+ if (IsInterface() && !IsMdFinal(dwImplAttrs))
+ {
+ BuildMethodTableThrowException(IDS_CLASSLOAD_MI_FINAL_IMPL);
+ }
+
// Since MethodImpl's do not affect the visibility of the Decl method, there's
// no need to check.
@@ -5568,6 +5578,9 @@ MethodTableBuilder::ProcessMethodImpls()
{
STANDARD_VM_CONTRACT;
+ if (bmtMethod->dwNumberMethodImpls == 0)
+ return;
+
HRESULT hr = S_OK;
DeclaredMethodIterator it(*this);
@@ -6159,9 +6172,12 @@ MethodTableBuilder::PlaceMethodImpls()
}
// Allocate some temporary storage. The number of overrides for a single method impl
- // cannot be greater then the number of vtable slots.
- DWORD * slots = new (&GetThread()->m_MarshalAlloc) DWORD[bmtVT->cVirtualSlots];
- RelativePointer<MethodDesc *> * replaced = new (&GetThread()->m_MarshalAlloc) RelativePointer<MethodDesc*>[bmtVT->cVirtualSlots];
+ // cannot be greater then the number of vtable slots for classes. But for interfaces
+ // it might contain overrides for other interface methods.
+ DWORD dwMaxSlotSize = IsInterface() ? bmtMethod->dwNumberMethodImpls : bmtVT->cVirtualSlots;
+
+ DWORD * slots = new (&GetThread()->m_MarshalAlloc) DWORD[dwMaxSlotSize];
+ RelativePointer<MethodDesc *> * replaced = new (&GetThread()->m_MarshalAlloc) RelativePointer<MethodDesc*>[dwMaxSlotSize];
DWORD iEntry = 0;
bmtMDMethod * pCurImplMethod = bmtMethodImpl->GetImplementationMethod(iEntry);
@@ -6179,7 +6195,8 @@ MethodTableBuilder::PlaceMethodImpls()
// (declaration is on this type) or a method desc.
bmtMethodHandle hDeclMethod = bmtMethodImpl->GetDeclarationMethod(iEntry);
if(hDeclMethod.IsMDMethod())
- { // The declaration is on the type being built
+ {
+ // The declaration is on the type being built
bmtMDMethod * pCurDeclMethod = hDeclMethod.AsMDMethod();
mdToken mdef = pCurDeclMethod->GetMethodSignature().GetToken();
@@ -6190,22 +6207,25 @@ MethodTableBuilder::PlaceMethodImpls()
if (IsInterface())
{
- // We implement this slot, record it
- slots[slotIndex] = pCurDeclMethod->GetSlotIndex();
- replaced[slotIndex].SetValue(pCurDeclMethod->GetMethodDesc());
-
- // increment the counter
- slotIndex++;
+ // Throws
+ PlaceInterfaceDeclarationOnInterface(
+ hDeclMethod,
+ pCurImplMethod,
+ slots, // Adds override to the slot and replaced arrays.
+ replaced,
+ &slotIndex,
+ dwMaxSlotSize); // Increments count
}
else
{
// Throws
- PlaceLocalDeclaration(
+ PlaceLocalDeclarationOnClass(
pCurDeclMethod,
pCurImplMethod,
- slots, // Adds override to the slot and replaced arrays.
+ slots, // Adds override to the slot and replaced arrays.
replaced,
- &slotIndex); // Increments count
+ &slotIndex,
+ dwMaxSlotSize); // Increments count
}
}
else
@@ -6214,12 +6234,14 @@ MethodTableBuilder::PlaceMethodImpls()
if (IsInterface())
{
- // We implement this slot, record it
- slots[slotIndex] = pCurDeclMethod->GetSlotIndex();
- replaced[slotIndex].SetValue(pCurDeclMethod->GetMethodDesc());
-
- // increment the counter
- slotIndex++;
+ // Throws
+ PlaceInterfaceDeclarationOnInterface(
+ hDeclMethod,
+ pCurImplMethod,
+ slots, // Adds override to the slot and replaced arrays.
+ replaced,
+ &slotIndex,
+ dwMaxSlotSize); // Increments count
}
else
{
@@ -6227,22 +6249,20 @@ MethodTableBuilder::PlaceMethodImpls()
if (pCurDeclMethod->GetOwningType()->IsInterface())
{
// Throws
- PlaceInterfaceDeclaration(
+ PlaceInterfaceDeclarationOnClass(
pCurDeclMethod,
- pCurImplMethod,
- slots,
- replaced,
- &slotIndex); // Increments count
+ pCurImplMethod);
}
else
{
// Throws
- PlaceParentDeclaration(
+ PlaceParentDeclarationOnClass(
pCurDeclMethod,
pCurImplMethod,
slots,
replaced,
- &slotIndex); // Increments count
+ &slotIndex,
+ dwMaxSlotSize); // Increments count
}
}
}
@@ -6250,7 +6270,8 @@ MethodTableBuilder::PlaceMethodImpls()
iEntry++;
if(iEntry == bmtMethodImpl->pIndex)
- { // We hit the end of the list so dump the current data and leave
+ {
+ // We hit the end of the list so dump the current data and leave
WriteMethodImplData(pCurImplMethod, slotIndex, slots, replaced);
break;
}
@@ -6259,7 +6280,8 @@ MethodTableBuilder::PlaceMethodImpls()
bmtMDMethod * pNextImplMethod = bmtMethodImpl->GetImplementationMethod(iEntry);
if (pNextImplMethod != pCurImplMethod)
- { // If we're moving on to a new body, dump the current data and reset the counter
+ {
+ // If we're moving on to a new body, dump the current data and reset the counter
WriteMethodImplData(pCurImplMethod, slotIndex, slots, replaced);
slotIndex = 0;
}
@@ -6302,6 +6324,8 @@ MethodTableBuilder::WriteMethodImplData(
{
// If we are currently builting an interface, the slots here has no meaning and we can skip it
// Sort the two arrays in slot index order
+ // This is required in MethodImpl::FindSlotIndex and MethodImpl::Iterator as we'll be using
+ // binary search later
for (DWORD i = 0; i < cSlots; i++)
{
int min = i;
@@ -6335,12 +6359,13 @@ MethodTableBuilder::WriteMethodImplData(
//*******************************************************************************
VOID
-MethodTableBuilder::PlaceLocalDeclaration(
+MethodTableBuilder::PlaceLocalDeclarationOnClass(
bmtMDMethod * pDecl,
bmtMDMethod * pImpl,
DWORD * slots,
RelativePointer<MethodDesc *> * replaced,
- DWORD * pSlotIndex)
+ DWORD * pSlotIndex,
+ DWORD dwMaxSlotSize)
{
CONTRACTL
{
@@ -6395,20 +6420,18 @@ MethodTableBuilder::PlaceLocalDeclaration(
pImpl);
// We implement this slot, record it
+ ASSERT(*pSlotIndex < dwMaxSlotSize);
slots[*pSlotIndex] = pDecl->GetSlotIndex();
replaced[*pSlotIndex].SetValue(pDecl->GetMethodDesc());
// increment the counter
(*pSlotIndex)++;
-} // MethodTableBuilder::PlaceLocalDeclaration
+} // MethodTableBuilder::PlaceLocalDeclarationOnClass
//*******************************************************************************
-VOID MethodTableBuilder::PlaceInterfaceDeclaration(
+VOID MethodTableBuilder::PlaceInterfaceDeclarationOnClass(
bmtRTMethod * pDecl,
- bmtMDMethod * pImpl,
- DWORD* slots,
- RelativePointer<MethodDesc *> * replaced,
- DWORD* pSlotIndex)
+ bmtMDMethod * pImpl)
{
CONTRACTL {
STANDARD_VM_CHECK;
@@ -6504,16 +6527,60 @@ VOID MethodTableBuilder::PlaceInterfaceDeclaration(
}
}
#endif //_DEBUG
-} // MethodTableBuilder::PlaceInterfaceDeclaration
+} // MethodTableBuilder::PlaceInterfaceDeclarationOnClass
+
+//*******************************************************************************
+VOID MethodTableBuilder::PlaceInterfaceDeclarationOnInterface(
+ bmtMethodHandle hDecl,
+ bmtMDMethod *pImpl,
+ DWORD * slots,
+ RelativePointer<MethodDesc *> * replaced,
+ DWORD * pSlotIndex,
+ DWORD dwMaxSlotSize)
+{
+ CONTRACTL {
+ STANDARD_VM_CHECK;
+ PRECONDITION(CheckPointer(pImpl));
+ PRECONDITION(IsInterface());
+ PRECONDITION(hDecl.GetMethodDesc()->IsInterface());
+ } CONTRACTL_END;
+
+ MethodDesc * pDeclMD = hDecl.GetMethodDesc();
+
+ if (!bmtProp->fNoSanityChecks)
+ {
+ ///////////////////////////////
+ // Verify the signatures match
+
+ MethodImplCompareSignatures(
+ hDecl,
+ bmtMethodHandle(pImpl),
+ IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_INTERFACE_METHOD_IMPL);
+
+ ///////////////////////////////
+ // Validate the method impl.
+
+ TestMethodImpl(hDecl, bmtMethodHandle(pImpl));
+ }
+
+ // We implement this slot, record it
+ ASSERT(*pSlotIndex < dwMaxSlotSize);
+ slots[*pSlotIndex] = hDecl.GetSlotIndex();
+ replaced[*pSlotIndex].SetValue(pDeclMD);
+
+ // increment the counter
+ (*pSlotIndex)++;
+} // MethodTableBuilder::PlaceInterfaceDeclarationOnInterface
//*******************************************************************************
VOID
-MethodTableBuilder::PlaceParentDeclaration(
+MethodTableBuilder::PlaceParentDeclarationOnClass(
bmtRTMethod * pDecl,
bmtMDMethod * pImpl,
DWORD * slots,
RelativePointer<MethodDesc *> * replaced,
- DWORD * pSlotIndex)
+ DWORD * pSlotIndex,
+ DWORD dwMaxSlotSize)
{
CONTRACTL {
STANDARD_VM_CHECK;
@@ -6556,12 +6623,13 @@ MethodTableBuilder::PlaceParentDeclaration(
pImpl);
// We implement this slot, record it
+ ASSERT(*pSlotIndex < dwMaxSlotSize);
slots[*pSlotIndex] = pDeclMD->GetSlot();
replaced[*pSlotIndex].SetValue(pDeclMD);
// increment the counter
(*pSlotIndex)++;
-} // MethodTableBuilder::PlaceParentDeclaration
+} // MethodTableBuilder::PlaceParentDeclarationOnClass
//*******************************************************************************
// This will validate that all interface methods that were matched during
@@ -10783,6 +10851,45 @@ MethodTableBuilder::SetupMethodTable2(
#pragma warning(pop)
#endif
+// Returns true if there is at least one default implementation for this interface method
+// We don't care about conflicts at this stage in order to avoid impact type load performance
+BOOL MethodTableBuilder::HasDefaultInterfaceImplementation(MethodDesc *pDeclMD)
+{
+ STANDARD_VM_CONTRACT;
+
+ // If the interface method is already non-abstract, we are done
+ if (pDeclMD->IsDefaultInterfaceMethod())
+ return TRUE;
+
+ MethodTable *pDeclMT = pDeclMD->GetMethodTable();
+
+ // Otherwise, traverse the list of interfaces and see if there is at least one override
+ bmtInterfaceInfo::MapIterator intIt = bmtInterface->IterateInterfaceMap();
+ for (; !intIt.AtEnd(); intIt.Next())
+ {
+ MethodTable *pIntfMT = intIt->GetInterfaceType()->GetMethodTable();
+ if (pIntfMT->GetClass()->ContainsMethodImpls() && pIntfMT->CanCastToInterface(pDeclMT))
+ {
+ MethodTable::MethodIterator methodIt(pIntfMT);
+ for (; methodIt.IsValid(); methodIt.Next())
+ {
+ MethodDesc *pMD = methodIt.GetMethodDesc();
+ if (pMD->IsMethodImpl())
+ {
+ MethodImpl::Iterator it(pMD);
+ while (it.IsValid())
+ {
+ if (it.GetMethodDesc() == pDeclMD)
+ return TRUE;
+ }
+ }
+ }
+ }
+ }
+
+ return FALSE;
+}
+
void MethodTableBuilder::VerifyVirtualMethodsImplemented(MethodTable::MethodData * hMTData)
{
STANDARD_VM_CONTRACT;
@@ -10855,13 +10962,13 @@ void MethodTableBuilder::VerifyVirtualMethodsImplemented(MethodTable::MethodData
MethodTable::MethodIterator it(hData);
for (; it.IsValid() && it.IsVirtual(); it.Next())
{
- // @DIM_TODO - What is the right level of check if the interface itself does not have default implementation
- // but a derived interface do
- // if (it.GetTarget().IsNull())
- // {
- // MethodDesc *pMD = it.GetDeclMethodDesc();
- // BuildMethodTableThrowException(IDS_CLASSLOAD_NOTIMPLEMENTED, pMD->GetNameOnNonArrayClass());
- // }
+ if (it.GetTarget().IsNull())
+ {
+ MethodDesc *pMD = it.GetDeclMethodDesc();
+
+ if (!HasDefaultInterfaceImplementation(pMD))
+ BuildMethodTableThrowException(IDS_CLASSLOAD_NOTIMPLEMENTED, pMD->GetNameOnNonArrayClass());
+ }
}
}
}
diff --git a/src/vm/methodtablebuilder.h b/src/vm/methodtablebuilder.h
index e5043cf06d..8c838d37e6 100644
--- a/src/vm/methodtablebuilder.h
+++ b/src/vm/methodtablebuilder.h
@@ -2739,32 +2739,42 @@ private:
// --------------------------------------------------------------------------------------------
// Places a methodImpl pair where the decl is declared by the type being built.
VOID
- PlaceLocalDeclaration(
+ PlaceLocalDeclarationOnClass(
bmtMDMethod * pDecl,
bmtMDMethod * pImpl,
DWORD* slots,
RelativePointer<MethodDesc *> * replaced,
- DWORD* pSlotIndex);
+ DWORD* pSlotIndex,
+ DWORD dwMaxSlotSize);
// --------------------------------------------------------------------------------------------
// Places a methodImpl pair where the decl is declared by a parent type.
VOID
- PlaceParentDeclaration(
+ PlaceParentDeclarationOnClass(
bmtRTMethod * pDecl,
bmtMDMethod * pImpl,
DWORD* slots,
RelativePointer<MethodDesc *> * replaced,
- DWORD* pSlotIndex);
+ DWORD* pSlotIndex,
+ DWORD dwMaxSlotSize);
// --------------------------------------------------------------------------------------------
- // Places a methodImpl pair where the decl is declared by an interface.
+ // Places a methodImpl pair on a class where the decl is declared by an interface.
VOID
- PlaceInterfaceDeclaration(
+ PlaceInterfaceDeclarationOnClass(
bmtRTMethod * pDecl,
- bmtMDMethod * pImpl,
+ bmtMDMethod * pImpl);
+
+ // --------------------------------------------------------------------------------------------
+ // Places a methodImpl pair on an interface where the decl is declared by an interface.
+ VOID
+ PlaceInterfaceDeclarationOnInterface(
+ bmtMethodHandle hDecl,
+ bmtMDMethod * pImpl,
DWORD* slots,
RelativePointer<MethodDesc *> * replaced,
- DWORD* pSlotIndex);
+ DWORD* pSlotIndex,
+ DWORD dwMaxSlotSize);
// --------------------------------------------------------------------------------------------
// This will validate that all interface methods that were matched during
@@ -2846,6 +2856,7 @@ private:
VOID HandleGCForValueClasses(
MethodTable **);
+ BOOL HasDefaultInterfaceImplementation(MethodDesc *pIntfMD);
VOID VerifyVirtualMethodsImplemented(MethodTable::MethodData * hMTData);
VOID CheckForTypeEquivalence(
diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.cs b/tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.cs
index f6c77862ce..3ff3760aa3 100644
--- a/tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.cs
+++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.cs
@@ -48,9 +48,113 @@ class FooClass : IFoo2, IFooEx
}
}
+interface I1
+{
+ int Func(int a);
+}
+
+interface I2 : I1
+{
+ // int I1.Func(int a) { return a + 2; }
+}
+
+interface I3 : I1
+{
+ // int I1.Func(int a) { return a + 3; }
+}
+
+interface I4 : I2, I3
+{
+ // int I1.Func(int a) { return a + 4; }
+}
+
+class I4Class : I4
+{
+ // @REMOVE
+ int I1.Func(int a)
+ {
+ Console.WriteLine("At I4Class.Func");
+ return a + 4;
+ }
+}
+
+interface I5: I1
+{
+ // int I1.Func(int a) { return a + 5; }
+}
+
+interface I6: I1
+{
+ // int I1.Func(int a) { return a + 6; }
+}
+
+interface I7: I5, I6
+{
+ // int I1.Func(int a) { return a + 7; }
+}
+
+interface I8: I4, I7
+{
+ // int I1.Func(int a) { return a + 8; }
+}
+
+class I47Class: I4, I7
+{
+ // @REMOVE
+ int I1.Func(int a)
+ {
+ Console.WriteLine("At I4Class.Func");
+ return a + 8;
+ }
+
+}
+
+class I8Class: I8
+{
+ // @REMOVE
+ int I1.Func(int a)
+ {
+ Console.WriteLine("At I4Class.Func");
+ return a + 8;
+ }
+}
+
+interface GI1<T>
+{
+ int Func<S>(out Type[] types);
+}
+
+interface GI2<T> : GI1<T>
+{
+ // int GI1<T>.Func<S>(out Type[] types) { Console.WriteLine(typeof(T) + ", "typeof(S) + ", GI1Class"); types = new Type[] { typeof(T), typeof(S) }; return 2; }
+
+}
+
+interface GI3<T> : GI1<T>
+{
+ // int GI1<T>.Func<S>(out Type[] types) { Console.WriteLine(typeof(T) + ", "typeof(S) + ", GI1Class"); types = new Type[] { typeof(T), typeof(S) }; return 3; }
+}
+
+interface GI4<T> : GI2<T>, GI3<T>
+{
+ // int GI1<T>.Func<S>(out Type[] types) { Console.WriteLine(typeof(T) + ", "typeof(S) + ", GI1Class"); types = new Type[] { typeof(T), typeof(S) }; return 4; }
+}
+
+class GI23Class<T>: GI2<T>, GI3<T>
+{
+ // @REMOVE
+ int GI1<T>.Func<S>(out Type[] types) { Console.WriteLine(typeof(T) + ", " + typeof(S) + ", GI1Class"); types = new Type[] { typeof(T), typeof(S) }; return 4; }
+}
+
+class GI4Class<T>: GI4<T>
+{
+ // @REMOVE
+ int GI1<T>.Func<S>(out Type[] types) { Console.WriteLine(typeof(T) + ", " + typeof(S) + ", GI1Class"); types = new Type[] { typeof(T), typeof(S) }; return 4; }
+}
+
class Program
{
- public static int Main()
+ public static void Negative()
{
FooClass fooObj = new FooClass();
IFoo foo = (IFoo) fooObj;
@@ -59,12 +163,69 @@ class Program
try
{
foo.Foo(10);
- Test.Assert(false, "Expecting exception");
+ Test.Assert(false, "Expecting exception on Foo");
+ }
+ catch(Exception ex)
+ {
+ Console.WriteLine("Exception caught: " + ex.ToString());
}
- catch(Exception)
+
+ I47Class i47Class = new I47Class();
+ I1 i1 = (I1) i47Class;
+ Console.WriteLine("Calling I1.Func on I47Class - expecting exception");
+ try
+ {
+ i1.Func(10);
+ Test.Assert(false, "Expecting exception on I47Class");
+ }
+ catch(Exception ex)
+ {
+ Console.WriteLine("Exception caught: " + ex.ToString());
+ }
+
+ var gi23Class = new GI23Class<object>();
+ GI1<object> gi1 = (GI1<object>) gi23Class;
+ Console.WriteLine("Calling GI1<T>.Func on GI23Class<S> - expecting exception");
+ try
{
+ Type[] types;
+ gi1.Func<string>(out types);
+ Test.Assert(false, "Expecting exception on GI23Class");
}
+ catch(Exception ex)
+ {
+ Console.WriteLine("Exception caught: " + ex.ToString());
+ }
+ }
+ public static void Positive()
+ {
+ Console.WriteLine("Calling I1.Func on I4Class - expecting I4.Func");
+
+ I4Class i4Class = new I4Class();
+ I1 i1 = (I1) i4Class;
+ Test.Assert(i1.Func(10) == 14, "Expecting I1.Func to land on I4.Func");
+
+ Console.WriteLine("Calling I1.Func on I8Class - expecting I8.Func");
+
+ I8Class i8Class = new I8Class();
+ i1 = (I1) i8Class;
+ Test.Assert(i1.Func(10) == 18, "Expecting I1.Func to land on I8.Func");
+
+ Console.WriteLine("Calling GI1.Func on GI4Class<object> - expecting GI4.Func<S>");
+
+ var gi4Class = new GI4Class<object>();
+ Type[] types;
+ var gi1 = (GI1<object>) gi4Class;
+ Test.Assert(gi1.Func<string>(out types) == 4, "Expecting GI1<T>.Func to land on GII4<T>.Func<S>");
+ Test.Assert(types[0] == typeof(object), "T must be object");
+ Test.Assert(types[1] == typeof(string), "S must be string");
+ }
+
+ public static int Main()
+ {
+ Negative();
+ Positive();
return Test.Ret();
}
}
diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.il b/tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.il
index 82d9fa7acf..4173bc6aea 100644
--- a/tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.il
+++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.il
@@ -123,17 +123,505 @@
} // end of class FooClass
+.class interface private abstract auto ansi I1
+{
+ .method public hidebysig newslot abstract virtual
+ instance int32 Func(int32 a) cil managed
+ {
+ } // end of method I1::Func
+
+} // end of class I1
+
+.class interface private abstract auto ansi I2
+ implements I1
+{
+ .method private hidebysig newslot virtual final
+ instance int32 I1.Func(int32 a) cil managed
+ {
+ .override I1::Func
+ // Code size 20 (0x14)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At I2.Func"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.2
+ IL_000e: add
+ IL_000f: stloc.0
+ IL_0010: br.s IL_0012
+
+ IL_0012: ldloc.0
+ IL_0013: ret
+ } // end of method I2::I1.Func
+} // end of class I2
+
+.class interface private abstract auto ansi I3
+ implements I1
+{
+ .method private hidebysig newslot virtual final
+ instance int32 I1.Func(int32 a) cil managed
+ {
+ .override I1::Func
+ // Code size 20 (0x14)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At I3.Func"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.3
+ IL_000e: add
+ IL_000f: stloc.0
+ IL_0010: br.s IL_0012
+
+ IL_0012: ldloc.0
+ IL_0013: ret
+ } // end of method I3::I1.Func
+} // end of class I3
+
+.class interface private abstract auto ansi I4
+ implements I2,
+ I1,
+ I3
+{
+ .method private hidebysig newslot virtual final
+ instance int32 I1.Func(int32 a) cil managed
+ {
+ .override I1::Func
+ // Code size 20 (0x14)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At I4.Func"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.4
+ IL_000e: add
+ IL_000f: stloc.0
+ IL_0010: br.s IL_0012
+
+ IL_0012: ldloc.0
+ IL_0013: ret
+ } // end of method I4::I1.Func
+} // end of class I4
+
+.class private auto ansi beforefieldinit I4Class
+ extends [mscorlib]System.Object
+ implements I4,
+ I2,
+ I1,
+ I3
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method I4Class::.ctor
+
+} // end of class I4Class
+
+.class interface private abstract auto ansi I5
+ implements I1
+{
+ .method private hidebysig newslot virtual final
+ instance int32 I1.Func(int32 a) cil managed
+ {
+ .override I1::Func
+ // Code size 20 (0x14)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At I5.Func"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.5
+ IL_000e: add
+ IL_000f: stloc.0
+ IL_0010: br.s IL_0012
+
+ IL_0012: ldloc.0
+ IL_0013: ret
+ } // end of method I5::I1.Func
+} // end of class I5
+
+.class interface private abstract auto ansi I6
+ implements I1
+{
+ .method private hidebysig newslot virtual final
+ instance int32 I1.Func(int32 a) cil managed
+ {
+ .override I1::Func
+ // Code size 20 (0x14)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At I6.Func"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.6
+ IL_000e: add
+ IL_000f: stloc.0
+ IL_0010: br.s IL_0012
+
+ IL_0012: ldloc.0
+ IL_0013: ret
+ } // end of method I6::I1.Func
+} // end of class I6
+
+.class interface private abstract auto ansi I7
+ implements I5,
+ I1,
+ I6
+{
+ .method private hidebysig newslot virtual final
+ instance int32 I1.Func(int32 a) cil managed
+ {
+ .override I1::Func
+ // Code size 20 (0x14)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At I7.Func"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.7
+ IL_000e: add
+ IL_000f: stloc.0
+ IL_0010: br.s IL_0012
+
+ IL_0012: ldloc.0
+ IL_0013: ret
+ } // end of method I7::I1.Func
+} // end of class I7
+
+.class interface private abstract auto ansi I8
+ implements I4,
+ I2,
+ I1,
+ I3,
+ I7,
+ I5,
+ I6
+{
+ .method private hidebysig newslot virtual final
+ instance int32 I1.Func(int32 a) cil managed
+ {
+ .override I1::Func
+ // Code size 20 (0x14)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At I8.Func"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.8
+ IL_000e: add
+ IL_000f: stloc.0
+ IL_0010: br.s IL_0012
+
+ IL_0012: ldloc.0
+ IL_0013: ret
+ } // end of method I8::I1.Func
+} // end of class I8
+
+.class private auto ansi beforefieldinit I47Class
+ extends [mscorlib]System.Object
+ implements I4,
+ I2,
+ I1,
+ I3,
+ I7,
+ I5,
+ I6
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method I47Class::.ctor
+
+} // end of class I47Class
+
+.class private auto ansi beforefieldinit I8Class
+ extends [mscorlib]System.Object
+ implements I8,
+ I4,
+ I2,
+ I1,
+ I3,
+ I7,
+ I5,
+ I6
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method I8Class::.ctor
+
+} // end of class I8Class
+
+.class interface private abstract auto ansi GI1`1<T>
+{
+ .method public hidebysig newslot abstract virtual
+ instance int32 Func<S>([out] class [mscorlib]System.Type[]& types) cil managed
+ {
+ } // end of method GI1`1::'GI1<T>.Func'
+
+} // end of class GI1`1
+
+.class interface private abstract auto ansi GI2`1<T>
+ implements class GI1`1<!T>
+{
+.method private hidebysig newslot virtual final
+ instance int32 'GI1<T>.Func'<S>([out] class [mscorlib]System.Type[]& types) cil managed
+ {
+ .override method instance int32 class GI1`1<!T>::Func<[1]>(class [mscorlib]System.Type[]&)
+ // Code size 100 (0x64)
+ .maxstack 5
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldc.i4.4
+ IL_0002: newarr [mscorlib]System.Object
+ IL_0007: dup
+ IL_0008: ldc.i4.0
+ IL_0009: ldtoken !T
+ IL_000e: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_0013: stelem.ref
+ IL_0014: dup
+ IL_0015: ldc.i4.1
+ IL_0016: ldstr ", "
+ IL_001b: stelem.ref
+ IL_001c: dup
+ IL_001d: ldc.i4.2
+ IL_001e: ldtoken !!S
+ IL_0023: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_0028: stelem.ref
+ IL_0029: dup
+ IL_002a: ldc.i4.3
+ IL_002b: ldstr ", GI2"
+ IL_0030: stelem.ref
+ IL_0031: call string [mscorlib]System.String::Concat(object[])
+ IL_0036: call void [mscorlib]System.Console::WriteLine(string)
+ IL_003b: nop
+ IL_003c: ldarg.1
+ IL_003d: ldc.i4.2
+ IL_003e: newarr [mscorlib]System.Type
+ IL_0043: dup
+ IL_0044: ldc.i4.0
+ IL_0045: ldtoken !T
+ IL_004a: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_004f: stelem.ref
+ IL_0050: dup
+ IL_0051: ldc.i4.1
+ IL_0052: ldtoken !!S
+ IL_0057: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_005c: stelem.ref
+ IL_005d: stind.ref
+ IL_005e: ldc.i4.2
+ IL_005f: stloc.0
+ IL_0060: br.s IL_0062
+
+ IL_0062: ldloc.0
+ IL_0063: ret
+ } // end of method G2`1::'GI1<T>.Func'
+} // end of class GI2`1
+
+.class interface private abstract auto ansi GI3`1<T>
+ implements class GI1`1<!T>
+{
+.method private hidebysig newslot virtual final
+ instance int32 'GI1<T>.Func'<S>([out] class [mscorlib]System.Type[]& types) cil managed
+ {
+ .override method instance int32 class GI1`1<!T>::Func<[1]>(class [mscorlib]System.Type[]&)
+ // Code size 100 (0x64)
+ .maxstack 5
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldc.i4.4
+ IL_0002: newarr [mscorlib]System.Object
+ IL_0007: dup
+ IL_0008: ldc.i4.0
+ IL_0009: ldtoken !T
+ IL_000e: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_0013: stelem.ref
+ IL_0014: dup
+ IL_0015: ldc.i4.1
+ IL_0016: ldstr ", "
+ IL_001b: stelem.ref
+ IL_001c: dup
+ IL_001d: ldc.i4.2
+ IL_001e: ldtoken !!S
+ IL_0023: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_0028: stelem.ref
+ IL_0029: dup
+ IL_002a: ldc.i4.3
+ IL_002b: ldstr ", GI3"
+ IL_0030: stelem.ref
+ IL_0031: call string [mscorlib]System.String::Concat(object[])
+ IL_0036: call void [mscorlib]System.Console::WriteLine(string)
+ IL_003b: nop
+ IL_003c: ldarg.1
+ IL_003d: ldc.i4.2
+ IL_003e: newarr [mscorlib]System.Type
+ IL_0043: dup
+ IL_0044: ldc.i4.0
+ IL_0045: ldtoken !T
+ IL_004a: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_004f: stelem.ref
+ IL_0050: dup
+ IL_0051: ldc.i4.1
+ IL_0052: ldtoken !!S
+ IL_0057: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_005c: stelem.ref
+ IL_005d: stind.ref
+ IL_005e: ldc.i4.3
+ IL_005f: stloc.0
+ IL_0060: br.s IL_0062
+
+ IL_0062: ldloc.0
+ IL_0063: ret
+ } // end of method GI3`1::'GI1<T>.Func'
+} // end of class GI3`1
+
+.class interface private abstract auto ansi GI4`1<T>
+ implements class GI2`1<!T>,
+ class GI1`1<!T>,
+ class GI3`1<!T>
+{
+ .method private hidebysig newslot virtual final
+ instance int32 'GI1<T>.Func'<S>([out] class [mscorlib]System.Type[]& types) cil managed
+ {
+ .override method instance int32 class GI1`1<!T>::Func<[1]>(class [mscorlib]System.Type[]&)
+ // Code size 100 (0x64)
+ .maxstack 5
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldc.i4.4
+ IL_0002: newarr [mscorlib]System.Object
+ IL_0007: dup
+ IL_0008: ldc.i4.0
+ IL_0009: ldtoken !T
+ IL_000e: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_0013: stelem.ref
+ IL_0014: dup
+ IL_0015: ldc.i4.1
+ IL_0016: ldstr ", "
+ IL_001b: stelem.ref
+ IL_001c: dup
+ IL_001d: ldc.i4.2
+ IL_001e: ldtoken !!S
+ IL_0023: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_0028: stelem.ref
+ IL_0029: dup
+ IL_002a: ldc.i4.3
+ IL_002b: ldstr ", GI4"
+ IL_0030: stelem.ref
+ IL_0031: call string [mscorlib]System.String::Concat(object[])
+ IL_0036: call void [mscorlib]System.Console::WriteLine(string)
+ IL_003b: nop
+ IL_003c: ldarg.1
+ IL_003d: ldc.i4.2
+ IL_003e: newarr [mscorlib]System.Type
+ IL_0043: dup
+ IL_0044: ldc.i4.0
+ IL_0045: ldtoken !T
+ IL_004a: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_004f: stelem.ref
+ IL_0050: dup
+ IL_0051: ldc.i4.1
+ IL_0052: ldtoken !!S
+ IL_0057: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_005c: stelem.ref
+ IL_005d: stind.ref
+ IL_005e: ldc.i4.4
+ IL_005f: stloc.0
+ IL_0060: br.s IL_0062
+
+ IL_0062: ldloc.0
+ IL_0063: ret
+ } // end of method GI4`1::'GI1<T>.Func'
+} // end of class GI4`1
+
+.class private auto ansi beforefieldinit GI23Class`1<T>
+ extends [mscorlib]System.Object
+ implements class GI2`1<!T>,
+ class GI1`1<!T>,
+ class GI3`1<!T>
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method GI23Class`1::.ctor
+
+} // end of class GI23Class`1
+
+.class private auto ansi beforefieldinit GI4Class`1<T>
+ extends [mscorlib]System.Object
+ implements class GI4`1<!T>,
+ class GI2`1<!T>,
+ class GI1`1<!T>,
+ class GI3`1<!T>
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method GI4Class`1::.ctor
+
+} // end of class GI4Class`1
+
.class private auto ansi beforefieldinit Program
extends [mscorlib]System.Object
{
- .method public hidebysig static int32 Main() cil managed
+ .method public hidebysig static void Negative() cil managed
{
- .entrypoint
- // Code size 60 (0x3c)
+ // Code size 225 (0xe1)
.maxstack 2
.locals init (class FooClass V_0,
class IFoo V_1,
- int32 V_2)
+ class I47Class V_2,
+ class I1 V_3,
+ class GI23Class`1<object> V_4,
+ class GI1`1<object> V_5,
+ class [mscorlib]System.Exception V_6,
+ class [mscorlib]System.Exception V_7,
+ class [mscorlib]System.Type[] V_8,
+ class [mscorlib]System.Exception V_9)
IL_0000: nop
IL_0001: newobj instance void FooClass::.ctor()
IL_0006: stloc.0
@@ -150,28 +638,211 @@
IL_0018: callvirt instance int32 IFoo::Foo(int32)
IL_001d: pop
IL_001e: ldc.i4.0
- IL_001f: ldstr "Expecting exception"
+ IL_001f: ldstr "Expecting exception on Foo"
IL_0024: call void Test::Assert(bool,
string)
IL_0029: nop
IL_002a: nop
- IL_002b: leave.s IL_0032
+ IL_002b: leave.s IL_004a
} // end .try
catch [mscorlib]System.Exception
{
- IL_002d: pop
- IL_002e: nop
+ IL_002d: stloc.s V_6
IL_002f: nop
- IL_0030: leave.s IL_0032
+ IL_0030: ldstr "Exception caught: "
+ IL_0035: ldloc.s V_6
+ IL_0037: callvirt instance string [mscorlib]System.Object::ToString()
+ IL_003c: call string [mscorlib]System.String::Concat(string,
+ string)
+ IL_0041: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0046: nop
+ IL_0047: nop
+ IL_0048: leave.s IL_004a
} // end handler
- IL_0032: call int32 Test::Ret()
- IL_0037: stloc.2
- IL_0038: br.s IL_003a
+ IL_004a: newobj instance void I47Class::.ctor()
+ IL_004f: stloc.2
+ IL_0050: ldloc.2
+ IL_0051: stloc.3
+ IL_0052: ldstr "Calling I1.Func on I47Class - expecting exception"
+ IL_0057: call void [mscorlib]System.Console::WriteLine(string)
+ IL_005c: nop
+ .try
+ {
+ IL_005d: nop
+ IL_005e: ldloc.3
+ IL_005f: ldc.i4.s 10
+ IL_0061: callvirt instance int32 I1::Func(int32)
+ IL_0066: pop
+ IL_0067: ldc.i4.0
+ IL_0068: ldstr "Expecting exception on I47Class"
+ IL_006d: call void Test::Assert(bool,
+ string)
+ IL_0072: nop
+ IL_0073: nop
+ IL_0074: leave.s IL_0093
- IL_003a: ldloc.2
- IL_003b: ret
+ } // end .try
+ catch [mscorlib]System.Exception
+ {
+ IL_0076: stloc.s V_7
+ IL_0078: nop
+ IL_0079: ldstr "Exception caught: "
+ IL_007e: ldloc.s V_7
+ IL_0080: callvirt instance string [mscorlib]System.Object::ToString()
+ IL_0085: call string [mscorlib]System.String::Concat(string,
+ string)
+ IL_008a: call void [mscorlib]System.Console::WriteLine(string)
+ IL_008f: nop
+ IL_0090: nop
+ IL_0091: leave.s IL_0093
+
+ } // end handler
+ IL_0093: newobj instance void class GI23Class`1<object>::.ctor()
+ IL_0098: stloc.s V_4
+ IL_009a: ldloc.s V_4
+ IL_009c: stloc.s V_5
+ IL_009e: ldstr "Calling GI1<T>.Func on GI23Class<S> - expecting ex"
+ + "ception"
+ IL_00a3: call void [mscorlib]System.Console::WriteLine(string)
+ IL_00a8: nop
+ .try
+ {
+ IL_00a9: nop
+ IL_00aa: ldloc.s V_5
+ IL_00ac: ldloca.s V_8
+ IL_00ae: callvirt instance int32 class GI1`1<object>::Func<string>(class [mscorlib]System.Type[]&)
+ IL_00b3: pop
+ IL_00b4: ldc.i4.0
+ IL_00b5: ldstr "Expecting exception on GI23Class"
+ IL_00ba: call void Test::Assert(bool,
+ string)
+ IL_00bf: nop
+ IL_00c0: nop
+ IL_00c1: leave.s IL_00e0
+
+ } // end .try
+ catch [mscorlib]System.Exception
+ {
+ IL_00c3: stloc.s V_9
+ IL_00c5: nop
+ IL_00c6: ldstr "Exception caught: "
+ IL_00cb: ldloc.s V_9
+ IL_00cd: callvirt instance string [mscorlib]System.Object::ToString()
+ IL_00d2: call string [mscorlib]System.String::Concat(string,
+ string)
+ IL_00d7: call void [mscorlib]System.Console::WriteLine(string)
+ IL_00dc: nop
+ IL_00dd: nop
+ IL_00de: leave.s IL_00e0
+
+ } // end handler
+ IL_00e0: ret
+ } // end of method Program::Negative
+
+ .method public hidebysig static void Positive() cil managed
+ {
+ // Code size 189 (0xbd)
+ .maxstack 2
+ .locals init (class I4Class V_0,
+ class I1 V_1,
+ class I8Class V_2,
+ class GI4Class`1<object> V_3,
+ class [mscorlib]System.Type[] V_4,
+ class GI1`1<object> V_5)
+ IL_0000: nop
+ IL_0001: ldstr "Calling I1.Func on I4Class - expecting I4.Func"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: newobj instance void I4Class::.ctor()
+ IL_0011: stloc.0
+ IL_0012: ldloc.0
+ IL_0013: stloc.1
+ IL_0014: ldloc.1
+ IL_0015: ldc.i4.s 10
+ IL_0017: callvirt instance int32 I1::Func(int32)
+ IL_001c: ldc.i4.s 14
+ IL_001e: ceq
+ IL_0020: ldstr "Expecting I1.Func to land on I4.Func"
+ IL_0025: call void Test::Assert(bool,
+ string)
+ IL_002a: nop
+ IL_002b: ldstr "Calling I1.Func on I8Class - expecting I8.Func"
+ IL_0030: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0035: nop
+ IL_0036: newobj instance void I8Class::.ctor()
+ IL_003b: stloc.2
+ IL_003c: ldloc.2
+ IL_003d: stloc.1
+ IL_003e: ldloc.1
+ IL_003f: ldc.i4.s 10
+ IL_0041: callvirt instance int32 I1::Func(int32)
+ IL_0046: ldc.i4.s 18
+ IL_0048: ceq
+ IL_004a: ldstr "Expecting I1.Func to land on I8.Func"
+ IL_004f: call void Test::Assert(bool,
+ string)
+ IL_0054: nop
+ IL_0055: ldstr "Calling GI1.Func on GI4Class<object> - expecting G"
+ + "I4.Func<S>"
+ IL_005a: call void [mscorlib]System.Console::WriteLine(string)
+ IL_005f: nop
+ IL_0060: newobj instance void class GI4Class`1<object>::.ctor()
+ IL_0065: stloc.3
+ IL_0066: ldloc.3
+ IL_0067: stloc.s V_5
+ IL_0069: ldloc.s V_5
+ IL_006b: ldloca.s V_4
+ IL_006d: callvirt instance int32 class GI1`1<object>::Func<string>(class [mscorlib]System.Type[]&)
+ IL_0072: ldc.i4.4
+ IL_0073: ceq
+ IL_0075: ldstr "Expecting GI1<T>.Func to land on GII4<T>.Func<S>"
+ IL_007a: call void Test::Assert(bool,
+ string)
+ IL_007f: nop
+ IL_0080: ldloc.s V_4
+ IL_0082: ldc.i4.0
+ IL_0083: ldelem.ref
+ IL_0084: ldtoken [mscorlib]System.Object
+ IL_0089: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_008e: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type,
+ class [mscorlib]System.Type)
+ IL_0093: ldstr "T must be object"
+ IL_0098: call void Test::Assert(bool,
+ string)
+ IL_009d: nop
+ IL_009e: ldloc.s V_4
+ IL_00a0: ldc.i4.1
+ IL_00a1: ldelem.ref
+ IL_00a2: ldtoken [mscorlib]System.String
+ IL_00a7: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
+ IL_00ac: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type,
+ class [mscorlib]System.Type)
+ IL_00b1: ldstr "S must be string"
+ IL_00b6: call void Test::Assert(bool,
+ string)
+ IL_00bb: nop
+ IL_00bc: ret
+ } // end of method Program::Positive
+
+ .method public hidebysig static int32 Main() cil managed
+ {
+ .entrypoint
+ // Code size 23 (0x17)
+ .maxstack 1
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: call void Program::Negative()
+ IL_0006: nop
+ IL_0007: call void Program::Positive()
+ IL_000c: nop
+ IL_000d: call int32 Test::Ret()
+ IL_0012: stloc.0
+ IL_0013: br.s IL_0015
+
+ IL_0015: ldloc.0
+ IL_0016: ret
} // end of method Program::Main
.method public hidebysig specialname rtspecialname
diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.cs b/tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.cs
index 8f4b5d1021..0d4c119453 100755
--- a/tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.cs
+++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.cs
@@ -2,58 +2,291 @@ using System;
interface IFoo
{
- int Foo(int a);
+ int Foo1(int a); // { return a + 1 };
+ int Foo2(int a); // { return a + 2 };
+ int Foo3(int a);
+ int Foo4(int a);
+ int Foo5(int a);
+ int Foo6(int a);
+ int Foo7(int a);
+ int Foo8(int a);
+ int Foo9(int a);
}
-interface IBar
+interface IBar : IFoo
{
- int Bar(int b);
+ // @OVERRIDE
+ // IFoo.Foo1/2/3/4/5
+
+ int Bar1(int b); // { return a + 11; }
+ int Bar2(int b); // { return a + 22; }
+ int Bar3(int b); // { return a + 33; }
+ int Bar4(int b);
+ int Bar5(int b);
+ int Bar6(int b);
+ int Bar7(int b);
+ int Bar8(int b);
+ int Bar9(int b);
}
-interface IFooBar : IFoo, IBar
+interface IBlah : IBar
{
- int Foo(int a);
+ // @OVERRIDE IFoo.Foo6/7/8/9
+ // @OVERRIDE IBar.Bar6/7/8/9
+ int Blah1(int c);
+ int Blah2(int c);
+ int Blah3(int c);
}
-class Temp : IFoo
+class IBarImpl : IBar
{
- int IFoo.Foo(int a)
+ // @REMOVE all implementation
+ int IFoo.Foo1(int a)
{
- Console.WriteLine("At IFooBar::IFoo.Foo explicit methodimpl");
+ Console.WriteLine("At IIFoo.Foo1");
+ return a + 10;
+ }
+
+ int IFoo.Foo2(int a)
+ {
+ Console.WriteLine("At IIFoo.Foo1");
+ return a + 20;
+ }
+ int IFoo.Foo3(int a)
+ {
+ Console.WriteLine("At IIFoo.Foo1");
return a + 30;
}
+ int IFoo.Foo4(int a)
+ {
+ Console.WriteLine("At IIFoo.Foo1");
+ return a + 40;
+ }
+ int IFoo.Foo5(int a)
+ {
+ Console.WriteLine("At IIFoo.Foo1");
+ return a + 50;
+ }
+ int IFoo.Foo6(int a)
+ {
+ Console.WriteLine("At IIFoo.Foo1");
+ return a + 60;
+ }
+ int IFoo.Foo7(int a)
+ {
+ Console.WriteLine("At IIFoo.Foo1");
+ return a + 70;
+ }
+ int IFoo.Foo8(int a)
+ {
+ Console.WriteLine("At IIFoo.Foo1");
+ return a + 80;
+ }
+ int IFoo.Foo9(int a)
+ {
+ Console.WriteLine("At IIFoo.Foo1");
+ return a + 19;
+ }
+
+ int IBar.Bar1(int a)
+ {
+ Console.WriteLine("At IBar.Bar1");
+ return a + 110;
+ }
+
+ int IBar.Bar2(int a)
+ {
+ Console.WriteLine("At IBar.Bar1");
+ return a + 220;
+ }
+ int IBar.Bar3(int a)
+ {
+ Console.WriteLine("At IBar.Bar1");
+ return a + 330;
+ }
+ int IBar.Bar4(int a)
+ {
+ Console.WriteLine("At IBar.Bar1");
+ return a + 440;
+ }
+ int IBar.Bar5(int a)
+ {
+ Console.WriteLine("At IBar.Bar1");
+ return a + 550;
+ }
+ int IBar.Bar6(int a)
+ {
+ Console.WriteLine("At IBar.Bar1");
+ return a + 660;
+ }
+ int IBar.Bar7(int a)
+ {
+ Console.WriteLine("At IBar.Bar1");
+ return a + 770;
+ }
+ int IBar.Bar8(int a)
+ {
+ Console.WriteLine("At IBar.Bar1");
+ return a + 880;
+ }
+ int IBar.Bar9(int a)
+ {
+ Console.WriteLine("At IBar.Bar1");
+ return a + 990;
+ }
}
-class FooBar : IFooBar
+class IBlahImpl : IBarImpl, IBlah
{
- public int Foo(int a)
+ // @REMOVE all implementation
+ // @OVERRIDE IBlah2/3 with + 2220/3330
+ int IBlah.Blah1(int c)
+ {
+ Console.WriteLine("At IBlah.Blah1");
+ return c+111;
+ }
+
+ int IBlah.Blah2(int c)
{
- Console.WriteLine("At IFoo::Foo");
- return a+10;
+ Console.WriteLine("At IBlah.Blah2");
+ return c+222;
}
- public int Bar(int b)
+ int IBlah.Blah3(int c)
{
- Console.WriteLine("At IBar::Bar");
- return b+20;
+ Console.WriteLine("At IBlah.Blah3");
+ return c+333;
}
}
+interface IFooBarBlah : IFoo, IBar, IBlah
+{
+ // FooBarBlah1 .override IFoo.Foo1/IBar.Bar1/IBlah.Blah1 return 1+11111
+ // FooBarBlah2 .override IFoo.Foo2/IBar.Bar2/IBlah.Blah2 return i+22222
+ // FooBarBLah345 .override IFoo.Foo345/IBar.Bar345/IBlah.Blah3 return i+33333
+}
+
+class FooBarBlahImpl :
+ IBlahImpl, // @REMOVE
+ IFooBarBlah
+{
+
+}
+
class Program
{
public static int Main()
{
- FooBar fooBar = new FooBar();
- IFoo foo = (IFoo) fooBar;
- IBar bar = (IBar) fooBar;
+ SingleOverride();
+ MultiOverride();
+
+ return Test.Ret();
+ }
- Console.WriteLine("Calling IFoo.Foo on FooBar - expecting IFooBar::IFoo.Bar");
- Test.Assert(foo.Foo(10) == 40, "Calling IFoo.Foo on FooBar");
+ private static void SingleOverride()
+ {
+ IBarImpl barImpl = new IBarImpl();
+ IFoo foo = (IFoo) barImpl;
- Console.WriteLine("Calling IBar.Bar on FooBar - expecting IBar::Bar");
- Test.Assert(bar.Bar(10) == 30, "Calling IBar.Bar on FooBar");
+ Console.WriteLine("Calling IFoo.Foo methods on IBarImpl...");
- return Test.Ret();
+ Test.Assert(foo.Foo1(1) == 11, "Calling IFoo.Foo1 on IBarImpl");
+ Test.Assert(foo.Foo2(2) == 22, "Calling IFoo.Foo2 on IBarImpl");
+ Test.Assert(foo.Foo3(3) == 33, "Calling IFoo.Foo3 on IBarImpl");
+ Test.Assert(foo.Foo4(4) == 44, "Calling IFoo.Foo4 on IBarImpl");
+ Test.Assert(foo.Foo5(5) == 55, "Calling IFoo.Foo5 on IBarImpl");
+ Test.Assert(foo.Foo6(0) == 6, "Calling IFoo.Foo6 on IBarImpl");
+ Test.Assert(foo.Foo7(0) == 7, "Calling IFoo.Foo7 on IBarImpl");
+ Test.Assert(foo.Foo8(0) == 8, "Calling IFoo.Foo8 on IBarImpl");
+ Test.Assert(foo.Foo9(0) == 9, "Calling IFoo.Foo9 on IBarImpl");
+
+ IBar bar = (IBar) barImpl;
+
+ Console.WriteLine("Calling IBar.Bar methods on IBarImpl...");
+
+ Test.Assert(bar.Bar1(0) == 11, "Calling IBar.Bar1 on IBarImpl");
+ Test.Assert(bar.Bar2(0) == 22, "Calling IBar.Bar2 on IBarImpl");
+ Test.Assert(bar.Bar3(0) == 33, "Calling IBar.Bar3 on IBarImpl");
+ Test.Assert(bar.Bar4(0) == 44, "Calling IBar.Bar4 on IBarImpl");
+ Test.Assert(bar.Bar5(0) == 55, "Calling IBar.Bar5 on IBarImpl");
+ Test.Assert(bar.Bar6(0) == 66, "Calling IBar.Bar6 on IBarImpl");
+ Test.Assert(bar.Bar7(0) == 77, "Calling IBar.Bar7 on IBarImpl");
+ Test.Assert(bar.Bar8(0) == 88, "Calling IBar.Bar8 on IBarImpl");
+ Test.Assert(bar.Bar9(0) == 99, "Calling IBar.Bar9 on IBarImpl");
+
+ IBlahImpl blahImpl = new IBlahImpl();
+ foo = (IFoo) blahImpl;
+
+ Test.Assert(foo.Foo1(1) == 11, "Calling IFoo.Foo1 on IBlahImpl");
+ Test.Assert(foo.Foo2(2) == 22, "Calling IFoo.Foo2 on IBlahImpl");
+ Test.Assert(foo.Foo3(3) == 33, "Calling IFoo.Foo3 on IBlahImpl");
+ Test.Assert(foo.Foo4(4) == 44, "Calling IFoo.Foo4 on IBlahImpl");
+ Test.Assert(foo.Foo5(5) == 55, "Calling IFoo.Foo5 on IBlahImpl");
+ Test.Assert(foo.Foo6(6) == 66, "Calling IFoo.Foo6 on IBlahImpl");
+ Test.Assert(foo.Foo7(7) == 77, "Calling IFoo.Foo7 on IBlahImpl");
+ Test.Assert(foo.Foo8(8) == 88, "Calling IFoo.Foo8 on IBlahImpl");
+ Test.Assert(foo.Foo9(9) == 99, "Calling IFoo.Foo9 on IBlahImpl");
+
+ bar = (IBar) blahImpl;
+
+ Console.WriteLine("Calling IBar.Bar methods on IBlahImpl...");
+
+ Test.Assert(bar.Bar1(1) == 111, "Calling IBar.Bar1 on IBlahImpl");
+ Test.Assert(bar.Bar2(2) == 222, "Calling IBar.Bar2 on IBlahImpl");
+ Test.Assert(bar.Bar3(3) == 333, "Calling IBar.Bar3 on IBlahImpl");
+ Test.Assert(bar.Bar4(4) == 444, "Calling IBar.Bar4 on IBlahImpl");
+ Test.Assert(bar.Bar5(5) == 555, "Calling IBar.Bar5 on IBlahImpl");
+ Test.Assert(bar.Bar6(0) == 66, "Calling IBar.Bar6 on IBlahImpl");
+ Test.Assert(bar.Bar7(0) == 77, "Calling IBar.Bar7 on IBlahImpl");
+ Test.Assert(bar.Bar8(0) == 88, "Calling IBar.Bar8 on IBlahImpl");
+ Test.Assert(bar.Bar9(0) == 99, "Calling IBar.Bar9 on IBlahImpl");
+
+ IBlah blah = (IBlah) blahImpl;
+
+ Console.WriteLine("Calling IBlah.Blah methods on IBlahImpl...");
+
+ Test.Assert(blah.Blah1(0) == 111, "Calling IBlah.Blah1 on IBlahImpl");
+ Test.Assert(blah.Blah2(2) == 2222, "Calling IBlah.Blah1 on IBlahImpl");
+ Test.Assert(blah.Blah3(3) == 3333, "Calling IBlah.Blah1 on IBlahImpl");
+ }
+
+ private static void MultiOverride()
+ {
+ FooBarBlahImpl fooBarBlah = new FooBarBlahImpl();
+ IFoo foo = (IFoo) fooBarBlah;
+
+ Console.WriteLine("Calling IFoo.Foo methods on FooBarBlahImpl...");
+ Test.Assert(foo.Foo1(0) == 11111, "Calling IFoo.Foo1 on FooBarBlahImpl");
+ Test.Assert(foo.Foo2(0) == 22222, "Calling IFoo.Foo2 on FooBarBlahImpl");
+ Test.Assert(foo.Foo3(0) == 33333, "Calling IFoo.Foo3 on FooBarBlahImpl");
+ Test.Assert(foo.Foo4(0) == 33333, "Calling IFoo.Foo4 on FooBarBlahImpl");
+ Test.Assert(foo.Foo5(0) == 33333, "Calling IFoo.Foo5 on FooBarBlahImpl");
+ Test.Assert(foo.Foo6(6) == 66, "Calling IFoo.Foo6 on FooBarBlahImpl");
+ Test.Assert(foo.Foo7(7) == 77, "Calling IFoo.Foo7 on FooBarBlahImpl");
+ Test.Assert(foo.Foo8(8) == 88, "Calling IFoo.Foo8 on FooBarBlahImpl");
+ Test.Assert(foo.Foo9(9) == 99, "Calling IFoo.Foo9 on FooBarBlahImpl");
+
+ IBar bar = (IBar) fooBarBlah;
+
+ Console.WriteLine("Calling IBar.Bar methods on FooBarBlahImpl...");
+
+ Test.Assert(bar.Bar1(0) == 11111, "Calling IBar.Bar1 on FooBarBlahImpl");
+ Test.Assert(bar.Bar2(0) == 22222, "Calling IBar.Bar2 on FooBarBlahImpl");
+ Test.Assert(bar.Bar3(0) == 33333, "Calling IBar.Bar3 on FooBarBlahImpl");
+ Test.Assert(bar.Bar4(0) == 33333, "Calling IBar.Bar4 on FooBarBlahImpl");
+ Test.Assert(bar.Bar5(0) == 33333, "Calling IBar.Bar5 on FooBarBlahImpl");
+ Test.Assert(bar.Bar6(0) == 66, "Calling IBar.Bar6 on FooBarBlahImpl");
+ Test.Assert(bar.Bar7(0) == 77, "Calling IBar.Bar7 on FooBarBlahImpl");
+ Test.Assert(bar.Bar8(0) == 88, "Calling IBar.Bar8 on FooBarBlahImpl");
+ Test.Assert(bar.Bar9(0) == 99, "Calling IBar.Bar9 on FooBarBlahImpl");
+
+ IBlah blah = (IBlah) fooBarBlah;
+
+ Console.WriteLine("Calling IBlah.Blah methods on FooBarBlahImpl...");
+
+ Test.Assert(blah.Blah1(0) == 11111, "Calling IBlah.Blah1 on FooBarBlahImpl");
+ Test.Assert(blah.Blah2(0) == 22222, "Calling IBlah.Blah1 on FooBarBlahImpl");
+ Test.Assert(blah.Blah3(0) == 33333, "Calling IBlah.Blah1 on FooBarBlahImpl");
}
}
diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.il b/tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.il
index 6ab45f0164..7f9444283e 100644
--- a/tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.il
+++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.il
@@ -37,37 +37,403 @@
.class interface private abstract auto ansi IFoo
{
.method public hidebysig newslot virtual
- instance int32 Foo(int32 a) cil managed
+ instance int32 Foo1(int32 a) cil managed
{
// Code size 21 (0x15)
.maxstack 2
.locals init (int32 V_0)
IL_0000: nop
- IL_0001: ldstr "At IFoo::Foo"
+ IL_0001: ldstr "At IIFoo.Foo1"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ldarg.1
- IL_000d: ldc.i4.s 10
+ IL_000d: ldc.i4.s 1
IL_000f: add
IL_0010: stloc.0
IL_0011: br.s IL_0013
IL_0013: ldloc.0
- IL_0014: ret
- } // end of method IFoo::Foo
+ IL_0014: ret
+ } // end of method IFoo::Foo1
+
+ .method public hidebysig newslot virtual
+ instance int32 Foo2(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IFoo.Foo2"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 2
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IFoo::Foo2
+
+ .method public hidebysig newslot virtual
+ instance int32 Foo3(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IFoo.Foo3"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 3
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IFoo::Foo3
+
+ .method public hidebysig newslot virtual
+ instance int32 Foo4(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IFoo.Foo4"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 4
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IFoo::Foo4
+
+ .method public hidebysig newslot virtual
+ instance int32 Foo5(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IFoo.Foo5"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 5
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IFoo::Foo5
+
+ .method public hidebysig newslot virtual
+ instance int32 Foo6(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IFoo.Foo6"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 6
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IFoo::Foo6
+
+ .method public hidebysig newslot virtual
+ instance int32 Foo7(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IFoo.Foo7"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 7
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IFoo::Foo7
+
+ .method public hidebysig newslot virtual
+ instance int32 Foo8(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IFoo.Foo8"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 8
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IFoo::Foo8
+
+ .method public hidebysig newslot virtual
+ instance int32 Foo9(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IFoo.Foo9"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 9
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IFoo::Foo9
} // end of class IFoo
.class interface private abstract auto ansi IBar
+ implements IFoo
{
+ .method public hidebysig newslot virtual
+ instance int32 Bar1(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IIBar.Bar1"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 11
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBar::Bar1
+
+ .method public hidebysig newslot virtual
+ instance int32 Bar2(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar.Bar2"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 22
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBar::Bar2
+
.method public hidebysig newslot virtual
- instance int32 Bar(int32 b) cil managed
+ instance int32 Bar3(int32 a) cil managed
{
// Code size 21 (0x15)
.maxstack 2
.locals init (int32 V_0)
IL_0000: nop
- IL_0001: ldstr "At IBar::Bar"
+ IL_0001: ldstr "At IBar.Bar3"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 33
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBar::Bar3
+
+ .method public hidebysig newslot virtual
+ instance int32 Bar4(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar.Bar4"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 44
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBar::Bar4
+
+ .method public hidebysig newslot virtual
+ instance int32 Bar5(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar.Bar5"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 55
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBar::Bar5
+
+ .method public hidebysig newslot virtual
+ instance int32 Bar6(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar.Bar6"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 66
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBar::Bar6
+
+ .method public hidebysig newslot virtual
+ instance int32 Bar7(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar.Bar7"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 77
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBar::Bar7
+
+ .method public hidebysig newslot virtual
+ instance int32 Bar8(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar.Bar8"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 88
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBar::Bar8
+
+ .method public hidebysig newslot virtual
+ instance int32 Bar9(int32 a) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar.Bar9"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 99
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBar::Bar9
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Overriding IFoo
+ //////////////////////////////////////////////////////////////////////////////
+
+ .method private hidebysig newslot virtual final
+ instance int32 IFoo.Foo1(int32 a) cil managed
+ {
+ .override IFoo::Foo1
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar::IFoo.Foo1"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 10
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBar::IFoo.Foo1
+
+ .method private hidebysig newslot virtual final
+ instance int32 IFoo.Foo2(int32 a) cil managed
+ {
+ .override IFoo::Foo2
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar::IFoo.Foo2"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ldarg.1
@@ -78,42 +444,338 @@
IL_0013: ldloc.0
IL_0014: ret
- } // end of method IBar::Bar
+ } // end of method IBar::IFoo.Foo2
+ .method private hidebysig newslot virtual final
+ instance int32 IFoo.Foo3(int32 a) cil managed
+ {
+ .override IFoo::Foo3
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar::IFoo.Foo3"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 30
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBar::IFoo.Foo3
+
+ .method private hidebysig newslot virtual final
+ instance int32 IFoo.Foo4(int32 a) cil managed
+ {
+ .override IFoo::Foo4
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar::IFoo.Foo4"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 40
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBar::IFoo.Foo4
+
+ .method private hidebysig newslot virtual final
+ instance int32 IFoo.Foo5(int32 a) cil managed
+ {
+ .override IFoo::Foo5
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBar::IFoo.Foo5"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 50
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBar::IFoo.Foo5
} // end of class IBar
-.class interface private abstract auto ansi IFooBar
- implements IFoo,
- IBar
+.class interface private abstract auto ansi IBlah
+ implements IBar,
+ IFoo
{
+ .method public hidebysig newslot virtual
+ instance int32 Blah1(int32 c) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlah.Blah1"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4 111
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBlah::Blah1
+
+ .method public hidebysig newslot virtual
+ instance int32 Blah2(int32 c) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlah.Blah2"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4 222
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBlah::Blah2
+
+ .method public hidebysig newslot virtual
+ instance int32 Blah3(int32 c) cil managed
+ {
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlah.Blah3"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4 333
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBlah::Blah3
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Overriding IFoo
+ //////////////////////////////////////////////////////////////////////////////
+
.method private hidebysig newslot virtual final
- instance int32 IFoo.Foo(int32 a) cil managed
+ instance int32 IFoo.Foo6(int32 a) cil managed
{
- .override IFoo::Foo
+ .override IFoo::Foo6
// Code size 21 (0x15)
.maxstack 2
.locals init (int32 V_0)
IL_0000: nop
- IL_0001: ldstr "At IFooBar::IFoo.Foo explicit methodimpl"
+ IL_0001: ldstr "At IBlah::IFoo.Foo6"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ldarg.1
- IL_000d: ldc.i4.s 30
+ IL_000d: ldc.i4.s 60
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBlah::IFoo.Foo6
+
+ .method private hidebysig newslot virtual final
+ instance int32 IFoo.Foo7(int32 a) cil managed
+ {
+ .override IFoo::Foo7
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlah::IFoo.Foo7"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 70
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBlah::IFoo.Foo6
+
+ .method private hidebysig newslot virtual final
+ instance int32 IFoo.Foo8(int32 a) cil managed
+ {
+ .override IFoo::Foo8
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlah::IFoo.Foo8"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 80
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBlah::IFoo.Foo8
+
+ .method private hidebysig newslot virtual final
+ instance int32 IFoo.Foo9(int32 a) cil managed
+ {
+ .override IFoo::Foo9
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlah::IFoo.Foo9"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 90
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBlah::IFoo.Foo9
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Overriding IBar
+ //////////////////////////////////////////////////////////////////////////////
+
+ .method private hidebysig newslot virtual final
+ instance int32 IBar.Bar1(int32 a) cil managed
+ {
+ .override IBar::Bar1
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlah::IBar.Bar1"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4.s 110
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBlah::IBar.Bar1
+
+ .method private hidebysig newslot virtual final
+ instance int32 IBar.Bar2(int32 a) cil managed
+ {
+ .override IBar::Bar2
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlah::IBar.Bar2"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4 220
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBlah::IBar.Bar2
+
+ .method private hidebysig newslot virtual final
+ instance int32 IBar.Bar3(int32 a) cil managed
+ {
+ .override IBar::Bar3
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlah::IBar.Bar3"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4 330
IL_000f: add
IL_0010: stloc.0
IL_0011: br.s IL_0013
IL_0013: ldloc.0
IL_0014: ret
- } // end of method Temp::IFoo.Foo
+ } // end of method IBlah::IBar.Bar3
-} // end of class IFooBar
+ .method private hidebysig newslot virtual final
+ instance int32 IBar.Bar4(int32 a) cil managed
+ {
+ .override IBar::Bar4
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlah::IBar.Bar4"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4 440
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBlah::IBar.Bar4
+
+ .method private hidebysig newslot virtual final
+ instance int32 IBar.Bar5(int32 a) cil managed
+ {
+ .override IBar::Bar5
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlah::IBar.Bar5"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4 550
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
-.class private auto ansi beforefieldinit FooBar
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBlah::IBar.Bar5
+} // end of class IBlah
+
+.class private auto ansi beforefieldinit IBarImpl
extends [mscorlib]System.Object
- implements IFooBar,
- IFoo,
- IBar
+ implements IBar,
+ IFoo
{
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
@@ -124,9 +786,167 @@
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
- } // end of method FooBar::.ctor
+ } // end of method IBarImpl::.ctor
-} // end of class FooBar
+} // end of class IBarImpl
+
+.class private auto ansi beforefieldinit IBlahImpl
+ extends IBarImpl
+ implements IBlah,
+ IBar,
+ IFoo
+{
+ .method private hidebysig newslot virtual final
+ instance int32 IBlah.Blah2(int32 c) cil managed
+ {
+ .override IBlah::Blah2
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlahImpl::IBlah.Blah2"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4 2220
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBlahImpl::IBlah.Blah2
+
+ .method private hidebysig newslot virtual final
+ instance int32 IBlah.Blah3(int32 c) cil managed
+ {
+ .override IBlah::Blah3
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IBlahImpl::IBlah.Blah2"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4 3330
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IBlahImpl::IBlah.Blah3
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void IBarImpl::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method IBlahImpl::.ctor
+
+} // end of class IBlahImpl
+
+.class interface private abstract auto ansi IFooBarBlah
+ implements IFoo,
+ IBar,
+ IBlah
+{
+ .method private hidebysig newslot virtual final
+ instance int32 IFooBarBlah.FooBarBlah1(int32 c) cil managed
+ {
+ .override IFoo::Foo1
+ .override IBar::Bar1
+ .override IBlah::Blah1
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IFooBarBlah.FooBarBlah1"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4 11111
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IFooBarBlah.FooBarBlah1
+ .method private hidebysig newslot virtual final
+ instance int32 IFooBarBlah.FooBarBlah2(int32 c) cil managed
+ {
+ .override IFoo::Foo2
+ .override IBar::Bar2
+ .override IBlah::Blah2
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IFooBarBlah.FooBarBlah2"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4 22222
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IFooBarBlah.FooBarBlah1
+
+ .method private hidebysig newslot virtual final
+ instance int32 IFooBarBlah.FooBarBlah3(int32 c) cil managed
+ {
+ .override IFoo::Foo3
+ .override IFoo::Foo4
+ .override IFoo::Foo5
+ .override IBar::Bar3
+ .override IBar::Bar4
+ .override IBar::Bar5
+ .override IBlah::Blah3
+ // Code size 21 (0x15)
+ .maxstack 2
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: ldstr "At IFooBarBlah.FooBarBlah3"
+ IL_0006: call void [mscorlib]System.Console::WriteLine(string)
+ IL_000b: nop
+ IL_000c: ldarg.1
+ IL_000d: ldc.i4 33333
+ IL_000f: add
+ IL_0010: stloc.0
+ IL_0011: br.s IL_0013
+
+ IL_0013: ldloc.0
+ IL_0014: ret
+ } // end of method IFooBarBlah.FooBarBlah3
+} // end of class IFooBarBlah
+
+.class private auto ansi beforefieldinit FooBarBlahImpl
+ implements IFooBarBlah,
+ IFoo,
+ IBar,
+ IBlah
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 8 (0x8)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void IBlahImpl::.ctor()
+ IL_0006: nop
+ IL_0007: ret
+ } // end of method FooBarBlahImpl::.ctor
+
+} // end of class FooBarBlahImpl
.class private auto ansi beforefieldinit Program
extends [mscorlib]System.Object
@@ -134,51 +954,629 @@
.method public hidebysig static int32 Main() cil managed
{
.entrypoint
- // Code size 89 (0x59)
+ // Code size 23 (0x17)
+ .maxstack 1
+ .locals init (int32 V_0)
+ IL_0000: nop
+ IL_0001: call void Program::SingleOverride()
+ IL_0006: nop
+ IL_0007: call void Program::MultiOverride()
+ IL_000c: nop
+ IL_000d: call int32 Test::Ret()
+ IL_0012: stloc.0
+ IL_0013: br.s IL_0015
+
+ IL_0015: ldloc.0
+ IL_0016: ret
+ } // end of method Program::Main
+
+ .method private hidebysig static void SingleOverride() cil managed
+ {
+ // Code size 946 (0x3b2)
.maxstack 2
- .locals init (class FooBar V_0,
+ .locals init (class IBarImpl V_0,
class IFoo V_1,
class IBar V_2,
- int32 V_3)
+ class IBlahImpl V_3,
+ class IBlah V_4)
IL_0000: nop
- IL_0001: newobj instance void FooBar::.ctor()
+ IL_0001: newobj instance void IBarImpl::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: stloc.1
- IL_0009: ldloc.0
- IL_000a: stloc.2
- IL_000b: ldstr "Calling IFoo.Foo on FooBar - expecting IFooBar::IF"
- + "oo.Bar"
- IL_0010: call void [mscorlib]System.Console::WriteLine(string)
- IL_0015: nop
- IL_0016: ldloc.1
- IL_0017: ldc.i4.s 10
- IL_0019: callvirt instance int32 IFoo::Foo(int32)
- IL_001e: ldc.i4.s 40
+ IL_0009: ldstr "Calling IFoo.Foo methods on IBarImpl..."
+ IL_000e: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0013: nop
+ IL_0014: ldloc.1
+ IL_0015: ldc.i4.1
+ IL_0016: callvirt instance int32 IFoo::Foo1(int32)
+ IL_001b: ldc.i4.s 11
+ IL_001d: ceq
+ IL_001f: ldstr "Calling IFoo.Foo1 on IBarImpl"
+ IL_0024: call void Test::Assert(bool,
+ string)
+ IL_0029: nop
+ IL_002a: ldloc.1
+ IL_002b: ldc.i4.2
+ IL_002c: callvirt instance int32 IFoo::Foo2(int32)
+ IL_0031: ldc.i4.s 22
+ IL_0033: ceq
+ IL_0035: ldstr "Calling IFoo.Foo2 on IBarImpl"
+ IL_003a: call void Test::Assert(bool,
+ string)
+ IL_003f: nop
+ IL_0040: ldloc.1
+ IL_0041: ldc.i4.3
+ IL_0042: callvirt instance int32 IFoo::Foo3(int32)
+ IL_0047: ldc.i4.s 33
+ IL_0049: ceq
+ IL_004b: ldstr "Calling IFoo.Foo3 on IBarImpl"
+ IL_0050: call void Test::Assert(bool,
+ string)
+ IL_0055: nop
+ IL_0056: ldloc.1
+ IL_0057: ldc.i4.4
+ IL_0058: callvirt instance int32 IFoo::Foo4(int32)
+ IL_005d: ldc.i4.s 44
+ IL_005f: ceq
+ IL_0061: ldstr "Calling IFoo.Foo4 on IBarImpl"
+ IL_0066: call void Test::Assert(bool,
+ string)
+ IL_006b: nop
+ IL_006c: ldloc.1
+ IL_006d: ldc.i4.5
+ IL_006e: callvirt instance int32 IFoo::Foo5(int32)
+ IL_0073: ldc.i4.s 55
+ IL_0075: ceq
+ IL_0077: ldstr "Calling IFoo.Foo5 on IBarImpl"
+ IL_007c: call void Test::Assert(bool,
+ string)
+ IL_0081: nop
+ IL_0082: ldloc.1
+ IL_0083: ldc.i4.0
+ IL_0084: callvirt instance int32 IFoo::Foo6(int32)
+ IL_0089: ldc.i4.6
+ IL_008a: ceq
+ IL_008c: ldstr "Calling IFoo.Foo6 on IBarImpl"
+ IL_0091: call void Test::Assert(bool,
+ string)
+ IL_0096: nop
+ IL_0097: ldloc.1
+ IL_0098: ldc.i4.0
+ IL_0099: callvirt instance int32 IFoo::Foo7(int32)
+ IL_009e: ldc.i4.7
+ IL_009f: ceq
+ IL_00a1: ldstr "Calling IFoo.Foo7 on IBarImpl"
+ IL_00a6: call void Test::Assert(bool,
+ string)
+ IL_00ab: nop
+ IL_00ac: ldloc.1
+ IL_00ad: ldc.i4.0
+ IL_00ae: callvirt instance int32 IFoo::Foo8(int32)
+ IL_00b3: ldc.i4.8
+ IL_00b4: ceq
+ IL_00b6: ldstr "Calling IFoo.Foo8 on IBarImpl"
+ IL_00bb: call void Test::Assert(bool,
+ string)
+ IL_00c0: nop
+ IL_00c1: ldloc.1
+ IL_00c2: ldc.i4.0
+ IL_00c3: callvirt instance int32 IFoo::Foo9(int32)
+ IL_00c8: ldc.i4.s 9
+ IL_00ca: ceq
+ IL_00cc: ldstr "Calling IFoo.Foo9 on IBarImpl"
+ IL_00d1: call void Test::Assert(bool,
+ string)
+ IL_00d6: nop
+ IL_00d7: ldloc.0
+ IL_00d8: stloc.2
+ IL_00d9: ldstr "Calling IBar.Bar methods on IBarImpl..."
+ IL_00de: call void [mscorlib]System.Console::WriteLine(string)
+ IL_00e3: nop
+ IL_00e4: ldloc.2
+ IL_00e5: ldc.i4.0
+ IL_00e6: callvirt instance int32 IBar::Bar1(int32)
+ IL_00eb: ldc.i4.s 11
+ IL_00ed: ceq
+ IL_00ef: ldstr "Calling IBar.Bar1 on IBarImpl"
+ IL_00f4: call void Test::Assert(bool,
+ string)
+ IL_00f9: nop
+ IL_00fa: ldloc.2
+ IL_00fb: ldc.i4.0
+ IL_00fc: callvirt instance int32 IBar::Bar2(int32)
+ IL_0101: ldc.i4.s 22
+ IL_0103: ceq
+ IL_0105: ldstr "Calling IBar.Bar2 on IBarImpl"
+ IL_010a: call void Test::Assert(bool,
+ string)
+ IL_010f: nop
+ IL_0110: ldloc.2
+ IL_0111: ldc.i4.0
+ IL_0112: callvirt instance int32 IBar::Bar3(int32)
+ IL_0117: ldc.i4.s 33
+ IL_0119: ceq
+ IL_011b: ldstr "Calling IBar.Bar3 on IBarImpl"
+ IL_0120: call void Test::Assert(bool,
+ string)
+ IL_0125: nop
+ IL_0126: ldloc.2
+ IL_0127: ldc.i4.0
+ IL_0128: callvirt instance int32 IBar::Bar4(int32)
+ IL_012d: ldc.i4.s 44
+ IL_012f: ceq
+ IL_0131: ldstr "Calling IBar.Bar4 on IBarImpl"
+ IL_0136: call void Test::Assert(bool,
+ string)
+ IL_013b: nop
+ IL_013c: ldloc.2
+ IL_013d: ldc.i4.0
+ IL_013e: callvirt instance int32 IBar::Bar5(int32)
+ IL_0143: ldc.i4.s 55
+ IL_0145: ceq
+ IL_0147: ldstr "Calling IBar.Bar5 on IBarImpl"
+ IL_014c: call void Test::Assert(bool,
+ string)
+ IL_0151: nop
+ IL_0152: ldloc.2
+ IL_0153: ldc.i4.0
+ IL_0154: callvirt instance int32 IBar::Bar6(int32)
+ IL_0159: ldc.i4.s 66
+ IL_015b: ceq
+ IL_015d: ldstr "Calling IBar.Bar6 on IBarImpl"
+ IL_0162: call void Test::Assert(bool,
+ string)
+ IL_0167: nop
+ IL_0168: ldloc.2
+ IL_0169: ldc.i4.0
+ IL_016a: callvirt instance int32 IBar::Bar7(int32)
+ IL_016f: ldc.i4.s 77
+ IL_0171: ceq
+ IL_0173: ldstr "Calling IBar.Bar7 on IBarImpl"
+ IL_0178: call void Test::Assert(bool,
+ string)
+ IL_017d: nop
+ IL_017e: ldloc.2
+ IL_017f: ldc.i4.0
+ IL_0180: callvirt instance int32 IBar::Bar8(int32)
+ IL_0185: ldc.i4.s 88
+ IL_0187: ceq
+ IL_0189: ldstr "Calling IBar.Bar8 on IBarImpl"
+ IL_018e: call void Test::Assert(bool,
+ string)
+ IL_0193: nop
+ IL_0194: ldloc.2
+ IL_0195: ldc.i4.0
+ IL_0196: callvirt instance int32 IBar::Bar9(int32)
+ IL_019b: ldc.i4.s 99
+ IL_019d: ceq
+ IL_019f: ldstr "Calling IBar.Bar9 on IBarImpl"
+ IL_01a4: call void Test::Assert(bool,
+ string)
+ IL_01a9: nop
+ IL_01aa: newobj instance void IBlahImpl::.ctor()
+ IL_01af: stloc.3
+ IL_01b0: ldloc.3
+ IL_01b1: stloc.1
+ IL_01b2: ldloc.1
+ IL_01b3: ldc.i4.1
+ IL_01b4: callvirt instance int32 IFoo::Foo1(int32)
+ IL_01b9: ldc.i4.s 11
+ IL_01bb: ceq
+ IL_01bd: ldstr "Calling IFoo.Foo1 on IBlahImpl"
+ IL_01c2: call void Test::Assert(bool,
+ string)
+ IL_01c7: nop
+ IL_01c8: ldloc.1
+ IL_01c9: ldc.i4.2
+ IL_01ca: callvirt instance int32 IFoo::Foo2(int32)
+ IL_01cf: ldc.i4.s 22
+ IL_01d1: ceq
+ IL_01d3: ldstr "Calling IFoo.Foo2 on IBlahImpl"
+ IL_01d8: call void Test::Assert(bool,
+ string)
+ IL_01dd: nop
+ IL_01de: ldloc.1
+ IL_01df: ldc.i4.3
+ IL_01e0: callvirt instance int32 IFoo::Foo3(int32)
+ IL_01e5: ldc.i4.s 33
+ IL_01e7: ceq
+ IL_01e9: ldstr "Calling IFoo.Foo3 on IBlahImpl"
+ IL_01ee: call void Test::Assert(bool,
+ string)
+ IL_01f3: nop
+ IL_01f4: ldloc.1
+ IL_01f5: ldc.i4.4
+ IL_01f6: callvirt instance int32 IFoo::Foo4(int32)
+ IL_01fb: ldc.i4.s 44
+ IL_01fd: ceq
+ IL_01ff: ldstr "Calling IFoo.Foo4 on IBlahImpl"
+ IL_0204: call void Test::Assert(bool,
+ string)
+ IL_0209: nop
+ IL_020a: ldloc.1
+ IL_020b: ldc.i4.5
+ IL_020c: callvirt instance int32 IFoo::Foo5(int32)
+ IL_0211: ldc.i4.s 55
+ IL_0213: ceq
+ IL_0215: ldstr "Calling IFoo.Foo5 on IBlahImpl"
+ IL_021a: call void Test::Assert(bool,
+ string)
+ IL_021f: nop
+ IL_0220: ldloc.1
+ IL_0221: ldc.i4.6
+ IL_0222: callvirt instance int32 IFoo::Foo6(int32)
+ IL_0227: ldc.i4.s 66
+ IL_0229: ceq
+ IL_022b: ldstr "Calling IFoo.Foo6 on IBlahImpl"
+ IL_0230: call void Test::Assert(bool,
+ string)
+ IL_0235: nop
+ IL_0236: ldloc.1
+ IL_0237: ldc.i4.7
+ IL_0238: callvirt instance int32 IFoo::Foo7(int32)
+ IL_023d: ldc.i4.s 77
+ IL_023f: ceq
+ IL_0241: ldstr "Calling IFoo.Foo7 on IBlahImpl"
+ IL_0246: call void Test::Assert(bool,
+ string)
+ IL_024b: nop
+ IL_024c: ldloc.1
+ IL_024d: ldc.i4.8
+ IL_024e: callvirt instance int32 IFoo::Foo8(int32)
+ IL_0253: ldc.i4.s 88
+ IL_0255: ceq
+ IL_0257: ldstr "Calling IFoo.Foo8 on IBlahImpl"
+ IL_025c: call void Test::Assert(bool,
+ string)
+ IL_0261: nop
+ IL_0262: ldloc.1
+ IL_0263: ldc.i4.s 9
+ IL_0265: callvirt instance int32 IFoo::Foo9(int32)
+ IL_026a: ldc.i4.s 99
+ IL_026c: ceq
+ IL_026e: ldstr "Calling IFoo.Foo9 on IBlahImpl"
+ IL_0273: call void Test::Assert(bool,
+ string)
+ IL_0278: nop
+ IL_0279: ldloc.3
+ IL_027a: stloc.2
+ IL_027b: ldstr "Calling IBar.Bar methods on IBlahImpl..."
+ IL_0280: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0285: nop
+ IL_0286: ldloc.2
+ IL_0287: ldc.i4.1
+ IL_0288: callvirt instance int32 IBar::Bar1(int32)
+ IL_028d: ldc.i4.s 111
+ IL_028f: ceq
+ IL_0291: ldstr "Calling IBar.Bar1 on IBlahImpl"
+ IL_0296: call void Test::Assert(bool,
+ string)
+ IL_029b: nop
+ IL_029c: ldloc.2
+ IL_029d: ldc.i4.2
+ IL_029e: callvirt instance int32 IBar::Bar2(int32)
+ IL_02a3: ldc.i4 0xde
+ IL_02a8: ceq
+ IL_02aa: ldstr "Calling IBar.Bar2 on IBlahImpl"
+ IL_02af: call void Test::Assert(bool,
+ string)
+ IL_02b4: nop
+ IL_02b5: ldloc.2
+ IL_02b6: ldc.i4.3
+ IL_02b7: callvirt instance int32 IBar::Bar3(int32)
+ IL_02bc: ldc.i4 0x14d
+ IL_02c1: ceq
+ IL_02c3: ldstr "Calling IBar.Bar3 on IBlahImpl"
+ IL_02c8: call void Test::Assert(bool,
+ string)
+ IL_02cd: nop
+ IL_02ce: ldloc.2
+ IL_02cf: ldc.i4.4
+ IL_02d0: callvirt instance int32 IBar::Bar4(int32)
+ IL_02d5: ldc.i4 0x1bc
+ IL_02da: ceq
+ IL_02dc: ldstr "Calling IBar.Bar4 on IBlahImpl"
+ IL_02e1: call void Test::Assert(bool,
+ string)
+ IL_02e6: nop
+ IL_02e7: ldloc.2
+ IL_02e8: ldc.i4.5
+ IL_02e9: callvirt instance int32 IBar::Bar5(int32)
+ IL_02ee: ldc.i4 0x22b
+ IL_02f3: ceq
+ IL_02f5: ldstr "Calling IBar.Bar5 on IBlahImpl"
+ IL_02fa: call void Test::Assert(bool,
+ string)
+ IL_02ff: nop
+ IL_0300: ldloc.2
+ IL_0301: ldc.i4.0
+ IL_0302: callvirt instance int32 IBar::Bar6(int32)
+ IL_0307: ldc.i4.s 66
+ IL_0309: ceq
+ IL_030b: ldstr "Calling IBar.Bar6 on IBlahImpl"
+ IL_0310: call void Test::Assert(bool,
+ string)
+ IL_0315: nop
+ IL_0316: ldloc.2
+ IL_0317: ldc.i4.0
+ IL_0318: callvirt instance int32 IBar::Bar7(int32)
+ IL_031d: ldc.i4.s 77
+ IL_031f: ceq
+ IL_0321: ldstr "Calling IBar.Bar7 on IBlahImpl"
+ IL_0326: call void Test::Assert(bool,
+ string)
+ IL_032b: nop
+ IL_032c: ldloc.2
+ IL_032d: ldc.i4.0
+ IL_032e: callvirt instance int32 IBar::Bar8(int32)
+ IL_0333: ldc.i4.s 88
+ IL_0335: ceq
+ IL_0337: ldstr "Calling IBar.Bar8 on IBlahImpl"
+ IL_033c: call void Test::Assert(bool,
+ string)
+ IL_0341: nop
+ IL_0342: ldloc.2
+ IL_0343: ldc.i4.0
+ IL_0344: callvirt instance int32 IBar::Bar9(int32)
+ IL_0349: ldc.i4.s 99
+ IL_034b: ceq
+ IL_034d: ldstr "Calling IBar.Bar9 on IBlahImpl"
+ IL_0352: call void Test::Assert(bool,
+ string)
+ IL_0357: nop
+ IL_0358: ldloc.3
+ IL_0359: stloc.s V_4
+ IL_035b: ldstr "Calling IBlah.Blah methods on IBlahImpl..."
+ IL_0360: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0365: nop
+ IL_0366: ldloc.s V_4
+ IL_0368: ldc.i4.0
+ IL_0369: callvirt instance int32 IBlah::Blah1(int32)
+ IL_036e: ldc.i4.s 111
+ IL_0370: ceq
+ IL_0372: ldstr "Calling IBlah.Blah1 on IBlahImpl"
+ IL_0377: call void Test::Assert(bool,
+ string)
+ IL_037c: nop
+ IL_037d: ldloc.s V_4
+ IL_037f: ldc.i4.2
+ IL_0380: callvirt instance int32 IBlah::Blah2(int32)
+ IL_0385: ldc.i4 0x8ae
+ IL_038a: ceq
+ IL_038c: ldstr "Calling IBlah.Blah1 on IBlahImpl"
+ IL_0391: call void Test::Assert(bool,
+ string)
+ IL_0396: nop
+ IL_0397: ldloc.s V_4
+ IL_0399: ldc.i4.3
+ IL_039a: callvirt instance int32 IBlah::Blah3(int32)
+ IL_039f: ldc.i4 0xd05
+ IL_03a4: ceq
+ IL_03a6: ldstr "Calling IBlah.Blah1 on IBlahImpl"
+ IL_03ab: call void Test::Assert(bool,
+ string)
+ IL_03b0: nop
+ IL_03b1: ret
+ } // end of method Program::SingleOverride
+
+ .method private hidebysig static void MultiOverride() cil managed
+ {
+ // Code size 549 (0x225)
+ .maxstack 2
+ .locals init (class FooBarBlahImpl V_0,
+ class IFoo V_1,
+ class IBar V_2,
+ class IBlah V_3)
+ IL_0000: nop
+ IL_0001: newobj instance void FooBarBlahImpl::.ctor()
+ IL_0006: stloc.0
+ IL_0007: ldloc.0
+ IL_0008: stloc.1
+ IL_0009: ldstr "Calling IFoo.Foo methods on FooBarBlahImpl..."
+ IL_000e: call void [mscorlib]System.Console::WriteLine(string)
+ IL_0013: nop
+ IL_0014: ldloc.1
+ IL_0015: ldc.i4.0
+ IL_0016: callvirt instance int32 IFoo::Foo1(int32)
+ IL_001b: ldc.i4 0x2b67
IL_0020: ceq
- IL_0022: ldstr "Calling IFoo.Foo on FooBar"
+ IL_0022: ldstr "Calling IFoo.Foo1 on FooBarBlahImpl"
IL_0027: call void Test::Assert(bool,
string)
IL_002c: nop
- IL_002d: ldstr "Calling IBar.Bar on FooBar - expecting IBar::Bar"
- IL_0032: call void [mscorlib]System.Console::WriteLine(string)
- IL_0037: nop
- IL_0038: ldloc.2
- IL_0039: ldc.i4.s 10
- IL_003b: callvirt instance int32 IBar::Bar(int32)
- IL_0040: ldc.i4.s 30
- IL_0042: ceq
- IL_0044: ldstr "Calling IBar.Bar on FooBar"
- IL_0049: call void Test::Assert(bool,
- string)
- IL_004e: nop
- IL_004f: call int32 Test::Ret()
- IL_0054: stloc.3
- IL_0055: br.s IL_0057
-
- IL_0057: ldloc.3
- IL_0058: ret
- } // end of method Program::Main
+ IL_002d: ldloc.1
+ IL_002e: ldc.i4.0
+ IL_002f: callvirt instance int32 IFoo::Foo2(int32)
+ IL_0034: ldc.i4 0x56ce
+ IL_0039: ceq
+ IL_003b: ldstr "Calling IFoo.Foo2 on FooBarBlahImpl"
+ IL_0040: call void Test::Assert(bool,
+ string)
+ IL_0045: nop
+ IL_0046: ldloc.1
+ IL_0047: ldc.i4.0
+ IL_0048: callvirt instance int32 IFoo::Foo3(int32)
+ IL_004d: ldc.i4 0x8235
+ IL_0052: ceq
+ IL_0054: ldstr "Calling IFoo.Foo3 on FooBarBlahImpl"
+ IL_0059: call void Test::Assert(bool,
+ string)
+ IL_005e: nop
+ IL_005f: ldloc.1
+ IL_0060: ldc.i4.0
+ IL_0061: callvirt instance int32 IFoo::Foo4(int32)
+ IL_0066: ldc.i4 0x8235
+ IL_006b: ceq
+ IL_006d: ldstr "Calling IFoo.Foo4 on FooBarBlahImpl"
+ IL_0072: call void Test::Assert(bool,
+ string)
+ IL_0077: nop
+ IL_0078: ldloc.1
+ IL_0079: ldc.i4.0
+ IL_007a: callvirt instance int32 IFoo::Foo5(int32)
+ IL_007f: ldc.i4 0x8235
+ IL_0084: ceq
+ IL_0086: ldstr "Calling IFoo.Foo5 on FooBarBlahImpl"
+ IL_008b: call void Test::Assert(bool,
+ string)
+ IL_0090: nop
+ IL_0091: ldloc.1
+ IL_0092: ldc.i4.6
+ IL_0093: callvirt instance int32 IFoo::Foo6(int32)
+ IL_0098: ldc.i4.s 66
+ IL_009a: ceq
+ IL_009c: ldstr "Calling IFoo.Foo6 on FooBarBlahImpl"
+ IL_00a1: call void Test::Assert(bool,
+ string)
+ IL_00a6: nop
+ IL_00a7: ldloc.1
+ IL_00a8: ldc.i4.7
+ IL_00a9: callvirt instance int32 IFoo::Foo7(int32)
+ IL_00ae: ldc.i4.s 77
+ IL_00b0: ceq
+ IL_00b2: ldstr "Calling IFoo.Foo7 on FooBarBlahImpl"
+ IL_00b7: call void Test::Assert(bool,
+ string)
+ IL_00bc: nop
+ IL_00bd: ldloc.1
+ IL_00be: ldc.i4.8
+ IL_00bf: callvirt instance int32 IFoo::Foo8(int32)
+ IL_00c4: ldc.i4.s 88
+ IL_00c6: ceq
+ IL_00c8: ldstr "Calling IFoo.Foo8 on FooBarBlahImpl"
+ IL_00cd: call void Test::Assert(bool,
+ string)
+ IL_00d2: nop
+ IL_00d3: ldloc.1
+ IL_00d4: ldc.i4.s 9
+ IL_00d6: callvirt instance int32 IFoo::Foo9(int32)
+ IL_00db: ldc.i4.s 99
+ IL_00dd: ceq
+ IL_00df: ldstr "Calling IFoo.Foo9 on FooBarBlahImpl"
+ IL_00e4: call void Test::Assert(bool,
+ string)
+ IL_00e9: nop
+ IL_00ea: ldloc.0
+ IL_00eb: stloc.2
+ IL_00ec: ldstr "Calling IBar.Bar methods on FooBarBlahImpl..."
+ IL_00f1: call void [mscorlib]System.Console::WriteLine(string)
+ IL_00f6: nop
+ IL_00f7: ldloc.2
+ IL_00f8: ldc.i4.0
+ IL_00f9: callvirt instance int32 IBar::Bar1(int32)
+ IL_00fe: ldc.i4 0x2b67
+ IL_0103: ceq
+ IL_0105: ldstr "Calling IBar.Bar1 on FooBarBlahImpl"
+ IL_010a: call void Test::Assert(bool,
+ string)
+ IL_010f: nop
+ IL_0110: ldloc.2
+ IL_0111: ldc.i4.0
+ IL_0112: callvirt instance int32 IBar::Bar2(int32)
+ IL_0117: ldc.i4 0x56ce
+ IL_011c: ceq
+ IL_011e: ldstr "Calling IBar.Bar2 on FooBarBlahImpl"
+ IL_0123: call void Test::Assert(bool,
+ string)
+ IL_0128: nop
+ IL_0129: ldloc.2
+ IL_012a: ldc.i4.0
+ IL_012b: callvirt instance int32 IBar::Bar3(int32)
+ IL_0130: ldc.i4 0x8235
+ IL_0135: ceq
+ IL_0137: ldstr "Calling IBar.Bar3 on FooBarBlahImpl"
+ IL_013c: call void Test::Assert(bool,
+ string)
+ IL_0141: nop
+ IL_0142: ldloc.2
+ IL_0143: ldc.i4.0
+ IL_0144: callvirt instance int32 IBar::Bar4(int32)
+ IL_0149: ldc.i4 0x8235
+ IL_014e: ceq
+ IL_0150: ldstr "Calling IBar.Bar4 on FooBarBlahImpl"
+ IL_0155: call void Test::Assert(bool,
+ string)
+ IL_015a: nop
+ IL_015b: ldloc.2
+ IL_015c: ldc.i4.0
+ IL_015d: callvirt instance int32 IBar::Bar5(int32)
+ IL_0162: ldc.i4 0x8235
+ IL_0167: ceq
+ IL_0169: ldstr "Calling IBar.Bar5 on FooBarBlahImpl"
+ IL_016e: call void Test::Assert(bool,
+ string)
+ IL_0173: nop
+ IL_0174: ldloc.2
+ IL_0175: ldc.i4.0
+ IL_0176: callvirt instance int32 IBar::Bar6(int32)
+ IL_017b: ldc.i4.s 66
+ IL_017d: ceq
+ IL_017f: ldstr "Calling IBar.Bar6 on FooBarBlahImpl"
+ IL_0184: call void Test::Assert(bool,
+ string)
+ IL_0189: nop
+ IL_018a: ldloc.2
+ IL_018b: ldc.i4.0
+ IL_018c: callvirt instance int32 IBar::Bar7(int32)
+ IL_0191: ldc.i4.s 77
+ IL_0193: ceq
+ IL_0195: ldstr "Calling IBar.Bar7 on FooBarBlahImpl"
+ IL_019a: call void Test::Assert(bool,
+ string)
+ IL_019f: nop
+ IL_01a0: ldloc.2
+ IL_01a1: ldc.i4.0
+ IL_01a2: callvirt instance int32 IBar::Bar8(int32)
+ IL_01a7: ldc.i4.s 88
+ IL_01a9: ceq
+ IL_01ab: ldstr "Calling IBar.Bar8 on FooBarBlahImpl"
+ IL_01b0: call void Test::Assert(bool,
+ string)
+ IL_01b5: nop
+ IL_01b6: ldloc.2
+ IL_01b7: ldc.i4.0
+ IL_01b8: callvirt instance int32 IBar::Bar9(int32)
+ IL_01bd: ldc.i4.s 99
+ IL_01bf: ceq
+ IL_01c1: ldstr "Calling IBar.Bar9 on FooBarBlahImpl"
+ IL_01c6: call void Test::Assert(bool,
+ string)
+ IL_01cb: nop
+ IL_01cc: ldloc.0
+ IL_01cd: stloc.3
+ IL_01ce: ldstr "Calling IBlah.Blah methods on FooBarBlahImpl..."
+ IL_01d3: call void [mscorlib]System.Console::WriteLine(string)
+ IL_01d8: nop
+ IL_01d9: ldloc.3
+ IL_01da: ldc.i4.0
+ IL_01db: callvirt instance int32 IBlah::Blah1(int32)
+ IL_01e0: ldc.i4 0x2b67
+ IL_01e5: ceq
+ IL_01e7: ldstr "Calling IBlah.Blah1 on FooBarBlahImpl"
+ IL_01ec: call void Test::Assert(bool,
+ string)
+ IL_01f1: nop
+ IL_01f2: ldloc.3
+ IL_01f3: ldc.i4.0
+ IL_01f4: callvirt instance int32 IBlah::Blah2(int32)
+ IL_01f9: ldc.i4 0x56ce
+ IL_01fe: ceq
+ IL_0200: ldstr "Calling IBlah.Blah1 on FooBarBlahImpl"
+ IL_0205: call void Test::Assert(bool,
+ string)
+ IL_020a: nop
+ IL_020b: ldloc.3
+ IL_020c: ldc.i4.0
+ IL_020d: callvirt instance int32 IBlah::Blah3(int32)
+ IL_0212: ldc.i4 0x8235
+ IL_0217: ceq
+ IL_0219: ldstr "Calling IBlah.Blah1 on FooBarBlahImpl"
+ IL_021e: call void Test::Assert(bool,
+ string)
+ IL_0223: nop
+ IL_0224: ret
+ } // end of method Program::MultiOverride
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
@@ -191,7 +1589,7 @@
IL_0007: ret
} // end of method Program::.ctor
-} // end of class Program
+} // end of class Program
.class private auto ansi beforefieldinit Test
extends [mscorlib]System.Object