From acf7235dc1ab3434af7407357739e6ce75e99bbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Saffran?= Date: Mon, 1 Jun 2026 16:39:50 -0700 Subject: [PATCH 1/9] deny built in types --- .../clang/Basic/DiagnosticSemaKinds.td | 3 ++ tools/clang/include/clang/Sema/SemaHLSL.h | 5 ++ tools/clang/lib/Sema/SemaDecl.cpp | 11 +++++ tools/clang/lib/Sema/SemaHLSL.cpp | 46 +++++++++++++++++++ .../hlsl/auto/auto-deducible-types.hlsl | 46 +++++++++++++++++++ .../hlsl/auto/auto-undeducible-types.hlsl | 36 +++++++++++++++ 6 files changed, 147 insertions(+) create mode 100644 tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-deducible-types.hlsl create mode 100644 tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-undeducible-types.hlsl diff --git a/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td b/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td index a9f9f7d5fa..e3e472e48e 100644 --- a/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -8070,6 +8070,9 @@ def err_hlsl_auto_descriptor_heap : Error< "'auto' cannot deduce the type of '%select{ResourceDescriptorHeap|SamplerDescriptorHeap}0'; " "use a specific resource or sampler type instead">; +def err_hlsl_auto_undeducible_type : Error< + "'auto' cannot deduce type %0">; + // HLSL Change Ends // SPIRV Change Starts diff --git a/tools/clang/include/clang/Sema/SemaHLSL.h b/tools/clang/include/clang/Sema/SemaHLSL.h index 1917a9277a..c1836c26a1 100644 --- a/tools/clang/include/clang/Sema/SemaHLSL.h +++ b/tools/clang/include/clang/Sema/SemaHLSL.h @@ -93,6 +93,11 @@ bool DiagnoseTypeElements(clang::Sema &S, clang::SourceLocation Loc, TypeDiagContext LongVecDiagContext, const clang::FieldDecl *FD = nullptr); +// Returns true if 'auto' is allowed to deduce the given type. Container types +// (arrays, vectors, matrices, pointers) are deducible only when the type they +// wrap is deducible. +bool IsTypeDeducibleWithAuto(clang::Sema &S, clang::QualType Ty); + void DiagnoseControlFlowConditionForHLSL(clang::Sema *self, clang::Expr *condExpr, llvm::StringRef StmtName); diff --git a/tools/clang/lib/Sema/SemaDecl.cpp b/tools/clang/lib/Sema/SemaDecl.cpp index bde23e0d59..628f629f4f 100644 --- a/tools/clang/lib/Sema/SemaDecl.cpp +++ b/tools/clang/lib/Sema/SemaDecl.cpp @@ -9051,6 +9051,17 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, VDecl->setInvalidDecl(); return; } + + // A dependent deduced type (e.g. 'auto' bound to a template parameter + // inside a template body) cannot be classified yet; defer the check to + // instantiation, when 'auto' is re-deduced to a concrete type. + if (!DeducedType->isDependentType() && + !hlsl::IsTypeDeducibleWithAuto(*this, DeducedType)) { + Diag(VDecl->getLocation(), diag::err_hlsl_auto_undeducible_type) + << DeducedType; + VDecl->setInvalidDecl(); + return; + } } VDecl->setType(DeducedType); diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index 2067ebaf26..e859634b57 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -4773,6 +4773,48 @@ class HLSLExternalSource : public ExternalSemaSource { return type; } + /// Determines whether 'auto' is allowed to deduce the given type. + /// Container types (arrays, vectors, matrices, pointers, qualified types) are + /// deducible only when the type they wrap is deducible. + bool IsTypeDeducibleWithAuto(QualType type) { + if (type.isNull()) + return false; + + switch (GetTypeObjectKind(type)) { + // Types with no concrete, nameable form for 'auto' to bind to. + case AR_TOBJ_INVALID: + case AR_TOBJ_VOID: + case AR_TOBJ_INNER_OBJ: + case AR_TOBJ_DEPENDENT: + return false; + + // Fully-formed types that 'auto' can deduce directly. + case AR_TOBJ_OBJECT: + case AR_TOBJ_BASIC: + case AR_TOBJ_COMPOUND: + case AR_TOBJ_INTERFACE: + case AR_TOBJ_STRING: + case AR_TOBJ_LINALG_MATRIX: + return true; + + // Container types: deducible iff their wrapped type is deducible. + case AR_TOBJ_MATRIX: + case AR_TOBJ_VECTOR: + return IsTypeDeducibleWithAuto(GetMatrixOrVectorElementType(type)); + case AR_TOBJ_ARRAY: { + const ArrayType *arrayType = + GetStructuralForm(type)->getAsArrayTypeUnsafe(); + return IsTypeDeducibleWithAuto(arrayType->getElementType()); + } + case AR_TOBJ_POINTER: + return IsTypeDeducibleWithAuto(GetStructuralForm(type)->getPointeeType()); + case AR_TOBJ_QUALIFIER: + return IsTypeDeducibleWithAuto( + GetStructuralForm(type).getUnqualifiedType()); + } + return false; + } + /// Given a Clang type, return the ArBasicKind classification for its /// contents. ArBasicKind GetTypeElementKind(QualType type) { @@ -12787,6 +12829,10 @@ bool hlsl::DiagnoseTypeElements(Sema &S, SourceLocation Loc, QualType Ty, LongVecDiagContext, CheckedDecls, FD); } +bool hlsl::IsTypeDeducibleWithAuto(Sema &S, QualType Ty) { + return HLSLExternalSource::FromSema(&S)->IsTypeDeducibleWithAuto(Ty); +} + bool hlsl::DiagnoseNodeStructArgument(Sema *self, TemplateArgumentLoc ArgLoc, QualType ArgTy, bool &Empty, const FieldDecl *FD) { diff --git a/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-deducible-types.hlsl b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-deducible-types.hlsl new file mode 100644 index 0000000000..59c6d17a00 --- /dev/null +++ b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-deducible-types.hlsl @@ -0,0 +1,46 @@ +// RUN: %dxc -T cs_6_0 -HV 202x -verify %s +// expected-no-diagnostics + +// Test that 'auto' accepts every directly-deducible type kind, plus the +// container kinds that resolve to a deducible element: +// - scalars / enums -> AR_TOBJ_BASIC +// - vectors -> AR_TOBJ_VECTOR (element AR_TOBJ_BASIC) +// - matrices -> AR_TOBJ_MATRIX (element AR_TOBJ_BASIC) +// - user-defined structs -> AR_TOBJ_COMPOUND +// - built-in object/resources -> AR_TOBJ_OBJECT +// None of these should produce a deduction error. + +struct MyStruct { + float a; + int b; +}; + +Texture2D tex : register(t0); +SamplerState samp : register(s0); +RWBuffer output : register(u0); + +[numthreads(1,1,1)] +void main() { + // AR_TOBJ_BASIC + auto i = 5; + auto f = 1.5f; + auto b = true; + + // AR_TOBJ_VECTOR -> element AR_TOBJ_BASIC + auto v = float4(1, 2, 3, 4); + + // AR_TOBJ_MATRIX -> element AR_TOBJ_BASIC + float2x2 matInit = { 1, 2, 3, 4 }; + auto m = matInit; + + // AR_TOBJ_COMPOUND + MyStruct s = { 1.0f, 2 }; + auto sCopy = s; + + // AR_TOBJ_OBJECT: resource handles are copyable, so binding one is allowed. + auto t = tex; + + // Use every value to prevent dead-code elimination. + output[0] = (float)i + f + (float)b + v.x + m._11 + sCopy.a + + (float)sCopy.b + t.SampleLevel(samp, float2(0, 0), 0).x; +} diff --git a/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-undeducible-types.hlsl b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-undeducible-types.hlsl new file mode 100644 index 0000000000..c4e8da5b50 --- /dev/null +++ b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-undeducible-types.hlsl @@ -0,0 +1,36 @@ +// RUN: %dxc -T cs_6_0 -HV 202x -verify %s + +// Test that 'auto' rejects every type kind it cannot deduce: +// - void -> AR_TOBJ_VOID +// - built-in inner objects -> AR_TOBJ_INNER_OBJ (the indexer proxies behind +// double-subscript members like .mips and .sample) +// +// The deduced inner-object type name is verbose and version-dependent, so only +// the stable prefix of the diagnostic is matched for those cases. + +void voidFunc() {} + +Texture2D tex : register(t0); +Texture2DMS texMS : register(t1); + +[numthreads(1,1,1)] +void main() { + int y = 1; + + // AR_TOBJ_VOID: a void-returning call has no value type. + // expected-error@+1 {{'auto' cannot deduce type 'void'}} + auto x = voidFunc(); + + // AR_TOBJ_VOID: an explicit cast to void is equally non-deducible. + // expected-error@+1 {{'auto' cannot deduce type 'void'}} + auto v = (void)y; + + // AR_TOBJ_INNER_OBJ: .mips is an inner indexer object (Texture2D::mips_type). + // expected-error@+1 {{'auto' cannot deduce type}} + auto m = tex.mips; + + // AR_TOBJ_INNER_OBJ: .sample is an inner indexer object + // (Texture2DMS::sample_type). + // expected-error@+1 {{'auto' cannot deduce type}} + auto s = texMS.sample; +} From cc2eb8f56af89ec735b02e95755d0093fe0019a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Saffran?= Date: Mon, 1 Jun 2026 16:46:15 -0700 Subject: [PATCH 2/9] clean up --- tools/clang/include/clang/Sema/SemaHLSL.h | 3 +-- tools/clang/lib/Sema/SemaDecl.cpp | 3 +-- tools/clang/lib/Sema/SemaHLSL.cpp | 3 --- .../HLSLFileCheckLit/hlsl/auto/auto-deducible-types.hlsl | 9 --------- .../hlsl/auto/auto-undeducible-types.hlsl | 7 ------- 5 files changed, 2 insertions(+), 23 deletions(-) diff --git a/tools/clang/include/clang/Sema/SemaHLSL.h b/tools/clang/include/clang/Sema/SemaHLSL.h index c1836c26a1..be17274521 100644 --- a/tools/clang/include/clang/Sema/SemaHLSL.h +++ b/tools/clang/include/clang/Sema/SemaHLSL.h @@ -94,8 +94,7 @@ bool DiagnoseTypeElements(clang::Sema &S, clang::SourceLocation Loc, const clang::FieldDecl *FD = nullptr); // Returns true if 'auto' is allowed to deduce the given type. Container types -// (arrays, vectors, matrices, pointers) are deducible only when the type they -// wrap is deducible. +// are deducible only when the type they wrap is deducible. bool IsTypeDeducibleWithAuto(clang::Sema &S, clang::QualType Ty); void DiagnoseControlFlowConditionForHLSL(clang::Sema *self, diff --git a/tools/clang/lib/Sema/SemaDecl.cpp b/tools/clang/lib/Sema/SemaDecl.cpp index 628f629f4f..52c870d994 100644 --- a/tools/clang/lib/Sema/SemaDecl.cpp +++ b/tools/clang/lib/Sema/SemaDecl.cpp @@ -9052,8 +9052,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, return; } - // A dependent deduced type (e.g. 'auto' bound to a template parameter - // inside a template body) cannot be classified yet; defer the check to + // A dependent deduced type cannot be classified yet; defer the check to // instantiation, when 'auto' is re-deduced to a concrete type. if (!DeducedType->isDependentType() && !hlsl::IsTypeDeducibleWithAuto(*this, DeducedType)) { diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index e859634b57..8abd6887d4 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -4773,9 +4773,6 @@ class HLSLExternalSource : public ExternalSemaSource { return type; } - /// Determines whether 'auto' is allowed to deduce the given type. - /// Container types (arrays, vectors, matrices, pointers, qualified types) are - /// deducible only when the type they wrap is deducible. bool IsTypeDeducibleWithAuto(QualType type) { if (type.isNull()) return false; diff --git a/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-deducible-types.hlsl b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-deducible-types.hlsl index 59c6d17a00..7e0ee0f188 100644 --- a/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-deducible-types.hlsl +++ b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-deducible-types.hlsl @@ -1,15 +1,6 @@ // RUN: %dxc -T cs_6_0 -HV 202x -verify %s // expected-no-diagnostics -// Test that 'auto' accepts every directly-deducible type kind, plus the -// container kinds that resolve to a deducible element: -// - scalars / enums -> AR_TOBJ_BASIC -// - vectors -> AR_TOBJ_VECTOR (element AR_TOBJ_BASIC) -// - matrices -> AR_TOBJ_MATRIX (element AR_TOBJ_BASIC) -// - user-defined structs -> AR_TOBJ_COMPOUND -// - built-in object/resources -> AR_TOBJ_OBJECT -// None of these should produce a deduction error. - struct MyStruct { float a; int b; diff --git a/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-undeducible-types.hlsl b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-undeducible-types.hlsl index c4e8da5b50..aaaf82c219 100644 --- a/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-undeducible-types.hlsl +++ b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-undeducible-types.hlsl @@ -1,12 +1,5 @@ // RUN: %dxc -T cs_6_0 -HV 202x -verify %s -// Test that 'auto' rejects every type kind it cannot deduce: -// - void -> AR_TOBJ_VOID -// - built-in inner objects -> AR_TOBJ_INNER_OBJ (the indexer proxies behind -// double-subscript members like .mips and .sample) -// -// The deduced inner-object type name is verbose and version-dependent, so only -// the stable prefix of the diagnostic is matched for those cases. void voidFunc() {} From 8a363cc322dc06f70f95ce14d279a9f2677b1e4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Saffran?= Date: Mon, 1 Jun 2026 17:50:39 -0700 Subject: [PATCH 3/9] address tex comments --- tools/clang/lib/Sema/SemaHLSL.cpp | 32 ++++++++++------ .../hlsl/auto/auto-deducible-types.hlsl | 5 ++- .../hlsl/auto/auto-no-subobject.hlsl | 37 +++++++++++++++++++ .../hlsl/auto/auto-undeducible-types.hlsl | 8 ++++ 4 files changed, 69 insertions(+), 13 deletions(-) create mode 100644 tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-no-subobject.hlsl diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index 8abd6887d4..a65bd092db 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -4777,39 +4777,49 @@ class HLSLExternalSource : public ExternalSemaSource { if (type.isNull()) return false; + if (IsSubobjectType(type)) + return false; + switch (GetTypeObjectKind(type)) { - // Types with no concrete, nameable form for 'auto' to bind to. + // Types with no concrete, nameable form for 'auto' to bind to. 'string' is + // an internal type that only backs metadata (printf formats, subobject + // fields), so it is intentionally excluded here as well. case AR_TOBJ_INVALID: case AR_TOBJ_VOID: case AR_TOBJ_INNER_OBJ: + case AR_TOBJ_STRING: case AR_TOBJ_DEPENDENT: return false; - // Fully-formed types that 'auto' can deduce directly. + // Fully-formed types that 'auto' can deduce directly. Vector and matrix + // elements are always concrete scalars when classified here: a dependent + // vector/matrix is classified AR_TOBJ_DEPENDENT above, and elsewhere the + // element type is constrained to scalars. So they are always deducible. case AR_TOBJ_OBJECT: case AR_TOBJ_BASIC: case AR_TOBJ_COMPOUND: case AR_TOBJ_INTERFACE: - case AR_TOBJ_STRING: case AR_TOBJ_LINALG_MATRIX: - return true; - - // Container types: deducible iff their wrapped type is deducible. case AR_TOBJ_MATRIX: case AR_TOBJ_VECTOR: - return IsTypeDeducibleWithAuto(GetMatrixOrVectorElementType(type)); + return true; + + // An array is deducible iff its element type is. case AR_TOBJ_ARRAY: { const ArrayType *arrayType = GetStructuralForm(type)->getAsArrayTypeUnsafe(); return IsTypeDeducibleWithAuto(arrayType->getElementType()); } + + // Unreachable from 'auto' deduction: raw pointers are rejected earlier as + // unsupported in HLSL ('auto*' / '&x'), and GetTypeObjectKind never yields + // a bare qualifier node (GetStructuralForm strips qualifiers). case AR_TOBJ_POINTER: - return IsTypeDeducibleWithAuto(GetStructuralForm(type)->getPointeeType()); case AR_TOBJ_QUALIFIER: - return IsTypeDeducibleWithAuto( - GetStructuralForm(type).getUnqualifiedType()); + llvm_unreachable( + "pointer and qualifier types do not reach 'auto' deduction"); } - return false; + llvm_unreachable("unhandled ArTypeObjectKind in IsTypeDeducibleWithAuto"); } /// Given a Clang type, return the ArBasicKind classification for its diff --git a/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-deducible-types.hlsl b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-deducible-types.hlsl index 7e0ee0f188..4502fd0e63 100644 --- a/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-deducible-types.hlsl +++ b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-deducible-types.hlsl @@ -17,10 +17,11 @@ void main() { auto f = 1.5f; auto b = true; - // AR_TOBJ_VECTOR -> element AR_TOBJ_BASIC + // AR_TOBJ_VECTOR: elements are always concrete scalars (a dependent vector + // is classified AR_TOBJ_DEPENDENT instead), so vectors are always deducible. auto v = float4(1, 2, 3, 4); - // AR_TOBJ_MATRIX -> element AR_TOBJ_BASIC + // AR_TOBJ_MATRIX: likewise always deducible for the same reason. float2x2 matInit = { 1, 2, 3, 4 }; auto m = matInit; diff --git a/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-no-subobject.hlsl b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-no-subobject.hlsl new file mode 100644 index 0000000000..92554deac4 --- /dev/null +++ b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-no-subobject.hlsl @@ -0,0 +1,37 @@ +// RUN: %dxc -T lib_6_3 -HV 202x -verify %s + +// Subobjects are builtin object types used only to configure the DXR state +// object. They have no value semantics a deduced variable could meaningfully +// bind to, so 'auto' must not infer a subobject type. Each deduction below is +// expected to fail with err_hlsl_auto_undeducible_type. + +GlobalRootSignature grs = {"CBV(b0)"}; +LocalRootSignature lrs = {"UAV(u0)"}; +StateObjectConfig soc = { STATE_OBJECT_FLAGS_ALLOW_LOCAL_DEPENDENCIES_ON_EXTERNAL_DEFINITONS }; +SubobjectToExportsAssociation sea = { "grs", "a;b" }; +RaytracingShaderConfig rsc = { 128, 64 }; +RaytracingPipelineConfig rpc = { 512 }; +RaytracingPipelineConfig1 rpc1 = { 32, RAYTRACING_PIPELINE_FLAG_ALLOW_OPACITY_MICROMAPS }; +TriangleHitGroup trHitGt = { "a", "b" }; +ProceduralPrimitiveHitGroup ppHitGt = { "a", "b", "c" }; + +void useSubobjects() { + // expected-error@+1 {{'auto' cannot deduce type 'GlobalRootSignature'}} + auto a = grs; + // expected-error@+1 {{'auto' cannot deduce type 'LocalRootSignature'}} + auto b = lrs; + // expected-error@+1 {{'auto' cannot deduce type 'StateObjectConfig'}} + auto c = soc; + // expected-error@+1 {{'auto' cannot deduce type 'SubobjectToExportsAssociation'}} + auto d = sea; + // expected-error@+1 {{'auto' cannot deduce type 'RaytracingShaderConfig'}} + auto e = rsc; + // expected-error@+1 {{'auto' cannot deduce type 'RaytracingPipelineConfig'}} + auto f = rpc; + // expected-error@+1 {{'auto' cannot deduce type 'RaytracingPipelineConfig1'}} + auto g = rpc1; + // expected-error@+1 {{'auto' cannot deduce type 'TriangleHitGroup'}} + auto h = trHitGt; + // expected-error@+1 {{'auto' cannot deduce type 'ProceduralPrimitiveHitGroup'}} + auto i = ppHitGt; +} diff --git a/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-undeducible-types.hlsl b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-undeducible-types.hlsl index aaaf82c219..cd23c0bca2 100644 --- a/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-undeducible-types.hlsl +++ b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-undeducible-types.hlsl @@ -6,10 +6,18 @@ void voidFunc() {} Texture2D tex : register(t0); Texture2DMS texMS : register(t1); +// 'string' is an internal type (printf formats, subobject fields); it is only +// declarable as a global, and is intentionally not deducible by 'auto'. +string gStr = "abc"; + [numthreads(1,1,1)] void main() { int y = 1; + // AR_TOBJ_STRING: 'string' is excluded from 'auto' deduction. + // expected-error@+1 {{'auto' cannot deduce type}} + auto str = gStr; + // AR_TOBJ_VOID: a void-returning call has no value type. // expected-error@+1 {{'auto' cannot deduce type 'void'}} auto x = voidFunc(); From c7e29f41ce50d5efd438484b3f212f9bf04956ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Saffran?= Date: Mon, 1 Jun 2026 17:52:23 -0700 Subject: [PATCH 4/9] clean up --- tools/clang/lib/Sema/SemaHLSL.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index a65bd092db..f79fa8bbe5 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -4781,9 +4781,7 @@ class HLSLExternalSource : public ExternalSemaSource { return false; switch (GetTypeObjectKind(type)) { - // Types with no concrete, nameable form for 'auto' to bind to. 'string' is - // an internal type that only backs metadata (printf formats, subobject - // fields), so it is intentionally excluded here as well. + // Types with no concrete, nameable form for 'auto' to bind to. case AR_TOBJ_INVALID: case AR_TOBJ_VOID: case AR_TOBJ_INNER_OBJ: @@ -4791,10 +4789,7 @@ class HLSLExternalSource : public ExternalSemaSource { case AR_TOBJ_DEPENDENT: return false; - // Fully-formed types that 'auto' can deduce directly. Vector and matrix - // elements are always concrete scalars when classified here: a dependent - // vector/matrix is classified AR_TOBJ_DEPENDENT above, and elsewhere the - // element type is constrained to scalars. So they are always deducible. + // Fully-formed types that 'auto' can deduce directly. case AR_TOBJ_OBJECT: case AR_TOBJ_BASIC: case AR_TOBJ_COMPOUND: From 69045d544e6c68776a4473e75bff4a750338d408 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Saffran?= Date: Mon, 1 Jun 2026 17:56:44 -0700 Subject: [PATCH 5/9] format --- tools/clang/lib/Sema/SemaHLSL.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index f79fa8bbe5..ae3d99b48e 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -4781,7 +4781,7 @@ class HLSLExternalSource : public ExternalSemaSource { return false; switch (GetTypeObjectKind(type)) { - // Types with no concrete, nameable form for 'auto' to bind to. + // Types with no concrete, nameable form for 'auto' to bind to. case AR_TOBJ_INVALID: case AR_TOBJ_VOID: case AR_TOBJ_INNER_OBJ: @@ -4789,7 +4789,7 @@ class HLSLExternalSource : public ExternalSemaSource { case AR_TOBJ_DEPENDENT: return false; - // Fully-formed types that 'auto' can deduce directly. + // Fully-formed types that 'auto' can deduce directly. case AR_TOBJ_OBJECT: case AR_TOBJ_BASIC: case AR_TOBJ_COMPOUND: From 8dc7932fa949ce855aabe5607423642c43ef86a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Saffran?= Date: Tue, 2 Jun 2026 14:50:41 -0700 Subject: [PATCH 6/9] address comments from beanz --- tools/clang/include/clang/Basic/Attr.td | 9 ++++ tools/clang/lib/Sema/SemaHLSL.cpp | 46 +++++-------------- .../hlsl/auto/auto-undeducible-types.hlsl | 10 ++-- .../test/SemaHLSL/inner-object-ast-dump.hlsl | 27 +++++++++++ .../test/SemaHLSL/subobjects-ast-dump.hlsl | 9 ++++ 5 files changed, 62 insertions(+), 39 deletions(-) create mode 100644 tools/clang/test/SemaHLSL/inner-object-ast-dump.hlsl diff --git a/tools/clang/include/clang/Basic/Attr.td b/tools/clang/include/clang/Basic/Attr.td index 89c9a1b022..21b57c8934 100644 --- a/tools/clang/include/clang/Basic/Attr.td +++ b/tools/clang/include/clang/Basic/Attr.td @@ -1188,6 +1188,15 @@ def HLSLSubObject : InheritableAttr { let Args = [UnsignedArgument<"SubObjKindUint">, UnsignedArgument<"HitGroupType">]; } +// Marks builtin record types that have no deducible value form, so 'auto' must +// not infer them: the inner indexer objects behind .mips / .sample, and the +// subobject types used to configure DXR state objects. +def HLSLNonAutoDeducible : InheritableAttr { + let Spellings = []; // No spellings! + let Subjects = SubjectList<[CXXRecord]>; + let Documentation = [Undocumented]; +} + // HLSL HitObject Attribute def HLSLHitObject : InheritableAttr { diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index ae3d99b48e..0c1be9d6cc 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -3007,6 +3007,7 @@ StartSubobjectDecl(ASTContext &context, const char *name, NoLoc, &id, nullptr, DelayTypeCreationTrue); decl->addAttr(HLSLSubObjectAttr::CreateImplicit( context, static_cast(Kind), static_cast(HGT))); + decl->addAttr(HLSLNonAutoDeducibleAttr::CreateImplicit(context)); decl->addAttr(FinalAttr::CreateImplicit(context, FinalAttr::Keyword_final)); decl->startDefinition(); return decl; @@ -3528,6 +3529,8 @@ class HLSLExternalSource : public ExternalSemaSource { &m_context->Idents.get(StringRef(type1Name))); sampleSliceTypeDecl->setAccess(AS_public); sampleSliceTypeDecl->setImplicit(); + sampleSliceTypeDecl->addAttr( + HLSLNonAutoDeducibleAttr::CreateImplicit(*m_context)); recordDecl->addDecl(sampleSliceTypeDecl); sampleSliceTypeDecl->startDefinition(); const bool MutableFalse = false; @@ -3556,6 +3559,8 @@ class HLSLExternalSource : public ExternalSemaSource { recordDecl->addDecl(sampleTypeDecl); sampleTypeDecl->startDefinition(); sampleTypeDecl->setImplicit(); + sampleTypeDecl->addAttr( + HLSLNonAutoDeducibleAttr::CreateImplicit(*m_context)); FieldDecl *sampleHandleDecl = FieldDecl::Create( *m_context, sampleTypeDecl, NoLoc, NoLoc, @@ -4777,44 +4782,15 @@ class HLSLExternalSource : public ExternalSemaSource { if (type.isNull()) return false; - if (IsSubobjectType(type)) + if (GetTypeObjectKind(type) == AR_TOBJ_STRING) return false; - switch (GetTypeObjectKind(type)) { - // Types with no concrete, nameable form for 'auto' to bind to. - case AR_TOBJ_INVALID: - case AR_TOBJ_VOID: - case AR_TOBJ_INNER_OBJ: - case AR_TOBJ_STRING: - case AR_TOBJ_DEPENDENT: - return false; - - // Fully-formed types that 'auto' can deduce directly. - case AR_TOBJ_OBJECT: - case AR_TOBJ_BASIC: - case AR_TOBJ_COMPOUND: - case AR_TOBJ_INTERFACE: - case AR_TOBJ_LINALG_MATRIX: - case AR_TOBJ_MATRIX: - case AR_TOBJ_VECTOR: - return true; - - // An array is deducible iff its element type is. - case AR_TOBJ_ARRAY: { - const ArrayType *arrayType = - GetStructuralForm(type)->getAsArrayTypeUnsafe(); - return IsTypeDeducibleWithAuto(arrayType->getElementType()); - } + if (const CXXRecordDecl *recordDecl = + GetStructuralForm(type)->getAsCXXRecordDecl()) + if (recordDecl->hasAttr()) + return false; - // Unreachable from 'auto' deduction: raw pointers are rejected earlier as - // unsupported in HLSL ('auto*' / '&x'), and GetTypeObjectKind never yields - // a bare qualifier node (GetStructuralForm strips qualifiers). - case AR_TOBJ_POINTER: - case AR_TOBJ_QUALIFIER: - llvm_unreachable( - "pointer and qualifier types do not reach 'auto' deduction"); - } - llvm_unreachable("unhandled ArTypeObjectKind in IsTypeDeducibleWithAuto"); + return true; } /// Given a Clang type, return the ArBasicKind classification for its diff --git a/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-undeducible-types.hlsl b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-undeducible-types.hlsl index cd23c0bca2..c0e3fa56e5 100644 --- a/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-undeducible-types.hlsl +++ b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-undeducible-types.hlsl @@ -18,12 +18,14 @@ void main() { // expected-error@+1 {{'auto' cannot deduce type}} auto str = gStr; - // AR_TOBJ_VOID: a void-returning call has no value type. - // expected-error@+1 {{'auto' cannot deduce type 'void'}} + // void: a void-returning call has no value type. 'auto' deduces 'void', + // which is rejected as an incomplete variable type (not by the HLSL + // auto-deducibility check, which only special-cases string/inner/subobject). + // expected-error@+1 {{variable has incomplete type 'void'}} auto x = voidFunc(); - // AR_TOBJ_VOID: an explicit cast to void is equally non-deducible. - // expected-error@+1 {{'auto' cannot deduce type 'void'}} + // void: an explicit cast to void is equally non-deducible. + // expected-error@+1 {{variable has incomplete type 'void'}} auto v = (void)y; // AR_TOBJ_INNER_OBJ: .mips is an inner indexer object (Texture2D::mips_type). diff --git a/tools/clang/test/SemaHLSL/inner-object-ast-dump.hlsl b/tools/clang/test/SemaHLSL/inner-object-ast-dump.hlsl new file mode 100644 index 0000000000..0981457701 --- /dev/null +++ b/tools/clang/test/SemaHLSL/inner-object-ast-dump.hlsl @@ -0,0 +1,27 @@ +// RUN: %dxc -T ps_6_0 -ast-dump-implicit %s | FileCheck %s + +// This test verifies that the inner indexer object types backing .mips and +// .sample (mips_type / mips_slice_type, sample_type / sample_slice_type) carry +// the implicit HLSLNonAutoDeducibleAttr, so that 'auto' cannot deduce them. +// See also subobjects-ast-dump.hlsl, which checks the same attribute on +// subobject types. + +Texture2D srv; +Texture2DMS srvMS; + +float4 main() : SV_Target { + return 0; +} + +// The slice type is created before the indexer type, so it is dumped first; +// each carries the attribute as its first child. Texture2D (.mips) is referenced +// before Texture2DMS (.sample), so the mips records are dumped first. + +// CHECK: CXXRecordDecl {{0x[0-9a-fA-F]+}} <> implicit {{.*}}mips_slice_type definition +// CHECK-NEXT: HLSLNonAutoDeducibleAttr {{0x[0-9a-fA-F]+}} <> Implicit +// CHECK: CXXRecordDecl {{0x[0-9a-fA-F]+}} <> implicit {{.*}}mips_type definition +// CHECK-NEXT: HLSLNonAutoDeducibleAttr {{0x[0-9a-fA-F]+}} <> Implicit +// CHECK: CXXRecordDecl {{0x[0-9a-fA-F]+}} <> implicit {{.*}}sample_slice_type definition +// CHECK-NEXT: HLSLNonAutoDeducibleAttr {{0x[0-9a-fA-F]+}} <> Implicit +// CHECK: CXXRecordDecl {{0x[0-9a-fA-F]+}} <> implicit {{.*}}sample_type definition +// CHECK-NEXT: HLSLNonAutoDeducibleAttr {{0x[0-9a-fA-F]+}} <> Implicit diff --git a/tools/clang/test/SemaHLSL/subobjects-ast-dump.hlsl b/tools/clang/test/SemaHLSL/subobjects-ast-dump.hlsl index 6133847fb8..ecd155ed41 100644 --- a/tools/clang/test/SemaHLSL/subobjects-ast-dump.hlsl +++ b/tools/clang/test/SemaHLSL/subobjects-ast-dump.hlsl @@ -8,43 +8,52 @@ // ASTIMPL: CXXRecordDecl 0x{{.+}} <> implicit referenced struct StateObjectConfig definition // ASTIMPL-NEXT: HLSLSubObjectAttr 0x{{.+}} <> Implicit 0 2 +// ASTIMPL-NEXT: HLSLNonAutoDeducibleAttr 0x{{.+}} <> Implicit // ASTIMPL-NEXT: FinalAttr 0x{{.+}} <> Implicit final // ASTIMPL-NEXT: FieldDecl 0x{{.+}} <> implicit Flags 'unsigned int' // ASTIMPL-NEXT: CXXRecordDecl 0x{{.+}} <> implicit referenced struct GlobalRootSignature definition // ASTIMPL-NEXT: HLSLSubObjectAttr 0x{{.+}} <> Implicit 1 2 +// ASTIMPL-NEXT: HLSLNonAutoDeducibleAttr 0x{{.+}} <> Implicit // ASTIMPL-NEXT: FinalAttr 0x{{.+}} <> Implicit final // ASTIMPL-NEXT: FieldDecl 0x{{.+}} <> implicit Data 'string' // ASTIMPL-NEXT: CXXRecordDecl 0x{{.+}} <> implicit referenced struct LocalRootSignature definition // ASTIMPL-NEXT: HLSLSubObjectAttr 0x{{.+}} <> Implicit 2 2 +// ASTIMPL-NEXT: HLSLNonAutoDeducibleAttr 0x{{.+}} <> Implicit // ASTIMPL-NEXT: FinalAttr 0x{{.+}} <> Implicit final // ASTIMPL-NEXT: FieldDecl 0x{{.+}} <> implicit Data 'string' // ASTIMPL-NEXT: CXXRecordDecl 0x{{.+}} <> implicit referenced struct SubobjectToExportsAssociation definition // ASTIMPL-NEXT: HLSLSubObjectAttr 0x{{.+}} <> Implicit 8 2 +// ASTIMPL-NEXT: HLSLNonAutoDeducibleAttr 0x{{.+}} <> Implicit // ASTIMPL-NEXT: FinalAttr 0x{{.+}} <> Implicit final // ASTIMPL-NEXT: FieldDecl 0x{{.+}} <> implicit Subobject 'string' // ASTIMPL-NEXT: FieldDecl 0x{{.+}} <> implicit Exports 'string' // ASTIMPL-NEXT: CXXRecordDecl 0x{{.+}} <> implicit referenced struct RaytracingShaderConfig definition // ASTIMPL-NEXT: HLSLSubObjectAttr 0x{{.+}} <> Implicit 9 2 +// ASTIMPL-NEXT: HLSLNonAutoDeducibleAttr 0x{{.+}} <> Implicit // ASTIMPL-NEXT: FinalAttr 0x{{.+}} <> Implicit final // ASTIMPL-NEXT: FieldDecl 0x{{.+}} <> implicit MaxPayloadSizeInBytes 'unsigned int' // ASTIMPL-NEXT: FieldDecl 0x{{.+}} <> implicit MaxAttributeSizeInBytes 'unsigned int' // ASTIMPL-NEXT: CXXRecordDecl 0x{{.+}} <> implicit struct RaytracingPipelineConfig definition // ASTIMPL-NEXT: HLSLSubObjectAttr 0x{{.+}} <> Implicit 10 2 +// ASTIMPL-NEXT: HLSLNonAutoDeducibleAttr 0x{{.+}} <> Implicit // ASTIMPL-NEXT: FinalAttr 0x{{.+}} <> Implicit final // ASTIMPL-NEXT: FieldDecl 0x{{.+}} <> implicit MaxTraceRecursionDepth 'unsigned int' // ASTIMPL-NEXT: CXXRecordDecl 0x{{.+}} <> implicit referenced struct TriangleHitGroup definition // ASTIMPL-NEXT: HLSLSubObjectAttr 0x{{.+}} <> Implicit 11 0 +// ASTIMPL-NEXT: HLSLNonAutoDeducibleAttr 0x{{.+}} <> Implicit // ASTIMPL-NEXT: FinalAttr 0x{{.+}} <> Implicit final // ASTIMPL-NEXT: FieldDecl 0x{{.+}} <> implicit AnyHit 'string' // ASTIMPL-NEXT: FieldDecl 0x{{.+}} <> implicit ClosestHit 'string' // ASTIMPL-NEXT: CXXRecordDecl 0x{{.+}} <> implicit referenced struct ProceduralPrimitiveHitGroup definition // ASTIMPL-NEXT: HLSLSubObjectAttr 0x{{.+}} <> Implicit 11 1 +// ASTIMPL-NEXT: HLSLNonAutoDeducibleAttr 0x{{.+}} <> Implicit // ASTIMPL-NEXT: FinalAttr 0x{{.+}} <> Implicit final // ASTIMPL-NEXT: FieldDecl 0x{{.+}} <> implicit AnyHit 'string' // ASTIMPL-NEXT: FieldDecl 0x{{.+}} <> implicit ClosestHit 'string' // ASTIMPL-NEXT: FieldDecl 0x{{.+}} <> implicit Intersection 'string' // ASTIMPL-NEXT: CXXRecordDecl 0x{{.+}} <> implicit referenced struct RaytracingPipelineConfig1 definition // ASTIMPL-NEXT: HLSLSubObjectAttr 0x{{.+}} <> Implicit 12 2 +// ASTIMPL-NEXT: HLSLNonAutoDeducibleAttr 0x{{.+}} <> Implicit // ASTIMPL-NEXT: FinalAttr 0x{{.+}} <> Implicit final // ASTIMPL-NEXT: FieldDecl 0x{{.+}} <> implicit MaxTraceRecursionDepth 'unsigned int' // ASTIMPL-NEXT: FieldDecl 0x{{.+}} <> implicit Flags 'unsigned int' From 36aede0cebe8ce41dce93ce477889c847881c4db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Saffran?= Date: Tue, 2 Jun 2026 14:59:04 -0700 Subject: [PATCH 7/9] clean up --- .../hlsl/auto/auto-deducible-types.hlsl | 11 +++++------ .../hlsl/auto/auto-no-subobject.hlsl | 5 ----- .../hlsl/auto/auto-undeducible-types.hlsl | 14 +------------- 3 files changed, 6 insertions(+), 24 deletions(-) diff --git a/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-deducible-types.hlsl b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-deducible-types.hlsl index 4502fd0e63..b16a14b381 100644 --- a/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-deducible-types.hlsl +++ b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-deducible-types.hlsl @@ -12,24 +12,23 @@ RWBuffer output : register(u0); [numthreads(1,1,1)] void main() { - // AR_TOBJ_BASIC + // Scalars. auto i = 5; auto f = 1.5f; auto b = true; - // AR_TOBJ_VECTOR: elements are always concrete scalars (a dependent vector - // is classified AR_TOBJ_DEPENDENT instead), so vectors are always deducible. + // Vectors. auto v = float4(1, 2, 3, 4); - // AR_TOBJ_MATRIX: likewise always deducible for the same reason. + // Matrices. float2x2 matInit = { 1, 2, 3, 4 }; auto m = matInit; - // AR_TOBJ_COMPOUND + // User-defined structs. MyStruct s = { 1.0f, 2 }; auto sCopy = s; - // AR_TOBJ_OBJECT: resource handles are copyable, so binding one is allowed. + // Resource objects (their handles are copyable, so binding one is allowed). auto t = tex; // Use every value to prevent dead-code elimination. diff --git a/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-no-subobject.hlsl b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-no-subobject.hlsl index 92554deac4..7df36bd6c3 100644 --- a/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-no-subobject.hlsl +++ b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-no-subobject.hlsl @@ -1,10 +1,5 @@ // RUN: %dxc -T lib_6_3 -HV 202x -verify %s -// Subobjects are builtin object types used only to configure the DXR state -// object. They have no value semantics a deduced variable could meaningfully -// bind to, so 'auto' must not infer a subobject type. Each deduction below is -// expected to fail with err_hlsl_auto_undeducible_type. - GlobalRootSignature grs = {"CBV(b0)"}; LocalRootSignature lrs = {"UAV(u0)"}; StateObjectConfig soc = { STATE_OBJECT_FLAGS_ALLOW_LOCAL_DEPENDENCIES_ON_EXTERNAL_DEFINITONS }; diff --git a/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-undeducible-types.hlsl b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-undeducible-types.hlsl index c0e3fa56e5..7997f3f4e3 100644 --- a/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-undeducible-types.hlsl +++ b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-undeducible-types.hlsl @@ -6,34 +6,22 @@ void voidFunc() {} Texture2D tex : register(t0); Texture2DMS texMS : register(t1); -// 'string' is an internal type (printf formats, subobject fields); it is only -// declarable as a global, and is intentionally not deducible by 'auto'. -string gStr = "abc"; - [numthreads(1,1,1)] void main() { int y = 1; - // AR_TOBJ_STRING: 'string' is excluded from 'auto' deduction. // expected-error@+1 {{'auto' cannot deduce type}} - auto str = gStr; + auto str = "abc"; - // void: a void-returning call has no value type. 'auto' deduces 'void', - // which is rejected as an incomplete variable type (not by the HLSL - // auto-deducibility check, which only special-cases string/inner/subobject). // expected-error@+1 {{variable has incomplete type 'void'}} auto x = voidFunc(); - // void: an explicit cast to void is equally non-deducible. // expected-error@+1 {{variable has incomplete type 'void'}} auto v = (void)y; - // AR_TOBJ_INNER_OBJ: .mips is an inner indexer object (Texture2D::mips_type). // expected-error@+1 {{'auto' cannot deduce type}} auto m = tex.mips; - // AR_TOBJ_INNER_OBJ: .sample is an inner indexer object - // (Texture2DMS::sample_type). // expected-error@+1 {{'auto' cannot deduce type}} auto s = texMS.sample; } From 6adf8a0efeb5fb858a0a16dae91b6b87527492d3 Mon Sep 17 00:00:00 2001 From: joaosaffran Date: Tue, 2 Jun 2026 17:46:39 -0700 Subject: [PATCH 8/9] Update tools/clang/lib/Sema/SemaHLSL.cpp Co-authored-by: Chris B --- tools/clang/lib/Sema/SemaHLSL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index 0c1be9d6cc..7d83b10e47 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -4782,7 +4782,7 @@ class HLSLExternalSource : public ExternalSemaSource { if (type.isNull()) return false; - if (GetTypeObjectKind(type) == AR_TOBJ_STRING) + if (hlsl::IsPointerStringType(type)) return false; if (const CXXRecordDecl *recordDecl = From bf839622f984c881ea2e1b05b04525f78dda265b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Saffran?= Date: Tue, 2 Jun 2026 18:58:58 -0700 Subject: [PATCH 9/9] fix --- tools/clang/lib/Sema/SemaHLSL.cpp | 2 +- .../HLSLFileCheckLit/hlsl/auto/auto-deducible-types.hlsl | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index 7d83b10e47..267d0546ad 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -4782,7 +4782,7 @@ class HLSLExternalSource : public ExternalSemaSource { if (type.isNull()) return false; - if (hlsl::IsPointerStringType(type)) + if (hlsl::IsStringType(type) || hlsl::IsStringLiteralType(type)) return false; if (const CXXRecordDecl *recordDecl = diff --git a/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-deducible-types.hlsl b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-deducible-types.hlsl index b16a14b381..26a19f2b52 100644 --- a/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-deducible-types.hlsl +++ b/tools/clang/test/HLSLFileCheckLit/hlsl/auto/auto-deducible-types.hlsl @@ -20,9 +20,12 @@ void main() { // Vectors. auto v = float4(1, 2, 3, 4); + // Matrices. float2x2 matInit = { 1, 2, 3, 4 }; auto m = matInit; + auto row = m[0]; + auto elem = m[0][0]; // User-defined structs. MyStruct s = { 1.0f, 2 }; @@ -32,6 +35,6 @@ void main() { auto t = tex; // Use every value to prevent dead-code elimination. - output[0] = (float)i + f + (float)b + v.x + m._11 + sCopy.a + + output[0] = (float)i + f + (float)b + v.x + m._11 + row.x + elem + sCopy.a + (float)sCopy.b + t.SampleLevel(samp, float2(0, 0), 0).x; }