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
14239462Sdim#include "llvm/ADT/SmallString.h"
15226586Sdim#include "llvm/ADT/StringSwitch.h"
16263508Sdim#include "llvm/ADT/SmallSet.h"
17226586Sdim#include "llvm/TableGen/Record.h"
18239462Sdim#include "llvm/TableGen/StringMatcher.h"
19239462Sdim#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");
37243830Sdim    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++])")
50263508Sdim    .Case("TypeSourceInfo *", "GetTypeSourceInfo(F, Record, Idx)")
51249423Sdim    .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")
62263508Sdim    .Case("TypeSourceInfo *",
63263508Sdim          "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
72234353Sdim// Normalize attribute name by removing leading and trailing
73234353Sdim// underscores. For example, __foo, foo__, __foo__ would
74234353Sdim// become foo.
75234353Sdimstatic StringRef NormalizeAttrName(StringRef AttrName) {
76234353Sdim  if (AttrName.startswith("__"))
77234353Sdim    AttrName = AttrName.substr(2, AttrName.size());
78234353Sdim
79234353Sdim  if (AttrName.endswith("__"))
80234353Sdim    AttrName = AttrName.substr(0, AttrName.size() - 2);
81234353Sdim
82234353Sdim  return AttrName;
83234353Sdim}
84234353Sdim
85234353Sdim// Normalize attribute spelling only if the spelling has both leading
86234353Sdim// and trailing underscores. For example, __ms_struct__ will be
87234353Sdim// normalized to "ms_struct"; __cdecl will remain intact.
88234353Sdimstatic StringRef NormalizeAttrSpelling(StringRef AttrSpelling) {
89234353Sdim  if (AttrSpelling.startswith("__") && AttrSpelling.endswith("__")) {
90234353Sdim    AttrSpelling = AttrSpelling.substr(2, AttrSpelling.size() - 4);
91234353Sdim  }
92234353Sdim
93234353Sdim  return AttrSpelling;
94234353Sdim}
95234353Sdim
96226586Sdimnamespace {
97226586Sdim  class Argument {
98226586Sdim    std::string lowerName, upperName;
99226586Sdim    StringRef attrName;
100263508Sdim    bool isOpt;
101226586Sdim
102226586Sdim  public:
103226586Sdim    Argument(Record &Arg, StringRef Attr)
104226586Sdim      : lowerName(Arg.getValueAsString("Name")), upperName(lowerName),
105263508Sdim        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
117263508Sdim    bool isOptional() const { return isOpt; }
118263508Sdim    void setOptional(bool set) { isOpt = set; }
119263508Sdim
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;
124234353Sdim    virtual void writeTemplateInstantiationArgs(raw_ostream &OS) const = 0;
125234353Sdim    virtual void writeTemplateInstantiation(raw_ostream &OS) const {}
126226586Sdim    virtual void writeCtorBody(raw_ostream &OS) const {}
127226586Sdim    virtual void writeCtorInitializers(raw_ostream &OS) const = 0;
128263508Sdim    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;
134234353Sdim    virtual void writeValue(raw_ostream &OS) const = 0;
135249423Sdim    virtual void writeDump(raw_ostream &OS) const = 0;
136249423Sdim    virtual void writeDumpChildren(raw_ostream &OS) const {}
137249423Sdim    virtual void writeHasChildren(raw_ostream &OS) const { OS << "false"; }
138263508Sdim
139263508Sdim    virtual bool isEnumArg() const { return false; }
140263508Sdim    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
151234353Sdim    std::string getType() const { return type; }
152234353Sdim
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    }
161234353Sdim    void writeTemplateInstantiationArgs(raw_ostream &OS) const {
162234353Sdim      OS << "A->get" << getUpperName() << "()";
163234353Sdim    }
164226586Sdim    void writeCtorInitializers(raw_ostream &OS) const {
165226586Sdim      OS << getLowerName() << "(" << getUpperName() << ")";
166226586Sdim    }
167263508Sdim    void writeCtorDefaultInitializers(raw_ostream &OS) const {
168263508Sdim      OS << getLowerName() << "()";
169263508Sdim    }
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    }
187234353Sdim    void writeValue(raw_ostream &OS) const {
188234353Sdim      if (type == "FunctionDecl *") {
189263508Sdim        OS << "\" << get" << getUpperName()
190263508Sdim           << "()->getNameInfo().getAsString() << \"";
191234353Sdim      } else if (type == "IdentifierInfo *") {
192234353Sdim        OS << "\" << get" << getUpperName() << "()->getName() << \"";
193263508Sdim      } else if (type == "TypeSourceInfo *") {
194234353Sdim        OS << "\" << get" << getUpperName() << "().getAsString() << \"";
195234353Sdim      } else if (type == "SourceLocation") {
196234353Sdim        OS << "\" << get" << getUpperName() << "().getRawEncoding() << \"";
197234353Sdim      } else {
198234353Sdim        OS << "\" << get" << getUpperName() << "() << \"";
199234353Sdim      }
200234353Sdim    }
201249423Sdim    void writeDump(raw_ostream &OS) const {
202249423Sdim      if (type == "FunctionDecl *") {
203249423Sdim        OS << "    OS << \" \";\n";
204249423Sdim        OS << "    dumpBareDeclRef(SA->get" << getUpperName() << "());\n";
205249423Sdim      } else if (type == "IdentifierInfo *") {
206249423Sdim        OS << "    OS << \" \" << SA->get" << getUpperName()
207249423Sdim           << "()->getName();\n";
208263508Sdim      } else if (type == "TypeSourceInfo *") {
209249423Sdim        OS << "    OS << \" \" << SA->get" << getUpperName()
210249423Sdim           << "().getAsString();\n";
211249423Sdim      } else if (type == "SourceLocation") {
212249423Sdim        OS << "    OS << \" \";\n";
213249423Sdim        OS << "    SA->get" << getUpperName() << "().print(OS, *SM);\n";
214249423Sdim      } else if (type == "bool") {
215249423Sdim        OS << "    if (SA->get" << getUpperName() << "()) OS << \" "
216249423Sdim           << getUpperName() << "\";\n";
217249423Sdim      } else if (type == "int" || type == "unsigned") {
218249423Sdim        OS << "    OS << \" \" << SA->get" << getUpperName() << "();\n";
219249423Sdim      } else {
220249423Sdim        llvm_unreachable("Unknown SimpleArgument type!");
221249423Sdim      }
222249423Sdim    }
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    }
251234353Sdim    void writeTemplateInstantiationArgs(raw_ostream &OS) const {
252234353Sdim      OS << "A->get" << getUpperName() << "()";
253234353Sdim    }
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    }
263263508Sdim    void writeCtorDefaultInitializers(raw_ostream &OS) const {
264263508Sdim      OS << getLowerName() << "Length(0)," << getLowerName() << "(0)";
265263508Sdim    }
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    }
283234353Sdim    void writeValue(raw_ostream &OS) const {
284234353Sdim      OS << "\\\"\" << get" << getUpperName() << "() << \"\\\"";
285234353Sdim    }
286249423Sdim    void writeDump(raw_ostream &OS) const {
287249423Sdim      OS << "    OS << \" \\\"\" << SA->get" << getUpperName()
288249423Sdim         << "() << \"\\\"\";\n";
289249423Sdim    }
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    }
351234353Sdim    void writeTemplateInstantiationArgs(raw_ostream &OS) const {
352234353Sdim      // FIXME: move the definition in Sema::InstantiateAttrs to here.
353234353Sdim      // In the meantime, aligned attributes are cloned.
354234353Sdim    }
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    }
367263508Sdim    void writeCtorDefaultInitializers(raw_ostream &OS) const {
368263508Sdim      OS << "is" << getLowerName() << "Expr(false)";
369263508Sdim    }
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    }
400234353Sdim    void writeValue(raw_ostream &OS) const {
401239462Sdim      OS << "\";\n"
402239462Sdim         << "  " << getLowerName() << "Expr->printPretty(OS, 0, Policy);\n"
403239462Sdim         << "  OS << \"";
404234353Sdim    }
405249423Sdim    void writeDump(raw_ostream &OS) const {
406249423Sdim    }
407249423Sdim    void writeDumpChildren(raw_ostream &OS) const {
408249423Sdim      OS << "    if (SA->is" << getUpperName() << "Expr()) {\n";
409249423Sdim      OS << "      lastChild();\n";
410249423Sdim      OS << "      dumpStmt(SA->get" << getUpperName() << "Expr());\n";
411249423Sdim      OS << "    } else\n";
412249423Sdim      OS << "      dumpType(SA->get" << getUpperName()
413249423Sdim         << "Type()->getType());\n";
414249423Sdim    }
415249423Sdim    void writeHasChildren(raw_ostream &OS) const {
416249423Sdim      OS << "SA->is" << getUpperName() << "Expr()";
417249423Sdim    }
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"
442234353Sdim         << "    return " << getLowerName() << "Size;\n";
443226586Sdim      OS << "  }";
444226586Sdim    }
445226586Sdim    void writeCloneArgs(raw_ostream &OS) const {
446226586Sdim      OS << getLowerName() << ", " << getLowerName() << "Size";
447226586Sdim    }
448234353Sdim    void writeTemplateInstantiationArgs(raw_ostream &OS) const {
449234353Sdim      // This isn't elegant, but we have to go through public methods...
450234353Sdim      OS << "A->" << getLowerName() << "_begin(), "
451234353Sdim         << "A->" << getLowerName() << "_size()";
452234353Sdim    }
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    }
463263508Sdim    void writeCtorDefaultInitializers(raw_ostream &OS) const {
464263508Sdim      OS << getLowerName() << "Size(0), " << getLowerName() << "(0)";
465263508Sdim    }
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";
476249423Sdim      OS << "  SmallVector<" << type << ", 4> " << getLowerName()
477226586Sdim         << ";\n";
478226586Sdim      OS << "  " << getLowerName() << ".reserve(" << getLowerName()
479226586Sdim         << "Size);\n";
480263508Sdim      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    }
495234353Sdim    void writeValue(raw_ostream &OS) const {
496234353Sdim      OS << "\";\n";
497234353Sdim      OS << "  bool isFirst = true;\n"
498234353Sdim         << "  for (" << getAttrName() << "Attr::" << getLowerName()
499234353Sdim         << "_iterator i = " << getLowerName() << "_begin(), e = "
500234353Sdim         << getLowerName() << "_end(); i != e; ++i) {\n"
501234353Sdim         << "    if (isFirst) isFirst = false;\n"
502234353Sdim         << "    else OS << \", \";\n"
503234353Sdim         << "    OS << *i;\n"
504234353Sdim         << "  }\n";
505234353Sdim      OS << "  OS << \"";
506234353Sdim    }
507249423Sdim    void writeDump(raw_ostream &OS) const {
508249423Sdim      OS << "    for (" << getAttrName() << "Attr::" << getLowerName()
509249423Sdim         << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
510249423Sdim         << getLowerName() << "_end(); I != E; ++I)\n";
511249423Sdim      OS << "      OS << \" \" << *I;\n";
512249423Sdim    }
513226586Sdim  };
514226586Sdim
515226586Sdim  class EnumArgument : public Argument {
516226586Sdim    std::string type;
517249423Sdim    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")),
522249423Sdim        enums(getValueAsListOfStrings(Arg, "Enums")),
523249423Sdim        uniques(enums)
524249423Sdim    {
525249423Sdim      // Calculate the various enum values
526249423Sdim      std::sort(uniques.begin(), uniques.end());
527249423Sdim      uniques.erase(std::unique(uniques.begin(), uniques.end()), uniques.end());
528249423Sdim      // FIXME: Emit a proper error
529249423Sdim      assert(!uniques.empty());
530249423Sdim    }
531226586Sdim
532263508Sdim    bool isEnumArg() const { return true; }
533263508Sdim
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    }
542234353Sdim    void writeTemplateInstantiationArgs(raw_ostream &OS) const {
543234353Sdim      OS << "A->get" << getUpperName() << "()";
544234353Sdim    }
545226586Sdim    void writeCtorInitializers(raw_ostream &OS) const {
546226586Sdim      OS << getLowerName() << "(" << getUpperName() << ")";
547226586Sdim    }
548263508Sdim    void writeCtorDefaultInitializers(raw_ostream &OS) const {
549263508Sdim      OS << getLowerName() << "(" << type << "(0))";
550263508Sdim    }
551226586Sdim    void writeCtorParameters(raw_ostream &OS) const {
552226586Sdim      OS << type << " " << getUpperName();
553226586Sdim    }
554226586Sdim    void writeDeclarations(raw_ostream &OS) const {
555249423Sdim      std::vector<StringRef>::const_iterator i = uniques.begin(),
556249423Sdim                                             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    }
580234353Sdim    void writeValue(raw_ostream &OS) const {
581234353Sdim      OS << "\" << get" << getUpperName() << "() << \"";
582234353Sdim    }
583249423Sdim    void writeDump(raw_ostream &OS) const {
584249423Sdim      OS << "    switch(SA->get" << getUpperName() << "()) {\n";
585249423Sdim      for (std::vector<StringRef>::const_iterator I = uniques.begin(),
586249423Sdim           E = uniques.end(); I != E; ++I) {
587249423Sdim        OS << "    case " << getAttrName() << "Attr::" << *I << ":\n";
588249423Sdim        OS << "      OS << \" " << *I << "\";\n";
589249423Sdim        OS << "      break;\n";
590249423Sdim      }
591249423Sdim      OS << "    }\n";
592249423Sdim    }
593263508Sdim
594263508Sdim    void writeConversion(raw_ostream &OS) const {
595263508Sdim      OS << "  static bool ConvertStrTo" << type << "(StringRef Val, ";
596263508Sdim      OS << type << " &Out) {\n";
597263508Sdim      OS << "    Optional<" << type << "> R = llvm::StringSwitch<Optional<";
598263508Sdim      OS << type << "> >(Val)\n";
599263508Sdim      for (size_t I = 0; I < enums.size(); ++I) {
600263508Sdim        OS << "      .Case(\"" << values[I] << "\", ";
601263508Sdim        OS << getAttrName() << "Attr::" << enums[I] << ")\n";
602263508Sdim      }
603263508Sdim      OS << "      .Default(Optional<" << type << ">());\n";
604263508Sdim      OS << "    if (R) {\n";
605263508Sdim      OS << "      Out = *R;\n      return true;\n    }\n";
606263508Sdim      OS << "    return false;\n";
607263508Sdim      OS << "  }\n";
608263508Sdim    }
609226586Sdim  };
610263508Sdim
611263508Sdim  class VariadicEnumArgument: public VariadicArgument {
612263508Sdim    std::string type, QualifiedTypeName;
613263508Sdim    std::vector<StringRef> values, enums, uniques;
614263508Sdim  public:
615263508Sdim    VariadicEnumArgument(Record &Arg, StringRef Attr)
616263508Sdim      : VariadicArgument(Arg, Attr, Arg.getValueAsString("Type")),
617263508Sdim        type(Arg.getValueAsString("Type")),
618263508Sdim        values(getValueAsListOfStrings(Arg, "Values")),
619263508Sdim        enums(getValueAsListOfStrings(Arg, "Enums")),
620263508Sdim        uniques(enums)
621263508Sdim    {
622263508Sdim      // Calculate the various enum values
623263508Sdim      std::sort(uniques.begin(), uniques.end());
624263508Sdim      uniques.erase(std::unique(uniques.begin(), uniques.end()), uniques.end());
625263508Sdim
626263508Sdim      QualifiedTypeName = getAttrName().str() + "Attr::" + type;
627263508Sdim
628263508Sdim      // FIXME: Emit a proper error
629263508Sdim      assert(!uniques.empty());
630263508Sdim    }
631226586Sdim
632263508Sdim    bool isVariadicEnumArg() const { return true; }
633263508Sdim
634263508Sdim    void writeDeclarations(raw_ostream &OS) const {
635263508Sdim      std::vector<StringRef>::const_iterator i = uniques.begin(),
636263508Sdim                                             e = uniques.end();
637263508Sdim      // The last one needs to not have a comma.
638263508Sdim      --e;
639263508Sdim
640263508Sdim      OS << "public:\n";
641263508Sdim      OS << "  enum " << type << " {\n";
642263508Sdim      for (; i != e; ++i)
643263508Sdim        OS << "    " << *i << ",\n";
644263508Sdim      OS << "    " << *e << "\n";
645263508Sdim      OS << "  };\n";
646263508Sdim      OS << "private:\n";
647263508Sdim
648263508Sdim      VariadicArgument::writeDeclarations(OS);
649263508Sdim    }
650263508Sdim    void writeDump(raw_ostream &OS) const {
651263508Sdim      OS << "    for (" << getAttrName() << "Attr::" << getLowerName()
652263508Sdim         << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
653263508Sdim         << getLowerName() << "_end(); I != E; ++I) {\n";
654263508Sdim      OS << "      switch(*I) {\n";
655263508Sdim      for (std::vector<StringRef>::const_iterator UI = uniques.begin(),
656263508Sdim           UE = uniques.end(); UI != UE; ++UI) {
657263508Sdim        OS << "    case " << getAttrName() << "Attr::" << *UI << ":\n";
658263508Sdim        OS << "      OS << \" " << *UI << "\";\n";
659263508Sdim        OS << "      break;\n";
660263508Sdim      }
661263508Sdim      OS << "      }\n";
662263508Sdim      OS << "    }\n";
663263508Sdim    }
664263508Sdim    void writePCHReadDecls(raw_ostream &OS) const {
665263508Sdim      OS << "    unsigned " << getLowerName() << "Size = Record[Idx++];\n";
666263508Sdim      OS << "    SmallVector<" << QualifiedTypeName << ", 4> " << getLowerName()
667263508Sdim         << ";\n";
668263508Sdim      OS << "    " << getLowerName() << ".reserve(" << getLowerName()
669263508Sdim         << "Size);\n";
670263508Sdim      OS << "    for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
671263508Sdim      OS << "      " << getLowerName() << ".push_back(" << "static_cast<"
672263508Sdim         << QualifiedTypeName << ">(Record[Idx++]));\n";
673263508Sdim    }
674263508Sdim    void writePCHWrite(raw_ostream &OS) const{
675263508Sdim      OS << "    Record.push_back(SA->" << getLowerName() << "_size());\n";
676263508Sdim      OS << "    for (" << getAttrName() << "Attr::" << getLowerName()
677263508Sdim         << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
678263508Sdim         << getLowerName() << "_end(); i != e; ++i)\n";
679263508Sdim      OS << "      " << WritePCHRecord(QualifiedTypeName, "(*i)");
680263508Sdim    }
681263508Sdim    void writeConversion(raw_ostream &OS) const {
682263508Sdim      OS << "  static bool ConvertStrTo" << type << "(StringRef Val, ";
683263508Sdim      OS << type << " &Out) {\n";
684263508Sdim      OS << "    Optional<" << type << "> R = llvm::StringSwitch<Optional<";
685263508Sdim      OS << type << "> >(Val)\n";
686263508Sdim      for (size_t I = 0; I < enums.size(); ++I) {
687263508Sdim        OS << "      .Case(\"" << values[I] << "\", ";
688263508Sdim        OS << getAttrName() << "Attr::" << enums[I] << ")\n";
689263508Sdim      }
690263508Sdim      OS << "      .Default(Optional<" << type << ">());\n";
691263508Sdim      OS << "    if (R) {\n";
692263508Sdim      OS << "      Out = *R;\n      return true;\n    }\n";
693263508Sdim      OS << "    return false;\n";
694263508Sdim      OS << "  }\n";
695263508Sdim    }
696263508Sdim  };
697263508Sdim
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    }
716234353Sdim    void writeTemplateInstantiationArgs(raw_ostream &OS) const {
717234353Sdim      OS << "A->get" << getUpperName() << "()";
718234353Sdim    }
719226586Sdim    void writeCtorBody(raw_ostream &OS) const {
720226586Sdim    }
721226586Sdim    void writeCtorInitializers(raw_ostream &OS) const {
722226586Sdim      OS << getLowerName() << "(" << getUpperName() << ")";
723226586Sdim    }
724263508Sdim    void writeCtorDefaultInitializers(raw_ostream &OS) const {
725263508Sdim      OS << getLowerName() << "()";
726263508Sdim    }
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    }
743234353Sdim    void writeValue(raw_ostream &OS) const {
744234353Sdim      OS << getLowerName() << "=\" << get" << getUpperName() << "() << \"";
745234353Sdim    }
746249423Sdim    void writeDump(raw_ostream &OS) const {
747249423Sdim      OS << "    OS << \" \" << SA->get" << getUpperName() << "();\n";
748249423Sdim    }
749226586Sdim  };
750234353Sdim
751234353Sdim  class ExprArgument : public SimpleArgument {
752234353Sdim  public:
753234353Sdim    ExprArgument(Record &Arg, StringRef Attr)
754234353Sdim      : SimpleArgument(Arg, Attr, "Expr *")
755234353Sdim    {}
756234353Sdim
757234353Sdim    void writeTemplateInstantiationArgs(raw_ostream &OS) const {
758234353Sdim      OS << "tempInst" << getUpperName();
759234353Sdim    }
760234353Sdim
761234353Sdim    void writeTemplateInstantiation(raw_ostream &OS) const {
762234353Sdim      OS << "      " << getType() << " tempInst" << getUpperName() << ";\n";
763234353Sdim      OS << "      {\n";
764234353Sdim      OS << "        EnterExpressionEvaluationContext "
765234353Sdim         << "Unevaluated(S, Sema::Unevaluated);\n";
766234353Sdim      OS << "        ExprResult " << "Result = S.SubstExpr("
767234353Sdim         << "A->get" << getUpperName() << "(), TemplateArgs);\n";
768234353Sdim      OS << "        tempInst" << getUpperName() << " = "
769234353Sdim         << "Result.takeAs<Expr>();\n";
770234353Sdim      OS << "      }\n";
771234353Sdim    }
772249423Sdim
773249423Sdim    void writeDump(raw_ostream &OS) const {
774249423Sdim    }
775249423Sdim
776249423Sdim    void writeDumpChildren(raw_ostream &OS) const {
777249423Sdim      OS << "    lastChild();\n";
778249423Sdim      OS << "    dumpStmt(SA->get" << getUpperName() << "());\n";
779249423Sdim    }
780249423Sdim    void writeHasChildren(raw_ostream &OS) const { OS << "true"; }
781234353Sdim  };
782234353Sdim
783234353Sdim  class VariadicExprArgument : public VariadicArgument {
784234353Sdim  public:
785234353Sdim    VariadicExprArgument(Record &Arg, StringRef Attr)
786234353Sdim      : VariadicArgument(Arg, Attr, "Expr *")
787234353Sdim    {}
788234353Sdim
789234353Sdim    void writeTemplateInstantiationArgs(raw_ostream &OS) const {
790234353Sdim      OS << "tempInst" << getUpperName() << ", "
791234353Sdim         << "A->" << getLowerName() << "_size()";
792234353Sdim    }
793234353Sdim
794234353Sdim    void writeTemplateInstantiation(raw_ostream &OS) const {
795234353Sdim      OS << "      " << getType() << " *tempInst" << getUpperName()
796234353Sdim         << " = new (C, 16) " << getType()
797234353Sdim         << "[A->" << getLowerName() << "_size()];\n";
798234353Sdim      OS << "      {\n";
799234353Sdim      OS << "        EnterExpressionEvaluationContext "
800234353Sdim         << "Unevaluated(S, Sema::Unevaluated);\n";
801234353Sdim      OS << "        " << getType() << " *TI = tempInst" << getUpperName()
802234353Sdim         << ";\n";
803234353Sdim      OS << "        " << getType() << " *I = A->" << getLowerName()
804234353Sdim         << "_begin();\n";
805234353Sdim      OS << "        " << getType() << " *E = A->" << getLowerName()
806234353Sdim         << "_end();\n";
807234353Sdim      OS << "        for (; I != E; ++I, ++TI) {\n";
808234353Sdim      OS << "          ExprResult Result = S.SubstExpr(*I, TemplateArgs);\n";
809234353Sdim      OS << "          *TI = Result.takeAs<Expr>();\n";
810234353Sdim      OS << "        }\n";
811234353Sdim      OS << "      }\n";
812234353Sdim    }
813249423Sdim
814249423Sdim    void writeDump(raw_ostream &OS) const {
815249423Sdim    }
816249423Sdim
817249423Sdim    void writeDumpChildren(raw_ostream &OS) const {
818249423Sdim      OS << "    for (" << getAttrName() << "Attr::" << getLowerName()
819249423Sdim         << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
820249423Sdim         << getLowerName() << "_end(); I != E; ++I) {\n";
821249423Sdim      OS << "      if (I + 1 == E)\n";
822249423Sdim      OS << "        lastChild();\n";
823249423Sdim      OS << "      dumpStmt(*I);\n";
824249423Sdim      OS << "    }\n";
825249423Sdim    }
826249423Sdim
827249423Sdim    void writeHasChildren(raw_ostream &OS) const {
828249423Sdim      OS << "SA->" << getLowerName() << "_begin() != "
829249423Sdim         << "SA->" << getLowerName() << "_end()";
830249423Sdim    }
831234353Sdim  };
832263508Sdim
833263508Sdim  class TypeArgument : public SimpleArgument {
834263508Sdim  public:
835263508Sdim    TypeArgument(Record &Arg, StringRef Attr)
836263508Sdim      : SimpleArgument(Arg, Attr, "TypeSourceInfo *")
837263508Sdim    {}
838263508Sdim
839263508Sdim    void writeAccessors(raw_ostream &OS) const {
840263508Sdim      OS << "  QualType get" << getUpperName() << "() const {\n";
841263508Sdim      OS << "    return " << getLowerName() << "->getType();\n";
842263508Sdim      OS << "  }";
843263508Sdim      OS << "  " << getType() << " get" << getUpperName() << "Loc() const {\n";
844263508Sdim      OS << "    return " << getLowerName() << ";\n";
845263508Sdim      OS << "  }";
846263508Sdim    }
847263508Sdim    void writeTemplateInstantiationArgs(raw_ostream &OS) const {
848263508Sdim      OS << "A->get" << getUpperName() << "Loc()";
849263508Sdim    }
850263508Sdim    void writePCHWrite(raw_ostream &OS) const {
851263508Sdim      OS << "    " << WritePCHRecord(
852263508Sdim          getType(), "SA->get" + std::string(getUpperName()) + "Loc()");
853263508Sdim    }
854263508Sdim  };
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);
867234353Sdim  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);
876263508Sdim  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");
883263508Sdim  else if (ArgName == "VariadicEnumArgument")
884263508Sdim    Ptr = new VariadicEnumArgument(Arg, Attr);
885226586Sdim  else if (ArgName == "VariadicExprArgument")
886234353Sdim    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  }
899263508Sdim
900263508Sdim  if (Ptr && Arg.getValueAsBit("Optional"))
901263508Sdim    Ptr->setOptional(true);
902263508Sdim
903226586Sdim  return Ptr;
904226586Sdim}
905226586Sdim
906234353Sdimstatic void writeAvailabilityValue(raw_ostream &OS) {
907234353Sdim  OS << "\" << getPlatform()->getName();\n"
908234353Sdim     << "  if (!getIntroduced().empty()) OS << \", introduced=\" << getIntroduced();\n"
909234353Sdim     << "  if (!getDeprecated().empty()) OS << \", deprecated=\" << getDeprecated();\n"
910234353Sdim     << "  if (!getObsoleted().empty()) OS << \", obsoleted=\" << getObsoleted();\n"
911234353Sdim     << "  if (getUnavailable()) OS << \", unavailable\";\n"
912234353Sdim     << "  OS << \"";
913234353Sdim}
914234353Sdim
915249423Sdimstatic void writePrettyPrintFunction(Record &R, std::vector<Argument*> &Args,
916249423Sdim                                     raw_ostream &OS) {
917249423Sdim  std::vector<Record*> Spellings = R.getValueAsListOfDefs("Spellings");
918249423Sdim
919249423Sdim  OS << "void " << R.getName() << "Attr::printPretty("
920249423Sdim    << "raw_ostream &OS, const PrintingPolicy &Policy) const {\n";
921249423Sdim
922249423Sdim  if (Spellings.size() == 0) {
923249423Sdim    OS << "}\n\n";
924249423Sdim    return;
925249423Sdim  }
926249423Sdim
927249423Sdim  OS <<
928249423Sdim    "  switch (SpellingListIndex) {\n"
929249423Sdim    "  default:\n"
930249423Sdim    "    llvm_unreachable(\"Unknown attribute spelling!\");\n"
931249423Sdim    "    break;\n";
932249423Sdim
933249423Sdim  for (unsigned I = 0; I < Spellings.size(); ++ I) {
934249423Sdim    llvm::SmallString<16> Prefix;
935249423Sdim    llvm::SmallString<8> Suffix;
936249423Sdim    // The actual spelling of the name and namespace (if applicable)
937249423Sdim    // of an attribute without considering prefix and suffix.
938249423Sdim    llvm::SmallString<64> Spelling;
939249423Sdim    std::string Name = Spellings[I]->getValueAsString("Name");
940249423Sdim    std::string Variety = Spellings[I]->getValueAsString("Variety");
941249423Sdim
942249423Sdim    if (Variety == "GNU") {
943249423Sdim      Prefix = " __attribute__((";
944249423Sdim      Suffix = "))";
945249423Sdim    } else if (Variety == "CXX11") {
946249423Sdim      Prefix = " [[";
947249423Sdim      Suffix = "]]";
948249423Sdim      std::string Namespace = Spellings[I]->getValueAsString("Namespace");
949249423Sdim      if (Namespace != "") {
950249423Sdim        Spelling += Namespace;
951249423Sdim        Spelling += "::";
952249423Sdim      }
953249423Sdim    } else if (Variety == "Declspec") {
954249423Sdim      Prefix = " __declspec(";
955249423Sdim      Suffix = ")";
956249423Sdim    } else if (Variety == "Keyword") {
957249423Sdim      Prefix = " ";
958249423Sdim      Suffix = "";
959249423Sdim    } else {
960249423Sdim      llvm_unreachable("Unknown attribute syntax variety!");
961249423Sdim    }
962249423Sdim
963249423Sdim    Spelling += Name;
964249423Sdim
965249423Sdim    OS <<
966249423Sdim      "  case " << I << " : {\n"
967249423Sdim      "    OS << \"" + Prefix.str() + Spelling.str();
968249423Sdim
969249423Sdim    if (Args.size()) OS << "(";
970249423Sdim    if (Spelling == "availability") {
971249423Sdim      writeAvailabilityValue(OS);
972249423Sdim    } else {
973249423Sdim      for (std::vector<Argument*>::const_iterator I = Args.begin(),
974249423Sdim           E = Args.end(); I != E; ++ I) {
975249423Sdim        if (I != Args.begin()) OS << ", ";
976249423Sdim        (*I)->writeValue(OS);
977249423Sdim      }
978249423Sdim    }
979249423Sdim
980249423Sdim    if (Args.size()) OS << ")";
981249423Sdim    OS << Suffix.str() + "\";\n";
982249423Sdim
983249423Sdim    OS <<
984249423Sdim      "    break;\n"
985249423Sdim      "  }\n";
986249423Sdim  }
987249423Sdim
988249423Sdim  // End of the switch statement.
989249423Sdim  OS << "}\n";
990249423Sdim  // End of the print function.
991249423Sdim  OS << "}\n\n";
992249423Sdim}
993249423Sdim
994249423Sdim/// \brief Return the index of a spelling in a spelling list.
995249423Sdimstatic unsigned getSpellingListIndex(const std::vector<Record*> &SpellingList,
996249423Sdim                                     const Record &Spelling) {
997249423Sdim  assert(SpellingList.size() && "Spelling list is empty!");
998249423Sdim
999249423Sdim  for (unsigned Index = 0; Index < SpellingList.size(); ++Index) {
1000249423Sdim    Record *S = SpellingList[Index];
1001249423Sdim    if (S->getValueAsString("Variety") != Spelling.getValueAsString("Variety"))
1002249423Sdim      continue;
1003249423Sdim    if (S->getValueAsString("Variety") == "CXX11" &&
1004249423Sdim        S->getValueAsString("Namespace") !=
1005249423Sdim        Spelling.getValueAsString("Namespace"))
1006249423Sdim      continue;
1007249423Sdim    if (S->getValueAsString("Name") != Spelling.getValueAsString("Name"))
1008249423Sdim      continue;
1009249423Sdim
1010249423Sdim    return Index;
1011249423Sdim  }
1012249423Sdim
1013249423Sdim  llvm_unreachable("Unknown spelling!");
1014249423Sdim}
1015249423Sdim
1016249423Sdimstatic void writeAttrAccessorDefinition(Record &R, raw_ostream &OS) {
1017249423Sdim  std::vector<Record*> Accessors = R.getValueAsListOfDefs("Accessors");
1018249423Sdim  for (std::vector<Record*>::const_iterator I = Accessors.begin(),
1019249423Sdim       E = Accessors.end(); I != E; ++I) {
1020249423Sdim    Record *Accessor = *I;
1021249423Sdim    std::string Name = Accessor->getValueAsString("Name");
1022249423Sdim    std::vector<Record*> Spellings = Accessor->getValueAsListOfDefs(
1023249423Sdim      "Spellings");
1024249423Sdim    std::vector<Record*> SpellingList = R.getValueAsListOfDefs("Spellings");
1025249423Sdim    assert(SpellingList.size() &&
1026249423Sdim           "Attribute with empty spelling list can't have accessors!");
1027249423Sdim
1028249423Sdim    OS << "  bool " << Name << "() const { return SpellingListIndex == ";
1029249423Sdim    for (unsigned Index = 0; Index < Spellings.size(); ++Index) {
1030249423Sdim      OS << getSpellingListIndex(SpellingList, *Spellings[Index]);
1031249423Sdim      if (Index != Spellings.size() -1)
1032249423Sdim        OS << " ||\n    SpellingListIndex == ";
1033249423Sdim      else
1034249423Sdim        OS << "; }\n";
1035249423Sdim    }
1036249423Sdim  }
1037249423Sdim}
1038249423Sdim
1039239462Sdimnamespace clang {
1040239462Sdim
1041239462Sdim// Emits the class definitions for attributes.
1042239462Sdimvoid EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
1043249423Sdim  emitSourceFileHeader("Attribute classes' definitions", OS);
1044249423Sdim
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;
1053239462Sdim
1054239462Sdim    if (!R.getValueAsBit("ASTNode"))
1055239462Sdim      continue;
1056239462Sdim
1057263508Sdim    const std::vector<Record *> Supers = R.getSuperClasses();
1058263508Sdim    assert(!Supers.empty() && "Forgot to specify a superclass for the attr");
1059263508Sdim    std::string SuperName;
1060263508Sdim    for (std::vector<Record *>::const_reverse_iterator I = Supers.rbegin(),
1061263508Sdim         E = Supers.rend(); I != E; ++I) {
1062263508Sdim      const Record &R = **I;
1063263508Sdim      if (R.getName() != "TargetSpecificAttr" && SuperName.empty())
1064263508Sdim        SuperName = R.getName();
1065263508Sdim    }
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
1091263508Sdim    bool HasOpt = false;
1092226586Sdim    for (ai = Args.begin(); ai != ae; ++ai) {
1093226586Sdim      OS << "              , ";
1094226586Sdim      (*ai)->writeCtorParameters(OS);
1095226586Sdim      OS << "\n";
1096263508Sdim      if ((*ai)->isOptional())
1097263508Sdim        HasOpt = true;
1098226586Sdim    }
1099249423Sdim
1100249423Sdim    OS << "              , ";
1101249423Sdim    OS << "unsigned SI = 0\n";
1102249423Sdim
1103226586Sdim    OS << "             )\n";
1104249423Sdim    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
1120263508Sdim    // If there are optional arguments, write out a constructor that elides the
1121263508Sdim    // optional arguments as well.
1122263508Sdim    if (HasOpt) {
1123263508Sdim      OS << "  " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
1124263508Sdim      for (ai = Args.begin(); ai != ae; ++ai) {
1125263508Sdim        if (!(*ai)->isOptional()) {
1126263508Sdim          OS << "              , ";
1127263508Sdim          (*ai)->writeCtorParameters(OS);
1128263508Sdim          OS << "\n";
1129263508Sdim        }
1130263508Sdim      }
1131263508Sdim
1132263508Sdim      OS << "              , ";
1133263508Sdim      OS << "unsigned SI = 0\n";
1134263508Sdim
1135263508Sdim      OS << "             )\n";
1136263508Sdim      OS << "    : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n";
1137263508Sdim
1138263508Sdim      for (ai = Args.begin(); ai != ae; ++ai) {
1139263508Sdim        OS << "              , ";
1140263508Sdim        (*ai)->writeCtorDefaultInitializers(OS);
1141263508Sdim        OS << "\n";
1142263508Sdim      }
1143263508Sdim
1144263508Sdim      OS << "  {\n";
1145263508Sdim
1146263508Sdim      for (ai = Args.begin(); ai != ae; ++ai) {
1147263508Sdim        if (!(*ai)->isOptional()) {
1148263508Sdim          (*ai)->writeCtorBody(OS);
1149263508Sdim          OS << "\n";
1150263508Sdim        }
1151263508Sdim      }
1152263508Sdim      OS << "  }\n\n";
1153263508Sdim    }
1154263508Sdim
1155226586Sdim    OS << "  virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n";
1156249423Sdim    OS << "  virtual void printPretty(raw_ostream &OS,\n"
1157239462Sdim       << "                           const PrintingPolicy &Policy) const;\n";
1158226586Sdim
1159249423Sdim    writeAttrAccessorDefinition(R, OS);
1160249423Sdim
1161226586Sdim    for (ai = Args.begin(); ai != ae; ++ai) {
1162226586Sdim      (*ai)->writeAccessors(OS);
1163226586Sdim      OS << "\n\n";
1164263508Sdim
1165263508Sdim      if ((*ai)->isEnumArg()) {
1166263508Sdim        EnumArgument *EA = (EnumArgument *)*ai;
1167263508Sdim        EA->writeConversion(OS);
1168263508Sdim      } else if ((*ai)->isVariadicEnumArg()) {
1169263508Sdim        VariadicEnumArgument *VEA = (VariadicEnumArgument *)*ai;
1170263508Sdim        VEA->writeConversion(OS);
1171263508Sdim      }
1172226586Sdim    }
1173226586Sdim
1174234353Sdim    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";
1179234353Sdim
1180234353Sdim    bool LateParsed = R.getValueAsBit("LateParsed");
1181234353Sdim    OS << "  virtual bool isLateParsed() const { return "
1182234353Sdim       << LateParsed << "; }\n";
1183234353Sdim
1184226586Sdim    OS << "};\n\n";
1185226586Sdim  }
1186226586Sdim
1187226586Sdim  OS << "#endif\n";
1188226586Sdim}
1189226586Sdim
1190263508Sdimstatic bool isIdentifierArgument(Record *Arg) {
1191263508Sdim  return !Arg->getSuperClasses().empty() &&
1192263508Sdim         llvm::StringSwitch<bool>(Arg->getSuperClasses().back()->getName())
1193263508Sdim             .Case("IdentifierArgument", true)
1194263508Sdim             .Case("EnumArgument", true)
1195263508Sdim             .Default(false);
1196263508Sdim}
1197263508Sdim
1198263508Sdim/// \brief Emits the first-argument-is-type property for attributes.
1199263508Sdimvoid EmitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) {
1200263508Sdim  emitSourceFileHeader("llvm::StringSwitch code to match attributes with a "
1201263508Sdim                       "type argument", OS);
1202263508Sdim
1203263508Sdim  std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
1204263508Sdim
1205263508Sdim  for (std::vector<Record *>::iterator I = Attrs.begin(), E = Attrs.end();
1206263508Sdim       I != E; ++I) {
1207263508Sdim    Record &Attr = **I;
1208263508Sdim
1209263508Sdim    // Determine whether the first argument is a type.
1210263508Sdim    std::vector<Record *> Args = Attr.getValueAsListOfDefs("Args");
1211263508Sdim    if (Args.empty())
1212263508Sdim      continue;
1213263508Sdim
1214263508Sdim    if (Args[0]->getSuperClasses().back()->getName() != "TypeArgument")
1215263508Sdim      continue;
1216263508Sdim
1217263508Sdim    // All these spellings take a single type argument.
1218263508Sdim    std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
1219263508Sdim    std::set<std::string> Emitted;
1220263508Sdim    for (std::vector<Record*>::const_iterator I = Spellings.begin(),
1221263508Sdim         E = Spellings.end(); I != E; ++I) {
1222263508Sdim      if (Emitted.insert((*I)->getValueAsString("Name")).second)
1223263508Sdim        OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", "
1224263508Sdim           << "true" << ")\n";
1225263508Sdim    }
1226263508Sdim  }
1227263508Sdim}
1228263508Sdim
1229263508Sdim// Emits the first-argument-is-identifier property for attributes.
1230263508Sdimvoid EmitClangAttrIdentifierArgList(RecordKeeper &Records, raw_ostream &OS) {
1231251662Sdim  emitSourceFileHeader("llvm::StringSwitch code to match attributes with "
1232263508Sdim                       "an identifier argument", OS);
1233251662Sdim
1234251662Sdim  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1235251662Sdim
1236251662Sdim  for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1237251662Sdim       I != E; ++I) {
1238251662Sdim    Record &Attr = **I;
1239251662Sdim
1240263508Sdim    // Determine whether the first argument is an identifier.
1241251662Sdim    std::vector<Record *> Args = Attr.getValueAsListOfDefs("Args");
1242263508Sdim    if (Args.empty() || !isIdentifierArgument(Args[0]))
1243251662Sdim      continue;
1244251662Sdim
1245263508Sdim    // All these spellings take an identifier argument.
1246251662Sdim    std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
1247263508Sdim    std::set<std::string> Emitted;
1248251662Sdim    for (std::vector<Record*>::const_iterator I = Spellings.begin(),
1249251662Sdim         E = Spellings.end(); I != E; ++I) {
1250263508Sdim      if (Emitted.insert((*I)->getValueAsString("Name")).second)
1251263508Sdim        OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", "
1252263508Sdim           << "true" << ")\n";
1253251662Sdim    }
1254251662Sdim  }
1255251662Sdim}
1256251662Sdim
1257239462Sdim// Emits the class method definitions for attributes.
1258239462Sdimvoid EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
1259249423Sdim  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;
1267239462Sdim
1268239462Sdim    if (!R.getValueAsBit("ASTNode"))
1269239462Sdim      continue;
1270239462Sdim
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    }
1286249423Sdim    OS << ", getSpellingListIndex());\n}\n\n";
1287234353Sdim
1288249423Sdim    writePrettyPrintFunction(R, Args, OS);
1289226586Sdim  }
1290226586Sdim}
1291226586Sdim
1292239462Sdim} // end namespace clang
1293239462Sdim
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.
1300239462Sdim    for(--e; i != e; ++i) {
1301239462Sdim      if (!(*i)->getValueAsBit("ASTNode"))
1302239462Sdim        continue;
1303239462Sdim
1304226586Sdim      OS << Class << "(" << (*i)->getName() << ")\n";
1305239462Sdim    }
1306226586Sdim
1307226586Sdim    OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n";
1308226586Sdim  }
1309226586Sdim}
1310226586Sdim
1311239462Sdimnamespace clang {
1312239462Sdim
1313239462Sdim// Emits the enumeration list for attributes.
1314239462Sdimvoid EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) {
1315249423Sdim  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
1338263508Sdim  OS << "#ifndef MS_INHERITANCE_ATTR\n";
1339263508Sdim  OS << "#define MS_INHERITANCE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n";
1340249423Sdim  OS << "#endif\n\n";
1341249423Sdim
1342263508Sdim  OS << "#ifndef LAST_MS_INHERITANCE_ATTR\n";
1343263508Sdim  OS << "#define LAST_MS_INHERITANCE_ATTR(NAME)"
1344263508Sdim        " MS_INHERITANCE_ATTR(NAME)\n";
1345249423Sdim  OS << "#endif\n\n";
1346249423Sdim
1347226586Sdim  Record *InhClass = Records.getClass("InheritableAttr");
1348226586Sdim  Record *InhParamClass = Records.getClass("InheritableParamAttr");
1349249423Sdim  Record *MSInheritanceClass = Records.getClass("MSInheritanceAttr");
1350226586Sdim  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
1351249423Sdim                       NonInhAttrs, InhAttrs, InhParamAttrs, MSInhAttrs;
1352226586Sdim  for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
1353226586Sdim       i != e; ++i) {
1354239462Sdim    if (!(*i)->getValueAsBit("ASTNode"))
1355239462Sdim      continue;
1356239462Sdim
1357226586Sdim    if ((*i)->isSubClassOf(InhParamClass))
1358226586Sdim      InhParamAttrs.push_back(*i);
1359249423Sdim    else if ((*i)->isSubClassOf(MSInheritanceClass))
1360249423Sdim      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);
1368263508Sdim  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";
1374263508Sdim  OS << "#undef MS_INHERITANCE_ATTR\n";
1375226586Sdim  OS << "#undef LAST_INHERITABLE_ATTR\n";
1376226586Sdim  OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n";
1377263508Sdim  OS << "#undef LAST_MS_INHERITANCE_ATTR\n";
1378226586Sdim  OS << "#undef ATTR\n";
1379226586Sdim}
1380226586Sdim
1381239462Sdim// Emits the code to read an attribute from a precompiled header.
1382239462Sdimvoid EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) {
1383249423Sdim  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;
1398239462Sdim    if (!R.getValueAsBit("ASTNode"))
1399239462Sdim      continue;
1400239462Sdim
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
1425239462Sdim// Emits the code to write an attribute to a precompiled header.
1426239462Sdimvoid EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) {
1427249423Sdim  emitSourceFileHeader("Attribute serialization code", OS);
1428249423Sdim
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;
1439239462Sdim    if (!R.getValueAsBit("ASTNode"))
1440239462Sdim      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
1456239462Sdim// Emits the list of spellings for attributes.
1457239462Sdimvoid EmitClangAttrSpellingList(RecordKeeper &Records, raw_ostream &OS) {
1458249423Sdim  emitSourceFileHeader("llvm::StringSwitch code to match all known attributes",
1459249423Sdim                       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
1466239462Sdim    std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
1467226586Sdim
1468239462Sdim    for (std::vector<Record*>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) {
1469239462Sdim      OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", true)\n";
1470226586Sdim    }
1471226586Sdim  }
1472226586Sdim
1473226586Sdim}
1474226586Sdim
1475249423Sdimvoid EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) {
1476249423Sdim  emitSourceFileHeader("Code to translate different attribute spellings "
1477249423Sdim                       "into internal identifiers", OS);
1478249423Sdim
1479249423Sdim  OS <<
1480249423Sdim    "  unsigned Index = 0;\n"
1481249423Sdim    "  switch (AttrKind) {\n"
1482249423Sdim    "  default:\n"
1483249423Sdim    "    llvm_unreachable(\"Unknown attribute kind!\");\n"
1484249423Sdim    "    break;\n";
1485249423Sdim
1486249423Sdim  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1487249423Sdim  for (std::vector<Record*>::const_iterator I = Attrs.begin(), E = Attrs.end();
1488249423Sdim       I != E; ++I) {
1489249423Sdim    Record &R = **I;
1490249423Sdim    // We only care about attributes that participate in Sema checking, so
1491249423Sdim    // skip those attributes that are not able to make their way to Sema.
1492249423Sdim    if (!R.getValueAsBit("SemaHandler"))
1493249423Sdim      continue;
1494249423Sdim
1495249423Sdim    std::vector<Record*> Spellings = R.getValueAsListOfDefs("Spellings");
1496249423Sdim    // Each distinct spelling yields an attribute kind.
1497249423Sdim    if (R.getValueAsBit("DistinctSpellings")) {
1498249423Sdim      for (unsigned I = 0; I < Spellings.size(); ++ I) {
1499249423Sdim        OS <<
1500249423Sdim          "  case AT_" << Spellings[I]->getValueAsString("Name") << ": \n"
1501249423Sdim          "    Index = " << I << ";\n"
1502249423Sdim          "  break;\n";
1503249423Sdim      }
1504249423Sdim    } else {
1505249423Sdim      OS << "  case AT_" << R.getName() << " : {\n";
1506249423Sdim      for (unsigned I = 0; I < Spellings.size(); ++ I) {
1507249423Sdim        SmallString<16> Namespace;
1508249423Sdim        if (Spellings[I]->getValueAsString("Variety") == "CXX11")
1509249423Sdim          Namespace = Spellings[I]->getValueAsString("Namespace");
1510249423Sdim        else
1511249423Sdim          Namespace = "";
1512249423Sdim
1513249423Sdim        OS << "    if (Name == \""
1514249423Sdim          << Spellings[I]->getValueAsString("Name") << "\" && "
1515249423Sdim          << "SyntaxUsed == "
1516249423Sdim          << StringSwitch<unsigned>(Spellings[I]->getValueAsString("Variety"))
1517249423Sdim            .Case("GNU", 0)
1518249423Sdim            .Case("CXX11", 1)
1519249423Sdim            .Case("Declspec", 2)
1520249423Sdim            .Case("Keyword", 3)
1521249423Sdim            .Default(0)
1522249423Sdim          << " && Scope == \"" << Namespace << "\")\n"
1523249423Sdim          << "        return " << I << ";\n";
1524249423Sdim      }
1525249423Sdim
1526249423Sdim      OS << "    break;\n";
1527249423Sdim      OS << "  }\n";
1528249423Sdim    }
1529249423Sdim  }
1530249423Sdim
1531249423Sdim  OS << "  }\n";
1532249423Sdim  OS << "  return Index;\n";
1533249423Sdim}
1534249423Sdim
1535239462Sdim// Emits the LateParsed property for attributes.
1536239462Sdimvoid EmitClangAttrLateParsedList(RecordKeeper &Records, raw_ostream &OS) {
1537249423Sdim  emitSourceFileHeader("llvm::StringSwitch code to match late parsed "
1538249423Sdim                       "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) {
1549239462Sdim      std::vector<Record*> Spellings =
1550239462Sdim        Attr.getValueAsListOfDefs("Spellings");
1551226586Sdim
1552239462Sdim      // FIXME: Handle non-GNU attributes
1553239462Sdim      for (std::vector<Record*>::const_iterator I = Spellings.begin(),
1554226586Sdim           E = Spellings.end(); I != E; ++I) {
1555239462Sdim        if ((*I)->getValueAsString("Variety") != "GNU")
1556239462Sdim          continue;
1557239462Sdim        OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", "
1558239462Sdim           << LateParsed << ")\n";
1559226586Sdim      }
1560226586Sdim    }
1561226586Sdim  }
1562226586Sdim}
1563234353Sdim
1564239462Sdim// Emits code to instantiate dependent attributes on templates.
1565239462Sdimvoid EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) {
1566249423Sdim  emitSourceFileHeader("Template instantiation code for attributes", OS);
1567234353Sdim
1568234353Sdim  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1569234353Sdim
1570234353Sdim  OS << "namespace clang {\n"
1571234353Sdim     << "namespace sema {\n\n"
1572234353Sdim     << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, "
1573234353Sdim     << "Sema &S,\n"
1574234353Sdim     << "        const MultiLevelTemplateArgumentList &TemplateArgs) {\n"
1575234353Sdim     << "  switch (At->getKind()) {\n"
1576234353Sdim     << "    default:\n"
1577234353Sdim     << "      break;\n";
1578234353Sdim
1579234353Sdim  for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1580234353Sdim       I != E; ++I) {
1581234353Sdim    Record &R = **I;
1582239462Sdim    if (!R.getValueAsBit("ASTNode"))
1583239462Sdim      continue;
1584234353Sdim
1585234353Sdim    OS << "    case attr::" << R.getName() << ": {\n";
1586239462Sdim    bool ShouldClone = R.getValueAsBit("Clone");
1587239462Sdim
1588239462Sdim    if (!ShouldClone) {
1589239462Sdim      OS << "      return NULL;\n";
1590239462Sdim      OS << "    }\n";
1591239462Sdim      continue;
1592239462Sdim    }
1593239462Sdim
1594234353Sdim    OS << "      const " << R.getName() << "Attr *A = cast<"
1595234353Sdim       << R.getName() << "Attr>(At);\n";
1596234353Sdim    bool TDependent = R.getValueAsBit("TemplateDependent");
1597234353Sdim
1598234353Sdim    if (!TDependent) {
1599234353Sdim      OS << "      return A->clone(C);\n";
1600234353Sdim      OS << "    }\n";
1601234353Sdim      continue;
1602234353Sdim    }
1603234353Sdim
1604234353Sdim    std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
1605234353Sdim    std::vector<Argument*> Args;
1606234353Sdim    std::vector<Argument*>::iterator ai, ae;
1607234353Sdim    Args.reserve(ArgRecords.size());
1608234353Sdim
1609234353Sdim    for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
1610234353Sdim                                        re = ArgRecords.end();
1611234353Sdim         ri != re; ++ri) {
1612234353Sdim      Record &ArgRecord = **ri;
1613234353Sdim      Argument *Arg = createArgument(ArgRecord, R.getName());
1614234353Sdim      assert(Arg);
1615234353Sdim      Args.push_back(Arg);
1616234353Sdim    }
1617234353Sdim    ae = Args.end();
1618234353Sdim
1619234353Sdim    for (ai = Args.begin(); ai != ae; ++ai) {
1620234353Sdim      (*ai)->writeTemplateInstantiation(OS);
1621234353Sdim    }
1622234353Sdim    OS << "      return new (C) " << R.getName() << "Attr(A->getLocation(), C";
1623234353Sdim    for (ai = Args.begin(); ai != ae; ++ai) {
1624234353Sdim      OS << ", ";
1625234353Sdim      (*ai)->writeTemplateInstantiationArgs(OS);
1626234353Sdim    }
1627234353Sdim    OS << ");\n    }\n";
1628234353Sdim  }
1629234353Sdim  OS << "  } // end switch\n"
1630234353Sdim     << "  llvm_unreachable(\"Unknown attribute!\");\n"
1631234353Sdim     << "  return 0;\n"
1632234353Sdim     << "}\n\n"
1633234353Sdim     << "} // end namespace sema\n"
1634234353Sdim     << "} // end namespace clang\n";
1635234353Sdim}
1636234353Sdim
1637263508Sdimtypedef std::vector<std::pair<std::string, Record *> > ParsedAttrMap;
1638249423Sdim
1639263508Sdimstatic ParsedAttrMap getParsedAttrList(const RecordKeeper &Records) {
1640234353Sdim  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1641263508Sdim  ParsedAttrMap R;
1642234353Sdim  for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1643234353Sdim       I != E; ++I) {
1644234353Sdim    Record &Attr = **I;
1645234353Sdim
1646234353Sdim    bool SemaHandler = Attr.getValueAsBit("SemaHandler");
1647239462Sdim    bool DistinctSpellings = Attr.getValueAsBit("DistinctSpellings");
1648239462Sdim
1649234353Sdim    if (SemaHandler) {
1650239462Sdim      if (DistinctSpellings) {
1651239462Sdim        std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
1652239462Sdim
1653239462Sdim        for (std::vector<Record*>::const_iterator I = Spellings.begin(),
1654239462Sdim             E = Spellings.end(); I != E; ++I) {
1655239462Sdim          std::string AttrName = (*I)->getValueAsString("Name");
1656234353Sdim
1657239462Sdim          StringRef Spelling = NormalizeAttrName(AttrName);
1658263508Sdim          R.push_back(std::make_pair(Spelling.str(), &Attr));
1659239462Sdim        }
1660239462Sdim      } else {
1661239462Sdim        StringRef AttrName = Attr.getName();
1662234353Sdim        AttrName = NormalizeAttrName(AttrName);
1663263508Sdim        R.push_back(std::make_pair(AttrName.str(), *I));
1664234353Sdim      }
1665234353Sdim    }
1666234353Sdim  }
1667263508Sdim  return R;
1668234353Sdim}
1669234353Sdim
1670263508Sdim// Emits the list of parsed attributes.
1671263508Sdimvoid EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) {
1672263508Sdim  emitSourceFileHeader("List of all attributes that Clang recognizes", OS);
1673263508Sdim
1674263508Sdim  OS << "#ifndef PARSED_ATTR\n";
1675263508Sdim  OS << "#define PARSED_ATTR(NAME) NAME\n";
1676263508Sdim  OS << "#endif\n\n";
1677263508Sdim
1678263508Sdim  ParsedAttrMap Names = getParsedAttrList(Records);
1679263508Sdim  for (ParsedAttrMap::iterator I = Names.begin(), E = Names.end(); I != E;
1680263508Sdim       ++I) {
1681263508Sdim    OS << "PARSED_ATTR(" << I->first << ")\n";
1682263508Sdim  }
1683263508Sdim}
1684263508Sdim
1685263508Sdimstatic void emitArgInfo(const Record &R, raw_ostream &OS) {
1686263508Sdim  // This function will count the number of arguments specified for the
1687263508Sdim  // attribute and emit the number of required arguments followed by the
1688263508Sdim  // number of optional arguments.
1689263508Sdim  std::vector<Record *> Args = R.getValueAsListOfDefs("Args");
1690263508Sdim  unsigned ArgCount = 0, OptCount = 0;
1691263508Sdim  for (std::vector<Record *>::const_iterator I = Args.begin(), E = Args.end();
1692263508Sdim       I != E; ++I) {
1693263508Sdim    const Record &Arg = **I;
1694263508Sdim    Arg.getValueAsBit("Optional") ? ++OptCount : ++ArgCount;
1695263508Sdim  }
1696263508Sdim  OS << ArgCount << ", " << OptCount;
1697263508Sdim}
1698263508Sdim
1699263508Sdim/// Emits the parsed attribute helpers
1700263508Sdimvoid EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
1701263508Sdim  emitSourceFileHeader("Parsed attribute helpers", OS);
1702263508Sdim
1703263508Sdim  ParsedAttrMap Attrs = getParsedAttrList(Records);
1704263508Sdim
1705263508Sdim  OS << "static const ParsedAttrInfo AttrInfoMap[AttributeList::UnknownAttribute + 1] = {\n";
1706263508Sdim  for (ParsedAttrMap::iterator I = Attrs.begin(), E = Attrs.end(); I != E;
1707263508Sdim       ++I) {
1708263508Sdim    // We need to generate struct instances based off ParsedAttrInfo from
1709263508Sdim    // AttributeList.cpp.
1710263508Sdim    OS << "  { ";
1711263508Sdim    emitArgInfo(*I->second, OS);
1712263508Sdim    OS << ", " << I->second->getValueAsBit("HasCustomParsing");
1713263508Sdim    OS << " }";
1714263508Sdim
1715263508Sdim    if (I + 1 != E)
1716263508Sdim      OS << ",";
1717263508Sdim
1718263508Sdim    OS << "  // AT_" << I->first << "\n";
1719263508Sdim  }
1720263508Sdim  OS << "};\n\n";
1721263508Sdim}
1722263508Sdim
1723239462Sdim// Emits the kind list of parsed attributes
1724239462Sdimvoid EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
1725249423Sdim  emitSourceFileHeader("Attribute name matcher", OS);
1726249423Sdim
1727234353Sdim  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1728234353Sdim
1729239462Sdim  std::vector<StringMatcher::StringPair> Matches;
1730234353Sdim  for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1731234353Sdim       I != E; ++I) {
1732234353Sdim    Record &Attr = **I;
1733234353Sdim
1734234353Sdim    bool SemaHandler = Attr.getValueAsBit("SemaHandler");
1735239462Sdim    bool Ignored = Attr.getValueAsBit("Ignored");
1736239462Sdim    bool DistinctSpellings = Attr.getValueAsBit("DistinctSpellings");
1737239462Sdim    if (SemaHandler || Ignored) {
1738239462Sdim      std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
1739234353Sdim
1740239462Sdim      for (std::vector<Record*>::const_iterator I = Spellings.begin(),
1741234353Sdim           E = Spellings.end(); I != E; ++I) {
1742239462Sdim        std::string RawSpelling = (*I)->getValueAsString("Name");
1743239462Sdim        StringRef AttrName = NormalizeAttrName(DistinctSpellings
1744239462Sdim                                                 ? StringRef(RawSpelling)
1745239462Sdim                                                 : StringRef(Attr.getName()));
1746234353Sdim
1747239462Sdim        SmallString<64> Spelling;
1748239462Sdim        if ((*I)->getValueAsString("Variety") == "CXX11") {
1749239462Sdim          Spelling += (*I)->getValueAsString("Namespace");
1750239462Sdim          Spelling += "::";
1751239462Sdim        }
1752239462Sdim        Spelling += NormalizeAttrSpelling(RawSpelling);
1753239462Sdim
1754239462Sdim        if (SemaHandler)
1755239462Sdim          Matches.push_back(
1756239462Sdim            StringMatcher::StringPair(
1757239462Sdim              StringRef(Spelling),
1758239462Sdim              "return AttributeList::AT_" + AttrName.str() + ";"));
1759239462Sdim        else
1760239462Sdim          Matches.push_back(
1761239462Sdim            StringMatcher::StringPair(
1762239462Sdim              StringRef(Spelling),
1763239462Sdim              "return AttributeList::IgnoredAttribute;"));
1764234353Sdim      }
1765234353Sdim    }
1766234353Sdim  }
1767239462Sdim
1768239462Sdim  OS << "static AttributeList::Kind getAttrKind(StringRef Name) {\n";
1769239462Sdim  StringMatcher("Name", Matches, OS).Emit();
1770239462Sdim  OS << "return AttributeList::UnknownAttribute;\n"
1771239462Sdim     << "}\n";
1772234353Sdim}
1773234353Sdim
1774249423Sdim// Emits the code to dump an attribute.
1775249423Sdimvoid EmitClangAttrDump(RecordKeeper &Records, raw_ostream &OS) {
1776249423Sdim  emitSourceFileHeader("Attribute dumper", OS);
1777249423Sdim
1778249423Sdim  OS <<
1779249423Sdim    "  switch (A->getKind()) {\n"
1780249423Sdim    "  default:\n"
1781249423Sdim    "    llvm_unreachable(\"Unknown attribute kind!\");\n"
1782249423Sdim    "    break;\n";
1783249423Sdim  std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
1784249423Sdim  for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1785249423Sdim       I != E; ++I) {
1786249423Sdim    Record &R = **I;
1787249423Sdim    if (!R.getValueAsBit("ASTNode"))
1788249423Sdim      continue;
1789249423Sdim    OS << "  case attr::" << R.getName() << ": {\n";
1790249423Sdim    Args = R.getValueAsListOfDefs("Args");
1791249423Sdim    if (!Args.empty()) {
1792249423Sdim      OS << "    const " << R.getName() << "Attr *SA = cast<" << R.getName()
1793249423Sdim         << "Attr>(A);\n";
1794249423Sdim      for (std::vector<Record*>::iterator I = Args.begin(), E = Args.end();
1795249423Sdim           I != E; ++I)
1796249423Sdim        createArgument(**I, R.getName())->writeDump(OS);
1797249423Sdim
1798249423Sdim      // Code for detecting the last child.
1799249423Sdim      OS << "    bool OldMoreChildren = hasMoreChildren();\n";
1800249423Sdim      OS << "    bool MoreChildren = OldMoreChildren;\n";
1801249423Sdim
1802249423Sdim      for (std::vector<Record*>::iterator I = Args.begin(), E = Args.end();
1803249423Sdim           I != E; ++I) {
1804249423Sdim        // More code for detecting the last child.
1805249423Sdim        OS << "    MoreChildren = OldMoreChildren";
1806249423Sdim        for (std::vector<Record*>::iterator Next = I + 1; Next != E; ++Next) {
1807249423Sdim          OS << " || ";
1808249423Sdim          createArgument(**Next, R.getName())->writeHasChildren(OS);
1809249423Sdim        }
1810249423Sdim        OS << ";\n";
1811249423Sdim        OS << "    setMoreChildren(MoreChildren);\n";
1812249423Sdim
1813249423Sdim        createArgument(**I, R.getName())->writeDumpChildren(OS);
1814249423Sdim      }
1815249423Sdim
1816249423Sdim      // Reset the last child.
1817249423Sdim      OS << "    setMoreChildren(OldMoreChildren);\n";
1818249423Sdim    }
1819249423Sdim    OS <<
1820249423Sdim      "    break;\n"
1821249423Sdim      "  }\n";
1822249423Sdim  }
1823249423Sdim  OS << "  }\n";
1824249423Sdim}
1825249423Sdim
1826239462Sdim} // end namespace clang
1827