1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-09 03:52:19 +02:00

Improved string interpolation warnings/errors

This commit is contained in:
Brian Fiete 2020-12-03 05:58:15 -08:00
parent 11a7d2dd1c
commit adf46175cf
3 changed files with 68 additions and 14 deletions

View file

@ -4530,12 +4530,14 @@ void BfExprEvaluator::ResolveArgValues(BfResolvedArgs& resolvedArgs, BfResolveAr
//printf("Args: %p %p %d\n", resolvedArgs.mArguments, resolvedArgs.mArguments->mVals, resolvedArgs.mArguments->mSize); //printf("Args: %p %p %d\n", resolvedArgs.mArguments, resolvedArgs.mArguments->mVals, resolvedArgs.mArguments->mSize);
BfExpression* argExpr = NULL; BfExpression* argExpr = NULL;
bool isDeferredArg = false;
int curArgIdx = -1; int curArgIdx = -1;
if (deferredArgIdx < deferredArgs.size()) if (deferredArgIdx < deferredArgs.size())
{ {
argExpr = deferredArgs[deferredArgIdx++]; argExpr = deferredArgs[deferredArgIdx++];
isDeferredArg = true;
} }
else if (argIdx >= argCount) else if (argIdx >= argCount)
{ {
@ -4569,6 +4571,9 @@ void BfExprEvaluator::ResolveArgValues(BfResolvedArgs& resolvedArgs, BfResolveAr
} }
BfResolvedArg resolvedArg; BfResolvedArg resolvedArg;
if (isDeferredArg)
resolvedArg.mArgFlags = (BfArgFlags)(resolvedArg.mArgFlags | BfArgFlag_StringInterpolateArg);
BfExprEvaluator exprEvaluator(mModule); BfExprEvaluator exprEvaluator(mModule);
exprEvaluator.mResolveGenericParam = (flags & BfResolveArgFlag_AllowUnresolvedTypes) == 0; exprEvaluator.mResolveGenericParam = (flags & BfResolveArgFlag_AllowUnresolvedTypes) == 0;
exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator.mBfEvalExprFlags | BfEvalExprFlags_AllowRefExpr | BfEvalExprFlags_AllowOutExpr); exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator.mBfEvalExprFlags | BfEvalExprFlags_AllowRefExpr | BfEvalExprFlags_AllowOutExpr);
@ -5891,7 +5896,21 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
errorRef = targetSrc; errorRef = targetSrc;
BfError* error; BfError* error;
if ((prevBindResult.mPrevVal != NULL) && (prevBindResult.mPrevVal->mBindType != NULL)) if ((argValues[argExprIdx].mArgFlags & BfArgFlag_StringInterpolateArg) != 0)
{
int checkIdx = argExprIdx - 1;
while (checkIdx >= 0)
{
if ((argValues[checkIdx].mArgFlags & BfArgFlag_StringInterpolateFormat) != 0)
{
errorRef = argValues[checkIdx].mExpression;
break;
}
checkIdx--;
}
error = mModule->Fail("Expanded string interpolation generates too many arguments. If string allocation was intended then consider adding a specifier such as 'scope'.", errorRef);
}
else if ((prevBindResult.mPrevVal != NULL) && (prevBindResult.mPrevVal->mBindType != NULL))
error = mModule->Fail(StrFormat("Method '%s' has too few parameters to bind to '%s'.", mModule->MethodToString(methodInstance).c_str(), mModule->TypeToString(prevBindResult.mPrevVal->mBindType).c_str()), errorRef); error = mModule->Fail(StrFormat("Method '%s' has too few parameters to bind to '%s'.", mModule->MethodToString(methodInstance).c_str(), mModule->TypeToString(prevBindResult.mPrevVal->mBindType).c_str()), errorRef);
else else
error = mModule->Fail(StrFormat("Too many arguments, expected %d fewer.", (int)argValues.size() - argExprIdx), errorRef); error = mModule->Fail(StrFormat("Too many arguments, expected %d fewer.", (int)argValues.size() - argExprIdx), errorRef);
@ -5939,20 +5958,20 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
{ {
if (wantsSplat) if (wantsSplat)
{ {
SplatArgs(lookupVal, irArgs); SplatArgs(lookupVal, irArgs);
} }
else if (paramType->IsRef()) else if (paramType->IsRef())
{ {
irArgs.push_back(lookupVal.mValue); irArgs.push_back(lookupVal.mValue);
} }
else else
PushArg(lookupVal, irArgs, true); PushArg(lookupVal, irArgs, true);
} }
} }
paramIdx++; paramIdx++;
continue; continue;
} }
wantType = methodInstance->GetParamType(paramIdx); wantType = methodInstance->GetParamType(paramIdx);
if (wantType->IsSelf()) if (wantType->IsSelf())
wantType = methodInstance->GetOwner(); wantType = methodInstance->GetOwner();
@ -5968,7 +5987,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
//TODO: Check to see if it's a direct array pass //TODO: Check to see if it's a direct array pass
if (argIdx < (int)argValues.size()) if (argIdx < (int)argValues.size())
{ {
auto argValue = argValues[argIdx].mTypedValue; auto argValue = argValues[argIdx].mTypedValue;
if ((argValue.IsParams()) /*&& (mModule->CanCast(argValue, wantType))*/) if ((argValue.IsParams()) /*&& (mModule->CanCast(argValue, wantType))*/)
isDirectPass = true; isDirectPass = true;
@ -6002,7 +6021,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
mModule->Fail("INTERNAL ERROR: Unable to find array 'length' field", targetSrc); mModule->Fail("INTERNAL ERROR: Unable to find array 'length' field", targetSrc);
return BfTypedValue(); return BfTypedValue();
} }
auto addr = mModule->mBfIRBuilder->CreateInBoundsGEP(arrayBits, 0, 1); auto addr = mModule->mBfIRBuilder->CreateInBoundsGEP(arrayBits, 0, 1);
if (arrayLengthBitCount == 64) if (arrayLengthBitCount == 64)
mModule->mBfIRBuilder->CreateAlignedStore(mModule->GetConstValue64(numElements), addr, 8); mModule->mBfIRBuilder->CreateAlignedStore(mModule->GetConstValue64(numElements), addr, 8);
@ -6016,10 +6035,10 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
auto genericTypeInst = wantType->ToGenericTypeInstance(); auto genericTypeInst = wantType->ToGenericTypeInstance();
expandedParamsElementType = genericTypeInst->mGenericTypeInfo->mTypeGenericArguments[0]; expandedParamsElementType = genericTypeInst->mGenericTypeInfo->mTypeGenericArguments[0];
expandedParamsArray = BfTypedValue(mModule->CreateAlloca(wantType), wantType, true); expandedParamsArray = BfTypedValue(mModule->CreateAlloca(wantType), wantType, true);
expandedParamAlloca = mModule->CreateAlloca(genericTypeInst->mGenericTypeInfo->mTypeGenericArguments[0], true, NULL, mModule->GetConstValue(numElements)); expandedParamAlloca = mModule->CreateAlloca(genericTypeInst->mGenericTypeInfo->mTypeGenericArguments[0], true, NULL, mModule->GetConstValue(numElements));
mModule->mBfIRBuilder->CreateStore(expandedParamAlloca, mModule->mBfIRBuilder->CreateInBoundsGEP(expandedParamsArray.mValue, 0, 1)); mModule->mBfIRBuilder->CreateStore(expandedParamAlloca, mModule->mBfIRBuilder->CreateInBoundsGEP(expandedParamsArray.mValue, 0, 1));
mModule->mBfIRBuilder->CreateStore(mModule->GetConstValue(numElements), mModule->mBfIRBuilder->CreateInBoundsGEP(expandedParamsArray.mValue, 0, 2)); mModule->mBfIRBuilder->CreateStore(mModule->GetConstValue(numElements), mModule->mBfIRBuilder->CreateInBoundsGEP(expandedParamsArray.mValue, 0, 2));
PushArg(expandedParamsArray, irArgs); PushArg(expandedParamsArray, irArgs);
} }
@ -6028,16 +6047,32 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
} }
} }
} }
BfAstNode* arg = NULL; BfAstNode* arg = NULL;
bool hadMissingArg = false; bool hadMissingArg = false;
if (argExprIdx == -1) if (argExprIdx == -1)
arg = targetSrc; arg = targetSrc;
if (argExprIdx >= 0) if (argExprIdx >= 0)
{ {
if (argExprIdx < (int)argValues.size()) if (argExprIdx < (int)argValues.size())
{ {
arg = argValues[argExprIdx].mExpression; arg = argValues[argExprIdx].mExpression;
if (((argValues[argExprIdx].mArgFlags & BfArgFlag_StringInterpolateArg) != 0) && (!expandedParamsArray))
{
BfAstNode* errorRef = arg;
int checkIdx = argExprIdx - 1;
while (checkIdx >= 0)
{
if ((argValues[checkIdx].mArgFlags & BfArgFlag_StringInterpolateFormat) != 0)
{
errorRef = argValues[checkIdx].mExpression;
break;
}
checkIdx--;
}
mModule->Warn(BfWarning_BF4204_StringInterpolationParam, "Expanded string interpolation argument not used as 'params'. If string allocation was intended then consider adding a specifier such as 'scope'.", errorRef);
}
if ((arg == NULL) && (argValues[argExprIdx].mExpression != NULL)) if ((arg == NULL) && (argValues[argExprIdx].mExpression != NULL))
hadMissingArg = true; hadMissingArg = true;
} }
@ -6338,6 +6373,23 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
if (!argValue) if (!argValue)
{ {
if ((argValues[argExprIdx].mArgFlags & BfArgFlag_StringInterpolateArg) != 0)
{
BfAstNode* errorRef = NULL;
int checkIdx = argExprIdx - 1;
while (checkIdx >= 0)
{
if ((argValues[checkIdx].mArgFlags & BfArgFlag_StringInterpolateFormat) != 0)
{
errorRef = argValues[checkIdx].mExpression;
break;
}
checkIdx--;
}
if (errorRef != NULL)
mModule->Warn(0, "If string allocation was intended then consider adding a specifier such as 'scope'.", errorRef);
}
failed = true; failed = true;
} }
else if ((wantType->IsComposite()) && (!expandedParamsArray)) else if ((wantType->IsComposite()) && (!expandedParamsArray))

View file

@ -19,7 +19,8 @@ enum BfArgFlags
BfArgFlag_VariableDeclaration = 0x100, BfArgFlag_VariableDeclaration = 0x100,
BfArgFlag_ParamsExpr = 0x200, BfArgFlag_ParamsExpr = 0x200,
BfArgFlag_UninitializedExpr = 0x400, BfArgFlag_UninitializedExpr = 0x400,
BfArgFlag_StringInterpolateFormat = 0x800 BfArgFlag_StringInterpolateFormat = 0x800,
BfArgFlag_StringInterpolateArg = 0x1000
}; };
enum BfResolveArgFlags enum BfResolveArgFlags

View file

@ -1116,6 +1116,7 @@ enum BfWarning
BfWarning_BF4202_TooManyHexForInt = 4202, BfWarning_BF4202_TooManyHexForInt = 4202,
BfWarning_BF4203_UnnecessaryDynamicCast = 4203, BfWarning_BF4203_UnnecessaryDynamicCast = 4203,
BfWarning_BF4204_AddressOfReadOnly = 4204, BfWarning_BF4204_AddressOfReadOnly = 4204,
BfWarning_BF4204_StringInterpolationParam = 4205,
BfWarning_C4554_PossiblePrecedenceError = 4554 BfWarning_C4554_PossiblePrecedenceError = 4554
}; };