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