summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/slang/check.cpp36
-rw-r--r--source/slang/diagnostic-defs.h2
-rw-r--r--source/slang/syntax.cpp17
-rw-r--r--tests/diagnostics/implicit-cast-lvalue.slang15
-rw-r--r--tests/diagnostics/implicit-cast-lvalue.slang.expected7
5 files changed, 69 insertions, 8 deletions
diff --git a/source/slang/check.cpp b/source/slang/check.cpp
index 67b628596..acf473998 100644
--- a/source/slang/check.cpp
+++ b/source/slang/check.cpp
@@ -6738,13 +6738,37 @@ namespace Slang
auto paramType = funcType->getParamType(pp);
if (auto outParamType = paramType->As<OutTypeBase>())
{
- if (pp < expr->Arguments.Count()
- && !expr->Arguments[pp]->type.IsLeftValue)
+ if( pp < expr->Arguments.Count() )
{
- getSink()->diagnose(
- expr->Arguments[pp],
- Diagnostics::argumentExpectedLValue,
- pp);
+ auto argExpr = expr->Arguments[pp];
+ if( !argExpr->type.IsLeftValue )
+ {
+ getSink()->diagnose(
+ argExpr,
+ Diagnostics::argumentExpectedLValue,
+ pp);
+
+ if( auto implicitCastExpr = argExpr.As<ImplicitCastExpr>() )
+ {
+ getSink()->diagnose(
+ argExpr,
+ Diagnostics::implicitCastUsedAsLValue,
+ implicitCastExpr->Arguments[0]->type,
+ implicitCastExpr->type);
+ }
+ }
+ }
+ else
+ {
+ // This implies that the function had an `out`
+ // or `inout` parameter and they gave it a default
+ // argument expression. I'm not even sure what
+ // that would mean.
+ //
+ // TODO: make sure this gets validated on the
+ // declaring side.
+ //
+ SLANG_DIAGNOSE_UNEXPECTED(getSink(), invoke, "default argument expression for out/inout paameter");
}
}
}
diff --git a/source/slang/diagnostic-defs.h b/source/slang/diagnostic-defs.h
index f1aee496c..a3c51d67e 100644
--- a/source/slang/diagnostic-defs.h
+++ b/source/slang/diagnostic-defs.h
@@ -192,6 +192,8 @@ DIAGNOSTIC(30033, Error, invalidTypeForLocalVariable, "cannot declare a local va
DIAGNOSTIC(30035, Error, componentOverloadTypeMismatch, "'$0': type of overloaded component mismatches previous definition.")
DIAGNOSTIC(30041, Error, bitOperationNonIntegral, "bit operation: operand must be integral type.")
DIAGNOSTIC(30047, Error, argumentExpectedLValue, "argument passed to parameter '$0' must be l-value.")
+DIAGNOSTIC(30048, Note, implicitCastUsedAsLValue, "argument was implicitly cast from '$0' to '$1', and Slang does not support using an implicit cast as an l-value")
+
DIAGNOSTIC(30051, Error, invalidValueForArgument, "invalid value for argument '$0'")
DIAGNOSTIC(30052, Error, invalidSwizzleExpr, "invalid swizzle pattern '$0' on type '$1'")
DIAGNOSTIC(33070, Error, expectedFunction, "expression preceding parenthesis of apparent call must have function type.")
diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp
index 9d29e7d21..5e855de29 100644
--- a/source/slang/syntax.cpp
+++ b/source/slang/syntax.cpp
@@ -2081,9 +2081,22 @@ void Type::accept(IValVisitor* visitor, void* extra)
funcType->setSession(session);
funcType->resultType = GetResultType(declRef);
- for (auto pp : GetParameters(declRef))
+ for (auto paramDeclRef : GetParameters(declRef))
{
- funcType->paramTypes.Add(GetType(pp));
+ auto paramDecl = paramDeclRef.getDecl();
+ auto paramType = GetType(paramDeclRef);
+ if( paramDecl->FindModifier<OutModifier>() )
+ {
+ if(paramDecl->FindModifier<InOutModifier>() || paramDecl->FindModifier<InModifier>())
+ {
+ paramType = session->getInOutType(paramType);
+ }
+ else
+ {
+ paramType = session->getOutType(paramType);
+ }
+ }
+ funcType->paramTypes.Add(paramType);
}
return funcType;
diff --git a/tests/diagnostics/implicit-cast-lvalue.slang b/tests/diagnostics/implicit-cast-lvalue.slang
new file mode 100644
index 000000000..4bf3c13b0
--- /dev/null
+++ b/tests/diagnostics/implicit-cast-lvalue.slang
@@ -0,0 +1,15 @@
+//TEST:SIMPLE:
+
+// Passing an argument for an `out` parameter such
+// that implicit conversion would be required in
+// both directions.
+
+void a(out uint x)
+{
+ x = 0;
+}
+
+void b(int y)
+{
+ a(y);
+}
diff --git a/tests/diagnostics/implicit-cast-lvalue.slang.expected b/tests/diagnostics/implicit-cast-lvalue.slang.expected
new file mode 100644
index 000000000..e5685fc51
--- /dev/null
+++ b/tests/diagnostics/implicit-cast-lvalue.slang.expected
@@ -0,0 +1,7 @@
+result code = -1
+standard error = {
+tests/diagnostics/implicit-cast-lvalue.slang(14): error 30047: argument passed to parameter '0' must be l-value.
+tests/diagnostics/implicit-cast-lvalue.slang(14): note 30048: argument was implicitly cast from 'int' to 'uint', and Slang does not support using an implicit cast as an l-value
+}
+standard output = {
+}