string Namespace = namespace;
}
class Keyword<string name> : Spelling<name, "Keyword">;
+class Pragma<string namespace, string name> : Spelling<name, "Pragma"> {
+ string Namespace = namespace;
+}
// The GCC spelling implies GNU<name, "GNU"> and CXX11<"gnu", name> and also
// sets KnownToGCC to 1. This spelling should be used for any GCC-compatible
/// unroll: unroll loop if 'value != 0'.
/// unroll_count: unrolls loop 'value' times.
- /// FIXME: Add Pragma spelling to tablegen and
- /// use it here.
- let Spellings = [Keyword<"loop">];
+ let Spellings = [Pragma<"clang", "loop">];
/// State of the loop optimization specified by the spelling.
let Args = [EnumArgument<"Option", "OptionType",
return "disable";
}
- // FIXME: Modify pretty printer to print this pragma.
- void print(raw_ostream &OS, const PrintingPolicy &Policy) const {
- OS << "#pragma clang loop " << getOptionName(option) << "(";
+ void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const {
+ OS << getOptionName(option) << "(";
if (option == VectorizeWidth || option == InterleaveCount ||
option == UnrollCount)
OS << value;
--- /dev/null
+// RUN: %clang_cc1 -ast-print %s -o - | FileCheck %s
+
+// FIXME: A bug in ParsedAttributes causes the order of the attributes to be
+// reversed. The checks are consequently in the reverse order below.
+
+// CHECK: #pragma clang loop interleave_count(8)
+// CHECK-NEXT: #pragma clang loop vectorize_width(4)
+
+void test(int *List, int Length) {
+ int i = 0;
+#pragma clang loop vectorize_width(4)
+#pragma clang loop interleave_count(8)
+// CHECK-NEXT: while (i < Length)
+ while (i < Length) {
+ List[i] = i * 2;
+ i++;
+ }
+
+// CHECK: #pragma clang loop interleave(disable)
+// CHECK-NEXT: #pragma clang loop vectorize(enable)
+
+#pragma clang loop vectorize(enable)
+#pragma clang loop interleave(disable)
+// CHECK-NEXT: while (i - 1 < Length)
+ while (i - 1 < Length) {
+ List[i] = i * 2;
+ i++;
+ }
+
+// CHECK: #pragma clang loop interleave(enable)
+// CHECK-NEXT: #pragma clang loop vectorize(disable)
+
+#pragma clang loop vectorize(disable)
+#pragma clang loop interleave(enable)
+// CHECK-NEXT: while (i - 2 < Length)
+ while (i - 2 < Length) {
+ List[i] = i * 2;
+ i++;
+ }
+}
assert(V != "GCC" && "Given a GCC spelling, which means this hasn't been"
"flattened!");
- if (V == "CXX11")
+ if (V == "CXX11" || V == "Pragma")
NS = Spelling.getValueAsString("Namespace");
bool Unset;
K = Spelling.getValueAsBitOrUnset("KnownToGCC", Unset);
OS << "void " << R.getName() << "Attr::printPretty("
<< "raw_ostream &OS, const PrintingPolicy &Policy) const {\n";
- if (Spellings.size() == 0) {
+ if (Spellings.empty()) {
OS << "}\n\n";
return;
}
Prefix = " [[";
Suffix = "]]";
std::string Namespace = Spellings[I].nameSpace();
- if (Namespace != "") {
+ if (!Namespace.empty()) {
Spelling += Namespace;
Spelling += "::";
}
} else if (Variety == "Keyword") {
Prefix = " ";
Suffix = "";
+ } else if (Variety == "Pragma") {
+ Prefix = "#pragma ";
+ Suffix = "\n";
+ std::string Namespace = Spellings[I].nameSpace();
+ if (!Namespace.empty()) {
+ Spelling += Namespace;
+ Spelling += " ";
+ }
} else {
llvm_unreachable("Unknown attribute syntax variety!");
}
" case " << I << " : {\n"
" OS << \"" + Prefix.str() + Spelling.str();
+ if (Variety == "Pragma") {
+ OS << " \";\n";
+ OS << " printPrettyPragma(OS, Policy);\n";
+ OS << " break;\n";
+ OS << " }\n";
+ continue;
+ }
+
if (!Args.empty())
OS << "(";
if (Spelling == "availability") {
// Separate all of the attributes out into four group: generic, C++11, GNU,
// and declspecs. Then generate a big switch statement for each of them.
std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
- std::vector<Record *> Declspec, GNU;
+ std::vector<Record *> Declspec, GNU, Pragma;
std::map<std::string, std::vector<Record *>> CXX;
// Walk over the list of all attributes, and split them out based on the
GNU.push_back(R);
else if (Variety == "Declspec")
Declspec.push_back(R);
- else if (Variety == "CXX11") {
+ else if (Variety == "CXX11")
CXX[SI.nameSpace()].push_back(R);
- }
+ else if (Variety == "Pragma")
+ Pragma.push_back(R);
}
}
OS << "case AttrSyntax::Declspec:\n";
OS << " return llvm::StringSwitch<bool>(Name)\n";
GenerateHasAttrSpellingStringSwitch(Declspec, OS, "Declspec");
+ OS << "case AttrSyntax::Pragma:\n";
+ OS << " return llvm::StringSwitch<bool>(Name)\n";
+ GenerateHasAttrSpellingStringSwitch(Pragma, OS, "Pragma");
OS << "case AttrSyntax::CXX: {\n";
// C++11-style attributes are further split out based on the Scope.
for (std::map<std::string, std::vector<Record *>>::iterator I = CXX.begin(),
std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
OS << " case AT_" << I.first << ": {\n";
for (unsigned I = 0; I < Spellings.size(); ++ I) {
- OS << " if (Name == \""
- << Spellings[I].name() << "\" && "
- << "SyntaxUsed == "
- << StringSwitch<unsigned>(Spellings[I].variety())
- .Case("GNU", 0)
- .Case("CXX11", 1)
- .Case("Declspec", 2)
- .Case("Keyword", 3)
- .Default(0)
- << " && Scope == \"" << Spellings[I].nameSpace() << "\")\n"
- << " return " << I << ";\n";
+ OS << " if (Name == \"" << Spellings[I].name() << "\" && "
+ << "SyntaxUsed == "
+ << StringSwitch<unsigned>(Spellings[I].variety())
+ .Case("GNU", 0)
+ .Case("CXX11", 1)
+ .Case("Declspec", 2)
+ .Case("Keyword", 3)
+ .Case("Pragma", 4)
+ .Default(0)
+ << " && Scope == \"" << Spellings[I].nameSpace() << "\")\n"
+ << " return " << I << ";\n";
}
OS << " break;\n";
emitSourceFileHeader("Attribute name matcher", OS);
std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
- std::vector<StringMatcher::StringPair> GNU, Declspec, CXX11, Keywords;
+ std::vector<StringMatcher::StringPair> GNU, Declspec, CXX11, Keywords, Pragma;
std::set<std::string> Seen;
for (const auto *A : Attrs) {
const Record &Attr = *A;
Matches = &Declspec;
else if (Variety == "Keyword")
Matches = &Keywords;
+ else if (Variety == "Pragma")
+ Matches = &Pragma;
assert(Matches && "Unsupported spelling variety found");
StringMatcher("Name", CXX11, OS).Emit();
OS << " } else if (AttributeList::AS_Keyword == Syntax) {\n";
StringMatcher("Name", Keywords, OS).Emit();
+ OS << " } else if (AttributeList::AS_Pragma == Syntax) {\n";
+ StringMatcher("Name", Pragma, OS).Emit();
OS << " }\n";
OS << " return AttributeList::UnknownAttribute;\n"
<< "}\n";
GNU = 1 << 0,
CXX11 = 1 << 1,
Declspec = 1 << 2,
- Keyword = 1 << 3
+ Keyword = 1 << 3,
+ Pragma = 1 << 4
};
static void WriteDocumentation(const DocumentationData &Doc,
unsigned SupportedSpellings = 0;
for (const auto &I : Spellings) {
SpellingKind Kind = StringSwitch<SpellingKind>(I.variety())
- .Case("GNU", GNU)
- .Case("CXX11", CXX11)
- .Case("Declspec", Declspec)
- .Case("Keyword", Keyword);
+ .Case("GNU", GNU)
+ .Case("CXX11", CXX11)
+ .Case("Declspec", Declspec)
+ .Case("Keyword", Keyword)
+ .Case("Pragma", Pragma);
// Mask in the supported spelling.
SupportedSpellings |= Kind;
// List what spelling syntaxes the attribute supports.
OS << ".. csv-table:: Supported Syntaxes\n";
- OS << " :header: \"GNU\", \"C++11\", \"__declspec\", \"Keyword\"\n\n";
+ OS << " :header: \"GNU\", \"C++11\", \"__declspec\", \"Keyword\",";
+ OS << " \"Pragma\"\n\n";
OS << " \"";
if (SupportedSpellings & GNU) OS << "X";
OS << "\",\"";
OS << "\",\"";
if (SupportedSpellings & Keyword) OS << "X";
OS << "\"\n\n";
+ if (SupportedSpellings & Pragma) OS << "X";
+ OS << "\"\n\n";
// If the attribute is deprecated, print a message about it, and possibly
// provide a replacement attribute.