@@ -1372,6 +1372,115 @@ void Parser::parseObjCSelector(SmallVector<Identifier, 4> &Names,
13721372 }
13731373}
13741374
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+
13751484bool Parser::parseNewDeclAttribute (DeclAttributes &Attributes, SourceLoc AtLoc,
13761485 DeclAttrKind DK) {
13771486 // Ok, it is a valid attribute, eat it, and then process it.
@@ -1975,7 +2084,8 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
19752084 StringRef Platform = Tok.getText ();
19762085
19772086 if (Platform != " *" &&
1978- peekToken ().isAny (tok::integer_literal, tok::floating_literal)) {
2087+ (peekToken ().isAny (tok::integer_literal, tok::floating_literal) ||
2088+ peekAvailabilityMacroName ())) {
19792089 // We have the short form of available: @available(iOS 8.0.1, *)
19802090 SmallVector<AvailabilitySpec *, 5 > Specs;
19812091 ParserStatus Status = parseAvailabilitySpecList (Specs);
0 commit comments