diff --git a/tools/clang/lib/SPIRV/InitListHandler.cpp b/tools/clang/lib/SPIRV/InitListHandler.cpp index a4bef119e..34ebd95a9 100644 --- a/tools/clang/lib/SPIRV/InitListHandler.cpp +++ b/tools/clang/lib/SPIRV/InitListHandler.cpp @@ -48,7 +48,9 @@ SpirvInstruction *InitListHandler::processCast(QualType toType, initializers.clear(); scalars.clear(); - initializers.push_back(theEmitter.loadIfGLValue(expr)); + auto *initializer = theEmitter.loadIfGLValue(expr); + if (initializer) + initializers.push_back(initializer); return doProcess(toType, expr->getExprLoc()); } @@ -294,6 +296,10 @@ InitListHandler::createInitForVectorType(QualType elemType, uint32_t count, while (tryToSplitStruct() || tryToSplitConstantArray()) ; + // Not enough elements in the initializer list. Giving up. + if (initializers.empty()) + return nullptr; + auto init = initializers.back(); const auto initType = init->getAstResultType(); @@ -339,6 +345,10 @@ SpirvInstruction *InitListHandler::createInitForMatrixType( while (tryToSplitStruct() || tryToSplitConstantArray()) ; + // Not enough elements in the initializer list. Giving up. + if (initializers.empty()) + return nullptr; + auto init = initializers.back(); if (hlsl::IsHLSLMatType(init->getAstResultType())) { @@ -383,6 +393,8 @@ InitListHandler::createInitForStructType(QualType type, SourceLocation srcLoc, while (tryToSplitConstantArray()) ; + // Note: an empty initializer list can be valid. Ex: initializing an + // empty struct. if (!initializers.empty()) { auto init = initializers.back(); // We can only avoid decomposing and reconstructing when the type is @@ -418,6 +430,8 @@ InitListHandler::createInitForStructType(QualType type, SourceLocation srcLoc, const QualType &fieldType, const StructType::FieldInfo &fieldInfo) { SpirvInstruction *init = createInitForType(fieldType, srcLoc, range); + if (!init) + return false; // For non bit-fields, `init` will be the value for the component. if (!fieldInfo.bitfield.hasValue()) { @@ -449,6 +463,10 @@ InitListHandler::createInitForStructType(QualType type, SourceLocation srcLoc, return true; }, true); + + for (const auto *field : fields) + if (field == nullptr) + return nullptr; return spvBuilder.createCompositeConstruct(type, fields, srcLoc, range); } @@ -463,6 +481,10 @@ SpirvInstruction *InitListHandler::createInitForConstantArrayType( while (tryToSplitStruct()) ; + // Not enough elements in the initializer list. Giving up. + if (initializers.empty()) + return nullptr; + auto init = initializers.back(); // We can only avoid decomposing and reconstructing when the type is // exactly the same. @@ -485,8 +507,12 @@ SpirvInstruction *InitListHandler::createInitForConstantArrayType( const auto size = static_cast(arrType->getSize().getZExtValue()); llvm::SmallVector elements; - for (uint32_t i = 0; i < size; ++i) - elements.push_back(createInitForType(elemType, srcLoc, range)); + for (uint32_t i = 0; i < size; ++i) { + auto *it = createInitForType(elemType, srcLoc, range); + if (!it) + return nullptr; + elements.push_back(it); + } // TODO: use OpConstantComposite when all components are constants return spvBuilder.createCompositeConstruct(type, elements, srcLoc, range); @@ -516,6 +542,11 @@ InitListHandler::createInitForBufferOrImageType(QualType type, while (tryToSplitStruct() || tryToSplitConstantArray()) ; + // Not enough elements in the initializer list. Giving up. + if (initializers.empty()) { + return nullptr; + } + auto init = initializers.back(); initializers.pop_back(); diff --git a/tools/clang/test/CodeGenSPIRV/initializelist.undefined.hlsl b/tools/clang/test/CodeGenSPIRV/initializelist.undefined.hlsl new file mode 100644 index 000000000..0a737ad9b --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/initializelist.undefined.hlsl @@ -0,0 +1,51 @@ +// RUN: not %dxc -T cs_6_2 -E main -enable-16bit-types %s -spirv 2>&1 | FileCheck %s + +typedef vector uint32_t3; +typedef vector uint16_t3; +uint32_t3 gl_WorkGroupSize(); + +struct S { + float3 a; +}; + +float3 foo(); +RWStructuredBuffer bar(); +float baz(); + +struct Empty {}; + +struct B { + float a; + Empty b; +}; + +[numthreads(1, 1, 1)] +void main() { + + // createInitForVectorType +// CHECK: 27:20: error: found undefined function + int4 v = int4(1, foo()); +// CHECK: 29:36: error: found undefined function + const uint16_t3 dims = uint16_t3(gl_WorkGroupSize()); + + // createInitForMatrixType +// CHECK: 33:21: error: found undefined function + float2x2 m = { 0, foo() }; + + // createInitForStructType +// CHECK: 37:13: error: found undefined function + S s = (S)foo(); + + // createInitForConstantArrayType +// CHECK: 41:27: error: found undefined function + const float data[3] = { foo() }; + + // createInitForBufferOrImageType +// CHECK: 46:38: error: found undefined function +// CHECK: 46:36: fatal error: cannot find the associated counter variable + RWStructuredBuffer buff = { bar() }; + + // Valid empty initializer list. +// CHECK-NOT: error + B b = { 1.f }; +}