@@ -1561,7 +1561,7 @@ getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) {
15611561// / suggests the possible attribute subject rules in a fix-it together with
15621562// / any other missing tokens.
15631563DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic (
1564- unsigned DiagID, ParsedAttr &Attribute ,
1564+ unsigned DiagID, ParsedAttributes &Attrs ,
15651565 MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) {
15661566 SourceLocation Loc = PRef.getEndOfPreviousToken ();
15671567 if (Loc.isInvalid ())
@@ -1581,25 +1581,38 @@ DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic(
15811581 SourceRange FixItRange (Loc);
15821582 if (EndPoint == MissingAttributeSubjectRulesRecoveryPoint::None) {
15831583 // Gather the subject match rules that are supported by the attribute.
1584- SmallVector<std::pair<attr::SubjectMatchRule, bool >, 4 > SubjectMatchRuleSet;
1585- Attribute.getMatchRules (PRef.getLangOpts (), SubjectMatchRuleSet);
1586- if (SubjectMatchRuleSet.empty ()) {
1584+ // Add all the possible rules initially.
1585+ llvm::BitVector IsMatchRuleAvailable (attr::SubjectMatchRule_Last + 1 , true );
1586+ // Remove the ones that are not supported by any of the attributes.
1587+ for (const ParsedAttr &Attribute : Attrs) {
1588+ SmallVector<std::pair<attr::SubjectMatchRule, bool >, 4 > MatchRules;
1589+ Attribute.getMatchRules (PRef.getLangOpts (), MatchRules);
1590+ llvm::BitVector IsSupported (attr::SubjectMatchRule_Last + 1 );
1591+ for (const auto &Rule : MatchRules) {
1592+ // Ensure that the missing rule is reported in the fix-it only when it's
1593+ // supported in the current language mode.
1594+ if (!Rule.second )
1595+ continue ;
1596+ IsSupported[Rule.first ] = true ;
1597+ }
1598+ IsMatchRuleAvailable &= IsSupported;
1599+ }
1600+ if (IsMatchRuleAvailable.count () == 0 ) {
15871601 // FIXME: We can emit a "fix-it" with a subject list placeholder when
15881602 // placeholders will be supported by the fix-its.
15891603 return Diagnostic;
15901604 }
15911605 FixIt += " any(" ;
15921606 bool NeedsComma = false ;
1593- for (const auto &I : SubjectMatchRuleSet) {
1594- // Ensure that the missing rule is reported in the fix-it only when it's
1595- // supported in the current language mode.
1596- if (!I.second )
1607+ for (unsigned I = 0 ; I <= attr::SubjectMatchRule_Last; I++) {
1608+ if (!IsMatchRuleAvailable[I])
15971609 continue ;
15981610 if (NeedsComma)
15991611 FixIt += " , " ;
16001612 else
16011613 NeedsComma = true ;
1602- FixIt += attr::getSubjectMatchRuleSpelling (I.first );
1614+ FixIt += attr::getSubjectMatchRuleSpelling (
1615+ static_cast <attr::SubjectMatchRule>(I));
16031616 }
16041617 FixIt += " )" ;
16051618 // Check if we need to remove the range
@@ -1669,22 +1682,25 @@ void Parser::HandlePragmaAttribute() {
16691682 return SkipToEnd ();
16701683 }
16711684
1672- if (Tok.isNot (tok::identifier)) {
1673- Diag (Tok, diag::err_pragma_attribute_expected_attribute_name);
1674- SkipToEnd ();
1675- return ;
1676- }
1677- IdentifierInfo *AttrName = Tok.getIdentifierInfo ();
1678- SourceLocation AttrNameLoc = ConsumeToken ();
1685+ // Parse the comma-separated list of attributes.
1686+ do {
1687+ if (Tok.isNot (tok::identifier)) {
1688+ Diag (Tok, diag::err_pragma_attribute_expected_attribute_name);
1689+ SkipToEnd ();
1690+ return ;
1691+ }
1692+ IdentifierInfo *AttrName = Tok.getIdentifierInfo ();
1693+ SourceLocation AttrNameLoc = ConsumeToken ();
16791694
1680- if (Tok.isNot (tok::l_paren))
1681- Attrs.addNew (AttrName, AttrNameLoc, nullptr , AttrNameLoc, nullptr , 0 ,
1682- ParsedAttr::AS_GNU);
1683- else
1684- ParseGNUAttributeArgs (AttrName, AttrNameLoc, Attrs, /* EndLoc=*/ nullptr ,
1685- /* ScopeName=*/ nullptr ,
1686- /* ScopeLoc=*/ SourceLocation (), ParsedAttr::AS_GNU,
1687- /* Declarator=*/ nullptr );
1695+ if (Tok.isNot (tok::l_paren))
1696+ Attrs.addNew (AttrName, AttrNameLoc, nullptr , AttrNameLoc, nullptr , 0 ,
1697+ ParsedAttr::AS_GNU);
1698+ else
1699+ ParseGNUAttributeArgs (AttrName, AttrNameLoc, Attrs, /* EndLoc=*/ nullptr ,
1700+ /* ScopeName=*/ nullptr ,
1701+ /* ScopeLoc=*/ SourceLocation (), ParsedAttr::AS_GNU,
1702+ /* Declarator=*/ nullptr );
1703+ } while (TryConsumeToken (tok::comma));
16881704
16891705 if (ExpectAndConsume (tok::r_paren))
16901706 return SkipToEnd ();
@@ -1722,26 +1738,19 @@ void Parser::HandlePragmaAttribute() {
17221738 return ;
17231739 }
17241740
1725- // Ensure that we don't have more than one attribute.
1726- if (Attrs.size () > 1 ) {
1727- SourceLocation Loc = Attrs[1 ].getLoc ();
1728- Diag (Loc, diag::err_pragma_attribute_multiple_attributes);
1729- SkipToEnd ();
1730- return ;
1731- }
1732-
1733- ParsedAttr &Attribute = *Attrs.begin ();
1734- if (!Attribute.isSupportedByPragmaAttribute ()) {
1735- Diag (PragmaLoc, diag::err_pragma_attribute_unsupported_attribute)
1736- << Attribute;
1737- SkipToEnd ();
1738- return ;
1741+ for (const ParsedAttr &Attribute : Attrs) {
1742+ if (!Attribute.isSupportedByPragmaAttribute ()) {
1743+ Diag (PragmaLoc, diag::err_pragma_attribute_unsupported_attribute)
1744+ << Attribute;
1745+ SkipToEnd ();
1746+ return ;
1747+ }
17391748 }
17401749
17411750 // Parse the subject-list.
17421751 if (!TryConsumeToken (tok::comma)) {
17431752 createExpectedAttributeSubjectRulesTokenDiagnostic (
1744- diag::err_expected, Attribute ,
1753+ diag::err_expected, Attrs ,
17451754 MissingAttributeSubjectRulesRecoveryPoint::Comma, *this )
17461755 << tok::comma;
17471756 SkipToEnd ();
@@ -1750,15 +1759,15 @@ void Parser::HandlePragmaAttribute() {
17501759
17511760 if (Tok.isNot (tok::identifier)) {
17521761 createExpectedAttributeSubjectRulesTokenDiagnostic (
1753- diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute ,
1762+ diag::err_pragma_attribute_invalid_subject_set_specifier, Attrs ,
17541763 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this );
17551764 SkipToEnd ();
17561765 return ;
17571766 }
17581767 const IdentifierInfo *II = Tok.getIdentifierInfo ();
17591768 if (!II->isStr (" apply_to" )) {
17601769 createExpectedAttributeSubjectRulesTokenDiagnostic (
1761- diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute ,
1770+ diag::err_pragma_attribute_invalid_subject_set_specifier, Attrs ,
17621771 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this );
17631772 SkipToEnd ();
17641773 return ;
@@ -1767,7 +1776,7 @@ void Parser::HandlePragmaAttribute() {
17671776
17681777 if (!TryConsumeToken (tok::equal)) {
17691778 createExpectedAttributeSubjectRulesTokenDiagnostic (
1770- diag::err_expected, Attribute ,
1779+ diag::err_expected, Attrs ,
17711780 MissingAttributeSubjectRulesRecoveryPoint::Equals, *this )
17721781 << tok::equal;
17731782 SkipToEnd ();
@@ -1797,8 +1806,10 @@ void Parser::HandlePragmaAttribute() {
17971806 if (Info->Action == PragmaAttributeInfo::Push)
17981807 Actions.ActOnPragmaAttributeEmptyPush (PragmaLoc, Info->Namespace );
17991808
1800- Actions.ActOnPragmaAttributeAttribute (Attribute, PragmaLoc,
1801- std::move (SubjectMatchRules));
1809+ for (ParsedAttr &Attribute : Attrs) {
1810+ Actions.ActOnPragmaAttributeAttribute (Attribute, PragmaLoc,
1811+ SubjectMatchRules);
1812+ }
18021813}
18031814
18041815// #pragma GCC visibility comes in two variants:
0 commit comments