@@ -10829,18 +10829,24 @@ HLSLExternalSource::ApplyTypeSpecSignToParsedType(clang::QualType &type,
10829
10829
}
10830
10830
}
10831
10831
10832
- bool DiagnoseIntersectionAttributes(Sema &S, SourceLocation Loc, QualType Ty) {
10833
- // Must be a UDT
10832
+ bool CheckIntersectionAttributeArg(Sema &S, Expr *E) {
10833
+ SourceLocation Loc = E->getExprLoc();
10834
+ QualType Ty = E->getType();
10835
+
10836
+ // Identify problematic fields first (high diagnostic accuracy, may miss some
10837
+ // invalid cases)
10838
+ const TypeDiagContext DiagContext = TypeDiagContext::Attributes;
10839
+ if (DiagnoseTypeElements(S, Loc, Ty, DiagContext, DiagContext))
10840
+ return true;
10841
+
10842
+ // Must be a UDT (low diagnostic accuracy, catches remaining invalid cases)
10834
10843
if (Ty.isNull() || !hlsl::IsHLSLCopyableAnnotatableRecord(Ty)) {
10835
10844
S.Diag(Loc, diag::err_payload_attrs_must_be_udt)
10836
10845
<< /*payload|attributes|callable*/ 1 << /*parameter %2|type*/ 1;
10837
- return false ;
10846
+ return true ;
10838
10847
}
10839
10848
10840
- const TypeDiagContext DiagContext = TypeDiagContext::Attributes;
10841
- if (DiagnoseTypeElements(S, Loc, Ty, DiagContext, DiagContext))
10842
- return false;
10843
- return true;
10849
+ return false;
10844
10850
}
10845
10851
10846
10852
Sema::TemplateDeductionResult
@@ -10951,7 +10957,6 @@ HLSLExternalSource::DeduceTemplateArgumentsForHLSL(
10951
10957
LPCSTR tableName = cursor.GetTableName();
10952
10958
// Currently only intrinsic we allow for explicit template arguments are
10953
10959
// for Load/Store for ByteAddressBuffer/RWByteAddressBuffer
10954
- // and HitObject::GetAttributes with user-defined intersection attributes.
10955
10960
10956
10961
// Check Explicit template arguments
10957
10962
UINT intrinsicOp = (*cursor)->Op;
@@ -10966,11 +10971,9 @@ HLSLExternalSource::DeduceTemplateArgumentsForHLSL(
10966
10971
IsBABLoad = intrinsicOp == (UINT)IntrinsicOp::MOP_Load;
10967
10972
IsBABStore = intrinsicOp == (UINT)IntrinsicOp::MOP_Store;
10968
10973
}
10969
- bool IsHitObjectGetAttributes =
10970
- intrinsicOp == (UINT)IntrinsicOp::MOP_DxHitObject_GetAttributes;
10971
10974
if (ExplicitTemplateArgs && ExplicitTemplateArgs->size() >= 1) {
10972
10975
SourceLocation Loc = ExplicitTemplateArgs->getLAngleLoc();
10973
- if (!IsBABLoad && !IsBABStore && !IsHitObjectGetAttributes ) {
10976
+ if (!IsBABLoad && !IsBABStore) {
10974
10977
getSema()->Diag(Loc, diag::err_hlsl_intrinsic_template_arg_unsupported)
10975
10978
<< intrinsicName;
10976
10979
return Sema::TemplateDeductionResult::TDK_Invalid;
@@ -11000,10 +11003,6 @@ HLSLExternalSource::DeduceTemplateArgumentsForHLSL(
11000
11003
return Sema::TemplateDeductionResult::TDK_Invalid;
11001
11004
}
11002
11005
}
11003
- if (IsHitObjectGetAttributes &&
11004
- !DiagnoseIntersectionAttributes(*getSema(), Loc,
11005
- functionTemplateTypeArg))
11006
- return Sema::TemplateDeductionResult::TDK_Invalid;
11007
11006
} else if (IsBABStore) {
11008
11007
// Prior to HLSL 2018, Store operation only stored scalar uint.
11009
11008
if (!Is2018) {
@@ -12277,9 +12276,78 @@ static bool CheckVKBufferPointerCast(Sema &S, FunctionDecl *FD, CallExpr *CE,
12277
12276
}
12278
12277
#endif
12279
12278
12279
+ static bool isRelatedDeclMarkedNointerpolation(Expr *E) {
12280
+ if (!E)
12281
+ return false;
12282
+ E = E->IgnoreCasts();
12283
+ if (auto *DRE = dyn_cast<DeclRefExpr>(E))
12284
+ return DRE->getDecl()->hasAttr<HLSLNoInterpolationAttr>();
12285
+
12286
+ if (auto *ME = dyn_cast<MemberExpr>(E))
12287
+ return ME->getMemberDecl()->hasAttr<HLSLNoInterpolationAttr>() ||
12288
+ isRelatedDeclMarkedNointerpolation(ME->getBase());
12289
+
12290
+ if (auto *HVE = dyn_cast<HLSLVectorElementExpr>(E))
12291
+ return isRelatedDeclMarkedNointerpolation(HVE->getBase());
12292
+
12293
+ if (auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
12294
+ return isRelatedDeclMarkedNointerpolation(ASE->getBase());
12295
+
12296
+ return false;
12297
+ }
12298
+
12299
+ static bool CheckIntrinsicGetAttributeAtVertex(Sema &S, FunctionDecl *FDecl,
12300
+ CallExpr *TheCall) {
12301
+ assert(TheCall->getNumArgs() > 0);
12302
+ auto argument = TheCall->getArg(0)->IgnoreCasts();
12303
+
12304
+ if (!isRelatedDeclMarkedNointerpolation(argument)) {
12305
+ S.Diag(argument->getExprLoc(), diag::err_hlsl_parameter_requires_attribute)
12306
+ << 0 << FDecl->getName() << "nointerpolation";
12307
+ return true;
12308
+ }
12309
+
12310
+ return false;
12311
+ }
12312
+
12313
+ static bool CheckNoInterpolationParams(Sema &S, FunctionDecl *FDecl,
12314
+ CallExpr *TheCall) {
12315
+ // See #hlsl-specs/issues/181. Feature is broken. For SPIR-V we want
12316
+ // to limit the scope, and fail gracefully in some cases.
12317
+ if (!S.getLangOpts().SPIRV)
12318
+ return false;
12319
+
12320
+ bool error = false;
12321
+ for (unsigned i = 0; i < FDecl->getNumParams(); i++) {
12322
+ assert(i < TheCall->getNumArgs());
12323
+
12324
+ if (!FDecl->getParamDecl(i)->hasAttr<HLSLNoInterpolationAttr>())
12325
+ continue;
12326
+
12327
+ if (!isRelatedDeclMarkedNointerpolation(TheCall->getArg(i))) {
12328
+ S.Diag(TheCall->getArg(i)->getExprLoc(),
12329
+ diag::err_hlsl_parameter_requires_attribute)
12330
+ << i << FDecl->getName() << "nointerpolation";
12331
+ error = true;
12332
+ }
12333
+ }
12334
+
12335
+ return error;
12336
+ }
12337
+
12338
+ // Verify that user-defined intrinsic struct args contain no long vectors
12339
+ static bool CheckUDTIntrinsicArg(Sema &S, Expr *Arg) {
12340
+ const TypeDiagContext DiagContext =
12341
+ TypeDiagContext::UserDefinedStructParameter;
12342
+ return DiagnoseTypeElements(S, Arg->getExprLoc(), Arg->getType(), DiagContext,
12343
+ DiagContext);
12344
+ }
12345
+
12280
12346
// Check HLSL call constraints, not fatal to creating the AST.
12281
- void Sema::CheckHLSLFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
12282
- const FunctionProtoType *Proto) {
12347
+ void Sema::CheckHLSLFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) {
12348
+ if (CheckNoInterpolationParams(*this, FDecl, TheCall))
12349
+ return;
12350
+
12283
12351
HLSLIntrinsicAttr *IntrinsicAttr = FDecl->getAttr<HLSLIntrinsicAttr>();
12284
12352
if (!IntrinsicAttr)
12285
12353
return;
@@ -12307,6 +12375,28 @@ void Sema::CheckHLSLFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
12307
12375
case hlsl::IntrinsicOp::IOP___builtin_OuterProductAccumulate:
12308
12376
CheckOuterProductAccumulateCall(*this, FDecl, TheCall);
12309
12377
break;
12378
+ case hlsl::IntrinsicOp::IOP_GetAttributeAtVertex:
12379
+ // See #hlsl-specs/issues/181. Feature is broken. For SPIR-V we want
12380
+ // to limit the scope, and fail gracefully in some cases.
12381
+ if (!getLangOpts().SPIRV)
12382
+ return;
12383
+ CheckIntrinsicGetAttributeAtVertex(*this, FDecl, TheCall);
12384
+ break;
12385
+ case hlsl::IntrinsicOp::IOP_DispatchMesh:
12386
+ CheckUDTIntrinsicArg(*this, TheCall->getArg(3)->IgnoreCasts());
12387
+ break;
12388
+ case hlsl::IntrinsicOp::IOP_CallShader:
12389
+ CheckUDTIntrinsicArg(*this, TheCall->getArg(1)->IgnoreCasts());
12390
+ break;
12391
+ case hlsl::IntrinsicOp::IOP_TraceRay:
12392
+ CheckUDTIntrinsicArg(*this, TheCall->getArg(7)->IgnoreCasts());
12393
+ break;
12394
+ case hlsl::IntrinsicOp::IOP_ReportHit:
12395
+ CheckIntersectionAttributeArg(*this, TheCall->getArg(2)->IgnoreCasts());
12396
+ break;
12397
+ case hlsl::IntrinsicOp::MOP_DxHitObject_GetAttributes:
12398
+ CheckIntersectionAttributeArg(*this, TheCall->getArg(0)->IgnoreCasts());
12399
+ break;
12310
12400
#ifdef ENABLE_SPIRV_CODEGEN
12311
12401
case hlsl::IntrinsicOp::IOP_Vkreinterpret_pointer_cast:
12312
12402
CheckVKBufferPointerCast(*this, FDecl, TheCall, false);
@@ -16841,118 +16931,6 @@ QualType Sema::getHLSLDefaultSpecialization(TemplateDecl *Decl) {
16841
16931
return QualType();
16842
16932
}
16843
16933
16844
- static bool isRelatedDeclMarkedNointerpolation(Expr *E) {
16845
- if (!E)
16846
- return false;
16847
- E = E->IgnoreCasts();
16848
- if (auto *DRE = dyn_cast<DeclRefExpr>(E))
16849
- return DRE->getDecl()->hasAttr<HLSLNoInterpolationAttr>();
16850
-
16851
- if (auto *ME = dyn_cast<MemberExpr>(E))
16852
- return ME->getMemberDecl()->hasAttr<HLSLNoInterpolationAttr>() ||
16853
- isRelatedDeclMarkedNointerpolation(ME->getBase());
16854
-
16855
- if (auto *HVE = dyn_cast<HLSLVectorElementExpr>(E))
16856
- return isRelatedDeclMarkedNointerpolation(HVE->getBase());
16857
-
16858
- if (auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
16859
- return isRelatedDeclMarkedNointerpolation(ASE->getBase());
16860
-
16861
- return false;
16862
- }
16863
-
16864
- // Verify that user-defined intrinsic struct args contain no long vectors
16865
- static bool CheckUDTIntrinsicArg(Sema *S, Expr *Arg) {
16866
- const TypeDiagContext DiagContext =
16867
- TypeDiagContext::UserDefinedStructParameter;
16868
- return DiagnoseTypeElements(*S, Arg->getExprLoc(), Arg->getType(),
16869
- DiagContext, DiagContext);
16870
- }
16871
-
16872
- static bool CheckIntrinsicGetAttributeAtVertex(Sema *S, FunctionDecl *FDecl,
16873
- CallExpr *TheCall) {
16874
- assert(TheCall->getNumArgs() > 0);
16875
- auto argument = TheCall->getArg(0)->IgnoreCasts();
16876
-
16877
- if (!isRelatedDeclMarkedNointerpolation(argument)) {
16878
- S->Diag(argument->getExprLoc(), diag::err_hlsl_parameter_requires_attribute)
16879
- << 0 << FDecl->getName() << "nointerpolation";
16880
- return true;
16881
- }
16882
-
16883
- return false;
16884
- }
16885
-
16886
- bool Sema::CheckHLSLIntrinsicCall(FunctionDecl *FDecl, CallExpr *TheCall) {
16887
- auto attr = FDecl->getAttr<HLSLIntrinsicAttr>();
16888
-
16889
- if (!attr)
16890
- return false;
16891
-
16892
- if (!IsBuiltinTable(attr->getGroup()))
16893
- return false;
16894
-
16895
- switch (hlsl::IntrinsicOp(attr->getOpcode())) {
16896
- case hlsl::IntrinsicOp::IOP_GetAttributeAtVertex:
16897
- // See #hlsl-specs/issues/181. Feature is broken. For SPIR-V we want
16898
- // to limit the scope, and fail gracefully in some cases.
16899
- if (!getLangOpts().SPIRV)
16900
- return false;
16901
- // This should never happen for SPIR-V. But on the DXIL side, extension can
16902
- // be added by inserting new intrinsics, meaning opcodes can collide with
16903
- // existing ones. See the ExtensionTest.EvalAttributeCollision test.
16904
- assert(FDecl->getName() == "GetAttributeAtVertex");
16905
- return CheckIntrinsicGetAttributeAtVertex(this, FDecl, TheCall);
16906
- case hlsl::IntrinsicOp::IOP_DispatchMesh:
16907
- assert(TheCall->getNumArgs() > 3);
16908
- assert(FDecl->getName() == "DispatchMesh");
16909
- return CheckUDTIntrinsicArg(this, TheCall->getArg(3)->IgnoreCasts());
16910
- case hlsl::IntrinsicOp::IOP_CallShader:
16911
- assert(TheCall->getNumArgs() > 1);
16912
- assert(FDecl->getName() == "CallShader");
16913
- return CheckUDTIntrinsicArg(this, TheCall->getArg(1)->IgnoreCasts());
16914
- case hlsl::IntrinsicOp::IOP_TraceRay:
16915
- assert(TheCall->getNumArgs() > 7);
16916
- assert(FDecl->getName() == "TraceRay");
16917
- return CheckUDTIntrinsicArg(this, TheCall->getArg(7)->IgnoreCasts());
16918
- case hlsl::IntrinsicOp::IOP_ReportHit:
16919
- assert(TheCall->getNumArgs() > 2);
16920
- assert(FDecl->getName() == "ReportHit");
16921
- return CheckUDTIntrinsicArg(this, TheCall->getArg(2)->IgnoreCasts());
16922
- default:
16923
- break;
16924
- }
16925
-
16926
- return false;
16927
- }
16928
-
16929
- bool Sema::CheckHLSLFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) {
16930
- if (hlsl::IsIntrinsicOp(FDecl) && CheckHLSLIntrinsicCall(FDecl, TheCall))
16931
- return true;
16932
-
16933
- // See #hlsl-specs/issues/181. Feature is broken. For SPIR-V we want
16934
- // to limit the scope, and fail gracefully in some cases.
16935
- if (!getLangOpts().SPIRV)
16936
- return false;
16937
-
16938
- bool error = false;
16939
- for (unsigned i = 0; i < FDecl->getNumParams(); i++) {
16940
- assert(i < TheCall->getNumArgs());
16941
-
16942
- if (!FDecl->getParamDecl(i)->hasAttr<HLSLNoInterpolationAttr>())
16943
- continue;
16944
-
16945
- if (!isRelatedDeclMarkedNointerpolation(TheCall->getArg(i))) {
16946
- Diag(TheCall->getArg(i)->getExprLoc(),
16947
- diag::err_hlsl_parameter_requires_attribute)
16948
- << i << FDecl->getName() << "nointerpolation";
16949
- error = true;
16950
- }
16951
- }
16952
-
16953
- return error;
16954
- }
16955
-
16956
16934
namespace hlsl {
16957
16935
16958
16936
static bool nodeInputIsCompatible(DXIL::NodeIOKind IOType,
0 commit comments