@@ -1720,22 +1720,16 @@ void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) {
1720
1720
OS << " }\n " ;
1721
1721
}
1722
1722
1723
- // Emits the list of spellings for attributes.
1724
- void EmitClangAttrSpellingList (RecordKeeper &Records, raw_ostream &OS) {
1725
- emitSourceFileHeader (" llvm::StringSwitch code to match attributes based on "
1726
- " the target triple, T" , OS);
1727
-
1728
- std::vector<Record*> Attrs = Records.getAllDerivedDefinitions (" Attr" );
1729
-
1730
- for (auto I : Attrs) {
1731
- Record &Attr = *I;
1732
-
1723
+ static void GenerateHasAttrSpellingStringSwitch (
1724
+ const std::vector<Record *> &Attrs, raw_ostream &OS,
1725
+ const std::string &Variety = " " , const std::string &Scope = " " ) {
1726
+ for (const auto *Attr : Attrs) {
1733
1727
// It is assumed that there will be an llvm::Triple object named T within
1734
1728
// scope that can be used to determine whether the attribute exists in
1735
1729
// a given target.
1736
1730
std::string Test;
1737
- if (Attr. isSubClassOf (" TargetSpecificAttr" )) {
1738
- const Record *R = Attr. getValueAsDef (" Target" );
1731
+ if (Attr-> isSubClassOf (" TargetSpecificAttr" )) {
1732
+ const Record *R = Attr-> getValueAsDef (" Target" );
1739
1733
std::vector<std::string> Arches = R->getValueAsListOfStrings (" Arches" );
1740
1734
1741
1735
Test += " (" ;
@@ -1760,13 +1754,79 @@ void EmitClangAttrSpellingList(RecordKeeper &Records, raw_ostream &OS) {
1760
1754
}
1761
1755
Test += " )" ;
1762
1756
}
1763
- } else
1757
+
1758
+ // If this is the C++11 variety, also add in the LangOpts test.
1759
+ if (Variety == " CXX11" )
1760
+ Test += " && LangOpts.CPlusPlus11" ;
1761
+ } else if (Variety == " CXX11" )
1762
+ // C++11 mode should be checked against LangOpts, which is presumed to be
1763
+ // present in the caller.
1764
+ Test = " LangOpts.CPlusPlus11" ;
1765
+ else
1764
1766
Test = " true" ;
1765
1767
1766
- std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings (Attr);
1768
+ std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings (* Attr);
1767
1769
for (const auto &S : Spellings)
1768
- OS << " .Case(\" " << S.name () << " \" , " << Test << " )\n " ;
1770
+ if (Variety.empty () || (Variety == S.variety () &&
1771
+ (Scope.empty () || Scope == S.nameSpace ())))
1772
+ OS << " .Case(\" " << S.name () << " \" , " << Test << " )\n " ;
1773
+ }
1774
+ OS << " .Default(false);\n " ;
1775
+ }
1776
+
1777
+ // Emits the list of spellings for attributes.
1778
+ void EmitClangAttrHasAttrImpl (RecordKeeper &Records, raw_ostream &OS) {
1779
+ emitSourceFileHeader (" Code to implement the __has_attribute logic" , OS);
1780
+
1781
+ // Separate all of the attributes out into four group: generic, C++11, GNU,
1782
+ // and declspecs. Then generate a big switch statement for each of them.
1783
+ std::vector<Record *> Attrs = Records.getAllDerivedDefinitions (" Attr" );
1784
+ std::vector<Record *> Declspec, GNU;
1785
+ std::map<std::string, std::vector<Record *>> CXX;
1786
+
1787
+ // Walk over the list of all attributes, and split them out based on the
1788
+ // spelling variety.
1789
+ for (auto *R : Attrs) {
1790
+ std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings (*R);
1791
+ for (const auto &SI : Spellings) {
1792
+ std::string Variety = SI.variety ();
1793
+ if (Variety == " GNU" )
1794
+ GNU.push_back (R);
1795
+ else if (Variety == " Declspec" )
1796
+ Declspec.push_back (R);
1797
+ else if (Variety == " CXX11" ) {
1798
+ CXX[SI.nameSpace ()].push_back (R);
1799
+ }
1800
+ }
1801
+ }
1802
+
1803
+ OS << " switch (Syntax) {\n " ;
1804
+ OS << " case AttrSyntax::Generic:\n " ;
1805
+ OS << " return llvm::StringSwitch<bool>(Name)\n " ;
1806
+ GenerateHasAttrSpellingStringSwitch (Attrs, OS);
1807
+ OS << " case AttrSyntax::GNU:\n " ;
1808
+ OS << " return llvm::StringSwitch<bool>(Name)\n " ;
1809
+ GenerateHasAttrSpellingStringSwitch (GNU, OS, " GNU" );
1810
+ OS << " case AttrSyntax::Declspec:\n " ;
1811
+ OS << " return llvm::StringSwitch<bool>(Name)\n " ;
1812
+ GenerateHasAttrSpellingStringSwitch (Declspec, OS, " Declspec" );
1813
+ OS << " case AttrSyntax::CXX: {\n " ;
1814
+ // C++11-style attributes are further split out based on the Scope.
1815
+ for (std::map<std::string, std::vector<Record *>>::iterator I = CXX.begin (),
1816
+ E = CXX.end ();
1817
+ I != E; ++I) {
1818
+ if (I != CXX.begin ())
1819
+ OS << " else " ;
1820
+ if (I->first .empty ())
1821
+ OS << " if (!Scope || Scope->getName() == \"\" ) {\n " ;
1822
+ else
1823
+ OS << " if (Scope->getName() == \" " << I->first << " \" ) {\n " ;
1824
+ OS << " return llvm::StringSwitch<bool>(Name)\n " ;
1825
+ GenerateHasAttrSpellingStringSwitch (I->second , OS, " CXX11" , I->first );
1826
+ OS << " }" ;
1769
1827
}
1828
+ OS << " \n }\n " ;
1829
+ OS << " }\n " ;
1770
1830
}
1771
1831
1772
1832
void EmitClangAttrSpellingListIndex (RecordKeeper &Records, raw_ostream &OS) {
0 commit comments