-
Notifications
You must be signed in to change notification settings - Fork 854
[SER] Diagnose HitObject in unsupported declaration contexts #7376
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
7a4f217
18e7c1c
57ff5a3
2c128ef
e39fe2f
92bb7fc
6bb2dbf
e0e063a
c039f8c
2a7b39c
21447bc
2be84a2
85746fb
36d678c
96c6b8c
c07e548
004dc1d
244c59c
fa895f7
9db0556
e7f8c5a
fea88fb
701c680
001eb50
ae98e48
2fd825f
43449f4
1b8af76
36e9615
4b34518
58b7642
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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<unsigned>(TypeDiagContext::TypeParameter); | ||
| return false; | ||
| case AR_TOBJ_COMPOUND: { | ||
| const RecordDecl *recordDecl = recordType->getDecl(); | ||
|
|
@@ -5539,8 +5541,24 @@ class HLSLExternalSource : public ExternalSemaSource { | |
| << ConstantBuffersOrTextureBuffersIdx; | ||
|
simoll marked this conversation as resolved.
Outdated
|
||
| return true; | ||
| } | ||
| if (DiagnoseTypeElements( | ||
| *m_sema, argSrcLoc, argType, | ||
| TypeDiagContext::ConstantBuffersOrTextureBuffers)) | ||
| 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)) | ||
| return true; | ||
| } | ||
| } | ||
|
|
||
| } else if (Template->getTemplatedDecl()->hasAttr<HLSLNodeObjectAttr>()) { | ||
|
|
||
|
|
@@ -5648,6 +5666,9 @@ class HLSLExternalSource : public ExternalSemaSource { | |
| << TessellationPatchesIDx; | ||
|
simoll marked this conversation as resolved.
Outdated
|
||
| return true; | ||
| } | ||
| if (DiagnoseTypeElements(*m_sema, argLoc.getLocation(), arg.getAsType(), | ||
| TypeDiagContext::TessellationPatches)) | ||
| return true; | ||
| } else if (Template->getTemplatedDecl()->hasAttr<HLSLStreamOutputAttr>()) { | ||
| DXASSERT(TemplateArgList.size() > 0, | ||
| "Geometry streams should have at least one template args"); | ||
|
|
@@ -5660,13 +5681,16 @@ class HLSLExternalSource : public ExternalSemaSource { | |
| CXXRecordDecl *Decl = arg.getAsType()->getAsCXXRecordDecl(); | ||
| if (Decl && !Decl->isCompleteDefinition()) | ||
| return true; | ||
| const unsigned GeometryStreamsIdx = 2; | ||
|
simoll marked this conversation as resolved.
Outdated
|
||
| if (ContainsLongVector(arg.getAsType())) { | ||
| const unsigned GeometryStreamsIdx = 2; | ||
| m_sema->Diag(argLoc.getLocation(), | ||
| diag::err_hlsl_unsupported_long_vector) | ||
| << GeometryStreamsIdx; | ||
|
simoll marked this conversation as resolved.
Outdated
|
||
| return true; | ||
| } | ||
| if (DiagnoseTypeElements(*m_sema, argLoc.getLocation(), arg.getAsType(), | ||
| TypeDiagContext::GeometryStreams)) | ||
| return true; | ||
| } | ||
|
|
||
| bool isMatrix = Template->getCanonicalDecl() == | ||
|
|
@@ -10942,6 +10966,9 @@ HLSLExternalSource::DeduceTemplateArgumentsForHLSL( | |
| << intrinsicName; | ||
| return Sema::TemplateDeductionResult::TDK_Invalid; | ||
| } | ||
| if (DiagnoseTypeElements(*getSema(), Loc, functionTemplateTypeArg, | ||
| TypeDiagContext::TypeParameter)) | ||
| return Sema::TemplateDeductionResult::TDK_Invalid; | ||
|
tex3d marked this conversation as resolved.
Outdated
|
||
| } | ||
| if (IsHitObjectGetAttributes && | ||
| !DiagnoseIntersectionAttributes(*getSema(), Loc, | ||
|
|
@@ -12128,34 +12155,59 @@ 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) { | ||
| static bool | ||
|
simoll marked this conversation as resolved.
|
||
| DiagnoseElementTypes(Sema &S, SourceLocation Loc, QualType Ty, bool &Empty, | ||
| bool CheckLongVec, TypeDiagContext DiagContext, | ||
| llvm::SmallPtrSet<const RecordDecl *, 8> &CheckedDecls, | ||
| const clang::FieldDecl *FD) { | ||
| if (Ty.isNull() || Ty->isDependentType()) | ||
| return false; | ||
|
|
||
| while (const ArrayType *Arr = Ty->getAsArrayTypeUnsafe()) | ||
| Ty = Arr->getElementType(); | ||
|
|
||
| const unsigned DiagContextIdx = static_cast<unsigned>(DiagContext); | ||
|
|
||
| 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; | ||
| // TODO: This is only here because DiagnoseNodeStructArgument got folded | ||
| // into this function. Could fold all context-dependent long vector checks | ||
| // into this function. | ||
|
simoll marked this conversation as resolved.
Outdated
|
||
| if (CheckLongVec && GetHLSLVecSize(Ty) > DXIL::kDefaultMaxVectorLength) { | ||
| S.Diag(Loc, diag::err_hlsl_unsupported_long_vector) << DiagContextIdx; | ||
|
simoll marked this conversation as resolved.
Outdated
|
||
| Empty = false; | ||
| return false; | ||
| } | ||
| LLVM_FALLTHROUGH; | ||
| case AR_TOBJ_ARRAY: | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why was array removed? The only difference I see is that empty is no longer assigned to false, which doesn't seem right and we don't have an unreachable indicator if we get something really unexpected.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We peel off arrays just before the switch and don't expect to see them here
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We only need to cover recursive types in the switch and the element types we are checking for. I've added a comment for this in the default case (and this sets |
||
| 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 (AllowObjectInContext(Ty, DiagContext)) | ||
| return false; | ||
| S.Diag(Loc, diag::err_hlsl_unsupported_object_context) | ||
| << Ty << DiagContextIdx; | ||
| 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 +12216,51 @@ bool hlsl::DiagnoseNodeStructArgument(Sema *self, TemplateArgumentLoc ArgLoc, | |
| return true; | ||
| case AR_TOBJ_COMPOUND: { | ||
| bool ErrorFound = false; | ||
| const RecordDecl *RD = ArgTy->getAs<RecordType>()->getDecl(); | ||
| const RecordDecl *RD = Ty->getAs<RecordType>()->getDecl(); | ||
| // Never recurse infinitely into related subtypes | ||
|
simoll marked this conversation as resolved.
Outdated
|
||
| 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<CXXRecordDecl>(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, CheckLongVec, | ||
| DiagContext, CheckedDecls, ElemFD); | ||
| } | ||
| if (!RD->isCompleteDefinition()) | ||
| return ErrorFound; | ||
|
|
||
| if (auto *Child = dyn_cast<CXXRecordDecl>(RD)) | ||
| // Walk up the inheritance chain and check base class fields | ||
| for (auto &B : Child->bases()) | ||
| ErrorFound |= | ||
| DiagnoseElementTypes(S, Loc, B.getType(), Empty, CheckLongVec, | ||
| DiagContext, CheckedDecls, nullptr); | ||
| return ErrorFound; | ||
| } | ||
| default: | ||
| DXASSERT(false, "unreachable"); | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| bool hlsl::DiagnoseTypeElements(Sema &S, SourceLocation Loc, QualType Ty, | ||
|
simoll marked this conversation as resolved.
|
||
| TypeDiagContext DiagContext, | ||
| const clang::FieldDecl *FD) { | ||
| bool Empty = false; | ||
| llvm::SmallPtrSet<const RecordDecl *, 8> CheckedDecls; | ||
| return DiagnoseElementTypes(S, Loc, Ty, Empty, false /*CheckLongVec*/, | ||
| DiagContext, CheckedDecls, FD); | ||
| } | ||
|
|
||
| bool hlsl::DiagnoseNodeStructArgument(Sema *self, TemplateArgumentLoc ArgLoc, | ||
| QualType ArgTy, bool &Empty, | ||
| const FieldDecl *FD) { | ||
| llvm::SmallPtrSet<const RecordDecl *, 8> CheckedDecls; | ||
| return DiagnoseElementTypes(*self, ArgLoc.getLocation(), ArgTy, Empty, | ||
| true /*CheckLongVec*/, | ||
| 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, | ||
|
|
@@ -15295,19 +15373,42 @@ 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)) { | ||
| if (isGroupShared) { | ||
| // Suppress actual emitting of errors for incompletable types here | ||
| // They are redundant to those produced in ActOnUninitializedDecl. | ||
| struct SilentDiagnoser : public TypeDiagnoser { | ||
| SilentDiagnoser() : TypeDiagnoser(true) {} | ||
| virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {} | ||
| } SD; | ||
| RequireCompleteType(D.getLocStart(), qt, SD); | ||
| if (DiagnoseTypeElements(*this, D.getLocStart(), qt, | ||
| TypeDiagContext::GroupShared)) | ||
| result = false; | ||
| } | ||
|
|
||
| // 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 { | ||
| SilentDiagnoser() : TypeDiagnoser(true) {} | ||
| virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {} | ||
| } SD; | ||
| RequireCompleteType(D.getLocStart(), qt, SD); | ||
| TypeDiagContext DiagContext = TypeDiagContext::CBuffersOrTBuffers; | ||
| if (isStatic) | ||
| DiagContext = TypeDiagContext::GlobalVariables; | ||
|
simoll marked this conversation as resolved.
Outdated
|
||
| if (DiagnoseTypeElements(*this, D.getLocStart(), qt, DiagContext)) | ||
| result = false; | ||
| } | ||
|
|
||
| // Disallow long vecs from $Global cbuffers. | ||
| if (isGlobal && !isStatic && !isGroupShared && !IS_BASIC_OBJECT(basicKind)) { | ||
| const unsigned CbuffersOrTbuffersIdx = 4; | ||
|
simoll marked this conversation as resolved.
Outdated
|
||
| if (ContainsLongVector(qt)) { | ||
| unsigned CbuffersOrTbuffersIdx = 4; | ||
| Diag(D.getLocStart(), diag::err_hlsl_unsupported_long_vector) | ||
| << CbuffersOrTbuffersIdx; | ||
|
simoll marked this conversation as resolved.
Outdated
|
||
|
|
||
| result = false; | ||
| } | ||
| } | ||
|
|
@@ -16220,7 +16321,8 @@ static bool CheckUDTIntrinsicArg(Sema *S, Expr *Arg) { | |
| << UserDefinedStructParameterIdx; | ||
| return true; | ||
| } | ||
| return false; | ||
| return DiagnoseTypeElements(*S, Arg->getExprLoc(), Arg->getType(), | ||
| TypeDiagContext::UserDefinedStructParameter); | ||
| } | ||
|
|
||
| static bool CheckIntrinsicGetAttributeAtVertex(Sema *S, FunctionDecl *FDecl, | ||
|
|
@@ -16962,13 +17064,17 @@ void DiagnoseEntry(Sema &S, FunctionDecl *FD) { | |
| S.Diag(param->getLocation(), diag::err_hlsl_unsupported_long_vector) | ||
| << EntryFunctionParametersIdx; | ||
| } | ||
| hlsl::DiagnoseTypeElements(S, param->getLocation(), param->getType(), | ||
| TypeDiagContext::EntryFunctionParameters); | ||
| } | ||
|
|
||
| if (ContainsLongVector(FD->getReturnType())) { | ||
| const unsigned EntryFunctionReturnIdx = 7; | ||
| S.Diag(FD->getLocation(), diag::err_hlsl_unsupported_long_vector) | ||
| << EntryFunctionReturnIdx; | ||
|
simoll marked this conversation as resolved.
Outdated
|
||
| } | ||
| DiagnoseTypeElements(S, FD->getLocation(), FD->getReturnType(), | ||
| TypeDiagContext::EntryFunctionReturnType); | ||
|
|
||
| DXIL::ShaderKind Stage = | ||
| ShaderModel::KindFromFullName(shaderAttr->getStage()); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.