xref: /minix3/external/bsd/llvm/dist/clang/utils/TableGen/ClangAttrEmitter.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===- ClangAttrEmitter.cpp - Generate Clang attribute handling =-*- C++ -*--=//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // These tablegen backends emit Clang attribute processing code
11f4a2713aSLionel Sambuc //
12f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
13f4a2713aSLionel Sambuc 
14f4a2713aSLionel Sambuc #include "llvm/ADT/SmallString.h"
15*0a6a1f1dSLionel Sambuc #include "llvm/ADT/STLExtras.h"
16f4a2713aSLionel Sambuc #include "llvm/ADT/SmallSet.h"
17*0a6a1f1dSLionel Sambuc #include "llvm/ADT/StringExtras.h"
18*0a6a1f1dSLionel Sambuc #include "llvm/ADT/StringSwitch.h"
19*0a6a1f1dSLionel Sambuc #include "llvm/TableGen/Error.h"
20f4a2713aSLionel Sambuc #include "llvm/TableGen/Record.h"
21f4a2713aSLionel Sambuc #include "llvm/TableGen/StringMatcher.h"
22f4a2713aSLionel Sambuc #include "llvm/TableGen/TableGenBackend.h"
23f4a2713aSLionel Sambuc #include <algorithm>
24f4a2713aSLionel Sambuc #include <cctype>
25*0a6a1f1dSLionel Sambuc #include <memory>
26*0a6a1f1dSLionel Sambuc #include <set>
27*0a6a1f1dSLionel Sambuc #include <sstream>
28f4a2713aSLionel Sambuc 
29f4a2713aSLionel Sambuc using namespace llvm;
30f4a2713aSLionel Sambuc 
31*0a6a1f1dSLionel Sambuc class FlattenedSpelling {
32*0a6a1f1dSLionel Sambuc   std::string V, N, NS;
33*0a6a1f1dSLionel Sambuc   bool K;
34f4a2713aSLionel Sambuc 
35*0a6a1f1dSLionel Sambuc public:
FlattenedSpelling(const std::string & Variety,const std::string & Name,const std::string & Namespace,bool KnownToGCC)36*0a6a1f1dSLionel Sambuc   FlattenedSpelling(const std::string &Variety, const std::string &Name,
37*0a6a1f1dSLionel Sambuc                     const std::string &Namespace, bool KnownToGCC) :
38*0a6a1f1dSLionel Sambuc     V(Variety), N(Name), NS(Namespace), K(KnownToGCC) {}
FlattenedSpelling(const Record & Spelling)39*0a6a1f1dSLionel Sambuc   explicit FlattenedSpelling(const Record &Spelling) :
40*0a6a1f1dSLionel Sambuc     V(Spelling.getValueAsString("Variety")),
41*0a6a1f1dSLionel Sambuc     N(Spelling.getValueAsString("Name")) {
42f4a2713aSLionel Sambuc 
43*0a6a1f1dSLionel Sambuc     assert(V != "GCC" && "Given a GCC spelling, which means this hasn't been"
44*0a6a1f1dSLionel Sambuc            "flattened!");
45*0a6a1f1dSLionel Sambuc     if (V == "CXX11" || V == "Pragma")
46*0a6a1f1dSLionel Sambuc       NS = Spelling.getValueAsString("Namespace");
47*0a6a1f1dSLionel Sambuc     bool Unset;
48*0a6a1f1dSLionel Sambuc     K = Spelling.getValueAsBitOrUnset("KnownToGCC", Unset);
49f4a2713aSLionel Sambuc   }
50f4a2713aSLionel Sambuc 
variety() const51*0a6a1f1dSLionel Sambuc   const std::string &variety() const { return V; }
name() const52*0a6a1f1dSLionel Sambuc   const std::string &name() const { return N; }
nameSpace() const53*0a6a1f1dSLionel Sambuc   const std::string &nameSpace() const { return NS; }
knownToGCC() const54*0a6a1f1dSLionel Sambuc   bool knownToGCC() const { return K; }
55*0a6a1f1dSLionel Sambuc };
56*0a6a1f1dSLionel Sambuc 
GetFlattenedSpellings(const Record & Attr)57*0a6a1f1dSLionel Sambuc std::vector<FlattenedSpelling> GetFlattenedSpellings(const Record &Attr) {
58*0a6a1f1dSLionel Sambuc   std::vector<Record *> Spellings = Attr.getValueAsListOfDefs("Spellings");
59*0a6a1f1dSLionel Sambuc   std::vector<FlattenedSpelling> Ret;
60*0a6a1f1dSLionel Sambuc 
61*0a6a1f1dSLionel Sambuc   for (const auto &Spelling : Spellings) {
62*0a6a1f1dSLionel Sambuc     if (Spelling->getValueAsString("Variety") == "GCC") {
63*0a6a1f1dSLionel Sambuc       // Gin up two new spelling objects to add into the list.
64*0a6a1f1dSLionel Sambuc       Ret.push_back(FlattenedSpelling("GNU", Spelling->getValueAsString("Name"),
65*0a6a1f1dSLionel Sambuc                                       "", true));
66*0a6a1f1dSLionel Sambuc       Ret.push_back(FlattenedSpelling(
67*0a6a1f1dSLionel Sambuc           "CXX11", Spelling->getValueAsString("Name"), "gnu", true));
68*0a6a1f1dSLionel Sambuc     } else
69*0a6a1f1dSLionel Sambuc       Ret.push_back(FlattenedSpelling(*Spelling));
70*0a6a1f1dSLionel Sambuc   }
71*0a6a1f1dSLionel Sambuc 
72*0a6a1f1dSLionel Sambuc   return Ret;
73f4a2713aSLionel Sambuc }
74f4a2713aSLionel Sambuc 
ReadPCHRecord(StringRef type)75f4a2713aSLionel Sambuc static std::string ReadPCHRecord(StringRef type) {
76f4a2713aSLionel Sambuc   return StringSwitch<std::string>(type)
77f4a2713aSLionel Sambuc     .EndsWith("Decl *", "GetLocalDeclAs<"
78f4a2713aSLionel Sambuc               + std::string(type, 0, type.size()-1) + ">(F, Record[Idx++])")
79f4a2713aSLionel Sambuc     .Case("TypeSourceInfo *", "GetTypeSourceInfo(F, Record, Idx)")
80f4a2713aSLionel Sambuc     .Case("Expr *", "ReadExpr(F)")
81f4a2713aSLionel Sambuc     .Case("IdentifierInfo *", "GetIdentifierInfo(F, Record, Idx)")
82f4a2713aSLionel Sambuc     .Default("Record[Idx++]");
83f4a2713aSLionel Sambuc }
84f4a2713aSLionel Sambuc 
85f4a2713aSLionel Sambuc // Assumes that the way to get the value is SA->getname()
WritePCHRecord(StringRef type,StringRef name)86f4a2713aSLionel Sambuc static std::string WritePCHRecord(StringRef type, StringRef name) {
87f4a2713aSLionel Sambuc   return StringSwitch<std::string>(type)
88f4a2713aSLionel Sambuc     .EndsWith("Decl *", "AddDeclRef(" + std::string(name) +
89f4a2713aSLionel Sambuc                         ", Record);\n")
90f4a2713aSLionel Sambuc     .Case("TypeSourceInfo *",
91f4a2713aSLionel Sambuc           "AddTypeSourceInfo(" + std::string(name) + ", Record);\n")
92f4a2713aSLionel Sambuc     .Case("Expr *", "AddStmt(" + std::string(name) + ");\n")
93f4a2713aSLionel Sambuc     .Case("IdentifierInfo *",
94f4a2713aSLionel Sambuc           "AddIdentifierRef(" + std::string(name) + ", Record);\n")
95f4a2713aSLionel Sambuc     .Default("Record.push_back(" + std::string(name) + ");\n");
96f4a2713aSLionel Sambuc }
97f4a2713aSLionel Sambuc 
98f4a2713aSLionel Sambuc // Normalize attribute name by removing leading and trailing
99f4a2713aSLionel Sambuc // underscores. For example, __foo, foo__, __foo__ would
100f4a2713aSLionel Sambuc // become foo.
NormalizeAttrName(StringRef AttrName)101f4a2713aSLionel Sambuc static StringRef NormalizeAttrName(StringRef AttrName) {
102f4a2713aSLionel Sambuc   if (AttrName.startswith("__"))
103f4a2713aSLionel Sambuc     AttrName = AttrName.substr(2, AttrName.size());
104f4a2713aSLionel Sambuc 
105f4a2713aSLionel Sambuc   if (AttrName.endswith("__"))
106f4a2713aSLionel Sambuc     AttrName = AttrName.substr(0, AttrName.size() - 2);
107f4a2713aSLionel Sambuc 
108f4a2713aSLionel Sambuc   return AttrName;
109f4a2713aSLionel Sambuc }
110f4a2713aSLionel Sambuc 
111*0a6a1f1dSLionel Sambuc // Normalize the name by removing any and all leading and trailing underscores.
112*0a6a1f1dSLionel Sambuc // This is different from NormalizeAttrName in that it also handles names like
113*0a6a1f1dSLionel Sambuc // _pascal and __pascal.
NormalizeNameForSpellingComparison(StringRef Name)114*0a6a1f1dSLionel Sambuc static StringRef NormalizeNameForSpellingComparison(StringRef Name) {
115*0a6a1f1dSLionel Sambuc   while (Name.startswith("_"))
116*0a6a1f1dSLionel Sambuc     Name = Name.substr(1, Name.size());
117*0a6a1f1dSLionel Sambuc   while (Name.endswith("_"))
118*0a6a1f1dSLionel Sambuc     Name = Name.substr(0, Name.size() - 1);
119*0a6a1f1dSLionel Sambuc   return Name;
120*0a6a1f1dSLionel Sambuc }
121*0a6a1f1dSLionel Sambuc 
122f4a2713aSLionel Sambuc // Normalize attribute spelling only if the spelling has both leading
123f4a2713aSLionel Sambuc // and trailing underscores. For example, __ms_struct__ will be
124f4a2713aSLionel Sambuc // normalized to "ms_struct"; __cdecl will remain intact.
NormalizeAttrSpelling(StringRef AttrSpelling)125f4a2713aSLionel Sambuc static StringRef NormalizeAttrSpelling(StringRef AttrSpelling) {
126f4a2713aSLionel Sambuc   if (AttrSpelling.startswith("__") && AttrSpelling.endswith("__")) {
127f4a2713aSLionel Sambuc     AttrSpelling = AttrSpelling.substr(2, AttrSpelling.size() - 4);
128f4a2713aSLionel Sambuc   }
129f4a2713aSLionel Sambuc 
130f4a2713aSLionel Sambuc   return AttrSpelling;
131f4a2713aSLionel Sambuc }
132f4a2713aSLionel Sambuc 
133*0a6a1f1dSLionel Sambuc typedef std::vector<std::pair<std::string, const Record *>> ParsedAttrMap;
134*0a6a1f1dSLionel Sambuc 
getParsedAttrList(const RecordKeeper & Records,ParsedAttrMap * Dupes=nullptr)135*0a6a1f1dSLionel Sambuc static ParsedAttrMap getParsedAttrList(const RecordKeeper &Records,
136*0a6a1f1dSLionel Sambuc                                        ParsedAttrMap *Dupes = nullptr) {
137*0a6a1f1dSLionel Sambuc   std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
138*0a6a1f1dSLionel Sambuc   std::set<std::string> Seen;
139*0a6a1f1dSLionel Sambuc   ParsedAttrMap R;
140*0a6a1f1dSLionel Sambuc   for (const auto *Attr : Attrs) {
141*0a6a1f1dSLionel Sambuc     if (Attr->getValueAsBit("SemaHandler")) {
142*0a6a1f1dSLionel Sambuc       std::string AN;
143*0a6a1f1dSLionel Sambuc       if (Attr->isSubClassOf("TargetSpecificAttr") &&
144*0a6a1f1dSLionel Sambuc           !Attr->isValueUnset("ParseKind")) {
145*0a6a1f1dSLionel Sambuc         AN = Attr->getValueAsString("ParseKind");
146*0a6a1f1dSLionel Sambuc 
147*0a6a1f1dSLionel Sambuc         // If this attribute has already been handled, it does not need to be
148*0a6a1f1dSLionel Sambuc         // handled again.
149*0a6a1f1dSLionel Sambuc         if (Seen.find(AN) != Seen.end()) {
150*0a6a1f1dSLionel Sambuc           if (Dupes)
151*0a6a1f1dSLionel Sambuc             Dupes->push_back(std::make_pair(AN, Attr));
152*0a6a1f1dSLionel Sambuc           continue;
153*0a6a1f1dSLionel Sambuc         }
154*0a6a1f1dSLionel Sambuc         Seen.insert(AN);
155*0a6a1f1dSLionel Sambuc       } else
156*0a6a1f1dSLionel Sambuc         AN = NormalizeAttrName(Attr->getName()).str();
157*0a6a1f1dSLionel Sambuc 
158*0a6a1f1dSLionel Sambuc       R.push_back(std::make_pair(AN, Attr));
159*0a6a1f1dSLionel Sambuc     }
160*0a6a1f1dSLionel Sambuc   }
161*0a6a1f1dSLionel Sambuc   return R;
162*0a6a1f1dSLionel Sambuc }
163*0a6a1f1dSLionel Sambuc 
164f4a2713aSLionel Sambuc namespace {
165f4a2713aSLionel Sambuc   class Argument {
166f4a2713aSLionel Sambuc     std::string lowerName, upperName;
167f4a2713aSLionel Sambuc     StringRef attrName;
168f4a2713aSLionel Sambuc     bool isOpt;
169f4a2713aSLionel Sambuc 
170f4a2713aSLionel Sambuc   public:
Argument(const Record & Arg,StringRef Attr)171*0a6a1f1dSLionel Sambuc     Argument(const Record &Arg, StringRef Attr)
172f4a2713aSLionel Sambuc       : lowerName(Arg.getValueAsString("Name")), upperName(lowerName),
173f4a2713aSLionel Sambuc         attrName(Attr), isOpt(false) {
174f4a2713aSLionel Sambuc       if (!lowerName.empty()) {
175f4a2713aSLionel Sambuc         lowerName[0] = std::tolower(lowerName[0]);
176f4a2713aSLionel Sambuc         upperName[0] = std::toupper(upperName[0]);
177f4a2713aSLionel Sambuc       }
178f4a2713aSLionel Sambuc     }
~Argument()179f4a2713aSLionel Sambuc     virtual ~Argument() {}
180f4a2713aSLionel Sambuc 
getLowerName() const181f4a2713aSLionel Sambuc     StringRef getLowerName() const { return lowerName; }
getUpperName() const182f4a2713aSLionel Sambuc     StringRef getUpperName() const { return upperName; }
getAttrName() const183f4a2713aSLionel Sambuc     StringRef getAttrName() const { return attrName; }
184f4a2713aSLionel Sambuc 
isOptional() const185f4a2713aSLionel Sambuc     bool isOptional() const { return isOpt; }
setOptional(bool set)186f4a2713aSLionel Sambuc     void setOptional(bool set) { isOpt = set; }
187f4a2713aSLionel Sambuc 
188f4a2713aSLionel Sambuc     // These functions print the argument contents formatted in different ways.
189f4a2713aSLionel Sambuc     virtual void writeAccessors(raw_ostream &OS) const = 0;
writeAccessorDefinitions(raw_ostream & OS) const190f4a2713aSLionel Sambuc     virtual void writeAccessorDefinitions(raw_ostream &OS) const {}
writeASTVisitorTraversal(raw_ostream & OS) const191*0a6a1f1dSLionel Sambuc     virtual void writeASTVisitorTraversal(raw_ostream &OS) const {}
192f4a2713aSLionel Sambuc     virtual void writeCloneArgs(raw_ostream &OS) const = 0;
193f4a2713aSLionel Sambuc     virtual void writeTemplateInstantiationArgs(raw_ostream &OS) const = 0;
writeTemplateInstantiation(raw_ostream & OS) const194f4a2713aSLionel Sambuc     virtual void writeTemplateInstantiation(raw_ostream &OS) const {}
writeCtorBody(raw_ostream & OS) const195f4a2713aSLionel Sambuc     virtual void writeCtorBody(raw_ostream &OS) const {}
196f4a2713aSLionel Sambuc     virtual void writeCtorInitializers(raw_ostream &OS) const = 0;
197f4a2713aSLionel Sambuc     virtual void writeCtorDefaultInitializers(raw_ostream &OS) const = 0;
198f4a2713aSLionel Sambuc     virtual void writeCtorParameters(raw_ostream &OS) const = 0;
199f4a2713aSLionel Sambuc     virtual void writeDeclarations(raw_ostream &OS) const = 0;
200f4a2713aSLionel Sambuc     virtual void writePCHReadArgs(raw_ostream &OS) const = 0;
201f4a2713aSLionel Sambuc     virtual void writePCHReadDecls(raw_ostream &OS) const = 0;
202f4a2713aSLionel Sambuc     virtual void writePCHWrite(raw_ostream &OS) const = 0;
203f4a2713aSLionel Sambuc     virtual void writeValue(raw_ostream &OS) const = 0;
204f4a2713aSLionel Sambuc     virtual void writeDump(raw_ostream &OS) const = 0;
writeDumpChildren(raw_ostream & OS) const205f4a2713aSLionel Sambuc     virtual void writeDumpChildren(raw_ostream &OS) const {}
writeHasChildren(raw_ostream & OS) const206f4a2713aSLionel Sambuc     virtual void writeHasChildren(raw_ostream &OS) const { OS << "false"; }
207f4a2713aSLionel Sambuc 
isEnumArg() const208f4a2713aSLionel Sambuc     virtual bool isEnumArg() const { return false; }
isVariadicEnumArg() const209f4a2713aSLionel Sambuc     virtual bool isVariadicEnumArg() const { return false; }
isVariadic() const210*0a6a1f1dSLionel Sambuc     virtual bool isVariadic() const { return false; }
211*0a6a1f1dSLionel Sambuc 
writeImplicitCtorArgs(raw_ostream & OS) const212*0a6a1f1dSLionel Sambuc     virtual void writeImplicitCtorArgs(raw_ostream &OS) const {
213*0a6a1f1dSLionel Sambuc       OS << getUpperName();
214*0a6a1f1dSLionel Sambuc     }
215f4a2713aSLionel Sambuc   };
216f4a2713aSLionel Sambuc 
217f4a2713aSLionel Sambuc   class SimpleArgument : public Argument {
218f4a2713aSLionel Sambuc     std::string type;
219f4a2713aSLionel Sambuc 
220f4a2713aSLionel Sambuc   public:
SimpleArgument(const Record & Arg,StringRef Attr,std::string T)221*0a6a1f1dSLionel Sambuc     SimpleArgument(const Record &Arg, StringRef Attr, std::string T)
222f4a2713aSLionel Sambuc       : Argument(Arg, Attr), type(T)
223f4a2713aSLionel Sambuc     {}
224f4a2713aSLionel Sambuc 
getType() const225f4a2713aSLionel Sambuc     std::string getType() const { return type; }
226f4a2713aSLionel Sambuc 
writeAccessors(raw_ostream & OS) const227*0a6a1f1dSLionel Sambuc     void writeAccessors(raw_ostream &OS) const override {
228f4a2713aSLionel Sambuc       OS << "  " << type << " get" << getUpperName() << "() const {\n";
229f4a2713aSLionel Sambuc       OS << "    return " << getLowerName() << ";\n";
230f4a2713aSLionel Sambuc       OS << "  }";
231f4a2713aSLionel Sambuc     }
writeCloneArgs(raw_ostream & OS) const232*0a6a1f1dSLionel Sambuc     void writeCloneArgs(raw_ostream &OS) const override {
233f4a2713aSLionel Sambuc       OS << getLowerName();
234f4a2713aSLionel Sambuc     }
writeTemplateInstantiationArgs(raw_ostream & OS) const235*0a6a1f1dSLionel Sambuc     void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
236f4a2713aSLionel Sambuc       OS << "A->get" << getUpperName() << "()";
237f4a2713aSLionel Sambuc     }
writeCtorInitializers(raw_ostream & OS) const238*0a6a1f1dSLionel Sambuc     void writeCtorInitializers(raw_ostream &OS) const override {
239f4a2713aSLionel Sambuc       OS << getLowerName() << "(" << getUpperName() << ")";
240f4a2713aSLionel Sambuc     }
writeCtorDefaultInitializers(raw_ostream & OS) const241*0a6a1f1dSLionel Sambuc     void writeCtorDefaultInitializers(raw_ostream &OS) const override {
242f4a2713aSLionel Sambuc       OS << getLowerName() << "()";
243f4a2713aSLionel Sambuc     }
writeCtorParameters(raw_ostream & OS) const244*0a6a1f1dSLionel Sambuc     void writeCtorParameters(raw_ostream &OS) const override {
245f4a2713aSLionel Sambuc       OS << type << " " << getUpperName();
246f4a2713aSLionel Sambuc     }
writeDeclarations(raw_ostream & OS) const247*0a6a1f1dSLionel Sambuc     void writeDeclarations(raw_ostream &OS) const override {
248f4a2713aSLionel Sambuc       OS << type << " " << getLowerName() << ";";
249f4a2713aSLionel Sambuc     }
writePCHReadDecls(raw_ostream & OS) const250*0a6a1f1dSLionel Sambuc     void writePCHReadDecls(raw_ostream &OS) const override {
251f4a2713aSLionel Sambuc       std::string read = ReadPCHRecord(type);
252f4a2713aSLionel Sambuc       OS << "    " << type << " " << getLowerName() << " = " << read << ";\n";
253f4a2713aSLionel Sambuc     }
writePCHReadArgs(raw_ostream & OS) const254*0a6a1f1dSLionel Sambuc     void writePCHReadArgs(raw_ostream &OS) const override {
255f4a2713aSLionel Sambuc       OS << getLowerName();
256f4a2713aSLionel Sambuc     }
writePCHWrite(raw_ostream & OS) const257*0a6a1f1dSLionel Sambuc     void writePCHWrite(raw_ostream &OS) const override {
258f4a2713aSLionel Sambuc       OS << "    " << WritePCHRecord(type, "SA->get" +
259f4a2713aSLionel Sambuc                                            std::string(getUpperName()) + "()");
260f4a2713aSLionel Sambuc     }
writeValue(raw_ostream & OS) const261*0a6a1f1dSLionel Sambuc     void writeValue(raw_ostream &OS) const override {
262f4a2713aSLionel Sambuc       if (type == "FunctionDecl *") {
263f4a2713aSLionel Sambuc         OS << "\" << get" << getUpperName()
264f4a2713aSLionel Sambuc            << "()->getNameInfo().getAsString() << \"";
265f4a2713aSLionel Sambuc       } else if (type == "IdentifierInfo *") {
266f4a2713aSLionel Sambuc         OS << "\" << get" << getUpperName() << "()->getName() << \"";
267f4a2713aSLionel Sambuc       } else if (type == "TypeSourceInfo *") {
268f4a2713aSLionel Sambuc         OS << "\" << get" << getUpperName() << "().getAsString() << \"";
269f4a2713aSLionel Sambuc       } else {
270f4a2713aSLionel Sambuc         OS << "\" << get" << getUpperName() << "() << \"";
271f4a2713aSLionel Sambuc       }
272f4a2713aSLionel Sambuc     }
writeDump(raw_ostream & OS) const273*0a6a1f1dSLionel Sambuc     void writeDump(raw_ostream &OS) const override {
274f4a2713aSLionel Sambuc       if (type == "FunctionDecl *") {
275f4a2713aSLionel Sambuc         OS << "    OS << \" \";\n";
276f4a2713aSLionel Sambuc         OS << "    dumpBareDeclRef(SA->get" << getUpperName() << "());\n";
277f4a2713aSLionel Sambuc       } else if (type == "IdentifierInfo *") {
278f4a2713aSLionel Sambuc         OS << "    OS << \" \" << SA->get" << getUpperName()
279f4a2713aSLionel Sambuc            << "()->getName();\n";
280f4a2713aSLionel Sambuc       } else if (type == "TypeSourceInfo *") {
281f4a2713aSLionel Sambuc         OS << "    OS << \" \" << SA->get" << getUpperName()
282f4a2713aSLionel Sambuc            << "().getAsString();\n";
283f4a2713aSLionel Sambuc       } else if (type == "bool") {
284f4a2713aSLionel Sambuc         OS << "    if (SA->get" << getUpperName() << "()) OS << \" "
285f4a2713aSLionel Sambuc            << getUpperName() << "\";\n";
286f4a2713aSLionel Sambuc       } else if (type == "int" || type == "unsigned") {
287f4a2713aSLionel Sambuc         OS << "    OS << \" \" << SA->get" << getUpperName() << "();\n";
288f4a2713aSLionel Sambuc       } else {
289f4a2713aSLionel Sambuc         llvm_unreachable("Unknown SimpleArgument type!");
290f4a2713aSLionel Sambuc       }
291f4a2713aSLionel Sambuc     }
292f4a2713aSLionel Sambuc   };
293f4a2713aSLionel Sambuc 
294*0a6a1f1dSLionel Sambuc   class DefaultSimpleArgument : public SimpleArgument {
295*0a6a1f1dSLionel Sambuc     int64_t Default;
296*0a6a1f1dSLionel Sambuc 
297*0a6a1f1dSLionel Sambuc   public:
DefaultSimpleArgument(const Record & Arg,StringRef Attr,std::string T,int64_t Default)298*0a6a1f1dSLionel Sambuc     DefaultSimpleArgument(const Record &Arg, StringRef Attr,
299*0a6a1f1dSLionel Sambuc                           std::string T, int64_t Default)
300*0a6a1f1dSLionel Sambuc       : SimpleArgument(Arg, Attr, T), Default(Default) {}
301*0a6a1f1dSLionel Sambuc 
writeAccessors(raw_ostream & OS) const302*0a6a1f1dSLionel Sambuc     void writeAccessors(raw_ostream &OS) const override {
303*0a6a1f1dSLionel Sambuc       SimpleArgument::writeAccessors(OS);
304*0a6a1f1dSLionel Sambuc 
305*0a6a1f1dSLionel Sambuc       OS << "\n\n  static const " << getType() << " Default" << getUpperName()
306*0a6a1f1dSLionel Sambuc          << " = " << Default << ";";
307*0a6a1f1dSLionel Sambuc     }
308*0a6a1f1dSLionel Sambuc   };
309*0a6a1f1dSLionel Sambuc 
310f4a2713aSLionel Sambuc   class StringArgument : public Argument {
311f4a2713aSLionel Sambuc   public:
StringArgument(const Record & Arg,StringRef Attr)312*0a6a1f1dSLionel Sambuc     StringArgument(const Record &Arg, StringRef Attr)
313f4a2713aSLionel Sambuc       : Argument(Arg, Attr)
314f4a2713aSLionel Sambuc     {}
315f4a2713aSLionel Sambuc 
writeAccessors(raw_ostream & OS) const316*0a6a1f1dSLionel Sambuc     void writeAccessors(raw_ostream &OS) const override {
317f4a2713aSLionel Sambuc       OS << "  llvm::StringRef get" << getUpperName() << "() const {\n";
318f4a2713aSLionel Sambuc       OS << "    return llvm::StringRef(" << getLowerName() << ", "
319f4a2713aSLionel Sambuc          << getLowerName() << "Length);\n";
320f4a2713aSLionel Sambuc       OS << "  }\n";
321f4a2713aSLionel Sambuc       OS << "  unsigned get" << getUpperName() << "Length() const {\n";
322f4a2713aSLionel Sambuc       OS << "    return " << getLowerName() << "Length;\n";
323f4a2713aSLionel Sambuc       OS << "  }\n";
324f4a2713aSLionel Sambuc       OS << "  void set" << getUpperName()
325f4a2713aSLionel Sambuc          << "(ASTContext &C, llvm::StringRef S) {\n";
326f4a2713aSLionel Sambuc       OS << "    " << getLowerName() << "Length = S.size();\n";
327f4a2713aSLionel Sambuc       OS << "    this->" << getLowerName() << " = new (C, 1) char ["
328f4a2713aSLionel Sambuc          << getLowerName() << "Length];\n";
329f4a2713aSLionel Sambuc       OS << "    std::memcpy(this->" << getLowerName() << ", S.data(), "
330f4a2713aSLionel Sambuc          << getLowerName() << "Length);\n";
331f4a2713aSLionel Sambuc       OS << "  }";
332f4a2713aSLionel Sambuc     }
writeCloneArgs(raw_ostream & OS) const333*0a6a1f1dSLionel Sambuc     void writeCloneArgs(raw_ostream &OS) const override {
334f4a2713aSLionel Sambuc       OS << "get" << getUpperName() << "()";
335f4a2713aSLionel Sambuc     }
writeTemplateInstantiationArgs(raw_ostream & OS) const336*0a6a1f1dSLionel Sambuc     void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
337f4a2713aSLionel Sambuc       OS << "A->get" << getUpperName() << "()";
338f4a2713aSLionel Sambuc     }
writeCtorBody(raw_ostream & OS) const339*0a6a1f1dSLionel Sambuc     void writeCtorBody(raw_ostream &OS) const override {
340f4a2713aSLionel Sambuc       OS << "      std::memcpy(" << getLowerName() << ", " << getUpperName()
341f4a2713aSLionel Sambuc          << ".data(), " << getLowerName() << "Length);";
342f4a2713aSLionel Sambuc     }
writeCtorInitializers(raw_ostream & OS) const343*0a6a1f1dSLionel Sambuc     void writeCtorInitializers(raw_ostream &OS) const override {
344f4a2713aSLionel Sambuc       OS << getLowerName() << "Length(" << getUpperName() << ".size()),"
345f4a2713aSLionel Sambuc          << getLowerName() << "(new (Ctx, 1) char[" << getLowerName()
346f4a2713aSLionel Sambuc          << "Length])";
347f4a2713aSLionel Sambuc     }
writeCtorDefaultInitializers(raw_ostream & OS) const348*0a6a1f1dSLionel Sambuc     void writeCtorDefaultInitializers(raw_ostream &OS) const override {
349f4a2713aSLionel Sambuc       OS << getLowerName() << "Length(0)," << getLowerName() << "(0)";
350f4a2713aSLionel Sambuc     }
writeCtorParameters(raw_ostream & OS) const351*0a6a1f1dSLionel Sambuc     void writeCtorParameters(raw_ostream &OS) const override {
352f4a2713aSLionel Sambuc       OS << "llvm::StringRef " << getUpperName();
353f4a2713aSLionel Sambuc     }
writeDeclarations(raw_ostream & OS) const354*0a6a1f1dSLionel Sambuc     void writeDeclarations(raw_ostream &OS) const override {
355f4a2713aSLionel Sambuc       OS << "unsigned " << getLowerName() << "Length;\n";
356f4a2713aSLionel Sambuc       OS << "char *" << getLowerName() << ";";
357f4a2713aSLionel Sambuc     }
writePCHReadDecls(raw_ostream & OS) const358*0a6a1f1dSLionel Sambuc     void writePCHReadDecls(raw_ostream &OS) const override {
359f4a2713aSLionel Sambuc       OS << "    std::string " << getLowerName()
360f4a2713aSLionel Sambuc          << "= ReadString(Record, Idx);\n";
361f4a2713aSLionel Sambuc     }
writePCHReadArgs(raw_ostream & OS) const362*0a6a1f1dSLionel Sambuc     void writePCHReadArgs(raw_ostream &OS) const override {
363f4a2713aSLionel Sambuc       OS << getLowerName();
364f4a2713aSLionel Sambuc     }
writePCHWrite(raw_ostream & OS) const365*0a6a1f1dSLionel Sambuc     void writePCHWrite(raw_ostream &OS) const override {
366f4a2713aSLionel Sambuc       OS << "    AddString(SA->get" << getUpperName() << "(), Record);\n";
367f4a2713aSLionel Sambuc     }
writeValue(raw_ostream & OS) const368*0a6a1f1dSLionel Sambuc     void writeValue(raw_ostream &OS) const override {
369f4a2713aSLionel Sambuc       OS << "\\\"\" << get" << getUpperName() << "() << \"\\\"";
370f4a2713aSLionel Sambuc     }
writeDump(raw_ostream & OS) const371*0a6a1f1dSLionel Sambuc     void writeDump(raw_ostream &OS) const override {
372f4a2713aSLionel Sambuc       OS << "    OS << \" \\\"\" << SA->get" << getUpperName()
373f4a2713aSLionel Sambuc          << "() << \"\\\"\";\n";
374f4a2713aSLionel Sambuc     }
375f4a2713aSLionel Sambuc   };
376f4a2713aSLionel Sambuc 
377f4a2713aSLionel Sambuc   class AlignedArgument : public Argument {
378f4a2713aSLionel Sambuc   public:
AlignedArgument(const Record & Arg,StringRef Attr)379*0a6a1f1dSLionel Sambuc     AlignedArgument(const Record &Arg, StringRef Attr)
380f4a2713aSLionel Sambuc       : Argument(Arg, Attr)
381f4a2713aSLionel Sambuc     {}
382f4a2713aSLionel Sambuc 
writeAccessors(raw_ostream & OS) const383*0a6a1f1dSLionel Sambuc     void writeAccessors(raw_ostream &OS) const override {
384f4a2713aSLionel Sambuc       OS << "  bool is" << getUpperName() << "Dependent() const;\n";
385f4a2713aSLionel Sambuc 
386f4a2713aSLionel Sambuc       OS << "  unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n";
387f4a2713aSLionel Sambuc 
388f4a2713aSLionel Sambuc       OS << "  bool is" << getUpperName() << "Expr() const {\n";
389f4a2713aSLionel Sambuc       OS << "    return is" << getLowerName() << "Expr;\n";
390f4a2713aSLionel Sambuc       OS << "  }\n";
391f4a2713aSLionel Sambuc 
392f4a2713aSLionel Sambuc       OS << "  Expr *get" << getUpperName() << "Expr() const {\n";
393f4a2713aSLionel Sambuc       OS << "    assert(is" << getLowerName() << "Expr);\n";
394f4a2713aSLionel Sambuc       OS << "    return " << getLowerName() << "Expr;\n";
395f4a2713aSLionel Sambuc       OS << "  }\n";
396f4a2713aSLionel Sambuc 
397f4a2713aSLionel Sambuc       OS << "  TypeSourceInfo *get" << getUpperName() << "Type() const {\n";
398f4a2713aSLionel Sambuc       OS << "    assert(!is" << getLowerName() << "Expr);\n";
399f4a2713aSLionel Sambuc       OS << "    return " << getLowerName() << "Type;\n";
400f4a2713aSLionel Sambuc       OS << "  }";
401f4a2713aSLionel Sambuc     }
writeAccessorDefinitions(raw_ostream & OS) const402*0a6a1f1dSLionel Sambuc     void writeAccessorDefinitions(raw_ostream &OS) const override {
403f4a2713aSLionel Sambuc       OS << "bool " << getAttrName() << "Attr::is" << getUpperName()
404f4a2713aSLionel Sambuc          << "Dependent() const {\n";
405f4a2713aSLionel Sambuc       OS << "  if (is" << getLowerName() << "Expr)\n";
406f4a2713aSLionel Sambuc       OS << "    return " << getLowerName() << "Expr && (" << getLowerName()
407f4a2713aSLionel Sambuc          << "Expr->isValueDependent() || " << getLowerName()
408f4a2713aSLionel Sambuc          << "Expr->isTypeDependent());\n";
409f4a2713aSLionel Sambuc       OS << "  else\n";
410f4a2713aSLionel Sambuc       OS << "    return " << getLowerName()
411f4a2713aSLionel Sambuc          << "Type->getType()->isDependentType();\n";
412f4a2713aSLionel Sambuc       OS << "}\n";
413f4a2713aSLionel Sambuc 
414f4a2713aSLionel Sambuc       // FIXME: Do not do the calculation here
415f4a2713aSLionel Sambuc       // FIXME: Handle types correctly
416f4a2713aSLionel Sambuc       // A null pointer means maximum alignment
417f4a2713aSLionel Sambuc       // FIXME: Load the platform-specific maximum alignment, rather than
418f4a2713aSLionel Sambuc       //        16, the x86 max.
419f4a2713aSLionel Sambuc       OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName()
420f4a2713aSLionel Sambuc          << "(ASTContext &Ctx) const {\n";
421f4a2713aSLionel Sambuc       OS << "  assert(!is" << getUpperName() << "Dependent());\n";
422f4a2713aSLionel Sambuc       OS << "  if (is" << getLowerName() << "Expr)\n";
423f4a2713aSLionel Sambuc       OS << "    return (" << getLowerName() << "Expr ? " << getLowerName()
424f4a2713aSLionel Sambuc          << "Expr->EvaluateKnownConstInt(Ctx).getZExtValue() : 16)"
425f4a2713aSLionel Sambuc          << "* Ctx.getCharWidth();\n";
426f4a2713aSLionel Sambuc       OS << "  else\n";
427f4a2713aSLionel Sambuc       OS << "    return 0; // FIXME\n";
428f4a2713aSLionel Sambuc       OS << "}\n";
429f4a2713aSLionel Sambuc     }
writeCloneArgs(raw_ostream & OS) const430*0a6a1f1dSLionel Sambuc     void writeCloneArgs(raw_ostream &OS) const override {
431f4a2713aSLionel Sambuc       OS << "is" << getLowerName() << "Expr, is" << getLowerName()
432f4a2713aSLionel Sambuc          << "Expr ? static_cast<void*>(" << getLowerName()
433f4a2713aSLionel Sambuc          << "Expr) : " << getLowerName()
434f4a2713aSLionel Sambuc          << "Type";
435f4a2713aSLionel Sambuc     }
writeTemplateInstantiationArgs(raw_ostream & OS) const436*0a6a1f1dSLionel Sambuc     void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
437f4a2713aSLionel Sambuc       // FIXME: move the definition in Sema::InstantiateAttrs to here.
438f4a2713aSLionel Sambuc       // In the meantime, aligned attributes are cloned.
439f4a2713aSLionel Sambuc     }
writeCtorBody(raw_ostream & OS) const440*0a6a1f1dSLionel Sambuc     void writeCtorBody(raw_ostream &OS) const override {
441f4a2713aSLionel Sambuc       OS << "    if (is" << getLowerName() << "Expr)\n";
442f4a2713aSLionel Sambuc       OS << "       " << getLowerName() << "Expr = reinterpret_cast<Expr *>("
443f4a2713aSLionel Sambuc          << getUpperName() << ");\n";
444f4a2713aSLionel Sambuc       OS << "    else\n";
445f4a2713aSLionel Sambuc       OS << "       " << getLowerName()
446f4a2713aSLionel Sambuc          << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName()
447f4a2713aSLionel Sambuc          << ");";
448f4a2713aSLionel Sambuc     }
writeCtorInitializers(raw_ostream & OS) const449*0a6a1f1dSLionel Sambuc     void writeCtorInitializers(raw_ostream &OS) const override {
450f4a2713aSLionel Sambuc       OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)";
451f4a2713aSLionel Sambuc     }
writeCtorDefaultInitializers(raw_ostream & OS) const452*0a6a1f1dSLionel Sambuc     void writeCtorDefaultInitializers(raw_ostream &OS) const override {
453f4a2713aSLionel Sambuc       OS << "is" << getLowerName() << "Expr(false)";
454f4a2713aSLionel Sambuc     }
writeCtorParameters(raw_ostream & OS) const455*0a6a1f1dSLionel Sambuc     void writeCtorParameters(raw_ostream &OS) const override {
456f4a2713aSLionel Sambuc       OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName();
457f4a2713aSLionel Sambuc     }
writeImplicitCtorArgs(raw_ostream & OS) const458*0a6a1f1dSLionel Sambuc     void writeImplicitCtorArgs(raw_ostream &OS) const override {
459*0a6a1f1dSLionel Sambuc       OS << "Is" << getUpperName() << "Expr, " << getUpperName();
460*0a6a1f1dSLionel Sambuc     }
writeDeclarations(raw_ostream & OS) const461*0a6a1f1dSLionel Sambuc     void writeDeclarations(raw_ostream &OS) const override {
462f4a2713aSLionel Sambuc       OS << "bool is" << getLowerName() << "Expr;\n";
463f4a2713aSLionel Sambuc       OS << "union {\n";
464f4a2713aSLionel Sambuc       OS << "Expr *" << getLowerName() << "Expr;\n";
465f4a2713aSLionel Sambuc       OS << "TypeSourceInfo *" << getLowerName() << "Type;\n";
466f4a2713aSLionel Sambuc       OS << "};";
467f4a2713aSLionel Sambuc     }
writePCHReadArgs(raw_ostream & OS) const468*0a6a1f1dSLionel Sambuc     void writePCHReadArgs(raw_ostream &OS) const override {
469f4a2713aSLionel Sambuc       OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr";
470f4a2713aSLionel Sambuc     }
writePCHReadDecls(raw_ostream & OS) const471*0a6a1f1dSLionel Sambuc     void writePCHReadDecls(raw_ostream &OS) const override {
472f4a2713aSLionel Sambuc       OS << "    bool is" << getLowerName() << "Expr = Record[Idx++];\n";
473f4a2713aSLionel Sambuc       OS << "    void *" << getLowerName() << "Ptr;\n";
474f4a2713aSLionel Sambuc       OS << "    if (is" << getLowerName() << "Expr)\n";
475f4a2713aSLionel Sambuc       OS << "      " << getLowerName() << "Ptr = ReadExpr(F);\n";
476f4a2713aSLionel Sambuc       OS << "    else\n";
477f4a2713aSLionel Sambuc       OS << "      " << getLowerName()
478f4a2713aSLionel Sambuc          << "Ptr = GetTypeSourceInfo(F, Record, Idx);\n";
479f4a2713aSLionel Sambuc     }
writePCHWrite(raw_ostream & OS) const480*0a6a1f1dSLionel Sambuc     void writePCHWrite(raw_ostream &OS) const override {
481f4a2713aSLionel Sambuc       OS << "    Record.push_back(SA->is" << getUpperName() << "Expr());\n";
482f4a2713aSLionel Sambuc       OS << "    if (SA->is" << getUpperName() << "Expr())\n";
483f4a2713aSLionel Sambuc       OS << "      AddStmt(SA->get" << getUpperName() << "Expr());\n";
484f4a2713aSLionel Sambuc       OS << "    else\n";
485f4a2713aSLionel Sambuc       OS << "      AddTypeSourceInfo(SA->get" << getUpperName()
486f4a2713aSLionel Sambuc          << "Type(), Record);\n";
487f4a2713aSLionel Sambuc     }
writeValue(raw_ostream & OS) const488*0a6a1f1dSLionel Sambuc     void writeValue(raw_ostream &OS) const override {
489*0a6a1f1dSLionel Sambuc       OS << "\";\n";
490*0a6a1f1dSLionel Sambuc       // The aligned attribute argument expression is optional.
491*0a6a1f1dSLionel Sambuc       OS << "    if (is" << getLowerName() << "Expr && "
492*0a6a1f1dSLionel Sambuc          << getLowerName() << "Expr)\n";
493*0a6a1f1dSLionel Sambuc       OS << "      " << getLowerName() << "Expr->printPretty(OS, 0, Policy);\n";
494*0a6a1f1dSLionel Sambuc       OS << "    OS << \"";
495f4a2713aSLionel Sambuc     }
writeDump(raw_ostream & OS) const496*0a6a1f1dSLionel Sambuc     void writeDump(raw_ostream &OS) const override {
497f4a2713aSLionel Sambuc     }
writeDumpChildren(raw_ostream & OS) const498*0a6a1f1dSLionel Sambuc     void writeDumpChildren(raw_ostream &OS) const override {
499*0a6a1f1dSLionel Sambuc       OS << "    if (SA->is" << getUpperName() << "Expr())\n";
500f4a2713aSLionel Sambuc       OS << "      dumpStmt(SA->get" << getUpperName() << "Expr());\n";
501*0a6a1f1dSLionel Sambuc       OS << "    else\n";
502f4a2713aSLionel Sambuc       OS << "      dumpType(SA->get" << getUpperName()
503f4a2713aSLionel Sambuc          << "Type()->getType());\n";
504f4a2713aSLionel Sambuc     }
writeHasChildren(raw_ostream & OS) const505*0a6a1f1dSLionel Sambuc     void writeHasChildren(raw_ostream &OS) const override {
506f4a2713aSLionel Sambuc       OS << "SA->is" << getUpperName() << "Expr()";
507f4a2713aSLionel Sambuc     }
508f4a2713aSLionel Sambuc   };
509f4a2713aSLionel Sambuc 
510f4a2713aSLionel Sambuc   class VariadicArgument : public Argument {
511*0a6a1f1dSLionel Sambuc     std::string Type, ArgName, ArgSizeName, RangeName;
512*0a6a1f1dSLionel Sambuc 
513*0a6a1f1dSLionel Sambuc   protected:
514*0a6a1f1dSLionel Sambuc     // Assumed to receive a parameter: raw_ostream OS.
writeValueImpl(raw_ostream & OS) const515*0a6a1f1dSLionel Sambuc     virtual void writeValueImpl(raw_ostream &OS) const {
516*0a6a1f1dSLionel Sambuc       OS << "    OS << Val;\n";
517*0a6a1f1dSLionel Sambuc     }
518f4a2713aSLionel Sambuc 
519f4a2713aSLionel Sambuc   public:
VariadicArgument(const Record & Arg,StringRef Attr,std::string T)520*0a6a1f1dSLionel Sambuc     VariadicArgument(const Record &Arg, StringRef Attr, std::string T)
521*0a6a1f1dSLionel Sambuc         : Argument(Arg, Attr), Type(T), ArgName(getLowerName().str() + "_"),
522*0a6a1f1dSLionel Sambuc           ArgSizeName(ArgName + "Size"), RangeName(getLowerName()) {}
523f4a2713aSLionel Sambuc 
getType() const524*0a6a1f1dSLionel Sambuc     std::string getType() const { return Type; }
isVariadic() const525*0a6a1f1dSLionel Sambuc     bool isVariadic() const override { return true; }
526f4a2713aSLionel Sambuc 
writeAccessors(raw_ostream & OS) const527*0a6a1f1dSLionel Sambuc     void writeAccessors(raw_ostream &OS) const override {
528*0a6a1f1dSLionel Sambuc       std::string IteratorType = getLowerName().str() + "_iterator";
529*0a6a1f1dSLionel Sambuc       std::string BeginFn = getLowerName().str() + "_begin()";
530*0a6a1f1dSLionel Sambuc       std::string EndFn = getLowerName().str() + "_end()";
531*0a6a1f1dSLionel Sambuc 
532*0a6a1f1dSLionel Sambuc       OS << "  typedef " << Type << "* " << IteratorType << ";\n";
533*0a6a1f1dSLionel Sambuc       OS << "  " << IteratorType << " " << BeginFn << " const {"
534*0a6a1f1dSLionel Sambuc          << " return " << ArgName << "; }\n";
535*0a6a1f1dSLionel Sambuc       OS << "  " << IteratorType << " " << EndFn << " const {"
536*0a6a1f1dSLionel Sambuc          << " return " << ArgName << " + " << ArgSizeName << "; }\n";
537*0a6a1f1dSLionel Sambuc       OS << "  unsigned " << getLowerName() << "_size() const {"
538*0a6a1f1dSLionel Sambuc          << " return " << ArgSizeName << "; }\n";
539*0a6a1f1dSLionel Sambuc       OS << "  llvm::iterator_range<" << IteratorType << "> " << RangeName
540*0a6a1f1dSLionel Sambuc          << "() const { return llvm::make_range(" << BeginFn << ", " << EndFn
541*0a6a1f1dSLionel Sambuc          << "); }\n";
542f4a2713aSLionel Sambuc     }
writeCloneArgs(raw_ostream & OS) const543*0a6a1f1dSLionel Sambuc     void writeCloneArgs(raw_ostream &OS) const override {
544*0a6a1f1dSLionel Sambuc       OS << ArgName << ", " << ArgSizeName;
545f4a2713aSLionel Sambuc     }
writeTemplateInstantiationArgs(raw_ostream & OS) const546*0a6a1f1dSLionel Sambuc     void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
547f4a2713aSLionel Sambuc       // This isn't elegant, but we have to go through public methods...
548f4a2713aSLionel Sambuc       OS << "A->" << getLowerName() << "_begin(), "
549f4a2713aSLionel Sambuc          << "A->" << getLowerName() << "_size()";
550f4a2713aSLionel Sambuc     }
writeCtorBody(raw_ostream & OS) const551*0a6a1f1dSLionel Sambuc     void writeCtorBody(raw_ostream &OS) const override {
552*0a6a1f1dSLionel Sambuc       OS << "    std::copy(" << getUpperName() << ", " << getUpperName()
553*0a6a1f1dSLionel Sambuc          << " + " << ArgSizeName << ", " << ArgName << ");";
554f4a2713aSLionel Sambuc     }
writeCtorInitializers(raw_ostream & OS) const555*0a6a1f1dSLionel Sambuc     void writeCtorInitializers(raw_ostream &OS) const override {
556*0a6a1f1dSLionel Sambuc       OS << ArgSizeName << "(" << getUpperName() << "Size), "
557*0a6a1f1dSLionel Sambuc          << ArgName << "(new (Ctx, 16) " << getType() << "["
558*0a6a1f1dSLionel Sambuc          << ArgSizeName << "])";
559f4a2713aSLionel Sambuc     }
writeCtorDefaultInitializers(raw_ostream & OS) const560*0a6a1f1dSLionel Sambuc     void writeCtorDefaultInitializers(raw_ostream &OS) const override {
561*0a6a1f1dSLionel Sambuc       OS << ArgSizeName << "(0), " << ArgName << "(nullptr)";
562f4a2713aSLionel Sambuc     }
writeCtorParameters(raw_ostream & OS) const563*0a6a1f1dSLionel Sambuc     void writeCtorParameters(raw_ostream &OS) const override {
564f4a2713aSLionel Sambuc       OS << getType() << " *" << getUpperName() << ", unsigned "
565f4a2713aSLionel Sambuc          << getUpperName() << "Size";
566f4a2713aSLionel Sambuc     }
writeImplicitCtorArgs(raw_ostream & OS) const567*0a6a1f1dSLionel Sambuc     void writeImplicitCtorArgs(raw_ostream &OS) const override {
568*0a6a1f1dSLionel Sambuc       OS << getUpperName() << ", " << getUpperName() << "Size";
569f4a2713aSLionel Sambuc     }
writeDeclarations(raw_ostream & OS) const570*0a6a1f1dSLionel Sambuc     void writeDeclarations(raw_ostream &OS) const override {
571*0a6a1f1dSLionel Sambuc       OS << "  unsigned " << ArgSizeName << ";\n";
572*0a6a1f1dSLionel Sambuc       OS << "  " << getType() << " *" << ArgName << ";";
573*0a6a1f1dSLionel Sambuc     }
writePCHReadDecls(raw_ostream & OS) const574*0a6a1f1dSLionel Sambuc     void writePCHReadDecls(raw_ostream &OS) const override {
575f4a2713aSLionel Sambuc       OS << "  unsigned " << getLowerName() << "Size = Record[Idx++];\n";
576*0a6a1f1dSLionel Sambuc       OS << "  SmallVector<" << Type << ", 4> " << getLowerName()
577f4a2713aSLionel Sambuc          << ";\n";
578f4a2713aSLionel Sambuc       OS << "  " << getLowerName() << ".reserve(" << getLowerName()
579f4a2713aSLionel Sambuc          << "Size);\n";
580f4a2713aSLionel Sambuc       OS << "    for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
581f4a2713aSLionel Sambuc 
582*0a6a1f1dSLionel Sambuc       std::string read = ReadPCHRecord(Type);
583f4a2713aSLionel Sambuc       OS << "    " << getLowerName() << ".push_back(" << read << ");\n";
584f4a2713aSLionel Sambuc     }
writePCHReadArgs(raw_ostream & OS) const585*0a6a1f1dSLionel Sambuc     void writePCHReadArgs(raw_ostream &OS) const override {
586f4a2713aSLionel Sambuc       OS << getLowerName() << ".data(), " << getLowerName() << "Size";
587f4a2713aSLionel Sambuc     }
writePCHWrite(raw_ostream & OS) const588*0a6a1f1dSLionel Sambuc     void writePCHWrite(raw_ostream &OS) const override {
589f4a2713aSLionel Sambuc       OS << "    Record.push_back(SA->" << getLowerName() << "_size());\n";
590*0a6a1f1dSLionel Sambuc       OS << "    for (auto &Val : SA->" << RangeName << "())\n";
591*0a6a1f1dSLionel Sambuc       OS << "      " << WritePCHRecord(Type, "Val");
592f4a2713aSLionel Sambuc     }
writeValue(raw_ostream & OS) const593*0a6a1f1dSLionel Sambuc     void writeValue(raw_ostream &OS) const override {
594f4a2713aSLionel Sambuc       OS << "\";\n";
595f4a2713aSLionel Sambuc       OS << "  bool isFirst = true;\n"
596*0a6a1f1dSLionel Sambuc          << "  for (const auto &Val : " << RangeName << "()) {\n"
597f4a2713aSLionel Sambuc          << "    if (isFirst) isFirst = false;\n"
598*0a6a1f1dSLionel Sambuc          << "    else OS << \", \";\n";
599*0a6a1f1dSLionel Sambuc       writeValueImpl(OS);
600*0a6a1f1dSLionel Sambuc       OS << "  }\n";
601f4a2713aSLionel Sambuc       OS << "  OS << \"";
602f4a2713aSLionel Sambuc     }
writeDump(raw_ostream & OS) const603*0a6a1f1dSLionel Sambuc     void writeDump(raw_ostream &OS) const override {
604*0a6a1f1dSLionel Sambuc       OS << "    for (const auto &Val : SA->" << RangeName << "())\n";
605*0a6a1f1dSLionel Sambuc       OS << "      OS << \" \" << Val;\n";
606f4a2713aSLionel Sambuc     }
607f4a2713aSLionel Sambuc   };
608f4a2713aSLionel Sambuc 
609*0a6a1f1dSLionel Sambuc   // Unique the enums, but maintain the original declaration ordering.
610*0a6a1f1dSLionel Sambuc   std::vector<std::string>
uniqueEnumsInOrder(const std::vector<std::string> & enums)611*0a6a1f1dSLionel Sambuc   uniqueEnumsInOrder(const std::vector<std::string> &enums) {
612*0a6a1f1dSLionel Sambuc     std::vector<std::string> uniques;
613*0a6a1f1dSLionel Sambuc     std::set<std::string> unique_set(enums.begin(), enums.end());
614*0a6a1f1dSLionel Sambuc     for (const auto &i : enums) {
615*0a6a1f1dSLionel Sambuc       std::set<std::string>::iterator set_i = unique_set.find(i);
616*0a6a1f1dSLionel Sambuc       if (set_i != unique_set.end()) {
617*0a6a1f1dSLionel Sambuc         uniques.push_back(i);
618*0a6a1f1dSLionel Sambuc         unique_set.erase(set_i);
619*0a6a1f1dSLionel Sambuc       }
620*0a6a1f1dSLionel Sambuc     }
621*0a6a1f1dSLionel Sambuc     return uniques;
622*0a6a1f1dSLionel Sambuc   }
623*0a6a1f1dSLionel Sambuc 
624f4a2713aSLionel Sambuc   class EnumArgument : public Argument {
625f4a2713aSLionel Sambuc     std::string type;
626*0a6a1f1dSLionel Sambuc     std::vector<std::string> values, enums, uniques;
627f4a2713aSLionel Sambuc   public:
EnumArgument(const Record & Arg,StringRef Attr)628*0a6a1f1dSLionel Sambuc     EnumArgument(const Record &Arg, StringRef Attr)
629f4a2713aSLionel Sambuc       : Argument(Arg, Attr), type(Arg.getValueAsString("Type")),
630*0a6a1f1dSLionel Sambuc         values(Arg.getValueAsListOfStrings("Values")),
631*0a6a1f1dSLionel Sambuc         enums(Arg.getValueAsListOfStrings("Enums")),
632*0a6a1f1dSLionel Sambuc         uniques(uniqueEnumsInOrder(enums))
633f4a2713aSLionel Sambuc     {
634f4a2713aSLionel Sambuc       // FIXME: Emit a proper error
635f4a2713aSLionel Sambuc       assert(!uniques.empty());
636f4a2713aSLionel Sambuc     }
637f4a2713aSLionel Sambuc 
isEnumArg() const638*0a6a1f1dSLionel Sambuc     bool isEnumArg() const override { return true; }
639f4a2713aSLionel Sambuc 
writeAccessors(raw_ostream & OS) const640*0a6a1f1dSLionel Sambuc     void writeAccessors(raw_ostream &OS) const override {
641f4a2713aSLionel Sambuc       OS << "  " << type << " get" << getUpperName() << "() const {\n";
642f4a2713aSLionel Sambuc       OS << "    return " << getLowerName() << ";\n";
643f4a2713aSLionel Sambuc       OS << "  }";
644f4a2713aSLionel Sambuc     }
writeCloneArgs(raw_ostream & OS) const645*0a6a1f1dSLionel Sambuc     void writeCloneArgs(raw_ostream &OS) const override {
646f4a2713aSLionel Sambuc       OS << getLowerName();
647f4a2713aSLionel Sambuc     }
writeTemplateInstantiationArgs(raw_ostream & OS) const648*0a6a1f1dSLionel Sambuc     void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
649f4a2713aSLionel Sambuc       OS << "A->get" << getUpperName() << "()";
650f4a2713aSLionel Sambuc     }
writeCtorInitializers(raw_ostream & OS) const651*0a6a1f1dSLionel Sambuc     void writeCtorInitializers(raw_ostream &OS) const override {
652f4a2713aSLionel Sambuc       OS << getLowerName() << "(" << getUpperName() << ")";
653f4a2713aSLionel Sambuc     }
writeCtorDefaultInitializers(raw_ostream & OS) const654*0a6a1f1dSLionel Sambuc     void writeCtorDefaultInitializers(raw_ostream &OS) const override {
655f4a2713aSLionel Sambuc       OS << getLowerName() << "(" << type << "(0))";
656f4a2713aSLionel Sambuc     }
writeCtorParameters(raw_ostream & OS) const657*0a6a1f1dSLionel Sambuc     void writeCtorParameters(raw_ostream &OS) const override {
658f4a2713aSLionel Sambuc       OS << type << " " << getUpperName();
659f4a2713aSLionel Sambuc     }
writeDeclarations(raw_ostream & OS) const660*0a6a1f1dSLionel Sambuc     void writeDeclarations(raw_ostream &OS) const override {
661*0a6a1f1dSLionel Sambuc       std::vector<std::string>::const_iterator i = uniques.begin(),
662f4a2713aSLionel Sambuc                                                e = uniques.end();
663f4a2713aSLionel Sambuc       // The last one needs to not have a comma.
664f4a2713aSLionel Sambuc       --e;
665f4a2713aSLionel Sambuc 
666f4a2713aSLionel Sambuc       OS << "public:\n";
667f4a2713aSLionel Sambuc       OS << "  enum " << type << " {\n";
668f4a2713aSLionel Sambuc       for (; i != e; ++i)
669f4a2713aSLionel Sambuc         OS << "    " << *i << ",\n";
670f4a2713aSLionel Sambuc       OS << "    " << *e << "\n";
671f4a2713aSLionel Sambuc       OS << "  };\n";
672f4a2713aSLionel Sambuc       OS << "private:\n";
673f4a2713aSLionel Sambuc       OS << "  " << type << " " << getLowerName() << ";";
674f4a2713aSLionel Sambuc     }
writePCHReadDecls(raw_ostream & OS) const675*0a6a1f1dSLionel Sambuc     void writePCHReadDecls(raw_ostream &OS) const override {
676f4a2713aSLionel Sambuc       OS << "    " << getAttrName() << "Attr::" << type << " " << getLowerName()
677f4a2713aSLionel Sambuc          << "(static_cast<" << getAttrName() << "Attr::" << type
678f4a2713aSLionel Sambuc          << ">(Record[Idx++]));\n";
679f4a2713aSLionel Sambuc     }
writePCHReadArgs(raw_ostream & OS) const680*0a6a1f1dSLionel Sambuc     void writePCHReadArgs(raw_ostream &OS) const override {
681f4a2713aSLionel Sambuc       OS << getLowerName();
682f4a2713aSLionel Sambuc     }
writePCHWrite(raw_ostream & OS) const683*0a6a1f1dSLionel Sambuc     void writePCHWrite(raw_ostream &OS) const override {
684f4a2713aSLionel Sambuc       OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
685f4a2713aSLionel Sambuc     }
writeValue(raw_ostream & OS) const686*0a6a1f1dSLionel Sambuc     void writeValue(raw_ostream &OS) const override {
687*0a6a1f1dSLionel Sambuc       // FIXME: this isn't 100% correct -- some enum arguments require printing
688*0a6a1f1dSLionel Sambuc       // as a string literal, while others require printing as an identifier.
689*0a6a1f1dSLionel Sambuc       // Tablegen currently does not distinguish between the two forms.
690*0a6a1f1dSLionel Sambuc       OS << "\\\"\" << " << getAttrName() << "Attr::Convert" << type << "ToStr(get"
691*0a6a1f1dSLionel Sambuc          << getUpperName() << "()) << \"\\\"";
692f4a2713aSLionel Sambuc     }
writeDump(raw_ostream & OS) const693*0a6a1f1dSLionel Sambuc     void writeDump(raw_ostream &OS) const override {
694f4a2713aSLionel Sambuc       OS << "    switch(SA->get" << getUpperName() << "()) {\n";
695*0a6a1f1dSLionel Sambuc       for (const auto &I : uniques) {
696*0a6a1f1dSLionel Sambuc         OS << "    case " << getAttrName() << "Attr::" << I << ":\n";
697*0a6a1f1dSLionel Sambuc         OS << "      OS << \" " << I << "\";\n";
698f4a2713aSLionel Sambuc         OS << "      break;\n";
699f4a2713aSLionel Sambuc       }
700f4a2713aSLionel Sambuc       OS << "    }\n";
701f4a2713aSLionel Sambuc     }
702f4a2713aSLionel Sambuc 
writeConversion(raw_ostream & OS) const703f4a2713aSLionel Sambuc     void writeConversion(raw_ostream &OS) const {
704f4a2713aSLionel Sambuc       OS << "  static bool ConvertStrTo" << type << "(StringRef Val, ";
705f4a2713aSLionel Sambuc       OS << type << " &Out) {\n";
706f4a2713aSLionel Sambuc       OS << "    Optional<" << type << "> R = llvm::StringSwitch<Optional<";
707f4a2713aSLionel Sambuc       OS << type << ">>(Val)\n";
708f4a2713aSLionel Sambuc       for (size_t I = 0; I < enums.size(); ++I) {
709f4a2713aSLionel Sambuc         OS << "      .Case(\"" << values[I] << "\", ";
710f4a2713aSLionel Sambuc         OS << getAttrName() << "Attr::" << enums[I] << ")\n";
711f4a2713aSLionel Sambuc       }
712f4a2713aSLionel Sambuc       OS << "      .Default(Optional<" << type << ">());\n";
713f4a2713aSLionel Sambuc       OS << "    if (R) {\n";
714f4a2713aSLionel Sambuc       OS << "      Out = *R;\n      return true;\n    }\n";
715f4a2713aSLionel Sambuc       OS << "    return false;\n";
716*0a6a1f1dSLionel Sambuc       OS << "  }\n\n";
717*0a6a1f1dSLionel Sambuc 
718*0a6a1f1dSLionel Sambuc       // Mapping from enumeration values back to enumeration strings isn't
719*0a6a1f1dSLionel Sambuc       // trivial because some enumeration values have multiple named
720*0a6a1f1dSLionel Sambuc       // enumerators, such as type_visibility(internal) and
721*0a6a1f1dSLionel Sambuc       // type_visibility(hidden) both mapping to TypeVisibilityAttr::Hidden.
722*0a6a1f1dSLionel Sambuc       OS << "  static const char *Convert" << type << "ToStr("
723*0a6a1f1dSLionel Sambuc          << type << " Val) {\n"
724*0a6a1f1dSLionel Sambuc          << "    switch(Val) {\n";
725*0a6a1f1dSLionel Sambuc       std::set<std::string> Uniques;
726*0a6a1f1dSLionel Sambuc       for (size_t I = 0; I < enums.size(); ++I) {
727*0a6a1f1dSLionel Sambuc         if (Uniques.insert(enums[I]).second)
728*0a6a1f1dSLionel Sambuc           OS << "    case " << getAttrName() << "Attr::" << enums[I]
729*0a6a1f1dSLionel Sambuc              << ": return \"" << values[I] << "\";\n";
730*0a6a1f1dSLionel Sambuc       }
731*0a6a1f1dSLionel Sambuc       OS << "    }\n"
732*0a6a1f1dSLionel Sambuc          << "    llvm_unreachable(\"No enumerator with that value\");\n"
733*0a6a1f1dSLionel Sambuc          << "  }\n";
734f4a2713aSLionel Sambuc     }
735f4a2713aSLionel Sambuc   };
736f4a2713aSLionel Sambuc 
737f4a2713aSLionel Sambuc   class VariadicEnumArgument: public VariadicArgument {
738f4a2713aSLionel Sambuc     std::string type, QualifiedTypeName;
739*0a6a1f1dSLionel Sambuc     std::vector<std::string> values, enums, uniques;
740*0a6a1f1dSLionel Sambuc 
741*0a6a1f1dSLionel Sambuc   protected:
writeValueImpl(raw_ostream & OS) const742*0a6a1f1dSLionel Sambuc     void writeValueImpl(raw_ostream &OS) const override {
743*0a6a1f1dSLionel Sambuc       // FIXME: this isn't 100% correct -- some enum arguments require printing
744*0a6a1f1dSLionel Sambuc       // as a string literal, while others require printing as an identifier.
745*0a6a1f1dSLionel Sambuc       // Tablegen currently does not distinguish between the two forms.
746*0a6a1f1dSLionel Sambuc       OS << "    OS << \"\\\"\" << " << getAttrName() << "Attr::Convert" << type
747*0a6a1f1dSLionel Sambuc          << "ToStr(Val)" << "<< \"\\\"\";\n";
748*0a6a1f1dSLionel Sambuc     }
749*0a6a1f1dSLionel Sambuc 
750f4a2713aSLionel Sambuc   public:
VariadicEnumArgument(const Record & Arg,StringRef Attr)751*0a6a1f1dSLionel Sambuc     VariadicEnumArgument(const Record &Arg, StringRef Attr)
752f4a2713aSLionel Sambuc       : VariadicArgument(Arg, Attr, Arg.getValueAsString("Type")),
753f4a2713aSLionel Sambuc         type(Arg.getValueAsString("Type")),
754*0a6a1f1dSLionel Sambuc         values(Arg.getValueAsListOfStrings("Values")),
755*0a6a1f1dSLionel Sambuc         enums(Arg.getValueAsListOfStrings("Enums")),
756*0a6a1f1dSLionel Sambuc         uniques(uniqueEnumsInOrder(enums))
757f4a2713aSLionel Sambuc     {
758f4a2713aSLionel Sambuc       QualifiedTypeName = getAttrName().str() + "Attr::" + type;
759f4a2713aSLionel Sambuc 
760f4a2713aSLionel Sambuc       // FIXME: Emit a proper error
761f4a2713aSLionel Sambuc       assert(!uniques.empty());
762f4a2713aSLionel Sambuc     }
763f4a2713aSLionel Sambuc 
isVariadicEnumArg() const764*0a6a1f1dSLionel Sambuc     bool isVariadicEnumArg() const override { return true; }
765f4a2713aSLionel Sambuc 
writeDeclarations(raw_ostream & OS) const766*0a6a1f1dSLionel Sambuc     void writeDeclarations(raw_ostream &OS) const override {
767*0a6a1f1dSLionel Sambuc       std::vector<std::string>::const_iterator i = uniques.begin(),
768f4a2713aSLionel Sambuc                                                e = uniques.end();
769f4a2713aSLionel Sambuc       // The last one needs to not have a comma.
770f4a2713aSLionel Sambuc       --e;
771f4a2713aSLionel Sambuc 
772f4a2713aSLionel Sambuc       OS << "public:\n";
773f4a2713aSLionel Sambuc       OS << "  enum " << type << " {\n";
774f4a2713aSLionel Sambuc       for (; i != e; ++i)
775f4a2713aSLionel Sambuc         OS << "    " << *i << ",\n";
776f4a2713aSLionel Sambuc       OS << "    " << *e << "\n";
777f4a2713aSLionel Sambuc       OS << "  };\n";
778f4a2713aSLionel Sambuc       OS << "private:\n";
779f4a2713aSLionel Sambuc 
780f4a2713aSLionel Sambuc       VariadicArgument::writeDeclarations(OS);
781f4a2713aSLionel Sambuc     }
writeDump(raw_ostream & OS) const782*0a6a1f1dSLionel Sambuc     void writeDump(raw_ostream &OS) const override {
783f4a2713aSLionel Sambuc       OS << "    for (" << getAttrName() << "Attr::" << getLowerName()
784f4a2713aSLionel Sambuc          << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
785f4a2713aSLionel Sambuc          << getLowerName() << "_end(); I != E; ++I) {\n";
786f4a2713aSLionel Sambuc       OS << "      switch(*I) {\n";
787*0a6a1f1dSLionel Sambuc       for (const auto &UI : uniques) {
788*0a6a1f1dSLionel Sambuc         OS << "    case " << getAttrName() << "Attr::" << UI << ":\n";
789*0a6a1f1dSLionel Sambuc         OS << "      OS << \" " << UI << "\";\n";
790f4a2713aSLionel Sambuc         OS << "      break;\n";
791f4a2713aSLionel Sambuc       }
792f4a2713aSLionel Sambuc       OS << "      }\n";
793f4a2713aSLionel Sambuc       OS << "    }\n";
794f4a2713aSLionel Sambuc     }
writePCHReadDecls(raw_ostream & OS) const795*0a6a1f1dSLionel Sambuc     void writePCHReadDecls(raw_ostream &OS) const override {
796f4a2713aSLionel Sambuc       OS << "    unsigned " << getLowerName() << "Size = Record[Idx++];\n";
797f4a2713aSLionel Sambuc       OS << "    SmallVector<" << QualifiedTypeName << ", 4> " << getLowerName()
798f4a2713aSLionel Sambuc          << ";\n";
799f4a2713aSLionel Sambuc       OS << "    " << getLowerName() << ".reserve(" << getLowerName()
800f4a2713aSLionel Sambuc          << "Size);\n";
801f4a2713aSLionel Sambuc       OS << "    for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
802f4a2713aSLionel Sambuc       OS << "      " << getLowerName() << ".push_back(" << "static_cast<"
803f4a2713aSLionel Sambuc          << QualifiedTypeName << ">(Record[Idx++]));\n";
804f4a2713aSLionel Sambuc     }
writePCHWrite(raw_ostream & OS) const805*0a6a1f1dSLionel Sambuc     void writePCHWrite(raw_ostream &OS) const override {
806f4a2713aSLionel Sambuc       OS << "    Record.push_back(SA->" << getLowerName() << "_size());\n";
807f4a2713aSLionel Sambuc       OS << "    for (" << getAttrName() << "Attr::" << getLowerName()
808f4a2713aSLionel Sambuc          << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
809f4a2713aSLionel Sambuc          << getLowerName() << "_end(); i != e; ++i)\n";
810f4a2713aSLionel Sambuc       OS << "      " << WritePCHRecord(QualifiedTypeName, "(*i)");
811f4a2713aSLionel Sambuc     }
writeConversion(raw_ostream & OS) const812f4a2713aSLionel Sambuc     void writeConversion(raw_ostream &OS) const {
813f4a2713aSLionel Sambuc       OS << "  static bool ConvertStrTo" << type << "(StringRef Val, ";
814f4a2713aSLionel Sambuc       OS << type << " &Out) {\n";
815f4a2713aSLionel Sambuc       OS << "    Optional<" << type << "> R = llvm::StringSwitch<Optional<";
816f4a2713aSLionel Sambuc       OS << type << ">>(Val)\n";
817f4a2713aSLionel Sambuc       for (size_t I = 0; I < enums.size(); ++I) {
818f4a2713aSLionel Sambuc         OS << "      .Case(\"" << values[I] << "\", ";
819f4a2713aSLionel Sambuc         OS << getAttrName() << "Attr::" << enums[I] << ")\n";
820f4a2713aSLionel Sambuc       }
821f4a2713aSLionel Sambuc       OS << "      .Default(Optional<" << type << ">());\n";
822f4a2713aSLionel Sambuc       OS << "    if (R) {\n";
823f4a2713aSLionel Sambuc       OS << "      Out = *R;\n      return true;\n    }\n";
824f4a2713aSLionel Sambuc       OS << "    return false;\n";
825*0a6a1f1dSLionel Sambuc       OS << "  }\n\n";
826*0a6a1f1dSLionel Sambuc 
827*0a6a1f1dSLionel Sambuc       OS << "  static const char *Convert" << type << "ToStr("
828*0a6a1f1dSLionel Sambuc         << type << " Val) {\n"
829*0a6a1f1dSLionel Sambuc         << "    switch(Val) {\n";
830*0a6a1f1dSLionel Sambuc       std::set<std::string> Uniques;
831*0a6a1f1dSLionel Sambuc       for (size_t I = 0; I < enums.size(); ++I) {
832*0a6a1f1dSLionel Sambuc         if (Uniques.insert(enums[I]).second)
833*0a6a1f1dSLionel Sambuc           OS << "    case " << getAttrName() << "Attr::" << enums[I]
834*0a6a1f1dSLionel Sambuc           << ": return \"" << values[I] << "\";\n";
835*0a6a1f1dSLionel Sambuc       }
836*0a6a1f1dSLionel Sambuc       OS << "    }\n"
837*0a6a1f1dSLionel Sambuc         << "    llvm_unreachable(\"No enumerator with that value\");\n"
838*0a6a1f1dSLionel Sambuc         << "  }\n";
839f4a2713aSLionel Sambuc     }
840f4a2713aSLionel Sambuc   };
841f4a2713aSLionel Sambuc 
842f4a2713aSLionel Sambuc   class VersionArgument : public Argument {
843f4a2713aSLionel Sambuc   public:
VersionArgument(const Record & Arg,StringRef Attr)844*0a6a1f1dSLionel Sambuc     VersionArgument(const Record &Arg, StringRef Attr)
845f4a2713aSLionel Sambuc       : Argument(Arg, Attr)
846f4a2713aSLionel Sambuc     {}
847f4a2713aSLionel Sambuc 
writeAccessors(raw_ostream & OS) const848*0a6a1f1dSLionel Sambuc     void writeAccessors(raw_ostream &OS) const override {
849f4a2713aSLionel Sambuc       OS << "  VersionTuple get" << getUpperName() << "() const {\n";
850f4a2713aSLionel Sambuc       OS << "    return " << getLowerName() << ";\n";
851f4a2713aSLionel Sambuc       OS << "  }\n";
852f4a2713aSLionel Sambuc       OS << "  void set" << getUpperName()
853f4a2713aSLionel Sambuc          << "(ASTContext &C, VersionTuple V) {\n";
854f4a2713aSLionel Sambuc       OS << "    " << getLowerName() << " = V;\n";
855f4a2713aSLionel Sambuc       OS << "  }";
856f4a2713aSLionel Sambuc     }
writeCloneArgs(raw_ostream & OS) const857*0a6a1f1dSLionel Sambuc     void writeCloneArgs(raw_ostream &OS) const override {
858f4a2713aSLionel Sambuc       OS << "get" << getUpperName() << "()";
859f4a2713aSLionel Sambuc     }
writeTemplateInstantiationArgs(raw_ostream & OS) const860*0a6a1f1dSLionel Sambuc     void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
861f4a2713aSLionel Sambuc       OS << "A->get" << getUpperName() << "()";
862f4a2713aSLionel Sambuc     }
writeCtorInitializers(raw_ostream & OS) const863*0a6a1f1dSLionel Sambuc     void writeCtorInitializers(raw_ostream &OS) const override {
864f4a2713aSLionel Sambuc       OS << getLowerName() << "(" << getUpperName() << ")";
865f4a2713aSLionel Sambuc     }
writeCtorDefaultInitializers(raw_ostream & OS) const866*0a6a1f1dSLionel Sambuc     void writeCtorDefaultInitializers(raw_ostream &OS) const override {
867f4a2713aSLionel Sambuc       OS << getLowerName() << "()";
868f4a2713aSLionel Sambuc     }
writeCtorParameters(raw_ostream & OS) const869*0a6a1f1dSLionel Sambuc     void writeCtorParameters(raw_ostream &OS) const override {
870f4a2713aSLionel Sambuc       OS << "VersionTuple " << getUpperName();
871f4a2713aSLionel Sambuc     }
writeDeclarations(raw_ostream & OS) const872*0a6a1f1dSLionel Sambuc     void writeDeclarations(raw_ostream &OS) const override {
873f4a2713aSLionel Sambuc       OS << "VersionTuple " << getLowerName() << ";\n";
874f4a2713aSLionel Sambuc     }
writePCHReadDecls(raw_ostream & OS) const875*0a6a1f1dSLionel Sambuc     void writePCHReadDecls(raw_ostream &OS) const override {
876f4a2713aSLionel Sambuc       OS << "    VersionTuple " << getLowerName()
877f4a2713aSLionel Sambuc          << "= ReadVersionTuple(Record, Idx);\n";
878f4a2713aSLionel Sambuc     }
writePCHReadArgs(raw_ostream & OS) const879*0a6a1f1dSLionel Sambuc     void writePCHReadArgs(raw_ostream &OS) const override {
880f4a2713aSLionel Sambuc       OS << getLowerName();
881f4a2713aSLionel Sambuc     }
writePCHWrite(raw_ostream & OS) const882*0a6a1f1dSLionel Sambuc     void writePCHWrite(raw_ostream &OS) const override {
883f4a2713aSLionel Sambuc       OS << "    AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n";
884f4a2713aSLionel Sambuc     }
writeValue(raw_ostream & OS) const885*0a6a1f1dSLionel Sambuc     void writeValue(raw_ostream &OS) const override {
886f4a2713aSLionel Sambuc       OS << getLowerName() << "=\" << get" << getUpperName() << "() << \"";
887f4a2713aSLionel Sambuc     }
writeDump(raw_ostream & OS) const888*0a6a1f1dSLionel Sambuc     void writeDump(raw_ostream &OS) const override {
889f4a2713aSLionel Sambuc       OS << "    OS << \" \" << SA->get" << getUpperName() << "();\n";
890f4a2713aSLionel Sambuc     }
891f4a2713aSLionel Sambuc   };
892f4a2713aSLionel Sambuc 
893f4a2713aSLionel Sambuc   class ExprArgument : public SimpleArgument {
894f4a2713aSLionel Sambuc   public:
ExprArgument(const Record & Arg,StringRef Attr)895*0a6a1f1dSLionel Sambuc     ExprArgument(const Record &Arg, StringRef Attr)
896f4a2713aSLionel Sambuc       : SimpleArgument(Arg, Attr, "Expr *")
897f4a2713aSLionel Sambuc     {}
898f4a2713aSLionel Sambuc 
writeASTVisitorTraversal(raw_ostream & OS) const899*0a6a1f1dSLionel Sambuc     void writeASTVisitorTraversal(raw_ostream &OS) const override {
900*0a6a1f1dSLionel Sambuc       OS << "  if (!"
901*0a6a1f1dSLionel Sambuc          << "getDerived().TraverseStmt(A->get" << getUpperName() << "()))\n";
902*0a6a1f1dSLionel Sambuc       OS << "    return false;\n";
903*0a6a1f1dSLionel Sambuc     }
904*0a6a1f1dSLionel Sambuc 
writeTemplateInstantiationArgs(raw_ostream & OS) const905*0a6a1f1dSLionel Sambuc     void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
906f4a2713aSLionel Sambuc       OS << "tempInst" << getUpperName();
907f4a2713aSLionel Sambuc     }
908f4a2713aSLionel Sambuc 
writeTemplateInstantiation(raw_ostream & OS) const909*0a6a1f1dSLionel Sambuc     void writeTemplateInstantiation(raw_ostream &OS) const override {
910f4a2713aSLionel Sambuc       OS << "      " << getType() << " tempInst" << getUpperName() << ";\n";
911f4a2713aSLionel Sambuc       OS << "      {\n";
912f4a2713aSLionel Sambuc       OS << "        EnterExpressionEvaluationContext "
913f4a2713aSLionel Sambuc          << "Unevaluated(S, Sema::Unevaluated);\n";
914f4a2713aSLionel Sambuc       OS << "        ExprResult " << "Result = S.SubstExpr("
915f4a2713aSLionel Sambuc          << "A->get" << getUpperName() << "(), TemplateArgs);\n";
916f4a2713aSLionel Sambuc       OS << "        tempInst" << getUpperName() << " = "
917*0a6a1f1dSLionel Sambuc          << "Result.getAs<Expr>();\n";
918f4a2713aSLionel Sambuc       OS << "      }\n";
919f4a2713aSLionel Sambuc     }
920f4a2713aSLionel Sambuc 
writeDump(raw_ostream & OS) const921*0a6a1f1dSLionel Sambuc     void writeDump(raw_ostream &OS) const override {}
922f4a2713aSLionel Sambuc 
writeDumpChildren(raw_ostream & OS) const923*0a6a1f1dSLionel Sambuc     void writeDumpChildren(raw_ostream &OS) const override {
924f4a2713aSLionel Sambuc       OS << "    dumpStmt(SA->get" << getUpperName() << "());\n";
925f4a2713aSLionel Sambuc     }
writeHasChildren(raw_ostream & OS) const926*0a6a1f1dSLionel Sambuc     void writeHasChildren(raw_ostream &OS) const override { OS << "true"; }
927f4a2713aSLionel Sambuc   };
928f4a2713aSLionel Sambuc 
929f4a2713aSLionel Sambuc   class VariadicExprArgument : public VariadicArgument {
930f4a2713aSLionel Sambuc   public:
VariadicExprArgument(const Record & Arg,StringRef Attr)931*0a6a1f1dSLionel Sambuc     VariadicExprArgument(const Record &Arg, StringRef Attr)
932f4a2713aSLionel Sambuc       : VariadicArgument(Arg, Attr, "Expr *")
933f4a2713aSLionel Sambuc     {}
934f4a2713aSLionel Sambuc 
writeASTVisitorTraversal(raw_ostream & OS) const935*0a6a1f1dSLionel Sambuc     void writeASTVisitorTraversal(raw_ostream &OS) const override {
936*0a6a1f1dSLionel Sambuc       OS << "  {\n";
937*0a6a1f1dSLionel Sambuc       OS << "    " << getType() << " *I = A->" << getLowerName()
938*0a6a1f1dSLionel Sambuc          << "_begin();\n";
939*0a6a1f1dSLionel Sambuc       OS << "    " << getType() << " *E = A->" << getLowerName()
940*0a6a1f1dSLionel Sambuc          << "_end();\n";
941*0a6a1f1dSLionel Sambuc       OS << "    for (; I != E; ++I) {\n";
942*0a6a1f1dSLionel Sambuc       OS << "      if (!getDerived().TraverseStmt(*I))\n";
943*0a6a1f1dSLionel Sambuc       OS << "        return false;\n";
944*0a6a1f1dSLionel Sambuc       OS << "    }\n";
945*0a6a1f1dSLionel Sambuc       OS << "  }\n";
946*0a6a1f1dSLionel Sambuc     }
947*0a6a1f1dSLionel Sambuc 
writeTemplateInstantiationArgs(raw_ostream & OS) const948*0a6a1f1dSLionel Sambuc     void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
949f4a2713aSLionel Sambuc       OS << "tempInst" << getUpperName() << ", "
950f4a2713aSLionel Sambuc          << "A->" << getLowerName() << "_size()";
951f4a2713aSLionel Sambuc     }
952f4a2713aSLionel Sambuc 
writeTemplateInstantiation(raw_ostream & OS) const953*0a6a1f1dSLionel Sambuc     void writeTemplateInstantiation(raw_ostream &OS) const override {
954f4a2713aSLionel Sambuc       OS << "      " << getType() << " *tempInst" << getUpperName()
955f4a2713aSLionel Sambuc          << " = new (C, 16) " << getType()
956f4a2713aSLionel Sambuc          << "[A->" << getLowerName() << "_size()];\n";
957f4a2713aSLionel Sambuc       OS << "      {\n";
958f4a2713aSLionel Sambuc       OS << "        EnterExpressionEvaluationContext "
959f4a2713aSLionel Sambuc          << "Unevaluated(S, Sema::Unevaluated);\n";
960f4a2713aSLionel Sambuc       OS << "        " << getType() << " *TI = tempInst" << getUpperName()
961f4a2713aSLionel Sambuc          << ";\n";
962f4a2713aSLionel Sambuc       OS << "        " << getType() << " *I = A->" << getLowerName()
963f4a2713aSLionel Sambuc          << "_begin();\n";
964f4a2713aSLionel Sambuc       OS << "        " << getType() << " *E = A->" << getLowerName()
965f4a2713aSLionel Sambuc          << "_end();\n";
966f4a2713aSLionel Sambuc       OS << "        for (; I != E; ++I, ++TI) {\n";
967f4a2713aSLionel Sambuc       OS << "          ExprResult Result = S.SubstExpr(*I, TemplateArgs);\n";
968*0a6a1f1dSLionel Sambuc       OS << "          *TI = Result.getAs<Expr>();\n";
969f4a2713aSLionel Sambuc       OS << "        }\n";
970f4a2713aSLionel Sambuc       OS << "      }\n";
971f4a2713aSLionel Sambuc     }
972f4a2713aSLionel Sambuc 
writeDump(raw_ostream & OS) const973*0a6a1f1dSLionel Sambuc     void writeDump(raw_ostream &OS) const override {}
974f4a2713aSLionel Sambuc 
writeDumpChildren(raw_ostream & OS) const975*0a6a1f1dSLionel Sambuc     void writeDumpChildren(raw_ostream &OS) const override {
976f4a2713aSLionel Sambuc       OS << "    for (" << getAttrName() << "Attr::" << getLowerName()
977f4a2713aSLionel Sambuc          << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
978*0a6a1f1dSLionel Sambuc          << getLowerName() << "_end(); I != E; ++I)\n";
979f4a2713aSLionel Sambuc       OS << "      dumpStmt(*I);\n";
980f4a2713aSLionel Sambuc     }
981f4a2713aSLionel Sambuc 
writeHasChildren(raw_ostream & OS) const982*0a6a1f1dSLionel Sambuc     void writeHasChildren(raw_ostream &OS) const override {
983f4a2713aSLionel Sambuc       OS << "SA->" << getLowerName() << "_begin() != "
984f4a2713aSLionel Sambuc          << "SA->" << getLowerName() << "_end()";
985f4a2713aSLionel Sambuc     }
986f4a2713aSLionel Sambuc   };
987f4a2713aSLionel Sambuc 
988f4a2713aSLionel Sambuc   class TypeArgument : public SimpleArgument {
989f4a2713aSLionel Sambuc   public:
TypeArgument(const Record & Arg,StringRef Attr)990*0a6a1f1dSLionel Sambuc     TypeArgument(const Record &Arg, StringRef Attr)
991f4a2713aSLionel Sambuc       : SimpleArgument(Arg, Attr, "TypeSourceInfo *")
992f4a2713aSLionel Sambuc     {}
993f4a2713aSLionel Sambuc 
writeAccessors(raw_ostream & OS) const994*0a6a1f1dSLionel Sambuc     void writeAccessors(raw_ostream &OS) const override {
995f4a2713aSLionel Sambuc       OS << "  QualType get" << getUpperName() << "() const {\n";
996f4a2713aSLionel Sambuc       OS << "    return " << getLowerName() << "->getType();\n";
997f4a2713aSLionel Sambuc       OS << "  }";
998f4a2713aSLionel Sambuc       OS << "  " << getType() << " get" << getUpperName() << "Loc() const {\n";
999f4a2713aSLionel Sambuc       OS << "    return " << getLowerName() << ";\n";
1000f4a2713aSLionel Sambuc       OS << "  }";
1001f4a2713aSLionel Sambuc     }
writeTemplateInstantiationArgs(raw_ostream & OS) const1002*0a6a1f1dSLionel Sambuc     void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
1003f4a2713aSLionel Sambuc       OS << "A->get" << getUpperName() << "Loc()";
1004f4a2713aSLionel Sambuc     }
writePCHWrite(raw_ostream & OS) const1005*0a6a1f1dSLionel Sambuc     void writePCHWrite(raw_ostream &OS) const override {
1006f4a2713aSLionel Sambuc       OS << "    " << WritePCHRecord(
1007f4a2713aSLionel Sambuc           getType(), "SA->get" + std::string(getUpperName()) + "Loc()");
1008f4a2713aSLionel Sambuc     }
1009f4a2713aSLionel Sambuc   };
1010f4a2713aSLionel Sambuc }
1011f4a2713aSLionel Sambuc 
1012*0a6a1f1dSLionel Sambuc static std::unique_ptr<Argument>
createArgument(const Record & Arg,StringRef Attr,const Record * Search=nullptr)1013*0a6a1f1dSLionel Sambuc createArgument(const Record &Arg, StringRef Attr,
1014*0a6a1f1dSLionel Sambuc                const Record *Search = nullptr) {
1015f4a2713aSLionel Sambuc   if (!Search)
1016f4a2713aSLionel Sambuc     Search = &Arg;
1017f4a2713aSLionel Sambuc 
1018*0a6a1f1dSLionel Sambuc   std::unique_ptr<Argument> Ptr;
1019f4a2713aSLionel Sambuc   llvm::StringRef ArgName = Search->getName();
1020f4a2713aSLionel Sambuc 
1021*0a6a1f1dSLionel Sambuc   if (ArgName == "AlignedArgument")
1022*0a6a1f1dSLionel Sambuc     Ptr = llvm::make_unique<AlignedArgument>(Arg, Attr);
1023*0a6a1f1dSLionel Sambuc   else if (ArgName == "EnumArgument")
1024*0a6a1f1dSLionel Sambuc     Ptr = llvm::make_unique<EnumArgument>(Arg, Attr);
1025*0a6a1f1dSLionel Sambuc   else if (ArgName == "ExprArgument")
1026*0a6a1f1dSLionel Sambuc     Ptr = llvm::make_unique<ExprArgument>(Arg, Attr);
1027f4a2713aSLionel Sambuc   else if (ArgName == "FunctionArgument")
1028*0a6a1f1dSLionel Sambuc     Ptr = llvm::make_unique<SimpleArgument>(Arg, Attr, "FunctionDecl *");
1029f4a2713aSLionel Sambuc   else if (ArgName == "IdentifierArgument")
1030*0a6a1f1dSLionel Sambuc     Ptr = llvm::make_unique<SimpleArgument>(Arg, Attr, "IdentifierInfo *");
1031*0a6a1f1dSLionel Sambuc   else if (ArgName == "DefaultBoolArgument")
1032*0a6a1f1dSLionel Sambuc     Ptr = llvm::make_unique<DefaultSimpleArgument>(
1033*0a6a1f1dSLionel Sambuc         Arg, Attr, "bool", Arg.getValueAsBit("Default"));
1034*0a6a1f1dSLionel Sambuc   else if (ArgName == "BoolArgument")
1035*0a6a1f1dSLionel Sambuc     Ptr = llvm::make_unique<SimpleArgument>(Arg, Attr, "bool");
1036*0a6a1f1dSLionel Sambuc   else if (ArgName == "DefaultIntArgument")
1037*0a6a1f1dSLionel Sambuc     Ptr = llvm::make_unique<DefaultSimpleArgument>(
1038*0a6a1f1dSLionel Sambuc         Arg, Attr, "int", Arg.getValueAsInt("Default"));
1039*0a6a1f1dSLionel Sambuc   else if (ArgName == "IntArgument")
1040*0a6a1f1dSLionel Sambuc     Ptr = llvm::make_unique<SimpleArgument>(Arg, Attr, "int");
1041*0a6a1f1dSLionel Sambuc   else if (ArgName == "StringArgument")
1042*0a6a1f1dSLionel Sambuc     Ptr = llvm::make_unique<StringArgument>(Arg, Attr);
1043*0a6a1f1dSLionel Sambuc   else if (ArgName == "TypeArgument")
1044*0a6a1f1dSLionel Sambuc     Ptr = llvm::make_unique<TypeArgument>(Arg, Attr);
1045f4a2713aSLionel Sambuc   else if (ArgName == "UnsignedArgument")
1046*0a6a1f1dSLionel Sambuc     Ptr = llvm::make_unique<SimpleArgument>(Arg, Attr, "unsigned");
1047f4a2713aSLionel Sambuc   else if (ArgName == "VariadicUnsignedArgument")
1048*0a6a1f1dSLionel Sambuc     Ptr = llvm::make_unique<VariadicArgument>(Arg, Attr, "unsigned");
1049f4a2713aSLionel Sambuc   else if (ArgName == "VariadicEnumArgument")
1050*0a6a1f1dSLionel Sambuc     Ptr = llvm::make_unique<VariadicEnumArgument>(Arg, Attr);
1051f4a2713aSLionel Sambuc   else if (ArgName == "VariadicExprArgument")
1052*0a6a1f1dSLionel Sambuc     Ptr = llvm::make_unique<VariadicExprArgument>(Arg, Attr);
1053f4a2713aSLionel Sambuc   else if (ArgName == "VersionArgument")
1054*0a6a1f1dSLionel Sambuc     Ptr = llvm::make_unique<VersionArgument>(Arg, Attr);
1055f4a2713aSLionel Sambuc 
1056f4a2713aSLionel Sambuc   if (!Ptr) {
1057*0a6a1f1dSLionel Sambuc     // Search in reverse order so that the most-derived type is handled first.
1058f4a2713aSLionel Sambuc     std::vector<Record*> Bases = Search->getSuperClasses();
1059*0a6a1f1dSLionel Sambuc     for (const auto *Base : llvm::make_range(Bases.rbegin(), Bases.rend())) {
1060*0a6a1f1dSLionel Sambuc       if ((Ptr = createArgument(Arg, Attr, Base)))
1061f4a2713aSLionel Sambuc         break;
1062f4a2713aSLionel Sambuc     }
1063f4a2713aSLionel Sambuc   }
1064f4a2713aSLionel Sambuc 
1065f4a2713aSLionel Sambuc   if (Ptr && Arg.getValueAsBit("Optional"))
1066f4a2713aSLionel Sambuc     Ptr->setOptional(true);
1067f4a2713aSLionel Sambuc 
1068f4a2713aSLionel Sambuc   return Ptr;
1069f4a2713aSLionel Sambuc }
1070f4a2713aSLionel Sambuc 
writeAvailabilityValue(raw_ostream & OS)1071f4a2713aSLionel Sambuc static void writeAvailabilityValue(raw_ostream &OS) {
1072f4a2713aSLionel Sambuc   OS << "\" << getPlatform()->getName();\n"
1073f4a2713aSLionel Sambuc      << "  if (!getIntroduced().empty()) OS << \", introduced=\" << getIntroduced();\n"
1074f4a2713aSLionel Sambuc      << "  if (!getDeprecated().empty()) OS << \", deprecated=\" << getDeprecated();\n"
1075f4a2713aSLionel Sambuc      << "  if (!getObsoleted().empty()) OS << \", obsoleted=\" << getObsoleted();\n"
1076f4a2713aSLionel Sambuc      << "  if (getUnavailable()) OS << \", unavailable\";\n"
1077f4a2713aSLionel Sambuc      << "  OS << \"";
1078f4a2713aSLionel Sambuc }
1079f4a2713aSLionel Sambuc 
writeGetSpellingFunction(Record & R,raw_ostream & OS)1080*0a6a1f1dSLionel Sambuc static void writeGetSpellingFunction(Record &R, raw_ostream &OS) {
1081*0a6a1f1dSLionel Sambuc   std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
1082*0a6a1f1dSLionel Sambuc 
1083*0a6a1f1dSLionel Sambuc   OS << "const char *" << R.getName() << "Attr::getSpelling() const {\n";
1084*0a6a1f1dSLionel Sambuc   if (Spellings.empty()) {
1085*0a6a1f1dSLionel Sambuc     OS << "  return \"(No spelling)\";\n}\n\n";
1086*0a6a1f1dSLionel Sambuc     return;
1087*0a6a1f1dSLionel Sambuc   }
1088*0a6a1f1dSLionel Sambuc 
1089*0a6a1f1dSLionel Sambuc   OS << "  switch (SpellingListIndex) {\n"
1090*0a6a1f1dSLionel Sambuc         "  default:\n"
1091*0a6a1f1dSLionel Sambuc         "    llvm_unreachable(\"Unknown attribute spelling!\");\n"
1092*0a6a1f1dSLionel Sambuc         "    return \"(No spelling)\";\n";
1093*0a6a1f1dSLionel Sambuc 
1094*0a6a1f1dSLionel Sambuc   for (unsigned I = 0; I < Spellings.size(); ++I)
1095*0a6a1f1dSLionel Sambuc     OS << "  case " << I << ":\n"
1096*0a6a1f1dSLionel Sambuc           "    return \"" << Spellings[I].name() << "\";\n";
1097*0a6a1f1dSLionel Sambuc   // End of the switch statement.
1098*0a6a1f1dSLionel Sambuc   OS << "  }\n";
1099*0a6a1f1dSLionel Sambuc   // End of the getSpelling function.
1100*0a6a1f1dSLionel Sambuc   OS << "}\n\n";
1101*0a6a1f1dSLionel Sambuc }
1102*0a6a1f1dSLionel Sambuc 
1103*0a6a1f1dSLionel Sambuc static void
writePrettyPrintFunction(Record & R,const std::vector<std::unique_ptr<Argument>> & Args,raw_ostream & OS)1104*0a6a1f1dSLionel Sambuc writePrettyPrintFunction(Record &R,
1105*0a6a1f1dSLionel Sambuc                          const std::vector<std::unique_ptr<Argument>> &Args,
1106f4a2713aSLionel Sambuc                          raw_ostream &OS) {
1107*0a6a1f1dSLionel Sambuc   std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
1108f4a2713aSLionel Sambuc 
1109f4a2713aSLionel Sambuc   OS << "void " << R.getName() << "Attr::printPretty("
1110f4a2713aSLionel Sambuc     << "raw_ostream &OS, const PrintingPolicy &Policy) const {\n";
1111f4a2713aSLionel Sambuc 
1112*0a6a1f1dSLionel Sambuc   if (Spellings.empty()) {
1113f4a2713aSLionel Sambuc     OS << "}\n\n";
1114f4a2713aSLionel Sambuc     return;
1115f4a2713aSLionel Sambuc   }
1116f4a2713aSLionel Sambuc 
1117f4a2713aSLionel Sambuc   OS <<
1118f4a2713aSLionel Sambuc     "  switch (SpellingListIndex) {\n"
1119f4a2713aSLionel Sambuc     "  default:\n"
1120f4a2713aSLionel Sambuc     "    llvm_unreachable(\"Unknown attribute spelling!\");\n"
1121f4a2713aSLionel Sambuc     "    break;\n";
1122f4a2713aSLionel Sambuc 
1123f4a2713aSLionel Sambuc   for (unsigned I = 0; I < Spellings.size(); ++ I) {
1124f4a2713aSLionel Sambuc     llvm::SmallString<16> Prefix;
1125f4a2713aSLionel Sambuc     llvm::SmallString<8> Suffix;
1126f4a2713aSLionel Sambuc     // The actual spelling of the name and namespace (if applicable)
1127f4a2713aSLionel Sambuc     // of an attribute without considering prefix and suffix.
1128f4a2713aSLionel Sambuc     llvm::SmallString<64> Spelling;
1129*0a6a1f1dSLionel Sambuc     std::string Name = Spellings[I].name();
1130*0a6a1f1dSLionel Sambuc     std::string Variety = Spellings[I].variety();
1131f4a2713aSLionel Sambuc 
1132f4a2713aSLionel Sambuc     if (Variety == "GNU") {
1133f4a2713aSLionel Sambuc       Prefix = " __attribute__((";
1134f4a2713aSLionel Sambuc       Suffix = "))";
1135f4a2713aSLionel Sambuc     } else if (Variety == "CXX11") {
1136f4a2713aSLionel Sambuc       Prefix = " [[";
1137f4a2713aSLionel Sambuc       Suffix = "]]";
1138*0a6a1f1dSLionel Sambuc       std::string Namespace = Spellings[I].nameSpace();
1139*0a6a1f1dSLionel Sambuc       if (!Namespace.empty()) {
1140f4a2713aSLionel Sambuc         Spelling += Namespace;
1141f4a2713aSLionel Sambuc         Spelling += "::";
1142f4a2713aSLionel Sambuc       }
1143f4a2713aSLionel Sambuc     } else if (Variety == "Declspec") {
1144f4a2713aSLionel Sambuc       Prefix = " __declspec(";
1145f4a2713aSLionel Sambuc       Suffix = ")";
1146f4a2713aSLionel Sambuc     } else if (Variety == "Keyword") {
1147f4a2713aSLionel Sambuc       Prefix = " ";
1148f4a2713aSLionel Sambuc       Suffix = "";
1149*0a6a1f1dSLionel Sambuc     } else if (Variety == "Pragma") {
1150*0a6a1f1dSLionel Sambuc       Prefix = "#pragma ";
1151*0a6a1f1dSLionel Sambuc       Suffix = "\n";
1152*0a6a1f1dSLionel Sambuc       std::string Namespace = Spellings[I].nameSpace();
1153*0a6a1f1dSLionel Sambuc       if (!Namespace.empty()) {
1154*0a6a1f1dSLionel Sambuc         Spelling += Namespace;
1155*0a6a1f1dSLionel Sambuc         Spelling += " ";
1156*0a6a1f1dSLionel Sambuc       }
1157f4a2713aSLionel Sambuc     } else {
1158f4a2713aSLionel Sambuc       llvm_unreachable("Unknown attribute syntax variety!");
1159f4a2713aSLionel Sambuc     }
1160f4a2713aSLionel Sambuc 
1161f4a2713aSLionel Sambuc     Spelling += Name;
1162f4a2713aSLionel Sambuc 
1163f4a2713aSLionel Sambuc     OS <<
1164f4a2713aSLionel Sambuc       "  case " << I << " : {\n"
1165f4a2713aSLionel Sambuc       "    OS << \"" + Prefix.str() + Spelling.str();
1166f4a2713aSLionel Sambuc 
1167*0a6a1f1dSLionel Sambuc     if (Variety == "Pragma") {
1168*0a6a1f1dSLionel Sambuc       OS << " \";\n";
1169*0a6a1f1dSLionel Sambuc       OS << "    printPrettyPragma(OS, Policy);\n";
1170*0a6a1f1dSLionel Sambuc       OS << "    break;\n";
1171*0a6a1f1dSLionel Sambuc       OS << "  }\n";
1172*0a6a1f1dSLionel Sambuc       continue;
1173*0a6a1f1dSLionel Sambuc     }
1174*0a6a1f1dSLionel Sambuc 
1175*0a6a1f1dSLionel Sambuc     // FIXME: always printing the parenthesis isn't the correct behavior for
1176*0a6a1f1dSLionel Sambuc     // attributes which have optional arguments that were not provided. For
1177*0a6a1f1dSLionel Sambuc     // instance: __attribute__((aligned)) will be pretty printed as
1178*0a6a1f1dSLionel Sambuc     // __attribute__((aligned())). The logic should check whether there is only
1179*0a6a1f1dSLionel Sambuc     // a single argument, and if it is optional, whether it has been provided.
1180*0a6a1f1dSLionel Sambuc     if (!Args.empty())
1181*0a6a1f1dSLionel Sambuc       OS << "(";
1182f4a2713aSLionel Sambuc     if (Spelling == "availability") {
1183f4a2713aSLionel Sambuc       writeAvailabilityValue(OS);
1184f4a2713aSLionel Sambuc     } else {
1185*0a6a1f1dSLionel Sambuc       for (auto I = Args.begin(), E = Args.end(); I != E; ++ I) {
1186f4a2713aSLionel Sambuc         if (I != Args.begin()) OS << ", ";
1187f4a2713aSLionel Sambuc         (*I)->writeValue(OS);
1188f4a2713aSLionel Sambuc       }
1189f4a2713aSLionel Sambuc     }
1190f4a2713aSLionel Sambuc 
1191*0a6a1f1dSLionel Sambuc     if (!Args.empty())
1192*0a6a1f1dSLionel Sambuc       OS << ")";
1193f4a2713aSLionel Sambuc     OS << Suffix.str() + "\";\n";
1194f4a2713aSLionel Sambuc 
1195f4a2713aSLionel Sambuc     OS <<
1196f4a2713aSLionel Sambuc       "    break;\n"
1197f4a2713aSLionel Sambuc       "  }\n";
1198f4a2713aSLionel Sambuc   }
1199f4a2713aSLionel Sambuc 
1200f4a2713aSLionel Sambuc   // End of the switch statement.
1201f4a2713aSLionel Sambuc   OS << "}\n";
1202f4a2713aSLionel Sambuc   // End of the print function.
1203f4a2713aSLionel Sambuc   OS << "}\n\n";
1204f4a2713aSLionel Sambuc }
1205f4a2713aSLionel Sambuc 
1206f4a2713aSLionel Sambuc /// \brief Return the index of a spelling in a spelling list.
1207*0a6a1f1dSLionel Sambuc static unsigned
getSpellingListIndex(const std::vector<FlattenedSpelling> & SpellingList,const FlattenedSpelling & Spelling)1208*0a6a1f1dSLionel Sambuc getSpellingListIndex(const std::vector<FlattenedSpelling> &SpellingList,
1209*0a6a1f1dSLionel Sambuc                      const FlattenedSpelling &Spelling) {
1210f4a2713aSLionel Sambuc   assert(SpellingList.size() && "Spelling list is empty!");
1211f4a2713aSLionel Sambuc 
1212f4a2713aSLionel Sambuc   for (unsigned Index = 0; Index < SpellingList.size(); ++Index) {
1213*0a6a1f1dSLionel Sambuc     const FlattenedSpelling &S = SpellingList[Index];
1214*0a6a1f1dSLionel Sambuc     if (S.variety() != Spelling.variety())
1215f4a2713aSLionel Sambuc       continue;
1216*0a6a1f1dSLionel Sambuc     if (S.nameSpace() != Spelling.nameSpace())
1217f4a2713aSLionel Sambuc       continue;
1218*0a6a1f1dSLionel Sambuc     if (S.name() != Spelling.name())
1219f4a2713aSLionel Sambuc       continue;
1220f4a2713aSLionel Sambuc 
1221f4a2713aSLionel Sambuc     return Index;
1222f4a2713aSLionel Sambuc   }
1223f4a2713aSLionel Sambuc 
1224f4a2713aSLionel Sambuc   llvm_unreachable("Unknown spelling!");
1225f4a2713aSLionel Sambuc }
1226f4a2713aSLionel Sambuc 
writeAttrAccessorDefinition(const Record & R,raw_ostream & OS)1227*0a6a1f1dSLionel Sambuc static void writeAttrAccessorDefinition(const Record &R, raw_ostream &OS) {
1228f4a2713aSLionel Sambuc   std::vector<Record*> Accessors = R.getValueAsListOfDefs("Accessors");
1229*0a6a1f1dSLionel Sambuc   for (const auto *Accessor : Accessors) {
1230f4a2713aSLionel Sambuc     std::string Name = Accessor->getValueAsString("Name");
1231*0a6a1f1dSLionel Sambuc     std::vector<FlattenedSpelling> Spellings =
1232*0a6a1f1dSLionel Sambuc       GetFlattenedSpellings(*Accessor);
1233*0a6a1f1dSLionel Sambuc     std::vector<FlattenedSpelling> SpellingList = GetFlattenedSpellings(R);
1234f4a2713aSLionel Sambuc     assert(SpellingList.size() &&
1235f4a2713aSLionel Sambuc            "Attribute with empty spelling list can't have accessors!");
1236f4a2713aSLionel Sambuc 
1237f4a2713aSLionel Sambuc     OS << "  bool " << Name << "() const { return SpellingListIndex == ";
1238f4a2713aSLionel Sambuc     for (unsigned Index = 0; Index < Spellings.size(); ++Index) {
1239*0a6a1f1dSLionel Sambuc       OS << getSpellingListIndex(SpellingList, Spellings[Index]);
1240f4a2713aSLionel Sambuc       if (Index != Spellings.size() -1)
1241f4a2713aSLionel Sambuc         OS << " ||\n    SpellingListIndex == ";
1242f4a2713aSLionel Sambuc       else
1243f4a2713aSLionel Sambuc         OS << "; }\n";
1244f4a2713aSLionel Sambuc     }
1245f4a2713aSLionel Sambuc   }
1246f4a2713aSLionel Sambuc }
1247f4a2713aSLionel Sambuc 
1248*0a6a1f1dSLionel Sambuc static bool
SpellingNamesAreCommon(const std::vector<FlattenedSpelling> & Spellings)1249*0a6a1f1dSLionel Sambuc SpellingNamesAreCommon(const std::vector<FlattenedSpelling>& Spellings) {
1250*0a6a1f1dSLionel Sambuc   assert(!Spellings.empty() && "An empty list of spellings was provided");
1251*0a6a1f1dSLionel Sambuc   std::string FirstName = NormalizeNameForSpellingComparison(
1252*0a6a1f1dSLionel Sambuc     Spellings.front().name());
1253*0a6a1f1dSLionel Sambuc   for (const auto &Spelling :
1254*0a6a1f1dSLionel Sambuc        llvm::make_range(std::next(Spellings.begin()), Spellings.end())) {
1255*0a6a1f1dSLionel Sambuc     std::string Name = NormalizeNameForSpellingComparison(Spelling.name());
1256*0a6a1f1dSLionel Sambuc     if (Name != FirstName)
1257*0a6a1f1dSLionel Sambuc       return false;
1258*0a6a1f1dSLionel Sambuc   }
1259*0a6a1f1dSLionel Sambuc   return true;
1260*0a6a1f1dSLionel Sambuc }
1261*0a6a1f1dSLionel Sambuc 
1262*0a6a1f1dSLionel Sambuc typedef std::map<unsigned, std::string> SemanticSpellingMap;
1263*0a6a1f1dSLionel Sambuc static std::string
CreateSemanticSpellings(const std::vector<FlattenedSpelling> & Spellings,SemanticSpellingMap & Map)1264*0a6a1f1dSLionel Sambuc CreateSemanticSpellings(const std::vector<FlattenedSpelling> &Spellings,
1265*0a6a1f1dSLionel Sambuc                         SemanticSpellingMap &Map) {
1266*0a6a1f1dSLionel Sambuc   // The enumerants are automatically generated based on the variety,
1267*0a6a1f1dSLionel Sambuc   // namespace (if present) and name for each attribute spelling. However,
1268*0a6a1f1dSLionel Sambuc   // care is taken to avoid trampling on the reserved namespace due to
1269*0a6a1f1dSLionel Sambuc   // underscores.
1270*0a6a1f1dSLionel Sambuc   std::string Ret("  enum Spelling {\n");
1271*0a6a1f1dSLionel Sambuc   std::set<std::string> Uniques;
1272*0a6a1f1dSLionel Sambuc   unsigned Idx = 0;
1273*0a6a1f1dSLionel Sambuc   for (auto I = Spellings.begin(), E = Spellings.end(); I != E; ++I, ++Idx) {
1274*0a6a1f1dSLionel Sambuc     const FlattenedSpelling &S = *I;
1275*0a6a1f1dSLionel Sambuc     std::string Variety = S.variety();
1276*0a6a1f1dSLionel Sambuc     std::string Spelling = S.name();
1277*0a6a1f1dSLionel Sambuc     std::string Namespace = S.nameSpace();
1278*0a6a1f1dSLionel Sambuc     std::string EnumName = "";
1279*0a6a1f1dSLionel Sambuc 
1280*0a6a1f1dSLionel Sambuc     EnumName += (Variety + "_");
1281*0a6a1f1dSLionel Sambuc     if (!Namespace.empty())
1282*0a6a1f1dSLionel Sambuc       EnumName += (NormalizeNameForSpellingComparison(Namespace).str() +
1283*0a6a1f1dSLionel Sambuc       "_");
1284*0a6a1f1dSLionel Sambuc     EnumName += NormalizeNameForSpellingComparison(Spelling);
1285*0a6a1f1dSLionel Sambuc 
1286*0a6a1f1dSLionel Sambuc     // Even if the name is not unique, this spelling index corresponds to a
1287*0a6a1f1dSLionel Sambuc     // particular enumerant name that we've calculated.
1288*0a6a1f1dSLionel Sambuc     Map[Idx] = EnumName;
1289*0a6a1f1dSLionel Sambuc 
1290*0a6a1f1dSLionel Sambuc     // Since we have been stripping underscores to avoid trampling on the
1291*0a6a1f1dSLionel Sambuc     // reserved namespace, we may have inadvertently created duplicate
1292*0a6a1f1dSLionel Sambuc     // enumerant names. These duplicates are not considered part of the
1293*0a6a1f1dSLionel Sambuc     // semantic spelling, and can be elided.
1294*0a6a1f1dSLionel Sambuc     if (Uniques.find(EnumName) != Uniques.end())
1295*0a6a1f1dSLionel Sambuc       continue;
1296*0a6a1f1dSLionel Sambuc 
1297*0a6a1f1dSLionel Sambuc     Uniques.insert(EnumName);
1298*0a6a1f1dSLionel Sambuc     if (I != Spellings.begin())
1299*0a6a1f1dSLionel Sambuc       Ret += ",\n";
1300*0a6a1f1dSLionel Sambuc     Ret += "    " + EnumName;
1301*0a6a1f1dSLionel Sambuc   }
1302*0a6a1f1dSLionel Sambuc   Ret += "\n  };\n\n";
1303*0a6a1f1dSLionel Sambuc   return Ret;
1304*0a6a1f1dSLionel Sambuc }
1305*0a6a1f1dSLionel Sambuc 
WriteSemanticSpellingSwitch(const std::string & VarName,const SemanticSpellingMap & Map,raw_ostream & OS)1306*0a6a1f1dSLionel Sambuc void WriteSemanticSpellingSwitch(const std::string &VarName,
1307*0a6a1f1dSLionel Sambuc                                  const SemanticSpellingMap &Map,
1308*0a6a1f1dSLionel Sambuc                                  raw_ostream &OS) {
1309*0a6a1f1dSLionel Sambuc   OS << "  switch (" << VarName << ") {\n    default: "
1310*0a6a1f1dSLionel Sambuc     << "llvm_unreachable(\"Unknown spelling list index\");\n";
1311*0a6a1f1dSLionel Sambuc   for (const auto &I : Map)
1312*0a6a1f1dSLionel Sambuc     OS << "    case " << I.first << ": return " << I.second << ";\n";
1313*0a6a1f1dSLionel Sambuc   OS << "  }\n";
1314*0a6a1f1dSLionel Sambuc }
1315*0a6a1f1dSLionel Sambuc 
1316*0a6a1f1dSLionel Sambuc // Emits the LateParsed property for attributes.
emitClangAttrLateParsedList(RecordKeeper & Records,raw_ostream & OS)1317*0a6a1f1dSLionel Sambuc static void emitClangAttrLateParsedList(RecordKeeper &Records, raw_ostream &OS) {
1318*0a6a1f1dSLionel Sambuc   OS << "#if defined(CLANG_ATTR_LATE_PARSED_LIST)\n";
1319*0a6a1f1dSLionel Sambuc   std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1320*0a6a1f1dSLionel Sambuc 
1321*0a6a1f1dSLionel Sambuc   for (const auto *Attr : Attrs) {
1322*0a6a1f1dSLionel Sambuc     bool LateParsed = Attr->getValueAsBit("LateParsed");
1323*0a6a1f1dSLionel Sambuc 
1324*0a6a1f1dSLionel Sambuc     if (LateParsed) {
1325*0a6a1f1dSLionel Sambuc       std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr);
1326*0a6a1f1dSLionel Sambuc 
1327*0a6a1f1dSLionel Sambuc       // FIXME: Handle non-GNU attributes
1328*0a6a1f1dSLionel Sambuc       for (const auto &I : Spellings) {
1329*0a6a1f1dSLionel Sambuc         if (I.variety() != "GNU")
1330*0a6a1f1dSLionel Sambuc           continue;
1331*0a6a1f1dSLionel Sambuc         OS << ".Case(\"" << I.name() << "\", " << LateParsed << ")\n";
1332*0a6a1f1dSLionel Sambuc       }
1333*0a6a1f1dSLionel Sambuc     }
1334*0a6a1f1dSLionel Sambuc   }
1335*0a6a1f1dSLionel Sambuc   OS << "#endif // CLANG_ATTR_LATE_PARSED_LIST\n\n";
1336*0a6a1f1dSLionel Sambuc }
1337*0a6a1f1dSLionel Sambuc 
1338*0a6a1f1dSLionel Sambuc /// \brief Emits the first-argument-is-type property for attributes.
emitClangAttrTypeArgList(RecordKeeper & Records,raw_ostream & OS)1339*0a6a1f1dSLionel Sambuc static void emitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) {
1340*0a6a1f1dSLionel Sambuc   OS << "#if defined(CLANG_ATTR_TYPE_ARG_LIST)\n";
1341*0a6a1f1dSLionel Sambuc   std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
1342*0a6a1f1dSLionel Sambuc 
1343*0a6a1f1dSLionel Sambuc   for (const auto *Attr : Attrs) {
1344*0a6a1f1dSLionel Sambuc     // Determine whether the first argument is a type.
1345*0a6a1f1dSLionel Sambuc     std::vector<Record *> Args = Attr->getValueAsListOfDefs("Args");
1346*0a6a1f1dSLionel Sambuc     if (Args.empty())
1347*0a6a1f1dSLionel Sambuc       continue;
1348*0a6a1f1dSLionel Sambuc 
1349*0a6a1f1dSLionel Sambuc     if (Args[0]->getSuperClasses().back()->getName() != "TypeArgument")
1350*0a6a1f1dSLionel Sambuc       continue;
1351*0a6a1f1dSLionel Sambuc 
1352*0a6a1f1dSLionel Sambuc     // All these spellings take a single type argument.
1353*0a6a1f1dSLionel Sambuc     std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr);
1354*0a6a1f1dSLionel Sambuc     std::set<std::string> Emitted;
1355*0a6a1f1dSLionel Sambuc     for (const auto &S : Spellings) {
1356*0a6a1f1dSLionel Sambuc       if (Emitted.insert(S.name()).second)
1357*0a6a1f1dSLionel Sambuc         OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n";
1358*0a6a1f1dSLionel Sambuc     }
1359*0a6a1f1dSLionel Sambuc   }
1360*0a6a1f1dSLionel Sambuc   OS << "#endif // CLANG_ATTR_TYPE_ARG_LIST\n\n";
1361*0a6a1f1dSLionel Sambuc }
1362*0a6a1f1dSLionel Sambuc 
1363*0a6a1f1dSLionel Sambuc /// \brief Emits the parse-arguments-in-unevaluated-context property for
1364*0a6a1f1dSLionel Sambuc /// attributes.
emitClangAttrArgContextList(RecordKeeper & Records,raw_ostream & OS)1365*0a6a1f1dSLionel Sambuc static void emitClangAttrArgContextList(RecordKeeper &Records, raw_ostream &OS) {
1366*0a6a1f1dSLionel Sambuc   OS << "#if defined(CLANG_ATTR_ARG_CONTEXT_LIST)\n";
1367*0a6a1f1dSLionel Sambuc   ParsedAttrMap Attrs = getParsedAttrList(Records);
1368*0a6a1f1dSLionel Sambuc   for (const auto &I : Attrs) {
1369*0a6a1f1dSLionel Sambuc     const Record &Attr = *I.second;
1370*0a6a1f1dSLionel Sambuc 
1371*0a6a1f1dSLionel Sambuc     if (!Attr.getValueAsBit("ParseArgumentsAsUnevaluated"))
1372*0a6a1f1dSLionel Sambuc       continue;
1373*0a6a1f1dSLionel Sambuc 
1374*0a6a1f1dSLionel Sambuc     // All these spellings take are parsed unevaluated.
1375*0a6a1f1dSLionel Sambuc     std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
1376*0a6a1f1dSLionel Sambuc     std::set<std::string> Emitted;
1377*0a6a1f1dSLionel Sambuc     for (const auto &S : Spellings) {
1378*0a6a1f1dSLionel Sambuc       if (Emitted.insert(S.name()).second)
1379*0a6a1f1dSLionel Sambuc         OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n";
1380*0a6a1f1dSLionel Sambuc     }
1381*0a6a1f1dSLionel Sambuc   }
1382*0a6a1f1dSLionel Sambuc   OS << "#endif // CLANG_ATTR_ARG_CONTEXT_LIST\n\n";
1383*0a6a1f1dSLionel Sambuc }
1384*0a6a1f1dSLionel Sambuc 
isIdentifierArgument(Record * Arg)1385*0a6a1f1dSLionel Sambuc static bool isIdentifierArgument(Record *Arg) {
1386*0a6a1f1dSLionel Sambuc   return !Arg->getSuperClasses().empty() &&
1387*0a6a1f1dSLionel Sambuc     llvm::StringSwitch<bool>(Arg->getSuperClasses().back()->getName())
1388*0a6a1f1dSLionel Sambuc     .Case("IdentifierArgument", true)
1389*0a6a1f1dSLionel Sambuc     .Case("EnumArgument", true)
1390*0a6a1f1dSLionel Sambuc     .Case("VariadicEnumArgument", true)
1391*0a6a1f1dSLionel Sambuc     .Default(false);
1392*0a6a1f1dSLionel Sambuc }
1393*0a6a1f1dSLionel Sambuc 
1394*0a6a1f1dSLionel Sambuc // Emits the first-argument-is-identifier property for attributes.
emitClangAttrIdentifierArgList(RecordKeeper & Records,raw_ostream & OS)1395*0a6a1f1dSLionel Sambuc static void emitClangAttrIdentifierArgList(RecordKeeper &Records, raw_ostream &OS) {
1396*0a6a1f1dSLionel Sambuc   OS << "#if defined(CLANG_ATTR_IDENTIFIER_ARG_LIST)\n";
1397*0a6a1f1dSLionel Sambuc   std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1398*0a6a1f1dSLionel Sambuc 
1399*0a6a1f1dSLionel Sambuc   for (const auto *Attr : Attrs) {
1400*0a6a1f1dSLionel Sambuc     // Determine whether the first argument is an identifier.
1401*0a6a1f1dSLionel Sambuc     std::vector<Record *> Args = Attr->getValueAsListOfDefs("Args");
1402*0a6a1f1dSLionel Sambuc     if (Args.empty() || !isIdentifierArgument(Args[0]))
1403*0a6a1f1dSLionel Sambuc       continue;
1404*0a6a1f1dSLionel Sambuc 
1405*0a6a1f1dSLionel Sambuc     // All these spellings take an identifier argument.
1406*0a6a1f1dSLionel Sambuc     std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr);
1407*0a6a1f1dSLionel Sambuc     std::set<std::string> Emitted;
1408*0a6a1f1dSLionel Sambuc     for (const auto &S : Spellings) {
1409*0a6a1f1dSLionel Sambuc       if (Emitted.insert(S.name()).second)
1410*0a6a1f1dSLionel Sambuc         OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n";
1411*0a6a1f1dSLionel Sambuc     }
1412*0a6a1f1dSLionel Sambuc   }
1413*0a6a1f1dSLionel Sambuc   OS << "#endif // CLANG_ATTR_IDENTIFIER_ARG_LIST\n\n";
1414*0a6a1f1dSLionel Sambuc }
1415*0a6a1f1dSLionel Sambuc 
1416f4a2713aSLionel Sambuc namespace clang {
1417f4a2713aSLionel Sambuc 
1418f4a2713aSLionel Sambuc // Emits the class definitions for attributes.
EmitClangAttrClass(RecordKeeper & Records,raw_ostream & OS)1419f4a2713aSLionel Sambuc void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
1420f4a2713aSLionel Sambuc   emitSourceFileHeader("Attribute classes' definitions", OS);
1421f4a2713aSLionel Sambuc 
1422f4a2713aSLionel Sambuc   OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
1423f4a2713aSLionel Sambuc   OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
1424f4a2713aSLionel Sambuc 
1425f4a2713aSLionel Sambuc   std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1426f4a2713aSLionel Sambuc 
1427*0a6a1f1dSLionel Sambuc   for (const auto *Attr : Attrs) {
1428*0a6a1f1dSLionel Sambuc     const Record &R = *Attr;
1429*0a6a1f1dSLionel Sambuc 
1430*0a6a1f1dSLionel Sambuc     // FIXME: Currently, documentation is generated as-needed due to the fact
1431*0a6a1f1dSLionel Sambuc     // that there is no way to allow a generated project "reach into" the docs
1432*0a6a1f1dSLionel Sambuc     // directory (for instance, it may be an out-of-tree build). However, we want
1433*0a6a1f1dSLionel Sambuc     // to ensure that every attribute has a Documentation field, and produce an
1434*0a6a1f1dSLionel Sambuc     // error if it has been neglected. Otherwise, the on-demand generation which
1435*0a6a1f1dSLionel Sambuc     // happens server-side will fail. This code is ensuring that functionality,
1436*0a6a1f1dSLionel Sambuc     // even though this Emitter doesn't technically need the documentation.
1437*0a6a1f1dSLionel Sambuc     // When attribute documentation can be generated as part of the build
1438*0a6a1f1dSLionel Sambuc     // itself, this code can be removed.
1439*0a6a1f1dSLionel Sambuc     (void)R.getValueAsListOfDefs("Documentation");
1440f4a2713aSLionel Sambuc 
1441f4a2713aSLionel Sambuc     if (!R.getValueAsBit("ASTNode"))
1442f4a2713aSLionel Sambuc       continue;
1443f4a2713aSLionel Sambuc 
1444f4a2713aSLionel Sambuc     const std::vector<Record *> Supers = R.getSuperClasses();
1445f4a2713aSLionel Sambuc     assert(!Supers.empty() && "Forgot to specify a superclass for the attr");
1446f4a2713aSLionel Sambuc     std::string SuperName;
1447*0a6a1f1dSLionel Sambuc     for (const auto *Super : llvm::make_range(Supers.rbegin(), Supers.rend())) {
1448*0a6a1f1dSLionel Sambuc       const Record &R = *Super;
1449f4a2713aSLionel Sambuc       if (R.getName() != "TargetSpecificAttr" && SuperName.empty())
1450f4a2713aSLionel Sambuc         SuperName = R.getName();
1451f4a2713aSLionel Sambuc     }
1452f4a2713aSLionel Sambuc 
1453f4a2713aSLionel Sambuc     OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n";
1454f4a2713aSLionel Sambuc 
1455f4a2713aSLionel Sambuc     std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
1456*0a6a1f1dSLionel Sambuc     std::vector<std::unique_ptr<Argument>> Args;
1457f4a2713aSLionel Sambuc     Args.reserve(ArgRecords.size());
1458f4a2713aSLionel Sambuc 
1459*0a6a1f1dSLionel Sambuc     for (const auto *ArgRecord : ArgRecords) {
1460*0a6a1f1dSLionel Sambuc       Args.emplace_back(createArgument(*ArgRecord, R.getName()));
1461*0a6a1f1dSLionel Sambuc       Args.back()->writeDeclarations(OS);
1462f4a2713aSLionel Sambuc       OS << "\n\n";
1463f4a2713aSLionel Sambuc     }
1464f4a2713aSLionel Sambuc 
1465f4a2713aSLionel Sambuc     OS << "\npublic:\n";
1466*0a6a1f1dSLionel Sambuc 
1467*0a6a1f1dSLionel Sambuc     std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
1468*0a6a1f1dSLionel Sambuc 
1469*0a6a1f1dSLionel Sambuc     // If there are zero or one spellings, all spelling-related functionality
1470*0a6a1f1dSLionel Sambuc     // can be elided. If all of the spellings share the same name, the spelling
1471*0a6a1f1dSLionel Sambuc     // functionality can also be elided.
1472*0a6a1f1dSLionel Sambuc     bool ElideSpelling = (Spellings.size() <= 1) ||
1473*0a6a1f1dSLionel Sambuc                          SpellingNamesAreCommon(Spellings);
1474*0a6a1f1dSLionel Sambuc 
1475*0a6a1f1dSLionel Sambuc     // This maps spelling index values to semantic Spelling enumerants.
1476*0a6a1f1dSLionel Sambuc     SemanticSpellingMap SemanticToSyntacticMap;
1477*0a6a1f1dSLionel Sambuc 
1478*0a6a1f1dSLionel Sambuc     if (!ElideSpelling)
1479*0a6a1f1dSLionel Sambuc       OS << CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);
1480*0a6a1f1dSLionel Sambuc 
1481*0a6a1f1dSLionel Sambuc     OS << "  static " << R.getName() << "Attr *CreateImplicit(";
1482*0a6a1f1dSLionel Sambuc     OS << "ASTContext &Ctx";
1483*0a6a1f1dSLionel Sambuc     if (!ElideSpelling)
1484*0a6a1f1dSLionel Sambuc       OS << ", Spelling S";
1485*0a6a1f1dSLionel Sambuc     for (auto const &ai : Args) {
1486*0a6a1f1dSLionel Sambuc       OS << ", ";
1487*0a6a1f1dSLionel Sambuc       ai->writeCtorParameters(OS);
1488*0a6a1f1dSLionel Sambuc     }
1489*0a6a1f1dSLionel Sambuc     OS << ", SourceRange Loc = SourceRange()";
1490*0a6a1f1dSLionel Sambuc     OS << ") {\n";
1491*0a6a1f1dSLionel Sambuc     OS << "    " << R.getName() << "Attr *A = new (Ctx) " << R.getName();
1492*0a6a1f1dSLionel Sambuc     OS << "Attr(Loc, Ctx, ";
1493*0a6a1f1dSLionel Sambuc     for (auto const &ai : Args) {
1494*0a6a1f1dSLionel Sambuc       ai->writeImplicitCtorArgs(OS);
1495*0a6a1f1dSLionel Sambuc       OS << ", ";
1496*0a6a1f1dSLionel Sambuc     }
1497*0a6a1f1dSLionel Sambuc     OS << (ElideSpelling ? "0" : "S") << ");\n";
1498*0a6a1f1dSLionel Sambuc     OS << "    A->setImplicit(true);\n";
1499*0a6a1f1dSLionel Sambuc     OS << "    return A;\n  }\n\n";
1500*0a6a1f1dSLionel Sambuc 
1501f4a2713aSLionel Sambuc     OS << "  " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
1502f4a2713aSLionel Sambuc 
1503f4a2713aSLionel Sambuc     bool HasOpt = false;
1504*0a6a1f1dSLionel Sambuc     for (auto const &ai : Args) {
1505f4a2713aSLionel Sambuc       OS << "              , ";
1506*0a6a1f1dSLionel Sambuc       ai->writeCtorParameters(OS);
1507f4a2713aSLionel Sambuc       OS << "\n";
1508*0a6a1f1dSLionel Sambuc       if (ai->isOptional())
1509f4a2713aSLionel Sambuc         HasOpt = true;
1510f4a2713aSLionel Sambuc     }
1511f4a2713aSLionel Sambuc 
1512f4a2713aSLionel Sambuc     OS << "              , ";
1513*0a6a1f1dSLionel Sambuc     OS << "unsigned SI\n";
1514f4a2713aSLionel Sambuc 
1515f4a2713aSLionel Sambuc     OS << "             )\n";
1516f4a2713aSLionel Sambuc     OS << "    : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n";
1517f4a2713aSLionel Sambuc 
1518*0a6a1f1dSLionel Sambuc     for (auto const &ai : Args) {
1519f4a2713aSLionel Sambuc       OS << "              , ";
1520*0a6a1f1dSLionel Sambuc       ai->writeCtorInitializers(OS);
1521f4a2713aSLionel Sambuc       OS << "\n";
1522f4a2713aSLionel Sambuc     }
1523f4a2713aSLionel Sambuc 
1524f4a2713aSLionel Sambuc     OS << "  {\n";
1525f4a2713aSLionel Sambuc 
1526*0a6a1f1dSLionel Sambuc     for (auto const &ai : Args) {
1527*0a6a1f1dSLionel Sambuc       ai->writeCtorBody(OS);
1528f4a2713aSLionel Sambuc       OS << "\n";
1529f4a2713aSLionel Sambuc     }
1530f4a2713aSLionel Sambuc     OS << "  }\n\n";
1531f4a2713aSLionel Sambuc 
1532f4a2713aSLionel Sambuc     // If there are optional arguments, write out a constructor that elides the
1533f4a2713aSLionel Sambuc     // optional arguments as well.
1534f4a2713aSLionel Sambuc     if (HasOpt) {
1535f4a2713aSLionel Sambuc       OS << "  " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
1536*0a6a1f1dSLionel Sambuc       for (auto const &ai : Args) {
1537*0a6a1f1dSLionel Sambuc         if (!ai->isOptional()) {
1538f4a2713aSLionel Sambuc           OS << "              , ";
1539*0a6a1f1dSLionel Sambuc           ai->writeCtorParameters(OS);
1540f4a2713aSLionel Sambuc           OS << "\n";
1541f4a2713aSLionel Sambuc         }
1542f4a2713aSLionel Sambuc       }
1543f4a2713aSLionel Sambuc 
1544f4a2713aSLionel Sambuc       OS << "              , ";
1545*0a6a1f1dSLionel Sambuc       OS << "unsigned SI\n";
1546f4a2713aSLionel Sambuc 
1547f4a2713aSLionel Sambuc       OS << "             )\n";
1548f4a2713aSLionel Sambuc       OS << "    : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n";
1549f4a2713aSLionel Sambuc 
1550*0a6a1f1dSLionel Sambuc       for (auto const &ai : Args) {
1551f4a2713aSLionel Sambuc         OS << "              , ";
1552*0a6a1f1dSLionel Sambuc         ai->writeCtorDefaultInitializers(OS);
1553f4a2713aSLionel Sambuc         OS << "\n";
1554f4a2713aSLionel Sambuc       }
1555f4a2713aSLionel Sambuc 
1556f4a2713aSLionel Sambuc       OS << "  {\n";
1557f4a2713aSLionel Sambuc 
1558*0a6a1f1dSLionel Sambuc       for (auto const &ai : Args) {
1559*0a6a1f1dSLionel Sambuc         if (!ai->isOptional()) {
1560*0a6a1f1dSLionel Sambuc           ai->writeCtorBody(OS);
1561f4a2713aSLionel Sambuc           OS << "\n";
1562f4a2713aSLionel Sambuc         }
1563f4a2713aSLionel Sambuc       }
1564f4a2713aSLionel Sambuc       OS << "  }\n\n";
1565f4a2713aSLionel Sambuc     }
1566f4a2713aSLionel Sambuc 
1567*0a6a1f1dSLionel Sambuc     OS << "  " << R.getName() << "Attr *clone(ASTContext &C) const override;\n";
1568*0a6a1f1dSLionel Sambuc     OS << "  void printPretty(raw_ostream &OS,\n"
1569*0a6a1f1dSLionel Sambuc        << "                   const PrintingPolicy &Policy) const override;\n";
1570*0a6a1f1dSLionel Sambuc     OS << "  const char *getSpelling() const override;\n";
1571*0a6a1f1dSLionel Sambuc 
1572*0a6a1f1dSLionel Sambuc     if (!ElideSpelling) {
1573*0a6a1f1dSLionel Sambuc       assert(!SemanticToSyntacticMap.empty() && "Empty semantic mapping list");
1574*0a6a1f1dSLionel Sambuc       OS << "  Spelling getSemanticSpelling() const {\n";
1575*0a6a1f1dSLionel Sambuc       WriteSemanticSpellingSwitch("SpellingListIndex", SemanticToSyntacticMap,
1576*0a6a1f1dSLionel Sambuc                                   OS);
1577*0a6a1f1dSLionel Sambuc       OS << "  }\n";
1578*0a6a1f1dSLionel Sambuc     }
1579f4a2713aSLionel Sambuc 
1580f4a2713aSLionel Sambuc     writeAttrAccessorDefinition(R, OS);
1581f4a2713aSLionel Sambuc 
1582*0a6a1f1dSLionel Sambuc     for (auto const &ai : Args) {
1583*0a6a1f1dSLionel Sambuc       ai->writeAccessors(OS);
1584f4a2713aSLionel Sambuc       OS << "\n\n";
1585f4a2713aSLionel Sambuc 
1586*0a6a1f1dSLionel Sambuc       if (ai->isEnumArg())
1587*0a6a1f1dSLionel Sambuc         static_cast<const EnumArgument *>(ai.get())->writeConversion(OS);
1588*0a6a1f1dSLionel Sambuc       else if (ai->isVariadicEnumArg())
1589*0a6a1f1dSLionel Sambuc         static_cast<const VariadicEnumArgument *>(ai.get())
1590*0a6a1f1dSLionel Sambuc             ->writeConversion(OS);
1591f4a2713aSLionel Sambuc     }
1592f4a2713aSLionel Sambuc 
1593f4a2713aSLionel Sambuc     OS << R.getValueAsString("AdditionalMembers");
1594f4a2713aSLionel Sambuc     OS << "\n\n";
1595f4a2713aSLionel Sambuc 
1596f4a2713aSLionel Sambuc     OS << "  static bool classof(const Attr *A) { return A->getKind() == "
1597f4a2713aSLionel Sambuc        << "attr::" << R.getName() << "; }\n";
1598f4a2713aSLionel Sambuc 
1599f4a2713aSLionel Sambuc     bool LateParsed = R.getValueAsBit("LateParsed");
1600*0a6a1f1dSLionel Sambuc     OS << "  bool isLateParsed() const override { return "
1601f4a2713aSLionel Sambuc        << LateParsed << "; }\n";
1602f4a2713aSLionel Sambuc 
1603*0a6a1f1dSLionel Sambuc     if (R.getValueAsBit("DuplicatesAllowedWhileMerging"))
1604*0a6a1f1dSLionel Sambuc       OS << "  bool duplicatesAllowed() const override { return true; }\n\n";
1605*0a6a1f1dSLionel Sambuc 
1606f4a2713aSLionel Sambuc     OS << "};\n\n";
1607f4a2713aSLionel Sambuc   }
1608f4a2713aSLionel Sambuc 
1609f4a2713aSLionel Sambuc   OS << "#endif\n";
1610f4a2713aSLionel Sambuc }
1611f4a2713aSLionel Sambuc 
1612f4a2713aSLionel Sambuc // Emits the class method definitions for attributes.
EmitClangAttrImpl(RecordKeeper & Records,raw_ostream & OS)1613f4a2713aSLionel Sambuc void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
1614f4a2713aSLionel Sambuc   emitSourceFileHeader("Attribute classes' member function definitions", OS);
1615f4a2713aSLionel Sambuc 
1616f4a2713aSLionel Sambuc   std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1617f4a2713aSLionel Sambuc 
1618*0a6a1f1dSLionel Sambuc   for (auto *Attr : Attrs) {
1619*0a6a1f1dSLionel Sambuc     Record &R = *Attr;
1620f4a2713aSLionel Sambuc 
1621f4a2713aSLionel Sambuc     if (!R.getValueAsBit("ASTNode"))
1622f4a2713aSLionel Sambuc       continue;
1623f4a2713aSLionel Sambuc 
1624f4a2713aSLionel Sambuc     std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
1625*0a6a1f1dSLionel Sambuc     std::vector<std::unique_ptr<Argument>> Args;
1626*0a6a1f1dSLionel Sambuc     for (const auto *Arg : ArgRecords)
1627*0a6a1f1dSLionel Sambuc       Args.emplace_back(createArgument(*Arg, R.getName()));
1628f4a2713aSLionel Sambuc 
1629*0a6a1f1dSLionel Sambuc     for (auto const &ai : Args)
1630*0a6a1f1dSLionel Sambuc       ai->writeAccessorDefinitions(OS);
1631f4a2713aSLionel Sambuc 
1632f4a2713aSLionel Sambuc     OS << R.getName() << "Attr *" << R.getName()
1633f4a2713aSLionel Sambuc        << "Attr::clone(ASTContext &C) const {\n";
1634*0a6a1f1dSLionel Sambuc     OS << "  auto *A = new (C) " << R.getName() << "Attr(getLocation(), C";
1635*0a6a1f1dSLionel Sambuc     for (auto const &ai : Args) {
1636f4a2713aSLionel Sambuc       OS << ", ";
1637*0a6a1f1dSLionel Sambuc       ai->writeCloneArgs(OS);
1638f4a2713aSLionel Sambuc     }
1639*0a6a1f1dSLionel Sambuc     OS << ", getSpellingListIndex());\n";
1640*0a6a1f1dSLionel Sambuc     OS << "  A->Inherited = Inherited;\n";
1641*0a6a1f1dSLionel Sambuc     OS << "  A->IsPackExpansion = IsPackExpansion;\n";
1642*0a6a1f1dSLionel Sambuc     OS << "  A->Implicit = Implicit;\n";
1643*0a6a1f1dSLionel Sambuc     OS << "  return A;\n}\n\n";
1644f4a2713aSLionel Sambuc 
1645f4a2713aSLionel Sambuc     writePrettyPrintFunction(R, Args, OS);
1646*0a6a1f1dSLionel Sambuc     writeGetSpellingFunction(R, OS);
1647f4a2713aSLionel Sambuc   }
1648f4a2713aSLionel Sambuc }
1649f4a2713aSLionel Sambuc 
1650f4a2713aSLionel Sambuc } // end namespace clang
1651f4a2713aSLionel Sambuc 
EmitAttrList(raw_ostream & OS,StringRef Class,const std::vector<Record * > & AttrList)1652f4a2713aSLionel Sambuc static void EmitAttrList(raw_ostream &OS, StringRef Class,
1653f4a2713aSLionel Sambuc                          const std::vector<Record*> &AttrList) {
1654f4a2713aSLionel Sambuc   std::vector<Record*>::const_iterator i = AttrList.begin(), e = AttrList.end();
1655f4a2713aSLionel Sambuc 
1656f4a2713aSLionel Sambuc   if (i != e) {
1657f4a2713aSLionel Sambuc     // Move the end iterator back to emit the last attribute.
1658f4a2713aSLionel Sambuc     for(--e; i != e; ++i) {
1659f4a2713aSLionel Sambuc       if (!(*i)->getValueAsBit("ASTNode"))
1660f4a2713aSLionel Sambuc         continue;
1661f4a2713aSLionel Sambuc 
1662f4a2713aSLionel Sambuc       OS << Class << "(" << (*i)->getName() << ")\n";
1663f4a2713aSLionel Sambuc     }
1664f4a2713aSLionel Sambuc 
1665f4a2713aSLionel Sambuc     OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n";
1666f4a2713aSLionel Sambuc   }
1667f4a2713aSLionel Sambuc }
1668f4a2713aSLionel Sambuc 
1669*0a6a1f1dSLionel Sambuc // Determines if an attribute has a Pragma spelling.
AttrHasPragmaSpelling(const Record * R)1670*0a6a1f1dSLionel Sambuc static bool AttrHasPragmaSpelling(const Record *R) {
1671*0a6a1f1dSLionel Sambuc   std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*R);
1672*0a6a1f1dSLionel Sambuc   return std::find_if(Spellings.begin(), Spellings.end(),
1673*0a6a1f1dSLionel Sambuc                       [](const FlattenedSpelling &S) {
1674*0a6a1f1dSLionel Sambuc            return S.variety() == "Pragma";
1675*0a6a1f1dSLionel Sambuc          }) != Spellings.end();
1676*0a6a1f1dSLionel Sambuc }
1677f4a2713aSLionel Sambuc 
1678*0a6a1f1dSLionel Sambuc namespace clang {
1679f4a2713aSLionel Sambuc // Emits the enumeration list for attributes.
EmitClangAttrList(RecordKeeper & Records,raw_ostream & OS)1680f4a2713aSLionel Sambuc void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) {
1681f4a2713aSLionel Sambuc   emitSourceFileHeader("List of all attributes that Clang recognizes", OS);
1682f4a2713aSLionel Sambuc 
1683f4a2713aSLionel Sambuc   OS << "#ifndef LAST_ATTR\n";
1684f4a2713aSLionel Sambuc   OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n";
1685f4a2713aSLionel Sambuc   OS << "#endif\n\n";
1686f4a2713aSLionel Sambuc 
1687f4a2713aSLionel Sambuc   OS << "#ifndef INHERITABLE_ATTR\n";
1688f4a2713aSLionel Sambuc   OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n";
1689f4a2713aSLionel Sambuc   OS << "#endif\n\n";
1690f4a2713aSLionel Sambuc 
1691f4a2713aSLionel Sambuc   OS << "#ifndef LAST_INHERITABLE_ATTR\n";
1692f4a2713aSLionel Sambuc   OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n";
1693f4a2713aSLionel Sambuc   OS << "#endif\n\n";
1694f4a2713aSLionel Sambuc 
1695f4a2713aSLionel Sambuc   OS << "#ifndef INHERITABLE_PARAM_ATTR\n";
1696f4a2713aSLionel Sambuc   OS << "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n";
1697f4a2713aSLionel Sambuc   OS << "#endif\n\n";
1698f4a2713aSLionel Sambuc 
1699f4a2713aSLionel Sambuc   OS << "#ifndef LAST_INHERITABLE_PARAM_ATTR\n";
1700f4a2713aSLionel Sambuc   OS << "#define LAST_INHERITABLE_PARAM_ATTR(NAME)"
1701f4a2713aSLionel Sambuc         " INHERITABLE_PARAM_ATTR(NAME)\n";
1702f4a2713aSLionel Sambuc   OS << "#endif\n\n";
1703f4a2713aSLionel Sambuc 
1704*0a6a1f1dSLionel Sambuc   OS << "#ifndef PRAGMA_SPELLING_ATTR\n";
1705*0a6a1f1dSLionel Sambuc   OS << "#define PRAGMA_SPELLING_ATTR(NAME)\n";
1706f4a2713aSLionel Sambuc   OS << "#endif\n\n";
1707f4a2713aSLionel Sambuc 
1708*0a6a1f1dSLionel Sambuc   OS << "#ifndef LAST_PRAGMA_SPELLING_ATTR\n";
1709*0a6a1f1dSLionel Sambuc   OS << "#define LAST_PRAGMA_SPELLING_ATTR(NAME) PRAGMA_SPELLING_ATTR(NAME)\n";
1710f4a2713aSLionel Sambuc   OS << "#endif\n\n";
1711f4a2713aSLionel Sambuc 
1712f4a2713aSLionel Sambuc   Record *InhClass = Records.getClass("InheritableAttr");
1713f4a2713aSLionel Sambuc   Record *InhParamClass = Records.getClass("InheritableParamAttr");
1714f4a2713aSLionel Sambuc   std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"),
1715*0a6a1f1dSLionel Sambuc                         NonInhAttrs, InhAttrs, InhParamAttrs, PragmaAttrs;
1716*0a6a1f1dSLionel Sambuc   for (auto *Attr : Attrs) {
1717*0a6a1f1dSLionel Sambuc     if (!Attr->getValueAsBit("ASTNode"))
1718f4a2713aSLionel Sambuc       continue;
1719f4a2713aSLionel Sambuc 
1720*0a6a1f1dSLionel Sambuc     if (AttrHasPragmaSpelling(Attr))
1721*0a6a1f1dSLionel Sambuc       PragmaAttrs.push_back(Attr);
1722*0a6a1f1dSLionel Sambuc 
1723*0a6a1f1dSLionel Sambuc     if (Attr->isSubClassOf(InhParamClass))
1724*0a6a1f1dSLionel Sambuc       InhParamAttrs.push_back(Attr);
1725*0a6a1f1dSLionel Sambuc     else if (Attr->isSubClassOf(InhClass))
1726*0a6a1f1dSLionel Sambuc       InhAttrs.push_back(Attr);
1727f4a2713aSLionel Sambuc     else
1728*0a6a1f1dSLionel Sambuc       NonInhAttrs.push_back(Attr);
1729f4a2713aSLionel Sambuc   }
1730f4a2713aSLionel Sambuc 
1731*0a6a1f1dSLionel Sambuc   EmitAttrList(OS, "PRAGMA_SPELLING_ATTR", PragmaAttrs);
1732f4a2713aSLionel Sambuc   EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs);
1733f4a2713aSLionel Sambuc   EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs);
1734f4a2713aSLionel Sambuc   EmitAttrList(OS, "ATTR", NonInhAttrs);
1735f4a2713aSLionel Sambuc 
1736f4a2713aSLionel Sambuc   OS << "#undef LAST_ATTR\n";
1737f4a2713aSLionel Sambuc   OS << "#undef INHERITABLE_ATTR\n";
1738f4a2713aSLionel Sambuc   OS << "#undef LAST_INHERITABLE_ATTR\n";
1739f4a2713aSLionel Sambuc   OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n";
1740*0a6a1f1dSLionel Sambuc   OS << "#undef LAST_PRAGMA_ATTR\n";
1741*0a6a1f1dSLionel Sambuc   OS << "#undef PRAGMA_SPELLING_ATTR\n";
1742f4a2713aSLionel Sambuc   OS << "#undef ATTR\n";
1743f4a2713aSLionel Sambuc }
1744f4a2713aSLionel Sambuc 
1745f4a2713aSLionel Sambuc // Emits the code to read an attribute from a precompiled header.
EmitClangAttrPCHRead(RecordKeeper & Records,raw_ostream & OS)1746f4a2713aSLionel Sambuc void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) {
1747f4a2713aSLionel Sambuc   emitSourceFileHeader("Attribute deserialization code", OS);
1748f4a2713aSLionel Sambuc 
1749f4a2713aSLionel Sambuc   Record *InhClass = Records.getClass("InheritableAttr");
1750f4a2713aSLionel Sambuc   std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
1751f4a2713aSLionel Sambuc                        ArgRecords;
1752*0a6a1f1dSLionel Sambuc   std::vector<std::unique_ptr<Argument>> Args;
1753f4a2713aSLionel Sambuc 
1754f4a2713aSLionel Sambuc   OS << "  switch (Kind) {\n";
1755f4a2713aSLionel Sambuc   OS << "  default:\n";
1756*0a6a1f1dSLionel Sambuc   OS << "    llvm_unreachable(\"Unknown attribute!\");\n";
1757*0a6a1f1dSLionel Sambuc   for (const auto *Attr : Attrs) {
1758*0a6a1f1dSLionel Sambuc     const Record &R = *Attr;
1759f4a2713aSLionel Sambuc     if (!R.getValueAsBit("ASTNode"))
1760f4a2713aSLionel Sambuc       continue;
1761f4a2713aSLionel Sambuc 
1762f4a2713aSLionel Sambuc     OS << "  case attr::" << R.getName() << ": {\n";
1763f4a2713aSLionel Sambuc     if (R.isSubClassOf(InhClass))
1764f4a2713aSLionel Sambuc       OS << "    bool isInherited = Record[Idx++];\n";
1765*0a6a1f1dSLionel Sambuc     OS << "    bool isImplicit = Record[Idx++];\n";
1766*0a6a1f1dSLionel Sambuc     OS << "    unsigned Spelling = Record[Idx++];\n";
1767f4a2713aSLionel Sambuc     ArgRecords = R.getValueAsListOfDefs("Args");
1768f4a2713aSLionel Sambuc     Args.clear();
1769*0a6a1f1dSLionel Sambuc     for (const auto *Arg : ArgRecords) {
1770*0a6a1f1dSLionel Sambuc       Args.emplace_back(createArgument(*Arg, R.getName()));
1771*0a6a1f1dSLionel Sambuc       Args.back()->writePCHReadDecls(OS);
1772f4a2713aSLionel Sambuc     }
1773f4a2713aSLionel Sambuc     OS << "    New = new (Context) " << R.getName() << "Attr(Range, Context";
1774*0a6a1f1dSLionel Sambuc     for (auto const &ri : Args) {
1775f4a2713aSLionel Sambuc       OS << ", ";
1776*0a6a1f1dSLionel Sambuc       ri->writePCHReadArgs(OS);
1777f4a2713aSLionel Sambuc     }
1778*0a6a1f1dSLionel Sambuc     OS << ", Spelling);\n";
1779f4a2713aSLionel Sambuc     if (R.isSubClassOf(InhClass))
1780f4a2713aSLionel Sambuc       OS << "    cast<InheritableAttr>(New)->setInherited(isInherited);\n";
1781*0a6a1f1dSLionel Sambuc     OS << "    New->setImplicit(isImplicit);\n";
1782f4a2713aSLionel Sambuc     OS << "    break;\n";
1783f4a2713aSLionel Sambuc     OS << "  }\n";
1784f4a2713aSLionel Sambuc   }
1785f4a2713aSLionel Sambuc   OS << "  }\n";
1786f4a2713aSLionel Sambuc }
1787f4a2713aSLionel Sambuc 
1788f4a2713aSLionel Sambuc // Emits the code to write an attribute to a precompiled header.
EmitClangAttrPCHWrite(RecordKeeper & Records,raw_ostream & OS)1789f4a2713aSLionel Sambuc void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) {
1790f4a2713aSLionel Sambuc   emitSourceFileHeader("Attribute serialization code", OS);
1791f4a2713aSLionel Sambuc 
1792f4a2713aSLionel Sambuc   Record *InhClass = Records.getClass("InheritableAttr");
1793f4a2713aSLionel Sambuc   std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
1794f4a2713aSLionel Sambuc 
1795f4a2713aSLionel Sambuc   OS << "  switch (A->getKind()) {\n";
1796f4a2713aSLionel Sambuc   OS << "  default:\n";
1797f4a2713aSLionel Sambuc   OS << "    llvm_unreachable(\"Unknown attribute kind!\");\n";
1798f4a2713aSLionel Sambuc   OS << "    break;\n";
1799*0a6a1f1dSLionel Sambuc   for (const auto *Attr : Attrs) {
1800*0a6a1f1dSLionel Sambuc     const Record &R = *Attr;
1801f4a2713aSLionel Sambuc     if (!R.getValueAsBit("ASTNode"))
1802f4a2713aSLionel Sambuc       continue;
1803f4a2713aSLionel Sambuc     OS << "  case attr::" << R.getName() << ": {\n";
1804f4a2713aSLionel Sambuc     Args = R.getValueAsListOfDefs("Args");
1805f4a2713aSLionel Sambuc     if (R.isSubClassOf(InhClass) || !Args.empty())
1806f4a2713aSLionel Sambuc       OS << "    const " << R.getName() << "Attr *SA = cast<" << R.getName()
1807f4a2713aSLionel Sambuc          << "Attr>(A);\n";
1808f4a2713aSLionel Sambuc     if (R.isSubClassOf(InhClass))
1809f4a2713aSLionel Sambuc       OS << "    Record.push_back(SA->isInherited());\n";
1810*0a6a1f1dSLionel Sambuc     OS << "    Record.push_back(A->isImplicit());\n";
1811*0a6a1f1dSLionel Sambuc     OS << "    Record.push_back(A->getSpellingListIndex());\n";
1812*0a6a1f1dSLionel Sambuc 
1813*0a6a1f1dSLionel Sambuc     for (const auto *Arg : Args)
1814*0a6a1f1dSLionel Sambuc       createArgument(*Arg, R.getName())->writePCHWrite(OS);
1815f4a2713aSLionel Sambuc     OS << "    break;\n";
1816f4a2713aSLionel Sambuc     OS << "  }\n";
1817f4a2713aSLionel Sambuc   }
1818f4a2713aSLionel Sambuc   OS << "  }\n";
1819f4a2713aSLionel Sambuc }
1820f4a2713aSLionel Sambuc 
GenerateHasAttrSpellingStringSwitch(const std::vector<Record * > & Attrs,raw_ostream & OS,const std::string & Variety="",const std::string & Scope="")1821*0a6a1f1dSLionel Sambuc static void GenerateHasAttrSpellingStringSwitch(
1822*0a6a1f1dSLionel Sambuc     const std::vector<Record *> &Attrs, raw_ostream &OS,
1823*0a6a1f1dSLionel Sambuc     const std::string &Variety = "", const std::string &Scope = "") {
1824*0a6a1f1dSLionel Sambuc   for (const auto *Attr : Attrs) {
1825*0a6a1f1dSLionel Sambuc     // C++11-style attributes have specific version information associated with
1826*0a6a1f1dSLionel Sambuc     // them. If the attribute has no scope, the version information must not
1827*0a6a1f1dSLionel Sambuc     // have the default value (1), as that's incorrect. Instead, the unscoped
1828*0a6a1f1dSLionel Sambuc     // attribute version information should be taken from the SD-6 standing
1829*0a6a1f1dSLionel Sambuc     // document, which can be found at:
1830*0a6a1f1dSLionel Sambuc     // https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations
1831*0a6a1f1dSLionel Sambuc     int Version = 1;
1832*0a6a1f1dSLionel Sambuc 
1833*0a6a1f1dSLionel Sambuc     if (Variety == "CXX11") {
1834*0a6a1f1dSLionel Sambuc         std::vector<Record *> Spellings = Attr->getValueAsListOfDefs("Spellings");
1835*0a6a1f1dSLionel Sambuc         for (const auto &Spelling : Spellings) {
1836*0a6a1f1dSLionel Sambuc           if (Spelling->getValueAsString("Variety") == "CXX11") {
1837*0a6a1f1dSLionel Sambuc             Version = static_cast<int>(Spelling->getValueAsInt("Version"));
1838*0a6a1f1dSLionel Sambuc             if (Scope.empty() && Version == 1)
1839*0a6a1f1dSLionel Sambuc               PrintError(Spelling->getLoc(), "C++ standard attributes must "
1840*0a6a1f1dSLionel Sambuc               "have valid version information.");
1841*0a6a1f1dSLionel Sambuc             break;
1842*0a6a1f1dSLionel Sambuc           }
1843*0a6a1f1dSLionel Sambuc       }
1844*0a6a1f1dSLionel Sambuc     }
1845*0a6a1f1dSLionel Sambuc 
1846*0a6a1f1dSLionel Sambuc     // It is assumed that there will be an llvm::Triple object named T within
1847*0a6a1f1dSLionel Sambuc     // scope that can be used to determine whether the attribute exists in
1848*0a6a1f1dSLionel Sambuc     // a given target.
1849*0a6a1f1dSLionel Sambuc     std::string Test;
1850*0a6a1f1dSLionel Sambuc     if (Attr->isSubClassOf("TargetSpecificAttr")) {
1851*0a6a1f1dSLionel Sambuc       const Record *R = Attr->getValueAsDef("Target");
1852*0a6a1f1dSLionel Sambuc       std::vector<std::string> Arches = R->getValueAsListOfStrings("Arches");
1853*0a6a1f1dSLionel Sambuc 
1854*0a6a1f1dSLionel Sambuc       Test += "(";
1855*0a6a1f1dSLionel Sambuc       for (auto AI = Arches.begin(), AE = Arches.end(); AI != AE; ++AI) {
1856*0a6a1f1dSLionel Sambuc         std::string Part = *AI;
1857*0a6a1f1dSLionel Sambuc         Test += "T.getArch() == llvm::Triple::" + Part;
1858*0a6a1f1dSLionel Sambuc         if (AI + 1 != AE)
1859*0a6a1f1dSLionel Sambuc           Test += " || ";
1860*0a6a1f1dSLionel Sambuc       }
1861*0a6a1f1dSLionel Sambuc       Test += ")";
1862*0a6a1f1dSLionel Sambuc 
1863*0a6a1f1dSLionel Sambuc       std::vector<std::string> OSes;
1864*0a6a1f1dSLionel Sambuc       if (!R->isValueUnset("OSes")) {
1865*0a6a1f1dSLionel Sambuc         Test += " && (";
1866*0a6a1f1dSLionel Sambuc         std::vector<std::string> OSes = R->getValueAsListOfStrings("OSes");
1867*0a6a1f1dSLionel Sambuc         for (auto AI = OSes.begin(), AE = OSes.end(); AI != AE; ++AI) {
1868*0a6a1f1dSLionel Sambuc           std::string Part = *AI;
1869*0a6a1f1dSLionel Sambuc 
1870*0a6a1f1dSLionel Sambuc           Test += "T.getOS() == llvm::Triple::" + Part;
1871*0a6a1f1dSLionel Sambuc           if (AI + 1 != AE)
1872*0a6a1f1dSLionel Sambuc             Test += " || ";
1873*0a6a1f1dSLionel Sambuc         }
1874*0a6a1f1dSLionel Sambuc         Test += ")";
1875*0a6a1f1dSLionel Sambuc       }
1876*0a6a1f1dSLionel Sambuc 
1877*0a6a1f1dSLionel Sambuc       // If this is the C++11 variety, also add in the LangOpts test.
1878*0a6a1f1dSLionel Sambuc       if (Variety == "CXX11")
1879*0a6a1f1dSLionel Sambuc         Test += " && LangOpts.CPlusPlus11";
1880*0a6a1f1dSLionel Sambuc     } else if (Variety == "CXX11")
1881*0a6a1f1dSLionel Sambuc       // C++11 mode should be checked against LangOpts, which is presumed to be
1882*0a6a1f1dSLionel Sambuc       // present in the caller.
1883*0a6a1f1dSLionel Sambuc       Test = "LangOpts.CPlusPlus11";
1884*0a6a1f1dSLionel Sambuc 
1885*0a6a1f1dSLionel Sambuc     std::string TestStr =
1886*0a6a1f1dSLionel Sambuc         !Test.empty() ? Test + " ? " + llvm::itostr(Version) + " : 0" : "1";
1887*0a6a1f1dSLionel Sambuc     std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr);
1888*0a6a1f1dSLionel Sambuc     for (const auto &S : Spellings)
1889*0a6a1f1dSLionel Sambuc       if (Variety.empty() || (Variety == S.variety() &&
1890*0a6a1f1dSLionel Sambuc                               (Scope.empty() || Scope == S.nameSpace())))
1891*0a6a1f1dSLionel Sambuc         OS << "    .Case(\"" << S.name() << "\", " << TestStr << ")\n";
1892*0a6a1f1dSLionel Sambuc   }
1893*0a6a1f1dSLionel Sambuc   OS << "    .Default(0);\n";
1894*0a6a1f1dSLionel Sambuc }
1895*0a6a1f1dSLionel Sambuc 
1896f4a2713aSLionel Sambuc // Emits the list of spellings for attributes.
EmitClangAttrHasAttrImpl(RecordKeeper & Records,raw_ostream & OS)1897*0a6a1f1dSLionel Sambuc void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
1898*0a6a1f1dSLionel Sambuc   emitSourceFileHeader("Code to implement the __has_attribute logic", OS);
1899f4a2713aSLionel Sambuc 
1900*0a6a1f1dSLionel Sambuc   // Separate all of the attributes out into four group: generic, C++11, GNU,
1901*0a6a1f1dSLionel Sambuc   // and declspecs. Then generate a big switch statement for each of them.
1902f4a2713aSLionel Sambuc   std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
1903*0a6a1f1dSLionel Sambuc   std::vector<Record *> Declspec, GNU, Pragma;
1904*0a6a1f1dSLionel Sambuc   std::map<std::string, std::vector<Record *>> CXX;
1905f4a2713aSLionel Sambuc 
1906*0a6a1f1dSLionel Sambuc   // Walk over the list of all attributes, and split them out based on the
1907*0a6a1f1dSLionel Sambuc   // spelling variety.
1908*0a6a1f1dSLionel Sambuc   for (auto *R : Attrs) {
1909*0a6a1f1dSLionel Sambuc     std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*R);
1910*0a6a1f1dSLionel Sambuc     for (const auto &SI : Spellings) {
1911*0a6a1f1dSLionel Sambuc       std::string Variety = SI.variety();
1912*0a6a1f1dSLionel Sambuc       if (Variety == "GNU")
1913*0a6a1f1dSLionel Sambuc         GNU.push_back(R);
1914*0a6a1f1dSLionel Sambuc       else if (Variety == "Declspec")
1915*0a6a1f1dSLionel Sambuc         Declspec.push_back(R);
1916*0a6a1f1dSLionel Sambuc       else if (Variety == "CXX11")
1917*0a6a1f1dSLionel Sambuc         CXX[SI.nameSpace()].push_back(R);
1918*0a6a1f1dSLionel Sambuc       else if (Variety == "Pragma")
1919*0a6a1f1dSLionel Sambuc         Pragma.push_back(R);
1920f4a2713aSLionel Sambuc     }
1921f4a2713aSLionel Sambuc   }
1922f4a2713aSLionel Sambuc 
1923*0a6a1f1dSLionel Sambuc   OS << "switch (Syntax) {\n";
1924*0a6a1f1dSLionel Sambuc   OS << "case AttrSyntax::GNU:\n";
1925*0a6a1f1dSLionel Sambuc   OS << "  return llvm::StringSwitch<int>(Name)\n";
1926*0a6a1f1dSLionel Sambuc   GenerateHasAttrSpellingStringSwitch(GNU, OS, "GNU");
1927*0a6a1f1dSLionel Sambuc   OS << "case AttrSyntax::Declspec:\n";
1928*0a6a1f1dSLionel Sambuc   OS << "  return llvm::StringSwitch<int>(Name)\n";
1929*0a6a1f1dSLionel Sambuc   GenerateHasAttrSpellingStringSwitch(Declspec, OS, "Declspec");
1930*0a6a1f1dSLionel Sambuc   OS << "case AttrSyntax::Pragma:\n";
1931*0a6a1f1dSLionel Sambuc   OS << "  return llvm::StringSwitch<int>(Name)\n";
1932*0a6a1f1dSLionel Sambuc   GenerateHasAttrSpellingStringSwitch(Pragma, OS, "Pragma");
1933*0a6a1f1dSLionel Sambuc   OS << "case AttrSyntax::CXX: {\n";
1934*0a6a1f1dSLionel Sambuc   // C++11-style attributes are further split out based on the Scope.
1935*0a6a1f1dSLionel Sambuc   for (std::map<std::string, std::vector<Record *>>::iterator I = CXX.begin(),
1936*0a6a1f1dSLionel Sambuc                                                               E = CXX.end();
1937*0a6a1f1dSLionel Sambuc        I != E; ++I) {
1938*0a6a1f1dSLionel Sambuc     if (I != CXX.begin())
1939*0a6a1f1dSLionel Sambuc       OS << " else ";
1940*0a6a1f1dSLionel Sambuc     if (I->first.empty())
1941*0a6a1f1dSLionel Sambuc       OS << "if (!Scope || Scope->getName() == \"\") {\n";
1942*0a6a1f1dSLionel Sambuc     else
1943*0a6a1f1dSLionel Sambuc       OS << "if (Scope->getName() == \"" << I->first << "\") {\n";
1944*0a6a1f1dSLionel Sambuc     OS << "  return llvm::StringSwitch<int>(Name)\n";
1945*0a6a1f1dSLionel Sambuc     GenerateHasAttrSpellingStringSwitch(I->second, OS, "CXX11", I->first);
1946*0a6a1f1dSLionel Sambuc     OS << "}";
1947*0a6a1f1dSLionel Sambuc   }
1948*0a6a1f1dSLionel Sambuc   OS << "\n}\n";
1949*0a6a1f1dSLionel Sambuc   OS << "}\n";
1950f4a2713aSLionel Sambuc }
1951f4a2713aSLionel Sambuc 
EmitClangAttrSpellingListIndex(RecordKeeper & Records,raw_ostream & OS)1952f4a2713aSLionel Sambuc void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) {
1953f4a2713aSLionel Sambuc   emitSourceFileHeader("Code to translate different attribute spellings "
1954f4a2713aSLionel Sambuc                        "into internal identifiers", OS);
1955f4a2713aSLionel Sambuc 
1956f4a2713aSLionel Sambuc   OS <<
1957f4a2713aSLionel Sambuc     "  switch (AttrKind) {\n"
1958f4a2713aSLionel Sambuc     "  default:\n"
1959f4a2713aSLionel Sambuc     "    llvm_unreachable(\"Unknown attribute kind!\");\n"
1960f4a2713aSLionel Sambuc     "    break;\n";
1961f4a2713aSLionel Sambuc 
1962*0a6a1f1dSLionel Sambuc   ParsedAttrMap Attrs = getParsedAttrList(Records);
1963*0a6a1f1dSLionel Sambuc   for (const auto &I : Attrs) {
1964*0a6a1f1dSLionel Sambuc     const Record &R = *I.second;
1965*0a6a1f1dSLionel Sambuc     std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
1966*0a6a1f1dSLionel Sambuc     OS << "  case AT_" << I.first << ": {\n";
1967f4a2713aSLionel Sambuc     for (unsigned I = 0; I < Spellings.size(); ++ I) {
1968*0a6a1f1dSLionel Sambuc       OS << "    if (Name == \"" << Spellings[I].name() << "\" && "
1969f4a2713aSLionel Sambuc          << "SyntaxUsed == "
1970*0a6a1f1dSLionel Sambuc          << StringSwitch<unsigned>(Spellings[I].variety())
1971f4a2713aSLionel Sambuc                 .Case("GNU", 0)
1972f4a2713aSLionel Sambuc                 .Case("CXX11", 1)
1973f4a2713aSLionel Sambuc                 .Case("Declspec", 2)
1974f4a2713aSLionel Sambuc                 .Case("Keyword", 3)
1975*0a6a1f1dSLionel Sambuc                 .Case("Pragma", 4)
1976f4a2713aSLionel Sambuc                 .Default(0)
1977*0a6a1f1dSLionel Sambuc          << " && Scope == \"" << Spellings[I].nameSpace() << "\")\n"
1978f4a2713aSLionel Sambuc          << "        return " << I << ";\n";
1979f4a2713aSLionel Sambuc     }
1980f4a2713aSLionel Sambuc 
1981f4a2713aSLionel Sambuc     OS << "    break;\n";
1982f4a2713aSLionel Sambuc     OS << "  }\n";
1983f4a2713aSLionel Sambuc   }
1984f4a2713aSLionel Sambuc 
1985f4a2713aSLionel Sambuc   OS << "  }\n";
1986*0a6a1f1dSLionel Sambuc   OS << "  return 0;\n";
1987f4a2713aSLionel Sambuc }
1988f4a2713aSLionel Sambuc 
1989*0a6a1f1dSLionel Sambuc // Emits code used by RecursiveASTVisitor to visit attributes
EmitClangAttrASTVisitor(RecordKeeper & Records,raw_ostream & OS)1990*0a6a1f1dSLionel Sambuc void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS) {
1991*0a6a1f1dSLionel Sambuc   emitSourceFileHeader("Used by RecursiveASTVisitor to visit attributes.", OS);
1992f4a2713aSLionel Sambuc 
1993f4a2713aSLionel Sambuc   std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1994f4a2713aSLionel Sambuc 
1995*0a6a1f1dSLionel Sambuc   // Write method declarations for Traverse* methods.
1996*0a6a1f1dSLionel Sambuc   // We emit this here because we only generate methods for attributes that
1997*0a6a1f1dSLionel Sambuc   // are declared as ASTNodes.
1998*0a6a1f1dSLionel Sambuc   OS << "#ifdef ATTR_VISITOR_DECLS_ONLY\n\n";
1999*0a6a1f1dSLionel Sambuc   for (const auto *Attr : Attrs) {
2000*0a6a1f1dSLionel Sambuc     const Record &R = *Attr;
2001*0a6a1f1dSLionel Sambuc     if (!R.getValueAsBit("ASTNode"))
2002f4a2713aSLionel Sambuc       continue;
2003*0a6a1f1dSLionel Sambuc     OS << "  bool Traverse"
2004*0a6a1f1dSLionel Sambuc        << R.getName() << "Attr(" << R.getName() << "Attr *A);\n";
2005*0a6a1f1dSLionel Sambuc     OS << "  bool Visit"
2006*0a6a1f1dSLionel Sambuc        << R.getName() << "Attr(" << R.getName() << "Attr *A) {\n"
2007*0a6a1f1dSLionel Sambuc        << "    return true; \n"
2008*0a6a1f1dSLionel Sambuc        << "  };\n";
2009f4a2713aSLionel Sambuc   }
2010*0a6a1f1dSLionel Sambuc   OS << "\n#else // ATTR_VISITOR_DECLS_ONLY\n\n";
2011*0a6a1f1dSLionel Sambuc 
2012*0a6a1f1dSLionel Sambuc   // Write individual Traverse* methods for each attribute class.
2013*0a6a1f1dSLionel Sambuc   for (const auto *Attr : Attrs) {
2014*0a6a1f1dSLionel Sambuc     const Record &R = *Attr;
2015*0a6a1f1dSLionel Sambuc     if (!R.getValueAsBit("ASTNode"))
2016*0a6a1f1dSLionel Sambuc       continue;
2017*0a6a1f1dSLionel Sambuc 
2018*0a6a1f1dSLionel Sambuc     OS << "template <typename Derived>\n"
2019*0a6a1f1dSLionel Sambuc        << "bool VISITORCLASS<Derived>::Traverse"
2020*0a6a1f1dSLionel Sambuc        << R.getName() << "Attr(" << R.getName() << "Attr *A) {\n"
2021*0a6a1f1dSLionel Sambuc        << "  if (!getDerived().VisitAttr(A))\n"
2022*0a6a1f1dSLionel Sambuc        << "    return false;\n"
2023*0a6a1f1dSLionel Sambuc        << "  if (!getDerived().Visit" << R.getName() << "Attr(A))\n"
2024*0a6a1f1dSLionel Sambuc        << "    return false;\n";
2025*0a6a1f1dSLionel Sambuc 
2026*0a6a1f1dSLionel Sambuc     std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
2027*0a6a1f1dSLionel Sambuc     for (const auto *Arg : ArgRecords)
2028*0a6a1f1dSLionel Sambuc       createArgument(*Arg, R.getName())->writeASTVisitorTraversal(OS);
2029*0a6a1f1dSLionel Sambuc 
2030*0a6a1f1dSLionel Sambuc     OS << "  return true;\n";
2031*0a6a1f1dSLionel Sambuc     OS << "}\n\n";
2032f4a2713aSLionel Sambuc   }
2033*0a6a1f1dSLionel Sambuc 
2034*0a6a1f1dSLionel Sambuc   // Write generic Traverse routine
2035*0a6a1f1dSLionel Sambuc   OS << "template <typename Derived>\n"
2036*0a6a1f1dSLionel Sambuc      << "bool VISITORCLASS<Derived>::TraverseAttr(Attr *A) {\n"
2037*0a6a1f1dSLionel Sambuc      << "  if (!A)\n"
2038*0a6a1f1dSLionel Sambuc      << "    return true;\n"
2039*0a6a1f1dSLionel Sambuc      << "\n"
2040*0a6a1f1dSLionel Sambuc      << "  switch (A->getKind()) {\n"
2041*0a6a1f1dSLionel Sambuc      << "    default:\n"
2042*0a6a1f1dSLionel Sambuc      << "      return true;\n";
2043*0a6a1f1dSLionel Sambuc 
2044*0a6a1f1dSLionel Sambuc   for (const auto *Attr : Attrs) {
2045*0a6a1f1dSLionel Sambuc     const Record &R = *Attr;
2046*0a6a1f1dSLionel Sambuc     if (!R.getValueAsBit("ASTNode"))
2047*0a6a1f1dSLionel Sambuc       continue;
2048*0a6a1f1dSLionel Sambuc 
2049*0a6a1f1dSLionel Sambuc     OS << "    case attr::" << R.getName() << ":\n"
2050*0a6a1f1dSLionel Sambuc        << "      return getDerived().Traverse" << R.getName() << "Attr("
2051*0a6a1f1dSLionel Sambuc        << "cast<" << R.getName() << "Attr>(A));\n";
2052f4a2713aSLionel Sambuc   }
2053*0a6a1f1dSLionel Sambuc   OS << "  }\n";  // end case
2054*0a6a1f1dSLionel Sambuc   OS << "}\n";  // end function
2055*0a6a1f1dSLionel Sambuc   OS << "#endif  // ATTR_VISITOR_DECLS_ONLY\n";
2056f4a2713aSLionel Sambuc }
2057f4a2713aSLionel Sambuc 
2058f4a2713aSLionel Sambuc // Emits code to instantiate dependent attributes on templates.
EmitClangAttrTemplateInstantiate(RecordKeeper & Records,raw_ostream & OS)2059f4a2713aSLionel Sambuc void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) {
2060f4a2713aSLionel Sambuc   emitSourceFileHeader("Template instantiation code for attributes", OS);
2061f4a2713aSLionel Sambuc 
2062f4a2713aSLionel Sambuc   std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
2063f4a2713aSLionel Sambuc 
2064f4a2713aSLionel Sambuc   OS << "namespace clang {\n"
2065f4a2713aSLionel Sambuc      << "namespace sema {\n\n"
2066f4a2713aSLionel Sambuc      << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, "
2067f4a2713aSLionel Sambuc      << "Sema &S,\n"
2068f4a2713aSLionel Sambuc      << "        const MultiLevelTemplateArgumentList &TemplateArgs) {\n"
2069f4a2713aSLionel Sambuc      << "  switch (At->getKind()) {\n"
2070f4a2713aSLionel Sambuc      << "    default:\n"
2071f4a2713aSLionel Sambuc      << "      break;\n";
2072f4a2713aSLionel Sambuc 
2073*0a6a1f1dSLionel Sambuc   for (const auto *Attr : Attrs) {
2074*0a6a1f1dSLionel Sambuc     const Record &R = *Attr;
2075f4a2713aSLionel Sambuc     if (!R.getValueAsBit("ASTNode"))
2076f4a2713aSLionel Sambuc       continue;
2077f4a2713aSLionel Sambuc 
2078f4a2713aSLionel Sambuc     OS << "    case attr::" << R.getName() << ": {\n";
2079f4a2713aSLionel Sambuc     bool ShouldClone = R.getValueAsBit("Clone");
2080f4a2713aSLionel Sambuc 
2081f4a2713aSLionel Sambuc     if (!ShouldClone) {
2082f4a2713aSLionel Sambuc       OS << "      return NULL;\n";
2083f4a2713aSLionel Sambuc       OS << "    }\n";
2084f4a2713aSLionel Sambuc       continue;
2085f4a2713aSLionel Sambuc     }
2086f4a2713aSLionel Sambuc 
2087f4a2713aSLionel Sambuc     OS << "      const " << R.getName() << "Attr *A = cast<"
2088f4a2713aSLionel Sambuc        << R.getName() << "Attr>(At);\n";
2089f4a2713aSLionel Sambuc     bool TDependent = R.getValueAsBit("TemplateDependent");
2090f4a2713aSLionel Sambuc 
2091f4a2713aSLionel Sambuc     if (!TDependent) {
2092f4a2713aSLionel Sambuc       OS << "      return A->clone(C);\n";
2093f4a2713aSLionel Sambuc       OS << "    }\n";
2094f4a2713aSLionel Sambuc       continue;
2095f4a2713aSLionel Sambuc     }
2096f4a2713aSLionel Sambuc 
2097f4a2713aSLionel Sambuc     std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
2098*0a6a1f1dSLionel Sambuc     std::vector<std::unique_ptr<Argument>> Args;
2099f4a2713aSLionel Sambuc     Args.reserve(ArgRecords.size());
2100f4a2713aSLionel Sambuc 
2101*0a6a1f1dSLionel Sambuc     for (const auto *ArgRecord : ArgRecords)
2102*0a6a1f1dSLionel Sambuc       Args.emplace_back(createArgument(*ArgRecord, R.getName()));
2103f4a2713aSLionel Sambuc 
2104*0a6a1f1dSLionel Sambuc     for (auto const &ai : Args)
2105*0a6a1f1dSLionel Sambuc       ai->writeTemplateInstantiation(OS);
2106*0a6a1f1dSLionel Sambuc 
2107f4a2713aSLionel Sambuc     OS << "      return new (C) " << R.getName() << "Attr(A->getLocation(), C";
2108*0a6a1f1dSLionel Sambuc     for (auto const &ai : Args) {
2109f4a2713aSLionel Sambuc       OS << ", ";
2110*0a6a1f1dSLionel Sambuc       ai->writeTemplateInstantiationArgs(OS);
2111f4a2713aSLionel Sambuc     }
2112*0a6a1f1dSLionel Sambuc     OS << ", A->getSpellingListIndex());\n    }\n";
2113f4a2713aSLionel Sambuc   }
2114f4a2713aSLionel Sambuc   OS << "  } // end switch\n"
2115f4a2713aSLionel Sambuc      << "  llvm_unreachable(\"Unknown attribute!\");\n"
2116f4a2713aSLionel Sambuc      << "  return 0;\n"
2117f4a2713aSLionel Sambuc      << "}\n\n"
2118f4a2713aSLionel Sambuc      << "} // end namespace sema\n"
2119f4a2713aSLionel Sambuc      << "} // end namespace clang\n";
2120f4a2713aSLionel Sambuc }
2121f4a2713aSLionel Sambuc 
2122f4a2713aSLionel Sambuc // Emits the list of parsed attributes.
EmitClangAttrParsedAttrList(RecordKeeper & Records,raw_ostream & OS)2123f4a2713aSLionel Sambuc void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) {
2124f4a2713aSLionel Sambuc   emitSourceFileHeader("List of all attributes that Clang recognizes", OS);
2125f4a2713aSLionel Sambuc 
2126f4a2713aSLionel Sambuc   OS << "#ifndef PARSED_ATTR\n";
2127f4a2713aSLionel Sambuc   OS << "#define PARSED_ATTR(NAME) NAME\n";
2128f4a2713aSLionel Sambuc   OS << "#endif\n\n";
2129f4a2713aSLionel Sambuc 
2130f4a2713aSLionel Sambuc   ParsedAttrMap Names = getParsedAttrList(Records);
2131*0a6a1f1dSLionel Sambuc   for (const auto &I : Names) {
2132*0a6a1f1dSLionel Sambuc     OS << "PARSED_ATTR(" << I.first << ")\n";
2133f4a2713aSLionel Sambuc   }
2134f4a2713aSLionel Sambuc }
2135f4a2713aSLionel Sambuc 
isArgVariadic(const Record & R,StringRef AttrName)2136*0a6a1f1dSLionel Sambuc static bool isArgVariadic(const Record &R, StringRef AttrName) {
2137*0a6a1f1dSLionel Sambuc   return createArgument(R, AttrName)->isVariadic();
2138*0a6a1f1dSLionel Sambuc }
2139*0a6a1f1dSLionel Sambuc 
emitArgInfo(const Record & R,std::stringstream & OS)2140*0a6a1f1dSLionel Sambuc static void emitArgInfo(const Record &R, std::stringstream &OS) {
2141f4a2713aSLionel Sambuc   // This function will count the number of arguments specified for the
2142f4a2713aSLionel Sambuc   // attribute and emit the number of required arguments followed by the
2143f4a2713aSLionel Sambuc   // number of optional arguments.
2144f4a2713aSLionel Sambuc   std::vector<Record *> Args = R.getValueAsListOfDefs("Args");
2145f4a2713aSLionel Sambuc   unsigned ArgCount = 0, OptCount = 0;
2146*0a6a1f1dSLionel Sambuc   bool HasVariadic = false;
2147*0a6a1f1dSLionel Sambuc   for (const auto *Arg : Args) {
2148*0a6a1f1dSLionel Sambuc     Arg->getValueAsBit("Optional") ? ++OptCount : ++ArgCount;
2149*0a6a1f1dSLionel Sambuc     if (!HasVariadic && isArgVariadic(*Arg, R.getName()))
2150*0a6a1f1dSLionel Sambuc       HasVariadic = true;
2151f4a2713aSLionel Sambuc   }
2152*0a6a1f1dSLionel Sambuc 
2153*0a6a1f1dSLionel Sambuc   // If there is a variadic argument, we will set the optional argument count
2154*0a6a1f1dSLionel Sambuc   // to its largest value. Since it's currently a 4-bit number, we set it to 15.
2155*0a6a1f1dSLionel Sambuc   OS << ArgCount << ", " << (HasVariadic ? 15 : OptCount);
2156*0a6a1f1dSLionel Sambuc }
2157*0a6a1f1dSLionel Sambuc 
GenerateDefaultAppertainsTo(raw_ostream & OS)2158*0a6a1f1dSLionel Sambuc static void GenerateDefaultAppertainsTo(raw_ostream &OS) {
2159*0a6a1f1dSLionel Sambuc   OS << "static bool defaultAppertainsTo(Sema &, const AttributeList &,";
2160*0a6a1f1dSLionel Sambuc   OS << "const Decl *) {\n";
2161*0a6a1f1dSLionel Sambuc   OS << "  return true;\n";
2162*0a6a1f1dSLionel Sambuc   OS << "}\n\n";
2163*0a6a1f1dSLionel Sambuc }
2164*0a6a1f1dSLionel Sambuc 
CalculateDiagnostic(const Record & S)2165*0a6a1f1dSLionel Sambuc static std::string CalculateDiagnostic(const Record &S) {
2166*0a6a1f1dSLionel Sambuc   // If the SubjectList object has a custom diagnostic associated with it,
2167*0a6a1f1dSLionel Sambuc   // return that directly.
2168*0a6a1f1dSLionel Sambuc   std::string CustomDiag = S.getValueAsString("CustomDiag");
2169*0a6a1f1dSLionel Sambuc   if (!CustomDiag.empty())
2170*0a6a1f1dSLionel Sambuc     return CustomDiag;
2171*0a6a1f1dSLionel Sambuc 
2172*0a6a1f1dSLionel Sambuc   // Given the list of subjects, determine what diagnostic best fits.
2173*0a6a1f1dSLionel Sambuc   enum {
2174*0a6a1f1dSLionel Sambuc     Func = 1U << 0,
2175*0a6a1f1dSLionel Sambuc     Var = 1U << 1,
2176*0a6a1f1dSLionel Sambuc     ObjCMethod = 1U << 2,
2177*0a6a1f1dSLionel Sambuc     Param = 1U << 3,
2178*0a6a1f1dSLionel Sambuc     Class = 1U << 4,
2179*0a6a1f1dSLionel Sambuc     GenericRecord = 1U << 5,
2180*0a6a1f1dSLionel Sambuc     Type = 1U << 6,
2181*0a6a1f1dSLionel Sambuc     ObjCIVar = 1U << 7,
2182*0a6a1f1dSLionel Sambuc     ObjCProp = 1U << 8,
2183*0a6a1f1dSLionel Sambuc     ObjCInterface = 1U << 9,
2184*0a6a1f1dSLionel Sambuc     Block = 1U << 10,
2185*0a6a1f1dSLionel Sambuc     Namespace = 1U << 11,
2186*0a6a1f1dSLionel Sambuc     Field = 1U << 12,
2187*0a6a1f1dSLionel Sambuc     CXXMethod = 1U << 13,
2188*0a6a1f1dSLionel Sambuc     ObjCProtocol = 1U << 14
2189*0a6a1f1dSLionel Sambuc   };
2190*0a6a1f1dSLionel Sambuc   uint32_t SubMask = 0;
2191*0a6a1f1dSLionel Sambuc 
2192*0a6a1f1dSLionel Sambuc   std::vector<Record *> Subjects = S.getValueAsListOfDefs("Subjects");
2193*0a6a1f1dSLionel Sambuc   for (const auto *Subject : Subjects) {
2194*0a6a1f1dSLionel Sambuc     const Record &R = *Subject;
2195*0a6a1f1dSLionel Sambuc     std::string Name;
2196*0a6a1f1dSLionel Sambuc 
2197*0a6a1f1dSLionel Sambuc     if (R.isSubClassOf("SubsetSubject")) {
2198*0a6a1f1dSLionel Sambuc       PrintError(R.getLoc(), "SubsetSubjects should use a custom diagnostic");
2199*0a6a1f1dSLionel Sambuc       // As a fallback, look through the SubsetSubject to see what its base
2200*0a6a1f1dSLionel Sambuc       // type is, and use that. This needs to be updated if SubsetSubjects
2201*0a6a1f1dSLionel Sambuc       // are allowed within other SubsetSubjects.
2202*0a6a1f1dSLionel Sambuc       Name = R.getValueAsDef("Base")->getName();
2203*0a6a1f1dSLionel Sambuc     } else
2204*0a6a1f1dSLionel Sambuc       Name = R.getName();
2205*0a6a1f1dSLionel Sambuc 
2206*0a6a1f1dSLionel Sambuc     uint32_t V = StringSwitch<uint32_t>(Name)
2207*0a6a1f1dSLionel Sambuc                    .Case("Function", Func)
2208*0a6a1f1dSLionel Sambuc                    .Case("Var", Var)
2209*0a6a1f1dSLionel Sambuc                    .Case("ObjCMethod", ObjCMethod)
2210*0a6a1f1dSLionel Sambuc                    .Case("ParmVar", Param)
2211*0a6a1f1dSLionel Sambuc                    .Case("TypedefName", Type)
2212*0a6a1f1dSLionel Sambuc                    .Case("ObjCIvar", ObjCIVar)
2213*0a6a1f1dSLionel Sambuc                    .Case("ObjCProperty", ObjCProp)
2214*0a6a1f1dSLionel Sambuc                    .Case("Record", GenericRecord)
2215*0a6a1f1dSLionel Sambuc                    .Case("ObjCInterface", ObjCInterface)
2216*0a6a1f1dSLionel Sambuc                    .Case("ObjCProtocol", ObjCProtocol)
2217*0a6a1f1dSLionel Sambuc                    .Case("Block", Block)
2218*0a6a1f1dSLionel Sambuc                    .Case("CXXRecord", Class)
2219*0a6a1f1dSLionel Sambuc                    .Case("Namespace", Namespace)
2220*0a6a1f1dSLionel Sambuc                    .Case("Field", Field)
2221*0a6a1f1dSLionel Sambuc                    .Case("CXXMethod", CXXMethod)
2222*0a6a1f1dSLionel Sambuc                    .Default(0);
2223*0a6a1f1dSLionel Sambuc     if (!V) {
2224*0a6a1f1dSLionel Sambuc       // Something wasn't in our mapping, so be helpful and let the developer
2225*0a6a1f1dSLionel Sambuc       // know about it.
2226*0a6a1f1dSLionel Sambuc       PrintFatalError(R.getLoc(), "Unknown subject type: " + R.getName());
2227*0a6a1f1dSLionel Sambuc       return "";
2228*0a6a1f1dSLionel Sambuc     }
2229*0a6a1f1dSLionel Sambuc 
2230*0a6a1f1dSLionel Sambuc     SubMask |= V;
2231*0a6a1f1dSLionel Sambuc   }
2232*0a6a1f1dSLionel Sambuc 
2233*0a6a1f1dSLionel Sambuc   switch (SubMask) {
2234*0a6a1f1dSLionel Sambuc     // For the simple cases where there's only a single entry in the mask, we
2235*0a6a1f1dSLionel Sambuc     // don't have to resort to bit fiddling.
2236*0a6a1f1dSLionel Sambuc     case Func:  return "ExpectedFunction";
2237*0a6a1f1dSLionel Sambuc     case Var:   return "ExpectedVariable";
2238*0a6a1f1dSLionel Sambuc     case Param: return "ExpectedParameter";
2239*0a6a1f1dSLionel Sambuc     case Class: return "ExpectedClass";
2240*0a6a1f1dSLionel Sambuc     case CXXMethod:
2241*0a6a1f1dSLionel Sambuc       // FIXME: Currently, this maps to ExpectedMethod based on existing code,
2242*0a6a1f1dSLionel Sambuc       // but should map to something a bit more accurate at some point.
2243*0a6a1f1dSLionel Sambuc     case ObjCMethod:  return "ExpectedMethod";
2244*0a6a1f1dSLionel Sambuc     case Type:  return "ExpectedType";
2245*0a6a1f1dSLionel Sambuc     case ObjCInterface: return "ExpectedObjectiveCInterface";
2246*0a6a1f1dSLionel Sambuc     case ObjCProtocol: return "ExpectedObjectiveCProtocol";
2247*0a6a1f1dSLionel Sambuc 
2248*0a6a1f1dSLionel Sambuc     // "GenericRecord" means struct, union or class; check the language options
2249*0a6a1f1dSLionel Sambuc     // and if not compiling for C++, strip off the class part. Note that this
2250*0a6a1f1dSLionel Sambuc     // relies on the fact that the context for this declares "Sema &S".
2251*0a6a1f1dSLionel Sambuc     case GenericRecord:
2252*0a6a1f1dSLionel Sambuc       return "(S.getLangOpts().CPlusPlus ? ExpectedStructOrUnionOrClass : "
2253*0a6a1f1dSLionel Sambuc                                            "ExpectedStructOrUnion)";
2254*0a6a1f1dSLionel Sambuc     case Func | ObjCMethod | Block: return "ExpectedFunctionMethodOrBlock";
2255*0a6a1f1dSLionel Sambuc     case Func | ObjCMethod | Class: return "ExpectedFunctionMethodOrClass";
2256*0a6a1f1dSLionel Sambuc     case Func | Param:
2257*0a6a1f1dSLionel Sambuc     case Func | ObjCMethod | Param: return "ExpectedFunctionMethodOrParameter";
2258*0a6a1f1dSLionel Sambuc     case Func | ObjCMethod: return "ExpectedFunctionOrMethod";
2259*0a6a1f1dSLionel Sambuc     case Func | Var: return "ExpectedVariableOrFunction";
2260*0a6a1f1dSLionel Sambuc 
2261*0a6a1f1dSLionel Sambuc     // If not compiling for C++, the class portion does not apply.
2262*0a6a1f1dSLionel Sambuc     case Func | Var | Class:
2263*0a6a1f1dSLionel Sambuc       return "(S.getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass : "
2264*0a6a1f1dSLionel Sambuc                                            "ExpectedVariableOrFunction)";
2265*0a6a1f1dSLionel Sambuc 
2266*0a6a1f1dSLionel Sambuc     case ObjCMethod | ObjCProp: return "ExpectedMethodOrProperty";
2267*0a6a1f1dSLionel Sambuc     case ObjCProtocol | ObjCInterface:
2268*0a6a1f1dSLionel Sambuc       return "ExpectedObjectiveCInterfaceOrProtocol";
2269*0a6a1f1dSLionel Sambuc     case Field | Var: return "ExpectedFieldOrGlobalVar";
2270*0a6a1f1dSLionel Sambuc   }
2271*0a6a1f1dSLionel Sambuc 
2272*0a6a1f1dSLionel Sambuc   PrintFatalError(S.getLoc(),
2273*0a6a1f1dSLionel Sambuc                   "Could not deduce diagnostic argument for Attr subjects");
2274*0a6a1f1dSLionel Sambuc 
2275*0a6a1f1dSLionel Sambuc   return "";
2276*0a6a1f1dSLionel Sambuc }
2277*0a6a1f1dSLionel Sambuc 
GetSubjectWithSuffix(const Record * R)2278*0a6a1f1dSLionel Sambuc static std::string GetSubjectWithSuffix(const Record *R) {
2279*0a6a1f1dSLionel Sambuc   std::string B = R->getName();
2280*0a6a1f1dSLionel Sambuc   if (B == "DeclBase")
2281*0a6a1f1dSLionel Sambuc     return "Decl";
2282*0a6a1f1dSLionel Sambuc   return B + "Decl";
2283*0a6a1f1dSLionel Sambuc }
GenerateCustomAppertainsTo(const Record & Subject,raw_ostream & OS)2284*0a6a1f1dSLionel Sambuc static std::string GenerateCustomAppertainsTo(const Record &Subject,
2285*0a6a1f1dSLionel Sambuc                                               raw_ostream &OS) {
2286*0a6a1f1dSLionel Sambuc   std::string FnName = "is" + Subject.getName();
2287*0a6a1f1dSLionel Sambuc 
2288*0a6a1f1dSLionel Sambuc   // If this code has already been generated, simply return the previous
2289*0a6a1f1dSLionel Sambuc   // instance of it.
2290*0a6a1f1dSLionel Sambuc   static std::set<std::string> CustomSubjectSet;
2291*0a6a1f1dSLionel Sambuc   std::set<std::string>::iterator I = CustomSubjectSet.find(FnName);
2292*0a6a1f1dSLionel Sambuc   if (I != CustomSubjectSet.end())
2293*0a6a1f1dSLionel Sambuc     return *I;
2294*0a6a1f1dSLionel Sambuc 
2295*0a6a1f1dSLionel Sambuc   Record *Base = Subject.getValueAsDef("Base");
2296*0a6a1f1dSLionel Sambuc 
2297*0a6a1f1dSLionel Sambuc   // Not currently support custom subjects within custom subjects.
2298*0a6a1f1dSLionel Sambuc   if (Base->isSubClassOf("SubsetSubject")) {
2299*0a6a1f1dSLionel Sambuc     PrintFatalError(Subject.getLoc(),
2300*0a6a1f1dSLionel Sambuc                     "SubsetSubjects within SubsetSubjects is not supported");
2301*0a6a1f1dSLionel Sambuc     return "";
2302*0a6a1f1dSLionel Sambuc   }
2303*0a6a1f1dSLionel Sambuc 
2304*0a6a1f1dSLionel Sambuc   OS << "static bool " << FnName << "(const Decl *D) {\n";
2305*0a6a1f1dSLionel Sambuc   OS << "  if (const " << GetSubjectWithSuffix(Base) << " *S = dyn_cast<";
2306*0a6a1f1dSLionel Sambuc   OS << GetSubjectWithSuffix(Base);
2307*0a6a1f1dSLionel Sambuc   OS << ">(D))\n";
2308*0a6a1f1dSLionel Sambuc   OS << "    return " << Subject.getValueAsString("CheckCode") << ";\n";
2309*0a6a1f1dSLionel Sambuc   OS << "  return false;\n";
2310*0a6a1f1dSLionel Sambuc   OS << "}\n\n";
2311*0a6a1f1dSLionel Sambuc 
2312*0a6a1f1dSLionel Sambuc   CustomSubjectSet.insert(FnName);
2313*0a6a1f1dSLionel Sambuc   return FnName;
2314*0a6a1f1dSLionel Sambuc }
2315*0a6a1f1dSLionel Sambuc 
GenerateAppertainsTo(const Record & Attr,raw_ostream & OS)2316*0a6a1f1dSLionel Sambuc static std::string GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) {
2317*0a6a1f1dSLionel Sambuc   // If the attribute does not contain a Subjects definition, then use the
2318*0a6a1f1dSLionel Sambuc   // default appertainsTo logic.
2319*0a6a1f1dSLionel Sambuc   if (Attr.isValueUnset("Subjects"))
2320*0a6a1f1dSLionel Sambuc     return "defaultAppertainsTo";
2321*0a6a1f1dSLionel Sambuc 
2322*0a6a1f1dSLionel Sambuc   const Record *SubjectObj = Attr.getValueAsDef("Subjects");
2323*0a6a1f1dSLionel Sambuc   std::vector<Record*> Subjects = SubjectObj->getValueAsListOfDefs("Subjects");
2324*0a6a1f1dSLionel Sambuc 
2325*0a6a1f1dSLionel Sambuc   // If the list of subjects is empty, it is assumed that the attribute
2326*0a6a1f1dSLionel Sambuc   // appertains to everything.
2327*0a6a1f1dSLionel Sambuc   if (Subjects.empty())
2328*0a6a1f1dSLionel Sambuc     return "defaultAppertainsTo";
2329*0a6a1f1dSLionel Sambuc 
2330*0a6a1f1dSLionel Sambuc   bool Warn = SubjectObj->getValueAsDef("Diag")->getValueAsBit("Warn");
2331*0a6a1f1dSLionel Sambuc 
2332*0a6a1f1dSLionel Sambuc   // Otherwise, generate an appertainsTo check specific to this attribute which
2333*0a6a1f1dSLionel Sambuc   // checks all of the given subjects against the Decl passed in. Return the
2334*0a6a1f1dSLionel Sambuc   // name of that check to the caller.
2335*0a6a1f1dSLionel Sambuc   std::string FnName = "check" + Attr.getName() + "AppertainsTo";
2336*0a6a1f1dSLionel Sambuc   std::stringstream SS;
2337*0a6a1f1dSLionel Sambuc   SS << "static bool " << FnName << "(Sema &S, const AttributeList &Attr, ";
2338*0a6a1f1dSLionel Sambuc   SS << "const Decl *D) {\n";
2339*0a6a1f1dSLionel Sambuc   SS << "  if (";
2340*0a6a1f1dSLionel Sambuc   for (auto I = Subjects.begin(), E = Subjects.end(); I != E; ++I) {
2341*0a6a1f1dSLionel Sambuc     // If the subject has custom code associated with it, generate a function
2342*0a6a1f1dSLionel Sambuc     // for it. The function cannot be inlined into this check (yet) because it
2343*0a6a1f1dSLionel Sambuc     // requires the subject to be of a specific type, and were that information
2344*0a6a1f1dSLionel Sambuc     // inlined here, it would not support an attribute with multiple custom
2345*0a6a1f1dSLionel Sambuc     // subjects.
2346*0a6a1f1dSLionel Sambuc     if ((*I)->isSubClassOf("SubsetSubject")) {
2347*0a6a1f1dSLionel Sambuc       SS << "!" << GenerateCustomAppertainsTo(**I, OS) << "(D)";
2348*0a6a1f1dSLionel Sambuc     } else {
2349*0a6a1f1dSLionel Sambuc       SS << "!isa<" << GetSubjectWithSuffix(*I) << ">(D)";
2350*0a6a1f1dSLionel Sambuc     }
2351*0a6a1f1dSLionel Sambuc 
2352*0a6a1f1dSLionel Sambuc     if (I + 1 != E)
2353*0a6a1f1dSLionel Sambuc       SS << " && ";
2354*0a6a1f1dSLionel Sambuc   }
2355*0a6a1f1dSLionel Sambuc   SS << ") {\n";
2356*0a6a1f1dSLionel Sambuc   SS << "    S.Diag(Attr.getLoc(), diag::";
2357*0a6a1f1dSLionel Sambuc   SS << (Warn ? "warn_attribute_wrong_decl_type" :
2358*0a6a1f1dSLionel Sambuc                "err_attribute_wrong_decl_type");
2359*0a6a1f1dSLionel Sambuc   SS << ")\n";
2360*0a6a1f1dSLionel Sambuc   SS << "      << Attr.getName() << ";
2361*0a6a1f1dSLionel Sambuc   SS << CalculateDiagnostic(*SubjectObj) << ";\n";
2362*0a6a1f1dSLionel Sambuc   SS << "    return false;\n";
2363*0a6a1f1dSLionel Sambuc   SS << "  }\n";
2364*0a6a1f1dSLionel Sambuc   SS << "  return true;\n";
2365*0a6a1f1dSLionel Sambuc   SS << "}\n\n";
2366*0a6a1f1dSLionel Sambuc 
2367*0a6a1f1dSLionel Sambuc   OS << SS.str();
2368*0a6a1f1dSLionel Sambuc   return FnName;
2369*0a6a1f1dSLionel Sambuc }
2370*0a6a1f1dSLionel Sambuc 
GenerateDefaultLangOptRequirements(raw_ostream & OS)2371*0a6a1f1dSLionel Sambuc static void GenerateDefaultLangOptRequirements(raw_ostream &OS) {
2372*0a6a1f1dSLionel Sambuc   OS << "static bool defaultDiagnoseLangOpts(Sema &, ";
2373*0a6a1f1dSLionel Sambuc   OS << "const AttributeList &) {\n";
2374*0a6a1f1dSLionel Sambuc   OS << "  return true;\n";
2375*0a6a1f1dSLionel Sambuc   OS << "}\n\n";
2376*0a6a1f1dSLionel Sambuc }
2377*0a6a1f1dSLionel Sambuc 
GenerateLangOptRequirements(const Record & R,raw_ostream & OS)2378*0a6a1f1dSLionel Sambuc static std::string GenerateLangOptRequirements(const Record &R,
2379*0a6a1f1dSLionel Sambuc                                                raw_ostream &OS) {
2380*0a6a1f1dSLionel Sambuc   // If the attribute has an empty or unset list of language requirements,
2381*0a6a1f1dSLionel Sambuc   // return the default handler.
2382*0a6a1f1dSLionel Sambuc   std::vector<Record *> LangOpts = R.getValueAsListOfDefs("LangOpts");
2383*0a6a1f1dSLionel Sambuc   if (LangOpts.empty())
2384*0a6a1f1dSLionel Sambuc     return "defaultDiagnoseLangOpts";
2385*0a6a1f1dSLionel Sambuc 
2386*0a6a1f1dSLionel Sambuc   // Generate the test condition, as well as a unique function name for the
2387*0a6a1f1dSLionel Sambuc   // diagnostic test. The list of options should usually be short (one or two
2388*0a6a1f1dSLionel Sambuc   // options), and the uniqueness isn't strictly necessary (it is just for
2389*0a6a1f1dSLionel Sambuc   // codegen efficiency).
2390*0a6a1f1dSLionel Sambuc   std::string FnName = "check", Test;
2391*0a6a1f1dSLionel Sambuc   for (auto I = LangOpts.begin(), E = LangOpts.end(); I != E; ++I) {
2392*0a6a1f1dSLionel Sambuc     std::string Part = (*I)->getValueAsString("Name");
2393*0a6a1f1dSLionel Sambuc     Test += "S.LangOpts." + Part;
2394*0a6a1f1dSLionel Sambuc     if (I + 1 != E)
2395*0a6a1f1dSLionel Sambuc       Test += " || ";
2396*0a6a1f1dSLionel Sambuc     FnName += Part;
2397*0a6a1f1dSLionel Sambuc   }
2398*0a6a1f1dSLionel Sambuc   FnName += "LangOpts";
2399*0a6a1f1dSLionel Sambuc 
2400*0a6a1f1dSLionel Sambuc   // If this code has already been generated, simply return the previous
2401*0a6a1f1dSLionel Sambuc   // instance of it.
2402*0a6a1f1dSLionel Sambuc   static std::set<std::string> CustomLangOptsSet;
2403*0a6a1f1dSLionel Sambuc   std::set<std::string>::iterator I = CustomLangOptsSet.find(FnName);
2404*0a6a1f1dSLionel Sambuc   if (I != CustomLangOptsSet.end())
2405*0a6a1f1dSLionel Sambuc     return *I;
2406*0a6a1f1dSLionel Sambuc 
2407*0a6a1f1dSLionel Sambuc   OS << "static bool " << FnName << "(Sema &S, const AttributeList &Attr) {\n";
2408*0a6a1f1dSLionel Sambuc   OS << "  if (" << Test << ")\n";
2409*0a6a1f1dSLionel Sambuc   OS << "    return true;\n\n";
2410*0a6a1f1dSLionel Sambuc   OS << "  S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) ";
2411*0a6a1f1dSLionel Sambuc   OS << "<< Attr.getName();\n";
2412*0a6a1f1dSLionel Sambuc   OS << "  return false;\n";
2413*0a6a1f1dSLionel Sambuc   OS << "}\n\n";
2414*0a6a1f1dSLionel Sambuc 
2415*0a6a1f1dSLionel Sambuc   CustomLangOptsSet.insert(FnName);
2416*0a6a1f1dSLionel Sambuc   return FnName;
2417*0a6a1f1dSLionel Sambuc }
2418*0a6a1f1dSLionel Sambuc 
GenerateDefaultTargetRequirements(raw_ostream & OS)2419*0a6a1f1dSLionel Sambuc static void GenerateDefaultTargetRequirements(raw_ostream &OS) {
2420*0a6a1f1dSLionel Sambuc   OS << "static bool defaultTargetRequirements(const llvm::Triple &) {\n";
2421*0a6a1f1dSLionel Sambuc   OS << "  return true;\n";
2422*0a6a1f1dSLionel Sambuc   OS << "}\n\n";
2423*0a6a1f1dSLionel Sambuc }
2424*0a6a1f1dSLionel Sambuc 
GenerateTargetRequirements(const Record & Attr,const ParsedAttrMap & Dupes,raw_ostream & OS)2425*0a6a1f1dSLionel Sambuc static std::string GenerateTargetRequirements(const Record &Attr,
2426*0a6a1f1dSLionel Sambuc                                               const ParsedAttrMap &Dupes,
2427*0a6a1f1dSLionel Sambuc                                               raw_ostream &OS) {
2428*0a6a1f1dSLionel Sambuc   // If the attribute is not a target specific attribute, return the default
2429*0a6a1f1dSLionel Sambuc   // target handler.
2430*0a6a1f1dSLionel Sambuc   if (!Attr.isSubClassOf("TargetSpecificAttr"))
2431*0a6a1f1dSLionel Sambuc     return "defaultTargetRequirements";
2432*0a6a1f1dSLionel Sambuc 
2433*0a6a1f1dSLionel Sambuc   // Get the list of architectures to be tested for.
2434*0a6a1f1dSLionel Sambuc   const Record *R = Attr.getValueAsDef("Target");
2435*0a6a1f1dSLionel Sambuc   std::vector<std::string> Arches = R->getValueAsListOfStrings("Arches");
2436*0a6a1f1dSLionel Sambuc   if (Arches.empty()) {
2437*0a6a1f1dSLionel Sambuc     PrintError(Attr.getLoc(), "Empty list of target architectures for a "
2438*0a6a1f1dSLionel Sambuc                               "target-specific attr");
2439*0a6a1f1dSLionel Sambuc     return "defaultTargetRequirements";
2440*0a6a1f1dSLionel Sambuc   }
2441*0a6a1f1dSLionel Sambuc 
2442*0a6a1f1dSLionel Sambuc   // If there are other attributes which share the same parsed attribute kind,
2443*0a6a1f1dSLionel Sambuc   // such as target-specific attributes with a shared spelling, collapse the
2444*0a6a1f1dSLionel Sambuc   // duplicate architectures. This is required because a shared target-specific
2445*0a6a1f1dSLionel Sambuc   // attribute has only one AttributeList::Kind enumeration value, but it
2446*0a6a1f1dSLionel Sambuc   // applies to multiple target architectures. In order for the attribute to be
2447*0a6a1f1dSLionel Sambuc   // considered valid, all of its architectures need to be included.
2448*0a6a1f1dSLionel Sambuc   if (!Attr.isValueUnset("ParseKind")) {
2449*0a6a1f1dSLionel Sambuc     std::string APK = Attr.getValueAsString("ParseKind");
2450*0a6a1f1dSLionel Sambuc     for (const auto &I : Dupes) {
2451*0a6a1f1dSLionel Sambuc       if (I.first == APK) {
2452*0a6a1f1dSLionel Sambuc         std::vector<std::string> DA = I.second->getValueAsDef("Target")
2453*0a6a1f1dSLionel Sambuc                                           ->getValueAsListOfStrings("Arches");
2454*0a6a1f1dSLionel Sambuc         std::copy(DA.begin(), DA.end(), std::back_inserter(Arches));
2455*0a6a1f1dSLionel Sambuc       }
2456*0a6a1f1dSLionel Sambuc     }
2457*0a6a1f1dSLionel Sambuc   }
2458*0a6a1f1dSLionel Sambuc 
2459*0a6a1f1dSLionel Sambuc   std::string FnName = "isTarget", Test = "(";
2460*0a6a1f1dSLionel Sambuc   for (auto I = Arches.begin(), E = Arches.end(); I != E; ++I) {
2461*0a6a1f1dSLionel Sambuc     std::string Part = *I;
2462*0a6a1f1dSLionel Sambuc     Test += "Arch == llvm::Triple::" + Part;
2463*0a6a1f1dSLionel Sambuc     if (I + 1 != E)
2464*0a6a1f1dSLionel Sambuc       Test += " || ";
2465*0a6a1f1dSLionel Sambuc     FnName += Part;
2466*0a6a1f1dSLionel Sambuc   }
2467*0a6a1f1dSLionel Sambuc   Test += ")";
2468*0a6a1f1dSLionel Sambuc 
2469*0a6a1f1dSLionel Sambuc   // If the target also requires OS testing, generate those tests as well.
2470*0a6a1f1dSLionel Sambuc   bool UsesOS = false;
2471*0a6a1f1dSLionel Sambuc   if (!R->isValueUnset("OSes")) {
2472*0a6a1f1dSLionel Sambuc     UsesOS = true;
2473*0a6a1f1dSLionel Sambuc 
2474*0a6a1f1dSLionel Sambuc     // We know that there was at least one arch test, so we need to and in the
2475*0a6a1f1dSLionel Sambuc     // OS tests.
2476*0a6a1f1dSLionel Sambuc     Test += " && (";
2477*0a6a1f1dSLionel Sambuc     std::vector<std::string> OSes = R->getValueAsListOfStrings("OSes");
2478*0a6a1f1dSLionel Sambuc     for (auto I = OSes.begin(), E = OSes.end(); I != E; ++I) {
2479*0a6a1f1dSLionel Sambuc       std::string Part = *I;
2480*0a6a1f1dSLionel Sambuc 
2481*0a6a1f1dSLionel Sambuc       Test += "OS == llvm::Triple::" + Part;
2482*0a6a1f1dSLionel Sambuc       if (I + 1 != E)
2483*0a6a1f1dSLionel Sambuc         Test += " || ";
2484*0a6a1f1dSLionel Sambuc       FnName += Part;
2485*0a6a1f1dSLionel Sambuc     }
2486*0a6a1f1dSLionel Sambuc     Test += ")";
2487*0a6a1f1dSLionel Sambuc   }
2488*0a6a1f1dSLionel Sambuc 
2489*0a6a1f1dSLionel Sambuc   // If this code has already been generated, simply return the previous
2490*0a6a1f1dSLionel Sambuc   // instance of it.
2491*0a6a1f1dSLionel Sambuc   static std::set<std::string> CustomTargetSet;
2492*0a6a1f1dSLionel Sambuc   std::set<std::string>::iterator I = CustomTargetSet.find(FnName);
2493*0a6a1f1dSLionel Sambuc   if (I != CustomTargetSet.end())
2494*0a6a1f1dSLionel Sambuc     return *I;
2495*0a6a1f1dSLionel Sambuc 
2496*0a6a1f1dSLionel Sambuc   OS << "static bool " << FnName << "(const llvm::Triple &T) {\n";
2497*0a6a1f1dSLionel Sambuc   OS << "  llvm::Triple::ArchType Arch = T.getArch();\n";
2498*0a6a1f1dSLionel Sambuc   if (UsesOS)
2499*0a6a1f1dSLionel Sambuc     OS << "  llvm::Triple::OSType OS = T.getOS();\n";
2500*0a6a1f1dSLionel Sambuc   OS << "  return " << Test << ";\n";
2501*0a6a1f1dSLionel Sambuc   OS << "}\n\n";
2502*0a6a1f1dSLionel Sambuc 
2503*0a6a1f1dSLionel Sambuc   CustomTargetSet.insert(FnName);
2504*0a6a1f1dSLionel Sambuc   return FnName;
2505*0a6a1f1dSLionel Sambuc }
2506*0a6a1f1dSLionel Sambuc 
GenerateDefaultSpellingIndexToSemanticSpelling(raw_ostream & OS)2507*0a6a1f1dSLionel Sambuc static void GenerateDefaultSpellingIndexToSemanticSpelling(raw_ostream &OS) {
2508*0a6a1f1dSLionel Sambuc   OS << "static unsigned defaultSpellingIndexToSemanticSpelling("
2509*0a6a1f1dSLionel Sambuc      << "const AttributeList &Attr) {\n";
2510*0a6a1f1dSLionel Sambuc   OS << "  return UINT_MAX;\n";
2511*0a6a1f1dSLionel Sambuc   OS << "}\n\n";
2512*0a6a1f1dSLionel Sambuc }
2513*0a6a1f1dSLionel Sambuc 
GenerateSpellingIndexToSemanticSpelling(const Record & Attr,raw_ostream & OS)2514*0a6a1f1dSLionel Sambuc static std::string GenerateSpellingIndexToSemanticSpelling(const Record &Attr,
2515*0a6a1f1dSLionel Sambuc                                                            raw_ostream &OS) {
2516*0a6a1f1dSLionel Sambuc   // If the attribute does not have a semantic form, we can bail out early.
2517*0a6a1f1dSLionel Sambuc   if (!Attr.getValueAsBit("ASTNode"))
2518*0a6a1f1dSLionel Sambuc     return "defaultSpellingIndexToSemanticSpelling";
2519*0a6a1f1dSLionel Sambuc 
2520*0a6a1f1dSLionel Sambuc   std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
2521*0a6a1f1dSLionel Sambuc 
2522*0a6a1f1dSLionel Sambuc   // If there are zero or one spellings, or all of the spellings share the same
2523*0a6a1f1dSLionel Sambuc   // name, we can also bail out early.
2524*0a6a1f1dSLionel Sambuc   if (Spellings.size() <= 1 || SpellingNamesAreCommon(Spellings))
2525*0a6a1f1dSLionel Sambuc     return "defaultSpellingIndexToSemanticSpelling";
2526*0a6a1f1dSLionel Sambuc 
2527*0a6a1f1dSLionel Sambuc   // Generate the enumeration we will use for the mapping.
2528*0a6a1f1dSLionel Sambuc   SemanticSpellingMap SemanticToSyntacticMap;
2529*0a6a1f1dSLionel Sambuc   std::string Enum = CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);
2530*0a6a1f1dSLionel Sambuc   std::string Name = Attr.getName() + "AttrSpellingMap";
2531*0a6a1f1dSLionel Sambuc 
2532*0a6a1f1dSLionel Sambuc   OS << "static unsigned " << Name << "(const AttributeList &Attr) {\n";
2533*0a6a1f1dSLionel Sambuc   OS << Enum;
2534*0a6a1f1dSLionel Sambuc   OS << "  unsigned Idx = Attr.getAttributeSpellingListIndex();\n";
2535*0a6a1f1dSLionel Sambuc   WriteSemanticSpellingSwitch("Idx", SemanticToSyntacticMap, OS);
2536*0a6a1f1dSLionel Sambuc   OS << "}\n\n";
2537*0a6a1f1dSLionel Sambuc 
2538*0a6a1f1dSLionel Sambuc   return Name;
2539*0a6a1f1dSLionel Sambuc }
2540*0a6a1f1dSLionel Sambuc 
IsKnownToGCC(const Record & Attr)2541*0a6a1f1dSLionel Sambuc static bool IsKnownToGCC(const Record &Attr) {
2542*0a6a1f1dSLionel Sambuc   // Look at the spellings for this subject; if there are any spellings which
2543*0a6a1f1dSLionel Sambuc   // claim to be known to GCC, the attribute is known to GCC.
2544*0a6a1f1dSLionel Sambuc   std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
2545*0a6a1f1dSLionel Sambuc   for (const auto &I : Spellings) {
2546*0a6a1f1dSLionel Sambuc     if (I.knownToGCC())
2547*0a6a1f1dSLionel Sambuc       return true;
2548*0a6a1f1dSLionel Sambuc   }
2549*0a6a1f1dSLionel Sambuc   return false;
2550f4a2713aSLionel Sambuc }
2551f4a2713aSLionel Sambuc 
2552f4a2713aSLionel Sambuc /// Emits the parsed attribute helpers
EmitClangAttrParsedAttrImpl(RecordKeeper & Records,raw_ostream & OS)2553f4a2713aSLionel Sambuc void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
2554f4a2713aSLionel Sambuc   emitSourceFileHeader("Parsed attribute helpers", OS);
2555f4a2713aSLionel Sambuc 
2556*0a6a1f1dSLionel Sambuc   // Get the list of parsed attributes, and accept the optional list of
2557*0a6a1f1dSLionel Sambuc   // duplicates due to the ParseKind.
2558*0a6a1f1dSLionel Sambuc   ParsedAttrMap Dupes;
2559*0a6a1f1dSLionel Sambuc   ParsedAttrMap Attrs = getParsedAttrList(Records, &Dupes);
2560f4a2713aSLionel Sambuc 
2561*0a6a1f1dSLionel Sambuc   // Generate the default appertainsTo, target and language option diagnostic,
2562*0a6a1f1dSLionel Sambuc   // and spelling list index mapping methods.
2563*0a6a1f1dSLionel Sambuc   GenerateDefaultAppertainsTo(OS);
2564*0a6a1f1dSLionel Sambuc   GenerateDefaultLangOptRequirements(OS);
2565*0a6a1f1dSLionel Sambuc   GenerateDefaultTargetRequirements(OS);
2566*0a6a1f1dSLionel Sambuc   GenerateDefaultSpellingIndexToSemanticSpelling(OS);
2567*0a6a1f1dSLionel Sambuc 
2568*0a6a1f1dSLionel Sambuc   // Generate the appertainsTo diagnostic methods and write their names into
2569*0a6a1f1dSLionel Sambuc   // another mapping. At the same time, generate the AttrInfoMap object
2570*0a6a1f1dSLionel Sambuc   // contents. Due to the reliance on generated code, use separate streams so
2571*0a6a1f1dSLionel Sambuc   // that code will not be interleaved.
2572*0a6a1f1dSLionel Sambuc   std::stringstream SS;
2573*0a6a1f1dSLionel Sambuc   for (auto I = Attrs.begin(), E = Attrs.end(); I != E; ++I) {
2574*0a6a1f1dSLionel Sambuc     // TODO: If the attribute's kind appears in the list of duplicates, that is
2575*0a6a1f1dSLionel Sambuc     // because it is a target-specific attribute that appears multiple times.
2576*0a6a1f1dSLionel Sambuc     // It would be beneficial to test whether the duplicates are "similar
2577*0a6a1f1dSLionel Sambuc     // enough" to each other to not cause problems. For instance, check that
2578*0a6a1f1dSLionel Sambuc     // the spellings are identical, and custom parsing rules match, etc.
2579*0a6a1f1dSLionel Sambuc 
2580f4a2713aSLionel Sambuc     // We need to generate struct instances based off ParsedAttrInfo from
2581f4a2713aSLionel Sambuc     // AttributeList.cpp.
2582*0a6a1f1dSLionel Sambuc     SS << "  { ";
2583*0a6a1f1dSLionel Sambuc     emitArgInfo(*I->second, SS);
2584*0a6a1f1dSLionel Sambuc     SS << ", " << I->second->getValueAsBit("HasCustomParsing");
2585*0a6a1f1dSLionel Sambuc     SS << ", " << I->second->isSubClassOf("TargetSpecificAttr");
2586*0a6a1f1dSLionel Sambuc     SS << ", " << I->second->isSubClassOf("TypeAttr");
2587*0a6a1f1dSLionel Sambuc     SS << ", " << IsKnownToGCC(*I->second);
2588*0a6a1f1dSLionel Sambuc     SS << ", " << GenerateAppertainsTo(*I->second, OS);
2589*0a6a1f1dSLionel Sambuc     SS << ", " << GenerateLangOptRequirements(*I->second, OS);
2590*0a6a1f1dSLionel Sambuc     SS << ", " << GenerateTargetRequirements(*I->second, Dupes, OS);
2591*0a6a1f1dSLionel Sambuc     SS << ", " << GenerateSpellingIndexToSemanticSpelling(*I->second, OS);
2592*0a6a1f1dSLionel Sambuc     SS << " }";
2593f4a2713aSLionel Sambuc 
2594f4a2713aSLionel Sambuc     if (I + 1 != E)
2595*0a6a1f1dSLionel Sambuc       SS << ",";
2596f4a2713aSLionel Sambuc 
2597*0a6a1f1dSLionel Sambuc     SS << "  // AT_" << I->first << "\n";
2598f4a2713aSLionel Sambuc   }
2599*0a6a1f1dSLionel Sambuc 
2600*0a6a1f1dSLionel Sambuc   OS << "static const ParsedAttrInfo AttrInfoMap[AttributeList::UnknownAttribute + 1] = {\n";
2601*0a6a1f1dSLionel Sambuc   OS << SS.str();
2602f4a2713aSLionel Sambuc   OS << "};\n\n";
2603f4a2713aSLionel Sambuc }
2604f4a2713aSLionel Sambuc 
2605f4a2713aSLionel Sambuc // Emits the kind list of parsed attributes
EmitClangAttrParsedAttrKinds(RecordKeeper & Records,raw_ostream & OS)2606f4a2713aSLionel Sambuc void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
2607f4a2713aSLionel Sambuc   emitSourceFileHeader("Attribute name matcher", OS);
2608f4a2713aSLionel Sambuc 
2609f4a2713aSLionel Sambuc   std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
2610*0a6a1f1dSLionel Sambuc   std::vector<StringMatcher::StringPair> GNU, Declspec, CXX11, Keywords, Pragma;
2611*0a6a1f1dSLionel Sambuc   std::set<std::string> Seen;
2612*0a6a1f1dSLionel Sambuc   for (const auto *A : Attrs) {
2613*0a6a1f1dSLionel Sambuc     const Record &Attr = *A;
2614f4a2713aSLionel Sambuc 
2615f4a2713aSLionel Sambuc     bool SemaHandler = Attr.getValueAsBit("SemaHandler");
2616f4a2713aSLionel Sambuc     bool Ignored = Attr.getValueAsBit("Ignored");
2617f4a2713aSLionel Sambuc     if (SemaHandler || Ignored) {
2618*0a6a1f1dSLionel Sambuc       // Attribute spellings can be shared between target-specific attributes,
2619*0a6a1f1dSLionel Sambuc       // and can be shared between syntaxes for the same attribute. For
2620*0a6a1f1dSLionel Sambuc       // instance, an attribute can be spelled GNU<"interrupt"> for an ARM-
2621*0a6a1f1dSLionel Sambuc       // specific attribute, or MSP430-specific attribute. Additionally, an
2622*0a6a1f1dSLionel Sambuc       // attribute can be spelled GNU<"dllexport"> and Declspec<"dllexport">
2623*0a6a1f1dSLionel Sambuc       // for the same semantic attribute. Ultimately, we need to map each of
2624*0a6a1f1dSLionel Sambuc       // these to a single AttributeList::Kind value, but the StringMatcher
2625*0a6a1f1dSLionel Sambuc       // class cannot handle duplicate match strings. So we generate a list of
2626*0a6a1f1dSLionel Sambuc       // string to match based on the syntax, and emit multiple string matchers
2627*0a6a1f1dSLionel Sambuc       // depending on the syntax used.
2628*0a6a1f1dSLionel Sambuc       std::string AttrName;
2629*0a6a1f1dSLionel Sambuc       if (Attr.isSubClassOf("TargetSpecificAttr") &&
2630*0a6a1f1dSLionel Sambuc           !Attr.isValueUnset("ParseKind")) {
2631*0a6a1f1dSLionel Sambuc         AttrName = Attr.getValueAsString("ParseKind");
2632*0a6a1f1dSLionel Sambuc         if (Seen.find(AttrName) != Seen.end())
2633*0a6a1f1dSLionel Sambuc           continue;
2634*0a6a1f1dSLionel Sambuc         Seen.insert(AttrName);
2635*0a6a1f1dSLionel Sambuc       } else
2636*0a6a1f1dSLionel Sambuc         AttrName = NormalizeAttrName(StringRef(Attr.getName())).str();
2637f4a2713aSLionel Sambuc 
2638*0a6a1f1dSLionel Sambuc       std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
2639*0a6a1f1dSLionel Sambuc       for (const auto &S : Spellings) {
2640*0a6a1f1dSLionel Sambuc         std::string RawSpelling = S.name();
2641*0a6a1f1dSLionel Sambuc         std::vector<StringMatcher::StringPair> *Matches = nullptr;
2642*0a6a1f1dSLionel Sambuc         std::string Spelling, Variety = S.variety();
2643*0a6a1f1dSLionel Sambuc         if (Variety == "CXX11") {
2644*0a6a1f1dSLionel Sambuc           Matches = &CXX11;
2645*0a6a1f1dSLionel Sambuc           Spelling += S.nameSpace();
2646f4a2713aSLionel Sambuc           Spelling += "::";
2647*0a6a1f1dSLionel Sambuc         } else if (Variety == "GNU")
2648*0a6a1f1dSLionel Sambuc           Matches = &GNU;
2649*0a6a1f1dSLionel Sambuc         else if (Variety == "Declspec")
2650*0a6a1f1dSLionel Sambuc           Matches = &Declspec;
2651*0a6a1f1dSLionel Sambuc         else if (Variety == "Keyword")
2652*0a6a1f1dSLionel Sambuc           Matches = &Keywords;
2653*0a6a1f1dSLionel Sambuc         else if (Variety == "Pragma")
2654*0a6a1f1dSLionel Sambuc           Matches = &Pragma;
2655f4a2713aSLionel Sambuc 
2656*0a6a1f1dSLionel Sambuc         assert(Matches && "Unsupported spelling variety found");
2657*0a6a1f1dSLionel Sambuc 
2658*0a6a1f1dSLionel Sambuc         Spelling += NormalizeAttrSpelling(RawSpelling);
2659f4a2713aSLionel Sambuc         if (SemaHandler)
2660*0a6a1f1dSLionel Sambuc           Matches->push_back(StringMatcher::StringPair(Spelling,
2661*0a6a1f1dSLionel Sambuc                               "return AttributeList::AT_" + AttrName + ";"));
2662f4a2713aSLionel Sambuc         else
2663*0a6a1f1dSLionel Sambuc           Matches->push_back(StringMatcher::StringPair(Spelling,
2664f4a2713aSLionel Sambuc                               "return AttributeList::IgnoredAttribute;"));
2665f4a2713aSLionel Sambuc       }
2666f4a2713aSLionel Sambuc     }
2667f4a2713aSLionel Sambuc   }
2668f4a2713aSLionel Sambuc 
2669*0a6a1f1dSLionel Sambuc   OS << "static AttributeList::Kind getAttrKind(StringRef Name, ";
2670*0a6a1f1dSLionel Sambuc   OS << "AttributeList::Syntax Syntax) {\n";
2671*0a6a1f1dSLionel Sambuc   OS << "  if (AttributeList::AS_GNU == Syntax) {\n";
2672*0a6a1f1dSLionel Sambuc   StringMatcher("Name", GNU, OS).Emit();
2673*0a6a1f1dSLionel Sambuc   OS << "  } else if (AttributeList::AS_Declspec == Syntax) {\n";
2674*0a6a1f1dSLionel Sambuc   StringMatcher("Name", Declspec, OS).Emit();
2675*0a6a1f1dSLionel Sambuc   OS << "  } else if (AttributeList::AS_CXX11 == Syntax) {\n";
2676*0a6a1f1dSLionel Sambuc   StringMatcher("Name", CXX11, OS).Emit();
2677*0a6a1f1dSLionel Sambuc   OS << "  } else if (AttributeList::AS_Keyword == Syntax) {\n";
2678*0a6a1f1dSLionel Sambuc   StringMatcher("Name", Keywords, OS).Emit();
2679*0a6a1f1dSLionel Sambuc   OS << "  } else if (AttributeList::AS_Pragma == Syntax) {\n";
2680*0a6a1f1dSLionel Sambuc   StringMatcher("Name", Pragma, OS).Emit();
2681*0a6a1f1dSLionel Sambuc   OS << "  }\n";
2682f4a2713aSLionel Sambuc   OS << "  return AttributeList::UnknownAttribute;\n"
2683f4a2713aSLionel Sambuc      << "}\n";
2684f4a2713aSLionel Sambuc }
2685f4a2713aSLionel Sambuc 
2686f4a2713aSLionel Sambuc // Emits the code to dump an attribute.
EmitClangAttrDump(RecordKeeper & Records,raw_ostream & OS)2687f4a2713aSLionel Sambuc void EmitClangAttrDump(RecordKeeper &Records, raw_ostream &OS) {
2688f4a2713aSLionel Sambuc   emitSourceFileHeader("Attribute dumper", OS);
2689f4a2713aSLionel Sambuc 
2690f4a2713aSLionel Sambuc   OS <<
2691f4a2713aSLionel Sambuc     "  switch (A->getKind()) {\n"
2692f4a2713aSLionel Sambuc     "  default:\n"
2693f4a2713aSLionel Sambuc     "    llvm_unreachable(\"Unknown attribute kind!\");\n"
2694f4a2713aSLionel Sambuc     "    break;\n";
2695f4a2713aSLionel Sambuc   std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
2696*0a6a1f1dSLionel Sambuc   for (const auto *Attr : Attrs) {
2697*0a6a1f1dSLionel Sambuc     const Record &R = *Attr;
2698f4a2713aSLionel Sambuc     if (!R.getValueAsBit("ASTNode"))
2699f4a2713aSLionel Sambuc       continue;
2700f4a2713aSLionel Sambuc     OS << "  case attr::" << R.getName() << ": {\n";
2701*0a6a1f1dSLionel Sambuc 
2702*0a6a1f1dSLionel Sambuc     // If the attribute has a semantically-meaningful name (which is determined
2703*0a6a1f1dSLionel Sambuc     // by whether there is a Spelling enumeration for it), then write out the
2704*0a6a1f1dSLionel Sambuc     // spelling used for the attribute.
2705*0a6a1f1dSLionel Sambuc     std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
2706*0a6a1f1dSLionel Sambuc     if (Spellings.size() > 1 && !SpellingNamesAreCommon(Spellings))
2707*0a6a1f1dSLionel Sambuc       OS << "    OS << \" \" << A->getSpelling();\n";
2708*0a6a1f1dSLionel Sambuc 
2709f4a2713aSLionel Sambuc     Args = R.getValueAsListOfDefs("Args");
2710f4a2713aSLionel Sambuc     if (!Args.empty()) {
2711f4a2713aSLionel Sambuc       OS << "    const " << R.getName() << "Attr *SA = cast<" << R.getName()
2712f4a2713aSLionel Sambuc          << "Attr>(A);\n";
2713*0a6a1f1dSLionel Sambuc       for (const auto *Arg : Args)
2714*0a6a1f1dSLionel Sambuc         createArgument(*Arg, R.getName())->writeDump(OS);
2715f4a2713aSLionel Sambuc 
2716*0a6a1f1dSLionel Sambuc       for (auto AI = Args.begin(), AE = Args.end(); AI != AE; ++AI)
2717*0a6a1f1dSLionel Sambuc         createArgument(**AI, R.getName())->writeDumpChildren(OS);
2718f4a2713aSLionel Sambuc     }
2719f4a2713aSLionel Sambuc     OS <<
2720f4a2713aSLionel Sambuc       "    break;\n"
2721f4a2713aSLionel Sambuc       "  }\n";
2722f4a2713aSLionel Sambuc   }
2723f4a2713aSLionel Sambuc   OS << "  }\n";
2724f4a2713aSLionel Sambuc }
2725f4a2713aSLionel Sambuc 
EmitClangAttrParserStringSwitches(RecordKeeper & Records,raw_ostream & OS)2726*0a6a1f1dSLionel Sambuc void EmitClangAttrParserStringSwitches(RecordKeeper &Records,
2727*0a6a1f1dSLionel Sambuc                                        raw_ostream &OS) {
2728*0a6a1f1dSLionel Sambuc   emitSourceFileHeader("Parser-related llvm::StringSwitch cases", OS);
2729*0a6a1f1dSLionel Sambuc   emitClangAttrArgContextList(Records, OS);
2730*0a6a1f1dSLionel Sambuc   emitClangAttrIdentifierArgList(Records, OS);
2731*0a6a1f1dSLionel Sambuc   emitClangAttrTypeArgList(Records, OS);
2732*0a6a1f1dSLionel Sambuc   emitClangAttrLateParsedList(Records, OS);
2733*0a6a1f1dSLionel Sambuc }
2734*0a6a1f1dSLionel Sambuc 
2735*0a6a1f1dSLionel Sambuc class DocumentationData {
2736*0a6a1f1dSLionel Sambuc public:
2737*0a6a1f1dSLionel Sambuc   const Record *Documentation;
2738*0a6a1f1dSLionel Sambuc   const Record *Attribute;
2739*0a6a1f1dSLionel Sambuc 
DocumentationData(const Record & Documentation,const Record & Attribute)2740*0a6a1f1dSLionel Sambuc   DocumentationData(const Record &Documentation, const Record &Attribute)
2741*0a6a1f1dSLionel Sambuc       : Documentation(&Documentation), Attribute(&Attribute) {}
2742*0a6a1f1dSLionel Sambuc };
2743*0a6a1f1dSLionel Sambuc 
WriteCategoryHeader(const Record * DocCategory,raw_ostream & OS)2744*0a6a1f1dSLionel Sambuc static void WriteCategoryHeader(const Record *DocCategory,
2745*0a6a1f1dSLionel Sambuc                                 raw_ostream &OS) {
2746*0a6a1f1dSLionel Sambuc   const std::string &Name = DocCategory->getValueAsString("Name");
2747*0a6a1f1dSLionel Sambuc   OS << Name << "\n" << std::string(Name.length(), '=') << "\n";
2748*0a6a1f1dSLionel Sambuc 
2749*0a6a1f1dSLionel Sambuc   // If there is content, print that as well.
2750*0a6a1f1dSLionel Sambuc   std::string ContentStr = DocCategory->getValueAsString("Content");
2751*0a6a1f1dSLionel Sambuc   if (!ContentStr.empty()) {
2752*0a6a1f1dSLionel Sambuc     // Trim leading and trailing newlines and spaces.
2753*0a6a1f1dSLionel Sambuc     StringRef Content(ContentStr);
2754*0a6a1f1dSLionel Sambuc     while (Content.startswith("\r") || Content.startswith("\n") ||
2755*0a6a1f1dSLionel Sambuc            Content.startswith(" ") || Content.startswith("\t"))
2756*0a6a1f1dSLionel Sambuc            Content = Content.substr(1);
2757*0a6a1f1dSLionel Sambuc     while (Content.endswith("\r") || Content.endswith("\n") ||
2758*0a6a1f1dSLionel Sambuc            Content.endswith(" ") || Content.endswith("\t"))
2759*0a6a1f1dSLionel Sambuc            Content = Content.substr(0, Content.size() - 1);
2760*0a6a1f1dSLionel Sambuc     OS << Content;
2761*0a6a1f1dSLionel Sambuc   }
2762*0a6a1f1dSLionel Sambuc   OS << "\n\n";
2763*0a6a1f1dSLionel Sambuc }
2764*0a6a1f1dSLionel Sambuc 
2765*0a6a1f1dSLionel Sambuc enum SpellingKind {
2766*0a6a1f1dSLionel Sambuc   GNU = 1 << 0,
2767*0a6a1f1dSLionel Sambuc   CXX11 = 1 << 1,
2768*0a6a1f1dSLionel Sambuc   Declspec = 1 << 2,
2769*0a6a1f1dSLionel Sambuc   Keyword = 1 << 3,
2770*0a6a1f1dSLionel Sambuc   Pragma = 1 << 4
2771*0a6a1f1dSLionel Sambuc };
2772*0a6a1f1dSLionel Sambuc 
WriteDocumentation(const DocumentationData & Doc,raw_ostream & OS)2773*0a6a1f1dSLionel Sambuc static void WriteDocumentation(const DocumentationData &Doc,
2774*0a6a1f1dSLionel Sambuc                                raw_ostream &OS) {
2775*0a6a1f1dSLionel Sambuc   // FIXME: there is no way to have a per-spelling category for the attribute
2776*0a6a1f1dSLionel Sambuc   // documentation. This may not be a limiting factor since the spellings
2777*0a6a1f1dSLionel Sambuc   // should generally be consistently applied across the category.
2778*0a6a1f1dSLionel Sambuc 
2779*0a6a1f1dSLionel Sambuc   std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Doc.Attribute);
2780*0a6a1f1dSLionel Sambuc 
2781*0a6a1f1dSLionel Sambuc   // Determine the heading to be used for this attribute.
2782*0a6a1f1dSLionel Sambuc   std::string Heading = Doc.Documentation->getValueAsString("Heading");
2783*0a6a1f1dSLionel Sambuc   bool CustomHeading = !Heading.empty();
2784*0a6a1f1dSLionel Sambuc   if (Heading.empty()) {
2785*0a6a1f1dSLionel Sambuc     // If there's only one spelling, we can simply use that.
2786*0a6a1f1dSLionel Sambuc     if (Spellings.size() == 1)
2787*0a6a1f1dSLionel Sambuc       Heading = Spellings.begin()->name();
2788*0a6a1f1dSLionel Sambuc     else {
2789*0a6a1f1dSLionel Sambuc       std::set<std::string> Uniques;
2790*0a6a1f1dSLionel Sambuc       for (auto I = Spellings.begin(), E = Spellings.end();
2791*0a6a1f1dSLionel Sambuc            I != E && Uniques.size() <= 1; ++I) {
2792*0a6a1f1dSLionel Sambuc         std::string Spelling = NormalizeNameForSpellingComparison(I->name());
2793*0a6a1f1dSLionel Sambuc         Uniques.insert(Spelling);
2794*0a6a1f1dSLionel Sambuc       }
2795*0a6a1f1dSLionel Sambuc       // If the semantic map has only one spelling, that is sufficient for our
2796*0a6a1f1dSLionel Sambuc       // needs.
2797*0a6a1f1dSLionel Sambuc       if (Uniques.size() == 1)
2798*0a6a1f1dSLionel Sambuc         Heading = *Uniques.begin();
2799*0a6a1f1dSLionel Sambuc     }
2800*0a6a1f1dSLionel Sambuc   }
2801*0a6a1f1dSLionel Sambuc 
2802*0a6a1f1dSLionel Sambuc   // If the heading is still empty, it is an error.
2803*0a6a1f1dSLionel Sambuc   if (Heading.empty())
2804*0a6a1f1dSLionel Sambuc     PrintFatalError(Doc.Attribute->getLoc(),
2805*0a6a1f1dSLionel Sambuc                     "This attribute requires a heading to be specified");
2806*0a6a1f1dSLionel Sambuc 
2807*0a6a1f1dSLionel Sambuc   // Gather a list of unique spellings; this is not the same as the semantic
2808*0a6a1f1dSLionel Sambuc   // spelling for the attribute. Variations in underscores and other non-
2809*0a6a1f1dSLionel Sambuc   // semantic characters are still acceptable.
2810*0a6a1f1dSLionel Sambuc   std::vector<std::string> Names;
2811*0a6a1f1dSLionel Sambuc 
2812*0a6a1f1dSLionel Sambuc   unsigned SupportedSpellings = 0;
2813*0a6a1f1dSLionel Sambuc   for (const auto &I : Spellings) {
2814*0a6a1f1dSLionel Sambuc     SpellingKind Kind = StringSwitch<SpellingKind>(I.variety())
2815*0a6a1f1dSLionel Sambuc                             .Case("GNU", GNU)
2816*0a6a1f1dSLionel Sambuc                             .Case("CXX11", CXX11)
2817*0a6a1f1dSLionel Sambuc                             .Case("Declspec", Declspec)
2818*0a6a1f1dSLionel Sambuc                             .Case("Keyword", Keyword)
2819*0a6a1f1dSLionel Sambuc                             .Case("Pragma", Pragma);
2820*0a6a1f1dSLionel Sambuc 
2821*0a6a1f1dSLionel Sambuc     // Mask in the supported spelling.
2822*0a6a1f1dSLionel Sambuc     SupportedSpellings |= Kind;
2823*0a6a1f1dSLionel Sambuc 
2824*0a6a1f1dSLionel Sambuc     std::string Name;
2825*0a6a1f1dSLionel Sambuc     if (Kind == CXX11 && !I.nameSpace().empty())
2826*0a6a1f1dSLionel Sambuc       Name = I.nameSpace() + "::";
2827*0a6a1f1dSLionel Sambuc     Name += I.name();
2828*0a6a1f1dSLionel Sambuc 
2829*0a6a1f1dSLionel Sambuc     // If this name is the same as the heading, do not add it.
2830*0a6a1f1dSLionel Sambuc     if (Name != Heading)
2831*0a6a1f1dSLionel Sambuc       Names.push_back(Name);
2832*0a6a1f1dSLionel Sambuc   }
2833*0a6a1f1dSLionel Sambuc 
2834*0a6a1f1dSLionel Sambuc   // Print out the heading for the attribute. If there are alternate spellings,
2835*0a6a1f1dSLionel Sambuc   // then display those after the heading.
2836*0a6a1f1dSLionel Sambuc   if (!CustomHeading && !Names.empty()) {
2837*0a6a1f1dSLionel Sambuc     Heading += " (";
2838*0a6a1f1dSLionel Sambuc     for (auto I = Names.begin(), E = Names.end(); I != E; ++I) {
2839*0a6a1f1dSLionel Sambuc       if (I != Names.begin())
2840*0a6a1f1dSLionel Sambuc         Heading += ", ";
2841*0a6a1f1dSLionel Sambuc       Heading += *I;
2842*0a6a1f1dSLionel Sambuc     }
2843*0a6a1f1dSLionel Sambuc     Heading += ")";
2844*0a6a1f1dSLionel Sambuc   }
2845*0a6a1f1dSLionel Sambuc   OS << Heading << "\n" << std::string(Heading.length(), '-') << "\n";
2846*0a6a1f1dSLionel Sambuc 
2847*0a6a1f1dSLionel Sambuc   if (!SupportedSpellings)
2848*0a6a1f1dSLionel Sambuc     PrintFatalError(Doc.Attribute->getLoc(),
2849*0a6a1f1dSLionel Sambuc                     "Attribute has no supported spellings; cannot be "
2850*0a6a1f1dSLionel Sambuc                     "documented");
2851*0a6a1f1dSLionel Sambuc 
2852*0a6a1f1dSLionel Sambuc   // List what spelling syntaxes the attribute supports.
2853*0a6a1f1dSLionel Sambuc   OS << ".. csv-table:: Supported Syntaxes\n";
2854*0a6a1f1dSLionel Sambuc   OS << "   :header: \"GNU\", \"C++11\", \"__declspec\", \"Keyword\",";
2855*0a6a1f1dSLionel Sambuc   OS << " \"Pragma\"\n\n";
2856*0a6a1f1dSLionel Sambuc   OS << "   \"";
2857*0a6a1f1dSLionel Sambuc   if (SupportedSpellings & GNU) OS << "X";
2858*0a6a1f1dSLionel Sambuc   OS << "\",\"";
2859*0a6a1f1dSLionel Sambuc   if (SupportedSpellings & CXX11) OS << "X";
2860*0a6a1f1dSLionel Sambuc   OS << "\",\"";
2861*0a6a1f1dSLionel Sambuc   if (SupportedSpellings & Declspec) OS << "X";
2862*0a6a1f1dSLionel Sambuc   OS << "\",\"";
2863*0a6a1f1dSLionel Sambuc   if (SupportedSpellings & Keyword) OS << "X";
2864*0a6a1f1dSLionel Sambuc   OS << "\", \"";
2865*0a6a1f1dSLionel Sambuc   if (SupportedSpellings & Pragma) OS << "X";
2866*0a6a1f1dSLionel Sambuc   OS << "\"\n\n";
2867*0a6a1f1dSLionel Sambuc 
2868*0a6a1f1dSLionel Sambuc   // If the attribute is deprecated, print a message about it, and possibly
2869*0a6a1f1dSLionel Sambuc   // provide a replacement attribute.
2870*0a6a1f1dSLionel Sambuc   if (!Doc.Documentation->isValueUnset("Deprecated")) {
2871*0a6a1f1dSLionel Sambuc     OS << "This attribute has been deprecated, and may be removed in a future "
2872*0a6a1f1dSLionel Sambuc        << "version of Clang.";
2873*0a6a1f1dSLionel Sambuc     const Record &Deprecated = *Doc.Documentation->getValueAsDef("Deprecated");
2874*0a6a1f1dSLionel Sambuc     std::string Replacement = Deprecated.getValueAsString("Replacement");
2875*0a6a1f1dSLionel Sambuc     if (!Replacement.empty())
2876*0a6a1f1dSLionel Sambuc       OS << "  This attribute has been superseded by ``"
2877*0a6a1f1dSLionel Sambuc          << Replacement << "``.";
2878*0a6a1f1dSLionel Sambuc     OS << "\n\n";
2879*0a6a1f1dSLionel Sambuc   }
2880*0a6a1f1dSLionel Sambuc 
2881*0a6a1f1dSLionel Sambuc   std::string ContentStr = Doc.Documentation->getValueAsString("Content");
2882*0a6a1f1dSLionel Sambuc   // Trim leading and trailing newlines and spaces.
2883*0a6a1f1dSLionel Sambuc   StringRef Content(ContentStr);
2884*0a6a1f1dSLionel Sambuc   while (Content.startswith("\r") || Content.startswith("\n") ||
2885*0a6a1f1dSLionel Sambuc          Content.startswith(" ") || Content.startswith("\t"))
2886*0a6a1f1dSLionel Sambuc     Content = Content.substr(1);
2887*0a6a1f1dSLionel Sambuc   while (Content.endswith("\r") || Content.endswith("\n") ||
2888*0a6a1f1dSLionel Sambuc          Content.endswith(" ") || Content.endswith("\t"))
2889*0a6a1f1dSLionel Sambuc     Content = Content.substr(0, Content.size() - 1);
2890*0a6a1f1dSLionel Sambuc   OS << Content;
2891*0a6a1f1dSLionel Sambuc 
2892*0a6a1f1dSLionel Sambuc   OS << "\n\n\n";
2893*0a6a1f1dSLionel Sambuc }
2894*0a6a1f1dSLionel Sambuc 
EmitClangAttrDocs(RecordKeeper & Records,raw_ostream & OS)2895*0a6a1f1dSLionel Sambuc void EmitClangAttrDocs(RecordKeeper &Records, raw_ostream &OS) {
2896*0a6a1f1dSLionel Sambuc   // Get the documentation introduction paragraph.
2897*0a6a1f1dSLionel Sambuc   const Record *Documentation = Records.getDef("GlobalDocumentation");
2898*0a6a1f1dSLionel Sambuc   if (!Documentation) {
2899*0a6a1f1dSLionel Sambuc     PrintFatalError("The Documentation top-level definition is missing, "
2900*0a6a1f1dSLionel Sambuc                     "no documentation will be generated.");
2901*0a6a1f1dSLionel Sambuc     return;
2902*0a6a1f1dSLionel Sambuc   }
2903*0a6a1f1dSLionel Sambuc 
2904*0a6a1f1dSLionel Sambuc   OS << Documentation->getValueAsString("Intro") << "\n";
2905*0a6a1f1dSLionel Sambuc 
2906*0a6a1f1dSLionel Sambuc   // Gather the Documentation lists from each of the attributes, based on the
2907*0a6a1f1dSLionel Sambuc   // category provided.
2908*0a6a1f1dSLionel Sambuc   std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
2909*0a6a1f1dSLionel Sambuc   std::map<const Record *, std::vector<DocumentationData>> SplitDocs;
2910*0a6a1f1dSLionel Sambuc   for (const auto *A : Attrs) {
2911*0a6a1f1dSLionel Sambuc     const Record &Attr = *A;
2912*0a6a1f1dSLionel Sambuc     std::vector<Record *> Docs = Attr.getValueAsListOfDefs("Documentation");
2913*0a6a1f1dSLionel Sambuc     for (const auto *D : Docs) {
2914*0a6a1f1dSLionel Sambuc       const Record &Doc = *D;
2915*0a6a1f1dSLionel Sambuc       const Record *Category = Doc.getValueAsDef("Category");
2916*0a6a1f1dSLionel Sambuc       // If the category is "undocumented", then there cannot be any other
2917*0a6a1f1dSLionel Sambuc       // documentation categories (otherwise, the attribute would become
2918*0a6a1f1dSLionel Sambuc       // documented).
2919*0a6a1f1dSLionel Sambuc       std::string Cat = Category->getValueAsString("Name");
2920*0a6a1f1dSLionel Sambuc       bool Undocumented = Cat == "Undocumented";
2921*0a6a1f1dSLionel Sambuc       if (Undocumented && Docs.size() > 1)
2922*0a6a1f1dSLionel Sambuc         PrintFatalError(Doc.getLoc(),
2923*0a6a1f1dSLionel Sambuc                         "Attribute is \"Undocumented\", but has multiple "
2924*0a6a1f1dSLionel Sambuc                         "documentation categories");
2925*0a6a1f1dSLionel Sambuc 
2926*0a6a1f1dSLionel Sambuc       if (!Undocumented)
2927*0a6a1f1dSLionel Sambuc         SplitDocs[Category].push_back(DocumentationData(Doc, Attr));
2928*0a6a1f1dSLionel Sambuc     }
2929*0a6a1f1dSLionel Sambuc   }
2930*0a6a1f1dSLionel Sambuc 
2931*0a6a1f1dSLionel Sambuc   // Having split the attributes out based on what documentation goes where,
2932*0a6a1f1dSLionel Sambuc   // we can begin to generate sections of documentation.
2933*0a6a1f1dSLionel Sambuc   for (const auto &I : SplitDocs) {
2934*0a6a1f1dSLionel Sambuc     WriteCategoryHeader(I.first, OS);
2935*0a6a1f1dSLionel Sambuc 
2936*0a6a1f1dSLionel Sambuc     // Walk over each of the attributes in the category and write out their
2937*0a6a1f1dSLionel Sambuc     // documentation.
2938*0a6a1f1dSLionel Sambuc     for (const auto &Doc : I.second)
2939*0a6a1f1dSLionel Sambuc       WriteDocumentation(Doc, OS);
2940*0a6a1f1dSLionel Sambuc   }
2941*0a6a1f1dSLionel Sambuc }
2942*0a6a1f1dSLionel Sambuc 
2943f4a2713aSLionel Sambuc } // end namespace clang
2944