1226586Sdim//===- ClangAttrEmitter.cpp - Generate Clang attribute handling =-*- C++ -*--=//
2226586Sdim//
3226586Sdim//                     The LLVM Compiler Infrastructure
4226586Sdim//
5226586Sdim// This file is distributed under the University of Illinois Open Source
6226586Sdim// License. See LICENSE.TXT for details.
7226586Sdim//
8226586Sdim//===----------------------------------------------------------------------===//
9226586Sdim//
10226586Sdim// These tablegen backends emit Clang attribute processing code
11226586Sdim//
12226586Sdim//===----------------------------------------------------------------------===//
13226586Sdim
14245431Sdim#include "llvm/ADT/SmallString.h"
15226586Sdim#include "llvm/ADT/StringSwitch.h"
16263509Sdim#include "llvm/ADT/SmallSet.h"
17226586Sdim#include "llvm/TableGen/Record.h"
18245431Sdim#include "llvm/TableGen/StringMatcher.h"
19245431Sdim#include "llvm/TableGen/TableGenBackend.h"
20226586Sdim#include <algorithm>
21226586Sdim#include <cctype>
22226586Sdim
23226586Sdimusing namespace llvm;
24226586Sdim
25226586Sdimstatic const std::vector<StringRef>
26226586SdimgetValueAsListOfStrings(Record &R, StringRef FieldName) {
27226586Sdim  ListInit *List = R.getValueAsListInit(FieldName);
28226586Sdim  assert (List && "Got a null ListInit");
29226586Sdim
30226586Sdim  std::vector<StringRef> Strings;
31226586Sdim  Strings.reserve(List->getSize());
32226586Sdim
33226586Sdim  for (ListInit::const_iterator i = List->begin(), e = List->end();
34226586Sdim       i != e;
35226586Sdim       ++i) {
36226586Sdim    assert(*i && "Got a null element in a ListInit");
37245431Sdim    if (StringInit *S = dyn_cast<StringInit>(*i))
38226586Sdim      Strings.push_back(S->getValue());
39226586Sdim    else
40226586Sdim      assert(false && "Got a non-string, non-code element in a ListInit");
41226586Sdim  }
42226586Sdim
43226586Sdim  return Strings;
44226586Sdim}
45226586Sdim
46226586Sdimstatic std::string ReadPCHRecord(StringRef type) {
47226586Sdim  return StringSwitch<std::string>(type)
48226586Sdim    .EndsWith("Decl *", "GetLocalDeclAs<"
49226586Sdim              + std::string(type, 0, type.size()-1) + ">(F, Record[Idx++])")
50263509Sdim    .Case("TypeSourceInfo *", "GetTypeSourceInfo(F, Record, Idx)")
51252723Sdim    .Case("Expr *", "ReadExpr(F)")
52226586Sdim    .Case("IdentifierInfo *", "GetIdentifierInfo(F, Record, Idx)")
53226586Sdim    .Case("SourceLocation", "ReadSourceLocation(F, Record, Idx)")
54226586Sdim    .Default("Record[Idx++]");
55226586Sdim}
56226586Sdim
57226586Sdim// Assumes that the way to get the value is SA->getname()
58226586Sdimstatic std::string WritePCHRecord(StringRef type, StringRef name) {
59226586Sdim  return StringSwitch<std::string>(type)
60226586Sdim    .EndsWith("Decl *", "AddDeclRef(" + std::string(name) +
61226586Sdim                        ", Record);\n")
62263509Sdim    .Case("TypeSourceInfo *",
63263509Sdim          "AddTypeSourceInfo(" + std::string(name) + ", Record);\n")
64226586Sdim    .Case("Expr *", "AddStmt(" + std::string(name) + ");\n")
65226586Sdim    .Case("IdentifierInfo *",
66226586Sdim          "AddIdentifierRef(" + std::string(name) + ", Record);\n")
67226586Sdim    .Case("SourceLocation",
68226586Sdim          "AddSourceLocation(" + std::string(name) + ", Record);\n")
69226586Sdim    .Default("Record.push_back(" + std::string(name) + ");\n");
70226586Sdim}
71226586Sdim
72235633Sdim// Normalize attribute name by removing leading and trailing
73235633Sdim// underscores. For example, __foo, foo__, __foo__ would
74235633Sdim// become foo.
75235633Sdimstatic StringRef NormalizeAttrName(StringRef AttrName) {
76235633Sdim  if (AttrName.startswith("__"))
77235633Sdim    AttrName = AttrName.substr(2, AttrName.size());
78235633Sdim
79235633Sdim  if (AttrName.endswith("__"))
80235633Sdim    AttrName = AttrName.substr(0, AttrName.size() - 2);
81235633Sdim
82235633Sdim  return AttrName;
83235633Sdim}
84235633Sdim
85235633Sdim// Normalize attribute spelling only if the spelling has both leading
86235633Sdim// and trailing underscores. For example, __ms_struct__ will be
87235633Sdim// normalized to "ms_struct"; __cdecl will remain intact.
88235633Sdimstatic StringRef NormalizeAttrSpelling(StringRef AttrSpelling) {
89235633Sdim  if (AttrSpelling.startswith("__") && AttrSpelling.endswith("__")) {
90235633Sdim    AttrSpelling = AttrSpelling.substr(2, AttrSpelling.size() - 4);
91235633Sdim  }
92235633Sdim
93235633Sdim  return AttrSpelling;
94235633Sdim}
95235633Sdim
96226586Sdimnamespace {
97226586Sdim  class Argument {
98226586Sdim    std::string lowerName, upperName;
99226586Sdim    StringRef attrName;
100263509Sdim    bool isOpt;
101226586Sdim
102226586Sdim  public:
103226586Sdim    Argument(Record &Arg, StringRef Attr)
104226586Sdim      : lowerName(Arg.getValueAsString("Name")), upperName(lowerName),
105263509Sdim        attrName(Attr), isOpt(false) {
106226586Sdim      if (!lowerName.empty()) {
107226586Sdim        lowerName[0] = std::tolower(lowerName[0]);
108226586Sdim        upperName[0] = std::toupper(upperName[0]);
109226586Sdim      }
110226586Sdim    }
111226586Sdim    virtual ~Argument() {}
112226586Sdim
113226586Sdim    StringRef getLowerName() const { return lowerName; }
114226586Sdim    StringRef getUpperName() const { return upperName; }
115226586Sdim    StringRef getAttrName() const { return attrName; }
116226586Sdim
117263509Sdim    bool isOptional() const { return isOpt; }
118263509Sdim    void setOptional(bool set) { isOpt = set; }
119263509Sdim
120226586Sdim    // These functions print the argument contents formatted in different ways.
121226586Sdim    virtual void writeAccessors(raw_ostream &OS) const = 0;
122226586Sdim    virtual void writeAccessorDefinitions(raw_ostream &OS) const {}
123226586Sdim    virtual void writeCloneArgs(raw_ostream &OS) const = 0;
124235633Sdim    virtual void writeTemplateInstantiationArgs(raw_ostream &OS) const = 0;
125235633Sdim    virtual void writeTemplateInstantiation(raw_ostream &OS) const {}
126226586Sdim    virtual void writeCtorBody(raw_ostream &OS) const {}
127226586Sdim    virtual void writeCtorInitializers(raw_ostream &OS) const = 0;
128263509Sdim    virtual void writeCtorDefaultInitializers(raw_ostream &OS) const = 0;
129226586Sdim    virtual void writeCtorParameters(raw_ostream &OS) const = 0;
130226586Sdim    virtual void writeDeclarations(raw_ostream &OS) const = 0;
131226586Sdim    virtual void writePCHReadArgs(raw_ostream &OS) const = 0;
132226586Sdim    virtual void writePCHReadDecls(raw_ostream &OS) const = 0;
133226586Sdim    virtual void writePCHWrite(raw_ostream &OS) const = 0;
134235633Sdim    virtual void writeValue(raw_ostream &OS) const = 0;
135252723Sdim    virtual void writeDump(raw_ostream &OS) const = 0;
136252723Sdim    virtual void writeDumpChildren(raw_ostream &OS) const {}
137252723Sdim    virtual void writeHasChildren(raw_ostream &OS) const { OS << "false"; }
138263509Sdim
139263509Sdim    virtual bool isEnumArg() const { return false; }
140263509Sdim    virtual bool isVariadicEnumArg() const { return false; }
141226586Sdim  };
142226586Sdim
143226586Sdim  class SimpleArgument : public Argument {
144226586Sdim    std::string type;
145226586Sdim
146226586Sdim  public:
147226586Sdim    SimpleArgument(Record &Arg, StringRef Attr, std::string T)
148226586Sdim      : Argument(Arg, Attr), type(T)
149226586Sdim    {}
150226586Sdim
151235633Sdim    std::string getType() const { return type; }
152235633Sdim
153226586Sdim    void writeAccessors(raw_ostream &OS) const {
154226586Sdim      OS << "  " << type << " get" << getUpperName() << "() const {\n";
155226586Sdim      OS << "    return " << getLowerName() << ";\n";
156226586Sdim      OS << "  }";
157226586Sdim    }
158226586Sdim    void writeCloneArgs(raw_ostream &OS) const {
159226586Sdim      OS << getLowerName();
160226586Sdim    }
161235633Sdim    void writeTemplateInstantiationArgs(raw_ostream &OS) const {
162235633Sdim      OS << "A->get" << getUpperName() << "()";
163235633Sdim    }
164226586Sdim    void writeCtorInitializers(raw_ostream &OS) const {
165226586Sdim      OS << getLowerName() << "(" << getUpperName() << ")";
166226586Sdim    }
167263509Sdim    void writeCtorDefaultInitializers(raw_ostream &OS) const {
168263509Sdim      OS << getLowerName() << "()";
169263509Sdim    }
170226586Sdim    void writeCtorParameters(raw_ostream &OS) const {
171226586Sdim      OS << type << " " << getUpperName();
172226586Sdim    }
173226586Sdim    void writeDeclarations(raw_ostream &OS) const {
174226586Sdim      OS << type << " " << getLowerName() << ";";
175226586Sdim    }
176226586Sdim    void writePCHReadDecls(raw_ostream &OS) const {
177226586Sdim      std::string read = ReadPCHRecord(type);
178226586Sdim      OS << "    " << type << " " << getLowerName() << " = " << read << ";\n";
179226586Sdim    }
180226586Sdim    void writePCHReadArgs(raw_ostream &OS) const {
181226586Sdim      OS << getLowerName();
182226586Sdim    }
183226586Sdim    void writePCHWrite(raw_ostream &OS) const {
184226586Sdim      OS << "    " << WritePCHRecord(type, "SA->get" +
185226586Sdim                                           std::string(getUpperName()) + "()");
186226586Sdim    }
187235633Sdim    void writeValue(raw_ostream &OS) const {
188235633Sdim      if (type == "FunctionDecl *") {
189263509Sdim        OS << "\" << get" << getUpperName()
190263509Sdim           << "()->getNameInfo().getAsString() << \"";
191235633Sdim      } else if (type == "IdentifierInfo *") {
192235633Sdim        OS << "\" << get" << getUpperName() << "()->getName() << \"";
193263509Sdim      } else if (type == "TypeSourceInfo *") {
194235633Sdim        OS << "\" << get" << getUpperName() << "().getAsString() << \"";
195235633Sdim      } else if (type == "SourceLocation") {
196235633Sdim        OS << "\" << get" << getUpperName() << "().getRawEncoding() << \"";
197235633Sdim      } else {
198235633Sdim        OS << "\" << get" << getUpperName() << "() << \"";
199235633Sdim      }
200235633Sdim    }
201252723Sdim    void writeDump(raw_ostream &OS) const {
202252723Sdim      if (type == "FunctionDecl *") {
203252723Sdim        OS << "    OS << \" \";\n";
204252723Sdim        OS << "    dumpBareDeclRef(SA->get" << getUpperName() << "());\n";
205252723Sdim      } else if (type == "IdentifierInfo *") {
206252723Sdim        OS << "    OS << \" \" << SA->get" << getUpperName()
207252723Sdim           << "()->getName();\n";
208263509Sdim      } else if (type == "TypeSourceInfo *") {
209252723Sdim        OS << "    OS << \" \" << SA->get" << getUpperName()
210252723Sdim           << "().getAsString();\n";
211252723Sdim      } else if (type == "SourceLocation") {
212252723Sdim        OS << "    OS << \" \";\n";
213252723Sdim        OS << "    SA->get" << getUpperName() << "().print(OS, *SM);\n";
214252723Sdim      } else if (type == "bool") {
215252723Sdim        OS << "    if (SA->get" << getUpperName() << "()) OS << \" "
216252723Sdim           << getUpperName() << "\";\n";
217252723Sdim      } else if (type == "int" || type == "unsigned") {
218252723Sdim        OS << "    OS << \" \" << SA->get" << getUpperName() << "();\n";
219252723Sdim      } else {
220252723Sdim        llvm_unreachable("Unknown SimpleArgument type!");
221252723Sdim      }
222252723Sdim    }
223226586Sdim  };
224226586Sdim
225226586Sdim  class StringArgument : public Argument {
226226586Sdim  public:
227226586Sdim    StringArgument(Record &Arg, StringRef Attr)
228226586Sdim      : Argument(Arg, Attr)
229226586Sdim    {}
230226586Sdim
231226586Sdim    void writeAccessors(raw_ostream &OS) const {
232226586Sdim      OS << "  llvm::StringRef get" << getUpperName() << "() const {\n";
233226586Sdim      OS << "    return llvm::StringRef(" << getLowerName() << ", "
234226586Sdim         << getLowerName() << "Length);\n";
235226586Sdim      OS << "  }\n";
236226586Sdim      OS << "  unsigned get" << getUpperName() << "Length() const {\n";
237226586Sdim      OS << "    return " << getLowerName() << "Length;\n";
238226586Sdim      OS << "  }\n";
239226586Sdim      OS << "  void set" << getUpperName()
240226586Sdim         << "(ASTContext &C, llvm::StringRef S) {\n";
241226586Sdim      OS << "    " << getLowerName() << "Length = S.size();\n";
242226586Sdim      OS << "    this->" << getLowerName() << " = new (C, 1) char ["
243226586Sdim         << getLowerName() << "Length];\n";
244226586Sdim      OS << "    std::memcpy(this->" << getLowerName() << ", S.data(), "
245226586Sdim         << getLowerName() << "Length);\n";
246226586Sdim      OS << "  }";
247226586Sdim    }
248226586Sdim    void writeCloneArgs(raw_ostream &OS) const {
249226586Sdim      OS << "get" << getUpperName() << "()";
250226586Sdim    }
251235633Sdim    void writeTemplateInstantiationArgs(raw_ostream &OS) const {
252235633Sdim      OS << "A->get" << getUpperName() << "()";
253235633Sdim    }
254226586Sdim    void writeCtorBody(raw_ostream &OS) const {
255226586Sdim      OS << "      std::memcpy(" << getLowerName() << ", " << getUpperName()
256226586Sdim         << ".data(), " << getLowerName() << "Length);";
257226586Sdim    }
258226586Sdim    void writeCtorInitializers(raw_ostream &OS) const {
259226586Sdim      OS << getLowerName() << "Length(" << getUpperName() << ".size()),"
260226586Sdim         << getLowerName() << "(new (Ctx, 1) char[" << getLowerName()
261226586Sdim         << "Length])";
262226586Sdim    }
263263509Sdim    void writeCtorDefaultInitializers(raw_ostream &OS) const {
264263509Sdim      OS << getLowerName() << "Length(0)," << getLowerName() << "(0)";
265263509Sdim    }
266226586Sdim    void writeCtorParameters(raw_ostream &OS) const {
267226586Sdim      OS << "llvm::StringRef " << getUpperName();
268226586Sdim    }
269226586Sdim    void writeDeclarations(raw_ostream &OS) const {
270226586Sdim      OS << "unsigned " << getLowerName() << "Length;\n";
271226586Sdim      OS << "char *" << getLowerName() << ";";
272226586Sdim    }
273226586Sdim    void writePCHReadDecls(raw_ostream &OS) const {
274226586Sdim      OS << "    std::string " << getLowerName()
275226586Sdim         << "= ReadString(Record, Idx);\n";
276226586Sdim    }
277226586Sdim    void writePCHReadArgs(raw_ostream &OS) const {
278226586Sdim      OS << getLowerName();
279226586Sdim    }
280226586Sdim    void writePCHWrite(raw_ostream &OS) const {
281226586Sdim      OS << "    AddString(SA->get" << getUpperName() << "(), Record);\n";
282226586Sdim    }
283235633Sdim    void writeValue(raw_ostream &OS) const {
284235633Sdim      OS << "\\\"\" << get" << getUpperName() << "() << \"\\\"";
285235633Sdim    }
286252723Sdim    void writeDump(raw_ostream &OS) const {
287252723Sdim      OS << "    OS << \" \\\"\" << SA->get" << getUpperName()
288252723Sdim         << "() << \"\\\"\";\n";
289252723Sdim    }
290226586Sdim  };
291226586Sdim
292226586Sdim  class AlignedArgument : public Argument {
293226586Sdim  public:
294226586Sdim    AlignedArgument(Record &Arg, StringRef Attr)
295226586Sdim      : Argument(Arg, Attr)
296226586Sdim    {}
297226586Sdim
298226586Sdim    void writeAccessors(raw_ostream &OS) const {
299226586Sdim      OS << "  bool is" << getUpperName() << "Dependent() const;\n";
300226586Sdim
301226586Sdim      OS << "  unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n";
302226586Sdim
303226586Sdim      OS << "  bool is" << getUpperName() << "Expr() const {\n";
304226586Sdim      OS << "    return is" << getLowerName() << "Expr;\n";
305226586Sdim      OS << "  }\n";
306226586Sdim
307226586Sdim      OS << "  Expr *get" << getUpperName() << "Expr() const {\n";
308226586Sdim      OS << "    assert(is" << getLowerName() << "Expr);\n";
309226586Sdim      OS << "    return " << getLowerName() << "Expr;\n";
310226586Sdim      OS << "  }\n";
311226586Sdim
312226586Sdim      OS << "  TypeSourceInfo *get" << getUpperName() << "Type() const {\n";
313226586Sdim      OS << "    assert(!is" << getLowerName() << "Expr);\n";
314226586Sdim      OS << "    return " << getLowerName() << "Type;\n";
315226586Sdim      OS << "  }";
316226586Sdim    }
317226586Sdim    void writeAccessorDefinitions(raw_ostream &OS) const {
318226586Sdim      OS << "bool " << getAttrName() << "Attr::is" << getUpperName()
319226586Sdim         << "Dependent() const {\n";
320226586Sdim      OS << "  if (is" << getLowerName() << "Expr)\n";
321226586Sdim      OS << "    return " << getLowerName() << "Expr && (" << getLowerName()
322226586Sdim         << "Expr->isValueDependent() || " << getLowerName()
323226586Sdim         << "Expr->isTypeDependent());\n";
324226586Sdim      OS << "  else\n";
325226586Sdim      OS << "    return " << getLowerName()
326226586Sdim         << "Type->getType()->isDependentType();\n";
327226586Sdim      OS << "}\n";
328226586Sdim
329226586Sdim      // FIXME: Do not do the calculation here
330226586Sdim      // FIXME: Handle types correctly
331226586Sdim      // A null pointer means maximum alignment
332226586Sdim      // FIXME: Load the platform-specific maximum alignment, rather than
333226586Sdim      //        16, the x86 max.
334226586Sdim      OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName()
335226586Sdim         << "(ASTContext &Ctx) const {\n";
336226586Sdim      OS << "  assert(!is" << getUpperName() << "Dependent());\n";
337226586Sdim      OS << "  if (is" << getLowerName() << "Expr)\n";
338226586Sdim      OS << "    return (" << getLowerName() << "Expr ? " << getLowerName()
339226586Sdim         << "Expr->EvaluateKnownConstInt(Ctx).getZExtValue() : 16)"
340226586Sdim         << "* Ctx.getCharWidth();\n";
341226586Sdim      OS << "  else\n";
342226586Sdim      OS << "    return 0; // FIXME\n";
343226586Sdim      OS << "}\n";
344226586Sdim    }
345226586Sdim    void writeCloneArgs(raw_ostream &OS) const {
346226586Sdim      OS << "is" << getLowerName() << "Expr, is" << getLowerName()
347226586Sdim         << "Expr ? static_cast<void*>(" << getLowerName()
348226586Sdim         << "Expr) : " << getLowerName()
349226586Sdim         << "Type";
350226586Sdim    }
351235633Sdim    void writeTemplateInstantiationArgs(raw_ostream &OS) const {
352235633Sdim      // FIXME: move the definition in Sema::InstantiateAttrs to here.
353235633Sdim      // In the meantime, aligned attributes are cloned.
354235633Sdim    }
355226586Sdim    void writeCtorBody(raw_ostream &OS) const {
356226586Sdim      OS << "    if (is" << getLowerName() << "Expr)\n";
357226586Sdim      OS << "       " << getLowerName() << "Expr = reinterpret_cast<Expr *>("
358226586Sdim         << getUpperName() << ");\n";
359226586Sdim      OS << "    else\n";
360226586Sdim      OS << "       " << getLowerName()
361226586Sdim         << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName()
362226586Sdim         << ");";
363226586Sdim    }
364226586Sdim    void writeCtorInitializers(raw_ostream &OS) const {
365226586Sdim      OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)";
366226586Sdim    }
367263509Sdim    void writeCtorDefaultInitializers(raw_ostream &OS) const {
368263509Sdim      OS << "is" << getLowerName() << "Expr(false)";
369263509Sdim    }
370226586Sdim    void writeCtorParameters(raw_ostream &OS) const {
371226586Sdim      OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName();
372226586Sdim    }
373226586Sdim    void writeDeclarations(raw_ostream &OS) const {
374226586Sdim      OS << "bool is" << getLowerName() << "Expr;\n";
375226586Sdim      OS << "union {\n";
376226586Sdim      OS << "Expr *" << getLowerName() << "Expr;\n";
377226586Sdim      OS << "TypeSourceInfo *" << getLowerName() << "Type;\n";
378226586Sdim      OS << "};";
379226586Sdim    }
380226586Sdim    void writePCHReadArgs(raw_ostream &OS) const {
381226586Sdim      OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr";
382226586Sdim    }
383226586Sdim    void writePCHReadDecls(raw_ostream &OS) const {
384226586Sdim      OS << "    bool is" << getLowerName() << "Expr = Record[Idx++];\n";
385226586Sdim      OS << "    void *" << getLowerName() << "Ptr;\n";
386226586Sdim      OS << "    if (is" << getLowerName() << "Expr)\n";
387226586Sdim      OS << "      " << getLowerName() << "Ptr = ReadExpr(F);\n";
388226586Sdim      OS << "    else\n";
389226586Sdim      OS << "      " << getLowerName()
390226586Sdim         << "Ptr = GetTypeSourceInfo(F, Record, Idx);\n";
391226586Sdim    }
392226586Sdim    void writePCHWrite(raw_ostream &OS) const {
393226586Sdim      OS << "    Record.push_back(SA->is" << getUpperName() << "Expr());\n";
394226586Sdim      OS << "    if (SA->is" << getUpperName() << "Expr())\n";
395226586Sdim      OS << "      AddStmt(SA->get" << getUpperName() << "Expr());\n";
396226586Sdim      OS << "    else\n";
397226586Sdim      OS << "      AddTypeSourceInfo(SA->get" << getUpperName()
398226586Sdim         << "Type(), Record);\n";
399226586Sdim    }
400235633Sdim    void writeValue(raw_ostream &OS) const {
401245431Sdim      OS << "\";\n"
402245431Sdim         << "  " << getLowerName() << "Expr->printPretty(OS, 0, Policy);\n"
403245431Sdim         << "  OS << \"";
404235633Sdim    }
405252723Sdim    void writeDump(raw_ostream &OS) const {
406252723Sdim    }
407252723Sdim    void writeDumpChildren(raw_ostream &OS) const {
408252723Sdim      OS << "    if (SA->is" << getUpperName() << "Expr()) {\n";
409252723Sdim      OS << "      lastChild();\n";
410252723Sdim      OS << "      dumpStmt(SA->get" << getUpperName() << "Expr());\n";
411252723Sdim      OS << "    } else\n";
412252723Sdim      OS << "      dumpType(SA->get" << getUpperName()
413252723Sdim         << "Type()->getType());\n";
414252723Sdim    }
415252723Sdim    void writeHasChildren(raw_ostream &OS) const {
416252723Sdim      OS << "SA->is" << getUpperName() << "Expr()";
417252723Sdim    }
418226586Sdim  };
419226586Sdim
420226586Sdim  class VariadicArgument : public Argument {
421226586Sdim    std::string type;
422226586Sdim
423226586Sdim  public:
424226586Sdim    VariadicArgument(Record &Arg, StringRef Attr, std::string T)
425226586Sdim      : Argument(Arg, Attr), type(T)
426226586Sdim    {}
427226586Sdim
428226586Sdim    std::string getType() const { return type; }
429226586Sdim
430226586Sdim    void writeAccessors(raw_ostream &OS) const {
431226586Sdim      OS << "  typedef " << type << "* " << getLowerName() << "_iterator;\n";
432226586Sdim      OS << "  " << getLowerName() << "_iterator " << getLowerName()
433226586Sdim         << "_begin() const {\n";
434226586Sdim      OS << "    return " << getLowerName() << ";\n";
435226586Sdim      OS << "  }\n";
436226586Sdim      OS << "  " << getLowerName() << "_iterator " << getLowerName()
437226586Sdim         << "_end() const {\n";
438226586Sdim      OS << "    return " << getLowerName() << " + " << getLowerName()
439226586Sdim         << "Size;\n";
440226586Sdim      OS << "  }\n";
441226586Sdim      OS << "  unsigned " << getLowerName() << "_size() const {\n"
442235633Sdim         << "    return " << getLowerName() << "Size;\n";
443226586Sdim      OS << "  }";
444226586Sdim    }
445226586Sdim    void writeCloneArgs(raw_ostream &OS) const {
446226586Sdim      OS << getLowerName() << ", " << getLowerName() << "Size";
447226586Sdim    }
448235633Sdim    void writeTemplateInstantiationArgs(raw_ostream &OS) const {
449235633Sdim      // This isn't elegant, but we have to go through public methods...
450235633Sdim      OS << "A->" << getLowerName() << "_begin(), "
451235633Sdim         << "A->" << getLowerName() << "_size()";
452235633Sdim    }
453226586Sdim    void writeCtorBody(raw_ostream &OS) const {
454226586Sdim      // FIXME: memcpy is not safe on non-trivial types.
455226586Sdim      OS << "    std::memcpy(" << getLowerName() << ", " << getUpperName()
456226586Sdim         << ", " << getLowerName() << "Size * sizeof(" << getType() << "));\n";
457226586Sdim    }
458226586Sdim    void writeCtorInitializers(raw_ostream &OS) const {
459226586Sdim      OS << getLowerName() << "Size(" << getUpperName() << "Size), "
460226586Sdim         << getLowerName() << "(new (Ctx, 16) " << getType() << "["
461226586Sdim         << getLowerName() << "Size])";
462226586Sdim    }
463263509Sdim    void writeCtorDefaultInitializers(raw_ostream &OS) const {
464263509Sdim      OS << getLowerName() << "Size(0), " << getLowerName() << "(0)";
465263509Sdim    }
466226586Sdim    void writeCtorParameters(raw_ostream &OS) const {
467226586Sdim      OS << getType() << " *" << getUpperName() << ", unsigned "
468226586Sdim         << getUpperName() << "Size";
469226586Sdim    }
470226586Sdim    void writeDeclarations(raw_ostream &OS) const {
471226586Sdim      OS << "  unsigned " << getLowerName() << "Size;\n";
472226586Sdim      OS << "  " << getType() << " *" << getLowerName() << ";";
473226586Sdim    }
474226586Sdim    void writePCHReadDecls(raw_ostream &OS) const {
475226586Sdim      OS << "  unsigned " << getLowerName() << "Size = Record[Idx++];\n";
476252723Sdim      OS << "  SmallVector<" << type << ", 4> " << getLowerName()
477226586Sdim         << ";\n";
478226586Sdim      OS << "  " << getLowerName() << ".reserve(" << getLowerName()
479226586Sdim         << "Size);\n";
480263509Sdim      OS << "    for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
481226586Sdim
482226586Sdim      std::string read = ReadPCHRecord(type);
483226586Sdim      OS << "    " << getLowerName() << ".push_back(" << read << ");\n";
484226586Sdim    }
485226586Sdim    void writePCHReadArgs(raw_ostream &OS) const {
486226586Sdim      OS << getLowerName() << ".data(), " << getLowerName() << "Size";
487226586Sdim    }
488226586Sdim    void writePCHWrite(raw_ostream &OS) const{
489226586Sdim      OS << "    Record.push_back(SA->" << getLowerName() << "_size());\n";
490226586Sdim      OS << "    for (" << getAttrName() << "Attr::" << getLowerName()
491226586Sdim         << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
492226586Sdim         << getLowerName() << "_end(); i != e; ++i)\n";
493226586Sdim      OS << "      " << WritePCHRecord(type, "(*i)");
494226586Sdim    }
495235633Sdim    void writeValue(raw_ostream &OS) const {
496235633Sdim      OS << "\";\n";
497235633Sdim      OS << "  bool isFirst = true;\n"
498235633Sdim         << "  for (" << getAttrName() << "Attr::" << getLowerName()
499235633Sdim         << "_iterator i = " << getLowerName() << "_begin(), e = "
500235633Sdim         << getLowerName() << "_end(); i != e; ++i) {\n"
501235633Sdim         << "    if (isFirst) isFirst = false;\n"
502235633Sdim         << "    else OS << \", \";\n"
503235633Sdim         << "    OS << *i;\n"
504235633Sdim         << "  }\n";
505235633Sdim      OS << "  OS << \"";
506235633Sdim    }
507252723Sdim    void writeDump(raw_ostream &OS) const {
508252723Sdim      OS << "    for (" << getAttrName() << "Attr::" << getLowerName()
509252723Sdim         << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
510252723Sdim         << getLowerName() << "_end(); I != E; ++I)\n";
511252723Sdim      OS << "      OS << \" \" << *I;\n";
512252723Sdim    }
513226586Sdim  };
514226586Sdim
515226586Sdim  class EnumArgument : public Argument {
516226586Sdim    std::string type;
517252723Sdim    std::vector<StringRef> values, enums, uniques;
518226586Sdim  public:
519226586Sdim    EnumArgument(Record &Arg, StringRef Attr)
520226586Sdim      : Argument(Arg, Attr), type(Arg.getValueAsString("Type")),
521226586Sdim        values(getValueAsListOfStrings(Arg, "Values")),
522252723Sdim        enums(getValueAsListOfStrings(Arg, "Enums")),
523252723Sdim        uniques(enums)
524252723Sdim    {
525252723Sdim      // Calculate the various enum values
526252723Sdim      std::sort(uniques.begin(), uniques.end());
527252723Sdim      uniques.erase(std::unique(uniques.begin(), uniques.end()), uniques.end());
528252723Sdim      // FIXME: Emit a proper error
529252723Sdim      assert(!uniques.empty());
530252723Sdim    }
531226586Sdim
532263509Sdim    bool isEnumArg() const { return true; }
533263509Sdim
534226586Sdim    void writeAccessors(raw_ostream &OS) const {
535226586Sdim      OS << "  " << type << " get" << getUpperName() << "() const {\n";
536226586Sdim      OS << "    return " << getLowerName() << ";\n";
537226586Sdim      OS << "  }";
538226586Sdim    }
539226586Sdim    void writeCloneArgs(raw_ostream &OS) const {
540226586Sdim      OS << getLowerName();
541226586Sdim    }
542235633Sdim    void writeTemplateInstantiationArgs(raw_ostream &OS) const {
543235633Sdim      OS << "A->get" << getUpperName() << "()";
544235633Sdim    }
545226586Sdim    void writeCtorInitializers(raw_ostream &OS) const {
546226586Sdim      OS << getLowerName() << "(" << getUpperName() << ")";
547226586Sdim    }
548263509Sdim    void writeCtorDefaultInitializers(raw_ostream &OS) const {
549263509Sdim      OS << getLowerName() << "(" << type << "(0))";
550263509Sdim    }
551226586Sdim    void writeCtorParameters(raw_ostream &OS) const {
552226586Sdim      OS << type << " " << getUpperName();
553226586Sdim    }
554226586Sdim    void writeDeclarations(raw_ostream &OS) const {
555252723Sdim      std::vector<StringRef>::const_iterator i = uniques.begin(),
556252723Sdim                                             e = uniques.end();
557226586Sdim      // The last one needs to not have a comma.
558226586Sdim      --e;
559226586Sdim
560226586Sdim      OS << "public:\n";
561226586Sdim      OS << "  enum " << type << " {\n";
562226586Sdim      for (; i != e; ++i)
563226586Sdim        OS << "    " << *i << ",\n";
564226586Sdim      OS << "    " << *e << "\n";
565226586Sdim      OS << "  };\n";
566226586Sdim      OS << "private:\n";
567226586Sdim      OS << "  " << type << " " << getLowerName() << ";";
568226586Sdim    }
569226586Sdim    void writePCHReadDecls(raw_ostream &OS) const {
570226586Sdim      OS << "    " << getAttrName() << "Attr::" << type << " " << getLowerName()
571226586Sdim         << "(static_cast<" << getAttrName() << "Attr::" << type
572226586Sdim         << ">(Record[Idx++]));\n";
573226586Sdim    }
574226586Sdim    void writePCHReadArgs(raw_ostream &OS) const {
575226586Sdim      OS << getLowerName();
576226586Sdim    }
577226586Sdim    void writePCHWrite(raw_ostream &OS) const {
578226586Sdim      OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
579226586Sdim    }
580235633Sdim    void writeValue(raw_ostream &OS) const {
581235633Sdim      OS << "\" << get" << getUpperName() << "() << \"";
582235633Sdim    }
583252723Sdim    void writeDump(raw_ostream &OS) const {
584252723Sdim      OS << "    switch(SA->get" << getUpperName() << "()) {\n";
585252723Sdim      for (std::vector<StringRef>::const_iterator I = uniques.begin(),
586252723Sdim           E = uniques.end(); I != E; ++I) {
587252723Sdim        OS << "    case " << getAttrName() << "Attr::" << *I << ":\n";
588252723Sdim        OS << "      OS << \" " << *I << "\";\n";
589252723Sdim        OS << "      break;\n";
590252723Sdim      }
591252723Sdim      OS << "    }\n";
592252723Sdim    }
593263509Sdim
594263509Sdim    void writeConversion(raw_ostream &OS) const {
595263509Sdim      OS << "  static bool ConvertStrTo" << type << "(StringRef Val, ";
596263509Sdim      OS << type << " &Out) {\n";
597263509Sdim      OS << "    Optional<" << type << "> R = llvm::StringSwitch<Optional<";
598263509Sdim      OS << type << "> >(Val)\n";
599263509Sdim      for (size_t I = 0; I < enums.size(); ++I) {
600263509Sdim        OS << "      .Case(\"" << values[I] << "\", ";
601263509Sdim        OS << getAttrName() << "Attr::" << enums[I] << ")\n";
602263509Sdim      }
603263509Sdim      OS << "      .Default(Optional<" << type << ">());\n";
604263509Sdim      OS << "    if (R) {\n";
605263509Sdim      OS << "      Out = *R;\n      return true;\n    }\n";
606263509Sdim      OS << "    return false;\n";
607263509Sdim      OS << "  }\n";
608263509Sdim    }
609226586Sdim  };
610263509Sdim
611263509Sdim  class VariadicEnumArgument: public VariadicArgument {
612263509Sdim    std::string type, QualifiedTypeName;
613263509Sdim    std::vector<StringRef> values, enums, uniques;
614263509Sdim  public:
615263509Sdim    VariadicEnumArgument(Record &Arg, StringRef Attr)
616263509Sdim      : VariadicArgument(Arg, Attr, Arg.getValueAsString("Type")),
617263509Sdim        type(Arg.getValueAsString("Type")),
618263509Sdim        values(getValueAsListOfStrings(Arg, "Values")),
619263509Sdim        enums(getValueAsListOfStrings(Arg, "Enums")),
620263509Sdim        uniques(enums)
621263509Sdim    {
622263509Sdim      // Calculate the various enum values
623263509Sdim      std::sort(uniques.begin(), uniques.end());
624263509Sdim      uniques.erase(std::unique(uniques.begin(), uniques.end()), uniques.end());
625263509Sdim
626263509Sdim      QualifiedTypeName = getAttrName().str() + "Attr::" + type;
627263509Sdim
628263509Sdim      // FIXME: Emit a proper error
629263509Sdim      assert(!uniques.empty());
630263509Sdim    }
631226586Sdim
632263509Sdim    bool isVariadicEnumArg() const { return true; }
633263509Sdim
634263509Sdim    void writeDeclarations(raw_ostream &OS) const {
635263509Sdim      std::vector<StringRef>::const_iterator i = uniques.begin(),
636263509Sdim                                             e = uniques.end();
637263509Sdim      // The last one needs to not have a comma.
638263509Sdim      --e;
639263509Sdim
640263509Sdim      OS << "public:\n";
641263509Sdim      OS << "  enum " << type << " {\n";
642263509Sdim      for (; i != e; ++i)
643263509Sdim        OS << "    " << *i << ",\n";
644263509Sdim      OS << "    " << *e << "\n";
645263509Sdim      OS << "  };\n";
646263509Sdim      OS << "private:\n";
647263509Sdim
648263509Sdim      VariadicArgument::writeDeclarations(OS);
649263509Sdim    }
650263509Sdim    void writeDump(raw_ostream &OS) const {
651263509Sdim      OS << "    for (" << getAttrName() << "Attr::" << getLowerName()
652263509Sdim         << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
653263509Sdim         << getLowerName() << "_end(); I != E; ++I) {\n";
654263509Sdim      OS << "      switch(*I) {\n";
655263509Sdim      for (std::vector<StringRef>::const_iterator UI = uniques.begin(),
656263509Sdim           UE = uniques.end(); UI != UE; ++UI) {
657263509Sdim        OS << "    case " << getAttrName() << "Attr::" << *UI << ":\n";
658263509Sdim        OS << "      OS << \" " << *UI << "\";\n";
659263509Sdim        OS << "      break;\n";
660263509Sdim      }
661263509Sdim      OS << "      }\n";
662263509Sdim      OS << "    }\n";
663263509Sdim    }
664263509Sdim    void writePCHReadDecls(raw_ostream &OS) const {
665263509Sdim      OS << "    unsigned " << getLowerName() << "Size = Record[Idx++];\n";
666263509Sdim      OS << "    SmallVector<" << QualifiedTypeName << ", 4> " << getLowerName()
667263509Sdim         << ";\n";
668263509Sdim      OS << "    " << getLowerName() << ".reserve(" << getLowerName()
669263509Sdim         << "Size);\n";
670263509Sdim      OS << "    for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
671263509Sdim      OS << "      " << getLowerName() << ".push_back(" << "static_cast<"
672263509Sdim         << QualifiedTypeName << ">(Record[Idx++]));\n";
673263509Sdim    }
674263509Sdim    void writePCHWrite(raw_ostream &OS) const{
675263509Sdim      OS << "    Record.push_back(SA->" << getLowerName() << "_size());\n";
676263509Sdim      OS << "    for (" << getAttrName() << "Attr::" << getLowerName()
677263509Sdim         << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
678263509Sdim         << getLowerName() << "_end(); i != e; ++i)\n";
679263509Sdim      OS << "      " << WritePCHRecord(QualifiedTypeName, "(*i)");
680263509Sdim    }
681263509Sdim    void writeConversion(raw_ostream &OS) const {
682263509Sdim      OS << "  static bool ConvertStrTo" << type << "(StringRef Val, ";
683263509Sdim      OS << type << " &Out) {\n";
684263509Sdim      OS << "    Optional<" << type << "> R = llvm::StringSwitch<Optional<";
685263509Sdim      OS << type << "> >(Val)\n";
686263509Sdim      for (size_t I = 0; I < enums.size(); ++I) {
687263509Sdim        OS << "      .Case(\"" << values[I] << "\", ";
688263509Sdim        OS << getAttrName() << "Attr::" << enums[I] << ")\n";
689263509Sdim      }
690263509Sdim      OS << "      .Default(Optional<" << type << ">());\n";
691263509Sdim      OS << "    if (R) {\n";
692263509Sdim      OS << "      Out = *R;\n      return true;\n    }\n";
693263509Sdim      OS << "    return false;\n";
694263509Sdim      OS << "  }\n";
695263509Sdim    }
696263509Sdim  };
697263509Sdim
698226586Sdim  class VersionArgument : public Argument {
699226586Sdim  public:
700226586Sdim    VersionArgument(Record &Arg, StringRef Attr)
701226586Sdim      : Argument(Arg, Attr)
702226586Sdim    {}
703226586Sdim
704226586Sdim    void writeAccessors(raw_ostream &OS) const {
705226586Sdim      OS << "  VersionTuple get" << getUpperName() << "() const {\n";
706226586Sdim      OS << "    return " << getLowerName() << ";\n";
707226586Sdim      OS << "  }\n";
708226586Sdim      OS << "  void set" << getUpperName()
709226586Sdim         << "(ASTContext &C, VersionTuple V) {\n";
710226586Sdim      OS << "    " << getLowerName() << " = V;\n";
711226586Sdim      OS << "  }";
712226586Sdim    }
713226586Sdim    void writeCloneArgs(raw_ostream &OS) const {
714226586Sdim      OS << "get" << getUpperName() << "()";
715226586Sdim    }
716235633Sdim    void writeTemplateInstantiationArgs(raw_ostream &OS) const {
717235633Sdim      OS << "A->get" << getUpperName() << "()";
718235633Sdim    }
719226586Sdim    void writeCtorBody(raw_ostream &OS) const {
720226586Sdim    }
721226586Sdim    void writeCtorInitializers(raw_ostream &OS) const {
722226586Sdim      OS << getLowerName() << "(" << getUpperName() << ")";
723226586Sdim    }
724263509Sdim    void writeCtorDefaultInitializers(raw_ostream &OS) const {
725263509Sdim      OS << getLowerName() << "()";
726263509Sdim    }
727226586Sdim    void writeCtorParameters(raw_ostream &OS) const {
728226586Sdim      OS << "VersionTuple " << getUpperName();
729226586Sdim    }
730226586Sdim    void writeDeclarations(raw_ostream &OS) const {
731226586Sdim      OS << "VersionTuple " << getLowerName() << ";\n";
732226586Sdim    }
733226586Sdim    void writePCHReadDecls(raw_ostream &OS) const {
734226586Sdim      OS << "    VersionTuple " << getLowerName()
735226586Sdim         << "= ReadVersionTuple(Record, Idx);\n";
736226586Sdim    }
737226586Sdim    void writePCHReadArgs(raw_ostream &OS) const {
738226586Sdim      OS << getLowerName();
739226586Sdim    }
740226586Sdim    void writePCHWrite(raw_ostream &OS) const {
741226586Sdim      OS << "    AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n";
742226586Sdim    }
743235633Sdim    void writeValue(raw_ostream &OS) const {
744235633Sdim      OS << getLowerName() << "=\" << get" << getUpperName() << "() << \"";
745235633Sdim    }
746252723Sdim    void writeDump(raw_ostream &OS) const {
747252723Sdim      OS << "    OS << \" \" << SA->get" << getUpperName() << "();\n";
748252723Sdim    }
749226586Sdim  };
750235633Sdim
751235633Sdim  class ExprArgument : public SimpleArgument {
752235633Sdim  public:
753235633Sdim    ExprArgument(Record &Arg, StringRef Attr)
754235633Sdim      : SimpleArgument(Arg, Attr, "Expr *")
755235633Sdim    {}
756235633Sdim
757235633Sdim    void writeTemplateInstantiationArgs(raw_ostream &OS) const {
758235633Sdim      OS << "tempInst" << getUpperName();
759235633Sdim    }
760235633Sdim
761235633Sdim    void writeTemplateInstantiation(raw_ostream &OS) const {
762235633Sdim      OS << "      " << getType() << " tempInst" << getUpperName() << ";\n";
763235633Sdim      OS << "      {\n";
764235633Sdim      OS << "        EnterExpressionEvaluationContext "
765235633Sdim         << "Unevaluated(S, Sema::Unevaluated);\n";
766235633Sdim      OS << "        ExprResult " << "Result = S.SubstExpr("
767235633Sdim         << "A->get" << getUpperName() << "(), TemplateArgs);\n";
768235633Sdim      OS << "        tempInst" << getUpperName() << " = "
769235633Sdim         << "Result.takeAs<Expr>();\n";
770235633Sdim      OS << "      }\n";
771235633Sdim    }
772252723Sdim
773252723Sdim    void writeDump(raw_ostream &OS) const {
774252723Sdim    }
775252723Sdim
776252723Sdim    void writeDumpChildren(raw_ostream &OS) const {
777252723Sdim      OS << "    lastChild();\n";
778252723Sdim      OS << "    dumpStmt(SA->get" << getUpperName() << "());\n";
779252723Sdim    }
780252723Sdim    void writeHasChildren(raw_ostream &OS) const { OS << "true"; }
781235633Sdim  };
782235633Sdim
783235633Sdim  class VariadicExprArgument : public VariadicArgument {
784235633Sdim  public:
785235633Sdim    VariadicExprArgument(Record &Arg, StringRef Attr)
786235633Sdim      : VariadicArgument(Arg, Attr, "Expr *")
787235633Sdim    {}
788235633Sdim
789235633Sdim    void writeTemplateInstantiationArgs(raw_ostream &OS) const {
790235633Sdim      OS << "tempInst" << getUpperName() << ", "
791235633Sdim         << "A->" << getLowerName() << "_size()";
792235633Sdim    }
793235633Sdim
794235633Sdim    void writeTemplateInstantiation(raw_ostream &OS) const {
795235633Sdim      OS << "      " << getType() << " *tempInst" << getUpperName()
796235633Sdim         << " = new (C, 16) " << getType()
797235633Sdim         << "[A->" << getLowerName() << "_size()];\n";
798235633Sdim      OS << "      {\n";
799235633Sdim      OS << "        EnterExpressionEvaluationContext "
800235633Sdim         << "Unevaluated(S, Sema::Unevaluated);\n";
801235633Sdim      OS << "        " << getType() << " *TI = tempInst" << getUpperName()
802235633Sdim         << ";\n";
803235633Sdim      OS << "        " << getType() << " *I = A->" << getLowerName()
804235633Sdim         << "_begin();\n";
805235633Sdim      OS << "        " << getType() << " *E = A->" << getLowerName()
806235633Sdim         << "_end();\n";
807235633Sdim      OS << "        for (; I != E; ++I, ++TI) {\n";
808235633Sdim      OS << "          ExprResult Result = S.SubstExpr(*I, TemplateArgs);\n";
809235633Sdim      OS << "          *TI = Result.takeAs<Expr>();\n";
810235633Sdim      OS << "        }\n";
811235633Sdim      OS << "      }\n";
812235633Sdim    }
813252723Sdim
814252723Sdim    void writeDump(raw_ostream &OS) const {
815252723Sdim    }
816252723Sdim
817252723Sdim    void writeDumpChildren(raw_ostream &OS) const {
818252723Sdim      OS << "    for (" << getAttrName() << "Attr::" << getLowerName()
819252723Sdim         << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
820252723Sdim         << getLowerName() << "_end(); I != E; ++I) {\n";
821252723Sdim      OS << "      if (I + 1 == E)\n";
822252723Sdim      OS << "        lastChild();\n";
823252723Sdim      OS << "      dumpStmt(*I);\n";
824252723Sdim      OS << "    }\n";
825252723Sdim    }
826252723Sdim
827252723Sdim    void writeHasChildren(raw_ostream &OS) const {
828252723Sdim      OS << "SA->" << getLowerName() << "_begin() != "
829252723Sdim         << "SA->" << getLowerName() << "_end()";
830252723Sdim    }
831235633Sdim  };
832263509Sdim
833263509Sdim  class TypeArgument : public SimpleArgument {
834263509Sdim  public:
835263509Sdim    TypeArgument(Record &Arg, StringRef Attr)
836263509Sdim      : SimpleArgument(Arg, Attr, "TypeSourceInfo *")
837263509Sdim    {}
838263509Sdim
839263509Sdim    void writeAccessors(raw_ostream &OS) const {
840263509Sdim      OS << "  QualType get" << getUpperName() << "() const {\n";
841263509Sdim      OS << "    return " << getLowerName() << "->getType();\n";
842263509Sdim      OS << "  }";
843263509Sdim      OS << "  " << getType() << " get" << getUpperName() << "Loc() const {\n";
844263509Sdim      OS << "    return " << getLowerName() << ";\n";
845263509Sdim      OS << "  }";
846263509Sdim    }
847263509Sdim    void writeTemplateInstantiationArgs(raw_ostream &OS) const {
848263509Sdim      OS << "A->get" << getUpperName() << "Loc()";
849263509Sdim    }
850263509Sdim    void writePCHWrite(raw_ostream &OS) const {
851263509Sdim      OS << "    " << WritePCHRecord(
852263509Sdim          getType(), "SA->get" + std::string(getUpperName()) + "Loc()");
853263509Sdim    }
854263509Sdim  };
855226586Sdim}
856226586Sdim
857226586Sdimstatic Argument *createArgument(Record &Arg, StringRef Attr,
858226586Sdim                                Record *Search = 0) {
859226586Sdim  if (!Search)
860226586Sdim    Search = &Arg;
861226586Sdim
862226586Sdim  Argument *Ptr = 0;
863226586Sdim  llvm::StringRef ArgName = Search->getName();
864226586Sdim
865226586Sdim  if (ArgName == "AlignedArgument") Ptr = new AlignedArgument(Arg, Attr);
866226586Sdim  else if (ArgName == "EnumArgument") Ptr = new EnumArgument(Arg, Attr);
867235633Sdim  else if (ArgName == "ExprArgument") Ptr = new ExprArgument(Arg, Attr);
868226586Sdim  else if (ArgName == "FunctionArgument")
869226586Sdim    Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *");
870226586Sdim  else if (ArgName == "IdentifierArgument")
871226586Sdim    Ptr = new SimpleArgument(Arg, Attr, "IdentifierInfo *");
872226586Sdim  else if (ArgName == "BoolArgument") Ptr = new SimpleArgument(Arg, Attr,
873226586Sdim                                                               "bool");
874226586Sdim  else if (ArgName == "IntArgument") Ptr = new SimpleArgument(Arg, Attr, "int");
875226586Sdim  else if (ArgName == "StringArgument") Ptr = new StringArgument(Arg, Attr);
876263509Sdim  else if (ArgName == "TypeArgument") Ptr = new TypeArgument(Arg, Attr);
877226586Sdim  else if (ArgName == "UnsignedArgument")
878226586Sdim    Ptr = new SimpleArgument(Arg, Attr, "unsigned");
879226586Sdim  else if (ArgName == "SourceLocArgument")
880226586Sdim    Ptr = new SimpleArgument(Arg, Attr, "SourceLocation");
881226586Sdim  else if (ArgName == "VariadicUnsignedArgument")
882226586Sdim    Ptr = new VariadicArgument(Arg, Attr, "unsigned");
883263509Sdim  else if (ArgName == "VariadicEnumArgument")
884263509Sdim    Ptr = new VariadicEnumArgument(Arg, Attr);
885226586Sdim  else if (ArgName == "VariadicExprArgument")
886235633Sdim    Ptr = new VariadicExprArgument(Arg, Attr);
887226586Sdim  else if (ArgName == "VersionArgument")
888226586Sdim    Ptr = new VersionArgument(Arg, Attr);
889226586Sdim
890226586Sdim  if (!Ptr) {
891226586Sdim    std::vector<Record*> Bases = Search->getSuperClasses();
892226586Sdim    for (std::vector<Record*>::iterator i = Bases.begin(), e = Bases.end();
893226586Sdim         i != e; ++i) {
894226586Sdim      Ptr = createArgument(Arg, Attr, *i);
895226586Sdim      if (Ptr)
896226586Sdim        break;
897226586Sdim    }
898226586Sdim  }
899263509Sdim
900263509Sdim  if (Ptr && Arg.getValueAsBit("Optional"))
901263509Sdim    Ptr->setOptional(true);
902263509Sdim
903226586Sdim  return Ptr;
904226586Sdim}
905226586Sdim
906235633Sdimstatic void writeAvailabilityValue(raw_ostream &OS) {
907235633Sdim  OS << "\" << getPlatform()->getName();\n"
908235633Sdim     << "  if (!getIntroduced().empty()) OS << \", introduced=\" << getIntroduced();\n"
909235633Sdim     << "  if (!getDeprecated().empty()) OS << \", deprecated=\" << getDeprecated();\n"
910235633Sdim     << "  if (!getObsoleted().empty()) OS << \", obsoleted=\" << getObsoleted();\n"
911235633Sdim     << "  if (getUnavailable()) OS << \", unavailable\";\n"
912235633Sdim     << "  OS << \"";
913235633Sdim}
914235633Sdim
915252723Sdimstatic void writePrettyPrintFunction(Record &R, std::vector<Argument*> &Args,
916252723Sdim                                     raw_ostream &OS) {
917252723Sdim  std::vector<Record*> Spellings = R.getValueAsListOfDefs("Spellings");
918252723Sdim
919252723Sdim  OS << "void " << R.getName() << "Attr::printPretty("
920252723Sdim    << "raw_ostream &OS, const PrintingPolicy &Policy) const {\n";
921252723Sdim
922252723Sdim  if (Spellings.size() == 0) {
923252723Sdim    OS << "}\n\n";
924252723Sdim    return;
925252723Sdim  }
926252723Sdim
927252723Sdim  OS <<
928252723Sdim    "  switch (SpellingListIndex) {\n"
929252723Sdim    "  default:\n"
930252723Sdim    "    llvm_unreachable(\"Unknown attribute spelling!\");\n"
931252723Sdim    "    break;\n";
932252723Sdim
933252723Sdim  for (unsigned I = 0; I < Spellings.size(); ++ I) {
934252723Sdim    llvm::SmallString<16> Prefix;
935252723Sdim    llvm::SmallString<8> Suffix;
936252723Sdim    // The actual spelling of the name and namespace (if applicable)
937252723Sdim    // of an attribute without considering prefix and suffix.
938252723Sdim    llvm::SmallString<64> Spelling;
939252723Sdim    std::string Name = Spellings[I]->getValueAsString("Name");
940252723Sdim    std::string Variety = Spellings[I]->getValueAsString("Variety");
941252723Sdim
942252723Sdim    if (Variety == "GNU") {
943252723Sdim      Prefix = " __attribute__((";
944252723Sdim      Suffix = "))";
945252723Sdim    } else if (Variety == "CXX11") {
946252723Sdim      Prefix = " [[";
947252723Sdim      Suffix = "]]";
948252723Sdim      std::string Namespace = Spellings[I]->getValueAsString("Namespace");
949252723Sdim      if (Namespace != "") {
950252723Sdim        Spelling += Namespace;
951252723Sdim        Spelling += "::";
952252723Sdim      }
953252723Sdim    } else if (Variety == "Declspec") {
954252723Sdim      Prefix = " __declspec(";
955252723Sdim      Suffix = ")";
956252723Sdim    } else if (Variety == "Keyword") {
957252723Sdim      Prefix = " ";
958252723Sdim      Suffix = "";
959252723Sdim    } else {
960252723Sdim      llvm_unreachable("Unknown attribute syntax variety!");
961252723Sdim    }
962252723Sdim
963252723Sdim    Spelling += Name;
964252723Sdim
965252723Sdim    OS <<
966252723Sdim      "  case " << I << " : {\n"
967252723Sdim      "    OS << \"" + Prefix.str() + Spelling.str();
968252723Sdim
969252723Sdim    if (Args.size()) OS << "(";
970252723Sdim    if (Spelling == "availability") {
971252723Sdim      writeAvailabilityValue(OS);
972252723Sdim    } else {
973252723Sdim      for (std::vector<Argument*>::const_iterator I = Args.begin(),
974252723Sdim           E = Args.end(); I != E; ++ I) {
975252723Sdim        if (I != Args.begin()) OS << ", ";
976252723Sdim        (*I)->writeValue(OS);
977252723Sdim      }
978252723Sdim    }
979252723Sdim
980252723Sdim    if (Args.size()) OS << ")";
981252723Sdim    OS << Suffix.str() + "\";\n";
982252723Sdim
983252723Sdim    OS <<
984252723Sdim      "    break;\n"
985252723Sdim      "  }\n";
986252723Sdim  }
987252723Sdim
988252723Sdim  // End of the switch statement.
989252723Sdim  OS << "}\n";
990252723Sdim  // End of the print function.
991252723Sdim  OS << "}\n\n";
992252723Sdim}
993252723Sdim
994252723Sdim/// \brief Return the index of a spelling in a spelling list.
995252723Sdimstatic unsigned getSpellingListIndex(const std::vector<Record*> &SpellingList,
996252723Sdim                                     const Record &Spelling) {
997252723Sdim  assert(SpellingList.size() && "Spelling list is empty!");
998252723Sdim
999252723Sdim  for (unsigned Index = 0; Index < SpellingList.size(); ++Index) {
1000252723Sdim    Record *S = SpellingList[Index];
1001252723Sdim    if (S->getValueAsString("Variety") != Spelling.getValueAsString("Variety"))
1002252723Sdim      continue;
1003252723Sdim    if (S->getValueAsString("Variety") == "CXX11" &&
1004252723Sdim        S->getValueAsString("Namespace") !=
1005252723Sdim        Spelling.getValueAsString("Namespace"))
1006252723Sdim      continue;
1007252723Sdim    if (S->getValueAsString("Name") != Spelling.getValueAsString("Name"))
1008252723Sdim      continue;
1009252723Sdim
1010252723Sdim    return Index;
1011252723Sdim  }
1012252723Sdim
1013252723Sdim  llvm_unreachable("Unknown spelling!");
1014252723Sdim}
1015252723Sdim
1016252723Sdimstatic void writeAttrAccessorDefinition(Record &R, raw_ostream &OS) {
1017252723Sdim  std::vector<Record*> Accessors = R.getValueAsListOfDefs("Accessors");
1018252723Sdim  for (std::vector<Record*>::const_iterator I = Accessors.begin(),
1019252723Sdim       E = Accessors.end(); I != E; ++I) {
1020252723Sdim    Record *Accessor = *I;
1021252723Sdim    std::string Name = Accessor->getValueAsString("Name");
1022252723Sdim    std::vector<Record*> Spellings = Accessor->getValueAsListOfDefs(
1023252723Sdim      "Spellings");
1024252723Sdim    std::vector<Record*> SpellingList = R.getValueAsListOfDefs("Spellings");
1025252723Sdim    assert(SpellingList.size() &&
1026252723Sdim           "Attribute with empty spelling list can't have accessors!");
1027252723Sdim
1028252723Sdim    OS << "  bool " << Name << "() const { return SpellingListIndex == ";
1029252723Sdim    for (unsigned Index = 0; Index < Spellings.size(); ++Index) {
1030252723Sdim      OS << getSpellingListIndex(SpellingList, *Spellings[Index]);
1031252723Sdim      if (Index != Spellings.size() -1)
1032252723Sdim        OS << " ||\n    SpellingListIndex == ";
1033252723Sdim      else
1034252723Sdim        OS << "; }\n";
1035252723Sdim    }
1036252723Sdim  }
1037252723Sdim}
1038252723Sdim
1039245431Sdimnamespace clang {
1040245431Sdim
1041245431Sdim// Emits the class definitions for attributes.
1042245431Sdimvoid EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
1043252723Sdim  emitSourceFileHeader("Attribute classes' definitions", OS);
1044252723Sdim
1045226586Sdim  OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
1046226586Sdim  OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
1047226586Sdim
1048226586Sdim  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1049226586Sdim
1050226586Sdim  for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
1051226586Sdim       i != e; ++i) {
1052226586Sdim    Record &R = **i;
1053245431Sdim
1054245431Sdim    if (!R.getValueAsBit("ASTNode"))
1055245431Sdim      continue;
1056245431Sdim
1057263509Sdim    const std::vector<Record *> Supers = R.getSuperClasses();
1058263509Sdim    assert(!Supers.empty() && "Forgot to specify a superclass for the attr");
1059263509Sdim    std::string SuperName;
1060263509Sdim    for (std::vector<Record *>::const_reverse_iterator I = Supers.rbegin(),
1061263509Sdim         E = Supers.rend(); I != E; ++I) {
1062263509Sdim      const Record &R = **I;
1063263509Sdim      if (R.getName() != "TargetSpecificAttr" && SuperName.empty())
1064263509Sdim        SuperName = R.getName();
1065263509Sdim    }
1066226586Sdim
1067226586Sdim    OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n";
1068226586Sdim
1069226586Sdim    std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
1070226586Sdim    std::vector<Argument*> Args;
1071226586Sdim    std::vector<Argument*>::iterator ai, ae;
1072226586Sdim    Args.reserve(ArgRecords.size());
1073226586Sdim
1074226586Sdim    for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
1075226586Sdim                                        re = ArgRecords.end();
1076226586Sdim         ri != re; ++ri) {
1077226586Sdim      Record &ArgRecord = **ri;
1078226586Sdim      Argument *Arg = createArgument(ArgRecord, R.getName());
1079226586Sdim      assert(Arg);
1080226586Sdim      Args.push_back(Arg);
1081226586Sdim
1082226586Sdim      Arg->writeDeclarations(OS);
1083226586Sdim      OS << "\n\n";
1084226586Sdim    }
1085226586Sdim
1086226586Sdim    ae = Args.end();
1087226586Sdim
1088226586Sdim    OS << "\n public:\n";
1089226586Sdim    OS << "  " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
1090226586Sdim
1091263509Sdim    bool HasOpt = false;
1092226586Sdim    for (ai = Args.begin(); ai != ae; ++ai) {
1093226586Sdim      OS << "              , ";
1094226586Sdim      (*ai)->writeCtorParameters(OS);
1095226586Sdim      OS << "\n";
1096263509Sdim      if ((*ai)->isOptional())
1097263509Sdim        HasOpt = true;
1098226586Sdim    }
1099252723Sdim
1100252723Sdim    OS << "              , ";
1101252723Sdim    OS << "unsigned SI = 0\n";
1102252723Sdim
1103226586Sdim    OS << "             )\n";
1104252723Sdim    OS << "    : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n";
1105226586Sdim
1106226586Sdim    for (ai = Args.begin(); ai != ae; ++ai) {
1107226586Sdim      OS << "              , ";
1108226586Sdim      (*ai)->writeCtorInitializers(OS);
1109226586Sdim      OS << "\n";
1110226586Sdim    }
1111226586Sdim
1112226586Sdim    OS << "  {\n";
1113226586Sdim
1114226586Sdim    for (ai = Args.begin(); ai != ae; ++ai) {
1115226586Sdim      (*ai)->writeCtorBody(OS);
1116226586Sdim      OS << "\n";
1117226586Sdim    }
1118226586Sdim    OS << "  }\n\n";
1119226586Sdim
1120263509Sdim    // If there are optional arguments, write out a constructor that elides the
1121263509Sdim    // optional arguments as well.
1122263509Sdim    if (HasOpt) {
1123263509Sdim      OS << "  " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
1124263509Sdim      for (ai = Args.begin(); ai != ae; ++ai) {
1125263509Sdim        if (!(*ai)->isOptional()) {
1126263509Sdim          OS << "              , ";
1127263509Sdim          (*ai)->writeCtorParameters(OS);
1128263509Sdim          OS << "\n";
1129263509Sdim        }
1130263509Sdim      }
1131263509Sdim
1132263509Sdim      OS << "              , ";
1133263509Sdim      OS << "unsigned SI = 0\n";
1134263509Sdim
1135263509Sdim      OS << "             )\n";
1136263509Sdim      OS << "    : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n";
1137263509Sdim
1138263509Sdim      for (ai = Args.begin(); ai != ae; ++ai) {
1139263509Sdim        OS << "              , ";
1140263509Sdim        (*ai)->writeCtorDefaultInitializers(OS);
1141263509Sdim        OS << "\n";
1142263509Sdim      }
1143263509Sdim
1144263509Sdim      OS << "  {\n";
1145263509Sdim
1146263509Sdim      for (ai = Args.begin(); ai != ae; ++ai) {
1147263509Sdim        if (!(*ai)->isOptional()) {
1148263509Sdim          (*ai)->writeCtorBody(OS);
1149263509Sdim          OS << "\n";
1150263509Sdim        }
1151263509Sdim      }
1152263509Sdim      OS << "  }\n\n";
1153263509Sdim    }
1154263509Sdim
1155226586Sdim    OS << "  virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n";
1156252723Sdim    OS << "  virtual void printPretty(raw_ostream &OS,\n"
1157245431Sdim       << "                           const PrintingPolicy &Policy) const;\n";
1158226586Sdim
1159252723Sdim    writeAttrAccessorDefinition(R, OS);
1160252723Sdim
1161226586Sdim    for (ai = Args.begin(); ai != ae; ++ai) {
1162226586Sdim      (*ai)->writeAccessors(OS);
1163226586Sdim      OS << "\n\n";
1164263509Sdim
1165263509Sdim      if ((*ai)->isEnumArg()) {
1166263509Sdim        EnumArgument *EA = (EnumArgument *)*ai;
1167263509Sdim        EA->writeConversion(OS);
1168263509Sdim      } else if ((*ai)->isVariadicEnumArg()) {
1169263509Sdim        VariadicEnumArgument *VEA = (VariadicEnumArgument *)*ai;
1170263509Sdim        VEA->writeConversion(OS);
1171263509Sdim      }
1172226586Sdim    }
1173226586Sdim
1174235633Sdim    OS << R.getValueAsString("AdditionalMembers");
1175226586Sdim    OS << "\n\n";
1176226586Sdim
1177226586Sdim    OS << "  static bool classof(const Attr *A) { return A->getKind() == "
1178226586Sdim       << "attr::" << R.getName() << "; }\n";
1179235633Sdim
1180235633Sdim    bool LateParsed = R.getValueAsBit("LateParsed");
1181235633Sdim    OS << "  virtual bool isLateParsed() const { return "
1182235633Sdim       << LateParsed << "; }\n";
1183235633Sdim
1184226586Sdim    OS << "};\n\n";
1185226586Sdim  }
1186226586Sdim
1187226586Sdim  OS << "#endif\n";
1188226586Sdim}
1189226586Sdim
1190263509Sdimstatic bool isIdentifierArgument(Record *Arg) {
1191263509Sdim  return !Arg->getSuperClasses().empty() &&
1192263509Sdim         llvm::StringSwitch<bool>(Arg->getSuperClasses().back()->getName())
1193263509Sdim             .Case("IdentifierArgument", true)
1194263509Sdim             .Case("EnumArgument", true)
1195263509Sdim             .Default(false);
1196263509Sdim}
1197263509Sdim
1198263509Sdim/// \brief Emits the first-argument-is-type property for attributes.
1199263509Sdimvoid EmitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) {
1200263509Sdim  emitSourceFileHeader("llvm::StringSwitch code to match attributes with a "
1201263509Sdim                       "type argument", OS);
1202263509Sdim
1203263509Sdim  std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
1204263509Sdim
1205263509Sdim  for (std::vector<Record *>::iterator I = Attrs.begin(), E = Attrs.end();
1206263509Sdim       I != E; ++I) {
1207263509Sdim    Record &Attr = **I;
1208263509Sdim
1209263509Sdim    // Determine whether the first argument is a type.
1210263509Sdim    std::vector<Record *> Args = Attr.getValueAsListOfDefs("Args");
1211263509Sdim    if (Args.empty())
1212263509Sdim      continue;
1213263509Sdim
1214263509Sdim    if (Args[0]->getSuperClasses().back()->getName() != "TypeArgument")
1215263509Sdim      continue;
1216263509Sdim
1217263509Sdim    // All these spellings take a single type argument.
1218263509Sdim    std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
1219263509Sdim    std::set<std::string> Emitted;
1220263509Sdim    for (std::vector<Record*>::const_iterator I = Spellings.begin(),
1221263509Sdim         E = Spellings.end(); I != E; ++I) {
1222263509Sdim      if (Emitted.insert((*I)->getValueAsString("Name")).second)
1223263509Sdim        OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", "
1224263509Sdim           << "true" << ")\n";
1225263509Sdim    }
1226263509Sdim  }
1227263509Sdim}
1228263509Sdim
1229263509Sdim// Emits the first-argument-is-identifier property for attributes.
1230263509Sdimvoid EmitClangAttrIdentifierArgList(RecordKeeper &Records, raw_ostream &OS) {
1231252723Sdim  emitSourceFileHeader("llvm::StringSwitch code to match attributes with "
1232263509Sdim                       "an identifier argument", OS);
1233252723Sdim
1234252723Sdim  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1235252723Sdim
1236252723Sdim  for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1237252723Sdim       I != E; ++I) {
1238252723Sdim    Record &Attr = **I;
1239252723Sdim
1240263509Sdim    // Determine whether the first argument is an identifier.
1241252723Sdim    std::vector<Record *> Args = Attr.getValueAsListOfDefs("Args");
1242263509Sdim    if (Args.empty() || !isIdentifierArgument(Args[0]))
1243252723Sdim      continue;
1244252723Sdim
1245263509Sdim    // All these spellings take an identifier argument.
1246252723Sdim    std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
1247263509Sdim    std::set<std::string> Emitted;
1248252723Sdim    for (std::vector<Record*>::const_iterator I = Spellings.begin(),
1249252723Sdim         E = Spellings.end(); I != E; ++I) {
1250263509Sdim      if (Emitted.insert((*I)->getValueAsString("Name")).second)
1251263509Sdim        OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", "
1252263509Sdim           << "true" << ")\n";
1253252723Sdim    }
1254252723Sdim  }
1255252723Sdim}
1256252723Sdim
1257245431Sdim// Emits the class method definitions for attributes.
1258245431Sdimvoid EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
1259252723Sdim  emitSourceFileHeader("Attribute classes' member function definitions", OS);
1260226586Sdim
1261226586Sdim  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1262226586Sdim  std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ri, re;
1263226586Sdim  std::vector<Argument*>::iterator ai, ae;
1264226586Sdim
1265226586Sdim  for (; i != e; ++i) {
1266226586Sdim    Record &R = **i;
1267245431Sdim
1268245431Sdim    if (!R.getValueAsBit("ASTNode"))
1269245431Sdim      continue;
1270245431Sdim
1271226586Sdim    std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
1272226586Sdim    std::vector<Argument*> Args;
1273226586Sdim    for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri)
1274226586Sdim      Args.push_back(createArgument(**ri, R.getName()));
1275226586Sdim
1276226586Sdim    for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
1277226586Sdim      (*ai)->writeAccessorDefinitions(OS);
1278226586Sdim
1279226586Sdim    OS << R.getName() << "Attr *" << R.getName()
1280226586Sdim       << "Attr::clone(ASTContext &C) const {\n";
1281226586Sdim    OS << "  return new (C) " << R.getName() << "Attr(getLocation(), C";
1282226586Sdim    for (ai = Args.begin(); ai != ae; ++ai) {
1283226586Sdim      OS << ", ";
1284226586Sdim      (*ai)->writeCloneArgs(OS);
1285226586Sdim    }
1286252723Sdim    OS << ", getSpellingListIndex());\n}\n\n";
1287235633Sdim
1288252723Sdim    writePrettyPrintFunction(R, Args, OS);
1289226586Sdim  }
1290226586Sdim}
1291226586Sdim
1292245431Sdim} // end namespace clang
1293245431Sdim
1294226586Sdimstatic void EmitAttrList(raw_ostream &OS, StringRef Class,
1295226586Sdim                         const std::vector<Record*> &AttrList) {
1296226586Sdim  std::vector<Record*>::const_iterator i = AttrList.begin(), e = AttrList.end();
1297226586Sdim
1298226586Sdim  if (i != e) {
1299226586Sdim    // Move the end iterator back to emit the last attribute.
1300245431Sdim    for(--e; i != e; ++i) {
1301245431Sdim      if (!(*i)->getValueAsBit("ASTNode"))
1302245431Sdim        continue;
1303245431Sdim
1304226586Sdim      OS << Class << "(" << (*i)->getName() << ")\n";
1305245431Sdim    }
1306226586Sdim
1307226586Sdim    OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n";
1308226586Sdim  }
1309226586Sdim}
1310226586Sdim
1311245431Sdimnamespace clang {
1312245431Sdim
1313245431Sdim// Emits the enumeration list for attributes.
1314245431Sdimvoid EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) {
1315252723Sdim  emitSourceFileHeader("List of all attributes that Clang recognizes", OS);
1316226586Sdim
1317226586Sdim  OS << "#ifndef LAST_ATTR\n";
1318226586Sdim  OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n";
1319226586Sdim  OS << "#endif\n\n";
1320226586Sdim
1321226586Sdim  OS << "#ifndef INHERITABLE_ATTR\n";
1322226586Sdim  OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n";
1323226586Sdim  OS << "#endif\n\n";
1324226586Sdim
1325226586Sdim  OS << "#ifndef LAST_INHERITABLE_ATTR\n";
1326226586Sdim  OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n";
1327226586Sdim  OS << "#endif\n\n";
1328226586Sdim
1329226586Sdim  OS << "#ifndef INHERITABLE_PARAM_ATTR\n";
1330226586Sdim  OS << "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n";
1331226586Sdim  OS << "#endif\n\n";
1332226586Sdim
1333226586Sdim  OS << "#ifndef LAST_INHERITABLE_PARAM_ATTR\n";
1334226586Sdim  OS << "#define LAST_INHERITABLE_PARAM_ATTR(NAME)"
1335226586Sdim        " INHERITABLE_PARAM_ATTR(NAME)\n";
1336226586Sdim  OS << "#endif\n\n";
1337226586Sdim
1338263509Sdim  OS << "#ifndef MS_INHERITANCE_ATTR\n";
1339263509Sdim  OS << "#define MS_INHERITANCE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n";
1340252723Sdim  OS << "#endif\n\n";
1341252723Sdim
1342263509Sdim  OS << "#ifndef LAST_MS_INHERITANCE_ATTR\n";
1343263509Sdim  OS << "#define LAST_MS_INHERITANCE_ATTR(NAME)"
1344263509Sdim        " MS_INHERITANCE_ATTR(NAME)\n";
1345252723Sdim  OS << "#endif\n\n";
1346252723Sdim
1347226586Sdim  Record *InhClass = Records.getClass("InheritableAttr");
1348226586Sdim  Record *InhParamClass = Records.getClass("InheritableParamAttr");
1349252723Sdim  Record *MSInheritanceClass = Records.getClass("MSInheritanceAttr");
1350226586Sdim  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
1351252723Sdim                       NonInhAttrs, InhAttrs, InhParamAttrs, MSInhAttrs;
1352226586Sdim  for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
1353226586Sdim       i != e; ++i) {
1354245431Sdim    if (!(*i)->getValueAsBit("ASTNode"))
1355245431Sdim      continue;
1356245431Sdim
1357226586Sdim    if ((*i)->isSubClassOf(InhParamClass))
1358226586Sdim      InhParamAttrs.push_back(*i);
1359252723Sdim    else if ((*i)->isSubClassOf(MSInheritanceClass))
1360252723Sdim      MSInhAttrs.push_back(*i);
1361226586Sdim    else if ((*i)->isSubClassOf(InhClass))
1362226586Sdim      InhAttrs.push_back(*i);
1363226586Sdim    else
1364226586Sdim      NonInhAttrs.push_back(*i);
1365226586Sdim  }
1366226586Sdim
1367226586Sdim  EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs);
1368263509Sdim  EmitAttrList(OS, "MS_INHERITANCE_ATTR", MSInhAttrs);
1369226586Sdim  EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs);
1370226586Sdim  EmitAttrList(OS, "ATTR", NonInhAttrs);
1371226586Sdim
1372226586Sdim  OS << "#undef LAST_ATTR\n";
1373226586Sdim  OS << "#undef INHERITABLE_ATTR\n";
1374263509Sdim  OS << "#undef MS_INHERITANCE_ATTR\n";
1375226586Sdim  OS << "#undef LAST_INHERITABLE_ATTR\n";
1376226586Sdim  OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n";
1377263509Sdim  OS << "#undef LAST_MS_INHERITANCE_ATTR\n";
1378226586Sdim  OS << "#undef ATTR\n";
1379226586Sdim}
1380226586Sdim
1381245431Sdim// Emits the code to read an attribute from a precompiled header.
1382245431Sdimvoid EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) {
1383252723Sdim  emitSourceFileHeader("Attribute deserialization code", OS);
1384226586Sdim
1385226586Sdim  Record *InhClass = Records.getClass("InheritableAttr");
1386226586Sdim  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
1387226586Sdim                       ArgRecords;
1388226586Sdim  std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
1389226586Sdim  std::vector<Argument*> Args;
1390226586Sdim  std::vector<Argument*>::iterator ri, re;
1391226586Sdim
1392226586Sdim  OS << "  switch (Kind) {\n";
1393226586Sdim  OS << "  default:\n";
1394226586Sdim  OS << "    assert(0 && \"Unknown attribute!\");\n";
1395226586Sdim  OS << "    break;\n";
1396226586Sdim  for (; i != e; ++i) {
1397226586Sdim    Record &R = **i;
1398245431Sdim    if (!R.getValueAsBit("ASTNode"))
1399245431Sdim      continue;
1400245431Sdim
1401226586Sdim    OS << "  case attr::" << R.getName() << ": {\n";
1402226586Sdim    if (R.isSubClassOf(InhClass))
1403226586Sdim      OS << "    bool isInherited = Record[Idx++];\n";
1404226586Sdim    ArgRecords = R.getValueAsListOfDefs("Args");
1405226586Sdim    Args.clear();
1406226586Sdim    for (ai = ArgRecords.begin(), ae = ArgRecords.end(); ai != ae; ++ai) {
1407226586Sdim      Argument *A = createArgument(**ai, R.getName());
1408226586Sdim      Args.push_back(A);
1409226586Sdim      A->writePCHReadDecls(OS);
1410226586Sdim    }
1411226586Sdim    OS << "    New = new (Context) " << R.getName() << "Attr(Range, Context";
1412226586Sdim    for (ri = Args.begin(), re = Args.end(); ri != re; ++ri) {
1413226586Sdim      OS << ", ";
1414226586Sdim      (*ri)->writePCHReadArgs(OS);
1415226586Sdim    }
1416226586Sdim    OS << ");\n";
1417226586Sdim    if (R.isSubClassOf(InhClass))
1418226586Sdim      OS << "    cast<InheritableAttr>(New)->setInherited(isInherited);\n";
1419226586Sdim    OS << "    break;\n";
1420226586Sdim    OS << "  }\n";
1421226586Sdim  }
1422226586Sdim  OS << "  }\n";
1423226586Sdim}
1424226586Sdim
1425245431Sdim// Emits the code to write an attribute to a precompiled header.
1426245431Sdimvoid EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) {
1427252723Sdim  emitSourceFileHeader("Attribute serialization code", OS);
1428252723Sdim
1429226586Sdim  Record *InhClass = Records.getClass("InheritableAttr");
1430226586Sdim  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
1431226586Sdim  std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
1432226586Sdim
1433226586Sdim  OS << "  switch (A->getKind()) {\n";
1434226586Sdim  OS << "  default:\n";
1435226586Sdim  OS << "    llvm_unreachable(\"Unknown attribute kind!\");\n";
1436226586Sdim  OS << "    break;\n";
1437226586Sdim  for (; i != e; ++i) {
1438226586Sdim    Record &R = **i;
1439245431Sdim    if (!R.getValueAsBit("ASTNode"))
1440245431Sdim      continue;
1441226586Sdim    OS << "  case attr::" << R.getName() << ": {\n";
1442226586Sdim    Args = R.getValueAsListOfDefs("Args");
1443226586Sdim    if (R.isSubClassOf(InhClass) || !Args.empty())
1444226586Sdim      OS << "    const " << R.getName() << "Attr *SA = cast<" << R.getName()
1445226586Sdim         << "Attr>(A);\n";
1446226586Sdim    if (R.isSubClassOf(InhClass))
1447226586Sdim      OS << "    Record.push_back(SA->isInherited());\n";
1448226586Sdim    for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
1449226586Sdim      createArgument(**ai, R.getName())->writePCHWrite(OS);
1450226586Sdim    OS << "    break;\n";
1451226586Sdim    OS << "  }\n";
1452226586Sdim  }
1453226586Sdim  OS << "  }\n";
1454226586Sdim}
1455226586Sdim
1456245431Sdim// Emits the list of spellings for attributes.
1457245431Sdimvoid EmitClangAttrSpellingList(RecordKeeper &Records, raw_ostream &OS) {
1458252723Sdim  emitSourceFileHeader("llvm::StringSwitch code to match all known attributes",
1459252723Sdim                       OS);
1460226586Sdim
1461226586Sdim  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1462226586Sdim
1463226586Sdim  for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) {
1464226586Sdim    Record &Attr = **I;
1465226586Sdim
1466245431Sdim    std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
1467226586Sdim
1468245431Sdim    for (std::vector<Record*>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) {
1469245431Sdim      OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", true)\n";
1470226586Sdim    }
1471226586Sdim  }
1472226586Sdim
1473226586Sdim}
1474226586Sdim
1475252723Sdimvoid EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) {
1476252723Sdim  emitSourceFileHeader("Code to translate different attribute spellings "
1477252723Sdim                       "into internal identifiers", OS);
1478252723Sdim
1479252723Sdim  OS <<
1480252723Sdim    "  unsigned Index = 0;\n"
1481252723Sdim    "  switch (AttrKind) {\n"
1482252723Sdim    "  default:\n"
1483252723Sdim    "    llvm_unreachable(\"Unknown attribute kind!\");\n"
1484252723Sdim    "    break;\n";
1485252723Sdim
1486252723Sdim  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1487252723Sdim  for (std::vector<Record*>::const_iterator I = Attrs.begin(), E = Attrs.end();
1488252723Sdim       I != E; ++I) {
1489252723Sdim    Record &R = **I;
1490252723Sdim    // We only care about attributes that participate in Sema checking, so
1491252723Sdim    // skip those attributes that are not able to make their way to Sema.
1492252723Sdim    if (!R.getValueAsBit("SemaHandler"))
1493252723Sdim      continue;
1494252723Sdim
1495252723Sdim    std::vector<Record*> Spellings = R.getValueAsListOfDefs("Spellings");
1496252723Sdim    // Each distinct spelling yields an attribute kind.
1497252723Sdim    if (R.getValueAsBit("DistinctSpellings")) {
1498252723Sdim      for (unsigned I = 0; I < Spellings.size(); ++ I) {
1499252723Sdim        OS <<
1500252723Sdim          "  case AT_" << Spellings[I]->getValueAsString("Name") << ": \n"
1501252723Sdim          "    Index = " << I << ";\n"
1502252723Sdim          "  break;\n";
1503252723Sdim      }
1504252723Sdim    } else {
1505252723Sdim      OS << "  case AT_" << R.getName() << " : {\n";
1506252723Sdim      for (unsigned I = 0; I < Spellings.size(); ++ I) {
1507252723Sdim        SmallString<16> Namespace;
1508252723Sdim        if (Spellings[I]->getValueAsString("Variety") == "CXX11")
1509252723Sdim          Namespace = Spellings[I]->getValueAsString("Namespace");
1510252723Sdim        else
1511252723Sdim          Namespace = "";
1512252723Sdim
1513252723Sdim        OS << "    if (Name == \""
1514252723Sdim          << Spellings[I]->getValueAsString("Name") << "\" && "
1515252723Sdim          << "SyntaxUsed == "
1516252723Sdim          << StringSwitch<unsigned>(Spellings[I]->getValueAsString("Variety"))
1517252723Sdim            .Case("GNU", 0)
1518252723Sdim            .Case("CXX11", 1)
1519252723Sdim            .Case("Declspec", 2)
1520252723Sdim            .Case("Keyword", 3)
1521252723Sdim            .Default(0)
1522252723Sdim          << " && Scope == \"" << Namespace << "\")\n"
1523252723Sdim          << "        return " << I << ";\n";
1524252723Sdim      }
1525252723Sdim
1526252723Sdim      OS << "    break;\n";
1527252723Sdim      OS << "  }\n";
1528252723Sdim    }
1529252723Sdim  }
1530252723Sdim
1531252723Sdim  OS << "  }\n";
1532252723Sdim  OS << "  return Index;\n";
1533252723Sdim}
1534252723Sdim
1535245431Sdim// Emits the LateParsed property for attributes.
1536245431Sdimvoid EmitClangAttrLateParsedList(RecordKeeper &Records, raw_ostream &OS) {
1537252723Sdim  emitSourceFileHeader("llvm::StringSwitch code to match late parsed "
1538252723Sdim                       "attributes", OS);
1539226586Sdim
1540226586Sdim  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1541226586Sdim
1542226586Sdim  for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1543226586Sdim       I != E; ++I) {
1544226586Sdim    Record &Attr = **I;
1545226586Sdim
1546226586Sdim    bool LateParsed = Attr.getValueAsBit("LateParsed");
1547226586Sdim
1548226586Sdim    if (LateParsed) {
1549245431Sdim      std::vector<Record*> Spellings =
1550245431Sdim        Attr.getValueAsListOfDefs("Spellings");
1551226586Sdim
1552245431Sdim      // FIXME: Handle non-GNU attributes
1553245431Sdim      for (std::vector<Record*>::const_iterator I = Spellings.begin(),
1554226586Sdim           E = Spellings.end(); I != E; ++I) {
1555245431Sdim        if ((*I)->getValueAsString("Variety") != "GNU")
1556245431Sdim          continue;
1557245431Sdim        OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", "
1558245431Sdim           << LateParsed << ")\n";
1559226586Sdim      }
1560226586Sdim    }
1561226586Sdim  }
1562226586Sdim}
1563235633Sdim
1564245431Sdim// Emits code to instantiate dependent attributes on templates.
1565245431Sdimvoid EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) {
1566252723Sdim  emitSourceFileHeader("Template instantiation code for attributes", OS);
1567235633Sdim
1568235633Sdim  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1569235633Sdim
1570235633Sdim  OS << "namespace clang {\n"
1571235633Sdim     << "namespace sema {\n\n"
1572235633Sdim     << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, "
1573235633Sdim     << "Sema &S,\n"
1574235633Sdim     << "        const MultiLevelTemplateArgumentList &TemplateArgs) {\n"
1575235633Sdim     << "  switch (At->getKind()) {\n"
1576235633Sdim     << "    default:\n"
1577235633Sdim     << "      break;\n";
1578235633Sdim
1579235633Sdim  for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1580235633Sdim       I != E; ++I) {
1581235633Sdim    Record &R = **I;
1582245431Sdim    if (!R.getValueAsBit("ASTNode"))
1583245431Sdim      continue;
1584235633Sdim
1585235633Sdim    OS << "    case attr::" << R.getName() << ": {\n";
1586245431Sdim    bool ShouldClone = R.getValueAsBit("Clone");
1587245431Sdim
1588245431Sdim    if (!ShouldClone) {
1589245431Sdim      OS << "      return NULL;\n";
1590245431Sdim      OS << "    }\n";
1591245431Sdim      continue;
1592245431Sdim    }
1593245431Sdim
1594235633Sdim    OS << "      const " << R.getName() << "Attr *A = cast<"
1595235633Sdim       << R.getName() << "Attr>(At);\n";
1596235633Sdim    bool TDependent = R.getValueAsBit("TemplateDependent");
1597235633Sdim
1598235633Sdim    if (!TDependent) {
1599235633Sdim      OS << "      return A->clone(C);\n";
1600235633Sdim      OS << "    }\n";
1601235633Sdim      continue;
1602235633Sdim    }
1603235633Sdim
1604235633Sdim    std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
1605235633Sdim    std::vector<Argument*> Args;
1606235633Sdim    std::vector<Argument*>::iterator ai, ae;
1607235633Sdim    Args.reserve(ArgRecords.size());
1608235633Sdim
1609235633Sdim    for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
1610235633Sdim                                        re = ArgRecords.end();
1611235633Sdim         ri != re; ++ri) {
1612235633Sdim      Record &ArgRecord = **ri;
1613235633Sdim      Argument *Arg = createArgument(ArgRecord, R.getName());
1614235633Sdim      assert(Arg);
1615235633Sdim      Args.push_back(Arg);
1616235633Sdim    }
1617235633Sdim    ae = Args.end();
1618235633Sdim
1619235633Sdim    for (ai = Args.begin(); ai != ae; ++ai) {
1620235633Sdim      (*ai)->writeTemplateInstantiation(OS);
1621235633Sdim    }
1622235633Sdim    OS << "      return new (C) " << R.getName() << "Attr(A->getLocation(), C";
1623235633Sdim    for (ai = Args.begin(); ai != ae; ++ai) {
1624235633Sdim      OS << ", ";
1625235633Sdim      (*ai)->writeTemplateInstantiationArgs(OS);
1626235633Sdim    }
1627235633Sdim    OS << ");\n    }\n";
1628235633Sdim  }
1629235633Sdim  OS << "  } // end switch\n"
1630235633Sdim     << "  llvm_unreachable(\"Unknown attribute!\");\n"
1631235633Sdim     << "  return 0;\n"
1632235633Sdim     << "}\n\n"
1633235633Sdim     << "} // end namespace sema\n"
1634235633Sdim     << "} // end namespace clang\n";
1635235633Sdim}
1636235633Sdim
1637263509Sdimtypedef std::vector<std::pair<std::string, Record *> > ParsedAttrMap;
1638252723Sdim
1639263509Sdimstatic ParsedAttrMap getParsedAttrList(const RecordKeeper &Records) {
1640235633Sdim  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1641263509Sdim  ParsedAttrMap R;
1642235633Sdim  for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1643235633Sdim       I != E; ++I) {
1644235633Sdim    Record &Attr = **I;
1645235633Sdim
1646235633Sdim    bool SemaHandler = Attr.getValueAsBit("SemaHandler");
1647245431Sdim    bool DistinctSpellings = Attr.getValueAsBit("DistinctSpellings");
1648245431Sdim
1649235633Sdim    if (SemaHandler) {
1650245431Sdim      if (DistinctSpellings) {
1651245431Sdim        std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
1652245431Sdim
1653245431Sdim        for (std::vector<Record*>::const_iterator I = Spellings.begin(),
1654245431Sdim             E = Spellings.end(); I != E; ++I) {
1655245431Sdim          std::string AttrName = (*I)->getValueAsString("Name");
1656235633Sdim
1657245431Sdim          StringRef Spelling = NormalizeAttrName(AttrName);
1658263509Sdim          R.push_back(std::make_pair(Spelling.str(), &Attr));
1659245431Sdim        }
1660245431Sdim      } else {
1661245431Sdim        StringRef AttrName = Attr.getName();
1662235633Sdim        AttrName = NormalizeAttrName(AttrName);
1663263509Sdim        R.push_back(std::make_pair(AttrName.str(), *I));
1664235633Sdim      }
1665235633Sdim    }
1666235633Sdim  }
1667263509Sdim  return R;
1668235633Sdim}
1669235633Sdim
1670263509Sdim// Emits the list of parsed attributes.
1671263509Sdimvoid EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) {
1672263509Sdim  emitSourceFileHeader("List of all attributes that Clang recognizes", OS);
1673263509Sdim
1674263509Sdim  OS << "#ifndef PARSED_ATTR\n";
1675263509Sdim  OS << "#define PARSED_ATTR(NAME) NAME\n";
1676263509Sdim  OS << "#endif\n\n";
1677263509Sdim
1678263509Sdim  ParsedAttrMap Names = getParsedAttrList(Records);
1679263509Sdim  for (ParsedAttrMap::iterator I = Names.begin(), E = Names.end(); I != E;
1680263509Sdim       ++I) {
1681263509Sdim    OS << "PARSED_ATTR(" << I->first << ")\n";
1682263509Sdim  }
1683263509Sdim}
1684263509Sdim
1685263509Sdimstatic void emitArgInfo(const Record &R, raw_ostream &OS) {
1686263509Sdim  // This function will count the number of arguments specified for the
1687263509Sdim  // attribute and emit the number of required arguments followed by the
1688263509Sdim  // number of optional arguments.
1689263509Sdim  std::vector<Record *> Args = R.getValueAsListOfDefs("Args");
1690263509Sdim  unsigned ArgCount = 0, OptCount = 0;
1691263509Sdim  for (std::vector<Record *>::const_iterator I = Args.begin(), E = Args.end();
1692263509Sdim       I != E; ++I) {
1693263509Sdim    const Record &Arg = **I;
1694263509Sdim    Arg.getValueAsBit("Optional") ? ++OptCount : ++ArgCount;
1695263509Sdim  }
1696263509Sdim  OS << ArgCount << ", " << OptCount;
1697263509Sdim}
1698263509Sdim
1699263509Sdim/// Emits the parsed attribute helpers
1700263509Sdimvoid EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
1701263509Sdim  emitSourceFileHeader("Parsed attribute helpers", OS);
1702263509Sdim
1703263509Sdim  ParsedAttrMap Attrs = getParsedAttrList(Records);
1704263509Sdim
1705263509Sdim  OS << "static const ParsedAttrInfo AttrInfoMap[AttributeList::UnknownAttribute + 1] = {\n";
1706263509Sdim  for (ParsedAttrMap::iterator I = Attrs.begin(), E = Attrs.end(); I != E;
1707263509Sdim       ++I) {
1708263509Sdim    // We need to generate struct instances based off ParsedAttrInfo from
1709263509Sdim    // AttributeList.cpp.
1710263509Sdim    OS << "  { ";
1711263509Sdim    emitArgInfo(*I->second, OS);
1712263509Sdim    OS << ", " << I->second->getValueAsBit("HasCustomParsing");
1713263509Sdim    OS << " }";
1714263509Sdim
1715263509Sdim    if (I + 1 != E)
1716263509Sdim      OS << ",";
1717263509Sdim
1718263509Sdim    OS << "  // AT_" << I->first << "\n";
1719263509Sdim  }
1720263509Sdim  OS << "};\n\n";
1721263509Sdim}
1722263509Sdim
1723245431Sdim// Emits the kind list of parsed attributes
1724245431Sdimvoid EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
1725252723Sdim  emitSourceFileHeader("Attribute name matcher", OS);
1726252723Sdim
1727235633Sdim  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1728235633Sdim
1729245431Sdim  std::vector<StringMatcher::StringPair> Matches;
1730235633Sdim  for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1731235633Sdim       I != E; ++I) {
1732235633Sdim    Record &Attr = **I;
1733235633Sdim
1734235633Sdim    bool SemaHandler = Attr.getValueAsBit("SemaHandler");
1735245431Sdim    bool Ignored = Attr.getValueAsBit("Ignored");
1736245431Sdim    bool DistinctSpellings = Attr.getValueAsBit("DistinctSpellings");
1737245431Sdim    if (SemaHandler || Ignored) {
1738245431Sdim      std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
1739235633Sdim
1740245431Sdim      for (std::vector<Record*>::const_iterator I = Spellings.begin(),
1741235633Sdim           E = Spellings.end(); I != E; ++I) {
1742245431Sdim        std::string RawSpelling = (*I)->getValueAsString("Name");
1743245431Sdim        StringRef AttrName = NormalizeAttrName(DistinctSpellings
1744245431Sdim                                                 ? StringRef(RawSpelling)
1745245431Sdim                                                 : StringRef(Attr.getName()));
1746235633Sdim
1747245431Sdim        SmallString<64> Spelling;
1748245431Sdim        if ((*I)->getValueAsString("Variety") == "CXX11") {
1749245431Sdim          Spelling += (*I)->getValueAsString("Namespace");
1750245431Sdim          Spelling += "::";
1751245431Sdim        }
1752245431Sdim        Spelling += NormalizeAttrSpelling(RawSpelling);
1753245431Sdim
1754245431Sdim        if (SemaHandler)
1755245431Sdim          Matches.push_back(
1756245431Sdim            StringMatcher::StringPair(
1757245431Sdim              StringRef(Spelling),
1758245431Sdim              "return AttributeList::AT_" + AttrName.str() + ";"));
1759245431Sdim        else
1760245431Sdim          Matches.push_back(
1761245431Sdim            StringMatcher::StringPair(
1762245431Sdim              StringRef(Spelling),
1763245431Sdim              "return AttributeList::IgnoredAttribute;"));
1764235633Sdim      }
1765235633Sdim    }
1766235633Sdim  }
1767245431Sdim
1768245431Sdim  OS << "static AttributeList::Kind getAttrKind(StringRef Name) {\n";
1769245431Sdim  StringMatcher("Name", Matches, OS).Emit();
1770245431Sdim  OS << "return AttributeList::UnknownAttribute;\n"
1771245431Sdim     << "}\n";
1772235633Sdim}
1773235633Sdim
1774252723Sdim// Emits the code to dump an attribute.
1775252723Sdimvoid EmitClangAttrDump(RecordKeeper &Records, raw_ostream &OS) {
1776252723Sdim  emitSourceFileHeader("Attribute dumper", OS);
1777252723Sdim
1778252723Sdim  OS <<
1779252723Sdim    "  switch (A->getKind()) {\n"
1780252723Sdim    "  default:\n"
1781252723Sdim    "    llvm_unreachable(\"Unknown attribute kind!\");\n"
1782252723Sdim    "    break;\n";
1783252723Sdim  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
1784252723Sdim  for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1785252723Sdim       I != E; ++I) {
1786252723Sdim    Record &R = **I;
1787252723Sdim    if (!R.getValueAsBit("ASTNode"))
1788252723Sdim      continue;
1789252723Sdim    OS << "  case attr::" << R.getName() << ": {\n";
1790252723Sdim    Args = R.getValueAsListOfDefs("Args");
1791252723Sdim    if (!Args.empty()) {
1792252723Sdim      OS << "    const " << R.getName() << "Attr *SA = cast<" << R.getName()
1793252723Sdim         << "Attr>(A);\n";
1794252723Sdim      for (std::vector<Record*>::iterator I = Args.begin(), E = Args.end();
1795252723Sdim           I != E; ++I)
1796252723Sdim        createArgument(**I, R.getName())->writeDump(OS);
1797252723Sdim
1798252723Sdim      // Code for detecting the last child.
1799252723Sdim      OS << "    bool OldMoreChildren = hasMoreChildren();\n";
1800252723Sdim      OS << "    bool MoreChildren = OldMoreChildren;\n";
1801252723Sdim
1802252723Sdim      for (std::vector<Record*>::iterator I = Args.begin(), E = Args.end();
1803252723Sdim           I != E; ++I) {
1804252723Sdim        // More code for detecting the last child.
1805252723Sdim        OS << "    MoreChildren = OldMoreChildren";
1806252723Sdim        for (std::vector<Record*>::iterator Next = I + 1; Next != E; ++Next) {
1807252723Sdim          OS << " || ";
1808252723Sdim          createArgument(**Next, R.getName())->writeHasChildren(OS);
1809252723Sdim        }
1810252723Sdim        OS << ";\n";
1811252723Sdim        OS << "    setMoreChildren(MoreChildren);\n";
1812252723Sdim
1813252723Sdim        createArgument(**I, R.getName())->writeDumpChildren(OS);
1814252723Sdim      }
1815252723Sdim
1816252723Sdim      // Reset the last child.
1817252723Sdim      OS << "    setMoreChildren(OldMoreChildren);\n";
1818252723Sdim    }
1819252723Sdim    OS <<
1820252723Sdim      "    break;\n"
1821252723Sdim      "  }\n";
1822252723Sdim  }
1823252723Sdim  OS << "  }\n";
1824252723Sdim}
1825252723Sdim
1826245431Sdim} // end namespace clang
1827