diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index 2b3f065d71..5419863872 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -9901,6 +9901,7 @@ bool HLSLExternalSource::CanConvert(SourceLocation loc, Expr *sourceExpr, // We can only splat to target types that do not contain object/resource // types if (sourceSingleElementBuiltinType != nullptr && + !m_sema->RequireCompleteType(loc, target, 0) && hlsl::IsHLSLNumericOrAggregateOfNumericType(target)) { BuiltinType::Kind kind = sourceSingleElementBuiltinType->getKind(); switch (kind) { diff --git a/tools/clang/test/CodeGenDXIL/templates/incomplete-target-in-CanConvert.hlsl b/tools/clang/test/CodeGenDXIL/templates/incomplete-target-in-CanConvert.hlsl new file mode 100644 index 0000000000..bd559d2ed1 --- /dev/null +++ b/tools/clang/test/CodeGenDXIL/templates/incomplete-target-in-CanConvert.hlsl @@ -0,0 +1,39 @@ +// RUN: %dxc -T vs_6_0 -E main %s | FileCheck %s + +// CHECK: %[[IN:[^ ]+]] = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 0, i32 undef) +// CHECK: call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 0, float %[[IN]]) + +template struct Wrapper; +float get(float x) { return x;} +float get(Wrapper o); + +template struct Wrapper2; +float get(Wrapper2 o); + +template +struct Wrapper { + T value; + void set(float x) { + // Incomplete target in CanConvert triggered during check whether explicit + // cast would be allowed for converting to overload candidate 'float + // get(Wrapper)'. CanConvert would check spat potential when + // explicit and source is a basic numeric type. This would cause crash in + // IsHLSLCopyableAnnotatableRecord from the incomplete type. + // Here, we can complete the type: Wrapper, but not Wrapper2 + value = get(x); + } +}; + +float get(Wrapper o) { return o.value; } + +template +struct Wrapper2 : Wrapper { +}; + +float get(Wrapper2 o) { return o.value; } + +float main(float x : IN) : OUT { + Wrapper2 w; + w.set(x); + return get(w); +}