diff options
| author | Yong He <yonghe@outlook.com> | 2022-08-17 23:08:34 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-08-17 23:08:34 -0700 |
| commit | adaea0e993fd8db351b5dad92802e47ed6d0ec77 (patch) | |
| tree | dfad5201677b0202b0b890cbae066b5b2f3f033b /source/slang/slang-check-expr.cpp | |
| parent | d65c6183c0d8b365aa182c3d9026ba85522531f2 (diff) | |
Warning on lossy implicit casts. (#2367)
* Warning on bool to float conversion.
* Fix test cases.
* Improve.
* LanguageServer: don't show constant value for non constant variables.
* Fix tests.
* Fix warnings in tests.
Co-authored-by: Yong He <yhe@nvidia.com>
Diffstat (limited to 'source/slang/slang-check-expr.cpp')
| -rw-r--r-- | source/slang/slang-check-expr.cpp | 140 |
1 files changed, 96 insertions, 44 deletions
diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp index 2ac02b978..c96db6f3b 100644 --- a/source/slang/slang-check-expr.cpp +++ b/source/slang/slang-check-expr.cpp @@ -884,7 +884,8 @@ namespace Slang auto funcDeclRef = getDeclRef(m_astBuilder, funcDeclRefExpr); auto intrinsicMod = funcDeclRef.getDecl()->findModifier<IntrinsicOpModifier>(); - if (!intrinsicMod) + auto implicitCast = funcDeclRef.getDecl()->findModifier<ImplicitConversionModifier>(); + if (!intrinsicMod && !implicitCast) { // We can't constant fold anything that doesn't map to a builtin // operation right now. @@ -942,54 +943,91 @@ namespace Slang // At this point, all the operands had simple integer values, so we are golden. IntegerLiteralValue resultValue = 0; - auto opName = funcDeclRef.getName(); - - // handle binary operators - if (opName == getName("-")) + // If this is an implicit cast, we can try to fold. + if (implicitCast) { - if (argCount == 1) + auto targetBasicType = as<BasicExpressionType>(invokeExpr.getExpr()->type.type); + if (!targetBasicType) + return nullptr; + switch (targetBasicType->baseType) { - resultValue = -constArgVals[0]; + case BaseType::Bool: + resultValue = constArgVals[0] != 0; + break; + case BaseType::Int: + case BaseType::UInt: + case BaseType::UInt16: + case BaseType::Int16: + case BaseType::UInt8: + case BaseType::Int8: + resultValue = constArgVals[0]; + break; + default: + return nullptr; } - else if (argCount == 2) + } + else + { + auto opName = funcDeclRef.getName(); + + // handle binary operators + if (opName == getName("-")) { - resultValue = constArgVals[0] - constArgVals[1]; + if (argCount == 1) + { + resultValue = -constArgVals[0]; + } + else if (argCount == 2) + { + resultValue = constArgVals[0] - constArgVals[1]; + } + } + else if (opName == getName("!")) + { + resultValue = constArgVals[0] != 0; + } + else if (opName == getName("~")) + { + resultValue = ~constArgVals[0]; } - } - // simple binary operators + // simple binary operators #define CASE(OP) \ - else if(opName == getName(#OP)) do { \ - if(argCount != 2) return nullptr; \ - resultValue = constArgVals[0] OP constArgVals[1]; \ - } while(0) - - CASE(+); // TODO: this can also be unary... - CASE(*); - CASE(<<); - CASE(>>); - CASE(&); - CASE(|); - CASE(^); + else if(opName == getName(#OP)) do { \ + if(argCount != 2) return nullptr; \ + resultValue = constArgVals[0] OP constArgVals[1]; \ + } while(0) + + CASE(+); // TODO: this can also be unary... + CASE(*); + CASE(<<); + CASE(>>); + CASE(&); + CASE(|); + CASE(^); + CASE(!=); + CASE(==); + CASE(>=); + CASE(<=); + CASE(<); + CASE(>); #undef CASE - - // binary operators with chance of divide-by-zero - // TODO: issue a suitable error in that case + // binary operators with chance of divide-by-zero + // TODO: issue a suitable error in that case #define CASE(OP) \ - else if(opName == getName(#OP)) do { \ - if(argCount != 2) return nullptr; \ - if(!constArgVals[1]) return nullptr; \ - resultValue = constArgVals[0] OP constArgVals[1]; \ - } while(0) - - CASE(/); - CASE(%); + else if(opName == getName(#OP)) do { \ + if(argCount != 2) return nullptr; \ + if(!constArgVals[1]) return nullptr; \ + resultValue = constArgVals[0] OP constArgVals[1]; \ + } while(0) + CASE(/); + CASE(%); #undef CASE - - // TODO(tfoley): more cases - else - { - return nullptr; + // TODO(tfoley): more cases + else + { + return nullptr; + } } IntVal* result = m_astBuilder->create<ConstantIntVal>(resultValue); @@ -1126,13 +1164,27 @@ namespace Slang return tryConstantFoldExpr(expr, circularityInfo); } - IntVal* SemanticsVisitor::CheckIntegerConstantExpression(Expr* inExpr, DiagnosticSink* sink) + IntVal* SemanticsVisitor::CheckIntegerConstantExpression(Expr* inExpr, IntegerConstantExpressionCoercionType coercionType, Type* expectedType, DiagnosticSink* sink) { // No need to issue further errors if the expression didn't even type-check. if(IsErrorExpr(inExpr)) return nullptr; // First coerce the expression to the expected type - auto expr = coerce(m_astBuilder->getIntType(),inExpr); + Expr* expr = nullptr; + switch (coercionType) + { + case IntegerConstantExpressionCoercionType::SpecificType: + expr = coerce(expectedType, inExpr); + break; + case IntegerConstantExpressionCoercionType::AnyInteger: + if (isScalarIntegerType(inExpr->type)) + expr = inExpr; + else + expr = coerce(m_astBuilder->getIntType(), inExpr); + break; + default: + break; + } // No need to issue further errors if the type coercion failed. if(IsErrorExpr(expr)) return nullptr; @@ -1145,9 +1197,9 @@ namespace Slang return result; } - IntVal* SemanticsVisitor::CheckIntegerConstantExpression(Expr* inExpr) + IntVal* SemanticsVisitor::CheckIntegerConstantExpression(Expr* inExpr, IntegerConstantExpressionCoercionType coercionType, Type* expectedType) { - return CheckIntegerConstantExpression(inExpr, getSink()); + return CheckIntegerConstantExpression(inExpr, coercionType, expectedType, getSink()); } IntVal* SemanticsVisitor::CheckEnumConstantExpression(Expr* expr) @@ -1218,7 +1270,7 @@ namespace Slang IntVal* elementCount = nullptr; if (indexExpr) { - elementCount = CheckIntegerConstantExpression(indexExpr); + elementCount = CheckIntegerConstantExpression(indexExpr, IntegerConstantExpressionCoercionType::AnyInteger, nullptr); } auto elementType = CoerceToUsableType(TypeExp(baseExpr, baseTypeType->type)); |
