diff options
50 files changed, 6577 insertions, 335 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 5dfbc40310..9b24a77e90 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -349,6 +349,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/buildpipeline/DotNet-CoreClr-Trusted-Linux-Crossbuild.json b/buildpipeline/DotNet-CoreClr-Trusted-Linux-Crossbuild.json index f578be4797..a975bbd85b 100644 --- a/buildpipeline/DotNet-CoreClr-Trusted-Linux-Crossbuild.json +++ b/buildpipeline/DotNet-CoreClr-Trusted-Linux-Crossbuild.json @@ -345,7 +345,7 @@ "value": "Release" }, "GitHubRepo": { - "value": "http://github.com/dotnet/coreclr.git" + "value": "https://github.com/dotnet/coreclr.git" }, "GitHubDirectory": { "value": "/root/coreclr" diff --git a/buildpipeline/DotNet-CoreClr-Trusted-Linux.json b/buildpipeline/DotNet-CoreClr-Trusted-Linux.json index 711b7b0fe2..9c2b4af20f 100644 --- a/buildpipeline/DotNet-CoreClr-Trusted-Linux.json +++ b/buildpipeline/DotNet-CoreClr-Trusted-Linux.json @@ -309,7 +309,7 @@ "value": "Release" }, "GitHubRepo": { - "value": "http://github.com/dotnet/coreclr.git" + "value": "https://github.com/dotnet/coreclr.git" }, "GitHubDirectory": { "value": "/root/coreclr" @@ -449,4 +449,4 @@ "state": "wellFormed", "revision": 418097633 } -}
\ No newline at end of file +} diff --git a/dependencies.props b/dependencies.props index ad6b4fa126..3d2d605a5f 100644 --- a/dependencies.props +++ b/dependencies.props @@ -8,7 +8,7 @@ <StabilizePackageVersion Condition="'$(StabilizePackageVersion)' == ''">false</StabilizePackageVersion> <StableVersion Condition="'$(StabilizePackageVersion)' == 'true' and '$(StableVersion)' == ''">$(PackageVersion)</StableVersion> - <PreReleaseLabel>preview1</PreReleaseLabel> + <PreReleaseLabel>dev-di</PreReleaseLabel> </PropertyGroup> <!-- Source of truth for dependency tooling: the commit hash of the dotnet/versions master branch as of the last auto-upgrade. --> @@ -28,7 +28,7 @@ <!-- Full package version strings that are used in other parts of the build. --> <PropertyGroup> - <CoreClrPackageVersion>2.1.0-preview1-25713-01</CoreClrPackageVersion> + <CoreClrPackageVersion>2.1.0-dev-di-25528-01</CoreClrPackageVersion> <XunitPackageVersion>2.2.0-beta2-build3300</XunitPackageVersion> <XUnitConsoleNetCoreVersion>1.0.2-prerelease-00177</XUnitConsoleNetCoreVersion> <XUnitPerformanceApiVersion>1.0.0-beta-build0007</XUnitPerformanceApiVersion> @@ -39,7 +39,7 @@ <!-- Package dependency verification/auto-upgrade configuration. --> <PropertyGroup> <BaseDotNetBuildInfo>build-info/dotnet/</BaseDotNetBuildInfo> - <DependencyBranch>master</DependencyBranch> + <DependencyBranch>dev/defaultintf</DependencyBranch> <CurrentRefXmlPath>$(MSBuildThisFileFullPath)</CurrentRefXmlPath> </PropertyGroup> @@ -127,6 +127,7 @@ <!-- Packaging properties --> <PropertyGroup> <LicenseUrl>https://github.com/dotnet/coreclr/blob/master/LICENSE.TXT</LicenseUrl> + <PreReleaseLabel>dev-di</PreReleaseLabel> <PackageDescriptionFile>$(SourceDir).nuget/descriptions.json</PackageDescriptionFile> <PackageLicenseFile>$(ProjectDir)LICENSE.TXT</PackageLicenseFile> <PackageThirdPartyNoticesFile>$(ProjectDir)THIRD-PARTY-NOTICES.TXT</PackageThirdPartyNoticesFile> 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/ilasm/assem.cpp b/src/ilasm/assem.cpp index 6416dfe5c7..a3b8daf8ae 100644 --- a/src/ilasm/assem.cpp +++ b/src/ilasm/assem.cpp @@ -339,7 +339,6 @@ BOOL Assembler::AddMethod(Method *pMethod) { char sz[1024]; sz[0] = 0; - if(fIsInterface && (!IsMdStatic(pMethod->m_Attr))) strcat_s(sz,1024," non-static declared in interface"); if(fIsImport) strcat_s(sz,1024," imported"); if(IsMdAbstract(pMethod->m_Attr)) strcat_s(sz,1024," abstract"); if(IsMdPinvokeImpl(pMethod->m_Attr)) strcat_s(sz,1024," pinvoke"); diff --git a/src/ilasm/assembler.cpp b/src/ilasm/assembler.cpp index be535abce8..74190b7e0c 100644 --- a/src/ilasm/assembler.cpp +++ b/src/ilasm/assembler.cpp @@ -705,24 +705,6 @@ void Assembler::StartMethod(__in __nullterminated char* name, BinStr* sig, CorMe { flags = (CorMethodAttr)(flags | mdSpecialName); if(IsTdInterface(m_pCurClass->m_Attr)) report->error("Instance constructor in interface\n"); - - } - if(!IsMdStatic(flags)) - { - if(IsTdInterface(m_pCurClass->m_Attr)) - { - if(!IsMdPublic(flags)) report->error("Non-public instance method in interface\n"); - if((!(IsMdVirtual(flags) && IsMdAbstract(flags)))) - { - if(OnErrGo) report->error("Non-virtual, non-abstract instance method in interface\n"); - else - { - report->warn("Non-virtual, non-abstract instance method in interface, set to such\n"); - flags = (CorMethodAttr)(flags |mdVirtual | mdAbstract); - } - } - - } } m_pCurMethod = new Method(this, m_pCurClass, name, sig, flags); } diff --git a/src/ilasm/typar.hpp b/src/ilasm/typar.hpp index 143a4a2da3..146128e30a 100644 --- a/src/ilasm/typar.hpp +++ b/src/ilasm/typar.hpp @@ -51,17 +51,27 @@ private: class TyParList { public: - TyParList(DWORD a, BinStr* b, LPCUTF8 n, TyParList* nx = NULL) + TyParList(DWORD a, BinStr* b, LPCUTF8 n, TyParList* nx = NULL) { bound = (b == NULL) ? new BinStr() : b; bound->appendInt32(0); // zero terminator - attrs = a; name = n; next = nx; - }; - ~TyParList() - { - if(bound) delete bound; - if (next) delete next; - }; + attrs = a; name = n; next = nx; + }; + ~TyParList() + { + if( bound) delete bound; + + // To avoid excessive stack usage (especially in debug builds), we break the next chain + // and delete as we traverse the link list + TyParList *pCur = next; + while (pCur != NULL) + { + TyParList *pTmp = pCur->next; + pCur->next = NULL; + delete pCur; + pCur = pTmp; + } + }; int Count() { TyParList* tp = this; @@ -154,7 +164,7 @@ public: TyParList* Next() { return next; }; BinStr* Bound() { return bound; }; private: - BinStr* bound; + BinStr* bound; LPCUTF8 name; TyParList* next; DWORD attrs; diff --git a/src/mscorlib/shared/System/Runtime/CompilerServices/RuntimeFeature.cs b/src/mscorlib/shared/System/Runtime/CompilerServices/RuntimeFeature.cs index 090acff559..4978b09b72 100644 --- a/src/mscorlib/shared/System/Runtime/CompilerServices/RuntimeFeature.cs +++ b/src/mscorlib/shared/System/Runtime/CompilerServices/RuntimeFeature.cs @@ -11,17 +11,19 @@ namespace System.Runtime.CompilerServices /// </summary> public const string PortablePdb = nameof(PortablePdb); + /// Indicates that this version of runtime supports default interface method implementations. + /// </summary> + public const string DefaultImplementationsOfInterfaces = nameof(DefaultImplementationsOfInterfaces); + /// <summary> /// Checks whether a certain feature is supported by the Runtime. /// </summary> public static bool IsSupported(string feature) { - // Features should be added as public const string fields in the same class. - // Example: public const string FeatureName = nameof(FeatureName); - switch (feature) { - case nameof(PortablePdb): + case PortablePdb: + case DefaultImplementationsOfInterfaces: return true; } diff --git a/src/vm/classcompat.cpp b/src/vm/classcompat.cpp index 384e63fefb..fb97a79e85 100644 --- a/src/vm/classcompat.cpp +++ b/src/vm/classcompat.cpp @@ -2612,26 +2612,6 @@ VOID MethodTableBuilder::EnumerateClassMethods() } } - // Some interface checks. - if (IsInterface()) - { - if (IsMdVirtual(dwMemberAttrs)) - { - if (!IsMdAbstract(dwMemberAttrs)) - { - BuildMethodTableThrowException(BFA_VIRTUAL_NONAB_INT_METHOD); - } - } - else - { - // Instance field/method - if (!IsMdStatic(dwMemberAttrs)) - { - BuildMethodTableThrowException(BFA_NONVIRT_INST_INT_METHOD); - } - } - } - // No synchronized methods in ValueTypes if(fIsClassValueType && IsMiSynchronized(dwImplFlags)) { @@ -2797,17 +2777,20 @@ VOID MethodTableBuilder::EnumerateClassMethods() // If the interface is a standard managed interface then allocate space for an FCall method desc. Classification = mcFCall; } - else + else if (IsMdAbstract(dwMemberAttrs)) { // If COM interop is supported then all other interface MDs may be // accessed via COM interop <TODO> mcComInterop MDs are BIG - // this is very often a waste of space </TODO> + // @DIM_TODO - What if default interface method is called through COM interop? Classification = mcComInterop; } -#else // !FEATURE_COMINTEROP - // This codepath is used by remoting - Classification = mcIL; + else #endif // !FEATURE_COMINTEROP + { + // This codepath is used by remoting and default interface methods + Classification = mcIL; + } } else { diff --git a/src/vm/clsload.cpp b/src/vm/clsload.cpp index bb71f0b6ed..22b030caa0 100644 --- a/src/vm/clsload.cpp +++ b/src/vm/clsload.cpp @@ -5912,19 +5912,35 @@ BOOL ClassLoader::CanAccessFamily( _ASSERTE(pCurrentClass); _ASSERTE(pTargetClass); + BOOL bIsInterface = pTargetClass->IsInterface(); + //Look to see if Current is a child of the Target. while (pCurrentClass) { - MethodTable *pCurInstance = pCurrentClass; - - while (pCurInstance) { - //This is correct. csc is incredibly lax about generics. Essentially if you are a subclass of - //any type of generic it lets you access it. Since the standard is totally unclear, mirror that - //behavior here. - if (pCurInstance->HasSameTypeDefAs(pTargetClass)) { - return TRUE; + if (bIsInterface) + { + // Calling a protected interface member + MethodTable::InterfaceMapIterator it = pCurrentClass->IterateInterfaceMap(); + while (it.Next()) + { + // We only loosely check if they are of the same generic type + if (it.GetInterface()->HasSameTypeDefAs(pTargetClass)) + return TRUE; } + } + else + { + MethodTable *pCurInstance = pCurrentClass; + + while (pCurInstance) { + //This is correct. csc is incredibly lax about generics. Essentially if you are a subclass of + //any type of generic it lets you access it. Since the standard is totally unclear, mirror that + //behavior here. + if (pCurInstance->HasSameTypeDefAs(pTargetClass)) { + return TRUE; + } - pCurInstance = pCurInstance->GetParentMethodTable(); + pCurInstance = pCurInstance->GetParentMethodTable(); + } } ///Looking at 8.5.3, it looks like a protected member of a nested class in a parent type is also diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp index aa1365ca3d..d960394e12 100644 --- a/src/vm/jitinterface.cpp +++ b/src/vm/jitinterface.cpp @@ -5210,8 +5210,7 @@ void CEEInfo::getCallInfo( directCall = true; } else - // Force all interface calls to be interpreted as if they are virtual. - if (pTargetMD->GetMethodTable()->IsInterface()) + if (pTargetMD->GetMethodTable()->IsInterface() && pTargetMD->IsVirtual()) { directCall = false; } @@ -5614,7 +5613,7 @@ void CEEInfo::getCallInfo( pResult->classFlags = getClassAttribsInternal(pResolvedToken->hClass); pResult->methodFlags = getMethodAttribsInternal(pResult->hMethod); - getMethodSigInternal(pResult->hMethod, &pResult->sig, (pResult->hMethod == pResolvedToken->hMethod) ? pResolvedToken->hClass : NULL); + getMethodSigInternal(pResult->hMethod, &pResult->sig, (pResult->hMethod == pResolvedToken->hMethod) ? pResolvedToken->hClass : NULL, /* isCallSite = */ TRUE); if (flags & CORINFO_CALLINFO_VERIFICATION) { @@ -8283,7 +8282,8 @@ void CEEInfo::getMethodSigInternal( CORINFO_METHOD_HANDLE ftnHnd, CORINFO_SIG_INFO * sigRet, - CORINFO_CLASS_HANDLE owner) + CORINFO_CLASS_HANDLE owner, + BOOL isCallSite) { STANDARD_VM_CONTRACT; @@ -8309,7 +8309,15 @@ CEEInfo::getMethodSigInternal( // Shared generic methods and shared methods on generic structs take an extra argument representing their instantiation if (ftn->RequiresInstArg()) { - sigRet->callConv = (CorInfoCallConv) (sigRet->callConv | CORINFO_CALLCONV_PARAMTYPE); + // + // If we are making an interface call that is a default interface method, we need to lie to the JIT. + // The reason being that we already made sure target is always directly callable (through instantiation stubs), + // JIT should not generate shared generics aware call code and insert the secret argument again at the callsite. + // Otherwise we would end up with two secret generic dictionary arguments (since the stub also provides one). + // + BOOL isDefaultInterfaceMethodCallSite = isCallSite && ftn->IsDefaultInterfaceMethod(); + if (!isDefaultInterfaceMethodCallSite) + sigRet->callConv = (CorInfoCallConv) (sigRet->callConv | CORINFO_CALLCONV_PARAMTYPE); } // We want the calling convention bit to be consistant with the method attribute bit diff --git a/src/vm/jitinterface.h b/src/vm/jitinterface.h index 8ba65c3964..93470ecbac 100644 --- a/src/vm/jitinterface.h +++ b/src/vm/jitinterface.h @@ -714,7 +714,8 @@ public: void getMethodSigInternal ( CORINFO_METHOD_HANDLE ftnHnd, CORINFO_SIG_INFO* sigInfo, - CORINFO_CLASS_HANDLE owner = NULL + CORINFO_CLASS_HANDLE owner = NULL, + BOOL isCallSite = FALSE ); void getEHinfo( diff --git a/src/vm/method.cpp b/src/vm/method.cpp index 4bae82a61d..8778744537 100644 --- a/src/vm/method.cpp +++ b/src/vm/method.cpp @@ -1636,7 +1636,11 @@ BOOL MethodDesc::IsSharedByGenericMethodInstantiations() // Does this method require an extra MethodTable argument for instantiation information? // This is the case for // * per-inst static methods in shared-code instantiated generic classes (e.g. static void MyClass<string>::m()) +// - there is no this pointer providing generic dictionary info // * shared-code instance methods in instantiated generic structs (e.g. void MyValueType<string>::m()) +// - unboxed 'this' pointer in value-type instance methods don't have MethodTable pointer by definition +// * default interface method called via interface dispatch (e. g. IFoo<string>.Foo calling into IFoo<object>::Foo()) +// - this pointer is ambiguous as it can implement more than one IFoo<T> BOOL MethodDesc::RequiresInstMethodTableArg() { LIMITED_METHOD_DAC_CONTRACT; @@ -1644,7 +1648,7 @@ BOOL MethodDesc::RequiresInstMethodTableArg() return IsSharedByGenericInstantiations() && !HasMethodInstantiation() && - (IsStatic() || GetMethodTable()->IsValueType()); + (IsStatic() || GetMethodTable()->IsValueType() || IsDefaultInterfaceMethod()); } //******************************************************************************* @@ -1666,7 +1670,7 @@ BOOL MethodDesc::RequiresInstArg() LIMITED_METHOD_DAC_CONTRACT; BOOL fRet = IsSharedByGenericInstantiations() && - (HasMethodInstantiation() || IsStatic() || GetMethodTable()->IsValueType()); + (HasMethodInstantiation() || IsStatic() || GetMethodTable()->IsValueType() || IsDefaultInterfaceMethod()); _ASSERT(fRet == (RequiresInstMethodTableArg() || RequiresInstMethodDescArg())); return fRet; @@ -1742,7 +1746,8 @@ BOOL MethodDesc::AcquiresInstMethodTableFromThis() { IsSharedByGenericInstantiations() && !HasMethodInstantiation() && !IsStatic() && - !GetMethodTable()->IsValueType(); + !GetMethodTable()->IsValueType() && + !IsDefaultInterfaceMethod(); } //******************************************************************************* @@ -2430,7 +2435,7 @@ BOOL MethodDesc::RequiresStableEntryPoint(BOOL fEstimateForChunk /*=FALSE*/) return TRUE; // TODO: Can we avoid early allocation of precodes for interfaces and cominterop? - if ((IsInterface() && !IsStatic()) || IsComPlusCall()) + if ((IsInterface() && !IsStatic() && IsVirtual()) || IsComPlusCall()) return TRUE; } @@ -2526,7 +2531,7 @@ BOOL MethodDesc::MayHaveNativeCode() _ASSERTE(IsIL()); - if ((IsInterface() && !IsStatic()) || IsWrapperStub() || ContainsGenericVariables() || IsAbstract()) + if ((IsInterface() && !IsStatic() && IsVirtual() && IsAbstract()) || IsWrapperStub() || ContainsGenericVariables() || IsAbstract()) { return FALSE; } @@ -4823,6 +4828,11 @@ BOOL MethodDesc::SetNativeCodeInterlocked(PCODE addr, PCODE pExpected /*=NULL*/) return FastInterlockCompareExchangePointer(EnsureWritablePages(reinterpret_cast<TADDR*>(pSlot)), (TADDR&)value, (TADDR&)expected) == (TADDR&)expected; } + + if (IsDefaultInterfaceMethod() && HasPrecode()) + { + return GetPrecode()->SetTargetInterlocked(addr); + } _ASSERTE(pExpected == NULL); return SetStableEntryPointInterlocked(addr); diff --git a/src/vm/method.hpp b/src/vm/method.hpp index 9a20af2212..08318ec5b5 100644 --- a/src/vm/method.hpp +++ b/src/vm/method.hpp @@ -1005,6 +1005,14 @@ public: && GetSlot() < pMT->GetNumVirtuals(); } + // Is this a default interface method (virtual non-abstract instance method) + inline BOOL IsDefaultInterfaceMethod() + { + LIMITED_METHOD_CONTRACT; + + return (GetMethodTable()->IsInterface() && !IsStatic() && IsVirtual() && !IsAbstract()); + } + inline BOOL HasNonVtableSlot(); void SetHasNonVtableSlot() 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 32d55d303e..0adba6ac4e 100644 --- a/src/vm/methodtable.cpp +++ b/src/vm/methodtable.cpp @@ -1986,7 +1986,7 @@ MethodTable::Debug_DumpInterfaceMap( HRESULT hr; EX_TRY { - InterfaceMapIterator it(this, false); + InterfaceMapIterator it(this); while (it.Next()) { MethodTable *pInterfaceMT = it.GetInterface(); @@ -6922,6 +6922,12 @@ MethodTable::FindDispatchImpl( DispatchMapEntry e; if (!FindDispatchEntry(typeID, slotNumber, &e)) { + // Figure out the interface being called + MethodTable *pIfcMT = GetThread()->GetDomain()->LookupType(typeID); + + // Figure out which method of the interface the caller requested. + MethodDesc * pIfcMD = pIfcMT->GetMethodDescForSlot(slotNumber); + // A call to an array thru IList<T> (or IEnumerable<T> or ICollection<T>) has to be handled specially. // These interfaces are "magic" (mostly due to working set concerned - they are created on demand internally // even though semantically, these are static interfaces.) @@ -6935,7 +6941,7 @@ MethodTable::FindDispatchImpl( // IList<T> call thru an array. // Get the MT of IList<T> or IReadOnlyList<T> - MethodTable *pIfcMT = GetThread()->GetDomain()->LookupType(typeID); + // Quick sanity check if (!(pIfcMT->HasInstantiation())) @@ -6947,9 +6953,6 @@ MethodTable::FindDispatchImpl( // Get the type of T (as in IList<T>) TypeHandle theT = pIfcMT->GetInstantiation()[0]; - // Figure out which method of IList<T> the caller requested. - MethodDesc * pIfcMD = pIfcMT->GetMethodDescForSlot(slotNumber); - // Retrieve the corresponding method of SZArrayHelper. This is the guy that will actually execute. // This method will be an instantiation of a generic method. I.e. if the caller requested // IList<T>.Meth(), he will actually be diverted to SZArrayHelper.Meth<T>(). @@ -6966,11 +6969,34 @@ MethodTable::FindDispatchImpl( RETURN(TRUE); } + else + { + // + // See if we can find a default method from one of the implemented interfaces + // + MethodDesc *pDefaultMethod = NULL; + if (FindDefaultInterfaceImplementation( + pIfcMD, // the interface method being resolved + pIfcMT, // the interface being resolved + &pDefaultMethod)) + { + // Now, construct a DispatchSlot to return in *pImplSlot + DispatchSlot ds(pDefaultMethod->GetMethodEntryPoint()); + + if (pImplSlot != NULL) + { + *pImplSlot = ds; + } + + RETURN(TRUE); + } + } // This contract is not implemented by this class or any parent class. RETURN(FALSE); } + ///////////////////////////////// // 1.1. Update the typeID and slotNumber so that the full search can commense below typeID = TYPE_ID_THIS_CLASS; @@ -6988,6 +7014,273 @@ MethodTable::FindDispatchImpl( RETURN (TRUE); } +#ifndef DACCESS_COMPILE + +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 +) +{ + CONTRACT(BOOL) { + INSTANCE_CHECK; + MODE_ANY; + THROWS; + GC_TRIGGERS; + PRECONDITION(CheckPointer(pInterfaceMD)); + PRECONDITION(CheckPointer(pInterfaceMT)); + PRECONDITION(CheckPointer(ppDefaultMethod)); + POSTCONDITION(!RETVAL || (*ppDefaultMethod) != nullptr); + } CONTRACT_END; + + InterfaceMapIterator it = this->IterateInterfaceMap(); + + CQuickArray<MatchCandidate> candidates; + int candidatesCount = 0; + candidates.AllocThrows(this->GetNumInterfaces()); + + // + // Walk interface from derived class to parent class + // 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) + { + MethodTable *pParentMT = pMT->GetParentMethodTable(); + unsigned dwParentInterfaces = 0; + if (pParentMT) + dwParentInterfaces = pParentMT->GetNumInterfaces(); + + // Scanning only current class only if the current class have more interface than parent + // (parent interface are laid out first in interface map) + if (pMT->GetNumInterfaces() > dwParentInterfaces) + { + // Only iterate the interfaceimpls on current class + MethodTable::InterfaceMapIterator it = pMT->IterateInterfaceMapFrom(dwParentInterfaces); + while (!it.Finished()) + { + MethodTable *pCurMT = it.GetInterface(); + + MethodDesc *pCurMD = NULL; + if (pCurMT == pInterfaceMT) + { + if (!pInterfaceMD->IsAbstract()) + { + // exact match + pCurMD = pInterfaceMD; + } + } + else if (pCurMT->CanCastToInterface(pInterfaceMT)) + { + if (pCurMT->HasSameTypeDefAs(pInterfaceMT)) + { + // Generic variance match - we'll instantiate pCurMD with the right type arguments later + pCurMD = pInterfaceMD; + } + else + { + // + // 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(); + int targetSlot = pInterfaceMD->GetSlot(); + + if (pMD->IsMethodImpl()) + { + MethodImpl::Iterator it(pMD); + for (; it.IsValid(); it.Next()) + { + 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; + } + } + } + } + } + } + + if (pCurMD != NULL) + { + // + // Found a match. But is it a more specific match (we want most specific interfaces) + // + if (pCurMD->HasClassOrMethodInstantiation()) + { + // Instantiate the MethodDesc + // We don't want generic dictionary from this pointer - we need pass secret type argument + // from instantiating stubs to resolve ambiguity + pCurMD = MethodDesc::FindOrCreateAssociatedMethodDesc( + pCurMD, + pCurMT, + FALSE, // forceBoxedEntryPoint + pCurMD->HasMethodInstantiation() ? + pCurMD->AsInstantiatedMethodDesc()->IMD_GetMethodInstantiation() : + Instantiation(), // for method themselves that are generic + FALSE, // allowInstParam + TRUE // forceRemoteableMethod + ); + } + + 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) + { + // A dup - we are done + needToInsert = false; + break; + } + + if (pCurMT->CanCastToInterface(pCandidateMT)) + { + // pCurMT is a more specific choice than IFoo/IBar both overrides IBlah : + if (!seenMoreSpecific) + { + seenMoreSpecific = true; + candidates[i].pMT = pCurMT; + candidates[i].pMD = pCurMD; + } + else + { + 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(); + } + } + + 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; + RETURN(TRUE); + } + + RETURN(FALSE); +} +#endif // DACCESS_COMPILE + //========================================================================================== DispatchSlot MethodTable::FindDispatchSlot(UINT32 typeID, UINT32 slotNumber) { @@ -9538,79 +9831,79 @@ MethodTable::TryResolveConstraintMethodApprox( // we don't have enough exact type information at JIT time // even to decide whether we will be able to resolve to an unboxed entry point... // To cope with this case we always go via the helper function if there's any - // chance of this happening by checking for all interfaces which might possibly - // be compatible with the call (verification will have ensured that - // at least one of them will be) - - // Enumerate all potential interface instantiations - MethodTable::InterfaceMapIterator it = pCanonMT->IterateInterfaceMap(); - DWORD cPotentialMatchingInterfaces = 0; - while (it.Next()) +// chance of this happening by checking for all interfaces which might possibly +// be compatible with the call (verification will have ensured that +// at least one of them will be) + +// Enumerate all potential interface instantiations +MethodTable::InterfaceMapIterator it = pCanonMT->IterateInterfaceMap(); +DWORD cPotentialMatchingInterfaces = 0; +while (it.Next()) +{ + TypeHandle thPotentialInterfaceType(it.GetInterface()); + if (thPotentialInterfaceType.AsMethodTable()->GetCanonicalMethodTable() == + thInterfaceType.AsMethodTable()->GetCanonicalMethodTable()) + { + cPotentialMatchingInterfaces++; + pMD = pCanonMT->GetMethodDescForInterfaceMethod(thPotentialInterfaceType, pGenInterfaceMD); + + // See code:#TryResolveConstraintMethodApprox_DoNotReturnParentMethod + if ((pMD != NULL) && !pMD->GetMethodTable()->IsValueType()) { - TypeHandle thPotentialInterfaceType(it.GetInterface()); - if (thPotentialInterfaceType.AsMethodTable()->GetCanonicalMethodTable() == - thInterfaceType.AsMethodTable()->GetCanonicalMethodTable()) - { - cPotentialMatchingInterfaces++; - pMD = pCanonMT->GetMethodDescForInterfaceMethod(thPotentialInterfaceType, pGenInterfaceMD); - - // See code:#TryResolveConstraintMethodApprox_DoNotReturnParentMethod - if ((pMD != NULL) && !pMD->GetMethodTable()->IsValueType()) - { - LOG((LF_JIT, LL_INFO10000, "TryResolveConstraintMethodApprox: %s::%s not a value type method\n", - pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName)); - return NULL; - } - } + LOG((LF_JIT, LL_INFO10000, "TryResolveConstraintMethodApprox: %s::%s not a value type method\n", + pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName)); + return NULL; } - - _ASSERTE_MSG((cPotentialMatchingInterfaces != 0), - "At least one interface has to implement the method, otherwise there's a bug in JIT/verification."); + } +} - if (cPotentialMatchingInterfaces > 1) - { // We have more potentially matching interfaces - MethodTable * pInterfaceMT = thInterfaceType.GetMethodTable(); - _ASSERTE(pInterfaceMT->HasInstantiation()); - - BOOL fIsExactMethodResolved = FALSE; - - if (!pInterfaceMT->IsSharedByGenericInstantiations() && - !pInterfaceMT->IsGenericTypeDefinition() && - !this->IsSharedByGenericInstantiations() && - !this->IsGenericTypeDefinition()) - { // We have exact interface and type instantiations (no generic variables and __Canon used - // anywhere) - if (this->CanCastToInterface(pInterfaceMT)) - { - // We can resolve to exact method - pMD = this->GetMethodDescForInterfaceMethod(pInterfaceMT, pInterfaceMD); - _ASSERTE(pMD != NULL); - fIsExactMethodResolved = TRUE; - } - } - - if (!fIsExactMethodResolved) - { // We couldn't resolve the interface statically - _ASSERTE(pfForceUseRuntimeLookup != NULL); - // Notify the caller that it should use runtime lookup - // Note that we can leave pMD incorrect, because we will use runtime lookup - *pfForceUseRuntimeLookup = TRUE; - } +_ASSERTE_MSG((cPotentialMatchingInterfaces != 0), + "At least one interface has to implement the method, otherwise there's a bug in JIT/verification."); + +if (cPotentialMatchingInterfaces > 1) +{ // We have more potentially matching interfaces + MethodTable * pInterfaceMT = thInterfaceType.GetMethodTable(); + _ASSERTE(pInterfaceMT->HasInstantiation()); + + BOOL fIsExactMethodResolved = FALSE; + + if (!pInterfaceMT->IsSharedByGenericInstantiations() && + !pInterfaceMT->IsGenericTypeDefinition() && + !this->IsSharedByGenericInstantiations() && + !this->IsGenericTypeDefinition()) + { // We have exact interface and type instantiations (no generic variables and __Canon used + // anywhere) + if (this->CanCastToInterface(pInterfaceMT)) + { + // We can resolve to exact method + pMD = this->GetMethodDescForInterfaceMethod(pInterfaceMT, pInterfaceMD); + _ASSERTE(pMD != NULL); + fIsExactMethodResolved = TRUE; } - else + } + + if (!fIsExactMethodResolved) + { // We couldn't resolve the interface statically + _ASSERTE(pfForceUseRuntimeLookup != NULL); + // Notify the caller that it should use runtime lookup + // Note that we can leave pMD incorrect, because we will use runtime lookup + *pfForceUseRuntimeLookup = TRUE; + } +} +else +{ + // If we can resolve the interface exactly then do so (e.g. when doing the exact + // lookup at runtime, or when not sharing generic code). + if (pCanonMT->CanCastToInterface(thInterfaceType.GetMethodTable())) + { + pMD = pCanonMT->GetMethodDescForInterfaceMethod(thInterfaceType, pGenInterfaceMD); + if (pMD == NULL) { - // If we can resolve the interface exactly then do so (e.g. when doing the exact - // lookup at runtime, or when not sharing generic code). - if (pCanonMT->CanCastToInterface(thInterfaceType.GetMethodTable())) - { - pMD = pCanonMT->GetMethodDescForInterfaceMethod(thInterfaceType, pGenInterfaceMD); - if (pMD == NULL) - { - LOG((LF_JIT, LL_INFO10000, "TryResolveConstraintMethodApprox: failed to find method desc for interface method\n")); - } - } + LOG((LF_JIT, LL_INFO10000, "TryResolveConstraintMethodApprox: failed to find method desc for interface method\n")); } } +} + } else if (pGenInterfaceMD->IsVirtual()) { if (pGenInterfaceMD->HasNonVtableSlot() && pGenInterfaceMD->GetMethodTable()->IsValueType()) @@ -9631,33 +9924,36 @@ MethodTable::TryResolveConstraintMethodApprox( // methods on System.Object, i.e. when these are used as a constraint. pMD = NULL; } - + if (pMD == NULL) { // Fall back to VSD return NULL; } - - //#TryResolveConstraintMethodApprox_DoNotReturnParentMethod - // Only return a method if the value type itself declares the method, - // otherwise we might get a method from Object or System.ValueType - if (!pMD->GetMethodTable()->IsValueType()) - { // Fall back to VSD - return NULL; + + if (!pMD->GetMethodTable()->IsInterface()) + { + //#TryResolveConstraintMethodApprox_DoNotReturnParentMethod + // Only return a method if the value type itself declares the method + // otherwise we might get a method from Object or System.ValueType + if (!pMD->GetMethodTable()->IsValueType()) + { // Fall back to VSD + return NULL; + } + + // We've resolved the method, ignoring its generic method arguments + // If the method is a generic method then go and get the instantiated descriptor + pMD = MethodDesc::FindOrCreateAssociatedMethodDesc( + pMD, + this, + FALSE /* no BoxedEntryPointStub */, + pInterfaceMD->GetMethodInstantiation(), + FALSE /* no allowInstParam */); + + // FindOrCreateAssociatedMethodDesc won't return an BoxedEntryPointStub. + _ASSERTE(pMD != NULL); + _ASSERTE(!pMD->IsUnboxingStub()); } - - // We've resolved the method, ignoring its generic method arguments - // If the method is a generic method then go and get the instantiated descriptor - pMD = MethodDesc::FindOrCreateAssociatedMethodDesc( - pMD, - this, - FALSE /* no BoxedEntryPointStub */ , - pInterfaceMD->GetMethodInstantiation(), - FALSE /* no allowInstParam */ ); - - // FindOrCreateAssociatedMethodDesc won't return an BoxedEntryPointStub. - _ASSERTE(pMD != NULL); - _ASSERTE(!pMD->IsUnboxingStub()); - + return pMD; } // MethodTable::TryResolveConstraintMethodApprox diff --git a/src/vm/methodtable.h b/src/vm/methodtable.h index e5fd7fad07..60059675e9 100644 --- a/src/vm/methodtable.h +++ b/src/vm/methodtable.h @@ -2548,6 +2548,14 @@ public: UINT32 slotNumber, DispatchSlot * pImplSlot); + +#ifndef DACCESS_COMPILE + BOOL FindDefaultInterfaceImplementation( + MethodDesc *pInterfaceMD, + MethodTable *pObjectMT, + MethodDesc **ppDefaultMethod); +#endif // DACCESS_COMPILE + DispatchSlot FindDispatchSlot(UINT32 typeID, UINT32 slotNumber); DispatchSlot FindDispatchSlot(DispatchToken tok); diff --git a/src/vm/methodtable.inl b/src/vm/methodtable.inl index 0d0acda885..4fa81c931b 100644 --- a/src/vm/methodtable.inl +++ b/src/vm/methodtable.inl @@ -652,9 +652,8 @@ inline MethodDesc* MethodTable::GetMethodDescForSlot(DWORD slot) PCODE pCode = GetRestoredSlot(slot); - // This is an optimization that we can take advantage of if we're trying - // to get the MethodDesc for an interface virtual, since their slots - // always point to the stub. + // This is an optimization that we can take advantage of if we're trying to get the MethodDesc + // for an interface virtual, since their slots usually point to stub. if (IsInterface() && slot < GetNumVirtuals()) { return MethodDesc::GetMethodDescFromStubAddr(pCode); diff --git a/src/vm/methodtablebuilder.cpp b/src/vm/methodtablebuilder.cpp index cdee2d8667..f9876608eb 100644 --- a/src/vm/methodtablebuilder.cpp +++ b/src/vm/methodtablebuilder.cpp @@ -1619,19 +1619,28 @@ MethodTableBuilder::BuildMethodTableThrowing( // Allocate MethodDescs (expects methods placed methods) AllocAndInitMethodDescs(); - // - // If we are a class, then there may be some unplaced vtable methods (which are by definition - // interface methods, otherwise they'd already have been placed). Place as many unplaced methods - // as possible, in the order preferred by interfaces. However, do not allow any duplicates - once - // a method has been placed, it cannot be placed again - if we are unable to neatly place an interface, - // create duplicate slots for it starting at dwCurrentDuplicateVtableSlot. Fill out the interface - // map for all interfaces as they are placed. - // - // If we are an interface, then all methods are already placed. Fill out the interface map for - // interfaces as they are placed. - // - if (!IsInterface()) + 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(); + } + else { + // + // If we are a class, then there may be some unplaced vtable methods (which are by definition + // interface methods, otherwise they'd already have been placed). Place as many unplaced methods + // as possible, in the order preferred by interfaces. However, do not allow any duplicates - once + // a method has been placed, it cannot be placed again - if we are unable to neatly place an interface, + // create duplicate slots for it starting at dwCurrentDuplicateVtableSlot. Fill out the interface + // map for all interfaces as they are placed. + // + // If we are an interface, then all methods are already placed. Fill out the interface map for + // interfaces as they are placed. + // ComputeInterfaceMapEquivalenceSet(); PlaceInterfaceMethods(); @@ -2842,16 +2851,16 @@ MethodTableBuilder::EnumerateClassMethods() BuildMethodTableThrowException(BFA_NONVIRT_AB_METHOD); } } - else if(fIsClassInterface) - { - if (IsMdRTSpecialName(dwMemberAttrs) || IsMdVirtual(dwMemberAttrs)) - { - CONSISTENCY_CHECK(CheckPointer(strMethodName)); - if (strcmp(strMethodName, COR_CCTOR_METHOD_NAME)) - { - BuildMethodTableThrowException(BFA_NONAB_NONCCTOR_METHOD_ON_INT); - } - } + else if(fIsClassInterface) + { + if (IsMdRTSpecialName(dwMemberAttrs)) + { + CONSISTENCY_CHECK(CheckPointer(strMethodName)); + if (strcmp(strMethodName, COR_CCTOR_METHOD_NAME)) + { + BuildMethodTableThrowException(BFA_NONAB_NONCCTOR_METHOD_ON_INT); + } + } } // Virtual / not virtual @@ -2871,26 +2880,6 @@ MethodTableBuilder::EnumerateClassMethods() } } - // Some interface checks. - if (IsInterface()) - { - if (IsMdVirtual(dwMemberAttrs)) - { - if (!IsMdAbstract(dwMemberAttrs)) - { - BuildMethodTableThrowException(BFA_VIRTUAL_NONAB_INT_METHOD); - } - } - else - { - // Instance field/method - if (!IsMdStatic(dwMemberAttrs)) - { - BuildMethodTableThrowException(BFA_NONVIRT_INST_INT_METHOD); - } - } - } - // No synchronized methods in ValueTypes if(fIsClassValueType && IsMiSynchronized(dwImplFlags)) { @@ -3113,7 +3102,7 @@ MethodTableBuilder::EnumerateClassMethods() type = METHOD_TYPE_NORMAL; } else if (bmtGenerics->GetNumGenericArgs() != 0 && - (bmtGenerics->fSharedByGenericInstantiations || (!bmtProp->fIsRedirectedInterface && !GetHalfBakedClass()->IsProjectedFromWinRT()))) + (bmtGenerics->fSharedByGenericInstantiations || (!bmtProp->fIsRedirectedInterface && !GetHalfBakedClass()->IsProjectedFromWinRT()))) { // Methods in instantiated interfaces need nothing special - they are not visible from COM etc. // mcComInterop is only useful for unshared instantiated WinRT interfaces. If the interface is @@ -3125,7 +3114,7 @@ MethodTableBuilder::EnumerateClassMethods() // If the interface is a standard managed interface then allocate space for an FCall method desc. type = METHOD_TYPE_FCALL; } - else + else if (IsMdAbstract(dwMemberAttrs)) { // If COM interop is supported then all other interface MDs may be // accessed via COM interop. mcComInterop MDs have an additional @@ -3133,10 +3122,12 @@ MethodTableBuilder::EnumerateClassMethods() // allocated lazily when/if the MD actually gets used for interop. type = METHOD_TYPE_COMINTEROP; } -#else // !FEATURE_COMINTEROP - // This codepath is used by remoting - type = METHOD_TYPE_NORMAL; + else #endif // !FEATURE_COMINTEROP + { + // This codepath is used by remoting + type = METHOD_TYPE_NORMAL; + } } else { @@ -4752,6 +4743,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. @@ -5548,6 +5545,9 @@ MethodTableBuilder::ProcessMethodImpls() { STANDARD_VM_CONTRACT; + if (bmtMethod->dwNumberMethodImpls == 0) + return; + HRESULT hr = S_OK; DeclaredMethodIterator it(*this); @@ -5679,49 +5679,60 @@ MethodTableBuilder::ProcessMethodImpls() } } - if (pDeclType == NULL) + if (IsInterface()) { - DWORD equivalenceSet = 0; - - for (DWORD i = 0; i < bmtInterface->dwInterfaceMapSize; i++) - { - bmtRTType * pCurItf = bmtInterface->pInterfaceMap[i].GetInterfaceType(); - // Type Equivalence is respected for this comparision as we just need to find an - // equivalent interface, the particular interface is unimportant - if (MetaSig::CompareTypeDefsUnderSubstitutions( - pCurItf->GetMethodTable(), pDeclMT, - &pCurItf->GetSubstitution(), pDeclSubst, - NULL)) - { - equivalenceSet = bmtInterface->pInterfaceMap[i].GetInterfaceEquivalenceSet(); - pItfEntry = &bmtInterface->pInterfaceMap[i]; - break; - } - } - - if (equivalenceSet == 0) + if (pDeclType == NULL) { // Interface is not implemented by this type. BuildMethodTableThrowException(IDS_CLASSLOAD_MI_NOTIMPLEMENTED, it.Token()); } - - // Interface is not implemented by this type exactly. We need to consider this MethodImpl on non exact interface matches, - // as the only match may be one of the non-exact matches - bmtMetaData->rgMethodImplTokens[m].fConsiderDuringInexactMethodImplProcessing = true; - bmtMetaData->rgMethodImplTokens[m].fThrowIfUnmatchedDuringInexactMethodImplProcessing = true; - bmtMetaData->rgMethodImplTokens[m].interfaceEquivalenceSet = equivalenceSet; - bmtMethod->dwNumberInexactMethodImplCandidates++; - continue; // Move on to other MethodImpls } else { - // This method impl may need to match other methods during inexact processing - if (pItfEntry->InEquivalenceSetWithMultipleEntries()) + if (pDeclType == NULL) { + DWORD equivalenceSet = 0; + + for (DWORD i = 0; i < bmtInterface->dwInterfaceMapSize; i++) + { + bmtRTType * pCurItf = bmtInterface->pInterfaceMap[i].GetInterfaceType(); + // Type Equivalence is respected for this comparision as we just need to find an + // equivalent interface, the particular interface is unimportant + if (MetaSig::CompareTypeDefsUnderSubstitutions( + pCurItf->GetMethodTable(), pDeclMT, + &pCurItf->GetSubstitution(), pDeclSubst, + NULL)) + { + equivalenceSet = bmtInterface->pInterfaceMap[i].GetInterfaceEquivalenceSet(); + pItfEntry = &bmtInterface->pInterfaceMap[i]; + break; + } + } + + if (equivalenceSet == 0) + { + // Interface is not implemented by this type. + BuildMethodTableThrowException(IDS_CLASSLOAD_MI_NOTIMPLEMENTED, it.Token()); + } + + // Interface is not implemented by this type exactly. We need to consider this MethodImpl on non exact interface matches, + // as the only match may be one of the non-exact matches bmtMetaData->rgMethodImplTokens[m].fConsiderDuringInexactMethodImplProcessing = true; - bmtMetaData->rgMethodImplTokens[m].fThrowIfUnmatchedDuringInexactMethodImplProcessing = false; - bmtMetaData->rgMethodImplTokens[m].interfaceEquivalenceSet = pItfEntry->GetInterfaceEquivalenceSet(); + bmtMetaData->rgMethodImplTokens[m].fThrowIfUnmatchedDuringInexactMethodImplProcessing = true; + bmtMetaData->rgMethodImplTokens[m].interfaceEquivalenceSet = equivalenceSet; bmtMethod->dwNumberInexactMethodImplCandidates++; + continue; // Move on to other MethodImpls + } + else + { + // This method impl may need to match other methods during inexact processing + if (pItfEntry->InEquivalenceSetWithMultipleEntries()) + { + bmtMetaData->rgMethodImplTokens[m].fConsiderDuringInexactMethodImplProcessing = true; + bmtMetaData->rgMethodImplTokens[m].fThrowIfUnmatchedDuringInexactMethodImplProcessing = false; + bmtMetaData->rgMethodImplTokens[m].interfaceEquivalenceSet = pItfEntry->GetInterfaceEquivalenceSet(); + bmtMethod->dwNumberInexactMethodImplCandidates++; + } } } @@ -5823,7 +5834,7 @@ MethodTableBuilder::ProcessMethodImpls() { // Method not found, throw. BuildMethodTableThrowException(IDS_CLASSLOAD_MI_DECLARATIONNOTFOUND, it.Token()); } - + if (!IsMdVirtual(declMethod.GetDeclAttrs())) { // Make sure the decl is virtual BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MUSTBEVIRTUAL, it.Token()); @@ -6128,9 +6139,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); @@ -6148,7 +6162,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(); @@ -6157,42 +6172,73 @@ MethodTableBuilder::PlaceMethodImpls() BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MULTIPLEOVERRIDES, mdef); } - // Throws - PlaceLocalDeclaration(pCurDeclMethod, - pCurImplMethod, - slots, // Adds override to the slot and replaced arrays. - replaced, - &slotIndex); // Increments count + if (IsInterface()) + { + // Throws + PlaceInterfaceDeclarationOnInterface( + hDeclMethod, + pCurImplMethod, + slots, // Adds override to the slot and replaced arrays. + replaced, + &slotIndex, + dwMaxSlotSize); // Increments count + } + else + { + // Throws + PlaceLocalDeclarationOnClass( + pCurDeclMethod, + pCurImplMethod, + slots, // Adds override to the slot and replaced arrays. + replaced, + &slotIndex, + dwMaxSlotSize); // Increments count + } } else { bmtRTMethod * pCurDeclMethod = hDeclMethod.AsRTMethod(); - // Do not use pDecl->IsInterface here as that asks the method table and the MT may not yet be set up. - if(pCurDeclMethod->GetOwningType()->IsInterface()) + if (IsInterface()) { // Throws - PlaceInterfaceDeclaration(pCurDeclMethod, - pCurImplMethod, - slots, - replaced, - &slotIndex); // Increments count + PlaceInterfaceDeclarationOnInterface( + hDeclMethod, + pCurImplMethod, + slots, // Adds override to the slot and replaced arrays. + replaced, + &slotIndex, + dwMaxSlotSize); // Increments count } else { - // Throws - PlaceParentDeclaration(pCurDeclMethod, - pCurImplMethod, - slots, - replaced, - &slotIndex); // Increments count + // Do not use pDecl->IsInterface here as that asks the method table and the MT may not yet be set up. + if (pCurDeclMethod->GetOwningType()->IsInterface()) + { + // Throws + PlaceInterfaceDeclarationOnClass( + pCurDeclMethod, + pCurImplMethod); + } + else + { + // Throws + PlaceParentDeclarationOnClass( + pCurDeclMethod, + pCurImplMethod, + slots, + replaced, + &slotIndex, + dwMaxSlotSize); // Increments count + } } } 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; } @@ -6201,7 +6247,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; } @@ -6240,20 +6287,32 @@ MethodTableBuilder::WriteMethodImplData( // Set the size of the info the MethodImpl needs to keep track of. pImpl->SetSize(GetLoaderAllocator()->GetHighFrequencyHeap(), GetMemTracker(), cSlots); - // Gasp we do a bubble sort. Should change this to a qsort.. - for (DWORD i = 0; i < cSlots; i++) + if (!IsInterface()) { - for (DWORD j = i+1; j < cSlots; j++) + // 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++) { - if (rgSlots[j] < rgSlots[i]) + int min = i; + for (DWORD j = i + 1; j < cSlots; j++) + { + if (rgSlots[j] < rgSlots[min]) + { + min = j; + } + } + + if (min != i) { MethodDesc * mTmp = rgDeclMD[i].GetValue(); - rgDeclMD[i].SetValue(rgDeclMD[j].GetValue()); - rgDeclMD[j].SetValue(mTmp); + rgDeclMD[i].SetValue(rgDeclMD[min].GetValue()); + rgDeclMD[min].SetValue(mTmp); DWORD sTmp = rgSlots[i]; - rgSlots[i] = rgSlots[j]; - rgSlots[j] = sTmp; + rgSlots[i] = rgSlots[min]; + rgSlots[min] = sTmp; } } } @@ -6267,12 +6326,13 @@ MethodTableBuilder::WriteMethodImplData( //******************************************************************************* VOID -MethodTableBuilder::PlaceLocalDeclaration( +MethodTableBuilder::PlaceLocalDeclarationOnClass( bmtMDMethod * pDecl, bmtMDMethod * pImpl, DWORD * slots, RelativePointer<MethodDesc *> * replaced, - DWORD * pSlotIndex) + DWORD * pSlotIndex, + DWORD dwMaxSlotSize) { CONTRACTL { @@ -6327,20 +6387,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; @@ -6436,16 +6494,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; @@ -6488,12 +6590,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 @@ -6527,8 +6630,8 @@ VOID MethodTableBuilder::ValidateInterfaceMethodConstraints() // If pTargetMT is null, this indicates that the target MethodDesc belongs // to the current type. Otherwise, the MethodDesc MUST be owned by a parent // of the type we're building. - BOOL fTargetIsOwnedByParent = !pTargetMD->GetMethodTablePtr()->IsNull(); - + BOOL fTargetIsOwnedByParent = !pTargetMD->GetMethodTablePtr()->IsNull(); + // If the method is owned by a parent, we need to use the parent's module, // and we must construct the substitution chain all the way up to the parent. const Substitution *pSubstTgt = NULL; @@ -10529,6 +10632,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; @@ -10604,7 +10746,9 @@ void MethodTableBuilder::VerifyVirtualMethodsImplemented(MethodTable::MethodData if (it.GetTarget().IsNull()) { MethodDesc *pMD = it.GetDeclMethodDesc(); - BuildMethodTableThrowException(IDS_CLASSLOAD_NOTIMPLEMENTED, pMD->GetNameOnNonArrayClass()); + + if (!HasDefaultInterfaceImplementation(pMD)) + BuildMethodTableThrowException(IDS_CLASSLOAD_NOTIMPLEMENTED, pMD->GetNameOnNonArrayClass()); } } } diff --git a/src/vm/methodtablebuilder.h b/src/vm/methodtablebuilder.h index a7d7bdd158..fcb10a86fc 100644 --- a/src/vm/methodtablebuilder.h +++ b/src/vm/methodtablebuilder.h @@ -2737,32 +2737,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 @@ -2844,6 +2854,7 @@ private: VOID HandleGCForValueClasses( MethodTable **); + BOOL HasDefaultInterfaceImplementation(MethodDesc *pIntfMD); VOID VerifyVirtualMethodsImplemented(MethodTable::MethodData * hMTData); VOID CheckForTypeEquivalence( diff --git a/tests/src/IL.targets b/tests/src/IL.targets index d1075e53f7..11a82c50eb 100644 --- a/tests/src/IL.targets +++ b/tests/src/IL.targets @@ -13,8 +13,7 @@ <PropertyGroup> <_ShellKeyMarker Condition="'$(RunningOnUnix)' == 'true'">-</_ShellKeyMarker> <!-- Work around ilasm comandline parser bugs... --> <_ShellKeyMarker Condition="'$(RunningOnUnix)' != 'true'">/</_ShellKeyMarker> - <_ilasm>ilasm</_ilasm> - <_ilasm Condition="'$(RunningOnUnix)' == 'true'">$(CoreCLRBinDir)ilasm</_ilasm> + <_ilasm>$(CoreCLRBinDir)ilasm</_ilasm> <_OutputTypeArgument Condition="'$(OutputType)' == 'Library'">$(_ShellKeyMarker)DLL</_OutputTypeArgument> <_OutputTypeArgument Condition="'$(OutputType)' == 'Exe'">$(_ShellKeyMarker)EXE</_OutputTypeArgument> <_IlasmSwitches>-QUIET -NOLOGO</_IlasmSwitches> diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrainedcall.cs b/tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrainedcall.cs new file mode 100644 index 0000000000..decd7bdd8d --- /dev/null +++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrainedcall.cs @@ -0,0 +1,185 @@ +using System; +using System.Collections.Generic; + +interface IFoo +{ + int Foo(int c); +} + +interface IAdd +{ + int Add(int c); +} + +// Only needed for writing IFoo.Foo code +class IFoo_Impl : IFoo +{ + public int Foo(int c) + { + IAdd adder = (IAdd) this; + return adder.Add(c); + } +} + +struct FooValue : IFoo, IAdd +{ + public int val; + + public int Foo(int c) + { + val +=c; + return val; + } + + public int Add(int c) + { + val +=c; + return val; + } +} + +interface IHorrible<T> +{ + int GetLocalVal(); + void SetLocalVal(int val); + int Horrible(); +} + +// Only needed for the default interface implementation +class IHorrible_Impl<T> : IHorrible<T> +{ + public int GetLocalVal() { return 0; } + public void SetLocalVal(int val) {} + public int Horrible() + { + int val = GetLocalVal(); + val++; + SetLocalVal(val); + return val; + } +} + +struct HorribleCase<Z> : IHorrible<IList<Z>>, IHorrible<IEnumerable<Z>> +{ + int localVal; + public int GetLocalVal() { return localVal; } + public void SetLocalVal(int val) { localVal = val; } + int IHorrible<IList<Z>>.Horrible() { return ++localVal; } + + // Remove + int IHorrible<IEnumerable<Z>>.Horrible() { return ++localVal; } +} + +class HorribleTest +{ + public static int Horror<T,U>(T t) where T:IHorrible<U> + { + return t.Horrible() + t.Horrible(); + } + + public static void RunTest() + { + Test.Assert(Horror<HorribleCase<object>,IEnumerable<object>>(new HorribleCase<object>())) == 2, "Fail"); + Test.Assert(Horror<HorribleCase<object>,IList<object>>(default(HorribleCase<object>)) == 3, "Fail"); + } +} + +/* +interface IFoo<T> +{ + int Foo(int c); +} + +interface IAdd +{ + int Add(int c); +} + +// Only needed for writing IFoo.Foo code +class IFoo_Impl<T> : IFoo<T> +{ + public int Foo(int c) + { + IAdd adder = (IAdd) this; + return adder.Add(c); + } +} + +struct FooValue<T> : IFoo<T>, IAdd +{ + public int val; + + public int Foo(int c) + { + val +=c; + return val; + } + + public int Add(int c) + { + val +=c; + return val; + } +} +*/ + +class SimpleConstraintTest +{ + public static int CallFoo_WithConstraints<T>(ref T foo, int val) where T : IFoo + { + return foo.Foo(val); + } + + /* + public static int CallFoo_WithConstraints<T>(ref T foo, int val) where T : IFoo<object> + { + return foo.Foo(val); + } + */ + + public static void RunTest() + { + FooValue foo = new FooValue(); + foo.val = 10; + + Console.WriteLine("Calling CallFoo_WithConstraints on FooValue - expecting IFoo::Foo"); + Test.Assert(CallFoo_WithConstraints(ref foo, 10) == 20, "Calling CallFoo_WithConstraints on FooValue"); + + Test.Assert(foo.val == 10, "Expecting boxing on CallFoo_WithConstraints"); + } +} + +class Program +{ + public static int Main() + { + HorribleTest.RunTest(); + SimpleConstraintTest.RunTest(); + + return Test.Ret(); + } +} + +class Test +{ + private static bool Pass = true; + + public static int Ret() + { + return Pass? 100 : 101; + } + + public static void Assert(bool cond, string msg) + { + if (cond) + { + Console.WriteLine("PASS"); + } + else + { + Console.WriteLine("FAIL: " + msg); + Pass = false; + } + } +} + diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrainedcall.il b/tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrainedcall.il new file mode 100644 index 0000000000..ef39ba51e1 --- /dev/null +++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrainedcall.il @@ -0,0 +1,456 @@ + +// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Copyright (c) Microsoft Corporation. All rights reserved. + + + +// Metadata version: v4.0.30319 +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. + .ver 4:0:0:0 +} +.assembly constrainedcall +{ + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx + 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows. + + // --- The following custom attribute is added automatically, do not uncomment ------- + // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 ) + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module constrainedcall.exe +// MVID: {6171EA0F-1009-482D-8EF6-C944886D5D66} +.imagebase 0x00400000 +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 // WINDOWS_CUI +.corflags 0x00000001 // ILONLY +// Image base: 0x01860000 + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class interface private abstract auto ansi IFoo +{ + .method public hidebysig newslot virtual + instance int32 Foo(int32 c) cil managed + { + // Code size 20 (0x14) + .maxstack 2 + .locals init (class IAdd V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: castclass IAdd + IL_0007: stloc.0 + IL_0008: ldloc.0 + IL_0009: ldarg.1 + IL_000a: callvirt instance int32 IAdd::Add(int32) + IL_000f: stloc.1 + IL_0010: br.s IL_0012 + + IL_0012: ldloc.1 + IL_0013: ret + } // end of method IFoo::Foo + +} // end of class IFoo + +.class interface private abstract auto ansi IAdd +{ + .method public hidebysig newslot abstract virtual + instance int32 Add(int32 c) cil managed + { + } // end of method IAdd::Add + +} // end of class IAdd + +.class private sequential ansi sealed beforefieldinit FooValue + extends [mscorlib]System.ValueType + implements IFoo, + IAdd +{ + .field public int32 val + + .method public hidebysig newslot virtual final + instance int32 Add(int32 c) cil managed + { + // Code size 26 (0x1a) + .maxstack 3 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldarg.0 + IL_0003: ldfld int32 FooValue::val + IL_0008: ldarg.1 + IL_0009: add + IL_000a: stfld int32 FooValue::val + IL_000f: ldarg.0 + IL_0010: ldfld int32 FooValue::val + IL_0015: stloc.0 + IL_0016: br.s IL_0018 + + IL_0018: ldloc.0 + IL_0019: ret + } // end of method FooValue::Add + +} // end of class FooValue + +.class interface private abstract auto ansi IHorrible`1<T> +{ + .method public hidebysig newslot abstract virtual + instance int32 GetLocalVal() cil managed + { + } // end of method IHorrible`1::GetLocalVal + + .method public hidebysig newslot abstract virtual + instance void SetLocalVal(int32 val) cil managed + { + } // end of method IHorrible`1::SetLocalVal + + .method public hidebysig newslot virtual + instance int32 Horrible() cil managed + { + // Code size 26 (0x1a) + .maxstack 2 + .locals init (int32 V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: callvirt instance int32 class IHorrible`1<!T>::GetLocalVal() + IL_0007: stloc.0 + IL_0008: ldloc.0 + IL_0009: ldc.i4.1 + IL_000a: add + IL_000b: stloc.0 + IL_000c: ldarg.0 + IL_000d: ldloc.0 + IL_000e: callvirt instance void class IHorrible`1<!T>::SetLocalVal(int32) + IL_0013: nop + IL_0014: ldloc.0 + IL_0015: stloc.1 + IL_0016: br.s IL_0018 + + IL_0018: ldloc.1 + IL_0019: ret + } // end of method IHorrible`1::Horrible + +} // end of class IHorrible`1 + +.class private sequential ansi sealed beforefieldinit HorribleCase`1<Z> + extends [mscorlib]System.ValueType + implements class IHorrible`1<class [mscorlib]System.Collections.Generic.IList`1<!Z>>, + class IHorrible`1<class [mscorlib]System.Collections.Generic.IEnumerable`1<!Z>> +{ + .field private int32 localVal + .method public hidebysig newslot virtual final + instance int32 GetLocalVal() cil managed + { + // Code size 12 (0xc) + .maxstack 1 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldfld int32 valuetype HorribleCase`1<!Z>::localVal + IL_0007: stloc.0 + IL_0008: br.s IL_000a + + IL_000a: ldloc.0 + IL_000b: ret + } // end of method HorribleCase`1::GetLocalVal + + .method public hidebysig newslot virtual final + instance void SetLocalVal(int32 val) cil managed + { + // Code size 9 (0x9) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldarg.1 + IL_0003: stfld int32 valuetype HorribleCase`1<!Z>::localVal + IL_0008: ret + } // end of method HorribleCase`1::SetLocalVal + + .method private hidebysig newslot virtual final + instance int32 'IHorrible<System.Collections.Generic.IList<Z>>.Horrible'() cil managed + { + .override method instance int32 class IHorrible`1<class [mscorlib]System.Collections.Generic.IList`1<!Z>>::Horrible() + // Code size 23 (0x17) + .maxstack 3 + .locals init (int32 V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldarg.0 + IL_0003: ldfld int32 valuetype HorribleCase`1<!Z>::localVal + IL_0008: ldc.i4.1 + IL_0009: add + IL_000a: stloc.0 + IL_000b: ldloc.0 + IL_000c: stfld int32 valuetype HorribleCase`1<!Z>::localVal + IL_0011: ldloc.0 + IL_0012: stloc.1 + IL_0013: br.s IL_0015 + + IL_0015: ldloc.1 + IL_0016: ret + } // end of method HorribleCase`1::'IHorrible<System.Collections.Generic.IList<Z>>.Horrible' +} // end of class HorribleCase`1 + +.class private auto ansi beforefieldinit HorribleTest + extends [mscorlib]System.Object +{ + .method public hidebysig static int32 Horror<(class IHorrible`1<!!U>) T,U>(!!T t) cil managed + { + // Code size 33 (0x21) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldarga.s t + IL_0003: constrained. !!T + IL_0009: callvirt instance int32 class IHorrible`1<!!U>::Horrible() + IL_000e: ldarga.s t + IL_0010: constrained. !!T + IL_0016: callvirt instance int32 class IHorrible`1<!!U>::Horrible() + IL_001b: add + IL_001c: stloc.0 + IL_001d: br.s IL_001f + + IL_001f: ldloc.0 + IL_0020: ret + } // end of method HorribleTest::Horror + + .method public hidebysig static void RunTest() cil managed + { + // Code size 58 (0x3a) + .maxstack 2 + .locals init (valuetype HorribleCase`1<object> V_0) + IL_0000: nop + IL_0001: ldloca.s V_0 + IL_0003: initobj valuetype HorribleCase`1<object> + IL_0009: ldloc.0 + IL_000a: call int32 HorribleTest::Horror<valuetype HorribleCase`1<object>,class [mscorlib]System.Collections.Generic.IEnumerable`1<object>>(!!0) + IL_000f: ldc.i4.3 + IL_0010: ceq + IL_0012: ldstr "Fail" + IL_0017: call void Test::Assert(bool, + string) + IL_001c: nop + IL_001d: ldloca.s V_0 + IL_001f: initobj valuetype HorribleCase`1<object> + IL_0025: ldloc.0 + IL_0026: call int32 HorribleTest::Horror<valuetype HorribleCase`1<object>,class [mscorlib]System.Collections.Generic.IList`1<object>>(!!0) + IL_002b: ldc.i4.0 + IL_002c: ceq + IL_002e: ldstr "Fail" + IL_0033: call void Test::Assert(bool, + string) + IL_0038: nop + IL_0039: ret + } // end of method HorribleTest::RunTest + + .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 HorribleTest::.ctor + +} // end of class HorribleTest + +.class private auto ansi beforefieldinit SimpleConstraintTest + extends [mscorlib]System.Object +{ + .method public hidebysig static int32 CallFoo_WithConstraints<(IFoo) T>(!!T& foo, + int32 val) cil managed + { + // Code size 19 (0x13) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldarg.1 + IL_0003: constrained. !!T + IL_0009: callvirt instance int32 IFoo::Foo(int32) + IL_000e: stloc.0 + IL_000f: br.s IL_0011 + + IL_0011: ldloc.0 + IL_0012: ret + } // end of method SimpleConstraintTest::CallFoo_WithConstraints + + .method public hidebysig static void RunTest() cil managed + { + // Code size 75 (0x4b) + .maxstack 2 + .locals init (valuetype FooValue V_0) + IL_0000: nop + IL_0001: ldloca.s V_0 + IL_0003: initobj FooValue + IL_0009: ldloca.s V_0 + IL_000b: ldc.i4.s 10 + IL_000d: stfld int32 FooValue::val + IL_0012: ldstr "Calling CallFoo_WithConstraints on FooValue - expe" + + "cting IFoo::Foo" + IL_0017: call void [mscorlib]System.Console::WriteLine(string) + IL_001c: nop + IL_001d: ldloca.s V_0 + IL_001f: ldc.i4.s 10 + IL_0021: call int32 SimpleConstraintTest::CallFoo_WithConstraints<valuetype FooValue>(!!0&, + int32) + IL_0026: ldc.i4.s 20 + IL_0028: ceq + IL_002a: ldstr "Calling CallFoo_WithConstraints on FooValue" + IL_002f: call void Test::Assert(bool, + string) + IL_0034: nop + IL_0035: ldloc.0 + IL_0036: ldfld int32 FooValue::val + IL_003b: ldc.i4.s 10 + IL_003d: ceq + IL_003f: ldstr "Expecting boxing on CallFoo_WithConstraints" + IL_0044: call void Test::Assert(bool, + string) + IL_0049: nop + IL_004a: ret + } // end of method SimpleConstraintTest::RunTest + + .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 SimpleConstraintTest::.ctor + +} // end of class SimpleConstraintTest + +.class private auto ansi beforefieldinit Program + extends [mscorlib]System.Object +{ + .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 HorribleTest::RunTest() + IL_0006: nop + IL_0007: call void SimpleConstraintTest::RunTest() + 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 + 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 Program::.ctor + +} // end of class Program + +.class private auto ansi beforefieldinit Test + extends [mscorlib]System.Object +{ + .field private static bool Pass + .method public hidebysig static int32 Ret() cil managed + { + // Code size 19 (0x13) + .maxstack 1 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldsfld bool Test::Pass + IL_0006: brtrue.s IL_000c + + IL_0008: ldc.i4.s 101 + IL_000a: br.s IL_000e + + IL_000c: ldc.i4.s 100 + IL_000e: stloc.0 + IL_000f: br.s IL_0011 + + IL_0011: ldloc.0 + IL_0012: ret + } // end of method Test::Ret + + .method public hidebysig static void Assert(bool cond, + string msg) cil managed + { + // Code size 47 (0x2f) + .maxstack 2 + .locals init (bool V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: stloc.0 + IL_0003: ldloc.0 + IL_0004: brfalse.s IL_0015 + + IL_0006: nop + IL_0007: ldstr "PASS" + IL_000c: call void [mscorlib]System.Console::WriteLine(string) + IL_0011: nop + IL_0012: nop + IL_0013: br.s IL_002e + + IL_0015: nop + IL_0016: ldstr "FAIL: " + IL_001b: ldarg.1 + IL_001c: call string [mscorlib]System.String::Concat(string, + string) + IL_0021: call void [mscorlib]System.Console::WriteLine(string) + IL_0026: nop + IL_0027: ldc.i4.0 + IL_0028: stsfld bool Test::Pass + IL_002d: nop + IL_002e: ret + } // end of method Test::Assert + + .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 Test::.ctor + + .method private hidebysig specialname rtspecialname static + void .cctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: stsfld bool Test::Pass + IL_0006: ret + } // end of method Test::.cctor + +} // end of class Test + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** +// WARNING: Created Win32 resource file constrainedcall.res diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrainedcall.ilproj b/tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrainedcall.ilproj new file mode 100644 index 0000000000..e170b2b467 --- /dev/null +++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/constrainedcall/constrainedcall.ilproj @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" /> + <PropertyGroup> + <AssemblyName>constrainedcall</AssemblyName> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid> + <FileAlignment>512</FileAlignment> + <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + <ReferenceLocalMscorlib>true</ReferenceLocalMscorlib> + <OutputType>Exe</OutputType> + <CLRTestKind>BuildAndRun</CLRTestKind> + <CLRTestPriority>0</CLRTestPriority> + <!-- Use ILAsm that we just built for the new fixes required in default interface methods --> + <UseCustomILAsm>True</UseCustomILAsm> + </PropertyGroup> + + <ItemGroup> + <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies"> + <Visible>False</Visible> + </CodeAnalysisDependentAssemblyPaths> + </ItemGroup> + + <ItemGroup> + <Compile Include="constrainedcall.il" /> + </ItemGroup> + + + <ItemGroup> + <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> + </ItemGroup> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> +</Project> diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.cs b/tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.cs new file mode 100644 index 0000000000..3ff3760aa3 --- /dev/null +++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.cs @@ -0,0 +1,255 @@ +using System; + +interface IFoo +{ + int Foo(int a); +} + +class IFoo_Impl +{ + int Foo(int a) + { + return a; + } +} + +interface IFoo2 : IFoo +{ +} + +class IFoo2_Impl : IFoo +{ + int IFoo.Foo(int a) + { + Console.WriteLine("At IFoo2.Foo"); + return a + 1; + } +} + +interface IFooEx : IFoo +{ +} + +class IFooEx_Impl : IFoo +{ + int IFoo.Foo(int a) + { + Console.WriteLine("At IFooEx.Foo"); + return a + 2; + } +} + +class FooClass : IFoo2, IFooEx +{ + // Dummy + public int Foo(int a) + { + return 0; + } +} + +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 void Negative() + { + FooClass fooObj = new FooClass(); + IFoo foo = (IFoo) fooObj; + + Console.WriteLine("Calling IFoo.Foo on Foo - expecting exception."); + try + { + foo.Foo(10); + Test.Assert(false, "Expecting exception on Foo"); + } + catch(Exception ex) + { + Console.WriteLine("Exception caught: " + ex.ToString()); + } + + 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(); + } +} + +class Test +{ + private static bool Pass = true; + + public static int Ret() + { + return Pass? 100 : 101; + } + + public static void Assert(bool cond, string msg) + { + if (cond) + { + Console.WriteLine("PASS"); + } + else + { + Console.WriteLine("FAIL: " + msg); + Pass = false; + } + } +} + diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.il b/tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.il new file mode 100644 index 0000000000..4173bc6aea --- /dev/null +++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.il @@ -0,0 +1,944 @@ + +// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Copyright (c) Microsoft Corporation. All rights reserved. + + + +// Metadata version: v4.0.30319 +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. + .ver 4:0:0:0 +} +.assembly diamondshape +{ + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx + 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows. + + // --- The following custom attribute is added automatically, do not uncomment ------- + // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 ) + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module diamondshape.exe +// MVID: {25B467F3-D284-4DB6-BAD4-C7EAC75CF064} +.imagebase 0x00400000 +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 // WINDOWS_CUI +.corflags 0x00000001 // ILONLY +// Image base: 0x010B0000 + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class interface private abstract auto ansi IFoo +{ + .method public hidebysig newslot virtual + instance int32 Foo(int32 a) cil managed + { + // Code size 7 (0x7) + .maxstack 1 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldarg.1 + IL_0002: stloc.0 + IL_0003: br.s IL_0005 + + IL_0005: ldloc.0 + IL_0006: ret + } // end of method IFoo::Foo + +} // end of class IFoo + +.class interface private abstract auto ansi IFoo2 + implements IFoo +{ + .method public hidebysig newslot virtual final + instance int32 Foo(int32 a) cil managed + { + .override IFoo::Foo + // Code size 20 (0x14) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldstr "At IFoo2.Foo" + IL_0006: call void [mscorlib]System.Console::WriteLine(string) + IL_000b: nop + IL_000c: ldarg.1 + IL_000d: ldc.i4.1 + IL_000e: add + IL_000f: stloc.0 + IL_0010: br.s IL_0012 + + IL_0012: ldloc.0 + IL_0013: ret + } // end of method IFoo2::IFoo.Foo + +} // end of class IFoo2 + +.class interface private abstract auto ansi IFooEx + implements IFoo +{ + .method public hidebysig newslot virtual final + instance int32 IFoo.Foo(int32 a) cil managed + { + .override IFoo::Foo + // Code size 20 (0x14) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldstr "At IFooEx.Foo" + 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 IFooEx::IFoo.Foo +} // end of class IFooEx + +.class private auto ansi beforefieldinit FooClass + extends [mscorlib]System.Object + implements IFoo2, + IFoo, + IFooEx +{ + .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 FooClass::.ctor + +} // 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 void Negative() cil managed + { + // Code size 225 (0xe1) + .maxstack 2 + .locals init (class FooClass V_0, + class IFoo V_1, + 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 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldstr "Calling IFoo.Foo on Foo - expecting exception." + IL_000e: call void [mscorlib]System.Console::WriteLine(string) + IL_0013: nop + .try + { + IL_0014: nop + IL_0015: ldloc.1 + IL_0016: ldc.i4.s 10 + IL_0018: callvirt instance int32 IFoo::Foo(int32) + IL_001d: pop + IL_001e: ldc.i4.0 + 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_004a + + } // end .try + catch [mscorlib]System.Exception + { + IL_002d: stloc.s V_6 + IL_002f: nop + 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_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 + + } // 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 + 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 Program::.ctor + +} // end of class Program + +.class private auto ansi beforefieldinit Test + extends [mscorlib]System.Object +{ + .field private static bool Pass + .method public hidebysig static int32 Ret() cil managed + { + // Code size 19 (0x13) + .maxstack 1 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldsfld bool Test::Pass + IL_0006: brtrue.s IL_000c + + IL_0008: ldc.i4.s 101 + IL_000a: br.s IL_000e + + IL_000c: ldc.i4.s 100 + IL_000e: stloc.0 + IL_000f: br.s IL_0011 + + IL_0011: ldloc.0 + IL_0012: ret + } // end of method Test::Ret + + .method public hidebysig static void Assert(bool cond, + string msg) cil managed + { + // Code size 47 (0x2f) + .maxstack 2 + .locals init (bool V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: stloc.0 + IL_0003: ldloc.0 + IL_0004: brfalse.s IL_0015 + + IL_0006: nop + IL_0007: ldstr "PASS" + IL_000c: call void [mscorlib]System.Console::WriteLine(string) + IL_0011: nop + IL_0012: nop + IL_0013: br.s IL_002e + + IL_0015: nop + IL_0016: ldstr "FAIL: " + IL_001b: ldarg.1 + IL_001c: call string [mscorlib]System.String::Concat(string, + string) + IL_0021: call void [mscorlib]System.Console::WriteLine(string) + IL_0026: nop + IL_0027: ldc.i4.0 + IL_0028: stsfld bool Test::Pass + IL_002d: nop + IL_002e: ret + } // end of method Test::Assert + + .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 Test::.ctor + + .method private hidebysig specialname rtspecialname static + void .cctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: stsfld bool Test::Pass + IL_0006: ret + } // end of method Test::.cctor + +} // end of class Test + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** +// WARNING: Created Win32 resource file diamondshape.res diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.ilproj b/tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.ilproj new file mode 100644 index 0000000000..34df037a0d --- /dev/null +++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/diamondshape/diamondshape.ilproj @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" /> + <PropertyGroup> + <AssemblyName>diamondshape</AssemblyName> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid> + <FileAlignment>512</FileAlignment> + <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + <ReferenceLocalMscorlib>true</ReferenceLocalMscorlib> + <OutputType>Exe</OutputType> + <CLRTestKind>BuildAndRun</CLRTestKind> + <CLRTestPriority>0</CLRTestPriority> + <!-- Use ILAsm that we just built for the new fixes required in default interface methods --> + <UseCustomILAsm>True</UseCustomILAsm> + </PropertyGroup> + + <ItemGroup> + <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies"> + <Visible>False</Visible> + </CodeAnalysisDependentAssemblyPaths> + </ItemGroup> + + <ItemGroup> + <Compile Include="diamondshape.il" /> + </ItemGroup> + + + <ItemGroup> + <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> + </ItemGroup> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> +</Project> diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/genericmethods/genericmethods.cs b/tests/src/Loader/classloader/DefaultInterfaceMethods/genericmethods/genericmethods.cs new file mode 100644 index 0000000000..ca4936b270 --- /dev/null +++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/genericmethods/genericmethods.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +interface IFoo +{ + Type Foo<T>(); +} + +interface IBar<T> +{ + Type Bar1<P>(); + Type Bar2<K>(); + void Bar3<P, K>(out Type t, out Type u); +} + +class FooBar<V> : IFoo, IBar<V> +{ + public Type Foo<T>() + { + Console.WriteLine("At IFoo<T>::Foo<T>: TypeOf(T) = {0}", typeof(T)); + return typeof(T); + } + + public Type Bar1<P>() + { + Console.WriteLine("At IBar<T>::Foo<P>: TypeOf(P) = {0}", typeof(P)); + return typeof(P); + } + + public Type Bar2<K>() + { + Console.WriteLine("At IBar<T>::Bar2<K>: TypeOf(K) = {0}", typeof(K)); + return typeof(K); + } + + public void Bar3<P, K>(out Type t, out Type u) + { + Console.WriteLine("At IBar<T>::Bar3<P, K>: TypeOf(P) = {0}, TypeOf(K) = {1}", typeof(P), typeof(K)); + t = typeof(P); + u = typeof(K); + } +} + + +class Program +{ + static int Main(string[] args) + { + FooBar<object> fooBar = new FooBar<object>(); + IFoo foo = (IFoo) fooBar; + IBar<object> bar = (IBar<object>) fooBar; + + Console.WriteLine("Calling IFoo.Foo<String> on FooBar<Object> - expecting IFoo::Foo<string>() returning typeof(string)"); + Test.Assert(foo.Foo<string>() == typeof(string), "Calling IFoo.Foo<String> on FooBar<Object>"); + + Console.WriteLine("Calling IBar.Bar1<String> on FooBar<object> - expecting bar.Bar1<string>() returning typeof(string)"); + Test.Assert(bar.Bar1<string>() == typeof(string), "Calling IBar.Bar1<String> on FooBar<object>"); + + Console.WriteLine("Calling IBar.Bar2<String[]> on FooBar<object> - expecting bar.Bar2<string[]>() returning typeof(string[])"); + Test.Assert(bar.Bar2<string[]>() == typeof(string[]), "Calling IBar.Bar2<String[]> on FooBar<object>"); + + Type p, k; + Console.WriteLine("Calling IBar.Bar3<String, String[]> - expecting bar.Bar3<string>() returning typeof(string), typeof(string[])"); + bar.Bar3<string, string[]>(out p, out k); + Test.Assert(p == typeof(string) && k == typeof(string[]), "Calling IBar.Bar3<String, String[]>"); + + return Test.Ret(); + } +} + +class Test +{ + private static bool Pass = true; + + public static int Ret() + { + return Pass ? 100 : 101; + } + + public static void Assert(bool cond, string msg) + { + if (cond) + { + Console.WriteLine("PASS"); + } + else + { + Console.WriteLine("FAIL: " + msg); + Pass = false; + } + } +} + diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/genericmethods/genericmethods.il b/tests/src/Loader/classloader/DefaultInterfaceMethods/genericmethods/genericmethods.il new file mode 100644 index 0000000000..3a3204da41 --- /dev/null +++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/genericmethods/genericmethods.il @@ -0,0 +1,357 @@ + +// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Copyright (c) Microsoft Corporation. All rights reserved. + + + +// Metadata version: v4.0.30319 +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. + .ver 4:0:0:0 +} +.assembly genericmethods +{ + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx + 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows. + + // --- The following custom attribute is added automatically, do not uncomment ------- + // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 ) + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module genericmethods.exe +// MVID: {62CAFB9A-4CDB-4A62-8A4F-DC7648609070} +.imagebase 0x00400000 +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 // WINDOWS_CUI +.corflags 0x00000001 // ILONLY +// Image base: 0x01790000 + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class interface private abstract auto ansi IFoo +{ + .method public hidebysig newslot virtual + instance class [mscorlib]System.Type + Foo<T>() cil managed + { + // Code size 37 (0x25) + .maxstack 2 + .locals init (class [mscorlib]System.Type V_0) + IL_0000: nop + IL_0001: ldstr "At IFoo<T>::Foo<T>: TypeOf(T) = {0}" + IL_0006: ldtoken !!T + IL_000b: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_0010: call void [mscorlib]System.Console::WriteLine(string, + object) + IL_0015: nop + IL_0016: ldtoken !!T + IL_001b: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_0020: stloc.0 + IL_0021: br.s IL_0023 + + IL_0023: ldloc.0 + IL_0024: ret + } // end of method IFoo::Foo + +} // end of class IFoo + +.class interface private abstract auto ansi IBar`1<T> +{ + .method public hidebysig newslot virtual + instance class [mscorlib]System.Type + Bar1<P>() cil managed + { + // Code size 37 (0x25) + .maxstack 2 + .locals init (class [mscorlib]System.Type V_0) + IL_0000: nop + IL_0001: ldstr "At IBar<T>::Foo<P>: TypeOf(P) = {0}" + IL_0006: ldtoken !!P + IL_000b: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_0010: call void [mscorlib]System.Console::WriteLine(string, + object) + IL_0015: nop + IL_0016: ldtoken !!P + IL_001b: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_0020: stloc.0 + IL_0021: br.s IL_0023 + + IL_0023: ldloc.0 + IL_0024: ret + } // end of method IBar`1::Bar1 + + .method public hidebysig newslot virtual + instance class [mscorlib]System.Type + Bar2<K>() cil managed + { + // Code size 37 (0x25) + .maxstack 2 + .locals init (class [mscorlib]System.Type V_0) + IL_0000: nop + IL_0001: ldstr "At IBar<T>::Bar2<K>: TypeOf(K) = {0}" + IL_0006: ldtoken !!K + IL_000b: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_0010: call void [mscorlib]System.Console::WriteLine(string, + object) + IL_0015: nop + IL_0016: ldtoken !!K + IL_001b: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_0020: stloc.0 + IL_0021: br.s IL_0023 + + IL_0023: ldloc.0 + IL_0024: ret + } // end of method IBar`1::Bar2 + + .method public hidebysig newslot virtual + instance void Bar3<P,K>([out] class [mscorlib]System.Type& t, + [out] class [mscorlib]System.Type& u) cil managed + { + // Code size 57 (0x39) + .maxstack 8 + IL_0000: nop + IL_0001: ldstr "At IBar<T>::Bar3<P, K>: TypeOf(P) = {0}, TypeOf(K)" + + " = {1}" + IL_0006: ldtoken !!P + IL_000b: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_0010: ldtoken !!K + IL_0015: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_001a: call void [mscorlib]System.Console::WriteLine(string, + object, + object) + IL_001f: nop + IL_0020: ldarg.1 + IL_0021: ldtoken !!P + IL_0026: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_002b: stind.ref + IL_002c: ldarg.2 + IL_002d: ldtoken !!K + IL_0032: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_0037: stind.ref + IL_0038: ret + } // end of method IBar`1::Bar3 + +} // end of class IBar`1 + +.class private auto ansi beforefieldinit FooBar`1<V> + extends [mscorlib]System.Object + implements IFoo, + class IBar`1<!V> +{ + .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 FooBar`1::.ctor + +} // end of class FooBar`1 + +.class private auto ansi beforefieldinit Program + extends [mscorlib]System.Object +{ + .method private hidebysig static int32 + Main(string[] args) cil managed + { + .entrypoint + // Code size 223 (0xdf) + .maxstack 3 + .locals init (class FooBar`1<object> V_0, + class IFoo V_1, + class IBar`1<object> V_2, + class [mscorlib]System.Type V_3, + class [mscorlib]System.Type V_4, + int32 V_5) + IL_0000: nop + IL_0001: newobj instance void class FooBar`1<object>::.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<String> on FooBar<Object> - expec" + + "ting IFoo::Foo<string>() returning typeof(string)" + IL_0010: call void [mscorlib]System.Console::WriteLine(string) + IL_0015: nop + IL_0016: ldloc.1 + IL_0017: callvirt instance class [mscorlib]System.Type IFoo::Foo<string>() + IL_001c: ldtoken [mscorlib]System.String + IL_0021: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_0026: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type, + class [mscorlib]System.Type) + IL_002b: ldstr "Calling IFoo.Foo<String> on FooBar<Object>" + IL_0030: call void Test::Assert(bool, + string) + IL_0035: nop + IL_0036: ldstr "Calling IBar.Bar1<String> on FooBar<object> - expe" + + "cting bar.Bar1<string>() returning typeof(string)" + IL_003b: call void [mscorlib]System.Console::WriteLine(string) + IL_0040: nop + IL_0041: ldloc.2 + IL_0042: callvirt instance class [mscorlib]System.Type class IBar`1<object>::Bar1<string>() + IL_0047: ldtoken [mscorlib]System.String + IL_004c: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_0051: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type, + class [mscorlib]System.Type) + IL_0056: ldstr "Calling IBar.Bar1<String> on FooBar<object>" + IL_005b: call void Test::Assert(bool, + string) + IL_0060: nop + IL_0061: ldstr "Calling IBar.Bar2<String[]> on FooBar<object> - ex" + + "pecting bar.Bar2<string[]>() returning typeof(string[])" + IL_0066: call void [mscorlib]System.Console::WriteLine(string) + IL_006b: nop + IL_006c: ldloc.2 + IL_006d: callvirt instance class [mscorlib]System.Type class IBar`1<object>::Bar2<string[]>() + IL_0072: ldtoken string[] + IL_0077: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_007c: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type, + class [mscorlib]System.Type) + IL_0081: ldstr "Calling IBar.Bar2<String[]> on FooBar<object>" + IL_0086: call void Test::Assert(bool, + string) + IL_008b: nop + IL_008c: ldstr "Calling IBar.Bar3<String, String[]> - expecting ba" + + "r.Bar3<string>() returning typeof(string), typeof(string[])" + IL_0091: call void [mscorlib]System.Console::WriteLine(string) + IL_0096: nop + IL_0097: ldloc.2 + IL_0098: ldloca.s V_3 + IL_009a: ldloca.s V_4 + IL_009c: callvirt instance void class IBar`1<object>::Bar3<string,string[]>(class [mscorlib]System.Type&, + class [mscorlib]System.Type&) + IL_00a1: nop + IL_00a2: ldloc.3 + IL_00a3: ldtoken [mscorlib]System.String + IL_00a8: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_00ad: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type, + class [mscorlib]System.Type) + IL_00b2: brfalse.s IL_00c7 + + IL_00b4: ldloc.s V_4 + IL_00b6: ldtoken string[] + IL_00bb: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_00c0: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type, + class [mscorlib]System.Type) + IL_00c5: br.s IL_00c8 + + IL_00c7: ldc.i4.0 + IL_00c8: ldstr "Calling IBar.Bar3<String, String[]>" + IL_00cd: call void Test::Assert(bool, + string) + IL_00d2: nop + IL_00d3: call int32 Test::Ret() + IL_00d8: stloc.s V_5 + IL_00da: br.s IL_00dc + + IL_00dc: ldloc.s V_5 + IL_00de: ret + } // end of method Program::Main + + .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 Program::.ctor + +} // end of class Program + +.class private auto ansi beforefieldinit Test + extends [mscorlib]System.Object +{ + .field private static bool Pass + .method public hidebysig static int32 Ret() cil managed + { + // Code size 19 (0x13) + .maxstack 1 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldsfld bool Test::Pass + IL_0006: brtrue.s IL_000c + + IL_0008: ldc.i4.s 101 + IL_000a: br.s IL_000e + + IL_000c: ldc.i4.s 100 + IL_000e: stloc.0 + IL_000f: br.s IL_0011 + + IL_0011: ldloc.0 + IL_0012: ret + } // end of method Test::Ret + + .method public hidebysig static void Assert(bool cond, + string msg) cil managed + { + // Code size 47 (0x2f) + .maxstack 2 + .locals init (bool V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: stloc.0 + IL_0003: ldloc.0 + IL_0004: brfalse.s IL_0015 + + IL_0006: nop + IL_0007: ldstr "PASS" + IL_000c: call void [mscorlib]System.Console::WriteLine(string) + IL_0011: nop + IL_0012: nop + IL_0013: br.s IL_002e + + IL_0015: nop + IL_0016: ldstr "FAIL: " + IL_001b: ldarg.1 + IL_001c: call string [mscorlib]System.String::Concat(string, + string) + IL_0021: call void [mscorlib]System.Console::WriteLine(string) + IL_0026: nop + IL_0027: ldc.i4.0 + IL_0028: stsfld bool Test::Pass + IL_002d: nop + IL_002e: ret + } // end of method Test::Assert + + .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 Test::.ctor + + .method private hidebysig specialname rtspecialname static + void .cctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: stsfld bool Test::Pass + IL_0006: ret + } // end of method Test::.cctor + +} // end of class Test + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** +// WARNING: Created Win32 resource file genericmethods.res diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/genericmethods/genericmethods.ilproj b/tests/src/Loader/classloader/DefaultInterfaceMethods/genericmethods/genericmethods.ilproj new file mode 100644 index 0000000000..909dbe94dc --- /dev/null +++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/genericmethods/genericmethods.ilproj @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" /> + <PropertyGroup> + <AssemblyName>genericmethods</AssemblyName> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid> + <FileAlignment>512</FileAlignment> + <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + <ReferenceLocalMscorlib>true</ReferenceLocalMscorlib> + <OutputType>Exe</OutputType> + <CLRTestKind>BuildAndRun</CLRTestKind> + <CLRTestPriority>0</CLRTestPriority> + <!-- Use ILAsm that we just built for the new fixes required in default interface methods --> + <UseCustomILAsm>True</UseCustomILAsm> + </PropertyGroup> + + <ItemGroup> + <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies"> + <Visible>False</Visible> + </CodeAnalysisDependentAssemblyPaths> + </ItemGroup> + + <ItemGroup> + <Compile Include="genericmethods.il" /> + </ItemGroup> + + + <ItemGroup> + <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> + </ItemGroup> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> +</Project> diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.cs b/tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.cs new file mode 100755 index 0000000000..0d4c119453 --- /dev/null +++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.cs @@ -0,0 +1,316 @@ +using System; + +interface IFoo +{ + 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 : IFoo +{ + // @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 IBlah : IBar +{ + // @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 IBarImpl : IBar +{ + // @REMOVE all implementation + int IFoo.Foo1(int a) + { + 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 IBlahImpl : IBarImpl, IBlah +{ + // @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 IBlah.Blah2"); + return c+222; + } + + int IBlah.Blah3(int c) + { + 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() + { + SingleOverride(); + MultiOverride(); + + return Test.Ret(); + } + + private static void SingleOverride() + { + IBarImpl barImpl = new IBarImpl(); + IFoo foo = (IFoo) barImpl; + + Console.WriteLine("Calling IFoo.Foo methods on IBarImpl..."); + + 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"); + } +} + +class Test +{ + private static bool Pass = true; + + public static int Ret() + { + return Pass? 100 : 101; + } + + public static void Assert(bool cond, string msg) + { + if (cond) + { + Console.WriteLine("PASS"); + } + else + { + Console.WriteLine("FAIL: " + msg); + Pass = false; + } + } +} + + diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.il b/tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.il new file mode 100644 index 0000000000..7f9444283e --- /dev/null +++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.il @@ -0,0 +1,1677 @@ + +// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Copyright (c) Microsoft Corporation. All rights reserved. + + + +// Metadata version: v4.0.30319 +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. + .ver 4:0:0:0 +} +.assembly methodimpl +{ + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx + 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows. + + // --- The following custom attribute is added automatically, do not uncomment ------- + // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 ) + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module methodimpl.exe +// MVID: {F249A85F-3FD2-488F-B084-97B542AD68D6} +.imagebase 0x00400000 +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 // WINDOWS_CUI +.corflags 0x00000001 // ILONLY +// Image base: 0x02FD0000 + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class interface private abstract auto ansi IFoo +{ + .method public hidebysig newslot virtual + 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 IIFoo.Foo1" + IL_0006: call void [mscorlib]System.Console::WriteLine(string) + IL_000b: nop + IL_000c: ldarg.1 + 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::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 Bar3(int32 a) cil managed + { + // Code size 21 (0x15) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + 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 + IL_000d: ldc.i4.s 20 + 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.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 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.Foo6(int32 a) cil managed + { + .override IFoo::Foo6 + // Code size 21 (0x15) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + 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 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 IBlah::IBar.Bar3 + + .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 + + 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 IBar, + IFoo +{ + .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 IBarImpl::.ctor + +} // 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 +{ + .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::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 IBarImpl V_0, + class IFoo V_1, + class IBar V_2, + class IBlahImpl V_3, + class IBlah V_4) + IL_0000: nop + IL_0001: newobj instance void IBarImpl::.ctor() + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + 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.Foo1 on FooBarBlahImpl" + IL_0027: call void Test::Assert(bool, + string) + IL_002c: nop + 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 + { + // 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 Program::.ctor + +} // end of class Program + +.class private auto ansi beforefieldinit Test + extends [mscorlib]System.Object +{ + .field private static bool Pass + .method public hidebysig static int32 Ret() cil managed + { + // Code size 19 (0x13) + .maxstack 1 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldsfld bool Test::Pass + IL_0006: brtrue.s IL_000c + + IL_0008: ldc.i4.s 101 + IL_000a: br.s IL_000e + + IL_000c: ldc.i4.s 100 + IL_000e: stloc.0 + IL_000f: br.s IL_0011 + + IL_0011: ldloc.0 + IL_0012: ret + } // end of method Test::Ret + + .method public hidebysig static void Assert(bool cond, + string msg) cil managed + { + // Code size 47 (0x2f) + .maxstack 2 + .locals init (bool V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: stloc.0 + IL_0003: ldloc.0 + IL_0004: brfalse.s IL_0015 + + IL_0006: nop + IL_0007: ldstr "PASS" + IL_000c: call void [mscorlib]System.Console::WriteLine(string) + IL_0011: nop + IL_0012: nop + IL_0013: br.s IL_002e + + IL_0015: nop + IL_0016: ldstr "FAIL: " + IL_001b: ldarg.1 + IL_001c: call string [mscorlib]System.String::Concat(string, + string) + IL_0021: call void [mscorlib]System.Console::WriteLine(string) + IL_0026: nop + IL_0027: ldc.i4.0 + IL_0028: stsfld bool Test::Pass + IL_002d: nop + IL_002e: ret + } // end of method Test::Assert + + .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 Test::.ctor + + .method private hidebysig specialname rtspecialname static + void .cctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: stsfld bool Test::Pass + IL_0006: ret + } // end of method Test::.cctor + +} // end of class Test + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** +// WARNING: Created Win32 resource file methodimpl.res diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.ilproj b/tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.ilproj new file mode 100644 index 0000000000..16a1cadcd2 --- /dev/null +++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/methodimpl/methodimpl.ilproj @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" /> + <PropertyGroup> + <AssemblyName>methodimpl</AssemblyName> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid> + <FileAlignment>512</FileAlignment> + <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + <ReferenceLocalMscorlib>true</ReferenceLocalMscorlib> + <OutputType>Exe</OutputType> + <CLRTestKind>BuildAndRun</CLRTestKind> + <CLRTestPriority>0</CLRTestPriority> + <!-- Use ILAsm that we just built for the new fixes required in default interface methods --> + <UseCustomILAsm>True</UseCustomILAsm> + </PropertyGroup> + + <ItemGroup> + <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies"> + <Visible>False</Visible> + </CodeAnalysisDependentAssemblyPaths> + </ItemGroup> + + <ItemGroup> + <Compile Include="methodimpl.il" /> + </ItemGroup> + + + <ItemGroup> + <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> + </ItemGroup> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> +</Project> diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/sharedgenerics/sharedgenerics.cs b/tests/src/Loader/classloader/DefaultInterfaceMethods/sharedgenerics/sharedgenerics.cs new file mode 100644 index 0000000000..93b214dfb7 --- /dev/null +++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/sharedgenerics/sharedgenerics.cs @@ -0,0 +1,68 @@ +using System; + +interface IFoo<T> +{ + Type Foo(T a); +} + +interface IBar<in T> +{ + Type Bar(T b); +} + +class FooBar<T, U> : IFoo<T>, IBar<U> +{ + public Type Foo(T a) + { + Console.WriteLine("At IFoo.Foo:Arg={0}, TypeOf(T)={1}", a.ToString(), typeof(T)); + return typeof(T); + } + + public Type Bar(U b) + { + Console.WriteLine("At IBar.Bar:Arg={0}, TypeOf(T)={1}", b.ToString(), typeof(U)); + return typeof(U); + } +} + +class Program +{ + public static int Main() + { + FooBar<string, object> fooBar = new FooBar<string, object>(); + IFoo<string> foo = (IFoo<string>) fooBar; + IBar<string[]> bar = (IBar<string[]>) fooBar; + + Console.WriteLine("Calling IFoo<string>.Foo on FooBar<string, object> - expecting default method IFoo<string>.Foo"); + Test.Assert(foo.Foo("ABC") == typeof(string), "Calling IFoo<string>.Foo on FooBar<string, object>"); + + Console.WriteLine("Calling IBar<string[]>.Foo on FooBar<string, object> - expecting default method IBar<object>.Foo"); + Test.Assert(bar.Bar(new string[] { "ABC" }) == typeof(object), "Calling IBar<object>.Bar on FooBar<string, object>"); + + return Test.Ret(); + } +} + +class Test +{ + private static bool Pass = true; + + public static int Ret() + { + return Pass? 100 : 101; + } + + public static void Assert(bool cond, string msg) + { + if (cond) + { + Console.WriteLine("PASS"); + } + else + { + Console.WriteLine("FAIL: " + msg); + Pass = false; + } + } +} + diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/sharedgenerics/sharedgenerics.il b/tests/src/Loader/classloader/DefaultInterfaceMethods/sharedgenerics/sharedgenerics.il new file mode 100644 index 0000000000..8e9eaec325 --- /dev/null +++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/sharedgenerics/sharedgenerics.il @@ -0,0 +1,275 @@ + +// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Copyright (c) Microsoft Corporation. All rights reserved. + + + +// Metadata version: v4.0.30319 +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. + .ver 4:0:0:0 +} +.assembly sharedgenerics +{ + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx + 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows. + + // --- The following custom attribute is added automatically, do not uncomment ------- + // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 ) + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module sharedgenerics.exe +// MVID: {0DEEC74C-30FE-495C-9653-12BE5220327A} +.imagebase 0x00400000 +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 // WINDOWS_CUI +.corflags 0x00000001 // ILONLY +// Image base: 0x02D40000 + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class interface private abstract auto ansi IFoo`1<T> +{ + .method public hidebysig newslot virtual + instance class [mscorlib]System.Type + Foo(!T a) cil managed + { + // Code size 50 (0x32) + .maxstack 3 + .locals init (class [mscorlib]System.Type V_0) + IL_0000: nop + IL_0001: ldstr "At IFoo.Foo:Arg={0}, TypeOf(T)={1}" + IL_0006: ldarga.s a + IL_0008: constrained. !T + IL_000e: callvirt instance string [mscorlib]System.Object::ToString() + IL_0013: ldtoken !T + IL_0018: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_001d: call void [mscorlib]System.Console::WriteLine(string, + object, + object) + IL_0022: nop + IL_0023: ldtoken !T + IL_0028: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_002d: stloc.0 + IL_002e: br.s IL_0030 + + IL_0030: ldloc.0 + IL_0031: ret + } // end of method IFoo`1::Foo + +} // end of class IFoo`1 + +.class interface private abstract auto ansi IBar`1<- T> +{ + .method public hidebysig newslot virtual + instance class [mscorlib]System.Type + Bar(!T b) cil managed + { + // Code size 50 (0x32) + .maxstack 3 + .locals init (class [mscorlib]System.Type V_0) + IL_0000: nop + IL_0001: ldstr "At IBar.Bar:Arg={0}, TypeOf(T)={1}" + IL_0006: ldarga.s b + IL_0008: constrained. !T + IL_000e: callvirt instance string [mscorlib]System.Object::ToString() + IL_0013: ldtoken !T + IL_0018: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_001d: call void [mscorlib]System.Console::WriteLine(string, + object, + object) + IL_0022: nop + IL_0023: ldtoken !T + IL_0028: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_002d: stloc.0 + IL_002e: br.s IL_0030 + + IL_0030: ldloc.0 + IL_0031: ret + } // end of method IBar`1::Bar + +} // end of class IBar`1 + +.class private auto ansi beforefieldinit FooBar`2<T,U> + extends [mscorlib]System.Object + implements class IFoo`1<!T>, + class IBar`1<!U> +{ + .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 FooBar`2::.ctor + +} // end of class FooBar`2 + +.class private auto ansi beforefieldinit Program + extends [mscorlib]System.Object +{ + .method public hidebysig static int32 Main() cil managed + { + .entrypoint + // Code size 126 (0x7e) + .maxstack 5 + .locals init (class FooBar`2<string,object> V_0, + class IFoo`1<string> V_1, + class IBar`1<string[]> V_2, + int32 V_3) + IL_0000: nop + IL_0001: newobj instance void class FooBar`2<string,object>::.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<string>.Foo on FooBar<string, object>" + + " - expecting default method IFoo<string>.Foo" + IL_0010: call void [mscorlib]System.Console::WriteLine(string) + IL_0015: nop + IL_0016: ldloc.1 + IL_0017: ldstr "ABC" + IL_001c: callvirt instance class [mscorlib]System.Type class IFoo`1<string>::Foo(!0) + IL_0021: ldtoken [mscorlib]System.String + IL_0026: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_002b: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type, + class [mscorlib]System.Type) + IL_0030: ldstr "Calling IFoo<string>.Foo on FooBar<string, object>" + IL_0035: call void Test::Assert(bool, + string) + IL_003a: nop + IL_003b: ldstr "Calling IBar<string[]>.Foo on FooBar<string, objec" + + "t> - expecting default method IBar<object>.Foo" + IL_0040: call void [mscorlib]System.Console::WriteLine(string) + IL_0045: nop + IL_0046: ldloc.2 + IL_0047: ldc.i4.1 + IL_0048: newarr [mscorlib]System.String + IL_004d: dup + IL_004e: ldc.i4.0 + IL_004f: ldstr "ABC" + IL_0054: stelem.ref + IL_0055: callvirt instance class [mscorlib]System.Type class IBar`1<string[]>::Bar(!0) + IL_005a: ldtoken [mscorlib]System.Object + IL_005f: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_0064: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type, + class [mscorlib]System.Type) + IL_0069: ldstr "Calling IBar<object>.Bar on FooBar<string, object>" + IL_006e: call void Test::Assert(bool, + string) + IL_0073: nop + IL_0074: call int32 Test::Ret() + IL_0079: stloc.3 + IL_007a: br.s IL_007c + + IL_007c: ldloc.3 + IL_007d: ret + } // end of method Program::Main + + .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 Program::.ctor + +} // end of class Program + +.class private auto ansi beforefieldinit Test + extends [mscorlib]System.Object +{ + .field private static bool Pass + .method public hidebysig static int32 Ret() cil managed + { + // Code size 19 (0x13) + .maxstack 1 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldsfld bool Test::Pass + IL_0006: brtrue.s IL_000c + + IL_0008: ldc.i4.s 101 + IL_000a: br.s IL_000e + + IL_000c: ldc.i4.s 100 + IL_000e: stloc.0 + IL_000f: br.s IL_0011 + + IL_0011: ldloc.0 + IL_0012: ret + } // end of method Test::Ret + + .method public hidebysig static void Assert(bool cond, + string msg) cil managed + { + // Code size 47 (0x2f) + .maxstack 2 + .locals init (bool V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: stloc.0 + IL_0003: ldloc.0 + IL_0004: brfalse.s IL_0015 + + IL_0006: nop + IL_0007: ldstr "PASS" + IL_000c: call void [mscorlib]System.Console::WriteLine(string) + IL_0011: nop + IL_0012: nop + IL_0013: br.s IL_002e + + IL_0015: nop + IL_0016: ldstr "FAIL: " + IL_001b: ldarg.1 + IL_001c: call string [mscorlib]System.String::Concat(string, + string) + IL_0021: call void [mscorlib]System.Console::WriteLine(string) + IL_0026: nop + IL_0027: ldc.i4.0 + IL_0028: stsfld bool Test::Pass + IL_002d: nop + IL_002e: ret + } // end of method Test::Assert + + .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 Test::.ctor + + .method private hidebysig specialname rtspecialname static + void .cctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: stsfld bool Test::Pass + IL_0006: ret + } // end of method Test::.cctor + +} // end of class Test + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** +// WARNING: Created Win32 resource file sharedgenerics.res diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/sharedgenerics/sharedgenerics.ilproj b/tests/src/Loader/classloader/DefaultInterfaceMethods/sharedgenerics/sharedgenerics.ilproj new file mode 100644 index 0000000000..be40d201ff --- /dev/null +++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/sharedgenerics/sharedgenerics.ilproj @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" /> + <PropertyGroup> + <AssemblyName>sharedgenerics</AssemblyName> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid> + <FileAlignment>512</FileAlignment> + <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + <ReferenceLocalMscorlib>true</ReferenceLocalMscorlib> + <OutputType>Exe</OutputType> + <CLRTestKind>BuildAndRun</CLRTestKind> + <CLRTestPriority>0</CLRTestPriority> + <!-- Use ILAsm that we just built for the new fixes required in default interface methods --> + <UseCustomILAsm>True</UseCustomILAsm> + </PropertyGroup> + + <ItemGroup> + <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies"> + <Visible>False</Visible> + </CodeAnalysisDependentAssemblyPaths> + </ItemGroup> + + <ItemGroup> + <Compile Include="sharedgenerics.il" /> + </ItemGroup> + + + <ItemGroup> + <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> + </ItemGroup> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> +</Project> diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/simple/simple.cs b/tests/src/Loader/classloader/DefaultInterfaceMethods/simple/simple.cs new file mode 100644 index 0000000000..21e5c8aaf3 --- /dev/null +++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/simple/simple.cs @@ -0,0 +1,123 @@ +using System; + +interface IBlah +{ + int Blah(int c); +} + +// All methods go into IBlah +class IBlah_Impl +{ + public int Blah(int c) + { + Console.WriteLine("At IBlah.Blah"); + return c + Blah_Private_GetA() + Blah_Internal_GetB() + Blah_Protected_GetC(); + } + + private int Blah_Private_GetA() + { + Console.WriteLine("At IBlah.Blah_Private_GetA"); + return 1; + } + + internal int Blah_Internal_GetB() + { + Console.WriteLine("At IBlah.Blah_Internal_GetB"); + return 2; + } + + protected int Blah_Protected_GetC() + { + Console.WriteLine("At IBlah.Blah_Protected_GetC"); + return 3; + } +} + +interface IFoo +{ + int Foo(int a); +} + +interface IBar +{ + int Bar(int b); +} + +class Base : IBlah +{ + public int Blah(int c) + { + // Dummy + return 0; + } +} + +class FooBar : Base, IFoo, IBar +{ + public int Foo(int a) + { + Console.WriteLine("At IFoo.Foo"); + return a+1; + } + + public int Bar(int b) + { + Console.WriteLine("At IBar.Bar"); + return b+10; + } + + public int CallBlahProtected() + { + // change to IBlah.Blah_Protected_GetC(); + return CallBlahProtected(); + } +} + +class Program +{ + public static int Main() + { + FooBar fooBar = new FooBar(); + IFoo foo = (IFoo) fooBar; + IBar bar = (IBar) fooBar; + IBlah blah = (IBlah) fooBar; + + Console.WriteLine("Calling IFoo.Foo on FooBar - expecting default method on IFoo.Foo. "); + Test.Assert(foo.Foo(10) == 11, "Calling IFoo.Foo on FooBar"); + + Console.WriteLine("Calling IBar.Bar on FooBar - expecting default method on IBar.Bar. "); + Test.Assert(bar.Bar(10) == 20, "Calling IBar.Bar on FooBar"); + + Console.WriteLine("Calling IBlah.Blah on FooBar - expecting default method on IBlah.Blah from Base. "); + Test.Assert(blah.Blah(10) == 16, "Calling IBlah.Blah on FooBar"); + + Console.WriteLine("Calling FooBar.CallBlahProtected - expecting protected methods on interface can be called"); + Test.Assert(fooBar.CallBlahProtected() == 3, "Calling FooBar.CallBlahProtected"); + + return Test.Ret(); + } +} + +class Test +{ + private static bool Pass = true; + + public static int Ret() + { + return Pass? 100 : 101; + } + + public static void Assert(bool cond, string msg) + { + if (cond) + { + Console.WriteLine("PASS"); + } + else + { + Console.WriteLine("FAIL: " + msg); + Pass = false; + } + } +} + diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/simple/simple.il b/tests/src/Loader/classloader/DefaultInterfaceMethods/simple/simple.il new file mode 100644 index 0000000000..c53ed0f0a4 --- /dev/null +++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/simple/simple.il @@ -0,0 +1,397 @@ + +// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Copyright (c) Microsoft Corporation. All rights reserved. + + + +// Metadata version: v4.0.30319 +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. + .ver 4:0:0:0 +} +.assembly simple +{ + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx + 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows. + + // --- The following custom attribute is added automatically, do not uncomment ------- + // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 ) + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module simple.exe +// MVID: {0B8FCFD0-673A-4DEB-90CC-B96749DE09C8} +.imagebase 0x00400000 +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 // WINDOWS_CUI +.corflags 0x00000001 // ILONLY +// Image base: 0x01A80000 + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class interface private abstract auto ansi IBlah +{ + .method public hidebysig newslot virtual + instance int32 Blah(int32 c) cil managed + { + // Code size 39 (0x27) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldstr "At IBlah.Blah" + IL_0006: call void [mscorlib]System.Console::WriteLine(string) + IL_000b: nop + IL_000c: ldarg.1 + IL_000d: ldarg.0 + IL_000e: call instance int32 IBlah::Blah_Private_GetA() + IL_0013: add + IL_0014: ldarg.0 + IL_0015: call instance int32 IBlah::Blah_Internal_GetB() + IL_001a: add + IL_001b: ldarg.0 + IL_001c: call instance int32 IBlah::Blah_Protected_GetC() + IL_0021: add + IL_0022: stloc.0 + IL_0023: br.s IL_0025 + + IL_0025: ldloc.0 + IL_0026: ret + } // end of method IBlah::Blah + + .method private hidebysig instance int32 + Blah_Private_GetA() cil managed + { + // Code size 18 (0x12) + .maxstack 1 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldstr "At IBlah.Blah_Private_GetA" + IL_0006: call void [mscorlib]System.Console::WriteLine(string) + IL_000b: nop + IL_000c: ldc.i4.1 + IL_000d: stloc.0 + IL_000e: br.s IL_0010 + + IL_0010: ldloc.0 + IL_0011: ret + } // end of method IBlah_Impl::Blah_Private_GetA + + .method assembly hidebysig instance int32 + Blah_Internal_GetB() cil managed + { + // Code size 18 (0x12) + .maxstack 1 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldstr "At IBlah.Blah_Internal_GetB" + IL_0006: call void [mscorlib]System.Console::WriteLine(string) + IL_000b: nop + IL_000c: ldc.i4.2 + IL_000d: stloc.0 + IL_000e: br.s IL_0010 + + IL_0010: ldloc.0 + IL_0011: ret + } // end of method IBlah_Impl::Blah_Internal_GetB + + .method family hidebysig instance int32 + Blah_Protected_GetC() cil managed + { + // Code size 18 (0x12) + .maxstack 1 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldstr "At IBlah.Blah_Protected_GetC" + IL_0006: call void [mscorlib]System.Console::WriteLine(string) + IL_000b: nop + IL_000c: ldc.i4.3 + IL_000d: stloc.0 + IL_000e: br.s IL_0010 + + IL_0010: ldloc.0 + IL_0011: ret + } // end of method IBlah_Impl::Blah_Protected_GetC +} // end of class IBlah + +.class interface private abstract auto ansi IFoo +{ + .method public hidebysig newslot virtual + instance int32 Foo(int32 a) cil managed + { + // Code size 20 (0x14) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldstr "At IFoo.Foo" + IL_0006: call void [mscorlib]System.Console::WriteLine(string) + IL_000b: nop + IL_000c: ldarg.1 + IL_000d: ldc.i4.1 + IL_000e: add + IL_000f: stloc.0 + IL_0010: br.s IL_0012 + + IL_0012: ldloc.0 + IL_0013: ret + } // end of method IFoo::Foo + +} // end of class IFoo + +.class interface private abstract auto ansi IBar +{ + .method public hidebysig newslot virtual + instance int32 Bar(int32 b) cil managed + { + // Code size 21 (0x15) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldstr "At IBar.Bar" + 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::Bar + +} // end of class IBar + +.class private auto ansi beforefieldinit Base + extends [mscorlib]System.Object + implements 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 [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method Base::.ctor + +} // end of class Base + +.class private auto ansi beforefieldinit FooBar + extends Base + implements IFoo, + IBar +{ + .method public hidebysig instance int32 + CallBlahProtected() cil managed + { + // Code size 12 (0xc) + .maxstack 1 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance int32 IBlah::Blah_Protected_GetC() + IL_0007: stloc.0 + IL_0008: br.s IL_000a + + IL_000a: ldloc.0 + IL_000b: ret + } // end of method FooBar::CallBlahProtected + + .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 Base::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method FooBar::.ctor + +} // end of class FooBar + +.class private auto ansi beforefieldinit Program + extends [mscorlib]System.Object +{ + .method public hidebysig static int32 Main() cil managed + { + .entrypoint + // Code size 158 (0x9e) + .maxstack 2 + .locals init (class FooBar V_0, + class IFoo V_1, + class IBar V_2, + class IBlah V_3, + int32 V_4) + IL_0000: nop + IL_0001: newobj instance void FooBar::.ctor() + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: stloc.1 + IL_0009: ldloc.0 + IL_000a: stloc.2 + IL_000b: ldloc.0 + IL_000c: stloc.3 + IL_000d: ldstr "Calling IFoo.Foo on FooBar - expecting default met" + + "hod on IFoo.Foo. " + IL_0012: call void [mscorlib]System.Console::WriteLine(string) + IL_0017: nop + IL_0018: ldloc.1 + IL_0019: ldc.i4.s 10 + IL_001b: callvirt instance int32 IFoo::Foo(int32) + IL_0020: ldc.i4.s 11 + IL_0022: ceq + IL_0024: ldstr "Calling IFoo.Foo on FooBar" + IL_0029: call void Test::Assert(bool, + string) + IL_002e: nop + IL_002f: ldstr "Calling IBar.Bar on FooBar - expecting default met" + + "hod on IBar.Bar. " + IL_0034: call void [mscorlib]System.Console::WriteLine(string) + IL_0039: nop + IL_003a: ldloc.2 + IL_003b: ldc.i4.s 10 + IL_003d: callvirt instance int32 IBar::Bar(int32) + IL_0042: ldc.i4.s 20 + IL_0044: ceq + IL_0046: ldstr "Calling IBar.Bar on FooBar" + IL_004b: call void Test::Assert(bool, + string) + IL_0050: nop + IL_0051: ldstr "Calling IBlah.Blah on FooBar - expecting default m" + + "ethod on IBlah.Blah from Base. " + IL_0056: call void [mscorlib]System.Console::WriteLine(string) + IL_005b: nop + IL_005c: ldloc.3 + IL_005d: ldc.i4.s 10 + IL_005f: callvirt instance int32 IBlah::Blah(int32) + IL_0064: ldc.i4.s 16 + IL_0066: ceq + IL_0068: ldstr "Calling IBlah.Blah on FooBar" + IL_006d: call void Test::Assert(bool, + string) + IL_0072: nop + IL_0073: ldstr "Calling FooBar.CallBlahProtected - expecting prote" + + "cted methods on interface can be called" + IL_0078: call void [mscorlib]System.Console::WriteLine(string) + IL_007d: nop + IL_007e: ldloc.0 + IL_007f: callvirt instance int32 FooBar::CallBlahProtected() + IL_0084: ldc.i4.3 + IL_0085: ceq + IL_0087: ldstr "Calling FooBar.CallBlahProtected" + IL_008c: call void Test::Assert(bool, + string) + IL_0091: nop + IL_0092: call int32 Test::Ret() + IL_0097: stloc.s V_4 + IL_0099: br.s IL_009b + + IL_009b: ldloc.s V_4 + IL_009d: ret + } // end of method Program::Main + + .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 Program::.ctor + +} // end of class Program + +.class private auto ansi beforefieldinit Test + extends [mscorlib]System.Object +{ + .field private static bool Pass + .method public hidebysig static int32 Ret() cil managed + { + // Code size 19 (0x13) + .maxstack 1 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldsfld bool Test::Pass + IL_0006: brtrue.s IL_000c + + IL_0008: ldc.i4.s 101 + IL_000a: br.s IL_000e + + IL_000c: ldc.i4.s 100 + IL_000e: stloc.0 + IL_000f: br.s IL_0011 + + IL_0011: ldloc.0 + IL_0012: ret + } // end of method Test::Ret + + .method public hidebysig static void Assert(bool cond, + string msg) cil managed + { + // Code size 47 (0x2f) + .maxstack 2 + .locals init (bool V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: stloc.0 + IL_0003: ldloc.0 + IL_0004: brfalse.s IL_0015 + + IL_0006: nop + IL_0007: ldstr "PASS" + IL_000c: call void [mscorlib]System.Console::WriteLine(string) + IL_0011: nop + IL_0012: nop + IL_0013: br.s IL_002e + + IL_0015: nop + IL_0016: ldstr "FAIL: " + IL_001b: ldarg.1 + IL_001c: call string [mscorlib]System.String::Concat(string, + string) + IL_0021: call void [mscorlib]System.Console::WriteLine(string) + IL_0026: nop + IL_0027: ldc.i4.0 + IL_0028: stsfld bool Test::Pass + IL_002d: nop + IL_002e: ret + } // end of method Test::Assert + + .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 Test::.ctor + + .method private hidebysig specialname rtspecialname static + void .cctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: stsfld bool Test::Pass + IL_0006: ret + } // end of method Test::.cctor + +} // end of class Test + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** +// WARNING: Created Win32 resource file simple.res diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/simple/simple.ilproj b/tests/src/Loader/classloader/DefaultInterfaceMethods/simple/simple.ilproj new file mode 100644 index 0000000000..0bf910b766 --- /dev/null +++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/simple/simple.ilproj @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" /> + <PropertyGroup> + <AssemblyName>simple</AssemblyName> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid> + <FileAlignment>512</FileAlignment> + <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + <ReferenceLocalMscorlib>true</ReferenceLocalMscorlib> + <OutputType>Exe</OutputType> + <CLRTestKind>BuildAndRun</CLRTestKind> + <CLRTestPriority>0</CLRTestPriority> + <!-- Use ILAsm that we just built for the new fixes required in default interface methods --> + <UseCustomILAsm>True</UseCustomILAsm> + </PropertyGroup> + + <ItemGroup> + <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies"> + <Visible>False</Visible> + </CodeAnalysisDependentAssemblyPaths> + </ItemGroup> + + <ItemGroup> + <Compile Include="simple.il" /> + </ItemGroup> + + + <ItemGroup> + <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> + </ItemGroup> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> +</Project> diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/valuetypes/valuetypes.cs b/tests/src/Loader/classloader/DefaultInterfaceMethods/valuetypes/valuetypes.cs new file mode 100644 index 0000000000..0cf1be9a92 --- /dev/null +++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/valuetypes/valuetypes.cs @@ -0,0 +1,94 @@ +using System; + +interface IValue +{ + int GetValue(); + void SetValue(int a); + int Add(int a); +} + +// This class is only needed to spit out IL that assumes 'this' is an object (and therefore don't box) +struct FooBarStruct_ : IValue +{ + public int GetValue() + { + return 0; + } + + public void SetValue(int val) + { + } + + public int Add(int a) + { + // Force cast and boxing + IValue valueIntf = this as IValue; + int val = valueIntf.GetValue(); + val += a; + valueIntf.SetValue(val); + return val; + } +} + +struct FooBarStruct : IValue +{ + public int _val; + + public int GetValue() + { + return _val; + } + + public void SetValue(int val) + { + _val = val; + } + + public int Add(int a) + { + // Dummy + return 0; + } +} + +class Program +{ + public static int Main() + { + FooBarStruct fooBar = new FooBarStruct(); + + fooBar._val = 10; + + IValue foo = (IValue) fooBar; + + Console.WriteLine("Calling IFoo.Foo on FooBarStruct"); + Test.Assert(foo.Add(10) == 20, "Calling default method IValue.Add on FooBarStruct failed"); + Test.Assert(fooBar.GetValue() == 10, "FooBarStruct value should remain unchanged"); + + return Test.Ret(); + } +} + +class Test +{ + private static bool Pass = true; + + public static int Ret() + { + return Pass? 100 : 101; + } + + public static void Assert(bool cond, string msg) + { + if (cond) + { + Console.WriteLine("PASS"); + } + else + { + Console.WriteLine("FAIL: " + msg); + Pass = false; + } + } +} + diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/valuetypes/valuetypes.il b/tests/src/Loader/classloader/DefaultInterfaceMethods/valuetypes/valuetypes.il new file mode 100644 index 0000000000..56c23f111e --- /dev/null +++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/valuetypes/valuetypes.il @@ -0,0 +1,252 @@ + +// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Copyright (c) Microsoft Corporation. All rights reserved. + + + +// Metadata version: v4.0.30319 +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. + .ver 4:0:0:0 +} +.assembly valuetypes +{ + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx + 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows. + + // --- The following custom attribute is added automatically, do not uncomment ------- + // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 ) + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.module valuetypes.exe +// MVID: {E191F723-B724-4D70-B3A8-CEA89FD033D3} +.imagebase 0x00400000 +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 // WINDOWS_CUI +.corflags 0x00000001 // ILONLY +// Image base: 0x01170000 + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class interface private abstract auto ansi IValue +{ + .method public hidebysig newslot abstract virtual + instance int32 GetValue() cil managed + { + } // end of method IValue::GetValue + + .method public hidebysig newslot abstract virtual + instance void SetValue(int32 a) cil managed + { + } // end of method IValue::SetValue + + .method public hidebysig newslot virtual + instance int32 Add(int32 a) cil managed + { + // Code size 26 (0x1a) + .maxstack 2 + .locals init (int32 V_0, + int32 V_1) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: call instance int32 IValue::GetValue() + IL_0007: stloc.0 + IL_0008: ldloc.0 + IL_0009: ldarg.1 + IL_000a: add + IL_000b: stloc.0 + IL_000c: ldarg.0 + IL_000d: ldloc.0 + IL_000e: call instance void IValue::SetValue(int32) + IL_0013: nop + IL_0014: ldloc.0 + IL_0015: stloc.1 + IL_0016: br.s IL_0018 + + IL_0018: ldloc.1 + IL_0019: ret + } // end of method IValue::Add + +} // end of class IValue + +.class private sequential ansi sealed beforefieldinit FooBarStruct + extends [mscorlib]System.ValueType + implements IValue +{ + .field public int32 _val + .method public hidebysig newslot virtual final + instance int32 GetValue() cil managed + { + // Code size 12 (0xc) + .maxstack 1 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldfld int32 FooBarStruct::_val + IL_0007: stloc.0 + IL_0008: br.s IL_000a + + IL_000a: ldloc.0 + IL_000b: ret + } // end of method FooBarStruct::GetValue + + .method public hidebysig newslot virtual final + instance void SetValue(int32 val) cil managed + { + // Code size 9 (0x9) + .maxstack 8 + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: ldarg.1 + IL_0003: stfld int32 FooBarStruct::_val + IL_0008: ret + } // end of method FooBarStruct::SetValue +} // end of class FooBarStruct + +.class private auto ansi beforefieldinit Program + extends [mscorlib]System.Object +{ + .method public hidebysig static int32 Main() cil managed + { + .entrypoint + .maxstack 2 + .locals init (valuetype FooBarStruct V_0, + class IValue V_1, + int32 V_2) + IL_0000: nop + IL_0001: ldloca.s V_0 + IL_0003: initobj FooBarStruct + IL_0009: ldloca.s V_0 + IL_000b: ldc.i4.s 10 + IL_000d: stfld int32 FooBarStruct::_val + IL_0012: ldloc.0 + IL_0013: box FooBarStruct + IL_0018: stloc.1 + IL_0019: ldstr "Calling IFoo.Foo on FooBarStruct" + IL_001e: call void [mscorlib]System.Console::WriteLine(string) + IL_0023: nop + IL_0024: ldloc.1 + IL_0025: ldc.i4.s 10 + IL_0027: callvirt instance int32 IValue::Add(int32) + IL_002c: ldc.i4.s 20 + IL_002e: ceq + IL_0030: ldstr "Calling default method IValue.Add on FooBarStruct " + + "failed" + IL_0035: call void Test::Assert(bool, + string) + IL_003a: nop + IL_003b: ldloca V_0 + callvirt instance int32 FooBarStruct::GetValue() + ldc.i4.s 10 + ceq + ldstr "FooBarStruct value should remain unchanged" + call void Test::Assert(bool, + string) + nop + call int32 Test::Ret() + ret + } // end of method Program::Main + + .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 Program::.ctor + +} // end of class Program + +.class private auto ansi beforefieldinit Test + extends [mscorlib]System.Object +{ + .field private static bool Pass + .method public hidebysig static int32 Ret() cil managed + { + // Code size 19 (0x13) + .maxstack 1 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldsfld bool Test::Pass + IL_0006: brtrue.s IL_000c + + IL_0008: ldc.i4.s 101 + IL_000a: br.s IL_000e + + IL_000c: ldc.i4.s 100 + IL_000e: stloc.0 + IL_000f: br.s IL_0011 + + IL_0011: ldloc.0 + IL_0012: ret + } // end of method Test::Ret + + .method public hidebysig static void Assert(bool cond, + string msg) cil managed + { + // Code size 47 (0x2f) + .maxstack 2 + .locals init (bool V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: stloc.0 + IL_0003: ldloc.0 + IL_0004: brfalse.s IL_0015 + + IL_0006: nop + IL_0007: ldstr "PASS" + IL_000c: call void [mscorlib]System.Console::WriteLine(string) + IL_0011: nop + IL_0012: nop + IL_0013: br.s IL_002e + + IL_0015: nop + IL_0016: ldstr "FAIL: " + IL_001b: ldarg.1 + IL_001c: call string [mscorlib]System.String::Concat(string, + string) + IL_0021: call void [mscorlib]System.Console::WriteLine(string) + IL_0026: nop + IL_0027: ldc.i4.0 + IL_0028: stsfld bool Test::Pass + IL_002d: nop + IL_002e: ret + } // end of method Test::Assert + + .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 Test::.ctor + + .method private hidebysig specialname rtspecialname static + void .cctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: stsfld bool Test::Pass + IL_0006: ret + } // end of method Test::.cctor + +} // end of class Test + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** +// WARNING: Created Win32 resource file valuetypes.res diff --git a/tests/src/Loader/classloader/DefaultInterfaceMethods/valuetypes/valuetypes.ilproj b/tests/src/Loader/classloader/DefaultInterfaceMethods/valuetypes/valuetypes.ilproj new file mode 100644 index 0000000000..12973e7559 --- /dev/null +++ b/tests/src/Loader/classloader/DefaultInterfaceMethods/valuetypes/valuetypes.ilproj @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" /> + <PropertyGroup> + <AssemblyName>valuetypes</AssemblyName> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid> + <FileAlignment>512</FileAlignment> + <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + <ReferenceLocalMscorlib>true</ReferenceLocalMscorlib> + <OutputType>Exe</OutputType> + <CLRTestKind>BuildAndRun</CLRTestKind> + <CLRTestPriority>0</CLRTestPriority> + <!-- Use ILAsm that we just built for the new fixes required in default interface methods --> + <UseCustomILAsm>True</UseCustomILAsm> + </PropertyGroup> + + <ItemGroup> + <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies"> + <Visible>False</Visible> + </CodeAnalysisDependentAssemblyPaths> + </ItemGroup> + + <ItemGroup> + <Compile Include="valuetypes.il" /> + </ItemGroup> + + + <ItemGroup> + <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> + </ItemGroup> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> +</Project> diff --git a/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/Except.il b/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/Except.il index 1e481a350d..b885c241da 100644 --- a/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/Except.il +++ b/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/Except.il @@ -14,11 +14,7 @@ .ver 4:0:0:0 } -.assembly Except.exe{ - //This byte field requests that this assembly not be verified at run time and corresponds to this C# declaration: - //[assembly:System.Security.Permissions.SecurityPermissionAttribute( [mscorlib]System.Security.Permissions.SecurityAction.RequestMinimum, Flags=System.Security.Permissions.SecurityPermissionFlag.SkipVerification )] - .permission reqmin ['mscorlib']System.Security.Permissions.SecurityPermissionAttribute ( "SkipVerification" = true ) -} +.assembly Except.exe {} .class Except { diff --git a/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/FiltCatch.il b/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/FiltCatch.il index f248a93fb7..0cffb2bd13 100644 --- a/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/FiltCatch.il +++ b/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/FiltCatch.il @@ -16,10 +16,7 @@ .ver 4:0:0:0 } -.assembly FiltCatch.exe{ - //This byte field requests that this assembly not be verified at run time and corresponds to this C# declaration: - //[assembly:System.Security.Permissions.SecurityPermissionAttribute( [mscorlib]System.Security.Permissions.SecurityAction.RequestMinimum, Flags=System.Security.Permissions.SecurityPermissionFlag.SkipVerification )] - .permission reqmin ['mscorlib']System.Security.Permissions.SecurityPermissionAttribute ( "SkipVerification" = true )} +.assembly FiltCatch.exe{} .class FiltCatch { diff --git a/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/FiltFallThru.il b/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/FiltFallThru.il index 4168fcd40b..57f32f00e0 100644 --- a/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/FiltFallThru.il +++ b/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/FiltFallThru.il @@ -16,10 +16,7 @@ .ver 4:0:0:0 } -.assembly FiltFallThru{ -//This byte field requests that this assembly not be verified at run time and corresponds to this C# declaration: - //[assembly:System.Security.Permissions.SecurityPermissionAttribute( [mscorlib]System.Security.Permissions.SecurityAction.RequestMinimum, Flags=System.Security.Permissions.SecurityPermissionFlag.SkipVerification )] - .permission reqmin ['mscorlib']System.Security.Permissions.SecurityPermissionAttribute ( "SkipVerification" = true )} +.assembly FiltFallThru{} .class FiltFallThru { diff --git a/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/Finally.il b/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/Finally.il index 06d1338a8c..266bd38f70 100644 --- a/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/Finally.il +++ b/tests/src/baseservices/exceptions/regressions/V1/SEH/asm/Finally.il @@ -14,11 +14,7 @@ .ver 4:0:0:0 } -.assembly Finally.exe{ -//This byte field requests that this assembly not be verified at run time and corresponds to this C# declaration: - //[assembly:System.Security.Permissions.SecurityPermissionAttribute( [mscorlib]System.Security.Permissions.SecurityAction.RequestMinimum, Flags=System.Security.Permissions.SecurityPermissionFlag.SkipVerification )] - .permission reqmin ['mscorlib']System.Security.Permissions.SecurityPermissionAttribute ( "SkipVerification" = true )} - +.assembly Finally.exe{} .class Finally { .field static int32 iResult |