Skip to content

[HLSL][RootSignature] Correct RootSignatureParser to use correct SourceLocation in diagnostics #147084

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jul 8, 2025
22 changes: 10 additions & 12 deletions clang/include/clang/Lex/LexHLSLRootSignature.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,17 @@ struct RootSignatureToken {

Kind TokKind = Kind::invalid;

// Retain the SouceLocation of the token for diagnostics
clang::SourceLocation TokLoc;
// Retain the location offset of the token in the Signature
// string
uint32_t LocOffset;

// Retain spelling of an numeric constant to be parsed later
StringRef NumSpelling;

// Constructors
RootSignatureToken(clang::SourceLocation TokLoc) : TokLoc(TokLoc) {}
RootSignatureToken(Kind TokKind, clang::SourceLocation TokLoc)
: TokKind(TokKind), TokLoc(TokLoc) {}
RootSignatureToken(uint32_t LocOffset) : LocOffset(LocOffset) {}
RootSignatureToken(Kind TokKind, uint32_t LocOffset)
: TokKind(TokKind), LocOffset(LocOffset) {}
};

inline const DiagnosticBuilder &
Expand All @@ -61,8 +62,7 @@ operator<<(const DiagnosticBuilder &DB, const RootSignatureToken::Kind Kind) {

class RootSignatureLexer {
public:
RootSignatureLexer(StringRef Signature, clang::SourceLocation SourceLoc)
: Buffer(Signature), SourceLoc(SourceLoc) {}
RootSignatureLexer(StringRef Signature) : Buffer(Signature) {}

/// Consumes and returns the next token.
RootSignatureToken consumeToken();
Expand All @@ -76,23 +76,21 @@ class RootSignatureLexer {
}

private:
// Internal buffer to iterate over
// Internal buffer state
StringRef Buffer;
uint32_t LocOffset = 0;

// Current peek state
std::optional<RootSignatureToken> NextToken = std::nullopt;

// Passed down parameters from Sema
clang::SourceLocation SourceLoc;

/// Consumes the buffer and returns the lexed token.
RootSignatureToken lexToken();

/// Advance the buffer by the specified number of characters.
/// Updates the SourceLocation appropriately.
void advanceBuffer(unsigned NumCharacters = 1) {
Buffer = Buffer.drop_front(NumCharacters);
SourceLoc = SourceLoc.getLocWithOffset(NumCharacters);
LocOffset += NumCharacters;
}
};

Expand Down
20 changes: 16 additions & 4 deletions clang/include/clang/Parse/ParseHLSLRootSignature.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#ifndef LLVM_CLANG_PARSE_PARSEHLSLROOTSIGNATURE_H
#define LLVM_CLANG_PARSE_PARSEHLSLROOTSIGNATURE_H

#include "clang/AST/Expr.h"
#include "clang/Basic/DiagnosticParse.h"
#include "clang/Lex/LexHLSLRootSignature.h"
#include "clang/Lex/Preprocessor.h"
Expand All @@ -29,7 +30,7 @@ class RootSignatureParser {
public:
RootSignatureParser(llvm::dxbc::RootSignatureVersion Version,
SmallVector<llvm::hlsl::rootsig::RootElement> &Elements,
RootSignatureLexer &Lexer, clang::Preprocessor &PP);
StringLiteral *Signature, Preprocessor &PP);

/// Consumes tokens from the Lexer and constructs the in-memory
/// representations of the RootElements. Tokens are consumed until an
Expand Down Expand Up @@ -187,12 +188,23 @@ class RootSignatureParser {
bool tryConsumeExpectedToken(RootSignatureToken::Kind Expected);
bool tryConsumeExpectedToken(ArrayRef<RootSignatureToken::Kind> Expected);

/// Convert the token's offset in the signature string to its SourceLocation
///
/// This allows to currently retrieve the location for multi-token
/// StringLiterals
SourceLocation getTokenLocation(RootSignatureToken Tok);

/// Construct a diagnostics at the location of the current token
DiagnosticBuilder reportDiag(unsigned DiagID) {
return getDiags().Report(getTokenLocation(CurToken), DiagID);
}

private:
llvm::dxbc::RootSignatureVersion Version;
SmallVector<llvm::hlsl::rootsig::RootElement> &Elements;
RootSignatureLexer &Lexer;

clang::Preprocessor &PP;
StringLiteral *Signature;
RootSignatureLexer Lexer;
Preprocessor &PP;

RootSignatureToken CurToken;
};
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/Lex/LexHLSLRootSignature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ RootSignatureToken RootSignatureLexer::lexToken() {
advanceBuffer(Buffer.take_while(isspace).size());

if (isEndOfBuffer())
return RootSignatureToken(TokenKind::end_of_stream, SourceLoc);
return RootSignatureToken(TokenKind::end_of_stream, LocOffset);

// Record where this token is in the text for usage in parser diagnostics
RootSignatureToken Result(SourceLoc);
RootSignatureToken Result(LocOffset);

char C = Buffer.front();

Expand Down Expand Up @@ -62,7 +62,7 @@ RootSignatureToken RootSignatureLexer::lexToken() {

// All following tokens require at least one additional character
if (Buffer.size() <= 1) {
Result = RootSignatureToken(TokenKind::invalid, SourceLoc);
Result = RootSignatureToken(TokenKind::invalid, LocOffset);
return Result;
}

Expand Down
10 changes: 3 additions & 7 deletions clang/lib/Parse/ParseDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4944,20 +4944,16 @@ void Parser::ParseHLSLRootSignatureAttributeArgs(ParsedAttributes &Attrs) {
}

// Construct our identifier
StringRef Signature = StrLiteral.value()->getString();
StringLiteral *Signature = StrLiteral.value();
auto [DeclIdent, Found] =
Actions.HLSL().ActOnStartRootSignatureDecl(Signature);
Actions.HLSL().ActOnStartRootSignatureDecl(Signature->getString());
// If we haven't found an already defined DeclIdent then parse the root
// signature string and construct the in-memory elements
if (!Found) {
// Offset location 1 to account for '"'
SourceLocation SignatureLoc =
StrLiteral.value()->getExprLoc().getLocWithOffset(1);
// Invoke the root signature parser to construct the in-memory constructs
hlsl::RootSignatureLexer Lexer(Signature, SignatureLoc);
SmallVector<llvm::hlsl::rootsig::RootElement> RootElements;
hlsl::RootSignatureParser Parser(getLangOpts().HLSLRootSigVer, RootElements,
Lexer, PP);
Signature, PP);
if (Parser.parse()) {
T.consumeClose();
return;
Expand Down
Loading
Loading