@@ -186,6 +186,30 @@ const PassPipelineInfo *mlir::PassPipelineInfo::lookup(StringRef pipelineArg) {
186
186
// PassOptions
187
187
// ===----------------------------------------------------------------------===//
188
188
189
+ // / Attempt to find the next occurance of character 'c' in the string starting
190
+ // / from the `index`-th position , omitting any occurances that appear within
191
+ // / intervening ranges or literals.
192
+ static size_t findChar (StringRef str, size_t index, char c) {
193
+ for (size_t i = index, e = str.size (); i < e; ++i) {
194
+ if (str[i] == c)
195
+ return i;
196
+ // Check for various range characters.
197
+ if (str[i] == ' {' )
198
+ i = findChar (str, i + 1 , ' }' );
199
+ else if (str[i] == ' (' )
200
+ i = findChar (str, i + 1 , ' )' );
201
+ else if (str[i] == ' [' )
202
+ i = findChar (str, i + 1 , ' ]' );
203
+ else if (str[i] == ' \" ' )
204
+ i = str.find_first_of (' \" ' , i + 1 );
205
+ else if (str[i] == ' \' ' )
206
+ i = str.find_first_of (' \' ' , i + 1 );
207
+ if (i == StringRef::npos)
208
+ return StringRef::npos;
209
+ }
210
+ return StringRef::npos;
211
+ }
212
+
189
213
// / Extract an argument from 'options' and update it to point after the arg.
190
214
// / Returns the cleaned argument string.
191
215
static StringRef extractArgAndUpdateOptions (StringRef &options,
@@ -194,47 +218,37 @@ static StringRef extractArgAndUpdateOptions(StringRef &options,
194
218
options = options.drop_front (argSize).ltrim ();
195
219
196
220
// Early exit if there's no escape sequence.
197
- if (str.size () <= 2 )
221
+ if (str.size () <= 1 )
198
222
return str;
199
223
200
224
const auto escapePairs = {std::make_pair (' \' ' , ' \' ' ),
201
- std::make_pair (' "' , ' "' ), std::make_pair ( ' { ' , ' } ' ) };
225
+ std::make_pair (' "' , ' "' )};
202
226
for (const auto &escape : escapePairs) {
203
227
if (str.front () == escape.first && str.back () == escape.second ) {
204
228
// Drop the escape characters and trim.
205
- str = str.drop_front ().drop_back ().trim ();
206
229
// Don't process additional escape sequences.
207
- break ;
230
+ return str. drop_front (). drop_back (). trim () ;
208
231
}
209
232
}
210
233
234
+ // Arguments may be wrapped in `{...}`. Unlike the quotation markers that
235
+ // denote literals, we respect scoping here. The outer `{...}` should not
236
+ // be stripped in cases such as "arg={...},{...}", which can be used to denote
237
+ // lists of nested option structs.
238
+ if (str.front () == ' {' ) {
239
+ unsigned match = findChar (str, 1 , ' }' );
240
+ if (match == str.size () - 1 )
241
+ str = str.drop_front ().drop_back ().trim ();
242
+ }
243
+
211
244
return str;
212
245
}
213
246
214
247
LogicalResult detail::pass_options::parseCommaSeparatedList (
215
248
llvm::cl::Option &opt, StringRef argName, StringRef optionStr,
216
249
function_ref<LogicalResult(StringRef)> elementParseFn) {
217
- // Functor used for finding a character in a string, and skipping over
218
- // various "range" characters.
219
- llvm::unique_function<size_t (StringRef, size_t , char )> findChar =
220
- [&](StringRef str, size_t index, char c) -> size_t {
221
- for (size_t i = index, e = str.size (); i < e; ++i) {
222
- if (str[i] == c)
223
- return i;
224
- // Check for various range characters.
225
- if (str[i] == ' {' )
226
- i = findChar (str, i + 1 , ' }' );
227
- else if (str[i] == ' (' )
228
- i = findChar (str, i + 1 , ' )' );
229
- else if (str[i] == ' [' )
230
- i = findChar (str, i + 1 , ' ]' );
231
- else if (str[i] == ' \" ' )
232
- i = str.find_first_of (' \" ' , i + 1 );
233
- else if (str[i] == ' \' ' )
234
- i = str.find_first_of (' \' ' , i + 1 );
235
- }
236
- return StringRef::npos;
237
- };
250
+ if (optionStr.empty ())
251
+ return success ();
238
252
239
253
size_t nextElePos = findChar (optionStr, 0 , ' ,' );
240
254
while (nextElePos != StringRef::npos) {
0 commit comments