@@ -88,50 +88,52 @@ bool RootSignatureParser::parseDescriptorTableClause() {
8888 CurToken.TokKind == TokenKind::kw_UAV ||
8989 CurToken.TokKind == TokenKind::kw_Sampler) &&
9090 " Expects to only be invoked starting at given keyword" );
91- TokenKind ParamKind = CurToken.TokKind ; // retain for diagnostics
91+
92+ TokenKind ParamKind = CurToken.TokKind ;
93+
94+ if (consumeExpectedToken (TokenKind::pu_l_paren, diag::err_expected_after,
95+ CurToken.TokKind ))
96+ return true ;
9297
9398 DescriptorTableClause Clause;
94- TokenKind ExpectedRegister ;
99+ TokenKind ExpectedReg ;
95100 switch (ParamKind) {
96101 default :
97102 llvm_unreachable (" Switch for consumed token was not provided" );
98103 case TokenKind::kw_CBV:
99104 Clause.Type = ClauseType::CBuffer;
100- ExpectedRegister = TokenKind::bReg;
105+ ExpectedReg = TokenKind::bReg;
101106 break ;
102107 case TokenKind::kw_SRV:
103108 Clause.Type = ClauseType::SRV;
104- ExpectedRegister = TokenKind::tReg;
109+ ExpectedReg = TokenKind::tReg;
105110 break ;
106111 case TokenKind::kw_UAV:
107112 Clause.Type = ClauseType::UAV;
108- ExpectedRegister = TokenKind::uReg;
113+ ExpectedReg = TokenKind::uReg;
109114 break ;
110115 case TokenKind::kw_Sampler:
111116 Clause.Type = ClauseType::Sampler;
112- ExpectedRegister = TokenKind::sReg ;
117+ ExpectedReg = TokenKind::sReg ;
113118 break ;
114119 }
115120
116- if (consumeExpectedToken (TokenKind::pu_l_paren, diag::err_expected_after,
117- ParamKind))
118- return true ;
119-
120- ParsedParams Result;
121- if (parseDescriptorTableClauseParams (Result, ExpectedRegister))
121+ auto Params = parseDescriptorTableClauseParams (ExpectedReg);
122+ if (!Params.has_value ())
122123 return true ;
123124
124125 // Check mandatory parameters were provided
125- if (!Result. Register .has_value ()) {
126+ if (!Params-> Register .has_value ()) {
126127 getDiags ().Report (CurToken.TokLoc , diag::err_hlsl_rootsig_missing_param)
127- << ExpectedRegister ;
128+ << ExpectedReg ;
128129 return true ;
129130 }
130131
131- Clause.Register = *Result. Register ;
132+ Clause.Register = Params-> Register . value () ;
132133
133- if (Result.Space )
134- Clause.Space = *Result.Space ;
134+ // Fill in optional values
135+ if (Params->Space .has_value ())
136+ Clause.Space = Params->Space .value ();
135137
136138 if (consumeExpectedToken (TokenKind::pu_r_paren,
137139 diag::err_hlsl_unexpected_end_of_params,
@@ -142,56 +144,68 @@ bool RootSignatureParser::parseDescriptorTableClause() {
142144 return false ;
143145}
144146
145- bool RootSignatureParser::parseDescriptorTableClauseParams (ParsedParams &Params, TokenKind RegType) {
147+ std::optional<RootSignatureParser::ParsedClauseParams>
148+ RootSignatureParser::parseDescriptorTableClauseParams (TokenKind RegType) {
146149 assert (CurToken.TokKind == TokenKind::pu_l_paren &&
147150 " Expects to only be invoked starting at given token" );
148151
152+ // Parameter arguments (eg. `bReg`, `space`, ...) can be specified in any
153+ // order and only exactly once. Parse through as many arguments as possible
154+ // reporting an error if a duplicate is seen.
155+ ParsedClauseParams Params;
149156 do {
157+ // ( `b` | `t` | `u` | `s`) POS_INT
150158 if (tryConsumeExpectedToken (RegType)) {
151159 if (Params.Register .has_value ()) {
152160 getDiags ().Report (CurToken.TokLoc , diag::err_hlsl_rootsig_repeat_param)
153- << CurToken.TokKind ;
154- return true ;
161+ << CurToken.TokKind ;
162+ return std:: nullopt ;
155163 }
156- Register Reg;
157- if (parseRegister ( Reg))
158- return true ;
164+ auto Reg = parseRegister () ;
165+ if (! Reg. has_value ( ))
166+ return std:: nullopt ;
159167 Params.Register = Reg;
160168 }
169+
170+ // `space` `=` POS_INT
161171 if (tryConsumeExpectedToken (TokenKind::kw_space)) {
162172 if (Params.Space .has_value ()) {
163173 getDiags ().Report (CurToken.TokLoc , diag::err_hlsl_rootsig_repeat_param)
164- << CurToken.TokKind ;
165- return true ;
174+ << CurToken.TokKind ;
175+ return std:: nullopt ;
166176 }
177+
167178 if (consumeExpectedToken (TokenKind::pu_equal))
168- return true ;
169- uint32_t Space;
170- if (parseUIntParam (Space))
171- return true ;
179+ return std::nullopt ;
180+
181+ auto Space = parseUIntParam ();
182+ if (!Space.has_value ())
183+ return std::nullopt ;
172184 Params.Space = Space;
173185 }
174186 } while (tryConsumeExpectedToken (TokenKind::pu_comma));
175187
176- return false ;
188+ return Params ;
177189}
178190
179- bool RootSignatureParser::parseUIntParam (uint32_t &X ) {
191+ std::optional< uint32_t > RootSignatureParser::parseUIntParam () {
180192 assert (CurToken.TokKind == TokenKind::pu_equal &&
181193 " Expects to only be invoked starting at given keyword" );
182194 tryConsumeExpectedToken (TokenKind::pu_plus);
183- return consumeExpectedToken (TokenKind::int_literal, diag::err_expected_after,
184- CurToken.TokKind ) ||
185- handleUIntLiteral (X);
195+ if (consumeExpectedToken (TokenKind::int_literal, diag::err_expected_after,
196+ CurToken.TokKind ))
197+ return std::nullopt ;
198+ return handleUIntLiteral ();
186199}
187200
188- bool RootSignatureParser::parseRegister (Register &Register ) {
201+ std::optional<Register> RootSignatureParser::parseRegister () {
189202 assert ((CurToken.TokKind == TokenKind::bReg ||
190203 CurToken.TokKind == TokenKind::tReg ||
191204 CurToken.TokKind == TokenKind::uReg ||
192205 CurToken.TokKind == TokenKind::sReg ) &&
193206 " Expects to only be invoked starting at given keyword" );
194207
208+ Register Register;
195209 switch (CurToken.TokKind ) {
196210 default :
197211 llvm_unreachable (" Switch for consumed token was not provided" );
@@ -209,13 +223,15 @@ bool RootSignatureParser::parseRegister(Register &Register) {
209223 break ;
210224 }
211225
212- if (handleUIntLiteral (Register.Number ))
213- return true ; // propogate NumericLiteralParser error
226+ auto Number = handleUIntLiteral ();
227+ if (!Number.has_value ())
228+ return std::nullopt ; // propogate NumericLiteralParser error
214229
215- return false ;
230+ Register.Number = *Number;
231+ return Register;
216232}
217233
218- bool RootSignatureParser::handleUIntLiteral (uint32_t &X ) {
234+ std::optional< uint32_t > RootSignatureParser::handleUIntLiteral () {
219235 // Parse the numeric value and do semantic checks on its specification
220236 clang::NumericLiteralParser Literal (CurToken.NumSpelling , CurToken.TokLoc ,
221237 PP.getSourceManager (), PP.getLangOpts (),
@@ -231,11 +247,10 @@ bool RootSignatureParser::handleUIntLiteral(uint32_t &X) {
231247 PP.getDiagnostics ().Report (CurToken.TokLoc ,
232248 diag::err_hlsl_number_literal_overflow)
233249 << 0 << CurToken.NumSpelling ;
234- return true ;
250+ return std:: nullopt ;
235251 }
236252
237- X = Val.getExtValue ();
238- return false ;
253+ return Val.getExtValue ();
239254}
240255
241256bool RootSignatureParser::peekExpectedToken (TokenKind Expected) {
0 commit comments