diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp index e5c6220bfb47d..257fdfd64ecf2 100644 --- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp +++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp @@ -613,6 +613,8 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleMember( ResourceClass RC, bool IsROV, bool RawBuffer, AccessSpecifier Access) { assert(!Record->isCompleteDefinition() && "record is already complete"); + ResClass = RC; + ASTContext &Ctx = SemaRef.getASTContext(); TypeSourceInfo *ElementTypeInfo = Ctx.getTrivialTypeSourceInfo(getHandleElementType(), SourceLocation()); @@ -620,7 +622,7 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addHandleMember( // add handle member with resource type attributes QualType AttributedResTy = QualType(); SmallVector Attrs = { - HLSLResourceClassAttr::CreateImplicit(Ctx, RC), + HLSLResourceClassAttr::CreateImplicit(Ctx, ResClass), IsROV ? HLSLROVAttr::CreateImplicit(Ctx) : nullptr, RawBuffer ? HLSLRawBufferAttr::CreateImplicit(Ctx) : nullptr, ElementTypeInfo @@ -697,7 +699,9 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addArraySubscriptOperators() { AST.DeclarationNames.getCXXOperatorName(OO_Subscript); addHandleAccessFunction(Subscript, /*IsConst=*/true, /*IsRef=*/true); - addHandleAccessFunction(Subscript, /*IsConst=*/false, /*IsRef=*/true); + if (ResClass == llvm::dxil::ResourceClass::UAV) + addHandleAccessFunction(Subscript, /*IsConst=*/false, /*IsRef=*/true); + return *this; } diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h index a52e2938104c7..91bf8748d0a45 100644 --- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h +++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h @@ -52,6 +52,7 @@ class BuiltinTypeDeclBuilder { ClassTemplateDecl *PrevTemplate = nullptr; NamespaceDecl *HLSLNamespace = nullptr; llvm::StringMap Fields; + ResourceClass ResClass; public: friend struct TemplateParameterListBuilder; diff --git a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl index b74e183eec9cc..1c8b9c10f5a98 100644 --- a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl +++ b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl @@ -12,7 +12,7 @@ // // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump \ // RUN: -DRESOURCE=RWStructuredBuffer %s | FileCheck -DRESOURCE=RWStructuredBuffer \ -// RUN: -check-prefixes=CHECK,CHECK-UAV,CHECK-SUBSCRIPT,CHECK-COUNTER,CHECK-LOAD %s +// RUN: -check-prefixes=CHECK,CHECK-UAV,CHECK-SUBSCRIPT,CHECK-SUBSCRIPT-UAV,CHECK-COUNTER,CHECK-LOAD %s // // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -DEMPTY \ // RUN: -DRESOURCE=AppendStructuredBuffer %s | FileCheck -DRESOURCE=AppendStructuredBuffer \ @@ -36,7 +36,7 @@ // // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump \ // RUN: -DRESOURCE=RasterizerOrderedStructuredBuffer %s | FileCheck -DRESOURCE=RasterizerOrderedStructuredBuffer \ -// RUN: -check-prefixes=CHECK,CHECK-UAV,CHECK-ROV,CHECK-SUBSCRIPT,CHECK-LOAD %s +// RUN: -check-prefixes=CHECK,CHECK-UAV,CHECK-ROV,CHECK-SUBSCRIPT,CHECK-SUBSCRIPT-UAV,CHECK-LOAD %s // This test tests two different AST generations for each structured buffer. // The "EMPTY" test mode verifies the AST generated by forward declaration @@ -170,22 +170,22 @@ RESOURCE Buffer; // CHECK-SUBSCRIPT-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int' // CHECK-SUBSCRIPT-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline -// CHECK-SUBSCRIPT-NEXT: CXXMethodDecl {{.*}} operator[] 'hlsl_device element_type &(unsigned int)' -// CHECK-SUBSCRIPT-NEXT: ParmVarDecl {{.*}} Index 'unsigned int' -// CHECK-SUBSCRIPT-NEXT: CompoundStmt -// CHECK-SUBSCRIPT-NEXT: ReturnStmt -// CHECK-SUBSCRIPT-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' prefix '*' cannot overflow -// CHECK-SUBSCRIPT-NEXT: CallExpr {{.*}} 'hlsl_device element_type *' -// CHECK-SUBSCRIPT-NEXT: ImplicitCastExpr {{.*}} -// CHECK-SUBSCRIPT-NEXT: DeclRefExpr {{.*}} '' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept' -// CHECK-SUBSCRIPT-NEXT: MemberExpr {{.*}} '__hlsl_resource_t -// CHECK-SUBSCRIPT-SAME{LITERAL}: [[hlsl::resource_class( -// CHECK-SUBSCRIPT-SAME{LITERAL}: [[hlsl::raw_buffer]] -// CHECK-SUBSCRIPT-SAME{LITERAL}: [[hlsl::contained_type(element_type)]] -// CHECK-SUBSCRIPT-SAME: ' lvalue .__handle {{.*}} -// CHECK-SUBSCRIPT-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]' lvalue implicit this -// CHECK-SUBSCRIPT-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int' -// CHECK-SUBSCRIPT-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline +// CHECK-SUBSCRIPT-UAV-NEXT: CXXMethodDecl {{.*}} operator[] 'hlsl_device element_type &(unsigned int)' +// CHECK-SUBSCRIPT-UAV-NEXT: ParmVarDecl {{.*}} Index 'unsigned int' +// CHECK-SUBSCRIPT-UAV-NEXT: CompoundStmt +// CHECK-SUBSCRIPT-UAV-NEXT: ReturnStmt +// CHECK-SUBSCRIPT-UAV-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' prefix '*' cannot overflow +// CHECK-SUBSCRIPT-UAV-NEXT: CallExpr {{.*}} 'hlsl_device element_type *' +// CHECK-SUBSCRIPT-UAV-NEXT: ImplicitCastExpr {{.*}} +// CHECK-SUBSCRIPT-UAV-NEXT: DeclRefExpr {{.*}} '' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept' +// CHECK-SUBSCRIPT-UAV-NEXT: MemberExpr {{.*}} '__hlsl_resource_t +// CHECK-SUBSCRIPT-UAV-SAME{LITERAL}: [[hlsl::resource_class( +// CHECK-SUBSCRIPT-UAV-SAME{LITERAL}: [[hlsl::raw_buffer]] +// CHECK-SUBSCRIPT-UAV-SAME{LITERAL}: [[hlsl::contained_type(element_type)]] +// CHECK-SUBSCRIPT-UAV-SAME: ' lvalue .__handle {{.*}} +// CHECK-SUBSCRIPT-UAV-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]' lvalue implicit this +// CHECK-SUBSCRIPT-UAV-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int' +// CHECK-SUBSCRIPT-UAV-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline // CHECK-NOSUBSCRIPT-NOT: CXXMethodDecl {{.*}} operator[] 'const hlsl_device element_type &(unsigned int) const' // CHECK-NOSUBSCRIPT-NOT: CXXMethodDecl {{.*}} operator[] 'hlsl_device element_type &(unsigned int)' diff --git a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl index d098e5a323ca7..d6b88e276762e 100644 --- a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl +++ b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl @@ -126,7 +126,7 @@ RESOURCE Buffer; // CHECK-NEXT: DeclRefExpr {{.*}} 'const char *' ParmVar {{.*}} 'name' 'const char *' // CHECK-NEXT: AlwaysInlineAttr -// Subsctript operators +// Subscript operators // CHECK: CXXMethodDecl {{.*}} operator[] 'const hlsl_device element_type &(unsigned int) const' // CHECK-NEXT: ParmVarDecl {{.*}} Index 'unsigned int' @@ -145,22 +145,21 @@ RESOURCE Buffer; // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int' // CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline -// CHECK-NEXT: CXXMethodDecl {{.*}} operator[] 'hlsl_device element_type &(unsigned int)' -// CHECK-NEXT: ParmVarDecl {{.*}} Index 'unsigned int' -// CHECK-NEXT: CompoundStmt -// CHECK-NEXT: ReturnStmt -// CHECK-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' prefix '*' cannot overflow -// CHECK-NEXT: CallExpr {{.*}} 'hlsl_device element_type *' -// CHECK-NEXT: ImplicitCastExpr {{.*}} -// CHECK-NEXT: DeclRefExpr {{.*}} '' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept' -// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t +// CHECK-UAV-NEXT: CXXMethodDecl {{.*}} operator[] 'hlsl_device element_type &(unsigned int)' +// CHECK-UAV-NEXT: ParmVarDecl {{.*}} Index 'unsigned int' +// CHECK-UAV-NEXT: CompoundStmt +// CHECK-UAV-NEXT: ReturnStmt +// CHECK-UAV-NEXT: UnaryOperator {{.*}} 'hlsl_device element_type' prefix '*' cannot overflow +// CHECK-UAV-NEXT: CallExpr {{.*}} 'hlsl_device element_type *' +// CHECK-UAV-NEXT: ImplicitCastExpr {{.*}} +// CHECK-UAV-NEXT: DeclRefExpr {{.*}} '' Function {{.*}} '__builtin_hlsl_resource_getpointer' 'void (...) noexcept' +// CHECK-UAV-NEXT: MemberExpr {{.*}} '__hlsl_resource_t // CHECK-UAV-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] -// CHECK-SRV-SAME{LITERAL}: [[hlsl::resource_class(SRV)]] -// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]] -// CHECK-SAME: ' lvalue .__handle {{.*}} -// CHECK-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]' lvalue implicit this -// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int' -// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline +// CHECK-UAV-SAME{LITERAL}: [[hlsl::contained_type(element_type)]] +// CHECK-UAV-SAME: ' lvalue .__handle {{.*}} +// CHECK-UAV-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]' lvalue implicit this +// CHECK-UAV-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int' +// CHECK-UAV-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline // Load method diff --git a/clang/test/SemaHLSL/BuiltIns/Buffers.hlsl b/clang/test/SemaHLSL/BuiltIns/Buffers.hlsl index 477a16a454a9c..d7c6876d3b9e3 100644 --- a/clang/test/SemaHLSL/BuiltIns/Buffers.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/Buffers.hlsl @@ -111,4 +111,8 @@ Buffer BufferErr3; void main() { (void)Buff.__handle; // expected-error {{'__handle' is a private member of 'hlsl::Buffer>'}} // expected-note@* {{implicitly declared private here}} + + // expected-error@+2 {{cannot assign to return value because function 'operator[]' returns a const value}} + // expected-note@* {{function 'operator[]' which returns const-qualified type 'vector' declared here}} + Buff[0] = 0.0; } diff --git a/clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl b/clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl index bf541f4a07da7..fbd9288590adc 100644 --- a/clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl @@ -28,4 +28,8 @@ StructuredBuffer BufferErr4; void main() { (void)Buff.__handle; // expected-error {{'__handle' is a private member of 'hlsl::StructuredBuffer>'}} // expected-note@* {{implicitly declared private here}} + + // expected-error@+2 {{cannot assign to return value because function 'operator[]' returns a const value}} + // expected-note@* {{function 'operator[]' which returns const-qualified type 'vector' declared here}} + Buff[0] = 0.0; }