Skip to content

Commit 0a7a1ef

Browse files
authored
[HLSL] Add [[hlsl::contained_type()]] attribute (#108456)
Introducing a new HLSL resource type attribute `[[contained_type(T)]]` which describes the "contained type" of a buffer or resource type. Specifically, the attribute will be used on the resource handle in templated buffer types like so: template <typename T> struct RWBuffer { __hlsl_resource_t [[hlsl::contained_type(T)]] [[hlsl::resource_class(UAV)]] h; }; Fixes #104855
1 parent f14fd32 commit 0a7a1ef

13 files changed

+181
-43
lines changed

clang/include/clang/AST/TypeLoc.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,7 @@ class BTFTagAttributedTypeLoc
942942

943943
struct HLSLAttributedResourceLocInfo {
944944
SourceRange Range;
945+
TypeSourceInfo *ContainedTyInfo;
945946
};
946947

947948
/// Type source information for HLSL attributed resource type.
@@ -952,8 +953,11 @@ class HLSLAttributedResourceTypeLoc
952953
public:
953954
TypeLoc getWrappedLoc() const { return getInnerTypeLoc(); }
954955

955-
TypeLoc getContainedLoc() const {
956-
return TypeLoc(getTypePtr()->getContainedType(), getNonLocalData());
956+
TypeSourceInfo *getContainedTypeSourceInfo() const {
957+
return getLocalData()->ContainedTyInfo;
958+
}
959+
void setContainedTypeSourceInfo(TypeSourceInfo *TSI) const {
960+
getLocalData()->ContainedTyInfo = TSI;
957961
}
958962

959963
void setSourceRange(const SourceRange &R) { getLocalData()->Range = R; }

clang/include/clang/Basic/Attr.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4667,6 +4667,13 @@ def HLSLResourceClass : TypeAttr {
46674667
let Documentation = [InternalOnly];
46684668
}
46694669

4670+
def HLSLContainedType : TypeAttr {
4671+
let Spellings = [CXX11<"hlsl", "contained_type">];
4672+
let LangOpts = [HLSL];
4673+
let Args = [TypeArgument<"Type", /*opt=*/0>];
4674+
let Documentation = [InternalOnly];
4675+
}
4676+
46704677
def HLSLGroupSharedAddressSpace : TypeAttr {
46714678
let Spellings = [CustomKeyword<"groupshared">];
46724679
let Subjects = SubjectList<[Var]>;

clang/include/clang/Sema/SemaHLSL.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "clang/AST/ASTFwd.h"
1717
#include "clang/AST/Attr.h"
1818
#include "clang/AST/Type.h"
19+
#include "clang/AST/TypeLoc.h"
1920
#include "clang/Basic/SourceLocation.h"
2021
#include "clang/Sema/SemaBase.h"
2122
#include "llvm/ADT/SmallVector.h"
@@ -30,9 +31,9 @@ class Scope;
3031

3132
// FIXME: This can be hidden (as static function in SemaHLSL.cpp) once we no
3233
// longer need to create builtin buffer types in HLSLExternalSemaSource.
33-
bool CreateHLSLAttributedResourceType(Sema &S, QualType Wrapped,
34-
ArrayRef<const Attr *> AttrList,
35-
QualType &ResType);
34+
bool CreateHLSLAttributedResourceType(
35+
Sema &S, QualType Wrapped, ArrayRef<const Attr *> AttrList,
36+
QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo = nullptr);
3637

3738
class SemaHLSL : public SemaBase {
3839
public:
@@ -73,7 +74,8 @@ class SemaHLSL : public SemaBase {
7374

7475
bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
7576
QualType ProcessResourceTypeAttributes(QualType Wrapped);
76-
SourceLocation TakeLocForHLSLAttribute(const HLSLAttributedResourceType *RT);
77+
HLSLAttributedResourceLocInfo
78+
TakeLocForHLSLAttribute(const HLSLAttributedResourceType *RT);
7779

7880
// HLSL Type trait implementations
7981
bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const;
@@ -90,9 +92,10 @@ class SemaHLSL : public SemaBase {
9092
// This is a list to collect them.
9193
llvm::SmallVector<const Attr *> HLSLResourcesTypeAttrs;
9294

93-
/// SourceLocation corresponding to HLSLAttributedResourceTypeLocs that we
95+
/// TypeLoc data for HLSLAttributedResourceType instances that we
9496
/// have not yet populated.
95-
llvm::DenseMap<const HLSLAttributedResourceType *, SourceLocation>
97+
llvm::DenseMap<const HLSLAttributedResourceType *,
98+
HLSLAttributedResourceLocInfo>
9699
LocsForHLSLAttributedResources;
97100
};
98101

clang/lib/AST/TypePrinter.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1945,6 +1945,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
19451945

19461946
case attr::HLSLResourceClass:
19471947
case attr::HLSLROV:
1948+
case attr::HLSLContainedType:
19481949
llvm_unreachable("HLSL resource type attributes handled separately");
19491950

19501951
case attr::OpenCLPrivateAddressSpace:
@@ -2078,6 +2079,14 @@ void TypePrinter::printHLSLAttributedResourceAfter(
20782079
<< ")]]";
20792080
if (Attrs.IsROV)
20802081
OS << " [[hlsl::is_rov]]";
2082+
2083+
QualType ContainedTy = T->getContainedType();
2084+
if (!ContainedTy.isNull()) {
2085+
OS << " [[hlsl::contained_type(";
2086+
printBefore(ContainedTy, OS);
2087+
printAfter(ContainedTy, OS);
2088+
OS << ")]]";
2089+
}
20812090
}
20822091

20832092
void TypePrinter::printObjCInterfaceBefore(const ObjCInterfaceType *T,

clang/lib/Sema/HLSLExternalSemaSource.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "clang/AST/Type.h"
1717
#include "clang/Basic/AttrKinds.h"
1818
#include "clang/Basic/HLSLRuntime.h"
19+
#include "clang/Basic/SourceLocation.h"
1920
#include "clang/Sema/Lookup.h"
2021
#include "clang/Sema/Sema.h"
2122
#include "clang/Sema/SemaHLSL.h"
@@ -114,19 +115,30 @@ struct BuiltinTypeDeclBuilder {
114115
AccessSpecifier Access = AccessSpecifier::AS_private) {
115116
if (Record->isCompleteDefinition())
116117
return *this;
118+
119+
TypeSourceInfo *ElementTypeInfo = nullptr;
120+
117121
QualType Ty = Record->getASTContext().VoidPtrTy;
118122
if (Template) {
119123
if (const auto *TTD = dyn_cast<TemplateTypeParmDecl>(
120-
Template->getTemplateParameters()->getParam(0)))
124+
Template->getTemplateParameters()->getParam(0))) {
121125
Ty = Record->getASTContext().getPointerType(
122126
QualType(TTD->getTypeForDecl(), 0));
127+
QualType ElemType = QualType(TTD->getTypeForDecl(), 0);
128+
ElementTypeInfo = S.getASTContext().getTrivialTypeSourceInfo(
129+
ElemType, SourceLocation());
130+
}
123131
}
124132

125133
// add handle member with resource type attributes
126134
QualType AttributedResTy = QualType();
127135
SmallVector<const Attr *> Attrs = {
128136
HLSLResourceClassAttr::CreateImplicit(Record->getASTContext(), RC),
129-
IsROV ? HLSLROVAttr::CreateImplicit(Record->getASTContext()) : nullptr};
137+
IsROV ? HLSLROVAttr::CreateImplicit(Record->getASTContext()) : nullptr,
138+
ElementTypeInfo ? HLSLContainedTypeAttr::CreateImplicit(
139+
Record->getASTContext(), ElementTypeInfo)
140+
: nullptr,
141+
};
130142
Attr *ResourceAttr =
131143
HLSLResourceAttr::CreateImplicit(Record->getASTContext(), RK);
132144
if (CreateHLSLAttributedResourceType(S, Ty, Attrs, AttributedResTy))

clang/lib/Sema/SemaHLSL.cpp

Lines changed: 66 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@
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
683730
SemaHLSL::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

693742
struct RegisterBindingFlags {

clang/lib/Sema/SemaType.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5801,8 +5801,10 @@ static void fillAttributedTypeLoc(AttributedTypeLoc TL,
58015801

58025802
static void fillHLSLAttributedResourceTypeLoc(HLSLAttributedResourceTypeLoc TL,
58035803
TypeProcessingState &State) {
5804-
TL.setSourceRange(
5805-
State.getSema().HLSL().TakeLocForHLSLAttribute(TL.getTypePtr()));
5804+
HLSLAttributedResourceLocInfo LocInfo =
5805+
State.getSema().HLSL().TakeLocForHLSLAttribute(TL.getTypePtr());
5806+
TL.setSourceRange(LocInfo.Range);
5807+
TL.setContainedTypeSourceInfo(LocInfo.ContainedTyInfo);
58065808
}
58075809

58085810
static void fillMatrixTypeLoc(MatrixTypeLoc MTL,
@@ -8843,7 +8845,8 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
88438845
break;
88448846
}
88458847
case ParsedAttr::AT_HLSLResourceClass:
8846-
case ParsedAttr::AT_HLSLROV: {
8848+
case ParsedAttr::AT_HLSLROV:
8849+
case ParsedAttr::AT_HLSLContainedType: {
88478850
// Only collect HLSL resource type attributes that are in
88488851
// decl-specifier-seq; do not collect attributes on declarations or those
88498852
// that get to slide after declaration name.

clang/lib/Sema/TreeTransform.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7477,8 +7477,17 @@ QualType TreeTransform<Derived>::TransformHLSLAttributedResourceType(
74777477
return QualType();
74787478

74797479
QualType ContainedTy = QualType();
7480-
if (!oldType->getContainedType().isNull())
7481-
ContainedTy = getDerived().TransformType(TLB, TL.getContainedLoc());
7480+
QualType OldContainedTy = oldType->getContainedType();
7481+
if (!OldContainedTy.isNull()) {
7482+
TypeSourceInfo *oldContainedTSI = TL.getContainedTypeSourceInfo();
7483+
if (!oldContainedTSI)
7484+
oldContainedTSI = getSema().getASTContext().getTrivialTypeSourceInfo(
7485+
OldContainedTy, SourceLocation());
7486+
TypeSourceInfo *ContainedTSI = getDerived().TransformType(oldContainedTSI);
7487+
if (!ContainedTSI)
7488+
return QualType();
7489+
ContainedTy = ContainedTSI->getType();
7490+
}
74827491

74837492
QualType Result = TL.getType();
74847493
if (getDerived().AlwaysRebuild() || WrappedTy != oldType->getWrappedType() ||

clang/test/AST/HLSL/RWBuffer-AST.hlsl

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -DEMPTY %s | FileCheck -check-prefix=EMPTY %s
22
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump %s | FileCheck %s
33

4-
54
// This test tests two different AST generations. The "EMPTY" test mode verifies
65
// the AST generated by forward declaration of the HLSL types which happens on
76
// initializing the HLSL external AST with an AST Context.
@@ -30,15 +29,15 @@ RWBuffer<float> Buffer;
3029
// CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit class RWBuffer definition
3130

3231
// CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
33-
// CHECK-NEXT: implicit h 'element_type * {{\[\[}}hlsl::resource_class(UAV)]]':'element_type *'
32+
// CHECK-NEXT: implicit h 'element_type * {{\[\[}}hlsl::resource_class(UAV)]] {{\[\[}}hlsl::contained_type(element_type)]]':'element_type *'
3433
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit TypedBuffer
3534

3635
// CHECK: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> operator[] 'element_type &const (unsigned int) const'
3736
// CHECK-NEXT: ParmVarDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> Idx 'unsigned int'
3837
// CHECK-NEXT: CompoundStmt 0x{{[0-9A-Fa-f]+}} <<invalid sloc>>
3938
// CHECK-NEXT: ReturnStmt 0x{{[0-9A-Fa-f]+}} <<invalid sloc>>
4039
// CHECK-NEXT: ArraySubscriptExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'element_type' lvalue
41-
// CHECK-NEXT: MemberExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'element_type * {{\[\[}}hlsl::resource_class(UAV)]]':'element_type *' lvalue .h 0x{{[0-9A-Fa-f]+}}
40+
// CHECK-NEXT: MemberExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'element_type * {{\[\[}}hlsl::resource_class(UAV)]] {{\[\[}}hlsl::contained_type(element_type)]]':'element_type *' lvalue .h 0x{{[0-9A-Fa-f]+}}
4241
// CHECK-NEXT: CXXThisExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'const RWBuffer<element_type>' lvalue implicit this
4342
// CHECK-NEXT: DeclRefExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'unsigned int' ParmVar 0x{{[0-9A-Fa-f]+}} 'Idx' 'unsigned int'
4443
// CHECK-NEXT: AlwaysInlineAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit always_inline
@@ -48,7 +47,7 @@ RWBuffer<float> Buffer;
4847
// CHECK-NEXT: CompoundStmt 0x{{[0-9A-Fa-f]+}} <<invalid sloc>>
4948
// CHECK-NEXT: ReturnStmt 0x{{[0-9A-Fa-f]+}} <<invalid sloc>>
5049
// CHECK-NEXT: ArraySubscriptExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'element_type' lvalue
51-
// CHECK-NEXT: MemberExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'element_type * {{\[\[}}hlsl::resource_class(UAV)]]':'element_type *' lvalue .h 0x{{[0-9A-Fa-f]+}}
50+
// CHECK-NEXT: MemberExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'element_type * {{\[\[}}hlsl::resource_class(UAV)]] {{\[\[}}hlsl::contained_type(element_type)]]':'element_type *' lvalue .h 0x{{[0-9A-Fa-f]+}}
5251
// CHECK-NEXT: CXXThisExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'RWBuffer<element_type>' lvalue implicit this
5352
// CHECK-NEXT: DeclRefExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'unsigned int' ParmVar 0x{{[0-9A-Fa-f]+}} 'Idx' 'unsigned int'
5453
// CHECK-NEXT: AlwaysInlineAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit always_inline
@@ -58,5 +57,5 @@ RWBuffer<float> Buffer;
5857
// CHECK: TemplateArgument type 'float'
5958
// CHECK-NEXT: BuiltinType 0x{{[0-9A-Fa-f]+}} 'float'
6059
// CHECK-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
61-
// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit referenced h 'float * {{\[\[}}hlsl::resource_class(UAV)]]':'float *'
60+
// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit referenced h 'float * {{\[\[}}hlsl::resource_class(UAV)]] {{\[\[}}hlsl::contained_type(float)]]':'float *'
6261
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit TypedBuffer

0 commit comments

Comments
 (0)