Skip to content

Commit 8ed7088

Browse files
joaosaffranllvm-beanztex3d
authored
Disallow built-in internal types to be inferred by auto (#8510)
This patch adds the check into SemaDecl to disallow auto to infer built-in internal types, like `sample_type` and `mip_type`. And Subobject types, like the ones used in DXR. --------- Co-authored-by: Chris B <beanz@abolishcrlf.org> Co-authored-by: Tex Riddell <texr@microsoft.com>
1 parent 517dd5e commit 8ed7088

10 files changed

Lines changed: 198 additions & 0 deletions

File tree

tools/clang/include/clang/Basic/Attr.td

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,6 +1188,15 @@ def HLSLSubObject : InheritableAttr {
11881188
let Args = [UnsignedArgument<"SubObjKindUint">, UnsignedArgument<"HitGroupType">];
11891189
}
11901190

1191+
// Marks builtin record types that have no deducible value form, so 'auto' must
1192+
// not infer them: the inner indexer objects behind .mips / .sample, and the
1193+
// subobject types used to configure DXR state objects.
1194+
def HLSLNonAutoDeducible : InheritableAttr {
1195+
let Spellings = []; // No spellings!
1196+
let Subjects = SubjectList<[CXXRecord]>;
1197+
let Documentation = [Undocumented];
1198+
}
1199+
11911200
// HLSL HitObject Attribute
11921201

11931202
def HLSLHitObject : InheritableAttr {

tools/clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8070,6 +8070,9 @@ def err_hlsl_auto_descriptor_heap : Error<
80708070
"'auto' cannot deduce the type of '%select{ResourceDescriptorHeap|SamplerDescriptorHeap}0'; "
80718071
"use a specific resource or sampler type instead">;
80728072

8073+
def err_hlsl_auto_undeducible_type : Error<
8074+
"'auto' cannot deduce type %0">;
8075+
80738076
// HLSL Change Ends
80748077

80758078
// SPIRV Change Starts

tools/clang/include/clang/Sema/SemaHLSL.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ bool DiagnoseTypeElements(clang::Sema &S, clang::SourceLocation Loc,
9393
TypeDiagContext LongVecDiagContext,
9494
const clang::FieldDecl *FD = nullptr);
9595

96+
// Returns true if 'auto' is allowed to deduce the given type. Container types
97+
// are deducible only when the type they wrap is deducible.
98+
bool IsTypeDeducibleWithAuto(clang::Sema &S, clang::QualType Ty);
99+
96100
void DiagnoseControlFlowConditionForHLSL(clang::Sema *self,
97101
clang::Expr *condExpr,
98102
llvm::StringRef StmtName);

tools/clang/lib/Sema/SemaDecl.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9051,6 +9051,16 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
90519051
VDecl->setInvalidDecl();
90529052
return;
90539053
}
9054+
9055+
// A dependent deduced type cannot be classified yet; defer the check to
9056+
// instantiation, when 'auto' is re-deduced to a concrete type.
9057+
if (!DeducedType->isDependentType() &&
9058+
!hlsl::IsTypeDeducibleWithAuto(*this, DeducedType)) {
9059+
Diag(VDecl->getLocation(), diag::err_hlsl_auto_undeducible_type)
9060+
<< DeducedType;
9061+
VDecl->setInvalidDecl();
9062+
return;
9063+
}
90549064
}
90559065

90569066
VDecl->setType(DeducedType);

tools/clang/lib/Sema/SemaHLSL.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3007,6 +3007,7 @@ StartSubobjectDecl(ASTContext &context, const char *name,
30073007
NoLoc, &id, nullptr, DelayTypeCreationTrue);
30083008
decl->addAttr(HLSLSubObjectAttr::CreateImplicit(
30093009
context, static_cast<unsigned>(Kind), static_cast<unsigned>(HGT)));
3010+
decl->addAttr(HLSLNonAutoDeducibleAttr::CreateImplicit(context));
30103011
decl->addAttr(FinalAttr::CreateImplicit(context, FinalAttr::Keyword_final));
30113012
decl->startDefinition();
30123013
return decl;
@@ -3528,6 +3529,8 @@ class HLSLExternalSource : public ExternalSemaSource {
35283529
&m_context->Idents.get(StringRef(type1Name)));
35293530
sampleSliceTypeDecl->setAccess(AS_public);
35303531
sampleSliceTypeDecl->setImplicit();
3532+
sampleSliceTypeDecl->addAttr(
3533+
HLSLNonAutoDeducibleAttr::CreateImplicit(*m_context));
35313534
recordDecl->addDecl(sampleSliceTypeDecl);
35323535
sampleSliceTypeDecl->startDefinition();
35333536
const bool MutableFalse = false;
@@ -3556,6 +3559,8 @@ class HLSLExternalSource : public ExternalSemaSource {
35563559
recordDecl->addDecl(sampleTypeDecl);
35573560
sampleTypeDecl->startDefinition();
35583561
sampleTypeDecl->setImplicit();
3562+
sampleTypeDecl->addAttr(
3563+
HLSLNonAutoDeducibleAttr::CreateImplicit(*m_context));
35593564

35603565
FieldDecl *sampleHandleDecl = FieldDecl::Create(
35613566
*m_context, sampleTypeDecl, NoLoc, NoLoc,
@@ -4773,6 +4778,26 @@ class HLSLExternalSource : public ExternalSemaSource {
47734778
return type;
47744779
}
47754780

4781+
bool IsTypeDeducibleWithAuto(QualType type) {
4782+
if (type.isNull())
4783+
return false;
4784+
4785+
if (hlsl::IsStringType(type) || hlsl::IsStringLiteralType(type))
4786+
return false;
4787+
4788+
if (const CXXRecordDecl *recordDecl =
4789+
GetStructuralForm(type)->getAsCXXRecordDecl()) {
4790+
if (!recordDecl->hasAttr<HLSLNonAutoDeducibleAttr>())
4791+
if (const CXXRecordDecl *pattern =
4792+
recordDecl->getTemplateInstantiationPattern())
4793+
recordDecl = pattern;
4794+
if (recordDecl->hasAttr<HLSLNonAutoDeducibleAttr>())
4795+
return false;
4796+
}
4797+
4798+
return true;
4799+
}
4800+
47764801
/// <summary>Given a Clang type, return the ArBasicKind classification for its
47774802
/// contents.</summary>
47784803
ArBasicKind GetTypeElementKind(QualType type) {
@@ -12787,6 +12812,10 @@ bool hlsl::DiagnoseTypeElements(Sema &S, SourceLocation Loc, QualType Ty,
1278712812
LongVecDiagContext, CheckedDecls, FD);
1278812813
}
1278912814

12815+
bool hlsl::IsTypeDeducibleWithAuto(Sema &S, QualType Ty) {
12816+
return HLSLExternalSource::FromSema(&S)->IsTypeDeducibleWithAuto(Ty);
12817+
}
12818+
1279012819
bool hlsl::DiagnoseNodeStructArgument(Sema *self, TemplateArgumentLoc ArgLoc,
1279112820
QualType ArgTy, bool &Empty,
1279212821
const FieldDecl *FD) {
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// RUN: %dxc -T cs_6_0 -HV 202x -verify %s
2+
// expected-no-diagnostics
3+
4+
struct MyStruct {
5+
float a;
6+
int b;
7+
};
8+
9+
Texture2D<float4> tex : register(t0);
10+
SamplerState samp : register(s0);
11+
RWBuffer<float> output : register(u0);
12+
13+
[numthreads(1,1,1)]
14+
void main() {
15+
// Scalars.
16+
auto i = 5;
17+
auto f = 1.5f;
18+
auto b = true;
19+
20+
// Vectors.
21+
auto v = float4(1, 2, 3, 4);
22+
23+
24+
// Matrices.
25+
float2x2 matInit = { 1, 2, 3, 4 };
26+
auto m = matInit;
27+
auto row = m[0];
28+
auto elem = m[0][0];
29+
30+
// User-defined structs.
31+
MyStruct s = { 1.0f, 2 };
32+
auto sCopy = s;
33+
34+
// Resource objects (their handles are copyable, so binding one is allowed).
35+
auto t = tex;
36+
37+
// Use every value to prevent dead-code elimination.
38+
output[0] = (float)i + f + (float)b + v.x + m._11 + row.x + elem + sCopy.a +
39+
(float)sCopy.b + t.SampleLevel(samp, float2(0, 0), 0).x;
40+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// RUN: %dxc -T lib_6_3 -HV 202x -verify %s
2+
3+
GlobalRootSignature grs = {"CBV(b0)"};
4+
LocalRootSignature lrs = {"UAV(u0)"};
5+
StateObjectConfig soc = { STATE_OBJECT_FLAGS_ALLOW_LOCAL_DEPENDENCIES_ON_EXTERNAL_DEFINITONS };
6+
SubobjectToExportsAssociation sea = { "grs", "a;b" };
7+
RaytracingShaderConfig rsc = { 128, 64 };
8+
RaytracingPipelineConfig rpc = { 512 };
9+
RaytracingPipelineConfig1 rpc1 = { 32, RAYTRACING_PIPELINE_FLAG_ALLOW_OPACITY_MICROMAPS };
10+
TriangleHitGroup trHitGt = { "a", "b" };
11+
ProceduralPrimitiveHitGroup ppHitGt = { "a", "b", "c" };
12+
13+
void useSubobjects() {
14+
// expected-error@+1 {{'auto' cannot deduce type 'GlobalRootSignature'}}
15+
auto a = grs;
16+
// expected-error@+1 {{'auto' cannot deduce type 'LocalRootSignature'}}
17+
auto b = lrs;
18+
// expected-error@+1 {{'auto' cannot deduce type 'StateObjectConfig'}}
19+
auto c = soc;
20+
// expected-error@+1 {{'auto' cannot deduce type 'SubobjectToExportsAssociation'}}
21+
auto d = sea;
22+
// expected-error@+1 {{'auto' cannot deduce type 'RaytracingShaderConfig'}}
23+
auto e = rsc;
24+
// expected-error@+1 {{'auto' cannot deduce type 'RaytracingPipelineConfig'}}
25+
auto f = rpc;
26+
// expected-error@+1 {{'auto' cannot deduce type 'RaytracingPipelineConfig1'}}
27+
auto g = rpc1;
28+
// expected-error@+1 {{'auto' cannot deduce type 'TriangleHitGroup'}}
29+
auto h = trHitGt;
30+
// expected-error@+1 {{'auto' cannot deduce type 'ProceduralPrimitiveHitGroup'}}
31+
auto i = ppHitGt;
32+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// RUN: %dxc -T cs_6_0 -HV 202x -verify %s
2+
3+
4+
void voidFunc() {}
5+
6+
Texture2D<float4> tex : register(t0);
7+
Texture2DMS<float4> texMS : register(t1);
8+
9+
[numthreads(1,1,1)]
10+
void main() {
11+
int y = 1;
12+
13+
// expected-error@+1 {{'auto' cannot deduce type}}
14+
auto str = "abc";
15+
16+
// expected-error@+1 {{variable has incomplete type 'void'}}
17+
auto x = voidFunc();
18+
19+
// expected-error@+1 {{variable has incomplete type 'void'}}
20+
auto v = (void)y;
21+
22+
// expected-error@+1 {{'auto' cannot deduce type}}
23+
auto m = tex.mips;
24+
// expected-error@+1 {{'auto' cannot deduce type}}
25+
auto m2 = tex.mips[0];
26+
// legal: load float4 from mip 0
27+
auto m3 = tex.mips[0][int2(1,2)];
28+
29+
// expected-error@+1 {{'auto' cannot deduce type}}
30+
auto s = texMS.sample;
31+
// expected-error@+1 {{'auto' cannot deduce type}}
32+
auto s2 = texMS.sample[0];
33+
// legal: load float4 from sample 0
34+
auto s3 = texMS.sample[0][int2(1,2)];
35+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %dxc -T ps_6_0 -ast-dump-implicit %s | FileCheck %s
2+
3+
// This test verifies that the inner indexer object types backing .mips and
4+
// .sample (mips_type / mips_slice_type, sample_type / sample_slice_type) carry
5+
// the implicit HLSLNonAutoDeducibleAttr, so that 'auto' cannot deduce them.
6+
// See also subobjects-ast-dump.hlsl, which checks the same attribute on
7+
// subobject types.
8+
9+
Texture2D<float4> srv;
10+
Texture2DMS<float4> srvMS;
11+
12+
float4 main() : SV_Target {
13+
return 0;
14+
}
15+
16+
// The slice type is created before the indexer type, so it is dumped first;
17+
// each carries the attribute as its first child. Texture2D (.mips) is referenced
18+
// before Texture2DMS (.sample), so the mips records are dumped first.
19+
20+
// CHECK: CXXRecordDecl {{0x[0-9a-fA-F]+}} <<invalid sloc>> <invalid sloc> implicit {{.*}}mips_slice_type definition
21+
// CHECK-NEXT: HLSLNonAutoDeducibleAttr {{0x[0-9a-fA-F]+}} <<invalid sloc>> Implicit
22+
// CHECK: CXXRecordDecl {{0x[0-9a-fA-F]+}} <<invalid sloc>> <invalid sloc> implicit {{.*}}mips_type definition
23+
// CHECK-NEXT: HLSLNonAutoDeducibleAttr {{0x[0-9a-fA-F]+}} <<invalid sloc>> Implicit
24+
// CHECK: CXXRecordDecl {{0x[0-9a-fA-F]+}} <<invalid sloc>> <invalid sloc> implicit {{.*}}sample_slice_type definition
25+
// CHECK-NEXT: HLSLNonAutoDeducibleAttr {{0x[0-9a-fA-F]+}} <<invalid sloc>> Implicit
26+
// CHECK: CXXRecordDecl {{0x[0-9a-fA-F]+}} <<invalid sloc>> <invalid sloc> implicit {{.*}}sample_type definition
27+
// CHECK-NEXT: HLSLNonAutoDeducibleAttr {{0x[0-9a-fA-F]+}} <<invalid sloc>> Implicit

tools/clang/test/SemaHLSL/subobjects-ast-dump.hlsl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,43 +8,52 @@
88

99
// ASTIMPL: CXXRecordDecl 0x{{.+}} <<invalid sloc>> <invalid sloc> implicit referenced struct StateObjectConfig definition
1010
// ASTIMPL-NEXT: HLSLSubObjectAttr 0x{{.+}} <<invalid sloc>> Implicit 0 2
11+
// ASTIMPL-NEXT: HLSLNonAutoDeducibleAttr 0x{{.+}} <<invalid sloc>> Implicit
1112
// ASTIMPL-NEXT: FinalAttr 0x{{.+}} <<invalid sloc>> Implicit final
1213
// ASTIMPL-NEXT: FieldDecl 0x{{.+}} <<invalid sloc>> <invalid sloc> implicit Flags 'unsigned int'
1314
// ASTIMPL-NEXT: CXXRecordDecl 0x{{.+}} <<invalid sloc>> <invalid sloc> implicit referenced struct GlobalRootSignature definition
1415
// ASTIMPL-NEXT: HLSLSubObjectAttr 0x{{.+}} <<invalid sloc>> Implicit 1 2
16+
// ASTIMPL-NEXT: HLSLNonAutoDeducibleAttr 0x{{.+}} <<invalid sloc>> Implicit
1517
// ASTIMPL-NEXT: FinalAttr 0x{{.+}} <<invalid sloc>> Implicit final
1618
// ASTIMPL-NEXT: FieldDecl 0x{{.+}} <<invalid sloc>> <invalid sloc> implicit Data 'string'
1719
// ASTIMPL-NEXT: CXXRecordDecl 0x{{.+}} <<invalid sloc>> <invalid sloc> implicit referenced struct LocalRootSignature definition
1820
// ASTIMPL-NEXT: HLSLSubObjectAttr 0x{{.+}} <<invalid sloc>> Implicit 2 2
21+
// ASTIMPL-NEXT: HLSLNonAutoDeducibleAttr 0x{{.+}} <<invalid sloc>> Implicit
1922
// ASTIMPL-NEXT: FinalAttr 0x{{.+}} <<invalid sloc>> Implicit final
2023
// ASTIMPL-NEXT: FieldDecl 0x{{.+}} <<invalid sloc>> <invalid sloc> implicit Data 'string'
2124
// ASTIMPL-NEXT: CXXRecordDecl 0x{{.+}} <<invalid sloc>> <invalid sloc> implicit referenced struct SubobjectToExportsAssociation definition
2225
// ASTIMPL-NEXT: HLSLSubObjectAttr 0x{{.+}} <<invalid sloc>> Implicit 8 2
26+
// ASTIMPL-NEXT: HLSLNonAutoDeducibleAttr 0x{{.+}} <<invalid sloc>> Implicit
2327
// ASTIMPL-NEXT: FinalAttr 0x{{.+}} <<invalid sloc>> Implicit final
2428
// ASTIMPL-NEXT: FieldDecl 0x{{.+}} <<invalid sloc>> <invalid sloc> implicit Subobject 'string'
2529
// ASTIMPL-NEXT: FieldDecl 0x{{.+}} <<invalid sloc>> <invalid sloc> implicit Exports 'string'
2630
// ASTIMPL-NEXT: CXXRecordDecl 0x{{.+}} <<invalid sloc>> <invalid sloc> implicit referenced struct RaytracingShaderConfig definition
2731
// ASTIMPL-NEXT: HLSLSubObjectAttr 0x{{.+}} <<invalid sloc>> Implicit 9 2
32+
// ASTIMPL-NEXT: HLSLNonAutoDeducibleAttr 0x{{.+}} <<invalid sloc>> Implicit
2833
// ASTIMPL-NEXT: FinalAttr 0x{{.+}} <<invalid sloc>> Implicit final
2934
// ASTIMPL-NEXT: FieldDecl 0x{{.+}} <<invalid sloc>> <invalid sloc> implicit MaxPayloadSizeInBytes 'unsigned int'
3035
// ASTIMPL-NEXT: FieldDecl 0x{{.+}} <<invalid sloc>> <invalid sloc> implicit MaxAttributeSizeInBytes 'unsigned int'
3136
// ASTIMPL-NEXT: CXXRecordDecl 0x{{.+}} <<invalid sloc>> <invalid sloc> implicit struct RaytracingPipelineConfig definition
3237
// ASTIMPL-NEXT: HLSLSubObjectAttr 0x{{.+}} <<invalid sloc>> Implicit 10 2
38+
// ASTIMPL-NEXT: HLSLNonAutoDeducibleAttr 0x{{.+}} <<invalid sloc>> Implicit
3339
// ASTIMPL-NEXT: FinalAttr 0x{{.+}} <<invalid sloc>> Implicit final
3440
// ASTIMPL-NEXT: FieldDecl 0x{{.+}} <<invalid sloc>> <invalid sloc> implicit MaxTraceRecursionDepth 'unsigned int'
3541
// ASTIMPL-NEXT: CXXRecordDecl 0x{{.+}} <<invalid sloc>> <invalid sloc> implicit referenced struct TriangleHitGroup definition
3642
// ASTIMPL-NEXT: HLSLSubObjectAttr 0x{{.+}} <<invalid sloc>> Implicit 11 0
43+
// ASTIMPL-NEXT: HLSLNonAutoDeducibleAttr 0x{{.+}} <<invalid sloc>> Implicit
3744
// ASTIMPL-NEXT: FinalAttr 0x{{.+}} <<invalid sloc>> Implicit final
3845
// ASTIMPL-NEXT: FieldDecl 0x{{.+}} <<invalid sloc>> <invalid sloc> implicit AnyHit 'string'
3946
// ASTIMPL-NEXT: FieldDecl 0x{{.+}} <<invalid sloc>> <invalid sloc> implicit ClosestHit 'string'
4047
// ASTIMPL-NEXT: CXXRecordDecl 0x{{.+}} <<invalid sloc>> <invalid sloc> implicit referenced struct ProceduralPrimitiveHitGroup definition
4148
// ASTIMPL-NEXT: HLSLSubObjectAttr 0x{{.+}} <<invalid sloc>> Implicit 11 1
49+
// ASTIMPL-NEXT: HLSLNonAutoDeducibleAttr 0x{{.+}} <<invalid sloc>> Implicit
4250
// ASTIMPL-NEXT: FinalAttr 0x{{.+}} <<invalid sloc>> Implicit final
4351
// ASTIMPL-NEXT: FieldDecl 0x{{.+}} <<invalid sloc>> <invalid sloc> implicit AnyHit 'string'
4452
// ASTIMPL-NEXT: FieldDecl 0x{{.+}} <<invalid sloc>> <invalid sloc> implicit ClosestHit 'string'
4553
// ASTIMPL-NEXT: FieldDecl 0x{{.+}} <<invalid sloc>> <invalid sloc> implicit Intersection 'string'
4654
// ASTIMPL-NEXT: CXXRecordDecl 0x{{.+}} <<invalid sloc>> <invalid sloc> implicit referenced struct RaytracingPipelineConfig1 definition
4755
// ASTIMPL-NEXT: HLSLSubObjectAttr 0x{{.+}} <<invalid sloc>> Implicit 12 2
56+
// ASTIMPL-NEXT: HLSLNonAutoDeducibleAttr 0x{{.+}} <<invalid sloc>> Implicit
4857
// ASTIMPL-NEXT: FinalAttr 0x{{.+}} <<invalid sloc>> Implicit final
4958
// ASTIMPL-NEXT: FieldDecl 0x{{.+}} <<invalid sloc>> <invalid sloc> implicit MaxTraceRecursionDepth 'unsigned int'
5059
// ASTIMPL-NEXT: FieldDecl 0x{{.+}} <<invalid sloc>> <invalid sloc> implicit Flags 'unsigned int'

0 commit comments

Comments
 (0)