@@ -1372,6 +1372,115 @@ 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
+ Specs.append (VersionMatch->getSecond ().begin (),
1412
+ VersionMatch->getSecond ().end ());
1413
+
1414
+ return makeParserSuccess ();
1415
+ }
1416
+
1417
+ void Parser::parseAllAvailabilityMacroArguments () {
1418
+
1419
+ if (AvailabilityMacrosComputed) return ;
1420
+
1421
+ AvailabilityMacroMap Map;
1422
+
1423
+ SourceManager &SM = Context.SourceMgr ;
1424
+ const LangOptions &LangOpts = Context.LangOpts ;
1425
+
1426
+ for (StringRef macro: LangOpts.AvailabilityMacros ) {
1427
+
1428
+ // Create temporary parser.
1429
+ int bufferID = SM.addMemBufferCopy (macro,
1430
+ " -define-availability argument" );
1431
+ swift::ParserUnit PU (SM,
1432
+ SourceFileKind::Main, bufferID,
1433
+ LangOpts,
1434
+ TypeCheckerOptions (), " unknown" );
1435
+
1436
+ ForwardingDiagnosticConsumer PDC (Context.Diags );
1437
+ PU.getDiagnosticEngine ().addConsumer (PDC);
1438
+
1439
+ // Parse the argument.
1440
+ AvailabilityMacroDefinition ParsedMacro;
1441
+ ParserStatus Status =
1442
+ PU.getParser ().parseAvailabilityMacroDefinition (ParsedMacro);
1443
+ if (Status.isError ())
1444
+ continue ;
1445
+
1446
+ // Copy the Specs to the requesting ASTContext from the temporary context
1447
+ // that parsed the argument.
1448
+ auto SpecsCopy = SmallVector<AvailabilitySpec*, 4 >();
1449
+ for (auto *Spec : ParsedMacro.Specs )
1450
+ if (auto *PlatformVersionSpec =
1451
+ dyn_cast<PlatformVersionConstraintAvailabilitySpec>(Spec)) {
1452
+ auto SpecCopy =
1453
+ new (Context) PlatformVersionConstraintAvailabilitySpec (
1454
+ *PlatformVersionSpec);
1455
+ SpecsCopy.push_back (SpecCopy);
1456
+ }
1457
+
1458
+ ParsedMacro.Specs = SpecsCopy;
1459
+
1460
+ // Find the macro info by name.
1461
+ AvailabilityMacroVersionMap MacroDefinition;
1462
+ auto NameMatch = Map.find (ParsedMacro.Name );
1463
+ if (NameMatch != Map.end ()) {
1464
+ MacroDefinition = NameMatch->getSecond ();
1465
+ }
1466
+
1467
+ // Set the macro info by version.
1468
+ auto PreviousEntry =
1469
+ MacroDefinition.insert ({ParsedMacro.Version , ParsedMacro.Specs });
1470
+ if (!PreviousEntry.second ) {
1471
+ diagnose (PU.getParser ().PreviousLoc , diag::attr_availability_duplicate,
1472
+ ParsedMacro.Name , ParsedMacro.Version .getAsString ());
1473
+ }
1474
+
1475
+ // Save back the macro spec.
1476
+ Map.erase (ParsedMacro.Name );
1477
+ Map.insert ({ParsedMacro.Name , MacroDefinition});
1478
+ }
1479
+
1480
+ AvailabilityMacros = Map;
1481
+ AvailabilityMacrosComputed = true ;
1482
+ }
1483
+
1375
1484
bool Parser::parseNewDeclAttribute (DeclAttributes &Attributes, SourceLoc AtLoc,
1376
1485
DeclAttrKind DK) {
1377
1486
// Ok, it is a valid attribute, eat it, and then process it.
@@ -1975,7 +2084,8 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
1975
2084
StringRef Platform = Tok.getText ();
1976
2085
1977
2086
if (Platform != " *" &&
1978
- peekToken ().isAny (tok::integer_literal, tok::floating_literal)) {
2087
+ (peekToken ().isAny (tok::integer_literal, tok::floating_literal) ||
2088
+ peekAvailabilityMacroName ())) {
1979
2089
// We have the short form of available: @available(iOS 8.0.1, *)
1980
2090
SmallVector<AvailabilitySpec *, 5 > Specs;
1981
2091
ParserStatus Status = parseAvailabilitySpecList (Specs);
0 commit comments