@@ -1255,8 +1255,16 @@ class FormatParser {
1255
1255
Optional<StringRef> transformer;
1256
1256
};
1257
1257
1258
+ // / An iterator over the elements of a format group.
1259
+ using ElementsIterT = llvm::pointee_iterator<
1260
+ std::vector<std::unique_ptr<Element>>::const_iterator>;
1261
+
1258
1262
// / Verify the state of operation attributes within the format.
1259
1263
LogicalResult verifyAttributes (llvm::SMLoc loc);
1264
+ // / Verify the attribute elements at the back of the given stack of iterators.
1265
+ LogicalResult verifyAttributes (
1266
+ llvm::SMLoc loc,
1267
+ SmallVectorImpl<std::pair<ElementsIterT, ElementsIterT>> &iteratorStack);
1260
1268
1261
1269
// / Verify the state of operation operands within the format.
1262
1270
LogicalResult
@@ -1423,54 +1431,60 @@ LogicalResult FormatParser::verifyAttributes(llvm::SMLoc loc) {
1423
1431
std::vector<std::unique_ptr<Element>>::const_iterator>;
1424
1432
SmallVector<std::pair<ElementsIterT, ElementsIterT>, 1 > iteratorStack;
1425
1433
iteratorStack.emplace_back (fmt.elements .begin (), fmt.elements .end ());
1426
- while (!iteratorStack.empty ()) {
1427
- auto &stackIt = iteratorStack.back ();
1428
- ElementsIterT &it = stackIt.first , e = stackIt.second ;
1429
- while (it != e) {
1430
- Element *element = &*(it++);
1431
-
1432
- // Traverse into optional groups.
1433
- if (auto *optional = dyn_cast<OptionalElement>(element)) {
1434
- auto elements = optional->getElements ();
1435
- iteratorStack.emplace_back (elements.begin (), elements.end ());
1436
- break ;
1437
- }
1434
+ while (!iteratorStack.empty ())
1435
+ if (failed (verifyAttributes (loc, iteratorStack)))
1436
+ return failure ();
1437
+ return success ();
1438
+ }
1439
+ // / Verify the attribute elements at the back of the given stack of iterators.
1440
+ LogicalResult FormatParser::verifyAttributes (
1441
+ llvm::SMLoc loc,
1442
+ SmallVectorImpl<std::pair<ElementsIterT, ElementsIterT>> &iteratorStack) {
1443
+ auto &stackIt = iteratorStack.back ();
1444
+ ElementsIterT &it = stackIt.first , e = stackIt.second ;
1445
+ while (it != e) {
1446
+ Element *element = &*(it++);
1447
+
1448
+ // Traverse into optional groups.
1449
+ if (auto *optional = dyn_cast<OptionalElement>(element)) {
1450
+ auto elements = optional->getElements ();
1451
+ iteratorStack.emplace_back (elements.begin (), elements.end ());
1452
+ return success ();
1453
+ }
1454
+
1455
+ // We are checking for an attribute element followed by a `:`, so there is
1456
+ // no need to check the end.
1457
+ if (it == e && iteratorStack.size () == 1 )
1458
+ break ;
1459
+
1460
+ // Check for an attribute with a constant type builder, followed by a `:`.
1461
+ auto *prevAttr = dyn_cast<AttributeVariable>(element);
1462
+ if (!prevAttr || prevAttr->getTypeBuilder ())
1463
+ continue ;
1438
1464
1439
- // We are checking for an attribute element followed by a `:`, so there is
1440
- // no need to check the end.
1441
- if (it == e && iteratorStack.size () == 1 )
1442
- break ;
1443
-
1444
- // Check for an attribute with a constant type builder, followed by a `:`.
1445
- auto *prevAttr = dyn_cast<AttributeVariable>(element);
1446
- if (!prevAttr || prevAttr->getTypeBuilder ())
1447
- continue ;
1448
-
1449
- // Check the next iterator within the stack for literal elements.
1450
- for (auto &nextItPair : iteratorStack) {
1451
- ElementsIterT nextIt = nextItPair.first , nextE = nextItPair.second ;
1452
- for (; nextIt != nextE; ++nextIt) {
1453
- // Skip any trailing optional groups or attribute dictionaries.
1454
- if (isa<AttrDictDirective>(*nextIt) || isa<OptionalElement>(*nextIt))
1455
- continue ;
1456
-
1457
- // We are only interested in `:` literals.
1458
- auto *literal = dyn_cast<LiteralElement>(&*nextIt);
1459
- if (!literal || literal->getLiteral () != " :" )
1460
- break ;
1461
-
1462
- // TODO: Use the ___location of the literal element itself.
1463
- return emitError (
1464
- loc, llvm::formatv (" format ambiguity caused by `:` literal found "
1465
- " after attribute `{0}` which does not have "
1466
- " a buildable type" ,
1467
- prevAttr->getVar ()->name ));
1468
- }
1465
+ // Check the next iterator within the stack for literal elements.
1466
+ for (auto &nextItPair : iteratorStack) {
1467
+ ElementsIterT nextIt = nextItPair.first , nextE = nextItPair.second ;
1468
+ for (; nextIt != nextE; ++nextIt) {
1469
+ // Skip any trailing optional groups or attribute dictionaries.
1470
+ if (isa<AttrDictDirective>(*nextIt) || isa<OptionalElement>(*nextIt))
1471
+ continue ;
1472
+
1473
+ // We are only interested in `:` literals.
1474
+ auto *literal = dyn_cast<LiteralElement>(&*nextIt);
1475
+ if (!literal || literal->getLiteral () != " :" )
1476
+ break ;
1477
+
1478
+ // TODO: Use the ___location of the literal element itself.
1479
+ return emitError (
1480
+ loc, llvm::formatv (" format ambiguity caused by `:` literal found "
1481
+ " after attribute `{0}` which does not have "
1482
+ " a buildable type" ,
1483
+ prevAttr->getVar ()->name ));
1469
1484
}
1470
1485
}
1471
- if (it == e)
1472
- iteratorStack.pop_back ();
1473
1486
}
1487
+ iteratorStack.pop_back ();
1474
1488
return success ();
1475
1489
}
1476
1490
0 commit comments