[clang] [llvm] Implement resource binding type prefix mismatch errors (PR #87578)
Justin Bogner via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 24 12:35:51 PDT 2024
================
@@ -7334,6 +7334,100 @@ static void handleHLSLShaderAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
D->addAttr(NewAttr);
}
+static void DiagnoseHLSLResourceRegType(Sema &S, SourceLocation &ArgLoc,
+ Decl *D, StringRef &Slot) {
+ // Samplers, UAVs, and SRVs are VarDecl types
+ VarDecl *SamplerUAVOrSRV = dyn_cast<VarDecl>(D);
+ // Cbuffers and Tbuffers are HLSLBufferDecl types
+ HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D);
+ if (!SamplerUAVOrSRV && !CBufferOrTBuffer)
+ return;
+
+ llvm::hlsl::ResourceClass DeclResourceClass;
+ StringRef VarTy = "";
+ if (SamplerUAVOrSRV) {
+ const Type *Ty = SamplerUAVOrSRV->getType()->getPointeeOrArrayElementType();
+ if (!Ty)
+ llvm_unreachable("Resource class must have an element type.");
+
+ if (const BuiltinType *BTy = dyn_cast<BuiltinType>(Ty)) {
+ QualType QT = SamplerUAVOrSRV->getType();
+ PrintingPolicy PP = S.getPrintingPolicy();
+ std::string typestr = QualType::getAsString(QT.split(), PP);
+
+ if (Slot[0] != 't')
+ S.Diag(ArgLoc,
+ diag::err_hlsl_mismatching_register_builtin_type_and_name)
+ << Slot.substr(0, 1) << typestr << "'t'";
+ return;
+ }
+
+ const CXXRecordDecl *TheRecordDecl = Ty->getAsCXXRecordDecl();
+ if (!TheRecordDecl)
+ llvm_unreachable(
+ "Resource class should have a resource type declaration.");
+
+ if (auto TDecl = dyn_cast<ClassTemplateSpecializationDecl>(TheRecordDecl))
+ TheRecordDecl = TDecl->getSpecializedTemplate()->getTemplatedDecl();
+ TheRecordDecl = TheRecordDecl->getCanonicalDecl();
+ const auto *Attr = TheRecordDecl->getAttr<HLSLResourceAttr>();
+ if (!Attr)
+ llvm_unreachable("Resource class should have a resource attribute.");
+
+ DeclResourceClass = Attr->getResourceClass();
+ VarTy = TheRecordDecl->getName();
+ } else {
+ if (CBufferOrTBuffer->isCBuffer()) {
+ DeclResourceClass = llvm::hlsl::ResourceClass::CBuffer;
+ VarTy = "cbuffer";
+ } else {
+ DeclResourceClass = llvm::hlsl::ResourceClass::TBuffer;
+ VarTy = "tbuffer";
+ }
+ }
+ switch (DeclResourceClass) {
+ case llvm::hlsl::ResourceClass::SRV: {
+ if (Slot[0] != 't')
+ S.Diag(ArgLoc, diag::err_hlsl_mismatching_register_resource_type_and_name)
+ << Slot.substr(0, 1) << VarTy
+ << (unsigned)llvm::hlsl::ResourceClass::SRV;
+ break;
----------------
bogner wrote:
This code is all a little repetitive. Should we reverse the logic and exit early in the valid cases instead, and emit the diagnostic in the fallthrough?
```c++
switch (DeclResourceClass) {
case llvm::hlsl::ResourceClass::SRV:
if (Slot[0] == 't')
return;
case llvm::hlsl::ResourceClass::UAV:
if (Slot[0] == 'u')
return;
// ...
}
S.Diag(ArgLoc, diag::err_hlsl_mismatching_register_resource_type_and_name)
<< Slot.substr(0, 1) << VarTy
<< (unsigned)DeclResourceClass;
```
https://github.com/llvm/llvm-project/pull/87578
More information about the cfe-commits
mailing list