summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/slang/slang-check-conversion.cpp42
-rw-r--r--source/slang/slang-check-decl.cpp25
-rw-r--r--source/slang/slang-ir-autodiff-transpose.h3
-rw-r--r--tests/diagnostics/extension-full-name.slang.expected25
-rw-r--r--tests/diagnostics/mismatching-types.slang.expected1
-rw-r--r--tests/initializer-list/c-style-type.slang2
-rw-r--r--tests/initializer-list/default-init-c-style-member.slang62
-rw-r--r--tests/initializer-list/generic-array-init.slang26
-rw-r--r--tests/initializer-list/partial-init.slang18
-rw-r--r--tests/initializer-list/struct-visibility-diagnostic-1.slang8
-rw-r--r--tests/initializer-list/struct-visibility-diagnostic-2.slang8
-rw-r--r--tests/initializer-list/struct-visibility-diagnostic-3.slang12
12 files changed, 191 insertions, 41 deletions
diff --git a/source/slang/slang-check-conversion.cpp b/source/slang/slang-check-conversion.cpp
index 8f2ea3ca7..705da89e3 100644
--- a/source/slang/slang-check-conversion.cpp
+++ b/source/slang/slang-check-conversion.cpp
@@ -97,7 +97,17 @@ bool SemanticsVisitor::shouldUseInitializerDirectly(Type* toType, Expr* fromExpr
// we want to check for is whether a direct initialization
// is possible (a type conversion exists).
//
- return canCoerce(toType, fromExpr->type, fromExpr);
+ ConversionCost cost;
+ if (canCoerce(toType, fromExpr->type, fromExpr, &cost))
+ {
+ if (cost >= kConversionCost_Explicit)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ return false;
}
bool SemanticsVisitor::_readValueFromInitializerList(
@@ -526,6 +536,19 @@ bool SemanticsVisitor::_readAggregateValueFromInitializerList(
}
else
{
+ auto isLinkTimeVal =
+ as<TypeCastIntVal>(toElementCount) || as<DeclRefIntVal>(toElementCount) ||
+ as<PolynomialIntVal>(toElementCount) || as<FuncCallIntVal>(toElementType);
+ if (isLinkTimeVal)
+ {
+ auto defaultConstructExpr = m_astBuilder->create<DefaultConstructExpr>();
+ defaultConstructExpr->loc = fromInitializerListExpr->loc;
+ defaultConstructExpr->type = QualType(toType);
+
+ *outToExpr = defaultConstructExpr;
+ return true;
+ }
+
// We don't know the element count statically,
// so what are we supposed to be doing?
//
@@ -702,12 +725,26 @@ bool SemanticsVisitor::_readAggregateValueFromInitializerList(
auto toRowType =
createVectorType(toMatrixType->getElementType(), toMatrixType->getColumnCount());
- if (auto constRowCount = as<ConstantIntVal>(toMatrixType->getRowCount()))
+ auto rowCountIntVal = toMatrixType->getRowCount();
+ if (auto constRowCount = as<ConstantIntVal>(rowCountIntVal))
{
rowCount = (UInt)constRowCount->getValue();
}
else
{
+ auto isLinkTimeVal =
+ as<TypeCastIntVal>(rowCountIntVal) || as<DeclRefIntVal>(rowCountIntVal) ||
+ as<PolynomialIntVal>(rowCountIntVal) || as<FuncCallIntVal>(rowCountIntVal);
+ if (isLinkTimeVal)
+ {
+ auto defaultConstructExpr = m_astBuilder->create<DefaultConstructExpr>();
+ defaultConstructExpr->loc = fromInitializerListExpr->loc;
+ defaultConstructExpr->type = QualType(toType);
+
+ *outToExpr = defaultConstructExpr;
+ return true;
+ }
+
// We don't know the element count statically,
// so what are we supposed to be doing?
//
@@ -1545,7 +1582,6 @@ bool SemanticsVisitor::_coerce(
return true;
}
-
// The main general-purpose approach for conversion is
// using suitable marked initializer ("constructor")
// declarations on the target type.
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp
index c03d8e985..1331839a4 100644
--- a/source/slang/slang-check-decl.cpp
+++ b/source/slang/slang-check-decl.cpp
@@ -2512,6 +2512,23 @@ static Expr* constructDefaultConstructorForType(SemanticsVisitor* visitor, Type*
return invoke;
}
+ // At the last, we will check if the type is a C-style type, if it is, we will use empty
+ // initializer list to construct the default constructor.
+ HashSet<Type*> visitSet;
+ if (visitor->isCStyleType(type, visitSet))
+ {
+ auto initListExpr = visitor->getASTBuilder()->create<InitializerListExpr>();
+ initListExpr->type = visitor->getASTBuilder()->getInitializerListType();
+ Expr* outExpr = nullptr;
+ auto fromType = type;
+ if (auto atomicType = as<AtomicType>(fromType))
+ {
+ fromType = atomicType->getElementType();
+ }
+ if (visitor->_coerceInitializerList(fromType, &outExpr, initListExpr))
+ return outExpr;
+ }
+
return nullptr;
}
@@ -13031,7 +13048,13 @@ static Expr* _getParamDefaultValue(SemanticsVisitor* visitor, VarDeclBase* varDe
if (!isDefaultInitializable(varDecl))
return nullptr;
- return constructDefaultConstructorForType(visitor, varDecl->type.type);
+ if (auto expr = constructDefaultConstructorForType(visitor, varDecl->type.type))
+ {
+ expr->loc = varDecl->loc;
+ return expr;
+ }
+
+ return nullptr;
}
bool SemanticsDeclAttributesVisitor::_synthesizeCtorSignature(StructDecl* structDecl)
diff --git a/source/slang/slang-ir-autodiff-transpose.h b/source/slang/slang-ir-autodiff-transpose.h
index 282cc9685..606428efe 100644
--- a/source/slang/slang-ir-autodiff-transpose.h
+++ b/source/slang/slang-ir-autodiff-transpose.h
@@ -1987,6 +1987,9 @@ struct DiffTransposePass
IRInst* fwdMakeStruct,
IRInst* revValue)
{
+ if (fwdMakeStruct->getOperandCount() == 0)
+ return TranspositionResult();
+
List<RevGradient> gradients;
auto structType = cast<IRStructType>(fwdMakeStruct->getFullType());
UInt ii = 0;
diff --git a/tests/diagnostics/extension-full-name.slang.expected b/tests/diagnostics/extension-full-name.slang.expected
index 8001298c1..72eef77e3 100644
--- a/tests/diagnostics/extension-full-name.slang.expected
+++ b/tests/diagnostics/extension-full-name.slang.expected
@@ -1,39 +1,40 @@
result code = -1
standard error = {
-tests/diagnostics/extension-full-name.slang(184): error 30019: expected an expression of type 'GenericType<half>.State', got 'int'
+tests/diagnostics/extension-full-name.slang(185): error 30019: expected an expression of type 'GenericType<half>.State', got 'int'
state1 = 0; // Error: expected expr of type 'GenericType<half>.State', got 'int'
^
-tests/diagnostics/extension-full-name.slang(185): error 30019: expected an expression of type 'GenericType<float>.InnerType.Options', got 'int'
+tests/diagnostics/extension-full-name.slang(186): error 30019: expected an expression of type 'GenericType<float>.InnerType.Options', got 'int'
options1 = 0; // Error: expected expr of type 'GenericType<float>.InnerType.Options', got 'int'
^
-tests/diagnostics/extension-full-name.slang(186): error 30019: expected an expression of type 'NonGenericType.Config', got 'int'
+tests/diagnostics/extension-full-name.slang(187): error 30019: expected an expression of type 'NonGenericType.Config', got 'int'
config1 = 0; // Error: expected expr of type 'NonGenericType.Config', got 'int'
^
-tests/diagnostics/extension-full-name.slang(187): error 30019: expected an expression of type 'Container.Nested.Settings', got 'int'
+tests/diagnostics/extension-full-name.slang(188): error 30019: expected an expression of type 'Container.Nested.Settings', got 'int'
settings1 = 0; // Error: expected expr of type 'Container.Nested.Settings', got 'int'
^
-tests/diagnostics/extension-full-name.slang(188): error 30019: expected an expression of type 'Container.Nested.DeepNested.Record', got 'int'
+tests/diagnostics/extension-full-name.slang(189): error 30019: expected an expression of type 'Container.Nested.DeepNested.Record', got 'int'
record1 = 0; // Error: expected expr of type 'Container.Nested.DeepNested.Record', got 'int'
^
-tests/diagnostics/extension-full-name.slang(196): error 30027: 'getOptions' is not a member of 'GenericType<int>.InnerType'.
+tests/diagnostics/extension-full-name.slang(189): note: explicit conversion from 'int' to 'Container.Nested.DeepNested.Record' is possible
+tests/diagnostics/extension-full-name.slang(197): error 30027: 'getOptions' is not a member of 'GenericType<int>.InnerType'.
intInner.getOptions(); // This won't compile as intInner doesn't have getOptions
^~~~~~~~~~
-tests/diagnostics/extension-full-name.slang(226): error 30019: expected an expression of type 'GenericType<float>.InnerType.Options', got 'GenericType<half>.State'
+tests/diagnostics/extension-full-name.slang(227): error 30019: expected an expression of type 'GenericType<float>.InnerType.Options', got 'GenericType<half>.State'
.createState(); // Error: expected expr of type 'GenericType<float>.InnerType.Options',
^
-tests/diagnostics/extension-full-name.slang(228): error 30019: expected an expression of type 'GenericType<half>.State', got 'NonGenericType.Config'
+tests/diagnostics/extension-full-name.slang(229): error 30019: expected an expression of type 'GenericType<half>.State', got 'NonGenericType.Config'
state1 = nonGenType.createConfig(); // Error: expected expr of type 'GenericType<half>.State',
^
-tests/diagnostics/extension-full-name.slang(230): error 30019: expected an expression of type 'NonGenericType.Config', got 'Container.Nested.Settings'
+tests/diagnostics/extension-full-name.slang(231): error 30019: expected an expression of type 'NonGenericType.Config', got 'Container.Nested.Settings'
config1 = nested.createSettings(); // Error: expected expr of type 'NonGenericType.Config', got
^
-tests/diagnostics/extension-full-name.slang(304): error 30019: expected an expression of type 'Bar[3].DataStats', got 'int'
+tests/diagnostics/extension-full-name.slang(305): error 30019: expected an expression of type 'Bar[3].DataStats', got 'int'
barStats = 0; // Error: expected expr of type 'Bar[3].DataStats', got 'int'
^
-tests/diagnostics/extension-full-name.slang(312): error 30019: expected an expression of type 'Bar[2].DataStats', got 'Bar[3].DataStats'
+tests/diagnostics/extension-full-name.slang(313): error 30019: expected an expression of type 'Bar[2].DataStats', got 'Bar[3].DataStats'
bar2Stats = barArray.computeStats(); // Error: expected expr of type 'Bar[2].DataStats', got 'Bar[3].DataStats'
^
-tests/diagnostics/extension-full-name.slang(355): error 30019: expected an expression of type 'SimpleBase.NamedConfig', got 'int'
+tests/diagnostics/extension-full-name.slang(356): error 30019: expected an expression of type 'SimpleBase.NamedConfig', got 'int'
config = 0; // Error: expected expr of type 'SimpleBase.NamedConfig', got 'int'
^
}
diff --git a/tests/diagnostics/mismatching-types.slang.expected b/tests/diagnostics/mismatching-types.slang.expected
index a706e30e6..e247d16a8 100644
--- a/tests/diagnostics/mismatching-types.slang.expected
+++ b/tests/diagnostics/mismatching-types.slang.expected
@@ -20,6 +20,7 @@ tests/diagnostics/mismatching-types.slang(63): error 30019: expected an expressi
tests/diagnostics/mismatching-types.slang(66): error 30019: expected an expression of type 'NonGenericOuter.GenericInner<int>', got 'int'
c.i = 0;
^
+tests/diagnostics/mismatching-types.slang(66): note: explicit conversion from 'int' to 'NonGenericOuter.GenericInner<int>' is possible
tests/diagnostics/mismatching-types.slang(68): error 30019: expected an expression of type 'NonGenericOuter.GenericInner<int>', got 'NonGenericOuter.GenericInner<float>'
c.i = c.f;
^
diff --git a/tests/initializer-list/c-style-type.slang b/tests/initializer-list/c-style-type.slang
index 500bf37bb..8afa1e282 100644
--- a/tests/initializer-list/c-style-type.slang
+++ b/tests/initializer-list/c-style-type.slang
@@ -6,7 +6,7 @@ struct CLike
int x;
int y;
// compiler synthesizes:
- // __init(int x, int y);
+ // __init(int x = {}, int y = {});
}
//TEST_INPUT:ubuffer(data=[0 0 0 0 0 0], stride=4):out,name=outputBuffer
diff --git a/tests/initializer-list/default-init-c-style-member.slang b/tests/initializer-list/default-init-c-style-member.slang
new file mode 100644
index 000000000..41dba5bd0
--- /dev/null
+++ b/tests/initializer-list/default-init-c-style-member.slang
@@ -0,0 +1,62 @@
+//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=BUFFER):-shaderobj -vk
+//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=BUFFER):-shaderobj
+
+struct NonCStyle
+{
+ int x;
+ __init(int x)
+ {
+ this.x = x;
+ }
+}
+
+struct CLike
+{
+ NonCStyle nonCStyleMember;
+ int x;
+ int y;
+ // compiler synthesizes:
+ // __init(NonCStyle nonCStyleMember, int x = {}, int y = {});
+}
+
+//TEST_INPUT:ubuffer(data=[0 0 0 0 0 0 0 0 0], stride=4):out,name=outputBuffer
+RWStructuredBuffer<int> outputBuffer;
+void test()
+{
+ // case 1: initialized with synthesized ctor call, but CLike::x and CLike::y are default initialized
+ // and `c1` is now `{1, 0, 0}`.
+ CLike c1 = {NonCStyle(1)};
+
+ // case 2: initialized with synthesized ctor call, CLike::y are default initialized
+ CLike c2 = {NonCStyle(1), 2};
+
+ // case 3: initialized with synthesized ctor call
+ CLike c3 = {NonCStyle(1), 2, 3};
+
+ outputBuffer[0] = c1.nonCStyleMember.x;
+ // BUFFER: 1
+ outputBuffer[1] = c1.x;
+ // BUFFER-NEXT: 0
+ outputBuffer[2] = c1.y;
+ // BUFFER-NEXT: 0
+
+ outputBuffer[3] = c2.nonCStyleMember.x;
+ // BUFFER-NEXT: 1
+ outputBuffer[4] = c2.x;
+ // BUFFER-NEXT: 2
+ outputBuffer[5] = c2.y;
+ // BUFFER-NEXT: 0
+
+ outputBuffer[6] = c3.nonCStyleMember.x;
+ // BUFFER-NEXT: 1
+ outputBuffer[7] = c3.x;
+ // BUFFER-NEXT: 2
+ outputBuffer[8] = c3.y;
+ // BUFFER-NEXT: 3
+}
+
+[shader("compute")]
+void computeMain()
+{
+ test();
+}
diff --git a/tests/initializer-list/generic-array-init.slang b/tests/initializer-list/generic-array-init.slang
index 4257e2972..83c14ebd2 100644
--- a/tests/initializer-list/generic-array-init.slang
+++ b/tests/initializer-list/generic-array-init.slang
@@ -2,7 +2,7 @@
//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=BUFFER):-shaderobj -mtl
//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=BUFFER):-cpu -compute -entry computeMain
-//TEST_INPUT:ubuffer(data=[9 9 9 9], stride=4):out,name=outputBuffer
+//TEST_INPUT:ubuffer(data=[9 9 9 9 9 9 9 9 9 9 9 9], stride=4):out,name=outputBuffer
RWStructuredBuffer<int> outputBuffer;
void test<let TSize : uint>()
@@ -18,6 +18,28 @@ void test<let TSize : uint>()
outputBuffer[2] = array[2];
// BUFFER-NEXT: 3
outputBuffer[3] = array.getCount();
+
+ vector<int, TSize> vec = {};
+
+ // BUFFER-NEXT: 0
+ outputBuffer[4] = vec[0];
+ // BUFFER-NEXT: 0
+ outputBuffer[5] = vec[1];
+ // BUFFER-NEXT: 0
+ outputBuffer[6] = vec[2];
+ // BUFFER-NEXT: 3
+ outputBuffer[7] = vec.getCount();
+
+ matrix<float, TSize, TSize-1> mat = {};
+
+ // BUFFER-NEXT: 0
+ outputBuffer[8] = (int)mat[0][0];
+ // BUFFER-NEXT: 0
+ outputBuffer[9] = (int)mat[1][1];
+ // BUFFER-NEXT: 0
+ outputBuffer[10] = (int)mat[2][1];
+ // BUFFER-NEXT: 3
+ outputBuffer[11] = mat.getCount(); // this is a bad name, getCount() is actually get the number of row.
}
[shader("compute")]
@@ -25,4 +47,4 @@ void test<let TSize : uint>()
void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
{
test<3>();
-}
+}
diff --git a/tests/initializer-list/partial-init.slang b/tests/initializer-list/partial-init.slang
index 55f3816fb..a4739f041 100644
--- a/tests/initializer-list/partial-init.slang
+++ b/tests/initializer-list/partial-init.slang
@@ -8,15 +8,15 @@ struct PartialInit {
int x;
int y = 1;
// compiler synthesizes:
- // __init(int x, int y = 1);
+ // __init(int x = {}, int y = 1);
}
struct PartialInit2 {
int x = 1;
int y;
- // __init(int x, int y);
+ // __init(int x, int y = {});
}
-//TEST_INPUT:ubuffer(data=[0 0 0 0 0 0], stride=4):out,name=outputBuffer
+//TEST_INPUT:ubuffer(data=[0 0 0 0 0 0 0 0 0 0], stride=4):out,name=outputBuffer
RWStructuredBuffer<int> outputBuffer;
void test()
{
@@ -38,6 +38,18 @@ void test()
outputBuffer[4] = p3.x;
// BUFFER-NEXT: 5
outputBuffer[5] = p3.y;
+
+ PartialInit p4 = {}; // calls `__init`, result is {0, 1}
+ // BUFFER-NEXT: 0
+ outputBuffer[6] = p4.x;
+ // BUFFER-NEXT: 1
+ outputBuffer[7] = p4.y;
+
+ PartialInit2 p5 = {}; // calls `__init`, result is {1, 0}
+ // BUFFER-NEXT: 1
+ outputBuffer[8] = p5.x;
+ // BUFFER-NEXT: 0
+ outputBuffer[9] = p5.y;
}
[shader("compute")]
diff --git a/tests/initializer-list/struct-visibility-diagnostic-1.slang b/tests/initializer-list/struct-visibility-diagnostic-1.slang
index ab11933ae..1670860ad 100644
--- a/tests/initializer-list/struct-visibility-diagnostic-1.slang
+++ b/tests/initializer-list/struct-visibility-diagnostic-1.slang
@@ -4,12 +4,8 @@ public struct Visibility
{
internal int x;
public int y = 0;
- // the compiler does not synthesize any ctor.
- // the compiler will try to synthesize:
- // public __init(int y);
- // but then it will find that `x` cannot be initialized.
- // so this synthesis will fail and no ctor will be added
- // to the type.
+ // will synthesize a constructor
+ // __init(int y = 0)
}
void test()
diff --git a/tests/initializer-list/struct-visibility-diagnostic-2.slang b/tests/initializer-list/struct-visibility-diagnostic-2.slang
index a3255de5e..b9e92555b 100644
--- a/tests/initializer-list/struct-visibility-diagnostic-2.slang
+++ b/tests/initializer-list/struct-visibility-diagnostic-2.slang
@@ -4,12 +4,8 @@ public struct Visibility
{
internal int x;
public int y = 5;
- // the compiler does not synthesize any ctor.
- // the compiler will try to synthesize:
- // public __init(int y);
- // but then it will find that `x` cannot be initialized.
- // so this synthesis will fail and no ctor will be added
- // to the type.
+ // will synthesize a constructor
+ // __init(int y = 0)
}
void test()
diff --git a/tests/initializer-list/struct-visibility-diagnostic-3.slang b/tests/initializer-list/struct-visibility-diagnostic-3.slang
index 75ac5919d..e36bd4e4e 100644
--- a/tests/initializer-list/struct-visibility-diagnostic-3.slang
+++ b/tests/initializer-list/struct-visibility-diagnostic-3.slang
@@ -1,15 +1,13 @@
//DIAGNOSTIC_TEST:SIMPLE(filecheck=CHECK):
+public struct NonCStyle
+{}
public struct Visibility
{
internal int x;
- public int y;
- // the compiler does not synthesize any ctor.
- // the compiler will try to synthesize:
- // public __init(int y);
- // but then it will find that `x` cannot be initialized.
- // so this synthesis will fail and no ctor will be added
- // to the type.
+ public int[] y; // define a unsized array here on purpose so that the ctor will not associate it with a '{}' initializer
+ // will synthesize a constructor
+ // __init(int[] y)
}
void test()