diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -34,6 +34,7 @@ ClassTemplateDecl *PrevTemplate = nullptr; NamespaceDecl *HLSLNamespace = nullptr; llvm::StringMap Fields; + llvm::SmallVector Bases; BuiltinTypeDeclBuilder(CXXRecordDecl *R) : Record(R) { Record->startDefinition(); @@ -306,6 +307,27 @@ return *this; } + BuiltinTypeDeclBuilder &addBase(TypeDecl *Parent) { + if (Record->isCompleteDefinition()) + return *this; + TypeSourceInfo *TInfo = + HLSLNamespace->getASTContext().getTrivialTypeSourceInfo( + QualType(Parent->getTypeForDecl(), 0)); + CXXBaseSpecifier Base(SourceRange(), false, false, + AccessSpecifier::AS_public, TInfo, SourceLocation()); + Bases.emplace_back(&Base); + return *this; + } + + BuiltinTypeDeclBuilder &setBases() { + if (Record->isCompleteDefinition()) + return *this; + + Record->setBases(Bases.data(), Bases.size()); + Bases.clear(); + return *this; + } + TemplateParameterListBuilder addTemplateArgumentList(); }; @@ -336,6 +358,13 @@ return *this; } + TemplateParameterListBuilder &addTypeParameterAsBase(uint32_t I) { + if (Params.size() <= I) + return *this; + Builder.addBase(cast(Params[I])); + return *this; + } + BuiltinTypeDeclBuilder &finalizeTemplateArgs() { if (Params.empty()) return Builder; @@ -466,6 +495,20 @@ .addHandleMember(AccessSpecifier::AS_public) .completeDefinition() .Record; + // Add CBV as + // template + // struct ConstantBuffer : T { + // }; + BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "ConstantBuffer") + .startDefinition() + .addTemplateArgumentList() + .addTypeParameter("element_type") + .addTypeParameterAsBase(0) + .finalizeTemplateArgs() + .setBases() + .annotateResourceClass(HLSLResourceAttr::CBuffer, + HLSLResourceAttr::CBufferKind) + .completeDefinition(); } void HLSLExternalSemaSource::forwardDeclareHLSLTypes() { diff --git a/clang/test/AST/HLSL/CBV.hlsl b/clang/test/AST/HLSL/CBV.hlsl new file mode 100644 --- /dev/null +++ b/clang/test/AST/HLSL/CBV.hlsl @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -fsyntax-only -ast-dump %s | FileCheck %s + +// CHECK:-ClassTemplateDecl 0x{{[0-9a-f]+}} <> implicit ConstantBuffer +// CHECK-NEXT:-TemplateTypeParmDecl 0x{{[0-9a-f]+}} <> class depth 0 index 0 element_type +// CHECK-NEXT:-CXXRecordDecl 0x{{[0-9a-f]+}} <> implicit class ConstantBuffer definition +// CHECK:-public 'element_type' +// CHECK-NEXT:-FinalAttr 0x{{[0-9a-f]+}} <> Implicit final +// CHECK-NEXT:-HLSLResourceAttr 0x{{[0-9a-f]+}} <> Implicit CBuffer CBufferKind + +// CHECK:-CXXRecordDecl 0x{{[0-9a-f]+}} col:8 implicit struct S +// CHECK-NEXT:-FieldDecl 0x[[A:[0-9a-f]+]] col:11 referenced a 'float' +struct S { + float a; +}; + +// CHECK:VarDecl 0x[[CB:[0-9a-f]+]] col:19 used CB 'ConstantBuffer':'hlsl::ConstantBuffer' +ConstantBuffer CB; + +float foo() { +// CHECK:ReturnStmt 0x{{[0-9a-f]+}} +// CHECK-NEXT:-ImplicitCastExpr 0x{{[0-9a-f]+}} 'float' +// CHECK-NEXT:-MemberExpr 0x{{[0-9a-f]+}} 'float' lvalue .a 0x[[A]] +// CHECK-NEXT:-ImplicitCastExpr 0x{{[0-9a-f]+}} 'S' lvalue +// CHECK-NEXT:-DeclRefExpr 0x{{[0-9a-f]+}} 'ConstantBuffer':'hlsl::ConstantBuffer' lvalue Var 0x[[CB]] 'CB' 'ConstantBuffer':'hlsl::ConstantBuffer' + return CB.a; +} diff --git a/clang/test/SemaHLSL/BuiltIns/CBV.hlsl b/clang/test/SemaHLSL/BuiltIns/CBV.hlsl new file mode 100644 --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/CBV.hlsl @@ -0,0 +1,8 @@ +// RUN: not %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -fsyntax-only -verify %s 2>&1 | FileCheck %s + +// CHECK:error: 'error' diagnostics seen but not expected: +// CHECK-NEXT: (frontend): base specifier must name a class +// CHECK:1 error generated + +// expected-note@+1 {{in instantiation of template class 'hlsl::ConstantBuffer' requested here}} +ConstantBuffer CB;