}
CONTRACTL_END
- CompareState temp{};
+ TokenPairList tempList { nullptr };
+ CompareState temp{ &tempList };
if (state == NULL)
state = &temp;
argCnt1++;
TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(state->Visited);
- state->Visited = &newVisited;
+ *state->Visited = newVisited;
// Compare all parameters, incl. return parameter
while (argCnt1 > 0)
pSig1 - 1,
(DWORD)(pEndSig1 - pSig1) + 1);
TokenPairList newVisitedAlwaysForbidden = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(state->Visited);
- state->Visited = &newVisitedAlwaysForbidden;
+ *state->Visited = newVisitedAlwaysForbidden;
// Type constructors - The actual type is never permitted to participate in type equivalence.
if (!CompareElementType(
return FALSE;
}
- state->Visited = &newVisited;
+ *state->Visited = newVisited;
while (argCnt1 > 0)
{
if (!CompareElementType(
SigPointer inst1 = pSubst1->GetInst();
SigPointer inst2 = pSubst2->GetInst();
- CompareState state{ pVisited };
+ TokenPairList visited { pVisited };
+ CompareState state{ &visited };
for (DWORD i = 0; i < pTypeDef1->GetNumGenericArgs(); i++)
{
PCCOR_SIGNATURE startInst1 = inst1.GetPtr();
IfFailThrow(CorSigUncompressData_EndPtr(pSig1, pEndSig1, &ArgCount1));
IfFailThrow(CorSigUncompressData_EndPtr(pSig2, pEndSig2, &ArgCount2));
+ TokenPairList visited{ pVisited };
+
if (ArgCount1 != ArgCount2)
{
if ((callConv & IMAGE_CEE_CS_CALLCONV_MASK) != IMAGE_CEE_CS_CALLCONV_VARARG)
// to correctly handle overloads, where there are a number of varargs methods
// to pick from, like m1(int,...) and m2(int,int,...), etc.
- CompareState state{ pVisited };
+ CompareState state{ &visited };
// <= because we want to include a check of the return value!
for (i = 0; i <= ArgCount1; i++)
{
}
// do return type as well
- CompareState state{ pVisited };
+ CompareState state{ &visited };
for (i = 0; i <= ArgCount1; i++)
{
if (i == 0 && skipReturnTypeSig)
pEndSig1 = pSig1 + cSig1;
pEndSig2 = pSig2 + cSig2;
- CompareState state{ pVisited };
+ TokenPairList visited { pVisited };
+ CompareState state{ &visited };
return(CompareElementType(++pSig1, ++pSig2, pEndSig1, pEndSig2, pModule1, pModule2, NULL, NULL, &state));
}
// because they
// a) are vacuous, and
// b) may be implicit (ie. absent) in the overridden variable's declaration
+ TokenPairList newVisited { nullptr };
if (!(CompareTypeDefOrRefOrSpec(pModule1, tkConstraintType1, NULL,
- CoreLibBinder::GetModule(), g_pObjectClass->GetCl(), NULL, NULL) ||
+ CoreLibBinder::GetModule(), g_pObjectClass->GetCl(), NULL, &newVisited) ||
(((specialConstraints1 & gpNotNullableValueTypeConstraint) != 0) &&
(CompareTypeDefOrRefOrSpec(pModule1, tkConstraintType1, NULL,
- CoreLibBinder::GetModule(), g_pValueTypeClass->GetCl(), NULL, NULL)))))
+ CoreLibBinder::GetModule(), g_pValueTypeClass->GetCl(), NULL, &newVisited)))))
{
HENUMInternalHolder hEnum2(pInternalImport2);
mdGenericParamConstraint tkConstraint2;
IfFailThrow(pInternalImport2->GetGenericParamConstraintProps(tkConstraint2, &tkParam2, &tkConstraintType2));
_ASSERTE(tkParam2 == tok2);
- found = CompareTypeDefOrRefOrSpec(pModule1, tkConstraintType1, pSubst1, pModule2, tkConstraintType2, pSubst2, NULL);
+ found = CompareTypeDefOrRefOrSpec(pModule1, tkConstraintType1, pSubst1, pModule2, tkConstraintType2, pSubst2, &newVisited);
}
if (!found)
{
// infinite recursion when types refer to each other in a cycle, e.g. a delegate that takes itself as
// a parameter or a struct that declares a field of itself (illegal but we don't know at this point).
//
-class TokenPairList
+class TokenPairList final
{
public:
+
// Chain using this constructor when comparing two typedefs for equivalence.
TokenPairList(mdToken token1, ModuleBase *pModule1, mdToken token2, ModuleBase *pModule2, TokenPairList *pNext)
: m_token1(token1), m_token2(token2),
static TokenPairList AdjustForTypeSpec(TokenPairList *pTemplate, ModuleBase *pTypeSpecModule, PCCOR_SIGNATURE pTypeSpecSig, DWORD cbTypeSpecSig);
static TokenPairList AdjustForTypeEquivalenceForbiddenScope(TokenPairList *pTemplate);
-private:
TokenPairList(TokenPairList *pTemplate)
: m_token1(pTemplate ? pTemplate->m_token1 : mdTokenNil),
m_token2(pTemplate ? pTemplate->m_token2 : mdTokenNil),
m_pNext(pTemplate ? pTemplate->m_pNext : NULL)
{ LIMITED_METHOD_CONTRACT; }
+private:
mdToken m_token1, m_token2;
ModuleBase *m_pModule1, *m_pModule2;
BOOL m_bInTypeEquivalenceForbiddenScope;