Skip to content

Commit 77dcbb6

Browse files
llvm-beanztex3d
andauthored
Require complete types in some missing places (microsoft#7511)
This change adds two additional calls to Sema::RequireCompleteType, one when evaluating unary `sizeof`, which fixes a reported issue with templates. The second is in the DXR diagnostics where complete type should be required but not diagnosed because ordering in the compiler is a bit wonky when diagnosing DXR entry points. Fixes microsoft#7510 --------- Co-authored-by: Tex Riddell <[email protected]>
1 parent 296d4ae commit 77dcbb6

File tree

7 files changed

+121
-10
lines changed

7 files changed

+121
-10
lines changed

tools/clang/lib/AST/HlslTypes.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ bool IsHLSLNumericOrAggregateOfNumericType(clang::QualType type) {
108108
// which can't be annotated. But includes UDTs of trivially copyable data and
109109
// the builtin trivially copyable raytracing structs.
110110
bool IsHLSLCopyableAnnotatableRecord(clang::QualType QT) {
111+
assert(!QT->isIncompleteType() && "Type must be complete!");
111112
const clang::Type *Ty = QT.getCanonicalType().getTypePtr();
112113
if (const RecordType *RT = dyn_cast<RecordType>(Ty)) {
113114
const RecordDecl *RD = RT->getDecl();

tools/clang/lib/Sema/SemaDXR.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1190,7 +1190,10 @@ void DiagnoseCallableEntry(Sema &S, FunctionDecl *FD,
11901190
<< /*payload|callable*/ 1 << Param;
11911191
QualType Ty = Param->getType().getNonReferenceType();
11921192

1193-
if (!(hlsl::IsHLSLCopyableAnnotatableRecord(Ty)))
1193+
// Don't diagnose incomplete type here. Function parameters are
1194+
// checked in Sema::CheckParmsForFunctionDef.
1195+
if (!S.RequireCompleteType(Param->getLocation(), Ty, 0) &&
1196+
!(hlsl::IsHLSLCopyableAnnotatableRecord(Ty)))
11941197
S.Diag(Param->getLocation(), diag::err_payload_attrs_must_be_udt)
11951198
<< /*payload|attributes|callable*/ 2 << /*parameter %2|type*/ 0
11961199
<< Param;
@@ -1232,6 +1235,11 @@ void DiagnoseMissOrAnyHitEntry(Sema &S, FunctionDecl *FD,
12321235

12331236
QualType Ty = Param->getType().getNonReferenceType();
12341237

1238+
// Don't diagnose here, just continue if this fails. Function parameters are
1239+
// checked in Sema::CheckParmsForFunctionDef.
1240+
if (S.RequireCompleteType(Param->getLocation(), Ty, 0))
1241+
continue;
1242+
12351243
if (!(hlsl::IsHLSLCopyableAnnotatableRecord(Ty))) {
12361244
S.Diag(Param->getLocation(), diag::err_payload_attrs_must_be_udt)
12371245
<< /*payload|attributes|callable*/ Idx << /*parameter %2|type*/ 0
@@ -1286,6 +1294,11 @@ void DiagnoseClosestHitEntry(Sema &S, FunctionDecl *FD,
12861294

12871295
QualType Ty = Param->getType().getNonReferenceType();
12881296

1297+
// Don't diagnose here, just continue if this fails. Function parameters are
1298+
// checked in Sema::CheckParmsForFunctionDef.
1299+
if (S.RequireCompleteType(Param->getLocation(), Ty, 0))
1300+
continue;
1301+
12891302
if (!(hlsl::IsHLSLCopyableAnnotatableRecord(Ty))) {
12901303
S.Diag(Param->getLocation(), diag::err_payload_attrs_must_be_udt)
12911304
<< /*payload|attributes|callable*/ Idx << /*parameter %2|type*/ 0

tools/clang/lib/Sema/SemaExpr.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3798,13 +3798,21 @@ static void warnOnSizeofOnArrayDecay(Sema &S, SourceLocation Loc, QualType T,
37983798
}
37993799

38003800
// HLSL Change Begins
3801-
bool Sema::CheckHLSLUnaryExprOrTypeTraitOperand(QualType ExprType, SourceLocation Loc,
3801+
bool Sema::CheckHLSLUnaryExprOrTypeTraitOperand(QualType ExprType,
3802+
SourceLocation Loc,
38023803
UnaryExprOrTypeTrait ExprKind) {
38033804
assert(ExprKind == UnaryExprOrTypeTrait::UETT_SizeOf);
38043805

3805-
// "sizeof 42" is ill-defined because HLSL has literal int type which can decay to an int of any size.
3806-
const BuiltinType* BuiltinTy = ExprType->getAs<BuiltinType>();
3807-
if (BuiltinTy != nullptr && (BuiltinTy->getKind() == BuiltinType::LitInt || BuiltinTy->getKind() == BuiltinType::LitFloat)) {
3806+
if (RequireCompleteType(Loc, ExprType,
3807+
diag::err_sizeof_alignof_incomplete_type, ExprKind,
3808+
ExprType))
3809+
return true;
3810+
3811+
// "sizeof 42" is ill-defined because HLSL has literal int type which can
3812+
// decay to an int of any size.
3813+
const BuiltinType *BuiltinTy = ExprType->getAs<BuiltinType>();
3814+
if (BuiltinTy != nullptr && (BuiltinTy->getKind() == BuiltinType::LitInt ||
3815+
BuiltinTy->getKind() == BuiltinType::LitFloat)) {
38083816
Diag(Loc, diag::err_hlsl_sizeof_literal) << ExprType;
38093817
return true;
38103818
}

tools/clang/lib/Sema/SemaHLSL.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10947,11 +10947,13 @@ HLSLExternalSource::DeduceTemplateArgumentsForHLSL(
1094710947
}
1094810948

1094910949
if (IsBABLoad || IsBABStore) {
10950-
const bool IsLegalTemplate =
10951-
!functionTemplateTypeArg.isNull() &&
10952-
hlsl::IsHLSLNumericOrAggregateOfNumericType(
10953-
functionTemplateTypeArg);
10954-
if (!IsLegalTemplate) {
10950+
const bool IsNull = functionTemplateTypeArg.isNull();
10951+
// Incomplete type is diagnosed elsewhere, so just fail if incomplete.
10952+
if (!IsNull &&
10953+
getSema()->RequireCompleteType(Loc, functionTemplateTypeArg, 0))
10954+
return Sema::TemplateDeductionResult::TDK_Invalid;
10955+
if (IsNull || !hlsl::IsHLSLNumericOrAggregateOfNumericType(
10956+
functionTemplateTypeArg)) {
1095510957
getSema()->Diag(Loc, diag::err_hlsl_intrinsic_template_arg_numeric)
1095610958
<< intrinsicName;
1095710959
DiagnoseTypeElements(

tools/clang/test/SemaHLSL/raytracing-entry-diags.hlsl

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,3 +181,24 @@ void callable7(inout MyPayload payload, float F) {}
181181

182182
[shader("callable")]
183183
float callable8(inout MyPayload payload) {} // expected-error{{return type for 'callable' shaders must be void}}
184+
185+
// expected-note@+1 6 {{forward declaration of 'Incomplete'}}
186+
struct Incomplete;
187+
188+
// expected-error@+3{{variable has incomplete type 'Incomplete'}}
189+
// expected-error@+2{{variable has incomplete type '__restrict Incomplete'}}
190+
[shader("anyhit")]
191+
void anyhit_incomplete( inout Incomplete A1, Incomplete A2) { }
192+
193+
// expected-error@+3{{variable has incomplete type 'Incomplete'}}
194+
// expected-error@+2{{variable has incomplete type '__restrict Incomplete'}}
195+
[shader("closesthit")]
196+
void closesthit_incomplete( inout Incomplete payload, Incomplete attr ) {}
197+
198+
// expected-error@+2{{variable has incomplete type '__restrict Incomplete'}}
199+
[shader("miss")]
200+
void miss_incomplete( inout Incomplete payload) { }
201+
202+
// expected-error@+2{{variable has incomplete type '__restrict Incomplete'}}
203+
[shader("callable")]
204+
void callable_incomplete(inout Incomplete payload) {}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %dxc -T lib_6_3 -verify %s
2+
3+
struct Complete {};
4+
5+
struct Incomplete; // expected-note{{forward declaration of 'Incomplete'}}
6+
template<typename T> struct CompleteTemplate {};
7+
8+
void fn() {
9+
uint s;
10+
// Complete types are easy. They are complete before we get to the expression.
11+
s = sizeof(Complete); // This works!
12+
13+
// A type may be incomplete for several reasons.
14+
15+
// It may be incomplete because there is only a forward declaration, which
16+
// should produce an error since we can't materialize a definition.
17+
s = sizeof(Incomplete); // expected-error{{invalid application of 'sizeof' to an incomplete type 'Incomplete'}}
18+
19+
// It may be incomplete because it is an un-instantiated template, which
20+
// should work because we can just instantiate it.
21+
s = sizeof(CompleteTemplate<int>); // This works!
22+
23+
// It may be incomplete because it is a lazy-initialized type from HLSL,
24+
// which can be completed, and then will report a non-numeric type error.
25+
// expected-error@+1{{invalid application of 'sizeof' to non-numeric type 'Buffer'}}
26+
s = sizeof(Buffer);
27+
}

tools/clang/test/SemaHLSL/template-udt-load.hlsl

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,51 @@
44
ByteAddressBuffer In;
55
RWBuffer<float> Out;
66

7+
template <typename T>
8+
struct Foo {
9+
// expected-note@+1{{'RWBuffer<float>' field declared here}}
10+
T Member;
11+
};
12+
13+
template <typename T>
14+
struct MyTemplate {
15+
T GetValue(ByteAddressBuffer srv, uint offset) {
16+
// expected-error@+2{{Explicit template arguments on intrinsic Load must be a single numeric type}}
17+
// expected-error@+1{{object 'RWBuffer<float>' is not allowed in builtin template parameters}}
18+
return srv.Load<T>(offset);
19+
}
20+
};
21+
template <typename T>
22+
T GetValue(uint offset) {
23+
MyTemplate<T> myTemplate;
24+
// expected-error@+2{{scalar, vector, or matrix expected}}
25+
// expected-note@+1{{in instantiation of member function 'MyTemplate<RWBuffer<float> >::GetValue' requested here}}
26+
return myTemplate.GetValue(In, offset) +
27+
// expected-error@+2{{Explicit template arguments on intrinsic Load must be a single numeric type}}
28+
// expected-error@+1{{object 'RWBuffer<float>' is not allowed in builtin template parameters}}
29+
In.Load<Foo<T> >(offset + 4).Member;
30+
}
31+
32+
// expected-note@+1{{forward declaration of 'Incomplete'}}
33+
struct Incomplete;
34+
735
[shader("compute")]
836
[numthreads(1,1,1)]
937
void main()
1038
{
1139
RWBuffer<float> FB = In.Load<RWBuffer<float> >(0);
1240
// expected-error@-1{{Explicit template arguments on intrinsic Load must be a single numeric type}}
1341
// expected-error@-2{{object 'RWBuffer<float>' is not allowed in builtin template parameters}}
42+
1443
Out[0] = FB[0];
44+
45+
// Ok:
46+
Out[4] = GetValue<float>(4);
47+
48+
// expected-note@?{{'Load' declared here}}
49+
// expected-error@+1{{calling 'Load' with incomplete return type 'Incomplete'}}
50+
Out[8] = In.Load<Incomplete>(8);
51+
52+
// expected-note@+1 2 {{in instantiation of function template specialization 'GetValue<RWBuffer<float> >' requested here}}
53+
RWBuffer<float> FB2 = GetValue<RWBuffer<float> >(16);
1554
}

0 commit comments

Comments
 (0)