@@ -1372,6 +1372,125 @@ void Parser::parseObjCSelector(SmallVector<Identifier, 4> &Names,
1372
1372
}
1373
1373
}
1374
1374
1375
+ bool Parser::peekAvailabilityMacroName () {
1376
+ parseAllAvailabilityMacroArguments ();
1377
+ AvailabilityMacroMap Map = AvailabilityMacros;
1378
+
1379
+ StringRef MacroName = Tok.getText ();
1380
+ return Map.find (MacroName) != Map.end ();
1381
+ }
1382
+
1383
+ ParserStatus
1384
+ Parser::parseAvailabilityMacro (SmallVectorImpl<AvailabilitySpec *> &Specs) {
1385
+ // Get the macros from the compiler arguments.
1386
+ parseAllAvailabilityMacroArguments ();
1387
+ AvailabilityMacroMap Map = AvailabilityMacros;
1388
+
1389
+ StringRef MacroName = Tok.getText ();
1390
+ auto NameMatch = Map.find (MacroName);
1391
+ if (NameMatch == Map.end ())
1392
+ return makeParserSuccess (); // No match, it could be a standard platform.
1393
+
1394
+ consumeToken ();
1395
+
1396
+ llvm::VersionTuple Version;
1397
+ SourceRange VersionRange;
1398
+ if (Tok.isAny (tok::integer_literal, tok::floating_literal)) {
1399
+ if (parseVersionTuple (Version, VersionRange,
1400
+ diag::avail_query_expected_version_number))
1401
+ return makeParserError ();
1402
+ }
1403
+
1404
+ auto VersionMatch = NameMatch->getSecond ().find (Version);
1405
+ if (VersionMatch == NameMatch->getSecond ().end ()) {
1406
+ diagnose (PreviousLoc, diag::attr_availability_unknown_version,
1407
+ Version.getAsString (), MacroName);
1408
+ return makeParserError (); // Failed to match the version, that's an error.
1409
+ }
1410
+
1411
+ // Make a copy of the specs to add the macro source location
1412
+ // for the diagnostic about the use of macros in inlinable code.
1413
+ SourceLoc MacroLoc = Tok.getLoc ();
1414
+ for (auto *Spec : VersionMatch->getSecond ())
1415
+ if (auto *PlatformVersionSpec =
1416
+ dyn_cast<PlatformVersionConstraintAvailabilitySpec>(Spec)) {
1417
+ auto SpecCopy =
1418
+ new (Context) PlatformVersionConstraintAvailabilitySpec (
1419
+ *PlatformVersionSpec);
1420
+ SpecCopy->setMacroLoc (MacroLoc);
1421
+ Specs.push_back (SpecCopy);
1422
+ }
1423
+
1424
+ return makeParserSuccess ();
1425
+ }
1426
+
1427
+ void Parser::parseAllAvailabilityMacroArguments () {
1428
+
1429
+ if (AvailabilityMacrosComputed) return ;
1430
+
1431
+ AvailabilityMacroMap Map;
1432
+
1433
+ SourceManager &SM = Context.SourceMgr ;
1434
+ const LangOptions &LangOpts = Context.LangOpts ;
1435
+
1436
+ for (StringRef macro: LangOpts.AvailabilityMacros ) {
1437
+
1438
+ // Create temporary parser.
1439
+ int bufferID = SM.addMemBufferCopy (macro,
1440
+ " -define-availability argument" );
1441
+ swift::ParserUnit PU (SM,
1442
+ SourceFileKind::Main, bufferID,
1443
+ LangOpts,
1444
+ TypeCheckerOptions (), " unknown" );
1445
+
1446
+ ForwardingDiagnosticConsumer PDC (Context.Diags );
1447
+ PU.getDiagnosticEngine ().addConsumer (PDC);
1448
+
1449
+ // Parse the argument.
1450
+ AvailabilityMacroDefinition ParsedMacro;
1451
+ ParserStatus Status =
1452
+ PU.getParser ().parseAvailabilityMacroDefinition (ParsedMacro);
1453
+ if (Status.isError ())
1454
+ continue ;
1455
+
1456
+ // Copy the Specs to the requesting ASTContext from the temporary context
1457
+ // that parsed the argument.
1458
+ auto SpecsCopy = SmallVector<AvailabilitySpec*, 4 >();
1459
+ for (auto *Spec : ParsedMacro.Specs )
1460
+ if (auto *PlatformVersionSpec =
1461
+ dyn_cast<PlatformVersionConstraintAvailabilitySpec>(Spec)) {
1462
+ auto SpecCopy =
1463
+ new (Context) PlatformVersionConstraintAvailabilitySpec (
1464
+ *PlatformVersionSpec);
1465
+ SpecsCopy.push_back (SpecCopy);
1466
+ }
1467
+
1468
+ ParsedMacro.Specs = SpecsCopy;
1469
+
1470
+ // Find the macro info by name.
1471
+ AvailabilityMacroVersionMap MacroDefinition;
1472
+ auto NameMatch = Map.find (ParsedMacro.Name );
1473
+ if (NameMatch != Map.end ()) {
1474
+ MacroDefinition = NameMatch->getSecond ();
1475
+ }
1476
+
1477
+ // Set the macro info by version.
1478
+ auto PreviousEntry =
1479
+ MacroDefinition.insert ({ParsedMacro.Version , ParsedMacro.Specs });
1480
+ if (!PreviousEntry.second ) {
1481
+ diagnose (PU.getParser ().PreviousLoc , diag::attr_availability_duplicate,
1482
+ ParsedMacro.Name , ParsedMacro.Version .getAsString ());
1483
+ }
1484
+
1485
+ // Save back the macro spec.
1486
+ Map.erase (ParsedMacro.Name );
1487
+ Map.insert ({ParsedMacro.Name , MacroDefinition});
1488
+ }
1489
+
1490
+ AvailabilityMacros = Map;
1491
+ AvailabilityMacrosComputed = true ;
1492
+ }
1493
+
1375
1494
bool Parser::parseNewDeclAttribute (DeclAttributes &Attributes, SourceLoc AtLoc,
1376
1495
DeclAttrKind DK) {
1377
1496
// Ok, it is a valid attribute, eat it, and then process it.
@@ -1975,7 +2094,8 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
1975
2094
StringRef Platform = Tok.getText ();
1976
2095
1977
2096
if (Platform != " *" &&
1978
- peekToken ().isAny (tok::integer_literal, tok::floating_literal)) {
2097
+ (peekToken ().isAny (tok::integer_literal, tok::floating_literal) ||
2098
+ peekAvailabilityMacroName ())) {
1979
2099
// We have the short form of available: @available(iOS 8.0.1, *)
1980
2100
SmallVector<AvailabilitySpec *, 5 > Specs;
1981
2101
ParserStatus Status = parseAvailabilitySpecList (Specs);
0 commit comments