blob: 112d9a5f23ffd642fa73d75cf035ee352a8e36dd [file] [log] [blame]
Peter Collingbourne51d77772011-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
14#include "ClangAttrEmitter.h"
15#include "llvm/ADT/StringSwitch.h"
16#include "llvm/TableGen/Record.h"
17#include <algorithm>
18#include <cctype>
Michael Hane53ac8a2012-03-07 00:12:16 +000019#include <set>
Peter Collingbourne51d77772011-10-06 13:03:08 +000020
21using namespace llvm;
22
23static const std::vector<StringRef>
24getValueAsListOfStrings(Record &R, StringRef FieldName) {
25 ListInit *List = R.getValueAsListInit(FieldName);
26 assert (List && "Got a null ListInit");
27
28 std::vector<StringRef> Strings;
29 Strings.reserve(List->getSize());
30
31 for (ListInit::const_iterator i = List->begin(), e = List->end();
32 i != e;
33 ++i) {
34 assert(*i && "Got a null element in a ListInit");
35 if (StringInit *S = dynamic_cast<StringInit *>(*i))
36 Strings.push_back(S->getValue());
Peter Collingbourne51d77772011-10-06 13:03:08 +000037 else
38 assert(false && "Got a non-string, non-code element in a ListInit");
39 }
40
41 return Strings;
42}
43
44static std::string ReadPCHRecord(StringRef type) {
45 return StringSwitch<std::string>(type)
46 .EndsWith("Decl *", "GetLocalDeclAs<"
47 + std::string(type, 0, type.size()-1) + ">(F, Record[Idx++])")
48 .Case("QualType", "getLocalType(F, Record[Idx++])")
49 .Case("Expr *", "ReadSubExpr()")
50 .Case("IdentifierInfo *", "GetIdentifierInfo(F, Record, Idx)")
51 .Case("SourceLocation", "ReadSourceLocation(F, Record, Idx)")
52 .Default("Record[Idx++]");
53}
54
55// Assumes that the way to get the value is SA->getname()
56static std::string WritePCHRecord(StringRef type, StringRef name) {
57 return StringSwitch<std::string>(type)
58 .EndsWith("Decl *", "AddDeclRef(" + std::string(name) +
59 ", Record);\n")
60 .Case("QualType", "AddTypeRef(" + std::string(name) + ", Record);\n")
61 .Case("Expr *", "AddStmt(" + std::string(name) + ");\n")
62 .Case("IdentifierInfo *",
63 "AddIdentifierRef(" + std::string(name) + ", Record);\n")
64 .Case("SourceLocation",
65 "AddSourceLocation(" + std::string(name) + ", Record);\n")
66 .Default("Record.push_back(" + std::string(name) + ");\n");
67}
68
Michael Hane53ac8a2012-03-07 00:12:16 +000069// Normalize attribute name by removing leading and trailing
70// underscores. For example, __foo, foo__, __foo__ would
71// become foo.
72static StringRef NormalizeAttrName(StringRef AttrName) {
73 if (AttrName.startswith("__"))
74 AttrName = AttrName.substr(2, AttrName.size());
75
76 if (AttrName.endswith("__"))
77 AttrName = AttrName.substr(0, AttrName.size() - 2);
78
79 return AttrName;
80}
81
82// Normalize attribute spelling only if the spelling has both leading
83// and trailing underscores. For example, __ms_struct__ will be
84// normalized to "ms_struct"; __cdecl will remain intact.
85static StringRef NormalizeAttrSpelling(StringRef AttrSpelling) {
86 if (AttrSpelling.startswith("__") && AttrSpelling.endswith("__")) {
87 AttrSpelling = AttrSpelling.substr(2, AttrSpelling.size() - 4);
88 }
89
90 return AttrSpelling;
91}
92
Peter Collingbourne51d77772011-10-06 13:03:08 +000093namespace {
94 class Argument {
95 std::string lowerName, upperName;
96 StringRef attrName;
97
98 public:
99 Argument(Record &Arg, StringRef Attr)
100 : lowerName(Arg.getValueAsString("Name")), upperName(lowerName),
101 attrName(Attr) {
102 if (!lowerName.empty()) {
103 lowerName[0] = std::tolower(lowerName[0]);
104 upperName[0] = std::toupper(upperName[0]);
105 }
106 }
107 virtual ~Argument() {}
108
109 StringRef getLowerName() const { return lowerName; }
110 StringRef getUpperName() const { return upperName; }
111 StringRef getAttrName() const { return attrName; }
112
113 // These functions print the argument contents formatted in different ways.
114 virtual void writeAccessors(raw_ostream &OS) const = 0;
115 virtual void writeAccessorDefinitions(raw_ostream &OS) const {}
116 virtual void writeCloneArgs(raw_ostream &OS) const = 0;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000117 virtual void writeTemplateInstantiationArgs(raw_ostream &OS) const = 0;
Daniel Dunbarb8806092012-02-10 06:00:29 +0000118 virtual void writeTemplateInstantiation(raw_ostream &OS) const {}
Peter Collingbourne51d77772011-10-06 13:03:08 +0000119 virtual void writeCtorBody(raw_ostream &OS) const {}
120 virtual void writeCtorInitializers(raw_ostream &OS) const = 0;
121 virtual void writeCtorParameters(raw_ostream &OS) const = 0;
122 virtual void writeDeclarations(raw_ostream &OS) const = 0;
123 virtual void writePCHReadArgs(raw_ostream &OS) const = 0;
124 virtual void writePCHReadDecls(raw_ostream &OS) const = 0;
125 virtual void writePCHWrite(raw_ostream &OS) const = 0;
Douglas Gregor1bea8802011-11-19 19:22:57 +0000126 virtual void writeValue(raw_ostream &OS) const = 0;
Peter Collingbourne51d77772011-10-06 13:03:08 +0000127 };
128
129 class SimpleArgument : public Argument {
130 std::string type;
131
132 public:
133 SimpleArgument(Record &Arg, StringRef Attr, std::string T)
134 : Argument(Arg, Attr), type(T)
135 {}
136
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000137 std::string getType() const { return type; }
138
Peter Collingbourne51d77772011-10-06 13:03:08 +0000139 void writeAccessors(raw_ostream &OS) const {
140 OS << " " << type << " get" << getUpperName() << "() const {\n";
141 OS << " return " << getLowerName() << ";\n";
142 OS << " }";
143 }
144 void writeCloneArgs(raw_ostream &OS) const {
145 OS << getLowerName();
146 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000147 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
148 OS << "A->get" << getUpperName() << "()";
149 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000150 void writeCtorInitializers(raw_ostream &OS) const {
151 OS << getLowerName() << "(" << getUpperName() << ")";
152 }
153 void writeCtorParameters(raw_ostream &OS) const {
154 OS << type << " " << getUpperName();
155 }
156 void writeDeclarations(raw_ostream &OS) const {
157 OS << type << " " << getLowerName() << ";";
158 }
159 void writePCHReadDecls(raw_ostream &OS) const {
160 std::string read = ReadPCHRecord(type);
161 OS << " " << type << " " << getLowerName() << " = " << read << ";\n";
162 }
163 void writePCHReadArgs(raw_ostream &OS) const {
164 OS << getLowerName();
165 }
166 void writePCHWrite(raw_ostream &OS) const {
167 OS << " " << WritePCHRecord(type, "SA->get" +
168 std::string(getUpperName()) + "()");
169 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000170 void writeValue(raw_ostream &OS) const {
171 if (type == "FunctionDecl *") {
172 OS << "\" << get" << getUpperName() << "()->getNameInfo().getAsString() << \"";
173 } else if (type == "IdentifierInfo *") {
174 OS << "\" << get" << getUpperName() << "()->getName() << \"";
175 } else if (type == "QualType") {
176 OS << "\" << get" << getUpperName() << "().getAsString() << \"";
177 } else if (type == "SourceLocation") {
178 OS << "\" << get" << getUpperName() << "().getRawEncoding() << \"";
179 } else {
180 OS << "\" << get" << getUpperName() << "() << \"";
181 }
182 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000183 };
184
185 class StringArgument : public Argument {
186 public:
187 StringArgument(Record &Arg, StringRef Attr)
188 : Argument(Arg, Attr)
189 {}
190
191 void writeAccessors(raw_ostream &OS) const {
192 OS << " llvm::StringRef get" << getUpperName() << "() const {\n";
193 OS << " return llvm::StringRef(" << getLowerName() << ", "
194 << getLowerName() << "Length);\n";
195 OS << " }\n";
196 OS << " unsigned get" << getUpperName() << "Length() const {\n";
197 OS << " return " << getLowerName() << "Length;\n";
198 OS << " }\n";
199 OS << " void set" << getUpperName()
200 << "(ASTContext &C, llvm::StringRef S) {\n";
201 OS << " " << getLowerName() << "Length = S.size();\n";
202 OS << " this->" << getLowerName() << " = new (C, 1) char ["
203 << getLowerName() << "Length];\n";
204 OS << " std::memcpy(this->" << getLowerName() << ", S.data(), "
205 << getLowerName() << "Length);\n";
206 OS << " }";
207 }
208 void writeCloneArgs(raw_ostream &OS) const {
209 OS << "get" << getUpperName() << "()";
210 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000211 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
212 OS << "A->get" << getUpperName() << "()";
213 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000214 void writeCtorBody(raw_ostream &OS) const {
215 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
216 << ".data(), " << getLowerName() << "Length);";
217 }
218 void writeCtorInitializers(raw_ostream &OS) const {
219 OS << getLowerName() << "Length(" << getUpperName() << ".size()),"
220 << getLowerName() << "(new (Ctx, 1) char[" << getLowerName()
221 << "Length])";
222 }
223 void writeCtorParameters(raw_ostream &OS) const {
224 OS << "llvm::StringRef " << getUpperName();
225 }
226 void writeDeclarations(raw_ostream &OS) const {
227 OS << "unsigned " << getLowerName() << "Length;\n";
228 OS << "char *" << getLowerName() << ";";
229 }
230 void writePCHReadDecls(raw_ostream &OS) const {
231 OS << " std::string " << getLowerName()
232 << "= ReadString(Record, Idx);\n";
233 }
234 void writePCHReadArgs(raw_ostream &OS) const {
235 OS << getLowerName();
236 }
237 void writePCHWrite(raw_ostream &OS) const {
238 OS << " AddString(SA->get" << getUpperName() << "(), Record);\n";
239 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000240 void writeValue(raw_ostream &OS) const {
241 OS << "\\\"\" << get" << getUpperName() << "() << \"\\\"";
242 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000243 };
244
245 class AlignedArgument : public Argument {
246 public:
247 AlignedArgument(Record &Arg, StringRef Attr)
248 : Argument(Arg, Attr)
249 {}
250
251 void writeAccessors(raw_ostream &OS) const {
252 OS << " bool is" << getUpperName() << "Dependent() const;\n";
253
254 OS << " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n";
255
256 OS << " bool is" << getUpperName() << "Expr() const {\n";
257 OS << " return is" << getLowerName() << "Expr;\n";
258 OS << " }\n";
259
260 OS << " Expr *get" << getUpperName() << "Expr() const {\n";
261 OS << " assert(is" << getLowerName() << "Expr);\n";
262 OS << " return " << getLowerName() << "Expr;\n";
263 OS << " }\n";
264
265 OS << " TypeSourceInfo *get" << getUpperName() << "Type() const {\n";
266 OS << " assert(!is" << getLowerName() << "Expr);\n";
267 OS << " return " << getLowerName() << "Type;\n";
268 OS << " }";
269 }
270 void writeAccessorDefinitions(raw_ostream &OS) const {
271 OS << "bool " << getAttrName() << "Attr::is" << getUpperName()
272 << "Dependent() const {\n";
273 OS << " if (is" << getLowerName() << "Expr)\n";
274 OS << " return " << getLowerName() << "Expr && (" << getLowerName()
275 << "Expr->isValueDependent() || " << getLowerName()
276 << "Expr->isTypeDependent());\n";
277 OS << " else\n";
278 OS << " return " << getLowerName()
279 << "Type->getType()->isDependentType();\n";
280 OS << "}\n";
281
282 // FIXME: Do not do the calculation here
283 // FIXME: Handle types correctly
284 // A null pointer means maximum alignment
285 // FIXME: Load the platform-specific maximum alignment, rather than
286 // 16, the x86 max.
287 OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName()
288 << "(ASTContext &Ctx) const {\n";
289 OS << " assert(!is" << getUpperName() << "Dependent());\n";
290 OS << " if (is" << getLowerName() << "Expr)\n";
291 OS << " return (" << getLowerName() << "Expr ? " << getLowerName()
Richard Smitha6b8b2c2011-10-10 18:28:20 +0000292 << "Expr->EvaluateKnownConstInt(Ctx).getZExtValue() : 16)"
Peter Collingbourne51d77772011-10-06 13:03:08 +0000293 << "* Ctx.getCharWidth();\n";
294 OS << " else\n";
295 OS << " return 0; // FIXME\n";
296 OS << "}\n";
297 }
298 void writeCloneArgs(raw_ostream &OS) const {
299 OS << "is" << getLowerName() << "Expr, is" << getLowerName()
300 << "Expr ? static_cast<void*>(" << getLowerName()
301 << "Expr) : " << getLowerName()
302 << "Type";
303 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000304 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
305 // FIXME: move the definition in Sema::InstantiateAttrs to here.
306 // In the meantime, aligned attributes are cloned.
307 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000308 void writeCtorBody(raw_ostream &OS) const {
309 OS << " if (is" << getLowerName() << "Expr)\n";
310 OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>("
311 << getUpperName() << ");\n";
312 OS << " else\n";
313 OS << " " << getLowerName()
314 << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName()
315 << ");";
316 }
317 void writeCtorInitializers(raw_ostream &OS) const {
318 OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)";
319 }
320 void writeCtorParameters(raw_ostream &OS) const {
321 OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName();
322 }
323 void writeDeclarations(raw_ostream &OS) const {
324 OS << "bool is" << getLowerName() << "Expr;\n";
325 OS << "union {\n";
326 OS << "Expr *" << getLowerName() << "Expr;\n";
327 OS << "TypeSourceInfo *" << getLowerName() << "Type;\n";
328 OS << "};";
329 }
330 void writePCHReadArgs(raw_ostream &OS) const {
331 OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr";
332 }
333 void writePCHReadDecls(raw_ostream &OS) const {
334 OS << " bool is" << getLowerName() << "Expr = Record[Idx++];\n";
335 OS << " void *" << getLowerName() << "Ptr;\n";
336 OS << " if (is" << getLowerName() << "Expr)\n";
337 OS << " " << getLowerName() << "Ptr = ReadExpr(F);\n";
338 OS << " else\n";
339 OS << " " << getLowerName()
340 << "Ptr = GetTypeSourceInfo(F, Record, Idx);\n";
341 }
342 void writePCHWrite(raw_ostream &OS) const {
343 OS << " Record.push_back(SA->is" << getUpperName() << "Expr());\n";
344 OS << " if (SA->is" << getUpperName() << "Expr())\n";
345 OS << " AddStmt(SA->get" << getUpperName() << "Expr());\n";
346 OS << " else\n";
347 OS << " AddTypeSourceInfo(SA->get" << getUpperName()
348 << "Type(), Record);\n";
349 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000350 void writeValue(raw_ostream &OS) const {
351 OS << "\" << get" << getUpperName() << "(Ctx) << \"";
352 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000353 };
354
355 class VariadicArgument : public Argument {
356 std::string type;
357
358 public:
359 VariadicArgument(Record &Arg, StringRef Attr, std::string T)
360 : Argument(Arg, Attr), type(T)
361 {}
362
363 std::string getType() const { return type; }
364
365 void writeAccessors(raw_ostream &OS) const {
366 OS << " typedef " << type << "* " << getLowerName() << "_iterator;\n";
367 OS << " " << getLowerName() << "_iterator " << getLowerName()
368 << "_begin() const {\n";
369 OS << " return " << getLowerName() << ";\n";
370 OS << " }\n";
371 OS << " " << getLowerName() << "_iterator " << getLowerName()
372 << "_end() const {\n";
373 OS << " return " << getLowerName() << " + " << getLowerName()
374 << "Size;\n";
375 OS << " }\n";
376 OS << " unsigned " << getLowerName() << "_size() const {\n"
DeLesley Hutchins23323e02012-01-20 22:50:54 +0000377 << " return " << getLowerName() << "Size;\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000378 OS << " }";
379 }
380 void writeCloneArgs(raw_ostream &OS) const {
381 OS << getLowerName() << ", " << getLowerName() << "Size";
382 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000383 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
384 // This isn't elegant, but we have to go through public methods...
385 OS << "A->" << getLowerName() << "_begin(), "
386 << "A->" << getLowerName() << "_size()";
387 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000388 void writeCtorBody(raw_ostream &OS) const {
389 // FIXME: memcpy is not safe on non-trivial types.
390 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
391 << ", " << getLowerName() << "Size * sizeof(" << getType() << "));\n";
392 }
393 void writeCtorInitializers(raw_ostream &OS) const {
394 OS << getLowerName() << "Size(" << getUpperName() << "Size), "
395 << getLowerName() << "(new (Ctx, 16) " << getType() << "["
396 << getLowerName() << "Size])";
397 }
398 void writeCtorParameters(raw_ostream &OS) const {
399 OS << getType() << " *" << getUpperName() << ", unsigned "
400 << getUpperName() << "Size";
401 }
402 void writeDeclarations(raw_ostream &OS) const {
403 OS << " unsigned " << getLowerName() << "Size;\n";
404 OS << " " << getType() << " *" << getLowerName() << ";";
405 }
406 void writePCHReadDecls(raw_ostream &OS) const {
407 OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
408 OS << " llvm::SmallVector<" << type << ", 4> " << getLowerName()
409 << ";\n";
410 OS << " " << getLowerName() << ".reserve(" << getLowerName()
411 << "Size);\n";
412 OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
413
414 std::string read = ReadPCHRecord(type);
415 OS << " " << getLowerName() << ".push_back(" << read << ");\n";
416 }
417 void writePCHReadArgs(raw_ostream &OS) const {
418 OS << getLowerName() << ".data(), " << getLowerName() << "Size";
419 }
420 void writePCHWrite(raw_ostream &OS) const{
421 OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";
422 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
423 << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
424 << getLowerName() << "_end(); i != e; ++i)\n";
425 OS << " " << WritePCHRecord(type, "(*i)");
426 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000427 void writeValue(raw_ostream &OS) const {
428 OS << "\";\n";
429 OS << " bool isFirst = true;\n"
430 << " for (" << getAttrName() << "Attr::" << getLowerName()
431 << "_iterator i = " << getLowerName() << "_begin(), e = "
432 << getLowerName() << "_end(); i != e; ++i) {\n"
433 << " if (isFirst) isFirst = false;\n"
434 << " else OS << \", \";\n"
435 << " OS << *i;\n"
436 << " }\n";
437 OS << " OS << \"";
438 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000439 };
440
441 class EnumArgument : public Argument {
442 std::string type;
443 std::vector<StringRef> values, enums;
444 public:
445 EnumArgument(Record &Arg, StringRef Attr)
446 : Argument(Arg, Attr), type(Arg.getValueAsString("Type")),
447 values(getValueAsListOfStrings(Arg, "Values")),
448 enums(getValueAsListOfStrings(Arg, "Enums"))
449 {}
450
451 void writeAccessors(raw_ostream &OS) const {
452 OS << " " << type << " get" << getUpperName() << "() const {\n";
453 OS << " return " << getLowerName() << ";\n";
454 OS << " }";
455 }
456 void writeCloneArgs(raw_ostream &OS) const {
457 OS << getLowerName();
458 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000459 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
460 OS << "A->get" << getUpperName() << "()";
461 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000462 void writeCtorInitializers(raw_ostream &OS) const {
463 OS << getLowerName() << "(" << getUpperName() << ")";
464 }
465 void writeCtorParameters(raw_ostream &OS) const {
466 OS << type << " " << getUpperName();
467 }
468 void writeDeclarations(raw_ostream &OS) const {
469 // Calculate the various enum values
470 std::vector<StringRef> uniques(enums);
471 std::sort(uniques.begin(), uniques.end());
472 uniques.erase(std::unique(uniques.begin(), uniques.end()),
473 uniques.end());
474 // FIXME: Emit a proper error
475 assert(!uniques.empty());
476
477 std::vector<StringRef>::iterator i = uniques.begin(),
478 e = uniques.end();
479 // The last one needs to not have a comma.
480 --e;
481
482 OS << "public:\n";
483 OS << " enum " << type << " {\n";
484 for (; i != e; ++i)
485 OS << " " << *i << ",\n";
486 OS << " " << *e << "\n";
487 OS << " };\n";
488 OS << "private:\n";
489 OS << " " << type << " " << getLowerName() << ";";
490 }
491 void writePCHReadDecls(raw_ostream &OS) const {
492 OS << " " << getAttrName() << "Attr::" << type << " " << getLowerName()
493 << "(static_cast<" << getAttrName() << "Attr::" << type
494 << ">(Record[Idx++]));\n";
495 }
496 void writePCHReadArgs(raw_ostream &OS) const {
497 OS << getLowerName();
498 }
499 void writePCHWrite(raw_ostream &OS) const {
500 OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
501 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000502 void writeValue(raw_ostream &OS) const {
503 OS << "\" << get" << getUpperName() << "() << \"";
504 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000505 };
506
507 class VersionArgument : public Argument {
508 public:
509 VersionArgument(Record &Arg, StringRef Attr)
510 : Argument(Arg, Attr)
511 {}
512
513 void writeAccessors(raw_ostream &OS) const {
514 OS << " VersionTuple get" << getUpperName() << "() const {\n";
515 OS << " return " << getLowerName() << ";\n";
516 OS << " }\n";
517 OS << " void set" << getUpperName()
518 << "(ASTContext &C, VersionTuple V) {\n";
519 OS << " " << getLowerName() << " = V;\n";
520 OS << " }";
521 }
522 void writeCloneArgs(raw_ostream &OS) const {
523 OS << "get" << getUpperName() << "()";
524 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000525 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
526 OS << "A->get" << getUpperName() << "()";
527 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000528 void writeCtorBody(raw_ostream &OS) const {
529 }
530 void writeCtorInitializers(raw_ostream &OS) const {
531 OS << getLowerName() << "(" << getUpperName() << ")";
532 }
533 void writeCtorParameters(raw_ostream &OS) const {
534 OS << "VersionTuple " << getUpperName();
535 }
536 void writeDeclarations(raw_ostream &OS) const {
537 OS << "VersionTuple " << getLowerName() << ";\n";
538 }
539 void writePCHReadDecls(raw_ostream &OS) const {
540 OS << " VersionTuple " << getLowerName()
541 << "= ReadVersionTuple(Record, Idx);\n";
542 }
543 void writePCHReadArgs(raw_ostream &OS) const {
544 OS << getLowerName();
545 }
546 void writePCHWrite(raw_ostream &OS) const {
547 OS << " AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n";
548 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000549 void writeValue(raw_ostream &OS) const {
550 OS << getLowerName() << "=\" << get" << getUpperName() << "() << \"";
551 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000552 };
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000553
554 class ExprArgument : public SimpleArgument {
555 public:
556 ExprArgument(Record &Arg, StringRef Attr)
557 : SimpleArgument(Arg, Attr, "Expr *")
558 {}
559
560 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
561 OS << "tempInst" << getUpperName();
562 }
563
564 void writeTemplateInstantiation(raw_ostream &OS) const {
565 OS << " " << getType() << " tempInst" << getUpperName() << ";\n";
566 OS << " {\n";
567 OS << " EnterExpressionEvaluationContext "
568 << "Unevaluated(S, Sema::Unevaluated);\n";
569 OS << " ExprResult " << "Result = S.SubstExpr("
570 << "A->get" << getUpperName() << "(), TemplateArgs);\n";
571 OS << " tempInst" << getUpperName() << " = "
572 << "Result.takeAs<Expr>();\n";
573 OS << " }\n";
574 }
575 };
576
577 class VariadicExprArgument : public VariadicArgument {
578 public:
579 VariadicExprArgument(Record &Arg, StringRef Attr)
580 : VariadicArgument(Arg, Attr, "Expr *")
581 {}
582
583 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
584 OS << "tempInst" << getUpperName() << ", "
585 << "A->" << getLowerName() << "_size()";
586 }
587
588 void writeTemplateInstantiation(raw_ostream &OS) const {
589 OS << " " << getType() << " *tempInst" << getUpperName()
590 << " = new (C, 16) " << getType()
591 << "[A->" << getLowerName() << "_size()];\n";
592 OS << " {\n";
593 OS << " EnterExpressionEvaluationContext "
594 << "Unevaluated(S, Sema::Unevaluated);\n";
595 OS << " " << getType() << " *TI = tempInst" << getUpperName()
596 << ";\n";
597 OS << " " << getType() << " *I = A->" << getLowerName()
598 << "_begin();\n";
599 OS << " " << getType() << " *E = A->" << getLowerName()
600 << "_end();\n";
601 OS << " for (; I != E; ++I, ++TI) {\n";
602 OS << " ExprResult Result = S.SubstExpr(*I, TemplateArgs);\n";
603 OS << " *TI = Result.takeAs<Expr>();\n";
604 OS << " }\n";
605 OS << " }\n";
606 }
607 };
Peter Collingbourne51d77772011-10-06 13:03:08 +0000608}
609
610static Argument *createArgument(Record &Arg, StringRef Attr,
611 Record *Search = 0) {
612 if (!Search)
613 Search = &Arg;
614
615 Argument *Ptr = 0;
616 llvm::StringRef ArgName = Search->getName();
617
618 if (ArgName == "AlignedArgument") Ptr = new AlignedArgument(Arg, Attr);
619 else if (ArgName == "EnumArgument") Ptr = new EnumArgument(Arg, Attr);
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000620 else if (ArgName == "ExprArgument") Ptr = new ExprArgument(Arg, Attr);
Peter Collingbourne51d77772011-10-06 13:03:08 +0000621 else if (ArgName == "FunctionArgument")
622 Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *");
623 else if (ArgName == "IdentifierArgument")
624 Ptr = new SimpleArgument(Arg, Attr, "IdentifierInfo *");
625 else if (ArgName == "BoolArgument") Ptr = new SimpleArgument(Arg, Attr,
626 "bool");
627 else if (ArgName == "IntArgument") Ptr = new SimpleArgument(Arg, Attr, "int");
628 else if (ArgName == "StringArgument") Ptr = new StringArgument(Arg, Attr);
629 else if (ArgName == "TypeArgument")
630 Ptr = new SimpleArgument(Arg, Attr, "QualType");
631 else if (ArgName == "UnsignedArgument")
632 Ptr = new SimpleArgument(Arg, Attr, "unsigned");
633 else if (ArgName == "SourceLocArgument")
634 Ptr = new SimpleArgument(Arg, Attr, "SourceLocation");
635 else if (ArgName == "VariadicUnsignedArgument")
636 Ptr = new VariadicArgument(Arg, Attr, "unsigned");
637 else if (ArgName == "VariadicExprArgument")
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000638 Ptr = new VariadicExprArgument(Arg, Attr);
Peter Collingbourne51d77772011-10-06 13:03:08 +0000639 else if (ArgName == "VersionArgument")
640 Ptr = new VersionArgument(Arg, Attr);
641
642 if (!Ptr) {
643 std::vector<Record*> Bases = Search->getSuperClasses();
644 for (std::vector<Record*>::iterator i = Bases.begin(), e = Bases.end();
645 i != e; ++i) {
646 Ptr = createArgument(Arg, Attr, *i);
647 if (Ptr)
648 break;
649 }
650 }
651 return Ptr;
652}
653
Douglas Gregor1bea8802011-11-19 19:22:57 +0000654static void writeAvailabilityValue(raw_ostream &OS) {
655 OS << "\" << getPlatform()->getName();\n"
656 << " if (!getIntroduced().empty()) OS << \", introduced=\" << getIntroduced();\n"
657 << " if (!getDeprecated().empty()) OS << \", deprecated=\" << getDeprecated();\n"
658 << " if (!getObsoleted().empty()) OS << \", obsoleted=\" << getObsoleted();\n"
659 << " if (getUnavailable()) OS << \", unavailable\";\n"
660 << " OS << \"";
661}
662
Peter Collingbourne51d77772011-10-06 13:03:08 +0000663void ClangAttrClassEmitter::run(raw_ostream &OS) {
664 OS << "// This file is generated by TableGen. Do not edit.\n\n";
665 OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
666 OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
667
668 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
669
670 for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
671 i != e; ++i) {
672 Record &R = **i;
Douglas Gregor3e7d31a2012-05-02 15:56:52 +0000673
674 if (!R.getValueAsBit("ASTNode"))
675 continue;
676
Peter Collingbourne51d77772011-10-06 13:03:08 +0000677 const std::string &SuperName = R.getSuperClasses().back()->getName();
678
679 OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n";
680
681 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
682 std::vector<Argument*> Args;
683 std::vector<Argument*>::iterator ai, ae;
684 Args.reserve(ArgRecords.size());
685
686 for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
687 re = ArgRecords.end();
688 ri != re; ++ri) {
689 Record &ArgRecord = **ri;
690 Argument *Arg = createArgument(ArgRecord, R.getName());
691 assert(Arg);
692 Args.push_back(Arg);
693
694 Arg->writeDeclarations(OS);
695 OS << "\n\n";
696 }
697
698 ae = Args.end();
699
700 OS << "\n public:\n";
701 OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
702
703 for (ai = Args.begin(); ai != ae; ++ai) {
704 OS << " , ";
705 (*ai)->writeCtorParameters(OS);
706 OS << "\n";
707 }
708
709 OS << " )\n";
710 OS << " : " << SuperName << "(attr::" << R.getName() << ", R)\n";
711
712 for (ai = Args.begin(); ai != ae; ++ai) {
713 OS << " , ";
714 (*ai)->writeCtorInitializers(OS);
715 OS << "\n";
716 }
717
718 OS << " {\n";
719
720 for (ai = Args.begin(); ai != ae; ++ai) {
721 (*ai)->writeCtorBody(OS);
722 OS << "\n";
723 }
724 OS << " }\n\n";
725
726 OS << " virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n";
Douglas Gregor1bea8802011-11-19 19:22:57 +0000727 OS << " virtual void printPretty(llvm::raw_ostream &OS, ASTContext &Ctx) const;\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000728
729 for (ai = Args.begin(); ai != ae; ++ai) {
730 (*ai)->writeAccessors(OS);
731 OS << "\n\n";
732 }
733
Jakob Stoklund Oleseneb666732012-01-13 04:57:47 +0000734 OS << R.getValueAsString("AdditionalMembers");
Peter Collingbourne51d77772011-10-06 13:03:08 +0000735 OS << "\n\n";
736
737 OS << " static bool classof(const Attr *A) { return A->getKind() == "
738 << "attr::" << R.getName() << "; }\n";
739 OS << " static bool classof(const " << R.getName()
740 << "Attr *) { return true; }\n";
DeLesley Hutchins23323e02012-01-20 22:50:54 +0000741
742 bool LateParsed = R.getValueAsBit("LateParsed");
743 OS << " virtual bool isLateParsed() const { return "
744 << LateParsed << "; }\n";
745
Peter Collingbourne51d77772011-10-06 13:03:08 +0000746 OS << "};\n\n";
747 }
748
749 OS << "#endif\n";
750}
751
752void ClangAttrImplEmitter::run(raw_ostream &OS) {
753 OS << "// This file is generated by TableGen. Do not edit.\n\n";
754
755 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
756 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ri, re;
757 std::vector<Argument*>::iterator ai, ae;
758
759 for (; i != e; ++i) {
760 Record &R = **i;
Douglas Gregor3e7d31a2012-05-02 15:56:52 +0000761
762 if (!R.getValueAsBit("ASTNode"))
763 continue;
764
Peter Collingbourne51d77772011-10-06 13:03:08 +0000765 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
Douglas Gregor1bea8802011-11-19 19:22:57 +0000766 std::vector<StringRef> Spellings = getValueAsListOfStrings(R, "Spellings");
Peter Collingbourne51d77772011-10-06 13:03:08 +0000767 std::vector<Argument*> Args;
768 for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri)
769 Args.push_back(createArgument(**ri, R.getName()));
770
771 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
772 (*ai)->writeAccessorDefinitions(OS);
773
774 OS << R.getName() << "Attr *" << R.getName()
775 << "Attr::clone(ASTContext &C) const {\n";
776 OS << " return new (C) " << R.getName() << "Attr(getLocation(), C";
777 for (ai = Args.begin(); ai != ae; ++ai) {
778 OS << ", ";
779 (*ai)->writeCloneArgs(OS);
780 }
781 OS << ");\n}\n\n";
Douglas Gregor1bea8802011-11-19 19:22:57 +0000782
783 OS << "void " << R.getName() << "Attr::printPretty("
784 << "llvm::raw_ostream &OS, ASTContext &Ctx) const {\n";
785 if (Spellings.begin() != Spellings.end()) {
786 OS << " OS << \" __attribute__((" << *Spellings.begin();
787 if (Args.size()) OS << "(";
788 if (*Spellings.begin()=="availability") {
789 writeAvailabilityValue(OS);
790 } else {
791 for (ai = Args.begin(); ai != ae; ++ai) {
792 if (ai!=Args.begin()) OS <<", ";
793 (*ai)->writeValue(OS);
794 }
795 }
796 if (Args.size()) OS << ")";
797 OS << "))\";\n";
798 }
799 OS << "}\n\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000800 }
801}
802
803static void EmitAttrList(raw_ostream &OS, StringRef Class,
804 const std::vector<Record*> &AttrList) {
805 std::vector<Record*>::const_iterator i = AttrList.begin(), e = AttrList.end();
806
807 if (i != e) {
808 // Move the end iterator back to emit the last attribute.
Douglas Gregor3e7d31a2012-05-02 15:56:52 +0000809 for(--e; i != e; ++i) {
810 if (!(*i)->getValueAsBit("ASTNode"))
811 continue;
812
Peter Collingbourne51d77772011-10-06 13:03:08 +0000813 OS << Class << "(" << (*i)->getName() << ")\n";
Douglas Gregor3e7d31a2012-05-02 15:56:52 +0000814 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000815
816 OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n";
817 }
818}
819
820void ClangAttrListEmitter::run(raw_ostream &OS) {
821 OS << "// This file is generated by TableGen. Do not edit.\n\n";
822
823 OS << "#ifndef LAST_ATTR\n";
824 OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n";
825 OS << "#endif\n\n";
826
827 OS << "#ifndef INHERITABLE_ATTR\n";
828 OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n";
829 OS << "#endif\n\n";
830
831 OS << "#ifndef LAST_INHERITABLE_ATTR\n";
832 OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n";
833 OS << "#endif\n\n";
834
835 OS << "#ifndef INHERITABLE_PARAM_ATTR\n";
836 OS << "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n";
837 OS << "#endif\n\n";
838
839 OS << "#ifndef LAST_INHERITABLE_PARAM_ATTR\n";
840 OS << "#define LAST_INHERITABLE_PARAM_ATTR(NAME)"
841 " INHERITABLE_PARAM_ATTR(NAME)\n";
842 OS << "#endif\n\n";
843
844 Record *InhClass = Records.getClass("InheritableAttr");
845 Record *InhParamClass = Records.getClass("InheritableParamAttr");
846 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
847 NonInhAttrs, InhAttrs, InhParamAttrs;
848 for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
849 i != e; ++i) {
Douglas Gregor3e7d31a2012-05-02 15:56:52 +0000850 if (!(*i)->getValueAsBit("ASTNode"))
851 continue;
852
Peter Collingbourne51d77772011-10-06 13:03:08 +0000853 if ((*i)->isSubClassOf(InhParamClass))
854 InhParamAttrs.push_back(*i);
855 else if ((*i)->isSubClassOf(InhClass))
856 InhAttrs.push_back(*i);
857 else
858 NonInhAttrs.push_back(*i);
859 }
860
861 EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs);
862 EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs);
863 EmitAttrList(OS, "ATTR", NonInhAttrs);
864
865 OS << "#undef LAST_ATTR\n";
866 OS << "#undef INHERITABLE_ATTR\n";
867 OS << "#undef LAST_INHERITABLE_ATTR\n";
868 OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n";
869 OS << "#undef ATTR\n";
870}
871
872void ClangAttrPCHReadEmitter::run(raw_ostream &OS) {
873 OS << "// This file is generated by TableGen. Do not edit.\n\n";
874
875 Record *InhClass = Records.getClass("InheritableAttr");
876 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
877 ArgRecords;
878 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
879 std::vector<Argument*> Args;
880 std::vector<Argument*>::iterator ri, re;
881
882 OS << " switch (Kind) {\n";
883 OS << " default:\n";
884 OS << " assert(0 && \"Unknown attribute!\");\n";
885 OS << " break;\n";
886 for (; i != e; ++i) {
887 Record &R = **i;
Douglas Gregor3e7d31a2012-05-02 15:56:52 +0000888 if (!R.getValueAsBit("ASTNode"))
889 continue;
890
Peter Collingbourne51d77772011-10-06 13:03:08 +0000891 OS << " case attr::" << R.getName() << ": {\n";
892 if (R.isSubClassOf(InhClass))
893 OS << " bool isInherited = Record[Idx++];\n";
894 ArgRecords = R.getValueAsListOfDefs("Args");
895 Args.clear();
896 for (ai = ArgRecords.begin(), ae = ArgRecords.end(); ai != ae; ++ai) {
897 Argument *A = createArgument(**ai, R.getName());
898 Args.push_back(A);
899 A->writePCHReadDecls(OS);
900 }
901 OS << " New = new (Context) " << R.getName() << "Attr(Range, Context";
902 for (ri = Args.begin(), re = Args.end(); ri != re; ++ri) {
903 OS << ", ";
904 (*ri)->writePCHReadArgs(OS);
905 }
906 OS << ");\n";
907 if (R.isSubClassOf(InhClass))
908 OS << " cast<InheritableAttr>(New)->setInherited(isInherited);\n";
909 OS << " break;\n";
910 OS << " }\n";
911 }
912 OS << " }\n";
913}
914
915void ClangAttrPCHWriteEmitter::run(raw_ostream &OS) {
916 Record *InhClass = Records.getClass("InheritableAttr");
917 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
918 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
919
920 OS << " switch (A->getKind()) {\n";
921 OS << " default:\n";
922 OS << " llvm_unreachable(\"Unknown attribute kind!\");\n";
923 OS << " break;\n";
924 for (; i != e; ++i) {
925 Record &R = **i;
Douglas Gregor3e7d31a2012-05-02 15:56:52 +0000926 if (!R.getValueAsBit("ASTNode"))
927 continue;
Peter Collingbourne51d77772011-10-06 13:03:08 +0000928 OS << " case attr::" << R.getName() << ": {\n";
929 Args = R.getValueAsListOfDefs("Args");
930 if (R.isSubClassOf(InhClass) || !Args.empty())
931 OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
932 << "Attr>(A);\n";
933 if (R.isSubClassOf(InhClass))
934 OS << " Record.push_back(SA->isInherited());\n";
935 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
936 createArgument(**ai, R.getName())->writePCHWrite(OS);
937 OS << " break;\n";
938 OS << " }\n";
939 }
940 OS << " }\n";
941}
942
943void ClangAttrSpellingListEmitter::run(raw_ostream &OS) {
944 OS << "// This file is generated by TableGen. Do not edit.\n\n";
945
946 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
947
948 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) {
949 Record &Attr = **I;
950
951 std::vector<StringRef> Spellings = getValueAsListOfStrings(Attr, "Spellings");
952
953 for (std::vector<StringRef>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) {
954 StringRef Spelling = *I;
955 OS << ".Case(\"" << Spelling << "\", true)\n";
956 }
957 }
958
959}
960
961void ClangAttrLateParsedListEmitter::run(raw_ostream &OS) {
962 OS << "// This file is generated by TableGen. Do not edit.\n\n";
963
964 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
965
966 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
967 I != E; ++I) {
968 Record &Attr = **I;
969
970 bool LateParsed = Attr.getValueAsBit("LateParsed");
971
972 if (LateParsed) {
973 std::vector<StringRef> Spellings =
974 getValueAsListOfStrings(Attr, "Spellings");
975
976 for (std::vector<StringRef>::const_iterator I = Spellings.begin(),
977 E = Spellings.end(); I != E; ++I) {
978 OS << ".Case(\"" << (*I) << "\", " << LateParsed << ")\n";
979 }
980 }
981 }
982}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000983
984
985void ClangAttrTemplateInstantiateEmitter::run(raw_ostream &OS) {
986 OS << "// This file is generated by TableGen. Do not edit.\n\n";
987
988 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
989
Benjamin Kramer5bbc3852012-02-06 11:13:08 +0000990 OS << "namespace clang {\n"
991 << "namespace sema {\n\n"
992 << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, "
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000993 << "Sema &S,\n"
994 << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n"
995 << " switch (At->getKind()) {\n"
996 << " default:\n"
997 << " break;\n";
998
999 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1000 I != E; ++I) {
1001 Record &R = **I;
Douglas Gregor3e7d31a2012-05-02 15:56:52 +00001002 if (!R.getValueAsBit("ASTNode"))
1003 continue;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001004
1005 OS << " case attr::" << R.getName() << ": {\n";
1006 OS << " const " << R.getName() << "Attr *A = cast<"
1007 << R.getName() << "Attr>(At);\n";
1008 bool TDependent = R.getValueAsBit("TemplateDependent");
1009
1010 if (!TDependent) {
1011 OS << " return A->clone(C);\n";
1012 OS << " }\n";
1013 continue;
1014 }
1015
1016 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
1017 std::vector<Argument*> Args;
1018 std::vector<Argument*>::iterator ai, ae;
1019 Args.reserve(ArgRecords.size());
1020
1021 for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
1022 re = ArgRecords.end();
1023 ri != re; ++ri) {
1024 Record &ArgRecord = **ri;
1025 Argument *Arg = createArgument(ArgRecord, R.getName());
1026 assert(Arg);
1027 Args.push_back(Arg);
1028 }
1029 ae = Args.end();
1030
1031 for (ai = Args.begin(); ai != ae; ++ai) {
1032 (*ai)->writeTemplateInstantiation(OS);
1033 }
1034 OS << " return new (C) " << R.getName() << "Attr(A->getLocation(), C";
1035 for (ai = Args.begin(); ai != ae; ++ai) {
1036 OS << ", ";
1037 (*ai)->writeTemplateInstantiationArgs(OS);
1038 }
1039 OS << ");\n }\n";
1040 }
1041 OS << " } // end switch\n"
1042 << " llvm_unreachable(\"Unknown attribute!\");\n"
1043 << " return 0;\n"
Benjamin Kramer5bbc3852012-02-06 11:13:08 +00001044 << "}\n\n"
1045 << "} // end namespace sema\n"
1046 << "} // end namespace clang\n";
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001047}
1048
Michael Hane53ac8a2012-03-07 00:12:16 +00001049void ClangAttrParsedAttrListEmitter::run(raw_ostream &OS) {
1050 OS << "// This file is generated by TableGen. Do not edit.\n\n";
1051
1052 OS << "#ifndef PARSED_ATTR\n";
1053 OS << "#define PARSED_ATTR(NAME) NAME\n";
1054 OS << "#endif\n\n";
1055
1056 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1057 std::set<StringRef> ProcessedAttrs;
1058
1059 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1060 I != E; ++I) {
1061 Record &Attr = **I;
1062
1063 bool SemaHandler = Attr.getValueAsBit("SemaHandler");
1064
1065 if (SemaHandler) {
1066 std::vector<StringRef> Spellings =
1067 getValueAsListOfStrings(Attr, "Spellings");
1068
1069 for (std::vector<StringRef>::const_iterator I = Spellings.begin(),
1070 E = Spellings.end(); I != E; ++I) {
1071 StringRef AttrName = *I;
1072
1073 AttrName = NormalizeAttrName(AttrName);
1074 // skip if a normalized version has been processed.
1075 if (ProcessedAttrs.find(AttrName) != ProcessedAttrs.end())
1076 continue;
1077 else
1078 ProcessedAttrs.insert(AttrName);
1079
1080 OS << "PARSED_ATTR(" << AttrName << ")\n";
1081 }
1082 }
1083 }
1084}
1085
1086void ClangAttrParsedAttrKindsEmitter::run(raw_ostream &OS) {
1087 OS << "// This file is generated by TableGen. Do not edit.\n\n";
1088
1089 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1090
1091 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1092 I != E; ++I) {
1093 Record &Attr = **I;
1094
1095 bool SemaHandler = Attr.getValueAsBit("SemaHandler");
Douglas Gregor331d2ec2012-05-02 16:18:45 +00001096 bool Ignored = Attr.getValueAsBit("Ignored");
Michael Hane53ac8a2012-03-07 00:12:16 +00001097
Douglas Gregor331d2ec2012-05-02 16:18:45 +00001098 if (SemaHandler || Ignored) {
Michael Hane53ac8a2012-03-07 00:12:16 +00001099 std::vector<StringRef> Spellings =
1100 getValueAsListOfStrings(Attr, "Spellings");
1101
1102 for (std::vector<StringRef>::const_iterator I = Spellings.begin(),
1103 E = Spellings.end(); I != E; ++I) {
Douglas Gregor331d2ec2012-05-02 16:18:45 +00001104 StringRef AttrName = *I, Spelling = *I;
Michael Hane53ac8a2012-03-07 00:12:16 +00001105
Douglas Gregor331d2ec2012-05-02 16:18:45 +00001106 AttrName = NormalizeAttrName(AttrName);
1107 Spelling = NormalizeAttrSpelling(Spelling);
Michael Hane53ac8a2012-03-07 00:12:16 +00001108
Douglas Gregor331d2ec2012-05-02 16:18:45 +00001109 if (SemaHandler)
1110 OS << ".Case(\"" << Spelling << "\", " << "AT_" << AttrName << ")\n";
1111 else
1112 OS << ".Case(\"" << Spelling << "\", IgnoredAttribute)\n";
Michael Hane53ac8a2012-03-07 00:12:16 +00001113 }
1114 }
1115 }
1116}
1117
1118