blob: 26c5faf5932cc63f7baca6783aef08fa39f18427 [file] [log] [blame]
Peter Collingbournebee583f2011-10-06 13:03:08 +00001//===- ClangAttrEmitter.cpp - Generate Clang attribute handling =-*- C++ -*--=//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// These tablegen backends emit Clang attribute processing code
11//
12//===----------------------------------------------------------------------===//
13
Alexis Hunta0e54d42012-06-18 16:13:52 +000014#include "llvm/ADT/SmallString.h"
Aaron Ballman8ee40b72013-09-09 23:33:17 +000015#include "llvm/ADT/SmallSet.h"
Chandler Carruth5553d0d2014-01-07 11:51:46 +000016#include "llvm/ADT/StringSwitch.h"
Aaron Ballman36a53502014-01-16 13:03:14 +000017#include "llvm/ADT/STLExtras.h"
Chandler Carruth5553d0d2014-01-07 11:51:46 +000018#include "llvm/TableGen/Error.h"
Peter Collingbournebee583f2011-10-06 13:03:08 +000019#include "llvm/TableGen/Record.h"
Douglas Gregor377f99b2012-05-02 17:33:51 +000020#include "llvm/TableGen/StringMatcher.h"
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +000021#include "llvm/TableGen/TableGenBackend.h"
Peter Collingbournebee583f2011-10-06 13:03:08 +000022#include <algorithm>
23#include <cctype>
Aaron Ballman80469032013-11-29 14:57:58 +000024#include <set>
Chandler Carruth5553d0d2014-01-07 11:51:46 +000025#include <sstream>
Peter Collingbournebee583f2011-10-06 13:03:08 +000026
27using namespace llvm;
28
Aaron Ballmanc669cc02014-01-27 22:10:04 +000029class FlattenedSpelling {
30 std::string V, N, NS;
31 bool K;
32
33public:
34 FlattenedSpelling(const std::string &Variety, const std::string &Name,
35 const std::string &Namespace, bool KnownToGCC) :
36 V(Variety), N(Name), NS(Namespace), K(KnownToGCC) {}
37 explicit FlattenedSpelling(const Record &Spelling) :
38 V(Spelling.getValueAsString("Variety")),
39 N(Spelling.getValueAsString("Name")) {
40
41 assert(V != "GCC" && "Given a GCC spelling, which means this hasn't been"
42 "flattened!");
43 if (V == "CXX11")
44 NS = Spelling.getValueAsString("Namespace");
45 bool Unset;
46 K = Spelling.getValueAsBitOrUnset("KnownToGCC", Unset);
47 }
48
49 const std::string &variety() const { return V; }
50 const std::string &name() const { return N; }
51 const std::string &nameSpace() const { return NS; }
52 bool knownToGCC() const { return K; }
53};
54
55std::vector<FlattenedSpelling> GetFlattenedSpellings(const Record &Attr) {
56 std::vector<Record *> Spellings = Attr.getValueAsListOfDefs("Spellings");
57 std::vector<FlattenedSpelling> Ret;
58
59 for (std::vector<Record *>::const_iterator I = Spellings.begin(),
60 E = Spellings.end(); I != E; ++I) {
61 const Record &Spelling = **I;
62
63 if (Spelling.getValueAsString("Variety") == "GCC") {
64 // Gin up two new spelling objects to add into the list.
65 Ret.push_back(FlattenedSpelling("GNU", Spelling.getValueAsString("Name"),
66 "", true));
67 Ret.push_back(FlattenedSpelling("CXX11",
68 Spelling.getValueAsString("Name"),
69 "gnu", true));
70 } else
71 Ret.push_back(FlattenedSpelling(Spelling));
72 }
73
74 return Ret;
75}
76
Peter Collingbournebee583f2011-10-06 13:03:08 +000077static std::string ReadPCHRecord(StringRef type) {
78 return StringSwitch<std::string>(type)
79 .EndsWith("Decl *", "GetLocalDeclAs<"
80 + std::string(type, 0, type.size()-1) + ">(F, Record[Idx++])")
Richard Smithb87c4652013-10-31 21:23:20 +000081 .Case("TypeSourceInfo *", "GetTypeSourceInfo(F, Record, Idx)")
Argyrios Kyrtzidisa660ae42012-11-15 01:31:39 +000082 .Case("Expr *", "ReadExpr(F)")
Peter Collingbournebee583f2011-10-06 13:03:08 +000083 .Case("IdentifierInfo *", "GetIdentifierInfo(F, Record, Idx)")
Peter Collingbournebee583f2011-10-06 13:03:08 +000084 .Default("Record[Idx++]");
85}
86
87// Assumes that the way to get the value is SA->getname()
88static std::string WritePCHRecord(StringRef type, StringRef name) {
89 return StringSwitch<std::string>(type)
90 .EndsWith("Decl *", "AddDeclRef(" + std::string(name) +
91 ", Record);\n")
Richard Smithb87c4652013-10-31 21:23:20 +000092 .Case("TypeSourceInfo *",
93 "AddTypeSourceInfo(" + std::string(name) + ", Record);\n")
Peter Collingbournebee583f2011-10-06 13:03:08 +000094 .Case("Expr *", "AddStmt(" + std::string(name) + ");\n")
95 .Case("IdentifierInfo *",
96 "AddIdentifierRef(" + std::string(name) + ", Record);\n")
Peter Collingbournebee583f2011-10-06 13:03:08 +000097 .Default("Record.push_back(" + std::string(name) + ");\n");
98}
99
Michael Han4a045172012-03-07 00:12:16 +0000100// Normalize attribute name by removing leading and trailing
101// underscores. For example, __foo, foo__, __foo__ would
102// become foo.
103static StringRef NormalizeAttrName(StringRef AttrName) {
104 if (AttrName.startswith("__"))
105 AttrName = AttrName.substr(2, AttrName.size());
106
107 if (AttrName.endswith("__"))
108 AttrName = AttrName.substr(0, AttrName.size() - 2);
109
110 return AttrName;
111}
112
Aaron Ballman36a53502014-01-16 13:03:14 +0000113// Normalize the name by removing any and all leading and trailing underscores.
114// This is different from NormalizeAttrName in that it also handles names like
115// _pascal and __pascal.
116static StringRef NormalizeNameForSpellingComparison(StringRef Name) {
117 while (Name.startswith("_"))
118 Name = Name.substr(1, Name.size());
119 while (Name.endswith("_"))
120 Name = Name.substr(0, Name.size() - 1);
121 return Name;
122}
123
Michael Han4a045172012-03-07 00:12:16 +0000124// Normalize attribute spelling only if the spelling has both leading
125// and trailing underscores. For example, __ms_struct__ will be
126// normalized to "ms_struct"; __cdecl will remain intact.
127static StringRef NormalizeAttrSpelling(StringRef AttrSpelling) {
128 if (AttrSpelling.startswith("__") && AttrSpelling.endswith("__")) {
129 AttrSpelling = AttrSpelling.substr(2, AttrSpelling.size() - 4);
130 }
131
132 return AttrSpelling;
133}
134
Aaron Ballman64e69862013-12-15 13:05:48 +0000135typedef std::vector<std::pair<std::string, Record *> > ParsedAttrMap;
136
Aaron Ballmanab7691c2014-01-09 22:48:32 +0000137static ParsedAttrMap getParsedAttrList(const RecordKeeper &Records,
138 ParsedAttrMap *Dupes = 0) {
Aaron Ballman64e69862013-12-15 13:05:48 +0000139 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
140 std::set<std::string> Seen;
141 ParsedAttrMap R;
142 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
143 I != E; ++I) {
144 Record &Attr = **I;
145 if (Attr.getValueAsBit("SemaHandler")) {
146 std::string AN;
147 if (Attr.isSubClassOf("TargetSpecificAttr") &&
148 !Attr.isValueUnset("ParseKind")) {
149 AN = Attr.getValueAsString("ParseKind");
150
151 // If this attribute has already been handled, it does not need to be
152 // handled again.
Aaron Ballmanab7691c2014-01-09 22:48:32 +0000153 if (Seen.find(AN) != Seen.end()) {
154 if (Dupes)
155 Dupes->push_back(std::make_pair(AN, *I));
Aaron Ballman64e69862013-12-15 13:05:48 +0000156 continue;
Aaron Ballmanab7691c2014-01-09 22:48:32 +0000157 }
Aaron Ballman64e69862013-12-15 13:05:48 +0000158 Seen.insert(AN);
159 } else
160 AN = NormalizeAttrName(Attr.getName()).str();
161
162 R.push_back(std::make_pair(AN, *I));
163 }
164 }
165 return R;
166}
167
Peter Collingbournebee583f2011-10-06 13:03:08 +0000168namespace {
169 class Argument {
170 std::string lowerName, upperName;
171 StringRef attrName;
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000172 bool isOpt;
Peter Collingbournebee583f2011-10-06 13:03:08 +0000173
174 public:
175 Argument(Record &Arg, StringRef Attr)
176 : lowerName(Arg.getValueAsString("Name")), upperName(lowerName),
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000177 attrName(Attr), isOpt(false) {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000178 if (!lowerName.empty()) {
179 lowerName[0] = std::tolower(lowerName[0]);
180 upperName[0] = std::toupper(upperName[0]);
181 }
182 }
183 virtual ~Argument() {}
184
185 StringRef getLowerName() const { return lowerName; }
186 StringRef getUpperName() const { return upperName; }
187 StringRef getAttrName() const { return attrName; }
188
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000189 bool isOptional() const { return isOpt; }
190 void setOptional(bool set) { isOpt = set; }
191
Peter Collingbournebee583f2011-10-06 13:03:08 +0000192 // These functions print the argument contents formatted in different ways.
193 virtual void writeAccessors(raw_ostream &OS) const = 0;
194 virtual void writeAccessorDefinitions(raw_ostream &OS) const {}
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +0000195 virtual void writeASTVisitorTraversal(raw_ostream &OS) const {}
Peter Collingbournebee583f2011-10-06 13:03:08 +0000196 virtual void writeCloneArgs(raw_ostream &OS) const = 0;
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000197 virtual void writeTemplateInstantiationArgs(raw_ostream &OS) const = 0;
Daniel Dunbardc51baa2012-02-10 06:00:29 +0000198 virtual void writeTemplateInstantiation(raw_ostream &OS) const {}
Peter Collingbournebee583f2011-10-06 13:03:08 +0000199 virtual void writeCtorBody(raw_ostream &OS) const {}
200 virtual void writeCtorInitializers(raw_ostream &OS) const = 0;
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000201 virtual void writeCtorDefaultInitializers(raw_ostream &OS) const = 0;
Peter Collingbournebee583f2011-10-06 13:03:08 +0000202 virtual void writeCtorParameters(raw_ostream &OS) const = 0;
203 virtual void writeDeclarations(raw_ostream &OS) const = 0;
204 virtual void writePCHReadArgs(raw_ostream &OS) const = 0;
205 virtual void writePCHReadDecls(raw_ostream &OS) const = 0;
206 virtual void writePCHWrite(raw_ostream &OS) const = 0;
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000207 virtual void writeValue(raw_ostream &OS) const = 0;
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000208 virtual void writeDump(raw_ostream &OS) const = 0;
209 virtual void writeDumpChildren(raw_ostream &OS) const {}
Richard Trieude5cc7d2013-01-31 01:44:26 +0000210 virtual void writeHasChildren(raw_ostream &OS) const { OS << "false"; }
Aaron Ballman682ee422013-09-11 19:47:58 +0000211
212 virtual bool isEnumArg() const { return false; }
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000213 virtual bool isVariadicEnumArg() const { return false; }
Aaron Ballman36a53502014-01-16 13:03:14 +0000214
215 virtual void writeImplicitCtorArgs(raw_ostream &OS) const {
216 OS << getUpperName();
217 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000218 };
219
220 class SimpleArgument : public Argument {
221 std::string type;
222
223 public:
224 SimpleArgument(Record &Arg, StringRef Attr, std::string T)
225 : Argument(Arg, Attr), type(T)
226 {}
227
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000228 std::string getType() const { return type; }
229
Peter Collingbournebee583f2011-10-06 13:03:08 +0000230 void writeAccessors(raw_ostream &OS) const {
231 OS << " " << type << " get" << getUpperName() << "() const {\n";
232 OS << " return " << getLowerName() << ";\n";
233 OS << " }";
234 }
235 void writeCloneArgs(raw_ostream &OS) const {
236 OS << getLowerName();
237 }
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000238 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
239 OS << "A->get" << getUpperName() << "()";
240 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000241 void writeCtorInitializers(raw_ostream &OS) const {
242 OS << getLowerName() << "(" << getUpperName() << ")";
243 }
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000244 void writeCtorDefaultInitializers(raw_ostream &OS) const {
245 OS << getLowerName() << "()";
246 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000247 void writeCtorParameters(raw_ostream &OS) const {
248 OS << type << " " << getUpperName();
249 }
250 void writeDeclarations(raw_ostream &OS) const {
251 OS << type << " " << getLowerName() << ";";
252 }
253 void writePCHReadDecls(raw_ostream &OS) const {
254 std::string read = ReadPCHRecord(type);
255 OS << " " << type << " " << getLowerName() << " = " << read << ";\n";
256 }
257 void writePCHReadArgs(raw_ostream &OS) const {
258 OS << getLowerName();
259 }
260 void writePCHWrite(raw_ostream &OS) const {
261 OS << " " << WritePCHRecord(type, "SA->get" +
262 std::string(getUpperName()) + "()");
263 }
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000264 void writeValue(raw_ostream &OS) const {
265 if (type == "FunctionDecl *") {
Richard Smithb87c4652013-10-31 21:23:20 +0000266 OS << "\" << get" << getUpperName()
267 << "()->getNameInfo().getAsString() << \"";
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000268 } else if (type == "IdentifierInfo *") {
269 OS << "\" << get" << getUpperName() << "()->getName() << \"";
Richard Smithb87c4652013-10-31 21:23:20 +0000270 } else if (type == "TypeSourceInfo *") {
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000271 OS << "\" << get" << getUpperName() << "().getAsString() << \"";
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000272 } else {
273 OS << "\" << get" << getUpperName() << "() << \"";
274 }
275 }
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000276 void writeDump(raw_ostream &OS) const {
277 if (type == "FunctionDecl *") {
278 OS << " OS << \" \";\n";
279 OS << " dumpBareDeclRef(SA->get" << getUpperName() << "());\n";
280 } else if (type == "IdentifierInfo *") {
281 OS << " OS << \" \" << SA->get" << getUpperName()
282 << "()->getName();\n";
Richard Smithb87c4652013-10-31 21:23:20 +0000283 } else if (type == "TypeSourceInfo *") {
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000284 OS << " OS << \" \" << SA->get" << getUpperName()
285 << "().getAsString();\n";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000286 } else if (type == "bool") {
287 OS << " if (SA->get" << getUpperName() << "()) OS << \" "
288 << getUpperName() << "\";\n";
289 } else if (type == "int" || type == "unsigned") {
290 OS << " OS << \" \" << SA->get" << getUpperName() << "();\n";
291 } else {
292 llvm_unreachable("Unknown SimpleArgument type!");
293 }
294 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000295 };
296
Aaron Ballman18a78382013-11-21 00:28:23 +0000297 class DefaultSimpleArgument : public SimpleArgument {
298 int64_t Default;
299
300 public:
301 DefaultSimpleArgument(Record &Arg, StringRef Attr,
302 std::string T, int64_t Default)
303 : SimpleArgument(Arg, Attr, T), Default(Default) {}
304
305 void writeAccessors(raw_ostream &OS) const {
306 SimpleArgument::writeAccessors(OS);
307
308 OS << "\n\n static const " << getType() << " Default" << getUpperName()
309 << " = " << Default << ";";
310 }
311 };
312
Peter Collingbournebee583f2011-10-06 13:03:08 +0000313 class StringArgument : public Argument {
314 public:
315 StringArgument(Record &Arg, StringRef Attr)
316 : Argument(Arg, Attr)
317 {}
318
319 void writeAccessors(raw_ostream &OS) const {
320 OS << " llvm::StringRef get" << getUpperName() << "() const {\n";
321 OS << " return llvm::StringRef(" << getLowerName() << ", "
322 << getLowerName() << "Length);\n";
323 OS << " }\n";
324 OS << " unsigned get" << getUpperName() << "Length() const {\n";
325 OS << " return " << getLowerName() << "Length;\n";
326 OS << " }\n";
327 OS << " void set" << getUpperName()
328 << "(ASTContext &C, llvm::StringRef S) {\n";
329 OS << " " << getLowerName() << "Length = S.size();\n";
330 OS << " this->" << getLowerName() << " = new (C, 1) char ["
331 << getLowerName() << "Length];\n";
332 OS << " std::memcpy(this->" << getLowerName() << ", S.data(), "
333 << getLowerName() << "Length);\n";
334 OS << " }";
335 }
336 void writeCloneArgs(raw_ostream &OS) const {
337 OS << "get" << getUpperName() << "()";
338 }
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000339 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
340 OS << "A->get" << getUpperName() << "()";
341 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000342 void writeCtorBody(raw_ostream &OS) const {
343 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
344 << ".data(), " << getLowerName() << "Length);";
345 }
346 void writeCtorInitializers(raw_ostream &OS) const {
347 OS << getLowerName() << "Length(" << getUpperName() << ".size()),"
348 << getLowerName() << "(new (Ctx, 1) char[" << getLowerName()
349 << "Length])";
350 }
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000351 void writeCtorDefaultInitializers(raw_ostream &OS) const {
352 OS << getLowerName() << "Length(0)," << getLowerName() << "(0)";
353 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000354 void writeCtorParameters(raw_ostream &OS) const {
355 OS << "llvm::StringRef " << getUpperName();
356 }
357 void writeDeclarations(raw_ostream &OS) const {
358 OS << "unsigned " << getLowerName() << "Length;\n";
359 OS << "char *" << getLowerName() << ";";
360 }
361 void writePCHReadDecls(raw_ostream &OS) const {
362 OS << " std::string " << getLowerName()
363 << "= ReadString(Record, Idx);\n";
364 }
365 void writePCHReadArgs(raw_ostream &OS) const {
366 OS << getLowerName();
367 }
368 void writePCHWrite(raw_ostream &OS) const {
369 OS << " AddString(SA->get" << getUpperName() << "(), Record);\n";
370 }
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000371 void writeValue(raw_ostream &OS) const {
372 OS << "\\\"\" << get" << getUpperName() << "() << \"\\\"";
373 }
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000374 void writeDump(raw_ostream &OS) const {
375 OS << " OS << \" \\\"\" << SA->get" << getUpperName()
376 << "() << \"\\\"\";\n";
377 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000378 };
379
380 class AlignedArgument : public Argument {
381 public:
382 AlignedArgument(Record &Arg, StringRef Attr)
383 : Argument(Arg, Attr)
384 {}
385
386 void writeAccessors(raw_ostream &OS) const {
387 OS << " bool is" << getUpperName() << "Dependent() const;\n";
388
389 OS << " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n";
390
391 OS << " bool is" << getUpperName() << "Expr() const {\n";
392 OS << " return is" << getLowerName() << "Expr;\n";
393 OS << " }\n";
394
395 OS << " Expr *get" << getUpperName() << "Expr() const {\n";
396 OS << " assert(is" << getLowerName() << "Expr);\n";
397 OS << " return " << getLowerName() << "Expr;\n";
398 OS << " }\n";
399
400 OS << " TypeSourceInfo *get" << getUpperName() << "Type() const {\n";
401 OS << " assert(!is" << getLowerName() << "Expr);\n";
402 OS << " return " << getLowerName() << "Type;\n";
403 OS << " }";
404 }
405 void writeAccessorDefinitions(raw_ostream &OS) const {
406 OS << "bool " << getAttrName() << "Attr::is" << getUpperName()
407 << "Dependent() const {\n";
408 OS << " if (is" << getLowerName() << "Expr)\n";
409 OS << " return " << getLowerName() << "Expr && (" << getLowerName()
410 << "Expr->isValueDependent() || " << getLowerName()
411 << "Expr->isTypeDependent());\n";
412 OS << " else\n";
413 OS << " return " << getLowerName()
414 << "Type->getType()->isDependentType();\n";
415 OS << "}\n";
416
417 // FIXME: Do not do the calculation here
418 // FIXME: Handle types correctly
419 // A null pointer means maximum alignment
420 // FIXME: Load the platform-specific maximum alignment, rather than
421 // 16, the x86 max.
422 OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName()
423 << "(ASTContext &Ctx) const {\n";
424 OS << " assert(!is" << getUpperName() << "Dependent());\n";
425 OS << " if (is" << getLowerName() << "Expr)\n";
426 OS << " return (" << getLowerName() << "Expr ? " << getLowerName()
Richard Smithcaf33902011-10-10 18:28:20 +0000427 << "Expr->EvaluateKnownConstInt(Ctx).getZExtValue() : 16)"
Peter Collingbournebee583f2011-10-06 13:03:08 +0000428 << "* Ctx.getCharWidth();\n";
429 OS << " else\n";
430 OS << " return 0; // FIXME\n";
431 OS << "}\n";
432 }
433 void writeCloneArgs(raw_ostream &OS) const {
434 OS << "is" << getLowerName() << "Expr, is" << getLowerName()
435 << "Expr ? static_cast<void*>(" << getLowerName()
436 << "Expr) : " << getLowerName()
437 << "Type";
438 }
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000439 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
440 // FIXME: move the definition in Sema::InstantiateAttrs to here.
441 // In the meantime, aligned attributes are cloned.
442 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000443 void writeCtorBody(raw_ostream &OS) const {
444 OS << " if (is" << getLowerName() << "Expr)\n";
445 OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>("
446 << getUpperName() << ");\n";
447 OS << " else\n";
448 OS << " " << getLowerName()
449 << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName()
450 << ");";
451 }
452 void writeCtorInitializers(raw_ostream &OS) const {
453 OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)";
454 }
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000455 void writeCtorDefaultInitializers(raw_ostream &OS) const {
456 OS << "is" << getLowerName() << "Expr(false)";
457 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000458 void writeCtorParameters(raw_ostream &OS) const {
459 OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName();
460 }
Aaron Ballman36a53502014-01-16 13:03:14 +0000461 void writeImplicitCtorArgs(raw_ostream &OS) const {
462 OS << "Is" << getUpperName() << "Expr, " << getUpperName();
463 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000464 void writeDeclarations(raw_ostream &OS) const {
465 OS << "bool is" << getLowerName() << "Expr;\n";
466 OS << "union {\n";
467 OS << "Expr *" << getLowerName() << "Expr;\n";
468 OS << "TypeSourceInfo *" << getLowerName() << "Type;\n";
469 OS << "};";
470 }
471 void writePCHReadArgs(raw_ostream &OS) const {
472 OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr";
473 }
474 void writePCHReadDecls(raw_ostream &OS) const {
475 OS << " bool is" << getLowerName() << "Expr = Record[Idx++];\n";
476 OS << " void *" << getLowerName() << "Ptr;\n";
477 OS << " if (is" << getLowerName() << "Expr)\n";
478 OS << " " << getLowerName() << "Ptr = ReadExpr(F);\n";
479 OS << " else\n";
480 OS << " " << getLowerName()
481 << "Ptr = GetTypeSourceInfo(F, Record, Idx);\n";
482 }
483 void writePCHWrite(raw_ostream &OS) const {
484 OS << " Record.push_back(SA->is" << getUpperName() << "Expr());\n";
485 OS << " if (SA->is" << getUpperName() << "Expr())\n";
486 OS << " AddStmt(SA->get" << getUpperName() << "Expr());\n";
487 OS << " else\n";
488 OS << " AddTypeSourceInfo(SA->get" << getUpperName()
489 << "Type(), Record);\n";
490 }
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000491 void writeValue(raw_ostream &OS) const {
Richard Smith52f04a22012-08-16 02:43:29 +0000492 OS << "\";\n"
493 << " " << getLowerName() << "Expr->printPretty(OS, 0, Policy);\n"
494 << " OS << \"";
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000495 }
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000496 void writeDump(raw_ostream &OS) const {
497 }
498 void writeDumpChildren(raw_ostream &OS) const {
Richard Trieude5cc7d2013-01-31 01:44:26 +0000499 OS << " if (SA->is" << getUpperName() << "Expr()) {\n";
500 OS << " lastChild();\n";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000501 OS << " dumpStmt(SA->get" << getUpperName() << "Expr());\n";
Richard Trieude5cc7d2013-01-31 01:44:26 +0000502 OS << " } else\n";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000503 OS << " dumpType(SA->get" << getUpperName()
504 << "Type()->getType());\n";
505 }
Richard Trieude5cc7d2013-01-31 01:44:26 +0000506 void writeHasChildren(raw_ostream &OS) const {
507 OS << "SA->is" << getUpperName() << "Expr()";
508 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000509 };
510
511 class VariadicArgument : public Argument {
512 std::string type;
513
514 public:
515 VariadicArgument(Record &Arg, StringRef Attr, std::string T)
516 : Argument(Arg, Attr), type(T)
517 {}
518
519 std::string getType() const { return type; }
520
521 void writeAccessors(raw_ostream &OS) const {
522 OS << " typedef " << type << "* " << getLowerName() << "_iterator;\n";
523 OS << " " << getLowerName() << "_iterator " << getLowerName()
524 << "_begin() const {\n";
525 OS << " return " << getLowerName() << ";\n";
526 OS << " }\n";
527 OS << " " << getLowerName() << "_iterator " << getLowerName()
528 << "_end() const {\n";
529 OS << " return " << getLowerName() << " + " << getLowerName()
530 << "Size;\n";
531 OS << " }\n";
532 OS << " unsigned " << getLowerName() << "_size() const {\n"
DeLesley Hutchins30398dd2012-01-20 22:50:54 +0000533 << " return " << getLowerName() << "Size;\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +0000534 OS << " }";
535 }
536 void writeCloneArgs(raw_ostream &OS) const {
537 OS << getLowerName() << ", " << getLowerName() << "Size";
538 }
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000539 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
540 // This isn't elegant, but we have to go through public methods...
541 OS << "A->" << getLowerName() << "_begin(), "
542 << "A->" << getLowerName() << "_size()";
543 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000544 void writeCtorBody(raw_ostream &OS) const {
545 // FIXME: memcpy is not safe on non-trivial types.
546 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
547 << ", " << getLowerName() << "Size * sizeof(" << getType() << "));\n";
548 }
549 void writeCtorInitializers(raw_ostream &OS) const {
550 OS << getLowerName() << "Size(" << getUpperName() << "Size), "
551 << getLowerName() << "(new (Ctx, 16) " << getType() << "["
552 << getLowerName() << "Size])";
553 }
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000554 void writeCtorDefaultInitializers(raw_ostream &OS) const {
555 OS << getLowerName() << "Size(0), " << getLowerName() << "(0)";
556 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000557 void writeCtorParameters(raw_ostream &OS) const {
558 OS << getType() << " *" << getUpperName() << ", unsigned "
559 << getUpperName() << "Size";
560 }
Aaron Ballman36a53502014-01-16 13:03:14 +0000561 void writeImplicitCtorArgs(raw_ostream &OS) const {
562 OS << getUpperName() << ", " << getUpperName() << "Size";
563 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000564 void writeDeclarations(raw_ostream &OS) const {
565 OS << " unsigned " << getLowerName() << "Size;\n";
566 OS << " " << getType() << " *" << getLowerName() << ";";
567 }
568 void writePCHReadDecls(raw_ostream &OS) const {
569 OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000570 OS << " SmallVector<" << type << ", 4> " << getLowerName()
Peter Collingbournebee583f2011-10-06 13:03:08 +0000571 << ";\n";
572 OS << " " << getLowerName() << ".reserve(" << getLowerName()
573 << "Size);\n";
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000574 OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +0000575
576 std::string read = ReadPCHRecord(type);
577 OS << " " << getLowerName() << ".push_back(" << read << ");\n";
578 }
579 void writePCHReadArgs(raw_ostream &OS) const {
580 OS << getLowerName() << ".data(), " << getLowerName() << "Size";
581 }
582 void writePCHWrite(raw_ostream &OS) const{
583 OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";
584 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
585 << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
586 << getLowerName() << "_end(); i != e; ++i)\n";
587 OS << " " << WritePCHRecord(type, "(*i)");
588 }
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000589 void writeValue(raw_ostream &OS) const {
590 OS << "\";\n";
591 OS << " bool isFirst = true;\n"
592 << " for (" << getAttrName() << "Attr::" << getLowerName()
593 << "_iterator i = " << getLowerName() << "_begin(), e = "
594 << getLowerName() << "_end(); i != e; ++i) {\n"
595 << " if (isFirst) isFirst = false;\n"
596 << " else OS << \", \";\n"
597 << " OS << *i;\n"
598 << " }\n";
599 OS << " OS << \"";
600 }
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000601 void writeDump(raw_ostream &OS) const {
602 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
603 << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
604 << getLowerName() << "_end(); I != E; ++I)\n";
605 OS << " OS << \" \" << *I;\n";
606 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000607 };
608
609 class EnumArgument : public Argument {
610 std::string type;
Aaron Ballman0e468c02014-01-05 21:08:29 +0000611 std::vector<std::string> values, enums, uniques;
Peter Collingbournebee583f2011-10-06 13:03:08 +0000612 public:
613 EnumArgument(Record &Arg, StringRef Attr)
614 : Argument(Arg, Attr), type(Arg.getValueAsString("Type")),
Aaron Ballman0e468c02014-01-05 21:08:29 +0000615 values(Arg.getValueAsListOfStrings("Values")),
616 enums(Arg.getValueAsListOfStrings("Enums")),
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000617 uniques(enums)
618 {
619 // Calculate the various enum values
620 std::sort(uniques.begin(), uniques.end());
621 uniques.erase(std::unique(uniques.begin(), uniques.end()), uniques.end());
622 // FIXME: Emit a proper error
623 assert(!uniques.empty());
624 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000625
Aaron Ballman682ee422013-09-11 19:47:58 +0000626 bool isEnumArg() const { return true; }
627
Peter Collingbournebee583f2011-10-06 13:03:08 +0000628 void writeAccessors(raw_ostream &OS) const {
629 OS << " " << type << " get" << getUpperName() << "() const {\n";
630 OS << " return " << getLowerName() << ";\n";
631 OS << " }";
632 }
633 void writeCloneArgs(raw_ostream &OS) const {
634 OS << getLowerName();
635 }
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000636 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
637 OS << "A->get" << getUpperName() << "()";
638 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000639 void writeCtorInitializers(raw_ostream &OS) const {
640 OS << getLowerName() << "(" << getUpperName() << ")";
641 }
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000642 void writeCtorDefaultInitializers(raw_ostream &OS) const {
643 OS << getLowerName() << "(" << type << "(0))";
644 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000645 void writeCtorParameters(raw_ostream &OS) const {
646 OS << type << " " << getUpperName();
647 }
648 void writeDeclarations(raw_ostream &OS) const {
Aaron Ballman0e468c02014-01-05 21:08:29 +0000649 std::vector<std::string>::const_iterator i = uniques.begin(),
650 e = uniques.end();
Peter Collingbournebee583f2011-10-06 13:03:08 +0000651 // The last one needs to not have a comma.
652 --e;
653
654 OS << "public:\n";
655 OS << " enum " << type << " {\n";
656 for (; i != e; ++i)
657 OS << " " << *i << ",\n";
658 OS << " " << *e << "\n";
659 OS << " };\n";
660 OS << "private:\n";
661 OS << " " << type << " " << getLowerName() << ";";
662 }
663 void writePCHReadDecls(raw_ostream &OS) const {
664 OS << " " << getAttrName() << "Attr::" << type << " " << getLowerName()
665 << "(static_cast<" << getAttrName() << "Attr::" << type
666 << ">(Record[Idx++]));\n";
667 }
668 void writePCHReadArgs(raw_ostream &OS) const {
669 OS << getLowerName();
670 }
671 void writePCHWrite(raw_ostream &OS) const {
672 OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
673 }
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000674 void writeValue(raw_ostream &OS) const {
675 OS << "\" << get" << getUpperName() << "() << \"";
676 }
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000677 void writeDump(raw_ostream &OS) const {
678 OS << " switch(SA->get" << getUpperName() << "()) {\n";
Aaron Ballman0e468c02014-01-05 21:08:29 +0000679 for (std::vector<std::string>::const_iterator I = uniques.begin(),
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000680 E = uniques.end(); I != E; ++I) {
681 OS << " case " << getAttrName() << "Attr::" << *I << ":\n";
682 OS << " OS << \" " << *I << "\";\n";
683 OS << " break;\n";
684 }
685 OS << " }\n";
686 }
Aaron Ballman682ee422013-09-11 19:47:58 +0000687
688 void writeConversion(raw_ostream &OS) const {
689 OS << " static bool ConvertStrTo" << type << "(StringRef Val, ";
690 OS << type << " &Out) {\n";
691 OS << " Optional<" << type << "> R = llvm::StringSwitch<Optional<";
692 OS << type << "> >(Val)\n";
693 for (size_t I = 0; I < enums.size(); ++I) {
694 OS << " .Case(\"" << values[I] << "\", ";
695 OS << getAttrName() << "Attr::" << enums[I] << ")\n";
696 }
697 OS << " .Default(Optional<" << type << ">());\n";
698 OS << " if (R) {\n";
699 OS << " Out = *R;\n return true;\n }\n";
700 OS << " return false;\n";
701 OS << " }\n";
702 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000703 };
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000704
705 class VariadicEnumArgument: public VariadicArgument {
706 std::string type, QualifiedTypeName;
Aaron Ballman0e468c02014-01-05 21:08:29 +0000707 std::vector<std::string> values, enums, uniques;
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000708 public:
709 VariadicEnumArgument(Record &Arg, StringRef Attr)
710 : VariadicArgument(Arg, Attr, Arg.getValueAsString("Type")),
711 type(Arg.getValueAsString("Type")),
Aaron Ballman0e468c02014-01-05 21:08:29 +0000712 values(Arg.getValueAsListOfStrings("Values")),
713 enums(Arg.getValueAsListOfStrings("Enums")),
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000714 uniques(enums)
715 {
716 // Calculate the various enum values
717 std::sort(uniques.begin(), uniques.end());
718 uniques.erase(std::unique(uniques.begin(), uniques.end()), uniques.end());
719
720 QualifiedTypeName = getAttrName().str() + "Attr::" + type;
721
722 // FIXME: Emit a proper error
723 assert(!uniques.empty());
724 }
725
726 bool isVariadicEnumArg() const { return true; }
727
728 void writeDeclarations(raw_ostream &OS) const {
Aaron Ballman0e468c02014-01-05 21:08:29 +0000729 std::vector<std::string>::const_iterator i = uniques.begin(),
730 e = uniques.end();
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000731 // The last one needs to not have a comma.
732 --e;
733
734 OS << "public:\n";
735 OS << " enum " << type << " {\n";
736 for (; i != e; ++i)
737 OS << " " << *i << ",\n";
738 OS << " " << *e << "\n";
739 OS << " };\n";
740 OS << "private:\n";
741
742 VariadicArgument::writeDeclarations(OS);
743 }
744 void writeDump(raw_ostream &OS) const {
745 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
746 << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
747 << getLowerName() << "_end(); I != E; ++I) {\n";
748 OS << " switch(*I) {\n";
Aaron Ballman0e468c02014-01-05 21:08:29 +0000749 for (std::vector<std::string>::const_iterator UI = uniques.begin(),
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000750 UE = uniques.end(); UI != UE; ++UI) {
751 OS << " case " << getAttrName() << "Attr::" << *UI << ":\n";
752 OS << " OS << \" " << *UI << "\";\n";
753 OS << " break;\n";
754 }
755 OS << " }\n";
756 OS << " }\n";
757 }
758 void writePCHReadDecls(raw_ostream &OS) const {
759 OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
760 OS << " SmallVector<" << QualifiedTypeName << ", 4> " << getLowerName()
761 << ";\n";
762 OS << " " << getLowerName() << ".reserve(" << getLowerName()
763 << "Size);\n";
764 OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
765 OS << " " << getLowerName() << ".push_back(" << "static_cast<"
766 << QualifiedTypeName << ">(Record[Idx++]));\n";
767 }
768 void writePCHWrite(raw_ostream &OS) const{
769 OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";
770 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
771 << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
772 << getLowerName() << "_end(); i != e; ++i)\n";
773 OS << " " << WritePCHRecord(QualifiedTypeName, "(*i)");
774 }
775 void writeConversion(raw_ostream &OS) const {
776 OS << " static bool ConvertStrTo" << type << "(StringRef Val, ";
777 OS << type << " &Out) {\n";
778 OS << " Optional<" << type << "> R = llvm::StringSwitch<Optional<";
779 OS << type << "> >(Val)\n";
780 for (size_t I = 0; I < enums.size(); ++I) {
781 OS << " .Case(\"" << values[I] << "\", ";
782 OS << getAttrName() << "Attr::" << enums[I] << ")\n";
783 }
784 OS << " .Default(Optional<" << type << ">());\n";
785 OS << " if (R) {\n";
786 OS << " Out = *R;\n return true;\n }\n";
787 OS << " return false;\n";
788 OS << " }\n";
789 }
790 };
Peter Collingbournebee583f2011-10-06 13:03:08 +0000791
792 class VersionArgument : public Argument {
793 public:
794 VersionArgument(Record &Arg, StringRef Attr)
795 : Argument(Arg, Attr)
796 {}
797
798 void writeAccessors(raw_ostream &OS) const {
799 OS << " VersionTuple get" << getUpperName() << "() const {\n";
800 OS << " return " << getLowerName() << ";\n";
801 OS << " }\n";
802 OS << " void set" << getUpperName()
803 << "(ASTContext &C, VersionTuple V) {\n";
804 OS << " " << getLowerName() << " = V;\n";
805 OS << " }";
806 }
807 void writeCloneArgs(raw_ostream &OS) const {
808 OS << "get" << getUpperName() << "()";
809 }
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000810 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
811 OS << "A->get" << getUpperName() << "()";
812 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000813 void writeCtorBody(raw_ostream &OS) const {
814 }
815 void writeCtorInitializers(raw_ostream &OS) const {
816 OS << getLowerName() << "(" << getUpperName() << ")";
817 }
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000818 void writeCtorDefaultInitializers(raw_ostream &OS) const {
819 OS << getLowerName() << "()";
820 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000821 void writeCtorParameters(raw_ostream &OS) const {
822 OS << "VersionTuple " << getUpperName();
823 }
824 void writeDeclarations(raw_ostream &OS) const {
825 OS << "VersionTuple " << getLowerName() << ";\n";
826 }
827 void writePCHReadDecls(raw_ostream &OS) const {
828 OS << " VersionTuple " << getLowerName()
829 << "= ReadVersionTuple(Record, Idx);\n";
830 }
831 void writePCHReadArgs(raw_ostream &OS) const {
832 OS << getLowerName();
833 }
834 void writePCHWrite(raw_ostream &OS) const {
835 OS << " AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n";
836 }
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000837 void writeValue(raw_ostream &OS) const {
838 OS << getLowerName() << "=\" << get" << getUpperName() << "() << \"";
839 }
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000840 void writeDump(raw_ostream &OS) const {
841 OS << " OS << \" \" << SA->get" << getUpperName() << "();\n";
842 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000843 };
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000844
845 class ExprArgument : public SimpleArgument {
846 public:
847 ExprArgument(Record &Arg, StringRef Attr)
848 : SimpleArgument(Arg, Attr, "Expr *")
849 {}
850
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +0000851 virtual void writeASTVisitorTraversal(raw_ostream &OS) const {
852 OS << " if (!"
853 << "getDerived().TraverseStmt(A->get" << getUpperName() << "()))\n";
854 OS << " return false;\n";
855 }
856
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000857 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
858 OS << "tempInst" << getUpperName();
859 }
860
861 void writeTemplateInstantiation(raw_ostream &OS) const {
862 OS << " " << getType() << " tempInst" << getUpperName() << ";\n";
863 OS << " {\n";
864 OS << " EnterExpressionEvaluationContext "
865 << "Unevaluated(S, Sema::Unevaluated);\n";
866 OS << " ExprResult " << "Result = S.SubstExpr("
867 << "A->get" << getUpperName() << "(), TemplateArgs);\n";
868 OS << " tempInst" << getUpperName() << " = "
869 << "Result.takeAs<Expr>();\n";
870 OS << " }\n";
871 }
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000872
873 void writeDump(raw_ostream &OS) const {
874 }
875
876 void writeDumpChildren(raw_ostream &OS) const {
Richard Trieude5cc7d2013-01-31 01:44:26 +0000877 OS << " lastChild();\n";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000878 OS << " dumpStmt(SA->get" << getUpperName() << "());\n";
879 }
Richard Trieude5cc7d2013-01-31 01:44:26 +0000880 void writeHasChildren(raw_ostream &OS) const { OS << "true"; }
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000881 };
882
883 class VariadicExprArgument : public VariadicArgument {
884 public:
885 VariadicExprArgument(Record &Arg, StringRef Attr)
886 : VariadicArgument(Arg, Attr, "Expr *")
887 {}
888
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +0000889 virtual void writeASTVisitorTraversal(raw_ostream &OS) const {
890 OS << " {\n";
891 OS << " " << getType() << " *I = A->" << getLowerName()
892 << "_begin();\n";
893 OS << " " << getType() << " *E = A->" << getLowerName()
894 << "_end();\n";
895 OS << " for (; I != E; ++I) {\n";
896 OS << " if (!getDerived().TraverseStmt(*I))\n";
897 OS << " return false;\n";
898 OS << " }\n";
899 OS << " }\n";
900 }
901
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000902 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
903 OS << "tempInst" << getUpperName() << ", "
904 << "A->" << getLowerName() << "_size()";
905 }
906
907 void writeTemplateInstantiation(raw_ostream &OS) const {
908 OS << " " << getType() << " *tempInst" << getUpperName()
909 << " = new (C, 16) " << getType()
910 << "[A->" << getLowerName() << "_size()];\n";
911 OS << " {\n";
912 OS << " EnterExpressionEvaluationContext "
913 << "Unevaluated(S, Sema::Unevaluated);\n";
914 OS << " " << getType() << " *TI = tempInst" << getUpperName()
915 << ";\n";
916 OS << " " << getType() << " *I = A->" << getLowerName()
917 << "_begin();\n";
918 OS << " " << getType() << " *E = A->" << getLowerName()
919 << "_end();\n";
920 OS << " for (; I != E; ++I, ++TI) {\n";
921 OS << " ExprResult Result = S.SubstExpr(*I, TemplateArgs);\n";
922 OS << " *TI = Result.takeAs<Expr>();\n";
923 OS << " }\n";
924 OS << " }\n";
925 }
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000926
927 void writeDump(raw_ostream &OS) const {
928 }
929
930 void writeDumpChildren(raw_ostream &OS) const {
931 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
932 << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
Richard Trieude5cc7d2013-01-31 01:44:26 +0000933 << getLowerName() << "_end(); I != E; ++I) {\n";
934 OS << " if (I + 1 == E)\n";
935 OS << " lastChild();\n";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000936 OS << " dumpStmt(*I);\n";
Richard Trieude5cc7d2013-01-31 01:44:26 +0000937 OS << " }\n";
938 }
939
940 void writeHasChildren(raw_ostream &OS) const {
941 OS << "SA->" << getLowerName() << "_begin() != "
942 << "SA->" << getLowerName() << "_end()";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000943 }
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000944 };
Richard Smithb87c4652013-10-31 21:23:20 +0000945
946 class TypeArgument : public SimpleArgument {
947 public:
948 TypeArgument(Record &Arg, StringRef Attr)
949 : SimpleArgument(Arg, Attr, "TypeSourceInfo *")
950 {}
951
952 void writeAccessors(raw_ostream &OS) const {
953 OS << " QualType get" << getUpperName() << "() const {\n";
954 OS << " return " << getLowerName() << "->getType();\n";
955 OS << " }";
956 OS << " " << getType() << " get" << getUpperName() << "Loc() const {\n";
957 OS << " return " << getLowerName() << ";\n";
958 OS << " }";
959 }
960 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
961 OS << "A->get" << getUpperName() << "Loc()";
962 }
963 void writePCHWrite(raw_ostream &OS) const {
964 OS << " " << WritePCHRecord(
965 getType(), "SA->get" + std::string(getUpperName()) + "Loc()");
966 }
967 };
Peter Collingbournebee583f2011-10-06 13:03:08 +0000968}
969
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000970static Argument *createArgument(Record &Arg, StringRef Attr,
971 Record *Search = 0) {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000972 if (!Search)
973 Search = &Arg;
974
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000975 Argument *Ptr = 0;
Peter Collingbournebee583f2011-10-06 13:03:08 +0000976 llvm::StringRef ArgName = Search->getName();
977
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000978 if (ArgName == "AlignedArgument") Ptr = new AlignedArgument(Arg, Attr);
979 else if (ArgName == "EnumArgument") Ptr = new EnumArgument(Arg, Attr);
980 else if (ArgName == "ExprArgument") Ptr = new ExprArgument(Arg, Attr);
Peter Collingbournebee583f2011-10-06 13:03:08 +0000981 else if (ArgName == "FunctionArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000982 Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *");
Peter Collingbournebee583f2011-10-06 13:03:08 +0000983 else if (ArgName == "IdentifierArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000984 Ptr = new SimpleArgument(Arg, Attr, "IdentifierInfo *");
David Majnemer4bb09802014-02-10 19:50:15 +0000985 else if (ArgName == "DefaultBoolArgument")
986 Ptr = new DefaultSimpleArgument(Arg, Attr, "bool",
987 Arg.getValueAsBit("Default"));
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000988 else if (ArgName == "BoolArgument") Ptr = new SimpleArgument(Arg, Attr,
989 "bool");
Aaron Ballman18a78382013-11-21 00:28:23 +0000990 else if (ArgName == "DefaultIntArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000991 Ptr = new DefaultSimpleArgument(Arg, Attr, "int",
992 Arg.getValueAsInt("Default"));
993 else if (ArgName == "IntArgument") Ptr = new SimpleArgument(Arg, Attr, "int");
994 else if (ArgName == "StringArgument") Ptr = new StringArgument(Arg, Attr);
995 else if (ArgName == "TypeArgument") Ptr = new TypeArgument(Arg, Attr);
Peter Collingbournebee583f2011-10-06 13:03:08 +0000996 else if (ArgName == "UnsignedArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000997 Ptr = new SimpleArgument(Arg, Attr, "unsigned");
Peter Collingbournebee583f2011-10-06 13:03:08 +0000998 else if (ArgName == "VariadicUnsignedArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000999 Ptr = new VariadicArgument(Arg, Attr, "unsigned");
DeLesley Hutchins210791a2013-10-04 21:28:06 +00001000 else if (ArgName == "VariadicEnumArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +00001001 Ptr = new VariadicEnumArgument(Arg, Attr);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001002 else if (ArgName == "VariadicExprArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +00001003 Ptr = new VariadicExprArgument(Arg, Attr);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001004 else if (ArgName == "VersionArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +00001005 Ptr = new VersionArgument(Arg, Attr);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001006
1007 if (!Ptr) {
Aaron Ballman18a78382013-11-21 00:28:23 +00001008 // Search in reverse order so that the most-derived type is handled first.
Peter Collingbournebee583f2011-10-06 13:03:08 +00001009 std::vector<Record*> Bases = Search->getSuperClasses();
Aaron Ballman18a78382013-11-21 00:28:23 +00001010 for (std::vector<Record*>::reverse_iterator i = Bases.rbegin(),
1011 e = Bases.rend(); i != e; ++i) {
Peter Collingbournebee583f2011-10-06 13:03:08 +00001012 Ptr = createArgument(Arg, Attr, *i);
1013 if (Ptr)
1014 break;
1015 }
1016 }
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001017
1018 if (Ptr && Arg.getValueAsBit("Optional"))
1019 Ptr->setOptional(true);
1020
Peter Collingbournebee583f2011-10-06 13:03:08 +00001021 return Ptr;
1022}
1023
Douglas Gregor49ccfaa2011-11-19 19:22:57 +00001024static void writeAvailabilityValue(raw_ostream &OS) {
1025 OS << "\" << getPlatform()->getName();\n"
1026 << " if (!getIntroduced().empty()) OS << \", introduced=\" << getIntroduced();\n"
1027 << " if (!getDeprecated().empty()) OS << \", deprecated=\" << getDeprecated();\n"
1028 << " if (!getObsoleted().empty()) OS << \", obsoleted=\" << getObsoleted();\n"
1029 << " if (getUnavailable()) OS << \", unavailable\";\n"
1030 << " OS << \"";
1031}
1032
Aaron Ballman3e424b52013-12-26 18:30:57 +00001033static void writeGetSpellingFunction(Record &R, raw_ostream &OS) {
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001034 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
Aaron Ballman3e424b52013-12-26 18:30:57 +00001035
1036 OS << "const char *" << R.getName() << "Attr::getSpelling() const {\n";
1037 if (Spellings.empty()) {
1038 OS << " return \"(No spelling)\";\n}\n\n";
1039 return;
1040 }
1041
1042 OS << " switch (SpellingListIndex) {\n"
1043 " default:\n"
1044 " llvm_unreachable(\"Unknown attribute spelling!\");\n"
1045 " return \"(No spelling)\";\n";
1046
1047 for (unsigned I = 0; I < Spellings.size(); ++I)
1048 OS << " case " << I << ":\n"
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001049 " return \"" << Spellings[I].name() << "\";\n";
Aaron Ballman3e424b52013-12-26 18:30:57 +00001050 // End of the switch statement.
1051 OS << " }\n";
1052 // End of the getSpelling function.
1053 OS << "}\n\n";
1054}
1055
Michael Han99315932013-01-24 16:46:58 +00001056static void writePrettyPrintFunction(Record &R, std::vector<Argument*> &Args,
1057 raw_ostream &OS) {
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001058 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
Michael Han99315932013-01-24 16:46:58 +00001059
1060 OS << "void " << R.getName() << "Attr::printPretty("
1061 << "raw_ostream &OS, const PrintingPolicy &Policy) const {\n";
1062
1063 if (Spellings.size() == 0) {
1064 OS << "}\n\n";
1065 return;
1066 }
1067
1068 OS <<
1069 " switch (SpellingListIndex) {\n"
1070 " default:\n"
1071 " llvm_unreachable(\"Unknown attribute spelling!\");\n"
1072 " break;\n";
1073
1074 for (unsigned I = 0; I < Spellings.size(); ++ I) {
1075 llvm::SmallString<16> Prefix;
1076 llvm::SmallString<8> Suffix;
1077 // The actual spelling of the name and namespace (if applicable)
1078 // of an attribute without considering prefix and suffix.
1079 llvm::SmallString<64> Spelling;
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001080 std::string Name = Spellings[I].name();
1081 std::string Variety = Spellings[I].variety();
Michael Han99315932013-01-24 16:46:58 +00001082
1083 if (Variety == "GNU") {
1084 Prefix = " __attribute__((";
1085 Suffix = "))";
1086 } else if (Variety == "CXX11") {
1087 Prefix = " [[";
1088 Suffix = "]]";
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001089 std::string Namespace = Spellings[I].nameSpace();
Michael Han99315932013-01-24 16:46:58 +00001090 if (Namespace != "") {
1091 Spelling += Namespace;
1092 Spelling += "::";
1093 }
1094 } else if (Variety == "Declspec") {
1095 Prefix = " __declspec(";
1096 Suffix = ")";
Richard Smith0cdcc982013-01-29 01:24:26 +00001097 } else if (Variety == "Keyword") {
1098 Prefix = " ";
1099 Suffix = "";
Michael Han99315932013-01-24 16:46:58 +00001100 } else {
Richard Smith0cdcc982013-01-29 01:24:26 +00001101 llvm_unreachable("Unknown attribute syntax variety!");
Michael Han99315932013-01-24 16:46:58 +00001102 }
1103
1104 Spelling += Name;
1105
1106 OS <<
1107 " case " << I << " : {\n"
1108 " OS << \"" + Prefix.str() + Spelling.str();
1109
1110 if (Args.size()) OS << "(";
1111 if (Spelling == "availability") {
1112 writeAvailabilityValue(OS);
1113 } else {
1114 for (std::vector<Argument*>::const_iterator I = Args.begin(),
1115 E = Args.end(); I != E; ++ I) {
1116 if (I != Args.begin()) OS << ", ";
1117 (*I)->writeValue(OS);
1118 }
1119 }
1120
1121 if (Args.size()) OS << ")";
1122 OS << Suffix.str() + "\";\n";
1123
1124 OS <<
1125 " break;\n"
1126 " }\n";
1127 }
1128
1129 // End of the switch statement.
1130 OS << "}\n";
1131 // End of the print function.
1132 OS << "}\n\n";
1133}
1134
Michael Hanaf02bbe2013-02-01 01:19:17 +00001135/// \brief Return the index of a spelling in a spelling list.
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001136static unsigned
1137getSpellingListIndex(const std::vector<FlattenedSpelling> &SpellingList,
1138 const FlattenedSpelling &Spelling) {
Michael Hanaf02bbe2013-02-01 01:19:17 +00001139 assert(SpellingList.size() && "Spelling list is empty!");
1140
1141 for (unsigned Index = 0; Index < SpellingList.size(); ++Index) {
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001142 const FlattenedSpelling &S = SpellingList[Index];
1143 if (S.variety() != Spelling.variety())
Michael Hanaf02bbe2013-02-01 01:19:17 +00001144 continue;
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001145 if (S.nameSpace() != Spelling.nameSpace())
Michael Hanaf02bbe2013-02-01 01:19:17 +00001146 continue;
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001147 if (S.name() != Spelling.name())
Michael Hanaf02bbe2013-02-01 01:19:17 +00001148 continue;
1149
1150 return Index;
1151 }
1152
1153 llvm_unreachable("Unknown spelling!");
1154}
1155
1156static void writeAttrAccessorDefinition(Record &R, raw_ostream &OS) {
1157 std::vector<Record*> Accessors = R.getValueAsListOfDefs("Accessors");
1158 for (std::vector<Record*>::const_iterator I = Accessors.begin(),
1159 E = Accessors.end(); I != E; ++I) {
1160 Record *Accessor = *I;
1161 std::string Name = Accessor->getValueAsString("Name");
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001162 std::vector<FlattenedSpelling> Spellings =
1163 GetFlattenedSpellings(*Accessor);
1164 std::vector<FlattenedSpelling> SpellingList = GetFlattenedSpellings(R);
Michael Hanaf02bbe2013-02-01 01:19:17 +00001165 assert(SpellingList.size() &&
1166 "Attribute with empty spelling list can't have accessors!");
1167
1168 OS << " bool " << Name << "() const { return SpellingListIndex == ";
1169 for (unsigned Index = 0; Index < Spellings.size(); ++Index) {
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001170 OS << getSpellingListIndex(SpellingList, Spellings[Index]);
Michael Hanaf02bbe2013-02-01 01:19:17 +00001171 if (Index != Spellings.size() -1)
1172 OS << " ||\n SpellingListIndex == ";
1173 else
1174 OS << "; }\n";
1175 }
1176 }
1177}
1178
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001179static bool
1180SpellingNamesAreCommon(const std::vector<FlattenedSpelling>& Spellings) {
Aaron Ballman36a53502014-01-16 13:03:14 +00001181 assert(!Spellings.empty() && "An empty list of spellings was provided");
1182 std::string FirstName = NormalizeNameForSpellingComparison(
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001183 Spellings.front().name());
1184 for (std::vector<FlattenedSpelling>::const_iterator
1185 I = llvm::next(Spellings.begin()), E = Spellings.end(); I != E; ++I) {
1186 std::string Name = NormalizeNameForSpellingComparison(I->name());
Aaron Ballman36a53502014-01-16 13:03:14 +00001187 if (Name != FirstName)
1188 return false;
1189 }
1190 return true;
1191}
1192
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001193typedef std::map<unsigned, std::string> SemanticSpellingMap;
1194static std::string
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001195CreateSemanticSpellings(const std::vector<FlattenedSpelling> &Spellings,
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001196 SemanticSpellingMap &Map) {
1197 // The enumerants are automatically generated based on the variety,
1198 // namespace (if present) and name for each attribute spelling. However,
1199 // care is taken to avoid trampling on the reserved namespace due to
1200 // underscores.
1201 std::string Ret(" enum Spelling {\n");
1202 std::set<std::string> Uniques;
1203 unsigned Idx = 0;
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001204 for (std::vector<FlattenedSpelling>::const_iterator I = Spellings.begin(),
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001205 E = Spellings.end(); I != E; ++I, ++Idx) {
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001206 const FlattenedSpelling &S = *I;
1207 std::string Variety = S.variety();
1208 std::string Spelling = S.name();
1209 std::string Namespace = S.nameSpace();
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001210 std::string EnumName = "";
1211
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001212 EnumName += (Variety + "_");
1213 if (!Namespace.empty())
1214 EnumName += (NormalizeNameForSpellingComparison(Namespace).str() +
1215 "_");
1216 EnumName += NormalizeNameForSpellingComparison(Spelling);
1217
1218 // Even if the name is not unique, this spelling index corresponds to a
1219 // particular enumerant name that we've calculated.
1220 Map[Idx] = EnumName;
1221
1222 // Since we have been stripping underscores to avoid trampling on the
1223 // reserved namespace, we may have inadvertently created duplicate
1224 // enumerant names. These duplicates are not considered part of the
1225 // semantic spelling, and can be elided.
1226 if (Uniques.find(EnumName) != Uniques.end())
1227 continue;
1228
1229 Uniques.insert(EnumName);
1230 if (I != Spellings.begin())
1231 Ret += ",\n";
1232 Ret += " " + EnumName;
1233 }
1234 Ret += "\n };\n\n";
1235 return Ret;
1236}
1237
1238void WriteSemanticSpellingSwitch(const std::string &VarName,
1239 const SemanticSpellingMap &Map,
1240 raw_ostream &OS) {
1241 OS << " switch (" << VarName << ") {\n default: "
1242 << "llvm_unreachable(\"Unknown spelling list index\");\n";
1243 for (SemanticSpellingMap::const_iterator I = Map.begin(), E = Map.end();
1244 I != E; ++I)
1245 OS << " case " << I->first << ": return " << I->second << ";\n";
1246 OS << " }\n";
1247}
1248
Aaron Ballman35db2b32014-01-29 22:13:45 +00001249// Emits the LateParsed property for attributes.
1250static void emitClangAttrLateParsedList(RecordKeeper &Records, raw_ostream &OS) {
1251 OS << "#if defined(CLANG_ATTR_LATE_PARSED_LIST)\n";
1252 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1253
1254 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1255 I != E; ++I) {
1256 Record &Attr = **I;
1257
1258 bool LateParsed = Attr.getValueAsBit("LateParsed");
1259
1260 if (LateParsed) {
1261 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
1262
1263 // FIXME: Handle non-GNU attributes
1264 for (std::vector<FlattenedSpelling>::const_iterator
1265 I = Spellings.begin(), E = Spellings.end(); I != E; ++I) {
1266 if (I->variety() != "GNU")
1267 continue;
1268 OS << ".Case(\"" << I->name() << "\", " << LateParsed << ")\n";
1269 }
1270 }
1271 }
1272 OS << "#endif // CLANG_ATTR_LATE_PARSED_LIST\n\n";
1273}
1274
1275/// \brief Emits the first-argument-is-type property for attributes.
1276static void emitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) {
1277 OS << "#if defined(CLANG_ATTR_TYPE_ARG_LIST)\n";
1278 std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
1279
1280 for (std::vector<Record *>::iterator I = Attrs.begin(), E = Attrs.end();
1281 I != E; ++I) {
1282 Record &Attr = **I;
1283
1284 // Determine whether the first argument is a type.
1285 std::vector<Record *> Args = Attr.getValueAsListOfDefs("Args");
1286 if (Args.empty())
1287 continue;
1288
1289 if (Args[0]->getSuperClasses().back()->getName() != "TypeArgument")
1290 continue;
1291
1292 // All these spellings take a single type argument.
1293 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
1294 std::set<std::string> Emitted;
1295 for (std::vector<FlattenedSpelling>::const_iterator I = Spellings.begin(),
1296 E = Spellings.end(); I != E; ++I) {
1297 if (Emitted.insert(I->name()).second)
1298 OS << ".Case(\"" << I->name() << "\", " << "true" << ")\n";
1299 }
1300 }
1301 OS << "#endif // CLANG_ATTR_TYPE_ARG_LIST\n\n";
1302}
1303
1304/// \brief Emits the parse-arguments-in-unevaluated-context property for
1305/// attributes.
1306static void emitClangAttrArgContextList(RecordKeeper &Records, raw_ostream &OS) {
1307 OS << "#if defined(CLANG_ATTR_ARG_CONTEXT_LIST)\n";
1308 ParsedAttrMap Attrs = getParsedAttrList(Records);
1309 for (ParsedAttrMap::const_iterator I = Attrs.begin(), E = Attrs.end();
1310 I != E; ++I) {
1311 const Record &Attr = *I->second;
1312
1313 if (!Attr.getValueAsBit("ParseArgumentsAsUnevaluated"))
1314 continue;
1315
1316 // All these spellings take are parsed unevaluated.
1317 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
1318 std::set<std::string> Emitted;
1319 for (std::vector<FlattenedSpelling>::const_iterator I = Spellings.begin(),
1320 E = Spellings.end(); I != E; ++I) {
1321 if (Emitted.insert(I->name()).second)
1322 OS << ".Case(\"" << I->name() << "\", " << "true" << ")\n";
1323 }
1324 }
1325 OS << "#endif // CLANG_ATTR_ARG_CONTEXT_LIST\n\n";
1326}
1327
1328static bool isIdentifierArgument(Record *Arg) {
1329 return !Arg->getSuperClasses().empty() &&
1330 llvm::StringSwitch<bool>(Arg->getSuperClasses().back()->getName())
1331 .Case("IdentifierArgument", true)
1332 .Case("EnumArgument", true)
1333 .Default(false);
1334}
1335
1336// Emits the first-argument-is-identifier property for attributes.
1337static void emitClangAttrIdentifierArgList(RecordKeeper &Records, raw_ostream &OS) {
1338 OS << "#if defined(CLANG_ATTR_IDENTIFIER_ARG_LIST)\n";
1339 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1340
1341 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1342 I != E; ++I) {
1343 Record &Attr = **I;
1344
1345 // Determine whether the first argument is an identifier.
1346 std::vector<Record *> Args = Attr.getValueAsListOfDefs("Args");
1347 if (Args.empty() || !isIdentifierArgument(Args[0]))
1348 continue;
1349
1350 // All these spellings take an identifier argument.
1351 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
1352 std::set<std::string> Emitted;
1353 for (std::vector<FlattenedSpelling>::const_iterator I = Spellings.begin(),
1354 E = Spellings.end(); I != E; ++I) {
1355 if (Emitted.insert(I->name()).second)
1356 OS << ".Case(\"" << I->name() << "\", " << "true" << ")\n";
1357 }
1358 }
1359 OS << "#endif // CLANG_ATTR_IDENTIFIER_ARG_LIST\n\n";
1360}
1361
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001362namespace clang {
1363
1364// Emits the class definitions for attributes.
1365void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00001366 emitSourceFileHeader("Attribute classes' definitions", OS);
1367
Peter Collingbournebee583f2011-10-06 13:03:08 +00001368 OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
1369 OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
1370
1371 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1372
1373 for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
1374 i != e; ++i) {
1375 Record &R = **i;
Douglas Gregorb2daf842012-05-02 15:56:52 +00001376
1377 if (!R.getValueAsBit("ASTNode"))
1378 continue;
1379
Aaron Ballman0979e9e2013-07-30 01:44:15 +00001380 const std::vector<Record *> Supers = R.getSuperClasses();
1381 assert(!Supers.empty() && "Forgot to specify a superclass for the attr");
Aaron Ballman0979e9e2013-07-30 01:44:15 +00001382 std::string SuperName;
1383 for (std::vector<Record *>::const_reverse_iterator I = Supers.rbegin(),
1384 E = Supers.rend(); I != E; ++I) {
1385 const Record &R = **I;
Aaron Ballman080cad72013-07-31 02:20:22 +00001386 if (R.getName() != "TargetSpecificAttr" && SuperName.empty())
Aaron Ballman0979e9e2013-07-30 01:44:15 +00001387 SuperName = R.getName();
1388 }
Peter Collingbournebee583f2011-10-06 13:03:08 +00001389
1390 OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n";
1391
1392 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
1393 std::vector<Argument*> Args;
1394 std::vector<Argument*>::iterator ai, ae;
1395 Args.reserve(ArgRecords.size());
1396
1397 for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
1398 re = ArgRecords.end();
1399 ri != re; ++ri) {
1400 Record &ArgRecord = **ri;
Aaron Ballmanaa47d242013-12-19 19:39:25 +00001401 Argument *Arg = createArgument(ArgRecord, R.getName());
Peter Collingbournebee583f2011-10-06 13:03:08 +00001402 assert(Arg);
1403 Args.push_back(Arg);
1404
1405 Arg->writeDeclarations(OS);
1406 OS << "\n\n";
1407 }
1408
1409 ae = Args.end();
1410
Aaron Ballman36a53502014-01-16 13:03:14 +00001411 OS << "\npublic:\n";
1412
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001413 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
Aaron Ballman36a53502014-01-16 13:03:14 +00001414
1415 // If there are zero or one spellings, all spelling-related functionality
1416 // can be elided. If all of the spellings share the same name, the spelling
1417 // functionality can also be elided.
1418 bool ElideSpelling = (Spellings.size() <= 1) ||
1419 SpellingNamesAreCommon(Spellings);
1420
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001421 // This maps spelling index values to semantic Spelling enumerants.
1422 SemanticSpellingMap SemanticToSyntacticMap;
Aaron Ballman36a53502014-01-16 13:03:14 +00001423
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001424 if (!ElideSpelling)
1425 OS << CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);
Aaron Ballman36a53502014-01-16 13:03:14 +00001426
1427 OS << " static " << R.getName() << "Attr *CreateImplicit(";
1428 OS << "ASTContext &Ctx";
1429 if (!ElideSpelling)
1430 OS << ", Spelling S";
1431 for (ai = Args.begin(); ai != ae; ++ai) {
1432 OS << ", ";
1433 (*ai)->writeCtorParameters(OS);
1434 }
1435 OS << ", SourceRange Loc = SourceRange()";
1436 OS << ") {\n";
1437 OS << " " << R.getName() << "Attr *A = new (Ctx) " << R.getName();
1438 OS << "Attr(Loc, Ctx, ";
1439 for (ai = Args.begin(); ai != ae; ++ai) {
1440 (*ai)->writeImplicitCtorArgs(OS);
1441 OS << ", ";
1442 }
1443 OS << (ElideSpelling ? "0" : "S") << ");\n";
1444 OS << " A->setImplicit(true);\n";
1445 OS << " return A;\n }\n\n";
1446
Peter Collingbournebee583f2011-10-06 13:03:08 +00001447 OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
1448
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001449 bool HasOpt = false;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001450 for (ai = Args.begin(); ai != ae; ++ai) {
1451 OS << " , ";
1452 (*ai)->writeCtorParameters(OS);
1453 OS << "\n";
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001454 if ((*ai)->isOptional())
1455 HasOpt = true;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001456 }
Michael Han99315932013-01-24 16:46:58 +00001457
1458 OS << " , ";
Aaron Ballman36a53502014-01-16 13:03:14 +00001459 OS << "unsigned SI\n";
Michael Han99315932013-01-24 16:46:58 +00001460
Peter Collingbournebee583f2011-10-06 13:03:08 +00001461 OS << " )\n";
Michael Han99315932013-01-24 16:46:58 +00001462 OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001463
1464 for (ai = Args.begin(); ai != ae; ++ai) {
1465 OS << " , ";
1466 (*ai)->writeCtorInitializers(OS);
1467 OS << "\n";
1468 }
1469
1470 OS << " {\n";
1471
1472 for (ai = Args.begin(); ai != ae; ++ai) {
1473 (*ai)->writeCtorBody(OS);
1474 OS << "\n";
1475 }
1476 OS << " }\n\n";
1477
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001478 // If there are optional arguments, write out a constructor that elides the
1479 // optional arguments as well.
1480 if (HasOpt) {
1481 OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
1482 for (ai = Args.begin(); ai != ae; ++ai) {
1483 if (!(*ai)->isOptional()) {
1484 OS << " , ";
1485 (*ai)->writeCtorParameters(OS);
1486 OS << "\n";
1487 }
1488 }
1489
1490 OS << " , ";
Aaron Ballman36a53502014-01-16 13:03:14 +00001491 OS << "unsigned SI\n";
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001492
1493 OS << " )\n";
1494 OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n";
1495
1496 for (ai = Args.begin(); ai != ae; ++ai) {
1497 OS << " , ";
1498 (*ai)->writeCtorDefaultInitializers(OS);
1499 OS << "\n";
1500 }
1501
1502 OS << " {\n";
1503
1504 for (ai = Args.begin(); ai != ae; ++ai) {
1505 if (!(*ai)->isOptional()) {
1506 (*ai)->writeCtorBody(OS);
1507 OS << "\n";
1508 }
1509 }
1510 OS << " }\n\n";
1511 }
1512
Peter Collingbournebee583f2011-10-06 13:03:08 +00001513 OS << " virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n";
Michael Han38d96ab2013-01-27 00:06:24 +00001514 OS << " virtual void printPretty(raw_ostream &OS,\n"
Richard Smith52f04a22012-08-16 02:43:29 +00001515 << " const PrintingPolicy &Policy) const;\n";
Aaron Ballman3e424b52013-12-26 18:30:57 +00001516 OS << " virtual const char *getSpelling() const;\n";
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001517
1518 if (!ElideSpelling) {
1519 assert(!SemanticToSyntacticMap.empty() && "Empty semantic mapping list");
1520 OS << " Spelling getSemanticSpelling() const {\n";
1521 WriteSemanticSpellingSwitch("SpellingListIndex", SemanticToSyntacticMap,
1522 OS);
1523 OS << " }\n";
1524 }
Peter Collingbournebee583f2011-10-06 13:03:08 +00001525
Michael Hanaf02bbe2013-02-01 01:19:17 +00001526 writeAttrAccessorDefinition(R, OS);
1527
Peter Collingbournebee583f2011-10-06 13:03:08 +00001528 for (ai = Args.begin(); ai != ae; ++ai) {
1529 (*ai)->writeAccessors(OS);
1530 OS << "\n\n";
Aaron Ballman682ee422013-09-11 19:47:58 +00001531
1532 if ((*ai)->isEnumArg()) {
1533 EnumArgument *EA = (EnumArgument *)*ai;
1534 EA->writeConversion(OS);
DeLesley Hutchins210791a2013-10-04 21:28:06 +00001535 } else if ((*ai)->isVariadicEnumArg()) {
1536 VariadicEnumArgument *VEA = (VariadicEnumArgument *)*ai;
1537 VEA->writeConversion(OS);
Aaron Ballman682ee422013-09-11 19:47:58 +00001538 }
Peter Collingbournebee583f2011-10-06 13:03:08 +00001539 }
1540
Jakob Stoklund Olesen6f2288b62012-01-13 04:57:47 +00001541 OS << R.getValueAsString("AdditionalMembers");
Peter Collingbournebee583f2011-10-06 13:03:08 +00001542 OS << "\n\n";
1543
1544 OS << " static bool classof(const Attr *A) { return A->getKind() == "
1545 << "attr::" << R.getName() << "; }\n";
DeLesley Hutchins30398dd2012-01-20 22:50:54 +00001546
1547 bool LateParsed = R.getValueAsBit("LateParsed");
1548 OS << " virtual bool isLateParsed() const { return "
1549 << LateParsed << "; }\n";
1550
Aaron Ballmanb9023ed2014-01-20 18:07:09 +00001551 if (R.getValueAsBit("DuplicatesAllowedWhileMerging"))
1552 OS << " virtual bool duplicatesAllowed() const { return true; }\n\n";
1553
Peter Collingbournebee583f2011-10-06 13:03:08 +00001554 OS << "};\n\n";
1555 }
1556
1557 OS << "#endif\n";
1558}
1559
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001560// Emits the class method definitions for attributes.
1561void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00001562 emitSourceFileHeader("Attribute classes' member function definitions", OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001563
1564 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1565 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ri, re;
1566 std::vector<Argument*>::iterator ai, ae;
1567
1568 for (; i != e; ++i) {
1569 Record &R = **i;
Douglas Gregorb2daf842012-05-02 15:56:52 +00001570
1571 if (!R.getValueAsBit("ASTNode"))
1572 continue;
1573
Peter Collingbournebee583f2011-10-06 13:03:08 +00001574 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
1575 std::vector<Argument*> Args;
1576 for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri)
Aaron Ballmanaa47d242013-12-19 19:39:25 +00001577 Args.push_back(createArgument(**ri, R.getName()));
Peter Collingbournebee583f2011-10-06 13:03:08 +00001578
1579 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
1580 (*ai)->writeAccessorDefinitions(OS);
1581
1582 OS << R.getName() << "Attr *" << R.getName()
1583 << "Attr::clone(ASTContext &C) const {\n";
1584 OS << " return new (C) " << R.getName() << "Attr(getLocation(), C";
1585 for (ai = Args.begin(); ai != ae; ++ai) {
1586 OS << ", ";
1587 (*ai)->writeCloneArgs(OS);
1588 }
Richard Smitha5aaca92013-01-29 04:21:28 +00001589 OS << ", getSpellingListIndex());\n}\n\n";
Douglas Gregor49ccfaa2011-11-19 19:22:57 +00001590
Michael Han99315932013-01-24 16:46:58 +00001591 writePrettyPrintFunction(R, Args, OS);
Aaron Ballman3e424b52013-12-26 18:30:57 +00001592 writeGetSpellingFunction(R, OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001593 }
1594}
1595
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001596} // end namespace clang
1597
Peter Collingbournebee583f2011-10-06 13:03:08 +00001598static void EmitAttrList(raw_ostream &OS, StringRef Class,
1599 const std::vector<Record*> &AttrList) {
1600 std::vector<Record*>::const_iterator i = AttrList.begin(), e = AttrList.end();
1601
1602 if (i != e) {
1603 // Move the end iterator back to emit the last attribute.
Douglas Gregorb2daf842012-05-02 15:56:52 +00001604 for(--e; i != e; ++i) {
1605 if (!(*i)->getValueAsBit("ASTNode"))
1606 continue;
1607
Peter Collingbournebee583f2011-10-06 13:03:08 +00001608 OS << Class << "(" << (*i)->getName() << ")\n";
Douglas Gregorb2daf842012-05-02 15:56:52 +00001609 }
Peter Collingbournebee583f2011-10-06 13:03:08 +00001610
1611 OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n";
1612 }
1613}
1614
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001615namespace clang {
1616
1617// Emits the enumeration list for attributes.
1618void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00001619 emitSourceFileHeader("List of all attributes that Clang recognizes", OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001620
1621 OS << "#ifndef LAST_ATTR\n";
1622 OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n";
1623 OS << "#endif\n\n";
1624
1625 OS << "#ifndef INHERITABLE_ATTR\n";
1626 OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n";
1627 OS << "#endif\n\n";
1628
1629 OS << "#ifndef LAST_INHERITABLE_ATTR\n";
1630 OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n";
1631 OS << "#endif\n\n";
1632
1633 OS << "#ifndef INHERITABLE_PARAM_ATTR\n";
1634 OS << "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n";
1635 OS << "#endif\n\n";
1636
1637 OS << "#ifndef LAST_INHERITABLE_PARAM_ATTR\n";
1638 OS << "#define LAST_INHERITABLE_PARAM_ATTR(NAME)"
1639 " INHERITABLE_PARAM_ATTR(NAME)\n";
1640 OS << "#endif\n\n";
1641
1642 Record *InhClass = Records.getClass("InheritableAttr");
1643 Record *InhParamClass = Records.getClass("InheritableParamAttr");
1644 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
Aaron Ballman8edb5c22013-12-18 23:44:18 +00001645 NonInhAttrs, InhAttrs, InhParamAttrs;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001646 for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
1647 i != e; ++i) {
Douglas Gregorb2daf842012-05-02 15:56:52 +00001648 if (!(*i)->getValueAsBit("ASTNode"))
1649 continue;
1650
Peter Collingbournebee583f2011-10-06 13:03:08 +00001651 if ((*i)->isSubClassOf(InhParamClass))
1652 InhParamAttrs.push_back(*i);
1653 else if ((*i)->isSubClassOf(InhClass))
1654 InhAttrs.push_back(*i);
1655 else
1656 NonInhAttrs.push_back(*i);
1657 }
1658
1659 EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs);
1660 EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs);
1661 EmitAttrList(OS, "ATTR", NonInhAttrs);
1662
1663 OS << "#undef LAST_ATTR\n";
1664 OS << "#undef INHERITABLE_ATTR\n";
1665 OS << "#undef LAST_INHERITABLE_ATTR\n";
1666 OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n";
1667 OS << "#undef ATTR\n";
1668}
1669
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001670// Emits the code to read an attribute from a precompiled header.
1671void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00001672 emitSourceFileHeader("Attribute deserialization code", OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001673
1674 Record *InhClass = Records.getClass("InheritableAttr");
1675 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
1676 ArgRecords;
1677 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
1678 std::vector<Argument*> Args;
1679 std::vector<Argument*>::iterator ri, re;
1680
1681 OS << " switch (Kind) {\n";
1682 OS << " default:\n";
1683 OS << " assert(0 && \"Unknown attribute!\");\n";
1684 OS << " break;\n";
1685 for (; i != e; ++i) {
1686 Record &R = **i;
Douglas Gregorb2daf842012-05-02 15:56:52 +00001687 if (!R.getValueAsBit("ASTNode"))
1688 continue;
1689
Peter Collingbournebee583f2011-10-06 13:03:08 +00001690 OS << " case attr::" << R.getName() << ": {\n";
1691 if (R.isSubClassOf(InhClass))
1692 OS << " bool isInherited = Record[Idx++];\n";
Aaron Ballman36a53502014-01-16 13:03:14 +00001693 OS << " bool isImplicit = Record[Idx++];\n";
1694 OS << " unsigned Spelling = Record[Idx++];\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001695 ArgRecords = R.getValueAsListOfDefs("Args");
1696 Args.clear();
1697 for (ai = ArgRecords.begin(), ae = ArgRecords.end(); ai != ae; ++ai) {
Aaron Ballmanaa47d242013-12-19 19:39:25 +00001698 Argument *A = createArgument(**ai, R.getName());
Peter Collingbournebee583f2011-10-06 13:03:08 +00001699 Args.push_back(A);
1700 A->writePCHReadDecls(OS);
1701 }
1702 OS << " New = new (Context) " << R.getName() << "Attr(Range, Context";
1703 for (ri = Args.begin(), re = Args.end(); ri != re; ++ri) {
1704 OS << ", ";
1705 (*ri)->writePCHReadArgs(OS);
1706 }
Aaron Ballman36a53502014-01-16 13:03:14 +00001707 OS << ", Spelling);\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001708 if (R.isSubClassOf(InhClass))
1709 OS << " cast<InheritableAttr>(New)->setInherited(isInherited);\n";
Aaron Ballman36a53502014-01-16 13:03:14 +00001710 OS << " New->setImplicit(isImplicit);\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001711 OS << " break;\n";
1712 OS << " }\n";
1713 }
1714 OS << " }\n";
1715}
1716
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001717// Emits the code to write an attribute to a precompiled header.
1718void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00001719 emitSourceFileHeader("Attribute serialization code", OS);
1720
Peter Collingbournebee583f2011-10-06 13:03:08 +00001721 Record *InhClass = Records.getClass("InheritableAttr");
1722 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
1723 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
1724
1725 OS << " switch (A->getKind()) {\n";
1726 OS << " default:\n";
1727 OS << " llvm_unreachable(\"Unknown attribute kind!\");\n";
1728 OS << " break;\n";
1729 for (; i != e; ++i) {
1730 Record &R = **i;
Douglas Gregorb2daf842012-05-02 15:56:52 +00001731 if (!R.getValueAsBit("ASTNode"))
1732 continue;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001733 OS << " case attr::" << R.getName() << ": {\n";
1734 Args = R.getValueAsListOfDefs("Args");
1735 if (R.isSubClassOf(InhClass) || !Args.empty())
1736 OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
1737 << "Attr>(A);\n";
1738 if (R.isSubClassOf(InhClass))
1739 OS << " Record.push_back(SA->isInherited());\n";
Aaron Ballman36a53502014-01-16 13:03:14 +00001740 OS << " Record.push_back(A->isImplicit());\n";
1741 OS << " Record.push_back(A->getSpellingListIndex());\n";
1742
Peter Collingbournebee583f2011-10-06 13:03:08 +00001743 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
1744 createArgument(**ai, R.getName())->writePCHWrite(OS);
1745 OS << " break;\n";
1746 OS << " }\n";
1747 }
1748 OS << " }\n";
1749}
1750
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001751// Emits the list of spellings for attributes.
1752void EmitClangAttrSpellingList(RecordKeeper &Records, raw_ostream &OS) {
Aaron Ballman0fa06d82014-01-09 22:57:44 +00001753 emitSourceFileHeader("llvm::StringSwitch code to match attributes based on "
1754 "the target triple, T", OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001755
1756 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1757
Aaron Ballman0fa06d82014-01-09 22:57:44 +00001758 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1759 I != E; ++I) {
Peter Collingbournebee583f2011-10-06 13:03:08 +00001760 Record &Attr = **I;
1761
Aaron Ballman0fa06d82014-01-09 22:57:44 +00001762 // It is assumed that there will be an llvm::Triple object named T within
1763 // scope that can be used to determine whether the attribute exists in
1764 // a given target.
1765 std::string Test;
1766 if (Attr.isSubClassOf("TargetSpecificAttr")) {
1767 const Record *R = Attr.getValueAsDef("Target");
1768 std::vector<std::string> Arches = R->getValueAsListOfStrings("Arches");
Peter Collingbournebee583f2011-10-06 13:03:08 +00001769
Aaron Ballman0fa06d82014-01-09 22:57:44 +00001770 Test += "(";
1771 for (std::vector<std::string>::const_iterator AI = Arches.begin(),
1772 AE = Arches.end(); AI != AE; ++AI) {
1773 std::string Part = *AI;
1774 Test += "T.getArch() == llvm::Triple::" + Part;
1775 if (AI + 1 != AE)
1776 Test += " || ";
1777 }
1778 Test += ")";
1779
1780 std::vector<std::string> OSes;
1781 if (!R->isValueUnset("OSes")) {
1782 Test += " && (";
1783 std::vector<std::string> OSes = R->getValueAsListOfStrings("OSes");
1784 for (std::vector<std::string>::const_iterator AI = OSes.begin(),
1785 AE = OSes.end(); AI != AE; ++AI) {
1786 std::string Part = *AI;
1787
1788 Test += "T.getOS() == llvm::Triple::" + Part;
1789 if (AI + 1 != AE)
1790 Test += " || ";
1791 }
1792 Test += ")";
1793 }
1794 } else
1795 Test = "true";
1796
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001797 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
1798 for (std::vector<FlattenedSpelling>::const_iterator I = Spellings.begin(),
1799 E = Spellings.end(); I != E; ++I)
1800 OS << ".Case(\"" << I->name() << "\", " << Test << ")\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001801 }
1802
1803}
1804
Michael Han99315932013-01-24 16:46:58 +00001805void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00001806 emitSourceFileHeader("Code to translate different attribute spellings "
1807 "into internal identifiers", OS);
Michael Han99315932013-01-24 16:46:58 +00001808
1809 OS <<
Michael Han99315932013-01-24 16:46:58 +00001810 " switch (AttrKind) {\n"
1811 " default:\n"
1812 " llvm_unreachable(\"Unknown attribute kind!\");\n"
1813 " break;\n";
1814
Aaron Ballman64e69862013-12-15 13:05:48 +00001815 ParsedAttrMap Attrs = getParsedAttrList(Records);
1816 for (ParsedAttrMap::const_iterator I = Attrs.begin(), E = Attrs.end();
Michael Han99315932013-01-24 16:46:58 +00001817 I != E; ++I) {
Aaron Ballman64e69862013-12-15 13:05:48 +00001818 Record &R = *I->second;
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001819 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
Aaron Ballman64e69862013-12-15 13:05:48 +00001820 OS << " case AT_" << I->first << ": {\n";
Richard Smith852e9ce2013-11-27 01:46:48 +00001821 for (unsigned I = 0; I < Spellings.size(); ++ I) {
Richard Smith852e9ce2013-11-27 01:46:48 +00001822 OS << " if (Name == \""
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001823 << Spellings[I].name() << "\" && "
Richard Smith852e9ce2013-11-27 01:46:48 +00001824 << "SyntaxUsed == "
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001825 << StringSwitch<unsigned>(Spellings[I].variety())
Richard Smith852e9ce2013-11-27 01:46:48 +00001826 .Case("GNU", 0)
1827 .Case("CXX11", 1)
1828 .Case("Declspec", 2)
1829 .Case("Keyword", 3)
1830 .Default(0)
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001831 << " && Scope == \"" << Spellings[I].nameSpace() << "\")\n"
Richard Smith852e9ce2013-11-27 01:46:48 +00001832 << " return " << I << ";\n";
Michael Han99315932013-01-24 16:46:58 +00001833 }
Richard Smith852e9ce2013-11-27 01:46:48 +00001834
1835 OS << " break;\n";
1836 OS << " }\n";
Michael Han99315932013-01-24 16:46:58 +00001837 }
1838
1839 OS << " }\n";
Aaron Ballman64e69862013-12-15 13:05:48 +00001840 OS << " return 0;\n";
Michael Han99315932013-01-24 16:46:58 +00001841}
1842
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +00001843// Emits code used by RecursiveASTVisitor to visit attributes
1844void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS) {
1845 emitSourceFileHeader("Used by RecursiveASTVisitor to visit attributes.", OS);
1846
1847 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1848
1849 // Write method declarations for Traverse* methods.
1850 // We emit this here because we only generate methods for attributes that
1851 // are declared as ASTNodes.
1852 OS << "#ifdef ATTR_VISITOR_DECLS_ONLY\n\n";
1853 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1854 I != E; ++I) {
1855 Record &R = **I;
1856 if (!R.getValueAsBit("ASTNode"))
1857 continue;
1858 OS << " bool Traverse"
1859 << R.getName() << "Attr(" << R.getName() << "Attr *A);\n";
1860 OS << " bool Visit"
1861 << R.getName() << "Attr(" << R.getName() << "Attr *A) {\n"
1862 << " return true; \n"
1863 << " };\n";
1864 }
1865 OS << "\n#else // ATTR_VISITOR_DECLS_ONLY\n\n";
1866
1867 // Write individual Traverse* methods for each attribute class.
1868 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1869 I != E; ++I) {
1870 Record &R = **I;
1871 if (!R.getValueAsBit("ASTNode"))
1872 continue;
1873
1874 OS << "template <typename Derived>\n"
DeLesley Hutchinsbb79c332013-12-30 21:03:02 +00001875 << "bool VISITORCLASS<Derived>::Traverse"
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +00001876 << R.getName() << "Attr(" << R.getName() << "Attr *A) {\n"
1877 << " if (!getDerived().VisitAttr(A))\n"
1878 << " return false;\n"
1879 << " if (!getDerived().Visit" << R.getName() << "Attr(A))\n"
1880 << " return false;\n";
1881
1882 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
1883 for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
1884 re = ArgRecords.end();
1885 ri != re; ++ri) {
1886 Record &ArgRecord = **ri;
1887 Argument *Arg = createArgument(ArgRecord, R.getName());
1888 assert(Arg);
1889 Arg->writeASTVisitorTraversal(OS);
1890 }
1891
1892 OS << " return true;\n";
1893 OS << "}\n\n";
1894 }
1895
1896 // Write generic Traverse routine
1897 OS << "template <typename Derived>\n"
DeLesley Hutchinsbb79c332013-12-30 21:03:02 +00001898 << "bool VISITORCLASS<Derived>::TraverseAttr(Attr *A) {\n"
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +00001899 << " if (!A)\n"
1900 << " return true;\n"
1901 << "\n"
1902 << " switch (A->getKind()) {\n"
1903 << " default:\n"
1904 << " return true;\n";
1905
1906 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1907 I != E; ++I) {
1908 Record &R = **I;
1909 if (!R.getValueAsBit("ASTNode"))
1910 continue;
1911
1912 OS << " case attr::" << R.getName() << ":\n"
1913 << " return getDerived().Traverse" << R.getName() << "Attr("
1914 << "cast<" << R.getName() << "Attr>(A));\n";
1915 }
1916 OS << " }\n"; // end case
1917 OS << "}\n"; // end function
1918 OS << "#endif // ATTR_VISITOR_DECLS_ONLY\n";
1919}
1920
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001921// Emits code to instantiate dependent attributes on templates.
1922void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00001923 emitSourceFileHeader("Template instantiation code for attributes", OS);
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001924
1925 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1926
Benjamin Kramerbf8da9d2012-02-06 11:13:08 +00001927 OS << "namespace clang {\n"
1928 << "namespace sema {\n\n"
1929 << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, "
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001930 << "Sema &S,\n"
1931 << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n"
1932 << " switch (At->getKind()) {\n"
1933 << " default:\n"
1934 << " break;\n";
1935
1936 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1937 I != E; ++I) {
1938 Record &R = **I;
Douglas Gregorb2daf842012-05-02 15:56:52 +00001939 if (!R.getValueAsBit("ASTNode"))
1940 continue;
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001941
1942 OS << " case attr::" << R.getName() << ": {\n";
Rafael Espindola7f90b7d2012-05-15 14:09:55 +00001943 bool ShouldClone = R.getValueAsBit("Clone");
1944
1945 if (!ShouldClone) {
1946 OS << " return NULL;\n";
1947 OS << " }\n";
1948 continue;
1949 }
1950
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001951 OS << " const " << R.getName() << "Attr *A = cast<"
1952 << R.getName() << "Attr>(At);\n";
1953 bool TDependent = R.getValueAsBit("TemplateDependent");
1954
1955 if (!TDependent) {
1956 OS << " return A->clone(C);\n";
1957 OS << " }\n";
1958 continue;
1959 }
1960
1961 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
1962 std::vector<Argument*> Args;
1963 std::vector<Argument*>::iterator ai, ae;
1964 Args.reserve(ArgRecords.size());
1965
1966 for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
1967 re = ArgRecords.end();
1968 ri != re; ++ri) {
1969 Record &ArgRecord = **ri;
Aaron Ballmanaa47d242013-12-19 19:39:25 +00001970 Argument *Arg = createArgument(ArgRecord, R.getName());
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001971 assert(Arg);
1972 Args.push_back(Arg);
1973 }
1974 ae = Args.end();
1975
1976 for (ai = Args.begin(); ai != ae; ++ai) {
1977 (*ai)->writeTemplateInstantiation(OS);
1978 }
1979 OS << " return new (C) " << R.getName() << "Attr(A->getLocation(), C";
1980 for (ai = Args.begin(); ai != ae; ++ai) {
1981 OS << ", ";
1982 (*ai)->writeTemplateInstantiationArgs(OS);
1983 }
Aaron Ballman36a53502014-01-16 13:03:14 +00001984 OS << ", A->getSpellingListIndex());\n }\n";
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001985 }
1986 OS << " } // end switch\n"
1987 << " llvm_unreachable(\"Unknown attribute!\");\n"
1988 << " return 0;\n"
Benjamin Kramerbf8da9d2012-02-06 11:13:08 +00001989 << "}\n\n"
1990 << "} // end namespace sema\n"
1991 << "} // end namespace clang\n";
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001992}
1993
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001994// Emits the list of parsed attributes.
1995void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) {
1996 emitSourceFileHeader("List of all attributes that Clang recognizes", OS);
1997
1998 OS << "#ifndef PARSED_ATTR\n";
1999 OS << "#define PARSED_ATTR(NAME) NAME\n";
2000 OS << "#endif\n\n";
2001
2002 ParsedAttrMap Names = getParsedAttrList(Records);
2003 for (ParsedAttrMap::iterator I = Names.begin(), E = Names.end(); I != E;
2004 ++I) {
2005 OS << "PARSED_ATTR(" << I->first << ")\n";
2006 }
2007}
2008
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002009static void emitArgInfo(const Record &R, std::stringstream &OS) {
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002010 // This function will count the number of arguments specified for the
2011 // attribute and emit the number of required arguments followed by the
2012 // number of optional arguments.
2013 std::vector<Record *> Args = R.getValueAsListOfDefs("Args");
2014 unsigned ArgCount = 0, OptCount = 0;
2015 for (std::vector<Record *>::const_iterator I = Args.begin(), E = Args.end();
2016 I != E; ++I) {
2017 const Record &Arg = **I;
2018 Arg.getValueAsBit("Optional") ? ++OptCount : ++ArgCount;
2019 }
2020 OS << ArgCount << ", " << OptCount;
2021}
2022
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002023static void GenerateDefaultAppertainsTo(raw_ostream &OS) {
Aaron Ballman93b5cc62013-12-02 19:36:42 +00002024 OS << "static bool defaultAppertainsTo(Sema &, const AttributeList &,";
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002025 OS << "const Decl *) {\n";
2026 OS << " return true;\n";
2027 OS << "}\n\n";
2028}
2029
2030static std::string CalculateDiagnostic(const Record &S) {
2031 // If the SubjectList object has a custom diagnostic associated with it,
2032 // return that directly.
2033 std::string CustomDiag = S.getValueAsString("CustomDiag");
2034 if (!CustomDiag.empty())
2035 return CustomDiag;
2036
2037 // Given the list of subjects, determine what diagnostic best fits.
2038 enum {
2039 Func = 1U << 0,
2040 Var = 1U << 1,
2041 ObjCMethod = 1U << 2,
2042 Param = 1U << 3,
2043 Class = 1U << 4,
Aaron Ballmanc1494bd2013-11-27 20:14:30 +00002044 GenericRecord = 1U << 5,
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002045 Type = 1U << 6,
2046 ObjCIVar = 1U << 7,
2047 ObjCProp = 1U << 8,
2048 ObjCInterface = 1U << 9,
2049 Block = 1U << 10,
2050 Namespace = 1U << 11,
2051 FuncTemplate = 1U << 12,
2052 Field = 1U << 13,
Ted Kremenekd980da22013-12-10 19:43:42 +00002053 CXXMethod = 1U << 14,
2054 ObjCProtocol = 1U << 15
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002055 };
2056 uint32_t SubMask = 0;
2057
2058 std::vector<Record *> Subjects = S.getValueAsListOfDefs("Subjects");
2059 for (std::vector<Record *>::const_iterator I = Subjects.begin(),
2060 E = Subjects.end(); I != E; ++I) {
Aaron Ballman80469032013-11-29 14:57:58 +00002061 const Record &R = (**I);
2062 std::string Name;
2063
2064 if (R.isSubClassOf("SubsetSubject")) {
2065 PrintError(R.getLoc(), "SubsetSubjects should use a custom diagnostic");
2066 // As a fallback, look through the SubsetSubject to see what its base
2067 // type is, and use that. This needs to be updated if SubsetSubjects
2068 // are allowed within other SubsetSubjects.
2069 Name = R.getValueAsDef("Base")->getName();
2070 } else
2071 Name = R.getName();
2072
2073 uint32_t V = StringSwitch<uint32_t>(Name)
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002074 .Case("Function", Func)
2075 .Case("Var", Var)
2076 .Case("ObjCMethod", ObjCMethod)
2077 .Case("ParmVar", Param)
2078 .Case("TypedefName", Type)
2079 .Case("ObjCIvar", ObjCIVar)
2080 .Case("ObjCProperty", ObjCProp)
Aaron Ballmanc1494bd2013-11-27 20:14:30 +00002081 .Case("Record", GenericRecord)
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002082 .Case("ObjCInterface", ObjCInterface)
Ted Kremenekd980da22013-12-10 19:43:42 +00002083 .Case("ObjCProtocol", ObjCProtocol)
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002084 .Case("Block", Block)
2085 .Case("CXXRecord", Class)
2086 .Case("Namespace", Namespace)
2087 .Case("FunctionTemplate", FuncTemplate)
2088 .Case("Field", Field)
2089 .Case("CXXMethod", CXXMethod)
2090 .Default(0);
2091 if (!V) {
2092 // Something wasn't in our mapping, so be helpful and let the developer
2093 // know about it.
2094 PrintFatalError((*I)->getLoc(), "Unknown subject type: " +
2095 (*I)->getName());
2096 return "";
2097 }
2098
2099 SubMask |= V;
2100 }
2101
2102 switch (SubMask) {
2103 // For the simple cases where there's only a single entry in the mask, we
2104 // don't have to resort to bit fiddling.
2105 case Func: return "ExpectedFunction";
2106 case Var: return "ExpectedVariable";
2107 case Param: return "ExpectedParameter";
2108 case Class: return "ExpectedClass";
2109 case CXXMethod:
2110 // FIXME: Currently, this maps to ExpectedMethod based on existing code,
2111 // but should map to something a bit more accurate at some point.
2112 case ObjCMethod: return "ExpectedMethod";
2113 case Type: return "ExpectedType";
2114 case ObjCInterface: return "ExpectedObjectiveCInterface";
Ted Kremenekd980da22013-12-10 19:43:42 +00002115 case ObjCProtocol: return "ExpectedObjectiveCProtocol";
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002116
Aaron Ballmanc1494bd2013-11-27 20:14:30 +00002117 // "GenericRecord" means struct, union or class; check the language options
2118 // and if not compiling for C++, strip off the class part. Note that this
2119 // relies on the fact that the context for this declares "Sema &S".
2120 case GenericRecord:
Aaron Ballman17046b82013-11-27 19:16:55 +00002121 return "(S.getLangOpts().CPlusPlus ? ExpectedStructOrUnionOrClass : "
2122 "ExpectedStructOrUnion)";
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002123 case Func | ObjCMethod | Block: return "ExpectedFunctionMethodOrBlock";
2124 case Func | ObjCMethod | Class: return "ExpectedFunctionMethodOrClass";
2125 case Func | Param:
2126 case Func | ObjCMethod | Param: return "ExpectedFunctionMethodOrParameter";
2127 case Func | FuncTemplate:
2128 case Func | ObjCMethod: return "ExpectedFunctionOrMethod";
2129 case Func | Var: return "ExpectedVariableOrFunction";
Aaron Ballman604dfec2013-12-02 17:07:07 +00002130
2131 // If not compiling for C++, the class portion does not apply.
2132 case Func | Var | Class:
2133 return "(S.getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass : "
2134 "ExpectedVariableOrFunction)";
2135
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002136 case ObjCMethod | ObjCProp: return "ExpectedMethodOrProperty";
2137 case Field | Var: return "ExpectedFieldOrGlobalVar";
2138 }
2139
2140 PrintFatalError(S.getLoc(),
2141 "Could not deduce diagnostic argument for Attr subjects");
2142
2143 return "";
2144}
2145
Aaron Ballman12b9f652014-01-16 13:55:42 +00002146static std::string GetSubjectWithSuffix(const Record *R) {
2147 std::string B = R->getName();
2148 if (B == "DeclBase")
2149 return "Decl";
2150 return B + "Decl";
2151}
Aaron Ballman80469032013-11-29 14:57:58 +00002152static std::string GenerateCustomAppertainsTo(const Record &Subject,
2153 raw_ostream &OS) {
Aaron Ballmana358c902013-12-02 14:58:17 +00002154 std::string FnName = "is" + Subject.getName();
2155
Aaron Ballman80469032013-11-29 14:57:58 +00002156 // If this code has already been generated, simply return the previous
2157 // instance of it.
2158 static std::set<std::string> CustomSubjectSet;
Aaron Ballmana358c902013-12-02 14:58:17 +00002159 std::set<std::string>::iterator I = CustomSubjectSet.find(FnName);
Aaron Ballman80469032013-11-29 14:57:58 +00002160 if (I != CustomSubjectSet.end())
2161 return *I;
2162
2163 Record *Base = Subject.getValueAsDef("Base");
2164
2165 // Not currently support custom subjects within custom subjects.
2166 if (Base->isSubClassOf("SubsetSubject")) {
2167 PrintFatalError(Subject.getLoc(),
2168 "SubsetSubjects within SubsetSubjects is not supported");
2169 return "";
2170 }
2171
Aaron Ballman80469032013-11-29 14:57:58 +00002172 OS << "static bool " << FnName << "(const Decl *D) {\n";
Aaron Ballman47553042014-01-16 14:32:03 +00002173 OS << " if (const " << GetSubjectWithSuffix(Base) << " *S = dyn_cast<";
Aaron Ballman12b9f652014-01-16 13:55:42 +00002174 OS << GetSubjectWithSuffix(Base);
Aaron Ballman47553042014-01-16 14:32:03 +00002175 OS << ">(D))\n";
2176 OS << " return " << Subject.getValueAsString("CheckCode") << ";\n";
2177 OS << " return false;\n";
Aaron Ballman80469032013-11-29 14:57:58 +00002178 OS << "}\n\n";
2179
2180 CustomSubjectSet.insert(FnName);
2181 return FnName;
2182}
2183
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002184static std::string GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) {
2185 // If the attribute does not contain a Subjects definition, then use the
2186 // default appertainsTo logic.
2187 if (Attr.isValueUnset("Subjects"))
Aaron Ballman93b5cc62013-12-02 19:36:42 +00002188 return "defaultAppertainsTo";
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002189
2190 const Record *SubjectObj = Attr.getValueAsDef("Subjects");
2191 std::vector<Record*> Subjects = SubjectObj->getValueAsListOfDefs("Subjects");
2192
2193 // If the list of subjects is empty, it is assumed that the attribute
2194 // appertains to everything.
2195 if (Subjects.empty())
Aaron Ballman93b5cc62013-12-02 19:36:42 +00002196 return "defaultAppertainsTo";
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002197
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002198 bool Warn = SubjectObj->getValueAsDef("Diag")->getValueAsBit("Warn");
2199
2200 // Otherwise, generate an appertainsTo check specific to this attribute which
2201 // checks all of the given subjects against the Decl passed in. Return the
2202 // name of that check to the caller.
Aaron Ballman00dcc432013-12-03 13:45:50 +00002203 std::string FnName = "check" + Attr.getName() + "AppertainsTo";
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002204 std::stringstream SS;
2205 SS << "static bool " << FnName << "(Sema &S, const AttributeList &Attr, ";
2206 SS << "const Decl *D) {\n";
2207 SS << " if (";
2208 for (std::vector<Record *>::const_iterator I = Subjects.begin(),
2209 E = Subjects.end(); I != E; ++I) {
Aaron Ballman80469032013-11-29 14:57:58 +00002210 // If the subject has custom code associated with it, generate a function
2211 // for it. The function cannot be inlined into this check (yet) because it
2212 // requires the subject to be of a specific type, and were that information
2213 // inlined here, it would not support an attribute with multiple custom
2214 // subjects.
2215 if ((*I)->isSubClassOf("SubsetSubject")) {
2216 SS << "!" << GenerateCustomAppertainsTo(**I, OS) << "(D)";
2217 } else {
Aaron Ballman12b9f652014-01-16 13:55:42 +00002218 SS << "!isa<" << GetSubjectWithSuffix(*I) << ">(D)";
Aaron Ballman80469032013-11-29 14:57:58 +00002219 }
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002220
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002221 if (I + 1 != E)
2222 SS << " && ";
2223 }
2224 SS << ") {\n";
2225 SS << " S.Diag(Attr.getLoc(), diag::";
2226 SS << (Warn ? "warn_attribute_wrong_decl_type" :
2227 "err_attribute_wrong_decl_type");
2228 SS << ")\n";
2229 SS << " << Attr.getName() << ";
2230 SS << CalculateDiagnostic(*SubjectObj) << ";\n";
2231 SS << " return false;\n";
2232 SS << " }\n";
2233 SS << " return true;\n";
2234 SS << "}\n\n";
2235
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002236 OS << SS.str();
2237 return FnName;
2238}
2239
Aaron Ballman3aff6332013-12-02 19:30:36 +00002240static void GenerateDefaultLangOptRequirements(raw_ostream &OS) {
2241 OS << "static bool defaultDiagnoseLangOpts(Sema &, ";
2242 OS << "const AttributeList &) {\n";
2243 OS << " return true;\n";
2244 OS << "}\n\n";
2245}
2246
2247static std::string GenerateLangOptRequirements(const Record &R,
2248 raw_ostream &OS) {
2249 // If the attribute has an empty or unset list of language requirements,
2250 // return the default handler.
2251 std::vector<Record *> LangOpts = R.getValueAsListOfDefs("LangOpts");
2252 if (LangOpts.empty())
2253 return "defaultDiagnoseLangOpts";
2254
2255 // Generate the test condition, as well as a unique function name for the
2256 // diagnostic test. The list of options should usually be short (one or two
2257 // options), and the uniqueness isn't strictly necessary (it is just for
2258 // codegen efficiency).
2259 std::string FnName = "check", Test;
2260 for (std::vector<Record *>::const_iterator I = LangOpts.begin(),
2261 E = LangOpts.end(); I != E; ++I) {
2262 std::string Part = (*I)->getValueAsString("Name");
2263 Test += "S.LangOpts." + Part;
2264 if (I + 1 != E)
2265 Test += " || ";
2266 FnName += Part;
2267 }
2268 FnName += "LangOpts";
2269
2270 // If this code has already been generated, simply return the previous
2271 // instance of it.
2272 static std::set<std::string> CustomLangOptsSet;
2273 std::set<std::string>::iterator I = CustomLangOptsSet.find(FnName);
2274 if (I != CustomLangOptsSet.end())
2275 return *I;
2276
2277 OS << "static bool " << FnName << "(Sema &S, const AttributeList &Attr) {\n";
2278 OS << " if (" << Test << ")\n";
2279 OS << " return true;\n\n";
2280 OS << " S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) ";
2281 OS << "<< Attr.getName();\n";
2282 OS << " return false;\n";
2283 OS << "}\n\n";
2284
2285 CustomLangOptsSet.insert(FnName);
2286 return FnName;
2287}
2288
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002289static void GenerateDefaultTargetRequirements(raw_ostream &OS) {
2290 OS << "static bool defaultTargetRequirements(llvm::Triple) {\n";
2291 OS << " return true;\n";
2292 OS << "}\n\n";
2293}
2294
2295static std::string GenerateTargetRequirements(const Record &Attr,
2296 const ParsedAttrMap &Dupes,
2297 raw_ostream &OS) {
2298 // If the attribute is not a target specific attribute, return the default
2299 // target handler.
2300 if (!Attr.isSubClassOf("TargetSpecificAttr"))
2301 return "defaultTargetRequirements";
2302
2303 // Get the list of architectures to be tested for.
2304 const Record *R = Attr.getValueAsDef("Target");
2305 std::vector<std::string> Arches = R->getValueAsListOfStrings("Arches");
2306 if (Arches.empty()) {
2307 PrintError(Attr.getLoc(), "Empty list of target architectures for a "
2308 "target-specific attr");
2309 return "defaultTargetRequirements";
2310 }
2311
2312 // If there are other attributes which share the same parsed attribute kind,
2313 // such as target-specific attributes with a shared spelling, collapse the
2314 // duplicate architectures. This is required because a shared target-specific
2315 // attribute has only one AttributeList::Kind enumeration value, but it
2316 // applies to multiple target architectures. In order for the attribute to be
2317 // considered valid, all of its architectures need to be included.
2318 if (!Attr.isValueUnset("ParseKind")) {
2319 std::string APK = Attr.getValueAsString("ParseKind");
2320 for (ParsedAttrMap::const_iterator I = Dupes.begin(), E = Dupes.end();
2321 I != E; ++I) {
2322 if (I->first == APK) {
2323 std::vector<std::string> DA = I->second->getValueAsDef("Target")->
2324 getValueAsListOfStrings("Arches");
2325 std::copy(DA.begin(), DA.end(), std::back_inserter(Arches));
2326 }
2327 }
2328 }
2329
2330 std::string FnName = "isTarget", Test = "(";
2331 for (std::vector<std::string>::const_iterator I = Arches.begin(),
2332 E = Arches.end(); I != E; ++I) {
2333 std::string Part = *I;
2334 Test += "Arch == llvm::Triple::" + Part;
2335 if (I + 1 != E)
2336 Test += " || ";
2337 FnName += Part;
2338 }
2339 Test += ")";
2340
2341 // If the target also requires OS testing, generate those tests as well.
2342 bool UsesOS = false;
2343 if (!R->isValueUnset("OSes")) {
2344 UsesOS = true;
2345
2346 // We know that there was at least one arch test, so we need to and in the
2347 // OS tests.
2348 Test += " && (";
2349 std::vector<std::string> OSes = R->getValueAsListOfStrings("OSes");
2350 for (std::vector<std::string>::const_iterator I = OSes.begin(),
2351 E = OSes.end(); I != E; ++I) {
2352 std::string Part = *I;
2353
2354 Test += "OS == llvm::Triple::" + Part;
2355 if (I + 1 != E)
2356 Test += " || ";
2357 FnName += Part;
2358 }
2359 Test += ")";
2360 }
2361
2362 // If this code has already been generated, simply return the previous
2363 // instance of it.
2364 static std::set<std::string> CustomTargetSet;
2365 std::set<std::string>::iterator I = CustomTargetSet.find(FnName);
2366 if (I != CustomTargetSet.end())
2367 return *I;
2368
2369 OS << "static bool " << FnName << "(llvm::Triple T) {\n";
2370 OS << " llvm::Triple::ArchType Arch = T.getArch();\n";
2371 if (UsesOS)
2372 OS << " llvm::Triple::OSType OS = T.getOS();\n";
2373 OS << " return " << Test << ";\n";
2374 OS << "}\n\n";
2375
2376 CustomTargetSet.insert(FnName);
2377 return FnName;
2378}
2379
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00002380static void GenerateDefaultSpellingIndexToSemanticSpelling(raw_ostream &OS) {
2381 OS << "static unsigned defaultSpellingIndexToSemanticSpelling("
2382 << "const AttributeList &Attr) {\n";
2383 OS << " return UINT_MAX;\n";
2384 OS << "}\n\n";
2385}
2386
2387static std::string GenerateSpellingIndexToSemanticSpelling(const Record &Attr,
2388 raw_ostream &OS) {
2389 // If the attribute does not have a semantic form, we can bail out early.
2390 if (!Attr.getValueAsBit("ASTNode"))
2391 return "defaultSpellingIndexToSemanticSpelling";
2392
Aaron Ballmanc669cc02014-01-27 22:10:04 +00002393 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00002394
2395 // If there are zero or one spellings, or all of the spellings share the same
2396 // name, we can also bail out early.
2397 if (Spellings.size() <= 1 || SpellingNamesAreCommon(Spellings))
2398 return "defaultSpellingIndexToSemanticSpelling";
2399
2400 // Generate the enumeration we will use for the mapping.
2401 SemanticSpellingMap SemanticToSyntacticMap;
2402 std::string Enum = CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);
2403 std::string Name = Attr.getName() + "AttrSpellingMap";
2404
2405 OS << "static unsigned " << Name << "(const AttributeList &Attr) {\n";
2406 OS << Enum;
2407 OS << " unsigned Idx = Attr.getAttributeSpellingListIndex();\n";
2408 WriteSemanticSpellingSwitch("Idx", SemanticToSyntacticMap, OS);
2409 OS << "}\n\n";
2410
2411 return Name;
2412}
2413
Aaron Ballmanc669cc02014-01-27 22:10:04 +00002414static bool IsKnownToGCC(const Record &Attr) {
2415 // Look at the spellings for this subject; if there are any spellings which
2416 // claim to be known to GCC, the attribute is known to GCC.
2417 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
2418 for (std::vector<FlattenedSpelling>::const_iterator I = Spellings.begin(),
2419 E = Spellings.end(); I != E; ++I) {
2420 if (I->knownToGCC())
Aaron Ballman9a99e0d2014-01-20 17:18:35 +00002421 return true;
2422 }
2423 return false;
2424}
2425
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002426/// Emits the parsed attribute helpers
2427void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
2428 emitSourceFileHeader("Parsed attribute helpers", OS);
2429
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002430 // Get the list of parsed attributes, and accept the optional list of
2431 // duplicates due to the ParseKind.
2432 ParsedAttrMap Dupes;
2433 ParsedAttrMap Attrs = getParsedAttrList(Records, &Dupes);
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002434
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00002435 // Generate the default appertainsTo, target and language option diagnostic,
2436 // and spelling list index mapping methods.
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002437 GenerateDefaultAppertainsTo(OS);
Aaron Ballman3aff6332013-12-02 19:30:36 +00002438 GenerateDefaultLangOptRequirements(OS);
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002439 GenerateDefaultTargetRequirements(OS);
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00002440 GenerateDefaultSpellingIndexToSemanticSpelling(OS);
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002441
2442 // Generate the appertainsTo diagnostic methods and write their names into
2443 // another mapping. At the same time, generate the AttrInfoMap object
2444 // contents. Due to the reliance on generated code, use separate streams so
2445 // that code will not be interleaved.
2446 std::stringstream SS;
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002447 for (ParsedAttrMap::iterator I = Attrs.begin(), E = Attrs.end(); I != E;
2448 ++I) {
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002449 // TODO: If the attribute's kind appears in the list of duplicates, that is
2450 // because it is a target-specific attribute that appears multiple times.
2451 // It would be beneficial to test whether the duplicates are "similar
2452 // enough" to each other to not cause problems. For instance, check that
Alp Toker96cf7582014-01-18 21:49:37 +00002453 // the spellings are identical, and custom parsing rules match, etc.
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002454
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002455 // We need to generate struct instances based off ParsedAttrInfo from
2456 // AttributeList.cpp.
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002457 SS << " { ";
2458 emitArgInfo(*I->second, SS);
2459 SS << ", " << I->second->getValueAsBit("HasCustomParsing");
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002460 SS << ", " << I->second->isSubClassOf("TargetSpecificAttr");
2461 SS << ", " << I->second->isSubClassOf("TypeAttr");
Aaron Ballmanc669cc02014-01-27 22:10:04 +00002462 SS << ", " << IsKnownToGCC(*I->second);
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002463 SS << ", " << GenerateAppertainsTo(*I->second, OS);
Aaron Ballman3aff6332013-12-02 19:30:36 +00002464 SS << ", " << GenerateLangOptRequirements(*I->second, OS);
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002465 SS << ", " << GenerateTargetRequirements(*I->second, Dupes, OS);
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00002466 SS << ", " << GenerateSpellingIndexToSemanticSpelling(*I->second, OS);
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002467 SS << " }";
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002468
2469 if (I + 1 != E)
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002470 SS << ",";
2471
2472 SS << " // AT_" << I->first << "\n";
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002473 }
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002474
2475 OS << "static const ParsedAttrInfo AttrInfoMap[AttributeList::UnknownAttribute + 1] = {\n";
2476 OS << SS.str();
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002477 OS << "};\n\n";
Michael Han4a045172012-03-07 00:12:16 +00002478}
2479
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00002480// Emits the kind list of parsed attributes
2481void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00002482 emitSourceFileHeader("Attribute name matcher", OS);
2483
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002484 std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
2485 std::vector<StringMatcher::StringPair> GNU, Declspec, CXX11, Keywords;
Aaron Ballman64e69862013-12-15 13:05:48 +00002486 std::set<std::string> Seen;
Michael Han4a045172012-03-07 00:12:16 +00002487 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
2488 I != E; ++I) {
2489 Record &Attr = **I;
Richard Smith852e9ce2013-11-27 01:46:48 +00002490
Michael Han4a045172012-03-07 00:12:16 +00002491 bool SemaHandler = Attr.getValueAsBit("SemaHandler");
Douglas Gregor19fbb8f2012-05-02 16:18:45 +00002492 bool Ignored = Attr.getValueAsBit("Ignored");
Douglas Gregor19fbb8f2012-05-02 16:18:45 +00002493 if (SemaHandler || Ignored) {
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002494 // Attribute spellings can be shared between target-specific attributes,
2495 // and can be shared between syntaxes for the same attribute. For
2496 // instance, an attribute can be spelled GNU<"interrupt"> for an ARM-
2497 // specific attribute, or MSP430-specific attribute. Additionally, an
2498 // attribute can be spelled GNU<"dllexport"> and Declspec<"dllexport">
2499 // for the same semantic attribute. Ultimately, we need to map each of
2500 // these to a single AttributeList::Kind value, but the StringMatcher
2501 // class cannot handle duplicate match strings. So we generate a list of
2502 // string to match based on the syntax, and emit multiple string matchers
2503 // depending on the syntax used.
Aaron Ballman64e69862013-12-15 13:05:48 +00002504 std::string AttrName;
2505 if (Attr.isSubClassOf("TargetSpecificAttr") &&
2506 !Attr.isValueUnset("ParseKind")) {
2507 AttrName = Attr.getValueAsString("ParseKind");
2508 if (Seen.find(AttrName) != Seen.end())
2509 continue;
2510 Seen.insert(AttrName);
2511 } else
2512 AttrName = NormalizeAttrName(StringRef(Attr.getName())).str();
2513
Aaron Ballmanc669cc02014-01-27 22:10:04 +00002514 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
2515 for (std::vector<FlattenedSpelling>::const_iterator
2516 I = Spellings.begin(), E = Spellings.end(); I != E; ++I) {
2517 std::string RawSpelling = I->name();
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002518 std::vector<StringMatcher::StringPair> *Matches = 0;
Aaron Ballmanc669cc02014-01-27 22:10:04 +00002519 std::string Spelling, Variety = I->variety();
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002520 if (Variety == "CXX11") {
2521 Matches = &CXX11;
Aaron Ballmanc669cc02014-01-27 22:10:04 +00002522 Spelling += I->nameSpace();
Alexis Hunt3bc72c12012-06-19 23:57:03 +00002523 Spelling += "::";
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002524 } else if (Variety == "GNU")
2525 Matches = &GNU;
2526 else if (Variety == "Declspec")
2527 Matches = &Declspec;
2528 else if (Variety == "Keyword")
2529 Matches = &Keywords;
Alexis Hunta0e54d42012-06-18 16:13:52 +00002530
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002531 assert(Matches && "Unsupported spelling variety found");
2532
2533 Spelling += NormalizeAttrSpelling(RawSpelling);
Douglas Gregor19fbb8f2012-05-02 16:18:45 +00002534 if (SemaHandler)
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002535 Matches->push_back(StringMatcher::StringPair(Spelling,
2536 "return AttributeList::AT_" + AttrName + ";"));
Douglas Gregor19fbb8f2012-05-02 16:18:45 +00002537 else
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002538 Matches->push_back(StringMatcher::StringPair(Spelling,
2539 "return AttributeList::IgnoredAttribute;"));
Michael Han4a045172012-03-07 00:12:16 +00002540 }
2541 }
2542 }
Douglas Gregor377f99b2012-05-02 17:33:51 +00002543
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002544 OS << "static AttributeList::Kind getAttrKind(StringRef Name, ";
2545 OS << "AttributeList::Syntax Syntax) {\n";
2546 OS << " if (AttributeList::AS_GNU == Syntax) {\n";
2547 StringMatcher("Name", GNU, OS).Emit();
2548 OS << " } else if (AttributeList::AS_Declspec == Syntax) {\n";
2549 StringMatcher("Name", Declspec, OS).Emit();
2550 OS << " } else if (AttributeList::AS_CXX11 == Syntax) {\n";
2551 StringMatcher("Name", CXX11, OS).Emit();
2552 OS << " } else if (AttributeList::AS_Keyword == Syntax) {\n";
2553 StringMatcher("Name", Keywords, OS).Emit();
2554 OS << " }\n";
2555 OS << " return AttributeList::UnknownAttribute;\n"
Douglas Gregor377f99b2012-05-02 17:33:51 +00002556 << "}\n";
Michael Han4a045172012-03-07 00:12:16 +00002557}
2558
Alexander Kornienko5bc364e2013-01-07 17:53:08 +00002559// Emits the code to dump an attribute.
2560void EmitClangAttrDump(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00002561 emitSourceFileHeader("Attribute dumper", OS);
2562
Alexander Kornienko5bc364e2013-01-07 17:53:08 +00002563 OS <<
2564 " switch (A->getKind()) {\n"
2565 " default:\n"
2566 " llvm_unreachable(\"Unknown attribute kind!\");\n"
2567 " break;\n";
2568 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
2569 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
2570 I != E; ++I) {
2571 Record &R = **I;
2572 if (!R.getValueAsBit("ASTNode"))
2573 continue;
2574 OS << " case attr::" << R.getName() << ": {\n";
Aaron Ballmanbc909612014-01-22 21:51:20 +00002575
2576 // If the attribute has a semantically-meaningful name (which is determined
2577 // by whether there is a Spelling enumeration for it), then write out the
2578 // spelling used for the attribute.
Aaron Ballmanc669cc02014-01-27 22:10:04 +00002579 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
Aaron Ballmanbc909612014-01-22 21:51:20 +00002580 if (Spellings.size() > 1 && !SpellingNamesAreCommon(Spellings))
2581 OS << " OS << \" \" << A->getSpelling();\n";
2582
Alexander Kornienko5bc364e2013-01-07 17:53:08 +00002583 Args = R.getValueAsListOfDefs("Args");
2584 if (!Args.empty()) {
2585 OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
2586 << "Attr>(A);\n";
2587 for (std::vector<Record*>::iterator I = Args.begin(), E = Args.end();
2588 I != E; ++I)
2589 createArgument(**I, R.getName())->writeDump(OS);
Richard Trieude5cc7d2013-01-31 01:44:26 +00002590
2591 // Code for detecting the last child.
2592 OS << " bool OldMoreChildren = hasMoreChildren();\n";
2593 OS << " bool MoreChildren = OldMoreChildren;\n";
2594
Alexander Kornienko5bc364e2013-01-07 17:53:08 +00002595 for (std::vector<Record*>::iterator I = Args.begin(), E = Args.end();
Richard Trieude5cc7d2013-01-31 01:44:26 +00002596 I != E; ++I) {
2597 // More code for detecting the last child.
2598 OS << " MoreChildren = OldMoreChildren";
2599 for (std::vector<Record*>::iterator Next = I + 1; Next != E; ++Next) {
2600 OS << " || ";
2601 createArgument(**Next, R.getName())->writeHasChildren(OS);
2602 }
2603 OS << ";\n";
2604 OS << " setMoreChildren(MoreChildren);\n";
2605
Alexander Kornienko5bc364e2013-01-07 17:53:08 +00002606 createArgument(**I, R.getName())->writeDumpChildren(OS);
Richard Trieude5cc7d2013-01-31 01:44:26 +00002607 }
2608
2609 // Reset the last child.
2610 OS << " setMoreChildren(OldMoreChildren);\n";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +00002611 }
2612 OS <<
2613 " break;\n"
2614 " }\n";
2615 }
2616 OS << " }\n";
2617}
2618
Aaron Ballman35db2b32014-01-29 22:13:45 +00002619void EmitClangAttrParserStringSwitches(RecordKeeper &Records,
2620 raw_ostream &OS) {
2621 emitSourceFileHeader("Parser-related llvm::StringSwitch cases", OS);
2622 emitClangAttrArgContextList(Records, OS);
2623 emitClangAttrIdentifierArgList(Records, OS);
2624 emitClangAttrTypeArgList(Records, OS);
2625 emitClangAttrLateParsedList(Records, OS);
2626}
2627
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00002628} // end namespace clang