1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-15 23:04:09 +02:00

Allow some warnings during specialization

This commit is contained in:
Brian Fiete 2021-11-01 13:46:24 -07:00
parent 487ef16efd
commit d593488591
5 changed files with 188 additions and 138 deletions

View file

@ -173,6 +173,10 @@ namespace System
// or the memory would already be registered with the GC // or the memory would already be registered with the GC
} }
public static mixin Mark<T>(T val)
{
}
public static mixin Mark<TSizedArray, T, Size>(TSizedArray val) where Size : const int where TSizedArray : SizedArray<T, Size> public static mixin Mark<TSizedArray, T, Size>(TSizedArray val) where Size : const int where TSizedArray : SizedArray<T, Size>
{ {
#if BF_ENABLE_REALTIME_LEAK_CHECK #if BF_ENABLE_REALTIME_LEAK_CHECK

View file

@ -2844,65 +2844,9 @@ bool BfModule::IsSkippingExtraResolveChecks()
return mCompiler->IsSkippingExtraResolveChecks(); return mCompiler->IsSkippingExtraResolveChecks();
} }
BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPersistent, bool deferError) bool BfModule::AddErrorContext(StringImpl& errorString, BfAstNode* refNode, bool& isWhileSpecializing)
{ {
BP_ZONE("BfModule::Fail");
if (mIgnoreErrors)
{
mHadIgnoredError = true;
if (mAttributeState != NULL)
mAttributeState->mFlags = (BfAttributeState::Flags)(mAttributeState->mFlags | BfAttributeState::Flag_HadError);
return NULL;
}
if (!mReportErrors)
{
mCompiler->mPassInstance->SilentFail();
return NULL;
}
if (refNode != NULL)
refNode = BfNodeToNonTemporary(refNode);
//BF_ASSERT(refNode != NULL);
if (mIsComptimeModule)
{
if ((mCompiler->mCEMachine->mCurContext != NULL) && (mCompiler->mCEMachine->mCurContext->mCurTargetSrc != NULL))
{
BfError* bfError = mCompiler->mPassInstance->Fail("Comptime method generation had errors", mCompiler->mCEMachine->mCurContext->mCurTargetSrc);
if (bfError != NULL)
mCompiler->mPassInstance->MoreInfo(error, refNode);
return bfError;
}
mHadBuildError = true;
return NULL;
}
if (mCurMethodInstance != NULL)
mCurMethodInstance->mHasFailed = true;
if ((mCurTypeInstance != NULL) && (mCurTypeInstance->IsUnspecializedTypeVariation()))
return NULL;
if ((mCurMethodInstance != NULL) && (mCurMethodInstance->IsOrInUnspecializedVariation()))
return NULL; // Ignore errors on unspecialized variations, they are always dups
if (!mHadBuildError)
mHadBuildError = true;
if (mParentModule != NULL)
mParentModule->mHadBuildError = true;
if (mCurTypeInstance != NULL)
AddFailType(mCurTypeInstance);
BfLogSysM("BfModule::Fail module %p type %p %s\n", this, mCurTypeInstance, error.c_str());
String errorString = error;
bool isWhileSpecializing = false;
bool isWhileSpecializingMethod = false; bool isWhileSpecializingMethod = false;
if ((mIsSpecialModule) && (mModuleName == "vdata")) if ((mIsSpecialModule) && (mModuleName == "vdata"))
errorString += StrFormat("\n while generating vdata for project '%s'", mProject->mName.c_str()); errorString += StrFormat("\n while generating vdata for project '%s'", mProject->mName.c_str());
if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mMethodDef->mMethodType == BfMethodType_CtorCalcAppend)) if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mMethodDef->mMethodType == BfMethodType_CtorCalcAppend))
@ -2975,7 +2919,7 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers
hadMethodInstance = true; hadMethodInstance = true;
if (!_CheckMethodInstance(methodInstance)) if (!_CheckMethodInstance(methodInstance))
return NULL; return false;
checkMethodState = checkMethodState->mPrevMethodState; checkMethodState = checkMethodState->mPrevMethodState;
} }
} }
@ -2983,21 +2927,83 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers
if ((!hadMethodInstance) && (mCurMethodInstance != NULL)) if ((!hadMethodInstance) && (mCurMethodInstance != NULL))
{ {
if (!_CheckMethodInstance(mCurMethodInstance)) if (!_CheckMethodInstance(mCurMethodInstance))
return NULL; return false;
} }
} }
BfError* bfError = NULL;
if (isWhileSpecializing)
deferError = true;
if ((!isWhileSpecializing) && (mCurTypeInstance != NULL) && ((mCurTypeInstance->IsGenericTypeInstance()) && (!mCurTypeInstance->IsUnspecializedType()))) if ((!isWhileSpecializing) && (mCurTypeInstance != NULL) && ((mCurTypeInstance->IsGenericTypeInstance()) && (!mCurTypeInstance->IsUnspecializedType())))
{ {
errorString += StrFormat("\n while specializing type '%s'", TypeToString(mCurTypeInstance).c_str()); errorString += StrFormat("\n while specializing type '%s'", TypeToString(mCurTypeInstance).c_str());
isWhileSpecializing = true; isWhileSpecializing = true;
} }
return true;
}
BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPersistent, bool deferError)
{
BP_ZONE("BfModule::Fail");
if (mIgnoreErrors)
{
mHadIgnoredError = true;
if (mAttributeState != NULL)
mAttributeState->mFlags = (BfAttributeState::Flags)(mAttributeState->mFlags | BfAttributeState::Flag_HadError);
return NULL;
}
if (!mReportErrors)
{
mCompiler->mPassInstance->SilentFail();
return NULL;
}
if (refNode != NULL)
refNode = BfNodeToNonTemporary(refNode);
//BF_ASSERT(refNode != NULL);
if (mIsComptimeModule)
{
if ((mCompiler->mCEMachine->mCurContext != NULL) && (mCompiler->mCEMachine->mCurContext->mCurTargetSrc != NULL))
{
BfError* bfError = mCompiler->mPassInstance->Fail("Comptime method generation had errors", mCompiler->mCEMachine->mCurContext->mCurTargetSrc);
if (bfError != NULL)
mCompiler->mPassInstance->MoreInfo(error, refNode);
return bfError;
}
mHadBuildError = true;
return NULL;
}
if (mCurMethodInstance != NULL)
mCurMethodInstance->mHasFailed = true;
if ((mCurTypeInstance != NULL) && (mCurTypeInstance->IsUnspecializedTypeVariation()))
return NULL;
if ((mCurMethodInstance != NULL) && (mCurMethodInstance->IsOrInUnspecializedVariation()))
return NULL; // Ignore errors on unspecialized variations, they are always dups
if (!mHadBuildError)
mHadBuildError = true;
if (mParentModule != NULL)
mParentModule->mHadBuildError = true;
if (mCurTypeInstance != NULL)
AddFailType(mCurTypeInstance);
BfLogSysM("BfModule::Fail module %p type %p %s\n", this, mCurTypeInstance, error.c_str());
String errorString = error;
bool isWhileSpecializing = false;
if (!AddErrorContext(errorString, refNode, isWhileSpecializing))
return false;
BfError* bfError = NULL;
if (isWhileSpecializing)
deferError = true;
if (!mHadBuildError) if (!mHadBuildError)
mHadBuildError = true; mHadBuildError = true;
@ -3085,7 +3091,7 @@ BfError* BfModule::FailAfter(const StringImpl& error, BfAstNode* refNode)
return bfError; return bfError;
} }
BfError* BfModule::Warn(int warningNum, const StringImpl& warning, BfAstNode* refNode, bool isPersistent) BfError* BfModule::Warn(int warningNum, const StringImpl& warning, BfAstNode* refNode, bool isPersistent, bool showInSpecialized)
{ {
if (mIgnoreErrors || mIgnoreWarnings) if (mIgnoreErrors || mIgnoreWarnings)
return NULL; return NULL;
@ -3118,16 +3124,28 @@ BfError* BfModule::Warn(int warningNum, const StringImpl& warning, BfAstNode* re
if (mCurMethodInstance != NULL) if (mCurMethodInstance != NULL)
{ {
if (mCurMethodInstance->IsSpecializedGenericMethodOrType()) if (mCurMethodInstance->IsSpecializedGenericMethodOrType())
{
if (!showInSpecialized)
return NULL; return NULL;
}
if (mCurMethodInstance->mMethodDef->mMethodType == BfMethodType_CtorCalcAppend) if (mCurMethodInstance->mMethodDef->mMethodType == BfMethodType_CtorCalcAppend)
return NULL; // No ctorCalcAppend warnings return NULL; // No ctorCalcAppend warnings
} }
if ((mCurTypeInstance != NULL) && (mCurTypeInstance->IsSpecializedType())) if ((mCurTypeInstance != NULL) && (mCurTypeInstance->IsSpecializedType()))
{
if (!showInSpecialized)
return NULL; return NULL;
}
if (refNode != NULL) if (refNode != NULL)
refNode = BfNodeToNonTemporary(refNode); refNode = BfNodeToNonTemporary(refNode);
String warningString = warning;
bool isWhileSpecializing = false;
if (!AddErrorContext(warningString, refNode, isWhileSpecializing))
return false;
bool deferWarning = isWhileSpecializing;
if ((mCurMethodState != NULL) && (mCurMethodState->mMixinState != NULL)) if ((mCurMethodState != NULL) && (mCurMethodState->mMixinState != NULL))
{ {
// We used to bubble up warnings into the mixin injection site, BUT // We used to bubble up warnings into the mixin injection site, BUT
@ -3139,17 +3157,18 @@ BfError* BfModule::Warn(int warningNum, const StringImpl& warning, BfAstNode* re
{ {
BfError* bfError = mCompiler->mPassInstance->Warn(warningNum, "Emitted code had errors", mCurMethodState->mEmitRefNode); BfError* bfError = mCompiler->mPassInstance->Warn(warningNum, "Emitted code had errors", mCurMethodState->mEmitRefNode);
if (bfError != NULL) if (bfError != NULL)
mCompiler->mPassInstance->MoreInfo(warning, refNode); mCompiler->mPassInstance->MoreInfo(warningString, refNode);
return bfError; return bfError;
} }
BfError* bfError; BfError* bfError;
if (refNode != NULL) if (refNode != NULL)
bfError = mCompiler->mPassInstance->WarnAt(warningNum, warning, refNode->GetSourceData(), refNode->GetSrcStart(), refNode->GetSrcLength()); bfError = mCompiler->mPassInstance->WarnAt(warningNum, warningString, refNode->GetSourceData(), refNode->GetSrcStart(), refNode->GetSrcLength());
else else
bfError = mCompiler->mPassInstance->Warn(warningNum, warning); bfError = mCompiler->mPassInstance->Warn(warningNum, warningString);
if (bfError != NULL) if (bfError != NULL)
{ {
bfError->mIsWhileSpecializing = isWhileSpecializing;
bfError->mProject = mProject; bfError->mProject = mProject;
AddFailType(mCurTypeInstance); AddFailType(mCurTypeInstance);
@ -3229,7 +3248,7 @@ void BfModule::CheckErrorAttributes(BfTypeInstance* typeInstance, BfMethodInstan
if (isError) if (isError)
error = Fail(err, targetSrc); error = Fail(err, targetSrc);
else else
error = Warn(0, err, targetSrc); error = Warn(0, err, targetSrc, false, true);
if (error != NULL) if (error != NULL)
_AddDeclarationMoreInfo(); _AddDeclarationMoreInfo();
} }
@ -3262,7 +3281,7 @@ void BfModule::CheckErrorAttributes(BfTypeInstance* typeInstance, BfMethodInstan
if (str != NULL) if (str != NULL)
err += *str; err += *str;
err += "'"; err += "'";
if (Warn(0, err, targetSrc) != NULL) if (Warn(0, err, targetSrc, false, true) != NULL)
_AddDeclarationMoreInfo(); _AddDeclarationMoreInfo();
} }
} }
@ -7590,7 +7609,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
if (origCheckArgType->IsRef()) if (origCheckArgType->IsRef())
origCheckArgType = origCheckArgType->GetUnderlyingType(); origCheckArgType = origCheckArgType->GetUnderlyingType();
bool argMayBeReferenceType = false; bool argIsReferenceType = false;
int checkGenericParamFlags = 0; int checkGenericParamFlags = 0;
if (checkArgType->IsGenericParam()) if (checkArgType->IsGenericParam())
@ -7600,18 +7619,18 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
if (checkGenericParamInst->mTypeConstraint != NULL) if (checkGenericParamInst->mTypeConstraint != NULL)
checkArgType = checkGenericParamInst->mTypeConstraint; checkArgType = checkGenericParamInst->mTypeConstraint;
if ((checkGenericParamFlags & (BfGenericParamFlag_Struct | BfGenericParamFlag_StructPtr)) != 0) // if ((checkGenericParamFlags & (BfGenericParamFlag_Struct | BfGenericParamFlag_StructPtr)) != 0)
{ // {
argMayBeReferenceType = false; // argMayBeReferenceType = false;
} // }
else // else
{ // {
argMayBeReferenceType = true; // argMayBeReferenceType = true;
} // }
} }
if (checkArgType->IsObjectOrInterface()) if (checkArgType->IsObjectOrInterface())
argMayBeReferenceType = true; argIsReferenceType = true;
BfTypeInstance* typeConstraintInst = NULL; BfTypeInstance* typeConstraintInst = NULL;
if (genericParamInst->mTypeConstraint != NULL) if (genericParamInst->mTypeConstraint != NULL)
@ -7636,7 +7655,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
} }
if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Class) && if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Class) &&
((checkGenericParamFlags & (BfGenericParamFlag_Class | BfGenericParamFlag_Var)) == 0) && (!argMayBeReferenceType)) ((checkGenericParamFlags & (BfGenericParamFlag_Class | BfGenericParamFlag_Var)) == 0) && (!argIsReferenceType))
{ {
if ((!ignoreErrors) && (PreFail())) if ((!ignoreErrors) && (PreFail()))
*errorOut = Fail(StrFormat("The type '%s' must be a reference type in order to use it as parameter '%s' for '%s'", *errorOut = Fail(StrFormat("The type '%s' must be a reference type in order to use it as parameter '%s' for '%s'",

View file

@ -1517,10 +1517,11 @@ public:
void SetFail(); void SetFail();
void VerifyOnDemandMethods(); void VerifyOnDemandMethods();
bool IsSkippingExtraResolveChecks(); bool IsSkippingExtraResolveChecks();
bool AddErrorContext(StringImpl& errorString, BfAstNode* refNode, bool& isWhileSpecializing);
BfError* Fail(const StringImpl& error, BfAstNode* refNode = NULL, bool isPersistent = false, bool deferError = false); BfError* Fail(const StringImpl& error, BfAstNode* refNode = NULL, bool isPersistent = false, bool deferError = false);
BfError* FailInternal(const StringImpl& error, BfAstNode* refNode = NULL); BfError* FailInternal(const StringImpl& error, BfAstNode* refNode = NULL);
BfError* FailAfter(const StringImpl& error, BfAstNode* refNode); BfError* FailAfter(const StringImpl& error, BfAstNode* refNode);
BfError* Warn(int warningNum, const StringImpl& warning, BfAstNode* refNode = NULL, bool isPersistent = false); BfError* Warn(int warningNum, const StringImpl& warning, BfAstNode* refNode = NULL, bool isPersistent = false, bool showInSpecialized = false);
void CheckErrorAttributes(BfTypeInstance* typeInstance, BfMethodInstance* methodInstance, BfCustomAttributes* customAttributes, BfAstNode* targetSrc); void CheckErrorAttributes(BfTypeInstance* typeInstance, BfMethodInstance* methodInstance, BfCustomAttributes* customAttributes, BfAstNode* targetSrc);
void CheckRangeError(BfType* type, BfAstNode* refNode); void CheckRangeError(BfType* type, BfAstNode* refNode);
bool CheckCircularDataError(); bool CheckCircularDataError();

View file

@ -1589,7 +1589,7 @@ void BfPassInstance::SilentFail()
mFailedIdx++; mFailedIdx++;
} }
BfError* BfPassInstance::WarnAt(int warningNumber, const StringImpl& warning, BfSourceData* bfSource, int srcIdx, int srcLen) BfError* BfPassInstance::WarnAt(int warningNumber, const StringImpl& warning, BfSourceData* bfSource, int srcIdx, int srcLen, bool isDeferred)
{ {
mLastWasAdded = false; mLastWasAdded = false;
if ((int) mErrors.size() >= sMaxErrors) if ((int) mErrors.size() >= sMaxErrors)
@ -1599,7 +1599,7 @@ BfError* BfPassInstance::WarnAt(int warningNumber, const StringImpl& warning, Bf
if ((bfParser != NULL) && (warningNumber > 0) && (!bfParser->IsWarningEnabledAtSrcIndex(warningNumber, srcIdx))) if ((bfParser != NULL) && (warningNumber > 0) && (!bfParser->IsWarningEnabledAtSrcIndex(warningNumber, srcIdx)))
return NULL; return NULL;
if (!WantsRangeRecorded(bfParser, srcIdx, srcLen, true)) if (!WantsRangeRecorded(bfParser, srcIdx, srcLen, true, isDeferred))
return NULL; return NULL;
mWarnIdx++; mWarnIdx++;
@ -1614,12 +1614,15 @@ BfError* BfPassInstance::WarnAt(int warningNumber, const StringImpl& warning, Bf
errorVal->mError = warning; errorVal->mError = warning;
errorVal->mSrcStart = srcIdx; errorVal->mSrcStart = srcIdx;
errorVal->mSrcEnd = srcIdx + srcLen; errorVal->mSrcEnd = srcIdx + srcLen;
errorVal->mIsDeferred = isDeferred;
FixSrcStartAndEnd(bfSource, errorVal->mSrcStart, errorVal->mSrcEnd); FixSrcStartAndEnd(bfSource, errorVal->mSrcStart, errorVal->mSrcEnd);
mErrorSet.Add(BfErrorEntry(errorVal)); mErrorSet.Add(BfErrorEntry(errorVal));
mErrors.push_back(errorVal); mErrors.push_back(errorVal);
++mWarningCount; ++mWarningCount;
mLastWasAdded = true; mLastWasAdded = true;
if (!isDeferred)
{
mLastWasDisplayed = WantsRangeDisplayed(bfParser, srcIdx, srcLen, true); mLastWasDisplayed = WantsRangeDisplayed(bfParser, srcIdx, srcLen, true);
if (mLastWasDisplayed) if (mLastWasDisplayed)
{ {
@ -1630,6 +1633,7 @@ BfError* BfPassInstance::WarnAt(int warningNumber, const StringImpl& warning, Bf
errorStart += StrFormat(": BF%04d", warningNumber); errorStart += StrFormat(": BF%04d", warningNumber);
MessageAt(":warn", errorStart + ": " + warning, bfParser, srcIdx); MessageAt(":warn", errorStart + ": " + warning, bfParser, srcIdx);
} }
}
return errorVal; return errorVal;
} }
@ -1645,7 +1649,7 @@ BfError* BfPassInstance::Warn(int warningNumber, const StringImpl& warning)
return NULL; return NULL;
} }
BfError* BfPassInstance::Warn(int warningNumber, const StringImpl& warning, BfAstNode* refNode) BfError* BfPassInstance::Warn(int warningNumber, const StringImpl& warning, BfAstNode* refNode, bool isDeferred)
{ {
BP_ZONE("BfPassInstance::Warn"); BP_ZONE("BfPassInstance::Warn");
@ -1666,7 +1670,7 @@ BfError* BfPassInstance::Warn(int warningNumber, const StringImpl& warning, BfAs
} }
if (refNode != NULL) if (refNode != NULL)
return WarnAt(warningNumber, warning, refNode->GetSourceData(), refNode->GetSrcStart(), refNode->GetSrcLength()); return WarnAt(warningNumber, warning, refNode->GetSourceData(), refNode->GetSrcStart(), refNode->GetSrcLength(), isDeferred);
else else
return Warn(warningNumber, warning); return Warn(warningNumber, warning);
} }
@ -1798,15 +1802,39 @@ void BfPassInstance::TryFlushDeferredError()
// This can happen in the case of an internal compiler error, where we believe we've satisfied // This can happen in the case of an internal compiler error, where we believe we've satisfied
// generic constraints but we generate an error on the specialization but not the unspecialized version // generic constraints but we generate an error on the specialization but not the unspecialized version
bool hasDisplayedError = false; bool hasDisplayedError = false;
bool hasDisplayedWarning = false;
for (int pass = 0; pass < 2; pass++) for (int pass = 0; pass < 2; pass++)
{ {
for (auto& error : mErrors) for (auto& error : mErrors)
{ {
if (!error->mIsWarning) if (error->mIsWarning)
{
if (!error->mIsDeferred)
hasDisplayedWarning = true;
else if ((pass == 1) && (!hasDisplayedWarning))
{
String errorText = "WARNING ";
if (error->mWarningNumber > 0)
errorText += StrFormat(": BF%04d", error->mWarningNumber);
errorText += ": ";
errorText += error->mError;
MessageAt(":warning", errorText, error->mSource, error->mSrcStart, error->mSrcEnd - error->mSrcStart);
for (auto moreInfo : error->mMoreInfo)
{
if (moreInfo->mSource != NULL)
MessageAt(":warning", " > " + moreInfo->mInfo, moreInfo->mSource, moreInfo->mSrcStart, moreInfo->mSrcEnd - moreInfo->mSrcStart);
else
OutputLine(":warning " + moreInfo->mInfo);
}
}
}
else
{ {
if (!error->mIsDeferred) if (!error->mIsDeferred)
hasDisplayedError = true; hasDisplayedError = true;
else if (pass == 1) else if ((pass == 1) && (!hasDisplayedError))
{ {
MessageAt(":error", "ERROR: " + error->mError, error->mSource, error->mSrcStart, error->mSrcEnd - error->mSrcStart); MessageAt(":error", "ERROR: " + error->mError, error->mSource, error->mSrcStart, error->mSrcEnd - error->mSrcStart);
@ -1820,9 +1848,6 @@ void BfPassInstance::TryFlushDeferredError()
} }
} }
} }
if ((pass == 0) && (hasDisplayedError))
break;
} }
} }

View file

@ -1383,9 +1383,10 @@ public:
void MessageAt(const StringImpl& msgPrefix, const StringImpl& error, BfSourceData* bfSource, int srcIdx, int srcLen = 1, BfFailFlags flags = BfFailFlag_None); void MessageAt(const StringImpl& msgPrefix, const StringImpl& error, BfSourceData* bfSource, int srcIdx, int srcLen = 1, BfFailFlags flags = BfFailFlag_None);
void FixSrcStartAndEnd(BfSourceData* source, int& startIdx, int& endIdx); void FixSrcStartAndEnd(BfSourceData* source, int& startIdx, int& endIdx);
BfError* WarnAt(int warningNumber, const StringImpl& warning, BfSourceData* bfSource, int srcIdx, int srcLen = 1); BfError* WarnAt(int warningNumber, const StringImpl& warning, BfSourceData* bfSource, int srcIdx, int srcLen = 1, bool isDeferred = false);
BfError* Warn(int warningNumber, const StringImpl& warning); BfError* Warn(int warningNumber, const StringImpl& warning);
BfError* Warn(int warningNumber, const StringImpl& warning, BfAstNode* refNode); BfError* Warn(int warningNumber, const StringImpl& warning, BfAstNode* refNode, bool isDeferred = false);
BfError* DeferWarn(int warningNumber, const StringImpl& warning, BfAstNode* refNode);
BfError* WarnAfter(int warningNumber, const StringImpl& warning, BfAstNode* refNode); BfError* WarnAfter(int warningNumber, const StringImpl& warning, BfAstNode* refNode);
BfError* WarnAfterAt(int warningNumber, const StringImpl& error, BfSourceData* bfSource, int srcIdx); BfError* WarnAfterAt(int warningNumber, const StringImpl& error, BfSourceData* bfSource, int srcIdx);