blob: 03b6f76e46af8256721f15e5116b4b74b55a5edf [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>
19
20using namespace llvm;
21
22static const std::vector<StringRef>
23getValueAsListOfStrings(Record &R, StringRef FieldName) {
24 ListInit *List = R.getValueAsListInit(FieldName);
25 assert (List && "Got a null ListInit");
26
27 std::vector<StringRef> Strings;
28 Strings.reserve(List->getSize());
29
30 for (ListInit::const_iterator i = List->begin(), e = List->end();
31 i != e;
32 ++i) {
33 assert(*i && "Got a null element in a ListInit");
34 if (StringInit *S = dynamic_cast<StringInit *>(*i))
35 Strings.push_back(S->getValue());
36 else if (CodeInit *C = dynamic_cast<CodeInit *>(*i))
37 Strings.push_back(C->getValue());
38 else
39 assert(false && "Got a non-string, non-code element in a ListInit");
40 }
41
42 return Strings;
43}
44
45static std::string ReadPCHRecord(StringRef type) {
46 return StringSwitch<std::string>(type)
47 .EndsWith("Decl *", "GetLocalDeclAs<"
48 + std::string(type, 0, type.size()-1) + ">(F, Record[Idx++])")
49 .Case("QualType", "getLocalType(F, Record[Idx++])")
50 .Case("Expr *", "ReadSubExpr()")
51 .Case("IdentifierInfo *", "GetIdentifierInfo(F, Record, Idx)")
52 .Case("SourceLocation", "ReadSourceLocation(F, Record, Idx)")
53 .Default("Record[Idx++]");
54}
55
56// Assumes that the way to get the value is SA->getname()
57static std::string WritePCHRecord(StringRef type, StringRef name) {
58 return StringSwitch<std::string>(type)
59 .EndsWith("Decl *", "AddDeclRef(" + std::string(name) +
60 ", Record);\n")
61 .Case("QualType", "AddTypeRef(" + std::string(name) + ", Record);\n")
62 .Case("Expr *", "AddStmt(" + std::string(name) + ");\n")
63 .Case("IdentifierInfo *",
64 "AddIdentifierRef(" + std::string(name) + ", Record);\n")
65 .Case("SourceLocation",
66 "AddSourceLocation(" + std::string(name) + ", Record);\n")
67 .Default("Record.push_back(" + std::string(name) + ");\n");
68}
69
70namespace {
71 class Argument {
72 std::string lowerName, upperName;
73 StringRef attrName;
74
75 public:
76 Argument(Record &Arg, StringRef Attr)
77 : lowerName(Arg.getValueAsString("Name")), upperName(lowerName),
78 attrName(Attr) {
79 if (!lowerName.empty()) {
80 lowerName[0] = std::tolower(lowerName[0]);
81 upperName[0] = std::toupper(upperName[0]);
82 }
83 }
84 virtual ~Argument() {}
85
86 StringRef getLowerName() const { return lowerName; }
87 StringRef getUpperName() const { return upperName; }
88 StringRef getAttrName() const { return attrName; }
89
90 // These functions print the argument contents formatted in different ways.
91 virtual void writeAccessors(raw_ostream &OS) const = 0;
92 virtual void writeAccessorDefinitions(raw_ostream &OS) const {}
93 virtual void writeCloneArgs(raw_ostream &OS) const = 0;
94 virtual void writeCtorBody(raw_ostream &OS) const {}
95 virtual void writeCtorInitializers(raw_ostream &OS) const = 0;
96 virtual void writeCtorParameters(raw_ostream &OS) const = 0;
97 virtual void writeDeclarations(raw_ostream &OS) const = 0;
98 virtual void writePCHReadArgs(raw_ostream &OS) const = 0;
99 virtual void writePCHReadDecls(raw_ostream &OS) const = 0;
100 virtual void writePCHWrite(raw_ostream &OS) const = 0;
Douglas Gregor1bea8802011-11-19 19:22:57 +0000101 virtual void writeValue(raw_ostream &OS) const = 0;
Peter Collingbourne51d77772011-10-06 13:03:08 +0000102 };
103
104 class SimpleArgument : public Argument {
105 std::string type;
106
107 public:
108 SimpleArgument(Record &Arg, StringRef Attr, std::string T)
109 : Argument(Arg, Attr), type(T)
110 {}
111
112 void writeAccessors(raw_ostream &OS) const {
113 OS << " " << type << " get" << getUpperName() << "() const {\n";
114 OS << " return " << getLowerName() << ";\n";
115 OS << " }";
116 }
117 void writeCloneArgs(raw_ostream &OS) const {
118 OS << getLowerName();
119 }
120 void writeCtorInitializers(raw_ostream &OS) const {
121 OS << getLowerName() << "(" << getUpperName() << ")";
122 }
123 void writeCtorParameters(raw_ostream &OS) const {
124 OS << type << " " << getUpperName();
125 }
126 void writeDeclarations(raw_ostream &OS) const {
127 OS << type << " " << getLowerName() << ";";
128 }
129 void writePCHReadDecls(raw_ostream &OS) const {
130 std::string read = ReadPCHRecord(type);
131 OS << " " << type << " " << getLowerName() << " = " << read << ";\n";
132 }
133 void writePCHReadArgs(raw_ostream &OS) const {
134 OS << getLowerName();
135 }
136 void writePCHWrite(raw_ostream &OS) const {
137 OS << " " << WritePCHRecord(type, "SA->get" +
138 std::string(getUpperName()) + "()");
139 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000140 void writeValue(raw_ostream &OS) const {
141 if (type == "FunctionDecl *") {
142 OS << "\" << get" << getUpperName() << "()->getNameInfo().getAsString() << \"";
143 } else if (type == "IdentifierInfo *") {
144 OS << "\" << get" << getUpperName() << "()->getName() << \"";
145 } else if (type == "QualType") {
146 OS << "\" << get" << getUpperName() << "().getAsString() << \"";
147 } else if (type == "SourceLocation") {
148 OS << "\" << get" << getUpperName() << "().getRawEncoding() << \"";
149 } else {
150 OS << "\" << get" << getUpperName() << "() << \"";
151 }
152 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000153 };
154
155 class StringArgument : public Argument {
156 public:
157 StringArgument(Record &Arg, StringRef Attr)
158 : Argument(Arg, Attr)
159 {}
160
161 void writeAccessors(raw_ostream &OS) const {
162 OS << " llvm::StringRef get" << getUpperName() << "() const {\n";
163 OS << " return llvm::StringRef(" << getLowerName() << ", "
164 << getLowerName() << "Length);\n";
165 OS << " }\n";
166 OS << " unsigned get" << getUpperName() << "Length() const {\n";
167 OS << " return " << getLowerName() << "Length;\n";
168 OS << " }\n";
169 OS << " void set" << getUpperName()
170 << "(ASTContext &C, llvm::StringRef S) {\n";
171 OS << " " << getLowerName() << "Length = S.size();\n";
172 OS << " this->" << getLowerName() << " = new (C, 1) char ["
173 << getLowerName() << "Length];\n";
174 OS << " std::memcpy(this->" << getLowerName() << ", S.data(), "
175 << getLowerName() << "Length);\n";
176 OS << " }";
177 }
178 void writeCloneArgs(raw_ostream &OS) const {
179 OS << "get" << getUpperName() << "()";
180 }
181 void writeCtorBody(raw_ostream &OS) const {
182 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
183 << ".data(), " << getLowerName() << "Length);";
184 }
185 void writeCtorInitializers(raw_ostream &OS) const {
186 OS << getLowerName() << "Length(" << getUpperName() << ".size()),"
187 << getLowerName() << "(new (Ctx, 1) char[" << getLowerName()
188 << "Length])";
189 }
190 void writeCtorParameters(raw_ostream &OS) const {
191 OS << "llvm::StringRef " << getUpperName();
192 }
193 void writeDeclarations(raw_ostream &OS) const {
194 OS << "unsigned " << getLowerName() << "Length;\n";
195 OS << "char *" << getLowerName() << ";";
196 }
197 void writePCHReadDecls(raw_ostream &OS) const {
198 OS << " std::string " << getLowerName()
199 << "= ReadString(Record, Idx);\n";
200 }
201 void writePCHReadArgs(raw_ostream &OS) const {
202 OS << getLowerName();
203 }
204 void writePCHWrite(raw_ostream &OS) const {
205 OS << " AddString(SA->get" << getUpperName() << "(), Record);\n";
206 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000207 void writeValue(raw_ostream &OS) const {
208 OS << "\\\"\" << get" << getUpperName() << "() << \"\\\"";
209 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000210 };
211
212 class AlignedArgument : public Argument {
213 public:
214 AlignedArgument(Record &Arg, StringRef Attr)
215 : Argument(Arg, Attr)
216 {}
217
218 void writeAccessors(raw_ostream &OS) const {
219 OS << " bool is" << getUpperName() << "Dependent() const;\n";
220
221 OS << " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n";
222
223 OS << " bool is" << getUpperName() << "Expr() const {\n";
224 OS << " return is" << getLowerName() << "Expr;\n";
225 OS << " }\n";
226
227 OS << " Expr *get" << getUpperName() << "Expr() const {\n";
228 OS << " assert(is" << getLowerName() << "Expr);\n";
229 OS << " return " << getLowerName() << "Expr;\n";
230 OS << " }\n";
231
232 OS << " TypeSourceInfo *get" << getUpperName() << "Type() const {\n";
233 OS << " assert(!is" << getLowerName() << "Expr);\n";
234 OS << " return " << getLowerName() << "Type;\n";
235 OS << " }";
236 }
237 void writeAccessorDefinitions(raw_ostream &OS) const {
238 OS << "bool " << getAttrName() << "Attr::is" << getUpperName()
239 << "Dependent() const {\n";
240 OS << " if (is" << getLowerName() << "Expr)\n";
241 OS << " return " << getLowerName() << "Expr && (" << getLowerName()
242 << "Expr->isValueDependent() || " << getLowerName()
243 << "Expr->isTypeDependent());\n";
244 OS << " else\n";
245 OS << " return " << getLowerName()
246 << "Type->getType()->isDependentType();\n";
247 OS << "}\n";
248
249 // FIXME: Do not do the calculation here
250 // FIXME: Handle types correctly
251 // A null pointer means maximum alignment
252 // FIXME: Load the platform-specific maximum alignment, rather than
253 // 16, the x86 max.
254 OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName()
255 << "(ASTContext &Ctx) const {\n";
256 OS << " assert(!is" << getUpperName() << "Dependent());\n";
257 OS << " if (is" << getLowerName() << "Expr)\n";
258 OS << " return (" << getLowerName() << "Expr ? " << getLowerName()
Richard Smitha6b8b2c2011-10-10 18:28:20 +0000259 << "Expr->EvaluateKnownConstInt(Ctx).getZExtValue() : 16)"
Peter Collingbourne51d77772011-10-06 13:03:08 +0000260 << "* Ctx.getCharWidth();\n";
261 OS << " else\n";
262 OS << " return 0; // FIXME\n";
263 OS << "}\n";
264 }
265 void writeCloneArgs(raw_ostream &OS) const {
266 OS << "is" << getLowerName() << "Expr, is" << getLowerName()
267 << "Expr ? static_cast<void*>(" << getLowerName()
268 << "Expr) : " << getLowerName()
269 << "Type";
270 }
271 void writeCtorBody(raw_ostream &OS) const {
272 OS << " if (is" << getLowerName() << "Expr)\n";
273 OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>("
274 << getUpperName() << ");\n";
275 OS << " else\n";
276 OS << " " << getLowerName()
277 << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName()
278 << ");";
279 }
280 void writeCtorInitializers(raw_ostream &OS) const {
281 OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)";
282 }
283 void writeCtorParameters(raw_ostream &OS) const {
284 OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName();
285 }
286 void writeDeclarations(raw_ostream &OS) const {
287 OS << "bool is" << getLowerName() << "Expr;\n";
288 OS << "union {\n";
289 OS << "Expr *" << getLowerName() << "Expr;\n";
290 OS << "TypeSourceInfo *" << getLowerName() << "Type;\n";
291 OS << "};";
292 }
293 void writePCHReadArgs(raw_ostream &OS) const {
294 OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr";
295 }
296 void writePCHReadDecls(raw_ostream &OS) const {
297 OS << " bool is" << getLowerName() << "Expr = Record[Idx++];\n";
298 OS << " void *" << getLowerName() << "Ptr;\n";
299 OS << " if (is" << getLowerName() << "Expr)\n";
300 OS << " " << getLowerName() << "Ptr = ReadExpr(F);\n";
301 OS << " else\n";
302 OS << " " << getLowerName()
303 << "Ptr = GetTypeSourceInfo(F, Record, Idx);\n";
304 }
305 void writePCHWrite(raw_ostream &OS) const {
306 OS << " Record.push_back(SA->is" << getUpperName() << "Expr());\n";
307 OS << " if (SA->is" << getUpperName() << "Expr())\n";
308 OS << " AddStmt(SA->get" << getUpperName() << "Expr());\n";
309 OS << " else\n";
310 OS << " AddTypeSourceInfo(SA->get" << getUpperName()
311 << "Type(), Record);\n";
312 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000313 void writeValue(raw_ostream &OS) const {
314 OS << "\" << get" << getUpperName() << "(Ctx) << \"";
315 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000316 };
317
318 class VariadicArgument : public Argument {
319 std::string type;
320
321 public:
322 VariadicArgument(Record &Arg, StringRef Attr, std::string T)
323 : Argument(Arg, Attr), type(T)
324 {}
325
326 std::string getType() const { return type; }
327
328 void writeAccessors(raw_ostream &OS) const {
329 OS << " typedef " << type << "* " << getLowerName() << "_iterator;\n";
330 OS << " " << getLowerName() << "_iterator " << getLowerName()
331 << "_begin() const {\n";
332 OS << " return " << getLowerName() << ";\n";
333 OS << " }\n";
334 OS << " " << getLowerName() << "_iterator " << getLowerName()
335 << "_end() const {\n";
336 OS << " return " << getLowerName() << " + " << getLowerName()
337 << "Size;\n";
338 OS << " }\n";
339 OS << " unsigned " << getLowerName() << "_size() const {\n"
340 << " return " << getLowerName() << "Size;\n;";
341 OS << " }";
342 }
343 void writeCloneArgs(raw_ostream &OS) const {
344 OS << getLowerName() << ", " << getLowerName() << "Size";
345 }
346 void writeCtorBody(raw_ostream &OS) const {
347 // FIXME: memcpy is not safe on non-trivial types.
348 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
349 << ", " << getLowerName() << "Size * sizeof(" << getType() << "));\n";
350 }
351 void writeCtorInitializers(raw_ostream &OS) const {
352 OS << getLowerName() << "Size(" << getUpperName() << "Size), "
353 << getLowerName() << "(new (Ctx, 16) " << getType() << "["
354 << getLowerName() << "Size])";
355 }
356 void writeCtorParameters(raw_ostream &OS) const {
357 OS << getType() << " *" << getUpperName() << ", unsigned "
358 << getUpperName() << "Size";
359 }
360 void writeDeclarations(raw_ostream &OS) const {
361 OS << " unsigned " << getLowerName() << "Size;\n";
362 OS << " " << getType() << " *" << getLowerName() << ";";
363 }
364 void writePCHReadDecls(raw_ostream &OS) const {
365 OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
366 OS << " llvm::SmallVector<" << type << ", 4> " << getLowerName()
367 << ";\n";
368 OS << " " << getLowerName() << ".reserve(" << getLowerName()
369 << "Size);\n";
370 OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
371
372 std::string read = ReadPCHRecord(type);
373 OS << " " << getLowerName() << ".push_back(" << read << ");\n";
374 }
375 void writePCHReadArgs(raw_ostream &OS) const {
376 OS << getLowerName() << ".data(), " << getLowerName() << "Size";
377 }
378 void writePCHWrite(raw_ostream &OS) const{
379 OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";
380 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
381 << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
382 << getLowerName() << "_end(); i != e; ++i)\n";
383 OS << " " << WritePCHRecord(type, "(*i)");
384 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000385 void writeValue(raw_ostream &OS) const {
386 OS << "\";\n";
387 OS << " bool isFirst = true;\n"
388 << " for (" << getAttrName() << "Attr::" << getLowerName()
389 << "_iterator i = " << getLowerName() << "_begin(), e = "
390 << getLowerName() << "_end(); i != e; ++i) {\n"
391 << " if (isFirst) isFirst = false;\n"
392 << " else OS << \", \";\n"
393 << " OS << *i;\n"
394 << " }\n";
395 OS << " OS << \"";
396 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000397 };
398
399 class EnumArgument : public Argument {
400 std::string type;
401 std::vector<StringRef> values, enums;
402 public:
403 EnumArgument(Record &Arg, StringRef Attr)
404 : Argument(Arg, Attr), type(Arg.getValueAsString("Type")),
405 values(getValueAsListOfStrings(Arg, "Values")),
406 enums(getValueAsListOfStrings(Arg, "Enums"))
407 {}
408
409 void writeAccessors(raw_ostream &OS) const {
410 OS << " " << type << " get" << getUpperName() << "() const {\n";
411 OS << " return " << getLowerName() << ";\n";
412 OS << " }";
413 }
414 void writeCloneArgs(raw_ostream &OS) const {
415 OS << getLowerName();
416 }
417 void writeCtorInitializers(raw_ostream &OS) const {
418 OS << getLowerName() << "(" << getUpperName() << ")";
419 }
420 void writeCtorParameters(raw_ostream &OS) const {
421 OS << type << " " << getUpperName();
422 }
423 void writeDeclarations(raw_ostream &OS) const {
424 // Calculate the various enum values
425 std::vector<StringRef> uniques(enums);
426 std::sort(uniques.begin(), uniques.end());
427 uniques.erase(std::unique(uniques.begin(), uniques.end()),
428 uniques.end());
429 // FIXME: Emit a proper error
430 assert(!uniques.empty());
431
432 std::vector<StringRef>::iterator i = uniques.begin(),
433 e = uniques.end();
434 // The last one needs to not have a comma.
435 --e;
436
437 OS << "public:\n";
438 OS << " enum " << type << " {\n";
439 for (; i != e; ++i)
440 OS << " " << *i << ",\n";
441 OS << " " << *e << "\n";
442 OS << " };\n";
443 OS << "private:\n";
444 OS << " " << type << " " << getLowerName() << ";";
445 }
446 void writePCHReadDecls(raw_ostream &OS) const {
447 OS << " " << getAttrName() << "Attr::" << type << " " << getLowerName()
448 << "(static_cast<" << getAttrName() << "Attr::" << type
449 << ">(Record[Idx++]));\n";
450 }
451 void writePCHReadArgs(raw_ostream &OS) const {
452 OS << getLowerName();
453 }
454 void writePCHWrite(raw_ostream &OS) const {
455 OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
456 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000457 void writeValue(raw_ostream &OS) const {
458 OS << "\" << get" << getUpperName() << "() << \"";
459 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000460 };
461
462 class VersionArgument : public Argument {
463 public:
464 VersionArgument(Record &Arg, StringRef Attr)
465 : Argument(Arg, Attr)
466 {}
467
468 void writeAccessors(raw_ostream &OS) const {
469 OS << " VersionTuple get" << getUpperName() << "() const {\n";
470 OS << " return " << getLowerName() << ";\n";
471 OS << " }\n";
472 OS << " void set" << getUpperName()
473 << "(ASTContext &C, VersionTuple V) {\n";
474 OS << " " << getLowerName() << " = V;\n";
475 OS << " }";
476 }
477 void writeCloneArgs(raw_ostream &OS) const {
478 OS << "get" << getUpperName() << "()";
479 }
480 void writeCtorBody(raw_ostream &OS) const {
481 }
482 void writeCtorInitializers(raw_ostream &OS) const {
483 OS << getLowerName() << "(" << getUpperName() << ")";
484 }
485 void writeCtorParameters(raw_ostream &OS) const {
486 OS << "VersionTuple " << getUpperName();
487 }
488 void writeDeclarations(raw_ostream &OS) const {
489 OS << "VersionTuple " << getLowerName() << ";\n";
490 }
491 void writePCHReadDecls(raw_ostream &OS) const {
492 OS << " VersionTuple " << getLowerName()
493 << "= ReadVersionTuple(Record, Idx);\n";
494 }
495 void writePCHReadArgs(raw_ostream &OS) const {
496 OS << getLowerName();
497 }
498 void writePCHWrite(raw_ostream &OS) const {
499 OS << " AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n";
500 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000501 void writeValue(raw_ostream &OS) const {
502 OS << getLowerName() << "=\" << get" << getUpperName() << "() << \"";
503 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000504 };
505}
506
507static Argument *createArgument(Record &Arg, StringRef Attr,
508 Record *Search = 0) {
509 if (!Search)
510 Search = &Arg;
511
512 Argument *Ptr = 0;
513 llvm::StringRef ArgName = Search->getName();
514
515 if (ArgName == "AlignedArgument") Ptr = new AlignedArgument(Arg, Attr);
516 else if (ArgName == "EnumArgument") Ptr = new EnumArgument(Arg, Attr);
517 else if (ArgName == "ExprArgument") Ptr = new SimpleArgument(Arg, Attr,
518 "Expr *");
519 else if (ArgName == "FunctionArgument")
520 Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *");
521 else if (ArgName == "IdentifierArgument")
522 Ptr = new SimpleArgument(Arg, Attr, "IdentifierInfo *");
523 else if (ArgName == "BoolArgument") Ptr = new SimpleArgument(Arg, Attr,
524 "bool");
525 else if (ArgName == "IntArgument") Ptr = new SimpleArgument(Arg, Attr, "int");
526 else if (ArgName == "StringArgument") Ptr = new StringArgument(Arg, Attr);
527 else if (ArgName == "TypeArgument")
528 Ptr = new SimpleArgument(Arg, Attr, "QualType");
529 else if (ArgName == "UnsignedArgument")
530 Ptr = new SimpleArgument(Arg, Attr, "unsigned");
531 else if (ArgName == "SourceLocArgument")
532 Ptr = new SimpleArgument(Arg, Attr, "SourceLocation");
533 else if (ArgName == "VariadicUnsignedArgument")
534 Ptr = new VariadicArgument(Arg, Attr, "unsigned");
535 else if (ArgName == "VariadicExprArgument")
536 Ptr = new VariadicArgument(Arg, Attr, "Expr *");
537 else if (ArgName == "VersionArgument")
538 Ptr = new VersionArgument(Arg, Attr);
539
540 if (!Ptr) {
541 std::vector<Record*> Bases = Search->getSuperClasses();
542 for (std::vector<Record*>::iterator i = Bases.begin(), e = Bases.end();
543 i != e; ++i) {
544 Ptr = createArgument(Arg, Attr, *i);
545 if (Ptr)
546 break;
547 }
548 }
549 return Ptr;
550}
551
Douglas Gregor1bea8802011-11-19 19:22:57 +0000552static void writeAvailabilityValue(raw_ostream &OS) {
553 OS << "\" << getPlatform()->getName();\n"
554 << " if (!getIntroduced().empty()) OS << \", introduced=\" << getIntroduced();\n"
555 << " if (!getDeprecated().empty()) OS << \", deprecated=\" << getDeprecated();\n"
556 << " if (!getObsoleted().empty()) OS << \", obsoleted=\" << getObsoleted();\n"
557 << " if (getUnavailable()) OS << \", unavailable\";\n"
558 << " OS << \"";
559}
560
Peter Collingbourne51d77772011-10-06 13:03:08 +0000561void ClangAttrClassEmitter::run(raw_ostream &OS) {
562 OS << "// This file is generated by TableGen. Do not edit.\n\n";
563 OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
564 OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
565
566 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
567
568 for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
569 i != e; ++i) {
570 Record &R = **i;
571 const std::string &SuperName = R.getSuperClasses().back()->getName();
572
573 OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n";
574
575 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
576 std::vector<Argument*> Args;
577 std::vector<Argument*>::iterator ai, ae;
578 Args.reserve(ArgRecords.size());
579
580 for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
581 re = ArgRecords.end();
582 ri != re; ++ri) {
583 Record &ArgRecord = **ri;
584 Argument *Arg = createArgument(ArgRecord, R.getName());
585 assert(Arg);
586 Args.push_back(Arg);
587
588 Arg->writeDeclarations(OS);
589 OS << "\n\n";
590 }
591
592 ae = Args.end();
593
594 OS << "\n public:\n";
595 OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
596
597 for (ai = Args.begin(); ai != ae; ++ai) {
598 OS << " , ";
599 (*ai)->writeCtorParameters(OS);
600 OS << "\n";
601 }
602
603 OS << " )\n";
604 OS << " : " << SuperName << "(attr::" << R.getName() << ", R)\n";
605
606 for (ai = Args.begin(); ai != ae; ++ai) {
607 OS << " , ";
608 (*ai)->writeCtorInitializers(OS);
609 OS << "\n";
610 }
611
612 OS << " {\n";
613
614 for (ai = Args.begin(); ai != ae; ++ai) {
615 (*ai)->writeCtorBody(OS);
616 OS << "\n";
617 }
618 OS << " }\n\n";
619
620 OS << " virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n";
Douglas Gregor1bea8802011-11-19 19:22:57 +0000621 OS << " virtual void printPretty(llvm::raw_ostream &OS, ASTContext &Ctx) const;\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000622
623 for (ai = Args.begin(); ai != ae; ++ai) {
624 (*ai)->writeAccessors(OS);
625 OS << "\n\n";
626 }
627
628 OS << R.getValueAsCode("AdditionalMembers");
629 OS << "\n\n";
630
631 OS << " static bool classof(const Attr *A) { return A->getKind() == "
632 << "attr::" << R.getName() << "; }\n";
633 OS << " static bool classof(const " << R.getName()
634 << "Attr *) { return true; }\n";
635 OS << "};\n\n";
636 }
637
638 OS << "#endif\n";
639}
640
641void ClangAttrImplEmitter::run(raw_ostream &OS) {
642 OS << "// This file is generated by TableGen. Do not edit.\n\n";
643
644 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
645 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ri, re;
646 std::vector<Argument*>::iterator ai, ae;
647
648 for (; i != e; ++i) {
649 Record &R = **i;
650 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
Douglas Gregor1bea8802011-11-19 19:22:57 +0000651 std::vector<StringRef> Spellings = getValueAsListOfStrings(R, "Spellings");
Peter Collingbourne51d77772011-10-06 13:03:08 +0000652 std::vector<Argument*> Args;
653 for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri)
654 Args.push_back(createArgument(**ri, R.getName()));
655
656 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
657 (*ai)->writeAccessorDefinitions(OS);
658
659 OS << R.getName() << "Attr *" << R.getName()
660 << "Attr::clone(ASTContext &C) const {\n";
661 OS << " return new (C) " << R.getName() << "Attr(getLocation(), C";
662 for (ai = Args.begin(); ai != ae; ++ai) {
663 OS << ", ";
664 (*ai)->writeCloneArgs(OS);
665 }
666 OS << ");\n}\n\n";
Douglas Gregor1bea8802011-11-19 19:22:57 +0000667
668 OS << "void " << R.getName() << "Attr::printPretty("
669 << "llvm::raw_ostream &OS, ASTContext &Ctx) const {\n";
670 if (Spellings.begin() != Spellings.end()) {
671 OS << " OS << \" __attribute__((" << *Spellings.begin();
672 if (Args.size()) OS << "(";
673 if (*Spellings.begin()=="availability") {
674 writeAvailabilityValue(OS);
675 } else {
676 for (ai = Args.begin(); ai != ae; ++ai) {
677 if (ai!=Args.begin()) OS <<", ";
678 (*ai)->writeValue(OS);
679 }
680 }
681 if (Args.size()) OS << ")";
682 OS << "))\";\n";
683 }
684 OS << "}\n\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000685 }
686}
687
688static void EmitAttrList(raw_ostream &OS, StringRef Class,
689 const std::vector<Record*> &AttrList) {
690 std::vector<Record*>::const_iterator i = AttrList.begin(), e = AttrList.end();
691
692 if (i != e) {
693 // Move the end iterator back to emit the last attribute.
694 for(--e; i != e; ++i)
695 OS << Class << "(" << (*i)->getName() << ")\n";
696
697 OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n";
698 }
699}
700
701void ClangAttrListEmitter::run(raw_ostream &OS) {
702 OS << "// This file is generated by TableGen. Do not edit.\n\n";
703
704 OS << "#ifndef LAST_ATTR\n";
705 OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n";
706 OS << "#endif\n\n";
707
708 OS << "#ifndef INHERITABLE_ATTR\n";
709 OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n";
710 OS << "#endif\n\n";
711
712 OS << "#ifndef LAST_INHERITABLE_ATTR\n";
713 OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n";
714 OS << "#endif\n\n";
715
716 OS << "#ifndef INHERITABLE_PARAM_ATTR\n";
717 OS << "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n";
718 OS << "#endif\n\n";
719
720 OS << "#ifndef LAST_INHERITABLE_PARAM_ATTR\n";
721 OS << "#define LAST_INHERITABLE_PARAM_ATTR(NAME)"
722 " INHERITABLE_PARAM_ATTR(NAME)\n";
723 OS << "#endif\n\n";
724
725 Record *InhClass = Records.getClass("InheritableAttr");
726 Record *InhParamClass = Records.getClass("InheritableParamAttr");
727 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
728 NonInhAttrs, InhAttrs, InhParamAttrs;
729 for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
730 i != e; ++i) {
731 if ((*i)->isSubClassOf(InhParamClass))
732 InhParamAttrs.push_back(*i);
733 else if ((*i)->isSubClassOf(InhClass))
734 InhAttrs.push_back(*i);
735 else
736 NonInhAttrs.push_back(*i);
737 }
738
739 EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs);
740 EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs);
741 EmitAttrList(OS, "ATTR", NonInhAttrs);
742
743 OS << "#undef LAST_ATTR\n";
744 OS << "#undef INHERITABLE_ATTR\n";
745 OS << "#undef LAST_INHERITABLE_ATTR\n";
746 OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n";
747 OS << "#undef ATTR\n";
748}
749
750void ClangAttrPCHReadEmitter::run(raw_ostream &OS) {
751 OS << "// This file is generated by TableGen. Do not edit.\n\n";
752
753 Record *InhClass = Records.getClass("InheritableAttr");
754 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
755 ArgRecords;
756 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
757 std::vector<Argument*> Args;
758 std::vector<Argument*>::iterator ri, re;
759
760 OS << " switch (Kind) {\n";
761 OS << " default:\n";
762 OS << " assert(0 && \"Unknown attribute!\");\n";
763 OS << " break;\n";
764 for (; i != e; ++i) {
765 Record &R = **i;
766 OS << " case attr::" << R.getName() << ": {\n";
767 if (R.isSubClassOf(InhClass))
768 OS << " bool isInherited = Record[Idx++];\n";
769 ArgRecords = R.getValueAsListOfDefs("Args");
770 Args.clear();
771 for (ai = ArgRecords.begin(), ae = ArgRecords.end(); ai != ae; ++ai) {
772 Argument *A = createArgument(**ai, R.getName());
773 Args.push_back(A);
774 A->writePCHReadDecls(OS);
775 }
776 OS << " New = new (Context) " << R.getName() << "Attr(Range, Context";
777 for (ri = Args.begin(), re = Args.end(); ri != re; ++ri) {
778 OS << ", ";
779 (*ri)->writePCHReadArgs(OS);
780 }
781 OS << ");\n";
782 if (R.isSubClassOf(InhClass))
783 OS << " cast<InheritableAttr>(New)->setInherited(isInherited);\n";
784 OS << " break;\n";
785 OS << " }\n";
786 }
787 OS << " }\n";
788}
789
790void ClangAttrPCHWriteEmitter::run(raw_ostream &OS) {
791 Record *InhClass = Records.getClass("InheritableAttr");
792 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
793 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
794
795 OS << " switch (A->getKind()) {\n";
796 OS << " default:\n";
797 OS << " llvm_unreachable(\"Unknown attribute kind!\");\n";
798 OS << " break;\n";
799 for (; i != e; ++i) {
800 Record &R = **i;
801 OS << " case attr::" << R.getName() << ": {\n";
802 Args = R.getValueAsListOfDefs("Args");
803 if (R.isSubClassOf(InhClass) || !Args.empty())
804 OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
805 << "Attr>(A);\n";
806 if (R.isSubClassOf(InhClass))
807 OS << " Record.push_back(SA->isInherited());\n";
808 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
809 createArgument(**ai, R.getName())->writePCHWrite(OS);
810 OS << " break;\n";
811 OS << " }\n";
812 }
813 OS << " }\n";
814}
815
816void ClangAttrSpellingListEmitter::run(raw_ostream &OS) {
817 OS << "// This file is generated by TableGen. Do not edit.\n\n";
818
819 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
820
821 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) {
822 Record &Attr = **I;
823
824 std::vector<StringRef> Spellings = getValueAsListOfStrings(Attr, "Spellings");
825
826 for (std::vector<StringRef>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) {
827 StringRef Spelling = *I;
828 OS << ".Case(\"" << Spelling << "\", true)\n";
829 }
830 }
831
832}
833
834void ClangAttrLateParsedListEmitter::run(raw_ostream &OS) {
835 OS << "// This file is generated by TableGen. Do not edit.\n\n";
836
837 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
838
839 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
840 I != E; ++I) {
841 Record &Attr = **I;
842
843 bool LateParsed = Attr.getValueAsBit("LateParsed");
844
845 if (LateParsed) {
846 std::vector<StringRef> Spellings =
847 getValueAsListOfStrings(Attr, "Spellings");
848
849 for (std::vector<StringRef>::const_iterator I = Spellings.begin(),
850 E = Spellings.end(); I != E; ++I) {
851 OS << ".Case(\"" << (*I) << "\", " << LateParsed << ")\n";
852 }
853 }
854 }
855}