python3kgae updated this revision to Diff 445162.
python3kgae added a comment.
Code cleanup and add test for error case.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D129883/new/
https://reviews.llvm.org/D129883
Files:
clang/include/clang/AST/Decl.h
clang/include/clang/AST/RecursiveASTVisitor.h
clang/include/clang/AST/TextNodeDumper.h
clang/include/clang/Basic/DeclNodes.td
clang/include/clang/Basic/TokenKinds.def
clang/include/clang/Parse/Parser.h
clang/include/clang/Sema/Sema.h
clang/lib/AST/Decl.cpp
clang/lib/AST/DeclBase.cpp
clang/lib/AST/DeclPrinter.cpp
clang/lib/AST/TextNodeDumper.cpp
clang/lib/Basic/IdentifierTable.cpp
clang/lib/Parse/ParseDecl.cpp
clang/lib/Parse/ParseHLSL.cpp
clang/lib/Parse/Parser.cpp
clang/lib/Sema/CMakeLists.txt
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaHLSL.cpp
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
clang/lib/Serialization/ASTCommon.cpp
clang/test/AST/HLSL/cbuffer_tbuffer.hlsl
clang/test/SemaHLSL/cb_error.hlsl
Index: clang/test/SemaHLSL/cb_error.hlsl
===================================================================
--- /dev/null
+++ clang/test/SemaHLSL/cb_error.hlsl
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s -verify
+
+// expected-error@+2 {{expected identifier}}
+// expected-error@+1 {{expected unqualified-id}}
+cbuffer { ... };
+// expected-error@+1 {{expected '{'}}
+cbuffer missing_definition;
+// expected-error@+1 {{expected unqualified-id}}
+int cbuffer;
+// expected-error@+1 {{expected identifier}}
+cbuffer;
+
Index: clang/test/AST/HLSL/cbuffer_tbuffer.hlsl
===================================================================
--- /dev/null
+++ clang/test/AST/HLSL/cbuffer_tbuffer.hlsl
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -ast-dump -o - %s | FileCheck %s
+
+// CHECK:HLSLBufferDecl 0x[[CB:[0-9a-f]+]] {{.*}} line:5:9 cbuffer CB
+// CHECK-NEXT:VarDecl 0x[[A:[0-9a-f]+]] {{.*}} col:9 used a 'float'
+cbuffer CB {
+ float a;
+}
+
+// CHECK:HLSLBufferDecl 0x[[TB:[0-9a-f]+]] {{.*}} line:11:9 tbuffer TB
+// CHECK-NEXT:VarDecl 0x[[B:[0-9a-f]+]] {{.*}} col:9 used b 'float'
+tbuffer TB {
+ float b;
+}
+
+float foo() {
+// CHECK: BinaryOperator 0x{{[0-9a-f]+}} <col:10, col:14> 'float' '+'
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-f]+}} <col:10> 'float' <LValueToRValue>
+// CHECK-NEXT: DeclRefExpr 0x{{[0-9a-f]+}} <col:10> 'float' lvalue Var 0x[[A]] 'a' 'float'
+// CHECK-NEXT: ImplicitCastExpr 0x{{[0-9a-f]+}} <col:14> 'float' <LValueToRValue>
+// CHECK-NEXT: DeclRefExpr 0x{{[0-9a-f]+}} <col:14> 'float' lvalue Var 0x[[B]] 'b' 'float'
+ return a + b;
+}
Index: clang/lib/Serialization/ASTCommon.cpp
===================================================================
--- clang/lib/Serialization/ASTCommon.cpp
+++ clang/lib/Serialization/ASTCommon.cpp
@@ -433,6 +433,7 @@
case Decl::LifetimeExtendedTemporary:
case Decl::RequiresExprBody:
case Decl::UnresolvedUsingIfExists:
+ case Decl::HLSLBuffer:
return false;
// These indirectly derive from Redeclarable<T> but are not actually
Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -873,6 +873,10 @@
llvm_unreachable("Translation units cannot be instantiated");
}
+Decl *TemplateDeclInstantiator::VisitHLSLBufferDecl(HLSLBufferDecl *Decl) {
+ llvm_unreachable("HLSL buffer declarations cannot be instantiated");
+}
+
Decl *
TemplateDeclInstantiator::VisitPragmaCommentDecl(PragmaCommentDecl *D) {
llvm_unreachable("pragma comment cannot be instantiated");
Index: clang/lib/Sema/SemaHLSL.cpp
===================================================================
--- /dev/null
+++ clang/lib/Sema/SemaHLSL.cpp
@@ -0,0 +1,37 @@
+//===- SemaHLSL.cpp - Semantic Analysis for HLSL constructs ---------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// This implements Semantic Analysis for HLSL constructs.
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/Sema.h"
+
+using namespace clang;
+
+Decl *Sema::ActOnStartHLSLBuffer(Scope *BufferScope, bool CBuffer,
+ SourceLocation KwLoc, IdentifierInfo *Ident,
+ SourceLocation IdentLoc,
+ SourceLocation LBrace) {
+ // For anonymous namespace, take the location of the left brace.
+ DeclContext *LexicalParent = getCurLexicalContext();
+ HLSLBufferDecl *Result = HLSLBufferDecl::Create(
+ Context, LexicalParent, CBuffer, KwLoc, Ident, IdentLoc, LBrace);
+
+ PushOnScopeChains(Result, BufferScope);
+ PushDeclContext(BufferScope, Result);
+
+ ActOnDocumentableDecl(Result);
+
+ return Result;
+}
+
+void Sema::ActOnFinishHLSLBuffer(Decl *Dcl, SourceLocation RBrace) {
+ HLSLBufferDecl *BufDecl = dyn_cast_or_null<HLSLBufferDecl>(Dcl);
+ assert(BufDecl && "Invalid parameter, expected HLSLBufferDecl");
+ BufDecl->setRBraceLoc(RBrace);
+ PopDeclContext();
+}
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -7039,6 +7039,9 @@
return true;
if (DC->isRecord())
return false;
+ if (DC->getDeclKind() == Decl::HLSLBuffer)
+ return false;
+
if (isa<RequiresExprBodyDecl>(DC))
return false;
llvm_unreachable("Unexpected context");
Index: clang/lib/Sema/CMakeLists.txt
===================================================================
--- clang/lib/Sema/CMakeLists.txt
+++ clang/lib/Sema/CMakeLists.txt
@@ -44,6 +44,7 @@
SemaExprMember.cpp
SemaExprObjC.cpp
SemaFixItUtils.cpp
+ SemaHLSL.cpp
SemaInit.cpp
SemaLambda.cpp
SemaLookup.cpp
Index: clang/lib/Parse/Parser.cpp
===================================================================
--- clang/lib/Parse/Parser.cpp
+++ clang/lib/Parse/Parser.cpp
@@ -947,6 +947,16 @@
EmptyDeclSpecAttrs);
}
+ case tok::kw_cbuffer:
+ case tok::kw_tbuffer:
+ if (getLangOpts().HLSL) {
+ SourceLocation DeclEnd;
+ ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
+ return ParseDeclaration(DeclaratorContext::File, DeclEnd, Attrs,
+ EmptyDeclSpecAttrs);
+ }
+ goto dont_know;
+
case tok::kw_static:
// Parse (then ignore) 'static' prior to a template instantiation. This is
// a GCC extension that we intentionally do not support.
Index: clang/lib/Parse/ParseHLSL.cpp
===================================================================
--- clang/lib/Parse/ParseHLSL.cpp
+++ clang/lib/Parse/ParseHLSL.cpp
@@ -13,9 +13,52 @@
#include "clang/Basic/AttributeCommonInfo.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
+#include "clang/Parse/RAIIObjectsForParser.h"
using namespace clang;
+Decl *Parser::ParseHLSLBuffer(SourceLocation &DeclEnd,
+ SourceLocation InlineLoc) {
+ assert((Tok.is(tok::kw_cbuffer) || Tok.is(tok::kw_tbuffer)) &&
+ "Not a cbuffer or tbuffer!");
+ bool IsCBuffer = Tok.is(tok::kw_cbuffer);
+ SourceLocation BufferLoc = ConsumeToken(); // eat the 'cbuffer or tbuffer'.
+
+ if (!Tok.is(tok::identifier)) {
+ Diag(Tok, diag::err_expected) << tok::identifier;
+ return nullptr;
+ }
+
+ IdentifierInfo *Identifier = Tok.getIdentifierInfo();
+ SourceLocation IdentifierLoc = ConsumeToken(); // consume identifier
+
+ ParseScope BufferScope(this, Scope::DeclScope);
+ BalancedDelimiterTracker T(*this, tok::l_brace);
+ if (T.consumeOpen()) {
+ Diag(Tok, diag::err_expected) << tok::l_brace;
+ return nullptr;
+ }
+
+ Decl *D = Actions.ActOnStartHLSLBuffer(getCurScope(), IsCBuffer, BufferLoc,
+ Identifier, IdentifierLoc,
+ T.getOpenLocation());
+
+ // FIXME: support attribute on cbuffer/tbuffer.
+
+ while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+ ParsedAttributes Attrs(AttrFactory);
+ // FIXME: support attribute on constants inside cbuffer/tbuffer.
+ ParseExternalDeclaration(Attrs);
+ }
+
+ T.consumeClose();
+ DeclEnd = T.getCloseLocation();
+ BufferScope.Exit();
+ Actions.ActOnFinishHLSLBuffer(D, DeclEnd);
+
+ return D;
+}
+
void Parser::ParseHLSLSemantics(ParsedAttributes &Attrs,
SourceLocation *EndLoc) {
assert(Tok.is(tok::colon) && "Not a HLSL Semantic");
Index: clang/lib/Parse/ParseDecl.cpp
===================================================================
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -1787,6 +1787,11 @@
}
return ParseSimpleDeclaration(Context, DeclEnd, DeclAttrs, DeclSpecAttrs,
true, nullptr, DeclSpecStart);
+
+ case tok::kw_cbuffer:
+ case tok::kw_tbuffer:
+ SingleDecl = ParseHLSLBuffer(DeclEnd);
+ break;
case tok::kw_namespace:
ProhibitAttributes(DeclAttrs);
ProhibitAttributes(DeclSpecAttrs);
Index: clang/lib/Basic/IdentifierTable.cpp
===================================================================
--- clang/lib/Basic/IdentifierTable.cpp
+++ clang/lib/Basic/IdentifierTable.cpp
@@ -109,7 +109,8 @@
KEYMSCOMPAT = 0x800000,
KEYSYCL = 0x1000000,
KEYCUDA = 0x2000000,
- KEYMAX = KEYCUDA, // The maximum key
+ KEYHLSL = 0x4000000,
+ KEYMAX = KEYHLSL, // The maximum key
KEYALLCXX = KEYCXX | KEYCXX11 | KEYCXX20,
KEYALL = (KEYMAX | (KEYMAX-1)) & ~KEYNOMS18 &
~KEYNOOPENCL // KEYNOMS18 and KEYNOOPENCL are used to exclude.
@@ -162,6 +163,8 @@
return KS_Enabled;
if (LangOpts.CUDA && (Flags & KEYCUDA))
return KS_Enabled;
+ if (LangOpts.HLSL && (Flags & KEYHLSL))
+ return KS_Enabled;
return KS_Disabled;
}
Index: clang/lib/AST/TextNodeDumper.cpp
===================================================================
--- clang/lib/AST/TextNodeDumper.cpp
+++ clang/lib/AST/TextNodeDumper.cpp
@@ -2377,3 +2377,11 @@
if (S->hasStoredFPFeatures())
printFPOptions(S->getStoredFPFeatures());
}
+
+void TextNodeDumper::VisitHLSLBufferDecl(const HLSLBufferDecl *D) {
+ if (D->isCBuffer())
+ OS << " cbuffer";
+ else
+ OS << " tbuffer";
+ dumpName(D);
+}
Index: clang/lib/AST/DeclPrinter.cpp
===================================================================
--- clang/lib/AST/DeclPrinter.cpp
+++ clang/lib/AST/DeclPrinter.cpp
@@ -108,6 +108,7 @@
void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D);
void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *TTP);
void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *NTTP);
+ void VisitHLSLBufferDecl(HLSLBufferDecl *D);
void printTemplateParameters(const TemplateParameterList *Params,
bool OmitTemplateKW = false);
@@ -467,7 +468,8 @@
isa<ObjCInterfaceDecl>(*D) ||
isa<ObjCProtocolDecl>(*D) ||
isa<ObjCCategoryImplDecl>(*D) ||
- isa<ObjCCategoryDecl>(*D))
+ isa<ObjCCategoryDecl>(*D) ||
+ isa<HLSLBufferDecl>(*D))
Terminator = nullptr;
else if (isa<EnumConstantDecl>(*D)) {
DeclContext::decl_iterator Next = D;
@@ -1658,6 +1660,22 @@
}
}
+void DeclPrinter::VisitHLSLBufferDecl(HLSLBufferDecl *D) {
+ if (D->isCBuffer()) {
+ Out << "cbuffer ";
+ } else {
+ Out << "tbuffer ";
+ }
+
+ Out << *D;
+
+ prettyPrintAttributes(D);
+
+ Out << " {\n";
+ VisitDeclContext(D);
+ Indent() << "}";
+}
+
void DeclPrinter::VisitOMPAllocateDecl(OMPAllocateDecl *D) {
Out << "#pragma omp allocate";
if (!D->varlist_empty()) {
Index: clang/lib/AST/DeclBase.cpp
===================================================================
--- clang/lib/AST/DeclBase.cpp
+++ clang/lib/AST/DeclBase.cpp
@@ -749,6 +749,7 @@
case ObjCMethod:
case ObjCProperty:
case MSProperty:
+ case HLSLBuffer:
return IDNS_Ordinary;
case Label:
return IDNS_Label;
@@ -1187,6 +1188,9 @@
if (getDeclKind() == Decl::Enum)
return !cast<EnumDecl>(this)->isScoped();
+ if (getDeclKind() == Decl::HLSLBuffer)
+ return true;
+
return getDeclKind() == Decl::LinkageSpec || getDeclKind() == Decl::Export;
}
@@ -1252,6 +1256,10 @@
// There is only one DeclContext for these entities.
return this;
+ case Decl::HLSLBuffer:
+ // Each buffer, even with the same name, is a distinct construct.
+ return this;
+
case Decl::TranslationUnit:
return static_cast<TranslationUnitDecl *>(this)->getFirstDecl();
case Decl::Namespace:
Index: clang/lib/AST/Decl.cpp
===================================================================
--- clang/lib/AST/Decl.cpp
+++ clang/lib/AST/Decl.cpp
@@ -5169,6 +5169,33 @@
return new (C, ID) EmptyDecl(nullptr, SourceLocation());
}
+HLSLBufferDecl::HLSLBufferDecl(DeclContext *DC, bool CBuffer,
+ SourceLocation KwLoc, IdentifierInfo *ID,
+ SourceLocation IDLoc, SourceLocation LBrace)
+ : NamedDecl(Decl::Kind::HLSLBuffer, DC, IDLoc, DeclarationName(ID)),
+ DeclContext(Decl::Kind::HLSLBuffer), LBraceLoc(LBrace), KwLoc(KwLoc),
+ IsCBuffer(CBuffer) {}
+
+HLSLBufferDecl *HLSLBufferDecl::Create(ASTContext &C,
+ DeclContext *LexicalParent, bool CBuffer,
+ SourceLocation KwLoc, IdentifierInfo *ID,
+ SourceLocation IDLoc,
+ SourceLocation LBrace) {
+ DeclContext *DC = C.getTranslationUnitDecl();
+ HLSLBufferDecl *Result =
+ new (C, DC) HLSLBufferDecl(DC, CBuffer, KwLoc, ID, IDLoc, LBrace);
+ if (DC != LexicalParent) {
+ Result->setLexicalDeclContext(LexicalParent);
+ }
+
+ return Result;
+}
+
+HLSLBufferDecl *HLSLBufferDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
+ return new (C, ID) HLSLBufferDecl(nullptr, false, SourceLocation(), nullptr,
+ SourceLocation(), SourceLocation());
+}
+
//===----------------------------------------------------------------------===//
// ImportDecl Implementation
//===----------------------------------------------------------------------===//
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -5913,6 +5913,12 @@
SourceLocation BuiltinLoc,
SourceLocation RParenLoc);
+ //===---------------------------- HLSL Features -------------------------===//
+ Decl *ActOnStartHLSLBuffer(Scope *BufferScope, bool CBuffer,
+ SourceLocation KwLoc, IdentifierInfo *Ident,
+ SourceLocation IdentLoc, SourceLocation LBrace);
+ void ActOnFinishHLSLBuffer(Decl *Dcl, SourceLocation RBrace);
+
//===---------------------------- C++ Features --------------------------===//
// Act on C++ namespaces
Index: clang/include/clang/Parse/Parser.h
===================================================================
--- clang/include/clang/Parse/Parser.h
+++ clang/include/clang/Parse/Parser.h
@@ -2817,6 +2817,8 @@
void ParseHLSLSemantics(ParsedAttributes &Attrs,
SourceLocation *EndLoc = nullptr);
+ Decl *ParseHLSLBuffer(SourceLocation &DeclEnd,
+ SourceLocation InlineLoc = SourceLocation());
void MaybeParseMicrosoftAttributes(ParsedAttributes &Attrs) {
if ((getLangOpts().MicrosoftExt || getLangOpts().HLSL) &&
Index: clang/include/clang/Basic/TokenKinds.def
===================================================================
--- clang/include/clang/Basic/TokenKinds.def
+++ clang/include/clang/Basic/TokenKinds.def
@@ -602,6 +602,10 @@
// CUDA/HIP function attributes
KEYWORD(__noinline__ , KEYCUDA)
+// HLSL keywords.
+KEYWORD(cbuffer , KEYHLSL)
+KEYWORD(tbuffer , KEYHLSL)
+
// OpenMP Type Traits
UNARY_EXPR_OR_TYPE_TRAIT(__builtin_omp_required_simd_align, OpenMPRequiredSimdAlign, KEYALL)
Index: clang/include/clang/Basic/DeclNodes.td
===================================================================
--- clang/include/clang/Basic/DeclNodes.td
+++ clang/include/clang/Basic/DeclNodes.td
@@ -108,4 +108,4 @@
def Empty : DeclNode<Decl>;
def RequiresExprBody : DeclNode<Decl>, DeclContext;
def LifetimeExtendedTemporary : DeclNode<Decl>;
-
+def HLSLBuffer : DeclNode<Named, "HLSLBuffer">, DeclContext;
Index: clang/include/clang/AST/TextNodeDumper.h
===================================================================
--- clang/include/clang/AST/TextNodeDumper.h
+++ clang/include/clang/AST/TextNodeDumper.h
@@ -380,6 +380,7 @@
void VisitConceptDecl(const ConceptDecl *D);
void
VisitLifetimeExtendedTemporaryDecl(const LifetimeExtendedTemporaryDecl *D);
+ void VisitHLSLBufferDecl(const HLSLBufferDecl *D);
};
} // namespace clang
Index: clang/include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- clang/include/clang/AST/RecursiveASTVisitor.h
+++ clang/include/clang/AST/RecursiveASTVisitor.h
@@ -1551,6 +1551,8 @@
DEF_TRAVERSE_DECL(EmptyDecl, {})
+DEF_TRAVERSE_DECL(HLSLBufferDecl, {})
+
DEF_TRAVERSE_DECL(LifetimeExtendedTemporaryDecl, {
TRY_TO(TraverseStmt(D->getTemporaryExpr()));
})
Index: clang/include/clang/AST/Decl.h
===================================================================
--- clang/include/clang/AST/Decl.h
+++ clang/include/clang/AST/Decl.h
@@ -4650,6 +4650,51 @@
static bool classofKind(Kind K) { return K == Empty; }
};
+/// HLSLBufferDecl - Represent a cbuffer or tbuffer declaration.
+class HLSLBufferDecl : public NamedDecl, public DeclContext {
+ /// LBraceLoc - The ending location of the source range.
+ SourceLocation LBraceLoc;
+ /// RBraceLoc - The ending location of the source range.
+ SourceLocation RBraceLoc;
+ /// KwLoc - The location of the cbuffer or tbuffer keyword.
+ SourceLocation KwLoc;
+ /// IsCBuffer - Whether the buffer is a cbuffer (and not a tbuffer).
+ bool IsCBuffer;
+
+ HLSLBufferDecl(DeclContext *DC, bool CBuffer, SourceLocation KwLoc,
+ IdentifierInfo *ID, SourceLocation IDLoc,
+ SourceLocation LBrace);
+
+public:
+ static HLSLBufferDecl *Create(ASTContext &C, DeclContext *LexicalParent,
+ bool CBuffer, SourceLocation KwLoc,
+ IdentifierInfo *ID, SourceLocation IDLoc,
+ SourceLocation LBrace);
+ static HLSLBufferDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ virtual SourceRange getSourceRange() const LLVM_READONLY {
+ return SourceRange(getLocStart(), RBraceLoc);
+ }
+ const char *getDeclKindName() const;
+ SourceLocation getLocStart() const LLVM_READONLY { return KwLoc; }
+ SourceLocation getRBraceLoc() const { return RBraceLoc; }
+ void setRBraceLoc(SourceLocation L) { RBraceLoc = L; }
+ bool isCBuffer() const { return IsCBuffer; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == HLSLBuffer; }
+ static DeclContext *castToDeclContext(const HLSLBufferDecl *D) {
+ return static_cast<DeclContext *>(const_cast<HLSLBufferDecl *>(D));
+ }
+ static HLSLBufferDecl *castFromDeclContext(const DeclContext *DC) {
+ return static_cast<HLSLBufferDecl *>(const_cast<DeclContext *>(DC));
+ }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
/// Insertion operator for diagnostics. This allows sending NamedDecl's
/// into a diagnostic with <<.
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &PD,
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits