diff --git a/tools/clang/include/clang/AST/DeclCXX.h b/tools/clang/include/clang/AST/DeclCXX.h index 36e0f99c82..3b07576545 100644 --- a/tools/clang/include/clang/AST/DeclCXX.h +++ b/tools/clang/include/clang/AST/DeclCXX.h @@ -465,10 +465,6 @@ class CXXRecordDecl : public RecordDecl { /// \brief Whether we are currently parsing base specifiers. bool IsParsingBaseSpecifiers : 1; - /// \brief Whether this class contains at least one member or base - /// class containing an HLSL vector longer than 4 elements. - bool HasHLSLLongVector : 1; - /// \brief The number of base class specifiers in Bases. unsigned NumBases; @@ -1022,13 +1018,6 @@ class CXXRecordDecl : public RecordDecl { return data().NeedOverloadResolutionForDestructor; } - // HLSL Change add HLSL Long vector bit. - /// \brief Determine whether this class contains an HLSL long vector - /// of over 4 elements. - bool hasHLSLLongVector() { return data().HasHLSLLongVector; } - /// \brief Set that this class contains an HLSL long vector of over 4 elements - bool setHasHLSLLongVector() { return data().HasHLSLLongVector = true; } - /// \brief Determine whether this class describes a lambda function object. bool isLambda() const { // An update record can't turn a non-lambda into a lambda. diff --git a/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td b/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td index ae7e777180..003aa50795 100644 --- a/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7558,8 +7558,6 @@ def err_hlsl_missing_type_specifier : Error< // Patterened after err_missing_typ "HLSL requires a type specifier for all declarations">; def err_hlsl_multiple_concrete_bases : Error< "multiple concrete base types specified">; -def err_hlsl_objectintemplateargument : Error< - "%0 is an object and cannot be used as a type parameter">; def err_hlsl_packoffset_requires_cbuffer : Error< "packoffset is only allowed in a constant buffer">; def warn_hlsl_packoffset_mix : Warning< @@ -7886,6 +7884,15 @@ def err_hlsl_unsupported_long_vector "entry function parameters|entry function return type|" "patch constant function parameters|patch constant function return type|" "payload parameters|attributes}0 are not supported">; +// First %select options must match err_hlsl_unsupported_long_vector (same index used) +def err_hlsl_unsupported_object_context + : Error<"object %0 is not allowed in " + "%select{ConstantBuffers or TextureBuffers|" + "tessellation patches|geometry streams|node records|" + "cbuffers or tbuffers|user-defined struct parameter|" + "entry function parameters|entry function return type|" + "patch constant function parameters|patch constant function return type|" + "payload parameters|attributes|builtin template parameters|structured buffers|global variables|groupshared variables}1">; def err_hlsl_logical_binop_scalar : Error< "operands for short-circuiting logical binary operator must be scalar, for non-scalar types use '%select{and|or}0'">; def err_hlsl_ternary_scalar : Error< @@ -7970,8 +7977,6 @@ def err_hlsl_too_many_node_inputs : Error< "Node shader '%0' may not have more than one input record">; def err_hlsl_node_record_type : Error< "%0 is not valid as a node record type - struct/class required">; -def err_hlsl_node_record_object : Error< - "object %0 may not appear in a node record">; def err_hlsl_array_disallowed : Error< "%select{entry parameter|declaration}1 of type %0 may not be an array">; def err_hlsl_inputpatch_size: Error< diff --git a/tools/clang/include/clang/Sema/SemaHLSL.h b/tools/clang/include/clang/Sema/SemaHLSL.h index 59d99ab4c5..80ce8ddd7d 100644 --- a/tools/clang/include/clang/Sema/SemaHLSL.h +++ b/tools/clang/include/clang/Sema/SemaHLSL.h @@ -59,6 +59,38 @@ bool DiagnoseNodeStructArgument(clang::Sema *self, clang::QualType ArgTy, bool &Empty, const clang::FieldDecl *FD = nullptr); +// Keep this in sync with err_hlsl_unsupported_object in DiagnosticSemaKinds.td +enum class TypeDiagContext { + // Indices that the type context is valid and no diagnostics should be emitted + // for this type category. + Valid = -1, + // Supported indices for both `err_hlsl_unsupported_object_context` and + // `err_hlsl_unsupported_long_vector` + ConstantBuffersOrTextureBuffers = 0, + TessellationPatches = 1, + GeometryStreams = 2, + NodeRecords = 3, + CBuffersOrTBuffers = 4, + UserDefinedStructParameter = 5, + EntryFunctionParameters = 6, + EntryFunctionReturnType = 7, + PatchConstantFunctionParameters = 8, + PatchConstantFunctionReturnType = 9, + PayloadParameters = 10, + Attributes = 11, + TypeParameter = 12, + LongVecDiagMaxSelectIndex = TypeParameter, + // Below only supported for `err_hlsl_diag_unsupported_object_context` + StructuredBuffers = 13, + GlobalVariables = 14, + GroupShared = 15, + DiagMaxSelectIndex = 15, +}; +bool DiagnoseTypeElements(clang::Sema &S, clang::SourceLocation Loc, + clang::QualType Ty, TypeDiagContext ObjDiagContext, + TypeDiagContext LongVecDiagContext, + const clang::FieldDecl *FD = nullptr); + void DiagnoseControlFlowConditionForHLSL(clang::Sema *self, clang::Expr *condExpr, llvm::StringRef StmtName); diff --git a/tools/clang/lib/AST/DeclCXX.cpp b/tools/clang/lib/AST/DeclCXX.cpp index baed44667f..8023a0a588 100644 --- a/tools/clang/lib/AST/DeclCXX.cpp +++ b/tools/clang/lib/AST/DeclCXX.cpp @@ -72,8 +72,8 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) ImplicitCopyAssignmentHasConstParam(true), HasDeclaredCopyConstructorWithConstParam(false), HasDeclaredCopyAssignmentWithConstParam(false), IsLambda(false), - IsParsingBaseSpecifiers(false), HasHLSLLongVector(false), NumBases(0), - NumVBases(0), Bases(), VBases(), Definition(D), FirstFriend() {} + IsParsingBaseSpecifiers(false), NumBases(0), NumVBases(0), Bases(), + VBases(), Definition(D), FirstFriend() {} // HLSL Change End - Add HasLongVector and clang-format CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getBasesSlowCase() const { @@ -203,11 +203,6 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, if (!BaseClassDecl->isStandardLayout()) data().IsStandardLayout = false; - // HLSL Change Begin - Propagate presence of long vector to child classes. - if (BaseClassDecl->hasHLSLLongVector()) - data().HasHLSLLongVector = true; - // HLSL Change End - // Record if this base is the first non-literal field or base. if (!hasNonLiteralTypeFieldsOrBases() && !BaseType->isLiteralType(C)) data().HasNonLiteralTypeFieldsOrBases = true; @@ -389,11 +384,6 @@ void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) { data().NeedOverloadResolutionForMoveConstructor = true; data().NeedOverloadResolutionForDestructor = true; } - - // HLSL Change Begin - Propagate presence of long vector to child classes. - if (Subobj->hasHLSLLongVector()) - data().HasHLSLLongVector = true; - // HLSL Change End } /// Callback function for CXXRecordDecl::forallBases that acknowledges diff --git a/tools/clang/lib/AST/HlslTypes.cpp b/tools/clang/lib/AST/HlslTypes.cpp index 07efb53c8c..871937aaa4 100644 --- a/tools/clang/lib/AST/HlslTypes.cpp +++ b/tools/clang/lib/AST/HlslTypes.cpp @@ -118,6 +118,13 @@ bool IsHLSLCopyableAnnotatableRecord(clang::QualType QT) { if (!IsHLSLNumericOrAggregateOfNumericType(Member->getType())) return false; } + if (auto *CXXRD = dyn_cast(RD)) { + // Walk up the inheritance chain and check base class fields + for (const auto &Base : CXXRD->bases()) { + if (!IsHLSLCopyableAnnotatableRecord(Base.getType())) + return false; + } + } return true; } return false; diff --git a/tools/clang/lib/Sema/SemaDXR.cpp b/tools/clang/lib/Sema/SemaDXR.cpp index f0102f9e3f..04e1582513 100644 --- a/tools/clang/lib/Sema/SemaDXR.cpp +++ b/tools/clang/lib/Sema/SemaDXR.cpp @@ -827,19 +827,16 @@ void DiagnoseBuiltinCallWithPayload(Sema &S, const VarDecl *Payload, } // Verify that the payload type is legal - if (!hlsl::IsHLSLCopyableAnnotatableRecord(Payload->getType())) { + if (!hlsl::IsHLSLCopyableAnnotatableRecord(Payload->getType())) S.Diag(Payload->getLocation(), diag::err_payload_attrs_must_be_udt) << /*payload|attributes|callable*/ 0 << /*parameter %2|type*/ 0 << Payload; - return; - } - if (ContainsLongVector(Payload->getType())) { - const unsigned PayloadParametersIdx = 10; - S.Diag(Payload->getLocation(), diag::err_hlsl_unsupported_long_vector) - << PayloadParametersIdx; + // This will produce more details, but also catch disallowed long vectors + const TypeDiagContext DiagContext = TypeDiagContext::PayloadParameters; + if (DiagnoseTypeElements(S, Payload->getLocation(), Payload->getType(), + DiagContext, DiagContext)) return; - } CollectNonAccessableFields(PayloadType, CallerStage, {}, {}, NonWriteableFields, NonReadableFields); diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index b15068638d..e5424ecdde 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -46,6 +46,7 @@ #include "clang/Sema/TemplateDeduction.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -5394,7 +5395,8 @@ class HLSLExternalSource : public ExternalSemaSource { objectKind = ClassifyRecordType(recordType); switch (objectKind) { case AR_TOBJ_OBJECT: - m_sema->Diag(argLoc, diag::err_hlsl_objectintemplateargument) << type; + m_sema->Diag(argLoc, diag::err_hlsl_unsupported_object_context) + << type << static_cast(TypeDiagContext::TypeParameter); return false; case AR_TOBJ_COMPOUND: { const RecordDecl *recordDecl = recordType->getDecl(); @@ -5533,14 +5535,27 @@ class HLSLExternalSource : public ExternalSemaSource { m_sema->RequireCompleteType(argSrcLoc, argType, diag::err_typecheck_decl_incomplete_type); - if (ContainsLongVector(argType)) { - const unsigned ConstantBuffersOrTextureBuffersIdx = 0; - m_sema->Diag(argSrcLoc, diag::err_hlsl_unsupported_long_vector) - << ConstantBuffersOrTextureBuffersIdx; + TypeDiagContext DiagContext = + TypeDiagContext::ConstantBuffersOrTextureBuffers; + if (DiagnoseTypeElements(*m_sema, argSrcLoc, argType, DiagContext, + DiagContext)) return true; - } } return false; + } else if (ResAttr && DXIL::IsStructuredBuffer(ResAttr->getResKind())) { + if (TemplateArgList.size() == 1) { + const TemplateArgumentLoc &ArgLoc = TemplateArgList[0]; + const TemplateArgument &Arg = ArgLoc.getArgument(); + if (Arg.getKind() == TemplateArgument::ArgKind::Type) { + QualType ArgType = Arg.getAsType(); + SourceLocation ArgSrcLoc = ArgLoc.getLocation(); + if (DiagnoseTypeElements( + *m_sema, ArgSrcLoc, ArgType, + TypeDiagContext::StructuredBuffers /*ObjDiagContext*/, + TypeDiagContext::Valid /*LongVecDiagContext*/)) + return true; + } + } } else if (Template->getTemplatedDecl()->hasAttr()) { @@ -5641,13 +5656,10 @@ class HLSLExternalSource : public ExternalSemaSource { CXXRecordDecl *Decl = arg.getAsType()->getAsCXXRecordDecl(); if (Decl && !Decl->isCompleteDefinition()) return true; - if (ContainsLongVector(arg.getAsType())) { - const unsigned TessellationPatchesIDx = 1; - m_sema->Diag(argLoc.getLocation(), - diag::err_hlsl_unsupported_long_vector) - << TessellationPatchesIDx; + const TypeDiagContext DiagContext = TypeDiagContext::TessellationPatches; + if (DiagnoseTypeElements(*m_sema, argLoc.getLocation(), arg.getAsType(), + DiagContext, DiagContext)) return true; - } } else if (Template->getTemplatedDecl()->hasAttr()) { DXASSERT(TemplateArgList.size() > 0, "Geometry streams should have at least one template args"); @@ -5660,13 +5672,10 @@ class HLSLExternalSource : public ExternalSemaSource { CXXRecordDecl *Decl = arg.getAsType()->getAsCXXRecordDecl(); if (Decl && !Decl->isCompleteDefinition()) return true; - if (ContainsLongVector(arg.getAsType())) { - const unsigned GeometryStreamsIdx = 2; - m_sema->Diag(argLoc.getLocation(), - diag::err_hlsl_unsupported_long_vector) - << GeometryStreamsIdx; + const TypeDiagContext DiagContext = TypeDiagContext::GeometryStreams; + if (DiagnoseTypeElements(*m_sema, argLoc.getLocation(), arg.getAsType(), + DiagContext, DiagContext)) return true; - } } bool isMatrix = Template->getCanonicalDecl() == @@ -10784,11 +10793,9 @@ bool DiagnoseIntersectionAttributes(Sema &S, SourceLocation Loc, QualType Ty) { return false; } - if (ContainsLongVector(Ty)) { - const unsigned AttributesIdx = 11; - S.Diag(Loc, diag::err_hlsl_unsupported_long_vector) << AttributesIdx; + const TypeDiagContext DiagContext = TypeDiagContext::Attributes; + if (DiagnoseTypeElements(S, Loc, Ty, DiagContext, DiagContext)) return false; - } return true; } @@ -10940,6 +10947,10 @@ HLSLExternalSource::DeduceTemplateArgumentsForHLSL( if (!IsLegalTemplate) { getSema()->Diag(Loc, diag::err_hlsl_intrinsic_template_arg_numeric) << intrinsicName; + DiagnoseTypeElements( + *getSema(), Loc, functionTemplateTypeArg, + TypeDiagContext::TypeParameter /*ObjDiagContext*/, + TypeDiagContext::Valid /*LongVecDiagContext*/); return Sema::TemplateDeductionResult::TDK_Invalid; } } @@ -12128,34 +12139,73 @@ void Sema::DiagnoseReachableHLSLCall(CallExpr *CE, const hlsl::ShaderModel *SM, ///////////////////////////////////////////////////////////////////////////// -bool hlsl::DiagnoseNodeStructArgument(Sema *self, TemplateArgumentLoc ArgLoc, - QualType ArgTy, bool &Empty, - const FieldDecl *FD) { - DXASSERT_NOMSG(!ArgTy.isNull()); +static bool AllowObjectInContext(QualType Ty, TypeDiagContext DiagContext) { + // Disallow all object in template type parameters (former + // err_hlsl_objectintemplateargument) + if (DiagContext == TypeDiagContext::TypeParameter) + return false; + // Disallow all objects in node records (former + // err_hlsl_node_record_object) + if (DiagContext == TypeDiagContext::NodeRecords) + return false; + // TODO: Extend this list for other object types. + if (IsHLSLHitObjectType(Ty)) + return false; + return true; +} - HLSLExternalSource *source = HLSLExternalSource::FromSema(self); - ArTypeObjectKind shapeKind = source->GetTypeObjectKind(ArgTy); - switch (shapeKind) { +// Determine if `Ty` is valid in this `DiagContext` and/or an empty type. If +// invalid returns false and Sema `S`, location `Loc`, error index +// `DiagContext`, and FieldDecl `FD` are used to emit diagnostics. If +// `CheckLongVec` is set, errors are produced if `Ty` is a long vector. If the +// type is not empty, `Empty` is set to false. `CheckedDecls` is used to prevent +// redundant recursive type checks. +static bool +DiagnoseElementTypes(Sema &S, SourceLocation Loc, QualType Ty, bool &Empty, + TypeDiagContext ObjDiagContext, + TypeDiagContext LongVecDiagContext, + llvm::SmallPtrSet &CheckedDecls, + const clang::FieldDecl *FD) { + if (Ty.isNull() || Ty->isDependentType()) + return false; + + const bool CheckLongVec = LongVecDiagContext != TypeDiagContext::Valid; + const bool CheckObjects = ObjDiagContext != TypeDiagContext::Valid; + + while (const ArrayType *Arr = Ty->getAsArrayTypeUnsafe()) + Ty = Arr->getElementType(); + + const int ObjDiagContextIdx = static_cast(ObjDiagContext); + const int LongVecDiagContextIdx = static_cast(LongVecDiagContext); + DXASSERT_NOMSG( + LongVecDiagContext == TypeDiagContext::Valid || + (0 <= LongVecDiagContextIdx && + LongVecDiagContextIdx <= + static_cast(TypeDiagContext::LongVecDiagMaxSelectIndex))); + + HLSLExternalSource *Source = HLSLExternalSource::FromSema(&S); + ArTypeObjectKind ShapeKind = Source->GetTypeObjectKind(Ty); + switch (ShapeKind) { case AR_TOBJ_VECTOR: - if (GetHLSLVecSize(ArgTy) > DXIL::kDefaultMaxVectorLength) { - const unsigned NodeRecordsIdx = 3; - self->Diag(ArgLoc.getLocation(), diag::err_hlsl_unsupported_long_vector) - << NodeRecordsIdx; + if (CheckLongVec && GetHLSLVecSize(Ty) > DXIL::kDefaultMaxVectorLength) { + S.Diag(Loc, diag::err_hlsl_unsupported_long_vector) + << LongVecDiagContextIdx; Empty = false; return false; } LLVM_FALLTHROUGH; - case AR_TOBJ_ARRAY: case AR_TOBJ_BASIC: case AR_TOBJ_MATRIX: Empty = false; return false; case AR_TOBJ_OBJECT: Empty = false; - self->Diag(ArgLoc.getLocation(), diag::err_hlsl_node_record_object) - << ArgTy << ArgLoc.getSourceRange(); + if (!CheckObjects || AllowObjectInContext(Ty, ObjDiagContext)) + return false; + S.Diag(Loc, diag::err_hlsl_unsupported_object_context) + << Ty << ObjDiagContextIdx; if (FD) - self->Diag(FD->getLocation(), diag::note_field_declared_here) + S.Diag(FD->getLocation(), diag::note_field_declared_here) << FD->getType() << FD->getSourceRange(); return true; case AR_TOBJ_DEPENDENT: @@ -12164,25 +12214,55 @@ bool hlsl::DiagnoseNodeStructArgument(Sema *self, TemplateArgumentLoc ArgLoc, return true; case AR_TOBJ_COMPOUND: { bool ErrorFound = false; - const RecordDecl *RD = ArgTy->getAs()->getDecl(); + const RecordDecl *RD = Ty->getAs()->getDecl(); + // Never recurse redundantly into related subtypes that have already been + // checked. + if (!CheckedDecls.insert(RD).second) + return false; + // Check the fields of the RecordDecl - for (auto *FD : RD->fields()) + for (auto *ElemFD : RD->fields()) { ErrorFound |= - DiagnoseNodeStructArgument(self, ArgLoc, FD->getType(), Empty, FD); - if (RD->isCompleteDefinition()) - if (auto *Child = dyn_cast(RD)) - // Walk up the inheritance chain and check base class fields - for (auto &B : Child->bases()) - ErrorFound |= - DiagnoseNodeStructArgument(self, ArgLoc, B.getType(), Empty); + DiagnoseElementTypes(S, Loc, ElemFD->getType(), Empty, ObjDiagContext, + LongVecDiagContext, CheckedDecls, ElemFD); + } + if (!RD->isCompleteDefinition()) + return ErrorFound; + + if (auto *Child = dyn_cast(RD)) + // Walk up the inheritance chain and check base class fields + for (auto &B : Child->bases()) + ErrorFound |= + DiagnoseElementTypes(S, Loc, B.getType(), Empty, ObjDiagContext, + LongVecDiagContext, CheckedDecls, nullptr); return ErrorFound; } default: - DXASSERT(false, "unreachable"); + // Not a recursive type, no element types to check here + Empty = false; return false; } } +bool hlsl::DiagnoseTypeElements(Sema &S, SourceLocation Loc, QualType Ty, + TypeDiagContext ObjDiagContext, + TypeDiagContext LongVecDiagContext, + const clang::FieldDecl *FD) { + bool Empty = false; + llvm::SmallPtrSet CheckedDecls; + return DiagnoseElementTypes(S, Loc, Ty, Empty, ObjDiagContext, + LongVecDiagContext, CheckedDecls, FD); +} + +bool hlsl::DiagnoseNodeStructArgument(Sema *self, TemplateArgumentLoc ArgLoc, + QualType ArgTy, bool &Empty, + const FieldDecl *FD) { + llvm::SmallPtrSet CheckedDecls; + return DiagnoseElementTypes(*self, ArgLoc.getLocation(), ArgTy, Empty, + TypeDiagContext::NodeRecords, + TypeDiagContext::NodeRecords, CheckedDecls, FD); +} + // This function diagnoses whether or not all entry-point attributes // should exist on this shader stage void DiagnoseEntryAttrAllowedOnStage(clang::Sema *self, @@ -12610,21 +12690,6 @@ bool hlsl::ShouldSkipNRVO(clang::Sema &sema, clang::QualType returnType, return false; } -bool hlsl::ContainsLongVector(QualType QT) { - if (QT.isNull() || QT->isDependentType()) - return false; - - while (const ArrayType *Arr = QT->getAsArrayTypeUnsafe()) - QT = Arr->getElementType(); - - if (CXXRecordDecl *Decl = QT->getAsCXXRecordDecl()) { - if (!Decl->isCompleteDefinition()) - return false; - return Decl->hasHLSLLongVector(); - } - return false; -} - bool hlsl::IsConversionToLessOrEqualElements( clang::Sema *self, const clang::ExprResult &sourceExpr, const clang::QualType &targetType, bool explicitConversion) { @@ -15295,8 +15360,8 @@ bool Sema::DiagnoseHLSLDecl(Declarator &D, DeclContext *DC, Expr *BitWidth, result = false; } - // Disallow long vecs from $Global cbuffers. - if (isGlobal && !isStatic && !isGroupShared && !IS_BASIC_OBJECT(basicKind)) { + // Disallow intangible HLSL objects in the global scope. + if (isGlobal) { // Suppress actual emitting of errors for incompletable types here // They are redundant to those produced in ActOnUninitializedDecl. struct SilentDiagnoser : public TypeDiagnoser { @@ -15304,12 +15369,22 @@ bool Sema::DiagnoseHLSLDecl(Declarator &D, DeclContext *DC, Expr *BitWidth, virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {} } SD; RequireCompleteType(D.getLocStart(), qt, SD); - if (ContainsLongVector(qt)) { - unsigned CbuffersOrTbuffersIdx = 4; - Diag(D.getLocStart(), diag::err_hlsl_unsupported_long_vector) - << CbuffersOrTbuffersIdx; + + // Disallow objects in the global context + TypeDiagContext ObjDiagContext = TypeDiagContext::CBuffersOrTBuffers; + if (isGroupShared) + ObjDiagContext = TypeDiagContext::GroupShared; + else if (isStatic) + ObjDiagContext = TypeDiagContext::GlobalVariables; + + TypeDiagContext LongVecDiagContext = TypeDiagContext::Valid; + + // Disallow long vecs from $Global cbuffers. + if (!isStatic && !isGroupShared && !IS_BASIC_OBJECT(basicKind)) + LongVecDiagContext = TypeDiagContext::CBuffersOrTBuffers; + if (DiagnoseTypeElements(*this, D.getLocStart(), qt, ObjDiagContext, + LongVecDiagContext)) result = false; - } } // SPIRV change starts @@ -16214,13 +16289,10 @@ static bool isRelatedDeclMarkedNointerpolation(Expr *E) { // Verify that user-defined intrinsic struct args contain no long vectors static bool CheckUDTIntrinsicArg(Sema *S, Expr *Arg) { - if (ContainsLongVector(Arg->getType())) { - const unsigned UserDefinedStructParameterIdx = 5; - S->Diag(Arg->getExprLoc(), diag::err_hlsl_unsupported_long_vector) - << UserDefinedStructParameterIdx; - return true; - } - return false; + const TypeDiagContext DiagContext = + TypeDiagContext::UserDefinedStructParameter; + return DiagnoseTypeElements(*S, Arg->getExprLoc(), Arg->getType(), + DiagContext, DiagContext); } static bool CheckIntrinsicGetAttributeAtVertex(Sema *S, FunctionDecl *FDecl, @@ -16957,18 +17029,15 @@ void DiagnoseEntry(Sema &S, FunctionDecl *FD) { // Would be nice to check for resources here as they crash the compiler now. // See issue #7186. for (const auto *param : FD->params()) { - if (ContainsLongVector(param->getType())) { - const unsigned EntryFunctionParametersIdx = 6; - S.Diag(param->getLocation(), diag::err_hlsl_unsupported_long_vector) - << EntryFunctionParametersIdx; - } + const TypeDiagContext DiagContext = + TypeDiagContext::EntryFunctionParameters; + hlsl::DiagnoseTypeElements(S, param->getLocation(), param->getType(), + DiagContext, DiagContext); } - if (ContainsLongVector(FD->getReturnType())) { - const unsigned EntryFunctionReturnIdx = 7; - S.Diag(FD->getLocation(), diag::err_hlsl_unsupported_long_vector) - << EntryFunctionReturnIdx; - } + const TypeDiagContext DiagContext = TypeDiagContext::EntryFunctionReturnType; + DiagnoseTypeElements(S, FD->getLocation(), FD->getReturnType(), DiagContext, + DiagContext); DXIL::ShaderKind Stage = ShaderModel::KindFromFullName(shaderAttr->getStage()); diff --git a/tools/clang/lib/Sema/SemaHLSLDiagnoseTU.cpp b/tools/clang/lib/Sema/SemaHLSLDiagnoseTU.cpp index abca7cbf86..a3ca955802 100644 --- a/tools/clang/lib/Sema/SemaHLSLDiagnoseTU.cpp +++ b/tools/clang/lib/Sema/SemaHLSLDiagnoseTU.cpp @@ -709,20 +709,18 @@ void hlsl::DiagnoseTranslationUnit(clang::Sema *self) { << hullPatchCount.value(); } } - for (const auto *param : pPatchFnDecl->params()) - if (ContainsLongVector(param->getType())) { - const unsigned PatchConstantFunctionParametersIdx = 8; - self->Diag(param->getLocation(), - diag::err_hlsl_unsupported_long_vector) - << PatchConstantFunctionParametersIdx; - } - - if (ContainsLongVector(pPatchFnDecl->getReturnType())) { - const unsigned PatchConstantFunctionReturnIdx = 9; - self->Diag(pPatchFnDecl->getLocation(), - diag::err_hlsl_unsupported_long_vector) - << PatchConstantFunctionReturnIdx; + for (const auto *param : pPatchFnDecl->params()) { + const TypeDiagContext ParamDiagContext = + TypeDiagContext::PatchConstantFunctionParameters; + DiagnoseTypeElements(*self, param->getLocation(), param->getType(), + ParamDiagContext, ParamDiagContext); } + + const TypeDiagContext ReturnDiagContext = + TypeDiagContext::PatchConstantFunctionReturnType; + DiagnoseTypeElements(*self, pPatchFnDecl->getLocation(), + pPatchFnDecl->getReturnType(), ReturnDiagContext, + ReturnDiagContext); } DXIL::ShaderKind EntrySK = shaderModel->GetKind(); DXIL::NodeLaunchType NodeLaunchTy = DXIL::NodeLaunchType::Invalid; diff --git a/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp b/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp index 1eacedbb0b..a6ae05faa5 100644 --- a/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -2139,18 +2139,6 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, SourceLocation(), SourceLocation(), nullptr); CheckCompletedCXXClass(Instantiation); - // HLSL Change Begin - set longvec bit for vectors of over 4 elements - ClassTemplateSpecializationDecl *Spec = - dyn_cast(Instantiation); - if (Spec && Spec->hasAttr()) { - const TemplateArgumentList &argList = Spec->getTemplateArgs(); - const TemplateArgument &arg1 = argList[1]; - llvm::APSInt vecSize = arg1.getAsIntegral(); - if (vecSize.getLimitedValue() > hlsl::DXIL::kDefaultMaxVectorLength) - Instantiation->setHasHLSLLongVector(); - } - // HLSL Change End - set longvec bit for vectors of over 4 elements - // Default arguments are parsed, if not instantiated. We can go instantiate // default arg exprs for default constructors if necessary now. ActOnFinishCXXMemberDefaultArgs(Instantiation); diff --git a/tools/clang/test/SemaHLSL/hlsl/objects/HitObject/hitobject-in-buffer.hlsl b/tools/clang/test/SemaHLSL/hlsl/objects/HitObject/hitobject-in-buffer.hlsl index baa3a07a5b..b091bd2ac5 100644 --- a/tools/clang/test/SemaHLSL/hlsl/objects/HitObject/hitobject-in-buffer.hlsl +++ b/tools/clang/test/SemaHLSL/hlsl/objects/HitObject/hitobject-in-buffer.hlsl @@ -1,4 +1,4 @@ // RUN: %dxc -T lib_6_9 %s -verify -// expected-error@+1{{'dx::HitObject' is an object and cannot be used as a type parameter}} +// expected-error@+1{{object 'dx::HitObject' is not allowed in structured buffers}} RWStructuredBuffer InvalidBuffer; diff --git a/tools/clang/test/SemaHLSL/hlsl/objects/HitObject/hitobject_traceinvoke_payload_udt.hlsl b/tools/clang/test/SemaHLSL/hlsl/objects/HitObject/hitobject_traceinvoke_payload_udt.hlsl index e89e33a78f..ee4ff8c020 100644 --- a/tools/clang/test/SemaHLSL/hlsl/objects/HitObject/hitobject_traceinvoke_payload_udt.hlsl +++ b/tools/clang/test/SemaHLSL/hlsl/objects/HitObject/hitobject_traceinvoke_payload_udt.hlsl @@ -4,19 +4,28 @@ struct [raypayload] Payload { - int a : read(caller, closesthit, miss) : write(caller, closesthit, miss); + int a : read(closesthit, miss) : write(anyhit); dx::HitObject hit; }; -struct Attribs +struct +[raypayload] +PayloadLV { - float2 barys; + int a : read(closesthit, miss) : write(anyhit); + vector b : read(closesthit, miss) : write(anyhit); }; [shader("raygeneration")] void RayGen() { - // expected-error@+1{{payload parameter 'payload_in_rg' must be a user-defined type composed of only numeric types}} + // expected-error@+3{{payload parameter 'payload_in_rg' must be a user-defined type composed of only numeric types}} + // expected-error@+2{{object 'dx::HitObject' is not allowed in payload parameters}} + // expected-note@8{{'dx::HitObject' field declared here}} Payload payload_in_rg; dx::HitObject::Invoke( dx::HitObject(), payload_in_rg ); + + // expected-error@+1{{vectors of over 4 elements in payload parameters are not supported}} + PayloadLV payload_with_lv; + dx::HitObject::Invoke( dx::HitObject(), payload_with_lv ); } \ No newline at end of file diff --git a/tools/clang/test/SemaHLSL/hlsl/types/invalid-hitobject-decls-hs.hlsl b/tools/clang/test/SemaHLSL/hlsl/types/invalid-hitobject-decls-hs.hlsl new file mode 100644 index 0000000000..3a4457bd5f --- /dev/null +++ b/tools/clang/test/SemaHLSL/hlsl/types/invalid-hitobject-decls-hs.hlsl @@ -0,0 +1,32 @@ +// RUN: %dxc -T hs_6_9 -verify %s + +struct HsConstantData { + float Edges[3] : SV_TessFactor; + dx::HitObject hit; +}; + +struct LongVec { + float4 f; + dx::HitObject hit; +}; + +HsConstantData +PatchConstantFunction( + // expected-error@-1{{object 'dx::HitObject' is not allowed in patch constant function return type}} + // expected-note@5{{'dx::HitObject' field declared here}} + dx::HitObject hit : V, + // expected-error@-1{{object 'dx::HitObject' is not allowed in patch constant function parameters}} + LongVec lv : L) + // expected-error@-1{{object 'dx::HitObject' is not allowed in patch constant function parameters}} + // expected-note@10{{'dx::HitObject' field declared here}} +{ + HsConstantData empty; + return empty; +} + +[domain("tri")] +[outputtopology("triangle_cw")] +[outputcontrolpoints(32)] +[patchconstantfunc("PatchConstantFunction")] +void main() { +} diff --git a/tools/clang/test/SemaHLSL/hlsl/types/invalid-hitobject-decls-struct.hlsl b/tools/clang/test/SemaHLSL/hlsl/types/invalid-hitobject-decls-struct.hlsl new file mode 100644 index 0000000000..b6b28700a9 --- /dev/null +++ b/tools/clang/test/SemaHLSL/hlsl/types/invalid-hitobject-decls-struct.hlsl @@ -0,0 +1,344 @@ +// RUN: %dxc -T lib_6_9 -DTYPE=HitStruct -verify %s +// RUN: %dxc -T lib_6_9 -DTYPE=HitStructSub -verify %s + + +#define PASTE_(x,y) x##y +#define PASTE(x,y) PASTE_(x,y) + +#ifndef TYPE +#define TYPE HitTpl +#endif + +// Add tests for base types and instantiated template classes with HitObjects + +struct HitStruct { + float4 f; + dx::HitObject hit; +}; + +struct HitStructSub : HitStruct { + int3 is; +}; + +template +struct HitTpl { + float4 f; + T val; +}; + +TYPE global_type; +// expected-error@-1{{object 'dx::HitObject' is not allowed in cbuffers or tbuffers}} +// expected-note@16{{'dx::HitObject' field declared here}} +dx::HitObject global_hit; +// expected-error@-1{{object 'dx::HitObject' is not allowed in cbuffers or tbuffers}} +dx::HitObject global_hit_arr[10]; +// expected-error@-1{{object 'dx::HitObject' is not allowed in cbuffers or tbuffers}} + +static TYPE static_gv; +// expected-error@-1{{object 'dx::HitObject' is not allowed in global variables}} +// expected-note@16{{'dx::HitObject' field declared here}} + +cbuffer BadBuffy { + dx::HitObject cb_hit; + // expected-error@-1{{object 'dx::HitObject' is not allowed in cbuffers or tbuffers}} + dx::HitObject cb_hit_arr[10]; + // expected-error@-1{{object 'dx::HitObject' is not allowed in cbuffers or tbuffers}} +}; + +tbuffer BadTuffy { + dx::HitObject tb_vec; + // expected-error@-1{{object 'dx::HitObject' is not allowed in cbuffers or tbuffers}} + dx::HitObject tb_vec_arr[10]; + // expected-error@-1{{object 'dx::HitObject' is not allowed in cbuffers or tbuffers}} + TYPE tb_vec_rec; + // expected-error@-1{{object 'dx::HitObject' is not allowed in cbuffers or tbuffers}} + // expected-note@16{{'dx::HitObject' field declared here}} + TYPE tb_vec_rec_arr[10]; + // expected-error@-1{{object 'dx::HitObject' is not allowed in cbuffers or tbuffers}} + // expected-note@16{{'dx::HitObject' field declared here}} +}; + +StructuredBuffer struct_buf; +// expected-error@-1{{object 'dx::HitObject' is not allowed in structured buffers}} +// expected-note@16{{'dx::HitObject' field declared here}} +RWStructuredBuffer rw_struct_buf; +// expected-error@-1{{object 'dx::HitObject' is not allowed in structured buffers}} +// expected-note@16{{'dx::HitObject' field declared here}} +ConstantBuffer const_buf; +// expected-error@-1{{object 'dx::HitObject' is not allowed in ConstantBuffers or TextureBuffers}} +// expected-note@16{{'dx::HitObject' field declared here}} +TextureBuffer tex_buf; +// expected-error@-1{{object 'dx::HitObject' is not allowed in ConstantBuffers or TextureBuffers}} +// expected-note@16{{'dx::HitObject' field declared here}} + +ByteAddressBuffer bab; +RWByteAddressBuffer rw_bab; + +[Shader("raygeneration")] +void main() +{ + bab.Load(0); + // expected-error@-1{{object 'dx::HitObject' is not allowed in builtin template parameters}} + // expected-note@16{{'dx::HitObject' field declared here}} + // expected-error@-3{{Explicit template arguments on intrinsic Load must be a single numeric type}} + rw_bab.Load(0); + // expected-error@-1{{object 'dx::HitObject' is not allowed in builtin template parameters}} + // expected-note@16{{'dx::HitObject' field declared here}} + // expected-error@-3{{Explicit template arguments on intrinsic Load must be a single numeric type}} + TYPE val; + rw_bab.Store(0, val); + // expected-error@-1{{object 'dx::HitObject' is not allowed in builtin template parameters}} + // expected-note@16{{'dx::HitObject' field declared here}} + // expected-error@-3{{Explicit template arguments on intrinsic Store must be a single numeric type}} +} + +[shader("pixel")] +TYPE ps_main( +// expected-error@-1{{object 'dx::HitObject' is not allowed in entry function return type}} +// expected-note@16{{'dx::HitObject' field declared here}} + TYPE vec : V) : SV_Target { + // expected-error@-1{{object 'dx::HitObject' is not allowed in entry function parameters}} + // expected-note@16{{'dx::HitObject' field declared here}} + return vec; +} + +[shader("vertex")] +TYPE vs_main( +// expected-error@-1{{object 'dx::HitObject' is not allowed in entry function return type}} +// expected-note@16{{'dx::HitObject' field declared here}} + TYPE parm : P) : SV_Target { + // expected-error@-1{{object 'dx::HitObject' is not allowed in entry function parameters}} + // expected-note@16{{'dx::HitObject' field declared here}} + parm.f = 0; + return parm; +} + + +[shader("geometry")] +[maxvertexcount(3)] +void gs_point( + line TYPE e, + // expected-error@-1{{object 'dx::HitObject' is not allowed in entry function parameters}} + // expected-note@16{{'dx::HitObject' field declared here}} + inout PointStream OutputStream0) + // expected-error@-1{{object 'dx::HitObject' is not allowed in geometry streams}} + // expected-note@16{{'dx::HitObject' field declared here}} +{} + +[shader("geometry")] +[maxvertexcount(12)] +void gs_line( + line TYPE a, + // expected-error@-1{{object 'dx::HitObject' is not allowed in entry function parameters}} + // expected-note@16{{'dx::HitObject' field declared here}} + inout LineStream OutputStream0) + // expected-error@-1{{object 'dx::HitObject' is not allowed in geometry streams}} + // expected-note@16{{'dx::HitObject' field declared here}} +{} + + +[shader("geometry")] +[maxvertexcount(12)] +void gs_tri( + triangle TYPE a, + // expected-error@-1{{object 'dx::HitObject' is not allowed in entry function parameters}} + // expected-note@16{{'dx::HitObject' field declared here}} + inout TriangleStream OutputStream0) + // expected-error@-1{{object 'dx::HitObject' is not allowed in geometry streams}} + // expected-note@16{{'dx::HitObject' field declared here}} +{} + +[shader("domain")] +[domain("tri")] +void ds_main( + OutputPatch TrianglePatch) + // expected-error@-1{{object 'dx::HitObject' is not allowed in tessellation patches}} + // expected-note@16{{'dx::HitObject' field declared here}} +{} + +void patch_const( + InputPatch inpatch, + // expected-error@-1{{object 'dx::HitObject' is not allowed in tessellation patches}} + // expected-note@16{{'dx::HitObject' field declared here}} + OutputPatch outpatch) + // expected-error@-1{{object 'dx::HitObject' is not allowed in tessellation patches}} + // expected-note@16{{'dx::HitObject' field declared here}} +{} + +[shader("hull")] +[domain("tri")] +[outputtopology("triangle_cw")] +[outputcontrolpoints(32)] +[patchconstantfunc("patch_const")] +void hs_main(InputPatch TrianglePatch) {} +// expected-error@-1{{object 'dx::HitObject' is not allowed in tessellation patches}} +// expected-note@16{{'dx::HitObject' field declared here}} + +RaytracingAccelerationStructure RTAS; + +struct [raypayload] DXRHitStruct { + float4 f : write(closesthit) : read(caller); + TYPE hit : write(closesthit) : read(caller); +}; + +struct [raypayload] DXRHitStructSub : DXRHitStruct { + int3 is : write(closesthit) : read(caller); +}; + +template +struct [raypayload] DXRHitTpl { + float4 f : write(closesthit) : read(caller); + T hit : write(closesthit) : read(caller); +}; + +#define RTTYPE PASTE(DXR,TYPE) + + +TYPE userFunc(TYPE arg) { + return arg; +} + +[shader("raygeneration")] +void raygen() { + RTTYPE p = (RTTYPE)0; + RayDesc ray = (RayDesc)0; + TraceRay(RTAS, RAY_FLAG_NONE, 0, 0, 1, 0, ray, p); + // expected-error@-1{{object 'dx::HitObject' is not allowed in user-defined struct parameter}} + // expected-note@16{{'dx::HitObject' field declared here}} + CallShader(0, p); + // expected-error@-1{{object 'dx::HitObject' is not allowed in user-defined struct parameter}} + // expected-note@16{{'dx::HitObject' field declared here}} + TYPE val; + TYPE res = userFunc(val); +} + +[shader("closesthit")] +void closesthit( + inout RTTYPE payload, + // expected-error@-1{{payload parameter 'payload' must be a user-defined type composed of only numeric types}} + // expected-error@-2{{object 'dx::HitObject' is not allowed in entry function parameters}} + // expected-note@16{{'dx::HitObject' field declared here}} + in RTTYPE attribs) { + // expected-error@-1{{attributes parameter 'attribs' must be a user-defined type composed of only numeric types}} + // expected-error@-2{{object 'dx::HitObject' is not allowed in entry function parameters}} + // expected-note@16{{'dx::HitObject' field declared here}} + RayDesc ray; + TraceRay( RTAS, RAY_FLAG_NONE, 0xff, 0, 1, 0, ray, payload ); + // expected-error@-1{{object 'dx::HitObject' is not allowed in user-defined struct parameter}} + // expected-note@16{{'dx::HitObject' field declared here}} + CallShader(0, payload); + // expected-error@-1{{object 'dx::HitObject' is not allowed in user-defined struct parameter}} + // expected-note@16{{'dx::HitObject' field declared here}} +} + +[shader("anyhit")] +void AnyHit( + inout RTTYPE payload, + // expected-error@-1{{payload parameter 'payload' must be a user-defined type composed of only numeric types}} + // expected-error@-2{{object 'dx::HitObject' is not allowed in entry function parameters}} + // expected-note@16{{'dx::HitObject' field declared here}} + in RTTYPE attribs) + // expected-error@-1{{attributes parameter 'attribs' must be a user-defined type composed of only numeric types}} + // expected-error@-2{{object 'dx::HitObject' is not allowed in entry function parameters}} + // expected-note@16{{'dx::HitObject' field declared here}} +{ +} + +[shader("miss")] +void Miss( + inout RTTYPE payload){ + // expected-error@-1{{payload parameter 'payload' must be a user-defined type composed of only numeric types}} + // expected-error@-2{{object 'dx::HitObject' is not allowed in entry function parameters}} + // expected-note@16{{'dx::HitObject' field declared here}} + RayDesc ray; + TraceRay( RTAS, RAY_FLAG_NONE, 0xff, 0, 1, 0, ray, payload ); + // expected-error@-1{{object 'dx::HitObject' is not allowed in user-defined struct parameter}} + // expected-note@16{{'dx::HitObject' field declared here}} + CallShader(0, payload); + // expected-error@-1{{object 'dx::HitObject' is not allowed in user-defined struct parameter}} + // expected-note@16{{'dx::HitObject' field declared here}} +} + +[shader("intersection")] +void Intersection() { + float hitT = RayTCurrent(); + RTTYPE attr = (RTTYPE)0; + bool bReported = ReportHit(hitT, 0, attr); + // expected-error@-1{{object 'dx::HitObject' is not allowed in user-defined struct parameter}} + // expected-note@16{{'dx::HitObject' field declared here}} +} + +[shader("callable")] +void callable1( + inout RTTYPE p) { + // expected-error@-1{{object 'dx::HitObject' is not allowed in entry function parameters}} + // expected-note@16{{'dx::HitObject' field declared here}} + // expected-error@-3{{callable parameter 'p' must be a user-defined type composed of only numeric types}} + CallShader(0, p); + // expected-error@-1{{object 'dx::HitObject' is not allowed in user-defined struct parameter}} + // expected-note@16{{'dx::HitObject' field declared here}} +} + +static groupshared TYPE gs_var; +// expected-error@-1{{object 'dx::HitObject' is not allowed in groupshared variables}} +// expected-note@16{{'dx::HitObject' field declared here}} + +[shader("amplification")] +[numthreads(1,1,1)] +void Amp() { + TYPE as_pld; + DispatchMesh(1,1,1,as_pld); + // expected-error@-1{{object 'dx::HitObject' is not allowed in user-defined struct parameter}} + // expected-note@16{{'dx::HitObject' field declared here}} +} + +struct NodeHitStruct { + uint3 grid : SV_DispatchGrid; + TYPE hit; +}; + +struct NodeHitStructSub : NodeHitStruct { + int3 is; +}; + +template +struct NodeHitTpl { + uint3 grid : SV_DispatchGrid; + T hit; +}; + +#define NTYPE PASTE(Node,TYPE) + +[Shader("node")] +[NodeLaunch("broadcasting")] +[NumThreads(8,1,1)] +[NodeMaxDispatchGrid(8, 1, 1)] +void broadcast( +// expected-error@-1{{Broadcasting node shader 'broadcast' with NodeMaxDispatchGrid attribute must declare an input record containing a field with SV_DispatchGrid semantic}} + DispatchNodeInputRecord input, + // expected-error@-1{{object 'dx::HitObject' is not allowed in node records}} + // expected-note@16{{'dx::HitObject' field declared here}} + NodeOutput output) + // expected-error@-1{{object 'dx::HitObject' is not allowed in node records}} + // expected-note@16{{'dx::HitObject' field declared here}} +{ + ThreadNodeOutputRecords touts; + // expected-error@-1{{object 'dx::HitObject' is not allowed in node records}} + // expected-note@16{{'dx::HitObject' field declared here}} + GroupNodeOutputRecords gouts; + // expected-error@-1{{object 'dx::HitObject' is not allowed in node records}} + // expected-note@16{{'dx::HitObject' field declared here}} +} + +[Shader("node")] +[NodeLaunch("coalescing")] +[NumThreads(8,1,1)] +void coalesce(GroupNodeInputRecords input) {} +// expected-error@-1{{object 'dx::HitObject' is not allowed in node records}} +// expected-note@16{{'dx::HitObject' field declared here}} + +[Shader("node")] +[NodeLaunch("thread")] +void threader(ThreadNodeInputRecord input) {} +// expected-error@-1{{object 'dx::HitObject' is not allowed in node records}} +// expected-note@16{{'dx::HitObject' field declared here}} diff --git a/tools/clang/test/SemaHLSL/hlsl/types/invalid-hitobject-decls-templated.hlsl b/tools/clang/test/SemaHLSL/hlsl/types/invalid-hitobject-decls-templated.hlsl new file mode 100644 index 0000000000..4ffd53878d --- /dev/null +++ b/tools/clang/test/SemaHLSL/hlsl/types/invalid-hitobject-decls-templated.hlsl @@ -0,0 +1,340 @@ +// RUN: %dxc -T lib_6_9 -verify %s + + +#define PASTE_(x,y) x##y +#define PASTE(x,y) PASTE_(x,y) + +#define TYPE HitTpl + +// Add tests for base types and instantiated template classes with HitObjects + +struct HitStruct { + float4 f; + dx::HitObject hit; +}; + +struct HitStructSub : HitStruct { + int3 is; +}; + +template +struct HitTpl { + float4 f; + T val; +}; + +RaytracingAccelerationStructure RTAS; + +struct [raypayload] DXRHitStruct { + float4 f : write(closesthit) : read(caller); + TYPE hit : write(closesthit) : read(caller); +}; + +struct [raypayload] DXRHitStructSub : DXRHitStruct { + int3 is : write(closesthit) : read(caller); +}; + +template +struct [raypayload] DXRHitTpl { + float4 f : write(closesthit) : read(caller); + T hit : write(closesthit) : read(caller); +}; + +struct NodeHitStruct { + uint3 grid : SV_DispatchGrid; + TYPE hit; +}; + +struct NodeHitStructSub : NodeHitStruct { + int3 is; +}; + +template +struct NodeHitTpl { + uint3 grid : SV_DispatchGrid; + T hit; +}; + +TYPE global_type; +// expected-error@-1{{object 'dx::HitObject' is not allowed in cbuffers or tbuffers}} +// expected-note@23{{'dx::HitObject' field declared here}} +dx::HitObject global_hit; +// expected-error@-1{{object 'dx::HitObject' is not allowed in cbuffers or tbuffers}} +dx::HitObject global_hit_arr[10]; +// expected-error@-1{{object 'dx::HitObject' is not allowed in cbuffers or tbuffers}} + +static TYPE static_gv; +// expected-error@-1{{object 'dx::HitObject' is not allowed in global variables}} +// expected-note@23{{'dx::HitObject' field declared here}} + +cbuffer BadBuffy { + dx::HitObject cb_hit; + // expected-error@-1{{object 'dx::HitObject' is not allowed in cbuffers or tbuffers}} + dx::HitObject cb_hit_arr[10]; + // expected-error@-1{{object 'dx::HitObject' is not allowed in cbuffers or tbuffers}} +}; + +tbuffer BadTuffy { + dx::HitObject tb_vec; + // expected-error@-1{{object 'dx::HitObject' is not allowed in cbuffers or tbuffers}} + dx::HitObject tb_vec_arr[10]; + // expected-error@-1{{object 'dx::HitObject' is not allowed in cbuffers or tbuffers}} + TYPE tb_vec_rec; + // expected-error@-1{{object 'dx::HitObject' is not allowed in cbuffers or tbuffers}} + // expected-note@23{{'dx::HitObject' field declared here}} + TYPE tb_vec_rec_arr[10]; + // expected-error@-1{{object 'dx::HitObject' is not allowed in cbuffers or tbuffers}} + // expected-note@23{{'dx::HitObject' field declared here}} +}; + +StructuredBuffer struct_buf; +// expected-error@-1{{object 'dx::HitObject' is not allowed in structured buffers}} +// expected-note@23{{'dx::HitObject' field declared here}} +RWStructuredBuffer rw_struct_buf; +// expected-error@-1{{object 'dx::HitObject' is not allowed in structured buffers}} +// expected-note@23{{'dx::HitObject' field declared here}} +ConstantBuffer const_buf; +// expected-error@-1{{object 'dx::HitObject' is not allowed in ConstantBuffers or TextureBuffers}} +// expected-note@23{{'dx::HitObject' field declared here}} +TextureBuffer tex_buf; +// expected-error@-1{{object 'dx::HitObject' is not allowed in ConstantBuffers or TextureBuffers}} +// expected-note@23{{'dx::HitObject' field declared here}} + +ByteAddressBuffer bab; +RWByteAddressBuffer rw_bab; + +[Shader("raygeneration")] +void main() +{ + bab.Load(0); + // expected-error@-1{{object 'dx::HitObject' is not allowed in builtin template parameters}} + // expected-note@23{{'dx::HitObject' field declared here}} + // expected-error@-3{{Explicit template arguments on intrinsic Load must be a single numeric type}} + rw_bab.Load(0); + // expected-error@-1{{object 'dx::HitObject' is not allowed in builtin template parameters}} + // expected-note@23{{'dx::HitObject' field declared here}} + // expected-error@-3{{Explicit template arguments on intrinsic Load must be a single numeric type}} + TYPE val; + rw_bab.Store(0, val); + // expected-error@-1{{object 'dx::HitObject' is not allowed in builtin template parameters}} + // expected-note@23{{'dx::HitObject' field declared here}} + // expected-error@-3{{Explicit template arguments on intrinsic Store must be a single numeric type}} +} + +[shader("pixel")] +TYPE ps_main( +// expected-error@-1{{object 'dx::HitObject' is not allowed in entry function return type}} +// expected-note@23{{'dx::HitObject' field declared here}} + TYPE vec : V) : SV_Target { + // expected-error@-1{{object 'dx::HitObject' is not allowed in entry function parameters}} + // expected-note@23{{'dx::HitObject' field declared here}} + return vec; +} + +[shader("vertex")] +TYPE vs_main( +// expected-error@-1{{object 'dx::HitObject' is not allowed in entry function return type}} +// expected-note@23{{'dx::HitObject' field declared here}} + TYPE parm : P) : SV_Target { + // expected-error@-1{{object 'dx::HitObject' is not allowed in entry function parameters}} + // expected-note@23{{'dx::HitObject' field declared here}} + parm.f = 0; + return parm; +} + + +[shader("geometry")] +[maxvertexcount(3)] +void gs_point( + line TYPE e, + // expected-error@-1{{object 'dx::HitObject' is not allowed in entry function parameters}} + // expected-note@23{{'dx::HitObject' field declared here}} + inout PointStream OutputStream0) + // expected-error@-1{{object 'dx::HitObject' is not allowed in geometry streams}} + // expected-note@23{{'dx::HitObject' field declared here}} +{} + +[shader("geometry")] +[maxvertexcount(12)] +void gs_line( + line TYPE a, + // expected-error@-1{{object 'dx::HitObject' is not allowed in entry function parameters}} + // expected-note@23{{'dx::HitObject' field declared here}} + inout LineStream OutputStream0) + // expected-error@-1{{object 'dx::HitObject' is not allowed in geometry streams}} + // expected-note@23{{'dx::HitObject' field declared here}} +{} + + +[shader("geometry")] +[maxvertexcount(12)] +void gs_line( + line TYPE a, + // expected-error@-1{{object 'dx::HitObject' is not allowed in entry function parameters}} + // expected-note@23{{'dx::HitObject' field declared here}} + inout TriangleStream OutputStream0) + // expected-error@-1{{object 'dx::HitObject' is not allowed in geometry streams}} + // expected-note@23{{'dx::HitObject' field declared here}} +{} + +[shader("domain")] +[domain("tri")] +void ds_main( + OutputPatch TrianglePatch) + // expected-error@-1{{object 'dx::HitObject' is not allowed in tessellation patches}} + // expected-note@23{{'dx::HitObject' field declared here}} +{} + +void patch_const( + InputPatch inpatch, + // expected-error@-1{{object 'dx::HitObject' is not allowed in tessellation patches}} + // expected-note@23{{'dx::HitObject' field declared here}} + OutputPatch outpatch) + // expected-error@-1{{object 'dx::HitObject' is not allowed in tessellation patches}} + // expected-note@23{{'dx::HitObject' field declared here}} +{} + +[shader("hull")] +[domain("tri")] +[outputtopology("triangle_cw")] +[outputcontrolpoints(32)] +[patchconstantfunc("patch_const")] +void hs_main(InputPatch TrianglePatch) {} +// expected-error@-1{{object 'dx::HitObject' is not allowed in tessellation patches}} +// expected-note@23{{'dx::HitObject' field declared here}} + +#define RTTYPE PASTE(DXR,TYPE) + +TYPE userFunc(TYPE arg) { + return arg; +} + +[shader("raygeneration")] +void raygen() { + RTTYPE p = (RTTYPE)0; + RayDesc ray = (RayDesc)0; + TraceRay(RTAS, RAY_FLAG_NONE, 0, 0, 1, 0, ray, p); + // expected-error@-1{{object 'dx::HitObject' is not allowed in user-defined struct parameter}} + // expected-note@40{{'dx::HitObject' field declared here}} + CallShader(0, p); + // expected-error@-1{{object 'dx::HitObject' is not allowed in user-defined struct parameter}} + // expected-note@40{{'dx::HitObject' field declared here}} + TYPE val; + TYPE res = userFunc(val); +} + +[shader("closesthit")] +void closesthit( + inout RTTYPE payload, + // expected-error@-1{{payload parameter 'payload' must be a user-defined type composed of only numeric types}} + // expected-error@-2{{object 'dx::HitObject' is not allowed in entry function parameters}} + // expected-note@40{{'dx::HitObject' field declared here}} + in RTTYPE attribs) { + // expected-error@-1{{attributes parameter 'attribs' must be a user-defined type composed of only numeric types}} + // expected-error@-2{{object 'dx::HitObject' is not allowed in entry function parameters}} + // expected-note@40{{'dx::HitObject' field declared here}} + RayDesc ray; + TraceRay( RTAS, RAY_FLAG_NONE, 0xff, 0, 1, 0, ray, payload ); + // expected-error@-1{{object 'dx::HitObject' is not allowed in user-defined struct parameter}} + // expected-note@40{{'dx::HitObject' field declared here}} + CallShader(0, payload); + // expected-error@-1{{object 'dx::HitObject' is not allowed in user-defined struct parameter}} + // expected-note@40{{'dx::HitObject' field declared here}} +} + +[shader("anyhit")] +void AnyHit( + inout RTTYPE payload, + // expected-error@-1{{payload parameter 'payload' must be a user-defined type composed of only numeric types}} + // expected-error@-2{{object 'dx::HitObject' is not allowed in entry function parameters}} + // expected-note@40{{'dx::HitObject' field declared here}} + in RTTYPE attribs) + // expected-error@-1{{attributes parameter 'attribs' must be a user-defined type composed of only numeric types}} + // expected-error@-2{{object 'dx::HitObject' is not allowed in entry function parameters}} + // expected-note@40{{'dx::HitObject' field declared here}} +{ +} + +[shader("miss")] +void Miss( + inout RTTYPE payload){ + // expected-error@-1{{payload parameter 'payload' must be a user-defined type composed of only numeric types}} + // expected-error@-2{{object 'dx::HitObject' is not allowed in entry function parameters}} + // expected-note@40{{'dx::HitObject' field declared here}} + RayDesc ray; + TraceRay( RTAS, RAY_FLAG_NONE, 0xff, 0, 1, 0, ray, payload ); + // expected-error@-1{{object 'dx::HitObject' is not allowed in user-defined struct parameter}} + // expected-note@40{{'dx::HitObject' field declared here}} + CallShader(0, payload); + // expected-error@-1{{object 'dx::HitObject' is not allowed in user-defined struct parameter}} + // expected-note@40{{'dx::HitObject' field declared here}} +} + +[shader("intersection")] +void Intersection() { + float hitT = RayTCurrent(); + RTTYPE attr = (RTTYPE)0; + bool bReported = ReportHit(hitT, 0, attr); + // expected-error@-1{{object 'dx::HitObject' is not allowed in user-defined struct parameter}} + // expected-note@40{{'dx::HitObject' field declared here}} +} + +[shader("callable")] +void callable1( + inout RTTYPE p) { + // expected-error@-1{{object 'dx::HitObject' is not allowed in entry function parameters}} + // expected-note@40{{'dx::HitObject' field declared here}} + // expected-error@-3{{callable parameter 'p' must be a user-defined type composed of only numeric types}} + CallShader(0, p); + // expected-error@-1{{object 'dx::HitObject' is not allowed in user-defined struct parameter}} + // expected-note@40{{'dx::HitObject' field declared here}} +} + +static groupshared TYPE gs_var; +// expected-error@-1{{object 'dx::HitObject' is not allowed in groupshared variables}} +// expected-note@23{{'dx::HitObject' field declared here}} + +[shader("amplification")] +[numthreads(1,1,1)] +void Amp() { + TYPE as_pld; + DispatchMesh(1,1,1,as_pld); + // expected-error@-1{{object 'dx::HitObject' is not allowed in user-defined struct parameter}} + // expected-note@23{{'dx::HitObject' field declared here}} +} + +#define NTYPE PASTE(Node,TYPE) + +[Shader("node")] +[NodeLaunch("broadcasting")] +[NumThreads(8,1,1)] +[NodeMaxDispatchGrid(8, 1, 1)] +void broadcast( +// expected-error@-1{{Broadcasting node shader 'broadcast' with NodeMaxDispatchGrid attribute must declare an input record containing a field with SV_DispatchGrid semantic}} + DispatchNodeInputRecord input, + // expected-error@-1{{object 'dx::HitObject' is not allowed in node records}} + // expected-note@55{{'dx::HitObject' field declared here}} + NodeOutput output) + // expected-error@-1{{object 'dx::HitObject' is not allowed in node records}} + // expected-note@23{{'dx::HitObject' field declared here}} +{ + ThreadNodeOutputRecords touts; + // expected-error@-1{{object 'dx::HitObject' is not allowed in node records}} + // expected-note@23{{'dx::HitObject' field declared here}} + GroupNodeOutputRecords gouts; + // expected-error@-1{{object 'dx::HitObject' is not allowed in node records}} + // expected-note@23{{'dx::HitObject' field declared here}} +} + +[Shader("node")] +[NodeLaunch("coalescing")] +[NumThreads(8,1,1)] +void coalesce(GroupNodeInputRecords input) {} +// expected-error@-1{{object 'dx::HitObject' is not allowed in node records}} +// expected-note@23{{'dx::HitObject' field declared here}} + +[Shader("node")] +[NodeLaunch("thread")] +void threader(ThreadNodeInputRecord input) {} +// expected-error@-1{{object 'dx::HitObject' is not allowed in node records}} +// expected-note@23{{'dx::HitObject' field declared here}} diff --git a/tools/clang/test/SemaHLSL/hlsl/workgraph/invalid_node_record_type.hlsl b/tools/clang/test/SemaHLSL/hlsl/workgraph/invalid_node_record_type.hlsl index 40b820a1b4..de523d51d1 100644 --- a/tools/clang/test/SemaHLSL/hlsl/workgraph/invalid_node_record_type.hlsl +++ b/tools/clang/test/SemaHLSL/hlsl/workgraph/invalid_node_record_type.hlsl @@ -76,7 +76,7 @@ void node07(RWThreadNodeInputRecord input) // expected-error {{'f2x2' (aka [Shader("node")] [NodeLaunch("thread")] -void node08(ThreadNodeInputRecord input) // expected-error {{object 'SamplerState' may not appear in a node record}} +void node08(ThreadNodeInputRecord input) // expected-error {{object 'SamplerState' is not allowed in node records}} { } [Shader("node")] @@ -86,17 +86,17 @@ void node09(ThreadNodeInputRecord input) // expected-error {{'BAD [Shader("node")] [NodeLaunch("thread")] -void node10(RWThreadNodeInputRecord input) // expected-error {{object 'SamplerState' may not appear in a node record}} +void node10(RWThreadNodeInputRecord input) // expected-error {{object 'SamplerState' is not allowed in node records}} { } [Shader("node")] [NodeLaunch("thread")] -void node11(NodeOutput input) // expected-error {{object 'SamplerState' may not appear in a node record}} +void node11(NodeOutput input) // expected-error {{object 'SamplerState' is not allowed in node records}} { } [Shader("node")] [NodeLaunch("thread")] -void node12(NodeOutputArray output) // expected-error {{object 'SamplerState' may not appear in a node record}} +void node12(NodeOutputArray output) // expected-error {{object 'SamplerState' is not allowed in node records}} { } [Shader("node")] @@ -129,7 +129,7 @@ void node16() ThreadNodeOutputRecords outrec2; // expected-error {{'f2x2' (aka 'matrix') is not valid as a node record type - struct/class required}} - GroupNodeOutputRecords outrec3; // expected-error {{object 'SamplerState' may not appear in a node record}} + GroupNodeOutputRecords outrec3; // expected-error {{object 'SamplerState' is not allowed in node records}} ThreadNodeOutputRecords outrec4; // expected-error {{'SamplerState' is not valid as a node record type - struct/class required}} } @@ -151,10 +151,10 @@ void node17(ThreadNodeInputRecord > input) [Shader("node")] [NodeLaunch("thread")] -void node18(ThreadNodeInputRecord > input) // expected-error {{object 'SamplerState' may not appear in a node record}} +void node18(ThreadNodeInputRecord > input) // expected-error {{object 'SamplerState' is not allowed in node records}} { } [Shader("node")] [NodeLaunch("thread")] -void node19(RWThreadNodeInputRecord input) // expected-error {{object 'SamplerState' may not appear in a node record}} +void node19(RWThreadNodeInputRecord input) // expected-error {{object 'SamplerState' is not allowed in node records}} { } diff --git a/tools/clang/test/SemaHLSL/template-checks.hlsl b/tools/clang/test/SemaHLSL/template-checks.hlsl index d0d736fc1f..751e89b652 100644 --- a/tools/clang/test/SemaHLSL/template-checks.hlsl +++ b/tools/clang/test/SemaHLSL/template-checks.hlsl @@ -1,8 +1,8 @@ // RUN: %dxc -Tlib_6_3 -verify %s Texture2D t_float4; -Texture2D t_obj_sampler; /* expected-error {{'SamplerState' is an object and cannot be used as a type parameter}} fxc-error {{X3124: object element type cannot be an object type}} */ -Texture2D > t_obj_tex; /* expected-error {{'Texture2D' is an object and cannot be used as a type parameter}} fxc-error {{X3124: object element type cannot be an object type}} */ +Texture2D t_obj_sampler; /* expected-error {{object 'SamplerState' is not allowed in builtin template parameters}} fxc-error {{X3124: object element type cannot be an object type}} */ +Texture2D > t_obj_tex; /* expected-error {{object 'Texture2D' is not allowed in builtin template parameters}} fxc-error {{X3124: object element type cannot be an object type}} */ matrix m_obj_sampler; /* expected-error {{'SamplerState' cannot be used as a type parameter where a scalar is required}} fxc-error {{X3123: matrix element type must be a scalar type}} */ matrix m_bool; @@ -15,7 +15,7 @@ matrix m_bool; RWBuffer rwb_struct; /* expected-error {{elements of typed buffers and textures must fit in four 32-bit quantities}} fxc-error {{X3037: elements of typed buffers and textures must fit in four 32-bit quantities}} */ -RWBuffer rwb_struct_objs; /* expected-error {{'SamplerState' is an object and cannot be used as a type parameter}} */ +RWBuffer rwb_struct_objs; /* expected-error {{object 'SamplerState' is not allowed in builtin template parameters}} */ void vain() { // Nothing to do here. diff --git a/tools/clang/test/SemaHLSL/template-udt-load.hlsl b/tools/clang/test/SemaHLSL/template-udt-load.hlsl index 591f27b384..f666297bb9 100644 --- a/tools/clang/test/SemaHLSL/template-udt-load.hlsl +++ b/tools/clang/test/SemaHLSL/template-udt-load.hlsl @@ -8,6 +8,8 @@ RWBuffer Out; [numthreads(1,1,1)] void main() { - RWBuffer FB = In.Load >(0); // expected-error {{Explicit template arguments on intrinsic Load must be a single numeric type}} + RWBuffer FB = In.Load >(0); + // expected-error@-1{{Explicit template arguments on intrinsic Load must be a single numeric type}} + // expected-error@-2{{object 'RWBuffer' is not allowed in builtin template parameters}} Out[0] = FB[0]; }