1010
1111#include " clang/Sema/SemaHLSL.h"
1212#include " clang/AST/ASTContext.h"
13+ #include " clang/AST/Attr.h"
14+ #include " clang/AST/Attrs.inc"
1315#include " clang/AST/Decl.h"
1416#include " clang/AST/DeclBase.h"
1517#include " clang/AST/DeclCXX.h"
1618#include " clang/AST/Expr.h"
1719#include " clang/AST/RecursiveASTVisitor.h"
1820#include " clang/AST/Type.h"
21+ #include " clang/AST/TypeLoc.h"
1922#include " clang/Basic/Builtins.h"
2023#include " clang/Basic/DiagnosticSema.h"
2124#include " clang/Basic/LLVM.h"
@@ -564,18 +567,23 @@ void SemaHLSL::handleShaderAttr(Decl *D, const ParsedAttr &AL) {
564567 D->addAttr (NewAttr);
565568}
566569
567- bool clang::CreateHLSLAttributedResourceType (Sema &S, QualType Wrapped,
568- ArrayRef<const Attr *> AttrList,
569- QualType &ResType) {
570+ bool clang::CreateHLSLAttributedResourceType (
571+ Sema &S, QualType Wrapped, ArrayRef<const Attr *> AttrList,
572+ QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo ) {
570573 assert (AttrList.size () && " expected list of resource attributes" );
571574
572- QualType Contained = QualType ();
575+ QualType ContainedTy = QualType ();
576+ TypeSourceInfo *ContainedTyInfo;
577+ SourceLocation LocBegin = AttrList[0 ]->getRange ().getBegin ();
578+ SourceLocation LocEnd = AttrList[0 ]->getRange ().getEnd ();
579+
573580 HLSLAttributedResourceType::Attributes ResAttrs = {};
574581
575582 bool HasResourceClass = false ;
576583 for (const Attr *A : AttrList) {
577584 if (!A)
578585 continue ;
586+ LocEnd = A->getRange ().getEnd ();
579587 switch (A->getKind ()) {
580588 case attr::HLSLResourceClass: {
581589 llvm::dxil::ResourceClass RC =
@@ -598,6 +606,20 @@ bool clang::CreateHLSLAttributedResourceType(Sema &S, QualType Wrapped,
598606 }
599607 ResAttrs.IsROV = true ;
600608 break ;
609+ case attr::HLSLContainedType: {
610+ const HLSLContainedTypeAttr *CTAttr = cast<HLSLContainedTypeAttr>(A);
611+ QualType Ty = CTAttr->getType ();
612+ if (!ContainedTy.isNull ()) {
613+ S.Diag (A->getLocation (), ContainedTy == Ty
614+ ? diag::warn_duplicate_attribute_exact
615+ : diag::warn_duplicate_attribute)
616+ << A;
617+ return false ;
618+ }
619+ ContainedTy = Ty;
620+ ContainedTyInfo = CTAttr->getTypeLoc ();
621+ break ;
622+ }
601623 default :
602624 llvm_unreachable (" unhandled resource attribute type" );
603625 }
@@ -609,8 +631,13 @@ bool clang::CreateHLSLAttributedResourceType(Sema &S, QualType Wrapped,
609631 return false ;
610632 }
611633
612- ResType = S.getASTContext ().getHLSLAttributedResourceType (Wrapped, Contained,
613- ResAttrs);
634+ ResType = S.getASTContext ().getHLSLAttributedResourceType (
635+ Wrapped, ContainedTy, ResAttrs);
636+
637+ if (LocInfo) {
638+ LocInfo->Range = SourceRange (LocBegin, LocEnd);
639+ LocInfo->ContainedTyInfo = ContainedTyInfo;
640+ }
614641 return true ;
615642}
616643
@@ -647,9 +674,27 @@ bool SemaHLSL::handleResourceTypeAttr(const ParsedAttr &AL) {
647674 A = HLSLResourceClassAttr::Create (getASTContext (), RC, AL.getLoc ());
648675 break ;
649676 }
677+
650678 case ParsedAttr::AT_HLSLROV:
651679 A = HLSLROVAttr::Create (getASTContext (), AL.getLoc ());
652680 break ;
681+
682+ case ParsedAttr::AT_HLSLContainedType: {
683+ if (AL.getNumArgs () != 1 && !AL.hasParsedType ()) {
684+ Diag (AL.getLoc (), diag::err_attribute_wrong_number_arguments) << AL << 1 ;
685+ return false ;
686+ }
687+
688+ TypeSourceInfo *TSI = nullptr ;
689+ QualType QT = SemaRef.GetTypeFromParser (AL.getTypeArg (), &TSI);
690+ assert (TSI && " no type source info for attribute argument" );
691+ if (SemaRef.RequireCompleteType (TSI->getTypeLoc ().getBeginLoc (), QT,
692+ diag::err_incomplete_type))
693+ return false ;
694+ A = HLSLContainedTypeAttr::Create (getASTContext (), TSI, AL.getLoc ());
695+ break ;
696+ }
697+
653698 default :
654699 llvm_unreachable (" unhandled HLSL attribute" );
655700 }
@@ -664,30 +709,34 @@ QualType SemaHLSL::ProcessResourceTypeAttributes(QualType CurrentType) {
664709 return CurrentType;
665710
666711 QualType QT = CurrentType;
712+ HLSLAttributedResourceLocInfo LocInfo;
667713 if (CreateHLSLAttributedResourceType (SemaRef, CurrentType,
668- HLSLResourcesTypeAttrs, QT)) {
714+ HLSLResourcesTypeAttrs, QT, &LocInfo )) {
669715 const HLSLAttributedResourceType *RT =
670- dyn_cast<HLSLAttributedResourceType>(QT.getTypePtr ());
671- // Use the location of the first attribute as the location of the aggregated
672- // type. The attributes are stored in HLSLResourceTypeAttrs in the same
673- // order as they are parsed.
674- SourceLocation Loc = HLSLResourcesTypeAttrs[0 ]->getLoc ();
675- LocsForHLSLAttributedResources.insert (std::pair (RT, Loc));
716+ cast<HLSLAttributedResourceType>(QT.getTypePtr ());
717+
718+ // Temporarily store TypeLoc information for the new type.
719+ // It will be transferred to HLSLAttributesResourceTypeLoc
720+ // shortly after the type is created by TypeSpecLocFiller which
721+ // will call the TakeLocForHLSLAttribute method below.
722+ LocsForHLSLAttributedResources.insert (std::pair (RT, LocInfo));
676723 }
677724 HLSLResourcesTypeAttrs.clear ();
678725 return QT;
679726}
680727
681728// Returns source location for the HLSLAttributedResourceType
682- SourceLocation
729+ HLSLAttributedResourceLocInfo
683730SemaHLSL::TakeLocForHLSLAttribute (const HLSLAttributedResourceType *RT) {
731+ HLSLAttributedResourceLocInfo LocInfo = {};
684732 auto I = LocsForHLSLAttributedResources.find (RT);
685733 if (I != LocsForHLSLAttributedResources.end ()) {
686- SourceLocation Loc = I->second ;
734+ LocInfo = I->second ;
687735 LocsForHLSLAttributedResources.erase (I);
688- return Loc ;
736+ return LocInfo ;
689737 }
690- return SourceLocation ();
738+ LocInfo.Range = SourceRange ();
739+ return LocInfo;
691740}
692741
693742struct RegisterBindingFlags {
0 commit comments