Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions tools/clang/lib/AST/HlslTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ bool IsHLSLNumericOrAggregateOfNumericType(clang::QualType type) {
// which can't be annotated. But includes UDTs of trivially copyable data and
// the builtin trivially copyable raytracing structs.
bool IsHLSLCopyableAnnotatableRecord(clang::QualType QT) {
assert(!QT->isIncompleteType() && "Type must be complete!");
const clang::Type *Ty = QT.getCanonicalType().getTypePtr();
if (const RecordType *RT = dyn_cast<RecordType>(Ty)) {
const RecordDecl *RD = RT->getDecl();
Expand Down
15 changes: 14 additions & 1 deletion tools/clang/lib/Sema/SemaDXR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1190,7 +1190,10 @@ void DiagnoseCallableEntry(Sema &S, FunctionDecl *FD,
<< /*payload|callable*/ 1 << Param;
QualType Ty = Param->getType().getNonReferenceType();

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

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

// Don't diagnose here, just continue if this fails. Function parameters are
// checked in Sema::CheckParmsForFunctionDef.
if (S.RequireCompleteType(Param->getLocation(), Ty, 0))
continue;

if (!(hlsl::IsHLSLCopyableAnnotatableRecord(Ty))) {
S.Diag(Param->getLocation(), diag::err_payload_attrs_must_be_udt)
<< /*payload|attributes|callable*/ Idx << /*parameter %2|type*/ 0
Expand Down Expand Up @@ -1286,6 +1294,11 @@ void DiagnoseClosestHitEntry(Sema &S, FunctionDecl *FD,

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

// Don't diagnose here, just continue if this fails. Function parameters are
// checked in Sema::CheckParmsForFunctionDef.
if (S.RequireCompleteType(Param->getLocation(), Ty, 0))
continue;

if (!(hlsl::IsHLSLCopyableAnnotatableRecord(Ty))) {
S.Diag(Param->getLocation(), diag::err_payload_attrs_must_be_udt)
<< /*payload|attributes|callable*/ Idx << /*parameter %2|type*/ 0
Expand Down
16 changes: 12 additions & 4 deletions tools/clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3798,13 +3798,21 @@ static void warnOnSizeofOnArrayDecay(Sema &S, SourceLocation Loc, QualType T,
}

// HLSL Change Begins
bool Sema::CheckHLSLUnaryExprOrTypeTraitOperand(QualType ExprType, SourceLocation Loc,
bool Sema::CheckHLSLUnaryExprOrTypeTraitOperand(QualType ExprType,
SourceLocation Loc,
UnaryExprOrTypeTrait ExprKind) {
assert(ExprKind == UnaryExprOrTypeTrait::UETT_SizeOf);

// "sizeof 42" is ill-defined because HLSL has literal int type which can decay to an int of any size.
const BuiltinType* BuiltinTy = ExprType->getAs<BuiltinType>();
if (BuiltinTy != nullptr && (BuiltinTy->getKind() == BuiltinType::LitInt || BuiltinTy->getKind() == BuiltinType::LitFloat)) {
if (RequireCompleteType(Loc, ExprType,
diag::err_sizeof_alignof_incomplete_type, ExprKind,
ExprType))
return true;

// "sizeof 42" is ill-defined because HLSL has literal int type which can
// decay to an int of any size.
const BuiltinType *BuiltinTy = ExprType->getAs<BuiltinType>();
if (BuiltinTy != nullptr && (BuiltinTy->getKind() == BuiltinType::LitInt ||
BuiltinTy->getKind() == BuiltinType::LitFloat)) {
Diag(Loc, diag::err_hlsl_sizeof_literal) << ExprType;
return true;
}
Expand Down
3 changes: 3 additions & 0 deletions tools/clang/lib/Sema/SemaHLSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10947,6 +10947,9 @@ HLSLExternalSource::DeduceTemplateArgumentsForHLSL(
}

if (IsBABLoad || IsBABStore) {
// Incomplete type is diagnosed elsewhere, so just fail here.
if (getSema()->RequireCompleteType(Loc, functionTemplateTypeArg, 0))
return Sema::TemplateDeductionResult::TDK_Invalid;
const bool IsLegalTemplate =
!functionTemplateTypeArg.isNull() &&
hlsl::IsHLSLNumericOrAggregateOfNumericType(
Expand Down
21 changes: 21 additions & 0 deletions tools/clang/test/SemaHLSL/raytracing-entry-diags.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -181,3 +181,24 @@ void callable7(inout MyPayload payload, float F) {}

[shader("callable")]
float callable8(inout MyPayload payload) {} // expected-error{{return type for 'callable' shaders must be void}}

// expected-note@+1 6 {{forward declaration of 'Incomplete'}}
struct Incomplete;

// expected-error@+3{{variable has incomplete type 'Incomplete'}}
// expected-error@+2{{variable has incomplete type '__restrict Incomplete'}}
[shader("anyhit")]
void anyhit_incomplete( inout Incomplete A1, Incomplete A2) { }

// expected-error@+3{{variable has incomplete type 'Incomplete'}}
// expected-error@+2{{variable has incomplete type '__restrict Incomplete'}}
[shader("closesthit")]
void closesthit_incomplete( inout Incomplete payload, Incomplete attr ) {}

// expected-error@+2{{variable has incomplete type '__restrict Incomplete'}}
[shader("miss")]
void miss_incomplete( inout Incomplete payload) { }

// expected-error@+2{{variable has incomplete type '__restrict Incomplete'}}
[shader("callable")]
void callable_incomplete(inout Incomplete payload) {}
26 changes: 26 additions & 0 deletions tools/clang/test/SemaHLSL/sizeof-requires-complete-type.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// RUN: %dxc -T lib_6_3 -verify %s

struct Complete {};

struct Incomplete; // expected-note{{forward declaration of 'Incomplete'}}
template<typename T> struct CompleteTemplate {};

void fn() {
uint s;
// Complete types are easy. They are complete before we get to the expression.
s = sizeof(Complete); // This works!

// A type may be incomplete for several reasons.

// It may be incomplete because there is only a forward declaration, which
// should produce an error since we can't materialize a definition.
s = sizeof(Incomplete); // expected-error{{invalid application of 'sizeof' to an incomplete type 'Incomplete'}}

// It may be incomplete because it is an un-instantiated template, which
// should work because we can just instantiate it.
s = sizeof(CompleteTemplate<int>); // This works!

// It may be incomplete because it is a lazy-initialized type from HLSL, which
// should work because we can just complete it.
s = sizeof(RayDesc);
}
39 changes: 39 additions & 0 deletions tools/clang/test/SemaHLSL/template-udt-load.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,51 @@
ByteAddressBuffer In;
RWBuffer<float> Out;

template <typename T>
struct Foo {
// expected-note@+1{{'RWBuffer<float>' field declared here}}
T Member;
};

template <typename T>
struct MyTemplate {
T GetValue(ByteAddressBuffer srv, uint offset) {
// expected-error@+2{{Explicit template arguments on intrinsic Load must be a single numeric type}}
// expected-error@+1{{object 'RWBuffer<float>' is not allowed in builtin template parameters}}
return srv.Load<T>(offset);
}
};
template <typename T>
T GetValue(uint offset) {
MyTemplate<T> myTemplate;
// expected-error@+2{{scalar, vector, or matrix expected}}
// expected-note@+1{{in instantiation of member function 'MyTemplate<RWBuffer<float> >::GetValue' requested here}}
return myTemplate.GetValue(In, offset) +
// expected-error@+2{{Explicit template arguments on intrinsic Load must be a single numeric type}}
// expected-error@+1{{object 'RWBuffer<float>' is not allowed in builtin template parameters}}
In.Load<Foo<T> >(offset + 4).Member;
}

// expected-note@+1{{forward declaration of 'Incomplete'}}
struct Incomplete;

[shader("compute")]
[numthreads(1,1,1)]
void main()
{
RWBuffer<float> FB = In.Load<RWBuffer<float> >(0);
// expected-error@-1{{Explicit template arguments on intrinsic Load must be a single numeric type}}
// expected-error@-2{{object 'RWBuffer<float>' is not allowed in builtin template parameters}}

Out[0] = FB[0];

// Ok:
Out[4] = GetValue<float>(4);

// expected-note@?{{'Load' declared here}}
// expected-error@+1{{calling 'Load' with incomplete return type 'Incomplete'}}
Out[8] = In.Load<Incomplete>(8);

// expected-note@+1 2 {{in instantiation of function template specialization 'GetValue<RWBuffer<float> >' requested here}}
RWBuffer<float> FB2 = GetValue<RWBuffer<float> >(16);
}
Loading