diff --git a/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td b/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td index cbd9412566..34a2195cbc 100644 --- a/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1303,6 +1303,10 @@ def err_not_integral_type_bitfield : Error< "bit-field %0 has non-integral type %1">; def err_not_integral_type_anon_bitfield : Error< "anonymous bit-field has non-integral type %0">; +def err_spirv_boolean_bitfield_in_type + : Error<"type %0 contains a boolean bitfield which is not supported for " + "variables that are not externally visible when " + "targeting SPIR-V">; def err_member_function_initialization : Error< "initializer on function does not look like a pure-specifier">; def err_non_virtual_pure : Error< diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index 97d7c94448..e9c8c90a2d 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -16072,6 +16072,33 @@ bool Sema::DiagnoseHLSLDecl(Declarator &D, DeclContext *DC, Expr *BitWidth, result = false; } } + if (getLangOpts().SPIRV) { + // See https://github.com/microsoft/DirectXShaderCompiler/issues/7790. + // Booleans are an abstract type in SPIR-V and cannot be used as a + // bitfield container. In variables that are externally visible, the + // boolean is turned into an integer, so this is not a problem. + if (isLocalVar || isParameter || (isGlobal && isStatic)) { + QualType T = qt; + if (!T->isDependentType()) { + if (const auto *AT = T->getAsArrayTypeUnsafe()) + T = AT->getElementType(); + + if (const RecordType *RT = T->getAs()) { + const RecordDecl *RD = RT->getDecl(); + for (const FieldDecl *FD : RD->fields()) { + if (FD->isBitField() && FD->getType()->isBooleanType()) { + Diag(D.getIdentifierLoc(), + diag::err_spirv_boolean_bitfield_in_type) + << T; + D.setInvalidType(); + return false; + } + } + } + } + } + } + #endif // ENABLE_SPIRV_CODEGEN // SPIRV change ends diff --git a/tools/clang/test/SemaHLSL/spirv-boolean-bitfield.hlsl b/tools/clang/test/SemaHLSL/spirv-boolean-bitfield.hlsl new file mode 100644 index 0000000000..89e1c9c8d1 --- /dev/null +++ b/tools/clang/test/SemaHLSL/spirv-boolean-bitfield.hlsl @@ -0,0 +1,29 @@ +// RUN: %dxc -T cs_6_0 -E main -spirv -verify %s + +struct Test { + bool a: 1; + int b; +}; + +// This should not have an error because it is externally visible. +RWStructuredBuffer buffer; +Test g_non_static_global; + +// Global static variable +static Test g_t; // expected-error {{type 'Test' contains a boolean bitfield which is not supported for variables that are not externally visible when targeting SPIR-V}} + +// Global static array +static Test g_t_arr[2]; // expected-error {{type 'Test' contains a boolean bitfield which is not supported for variables that are not externally visible when targeting SPIR-V}} + +void foo(Test p) {} // expected-error {{type 'Test' contains a boolean bitfield which is not supported for variables that are not externally visible when targeting SPIR-V}} + +void bar(Test p[2]) {} // expected-error {{type 'Test' contains a boolean bitfield which is not supported for variables that are not externally visible when targeting SPIR-V}} + +[numthreads(1, 1, 1)] +void main() { + // Local variable + Test t; // expected-error {{type 'Test' contains a boolean bitfield which is not supported for variables that are not externally visible when targeting SPIR-V}} + + // Local array + Test t_arr[2]; // expected-error {{type 'Test' contains a boolean bitfield which is not supported for variables that are not externally visible when targeting SPIR-V}} +}