Skip to content

Commit df50f51

Browse files
authored
[SPIR-V] Fix crash with out-of-line template decl (#8079)
The SPIR-V backend made no differentence between VarDecl from template declaration and VarDecl from template instantiation. Fixing this by not creating a SPIR-V variable for template declaration (and waiting for the final instantiation). Fixes #5823
1 parent 0e98343 commit df50f51

File tree

3 files changed

+57
-0
lines changed

3 files changed

+57
-0
lines changed

tools/clang/lib/SPIRV/SpirvEmitter.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2034,6 +2034,28 @@ void SpirvEmitter::doVarDecl(const VarDecl *decl) {
20342034
return;
20352035
}
20362036

2037+
// Considering the following example:
2038+
//
2039+
// ```cpp
2040+
// template<typename T> const static T MyClass<T>::myVar[2] = { 1, 2 };
2041+
// [...]
2042+
// int use = MyClass<int>::myVar[0];
2043+
// ```
2044+
//
2045+
// The AST will contain 2 variable declarations:
2046+
// - VarDecl for the template declaration
2047+
// - VarDecl for the template instantiation
2048+
// One of them is not yet defined (InitExpr will have the type void), the
2049+
// other is the actual instantiation, hence will have the proper type. They
2050+
// can be differentiated by looking at the declaration context:
2051+
// - the undefined ones will be in the template declaration context.
2052+
// We must not create a variable for the template declaration but wait
2053+
// for the instantiation (if any).
2054+
auto *RC = dyn_cast<clang::CXXRecordDecl>(decl->getDeclContext());
2055+
auto *TC = RC ? RC->getDescribedClassTemplate() : nullptr;
2056+
if (decl->getInit() && TC)
2057+
return;
2058+
20372059
// We cannot handle external initialization of column-major matrices now.
20382060
if (isExternalVar(decl) &&
20392061
isOrContainsNonFpColMajorMatrix(astContext, spirvOptions, decl->getType(),
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %dxc -T cs_6_8 -E main -fcgl %s -spirv | FileCheck %s
2+
3+
// CHECK-NOT: OpVariable
4+
5+
template<typename T>
6+
struct MyClass {
7+
const static T array[2];
8+
};
9+
10+
template<typename T> const static T MyClass<T>::array[2] = { 1, 2 };
11+
12+
[numthreads(1, 1, 1)]
13+
void main() {
14+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %dxc -T cs_6_8 -E main -fcgl %s -spirv | FileCheck %s
2+
3+
4+
template<typename T>
5+
struct MyClass {
6+
const static T array[2];
7+
};
8+
9+
// CHECK: %array = OpVariable %_ptr_Private__arr_int_uint_2 Private
10+
// CHECK: [[init_var:%[a-zA-Z0-9_]+]] = OpCompositeConstruct %_arr_int_uint_2 %int_1 %int_2
11+
// CHECK: OpStore %array [[init_var]]
12+
template<typename T> const static T MyClass<T>::array[2] = { 1, 2 };
13+
14+
[numthreads(1, 1, 1)]
15+
void main() {
16+
// CHECK: [[ptr:%[a-zA-Z0-9_]+]] = OpAccessChain %_ptr_Private_int %array %int_1
17+
// CHECK: [[tmp:%[a-zA-Z0-9_]+]] = OpLoad %int [[ptr]]
18+
// CHECK: OpStore %tmp [[tmp]]
19+
int tmp = MyClass<int>::array[1];
20+
}
21+

0 commit comments

Comments
 (0)