blob: 5c236be559f165d38ce74252f85af4acf35b8b53 [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;
101 };
102
103 class SimpleArgument : public Argument {
104 std::string type;
105
106 public:
107 SimpleArgument(Record &Arg, StringRef Attr, std::string T)
108 : Argument(Arg, Attr), type(T)
109 {}
110
111 void writeAccessors(raw_ostream &OS) const {
112 OS << " " << type << " get" << getUpperName() << "() const {\n";
113 OS << " return " << getLowerName() << ";\n";
114 OS << " }";
115 }
116 void writeCloneArgs(raw_ostream &OS) const {
117 OS << getLowerName();
118 }
119 void writeCtorInitializers(raw_ostream &OS) const {
120 OS << getLowerName() << "(" << getUpperName() << ")";
121 }
122 void writeCtorParameters(raw_ostream &OS) const {
123 OS << type << " " << getUpperName();
124 }
125 void writeDeclarations(raw_ostream &OS) const {
126 OS << type << " " << getLowerName() << ";";
127 }
128 void writePCHReadDecls(raw_ostream &OS) const {
129 std::string read = ReadPCHRecord(type);
130 OS << " " << type << " " << getLowerName() << " = " << read << ";\n";
131 }
132 void writePCHReadArgs(raw_ostream &OS) const {
133 OS << getLowerName();
134 }
135 void writePCHWrite(raw_ostream &OS) const {
136 OS << " " << WritePCHRecord(type, "SA->get" +
137 std::string(getUpperName()) + "()");
138 }
139 };
140
141 class StringArgument : public Argument {
142 public:
143 StringArgument(Record &Arg, StringRef Attr)
144 : Argument(Arg, Attr)
145 {}
146
147 void writeAccessors(raw_ostream &OS) const {
148 OS << " llvm::StringRef get" << getUpperName() << "() const {\n";
149 OS << " return llvm::StringRef(" << getLowerName() << ", "
150 << getLowerName() << "Length);\n";
151 OS << " }\n";
152 OS << " unsigned get" << getUpperName() << "Length() const {\n";
153 OS << " return " << getLowerName() << "Length;\n";
154 OS << " }\n";
155 OS << " void set" << getUpperName()
156 << "(ASTContext &C, llvm::StringRef S) {\n";
157 OS << " " << getLowerName() << "Length = S.size();\n";
158 OS << " this->" << getLowerName() << " = new (C, 1) char ["
159 << getLowerName() << "Length];\n";
160 OS << " std::memcpy(this->" << getLowerName() << ", S.data(), "
161 << getLowerName() << "Length);\n";
162 OS << " }";
163 }
164 void writeCloneArgs(raw_ostream &OS) const {
165 OS << "get" << getUpperName() << "()";
166 }
167 void writeCtorBody(raw_ostream &OS) const {
168 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
169 << ".data(), " << getLowerName() << "Length);";
170 }
171 void writeCtorInitializers(raw_ostream &OS) const {
172 OS << getLowerName() << "Length(" << getUpperName() << ".size()),"
173 << getLowerName() << "(new (Ctx, 1) char[" << getLowerName()
174 << "Length])";
175 }
176 void writeCtorParameters(raw_ostream &OS) const {
177 OS << "llvm::StringRef " << getUpperName();
178 }
179 void writeDeclarations(raw_ostream &OS) const {
180 OS << "unsigned " << getLowerName() << "Length;\n";
181 OS << "char *" << getLowerName() << ";";
182 }
183 void writePCHReadDecls(raw_ostream &OS) const {
184 OS << " std::string " << getLowerName()
185 << "= ReadString(Record, Idx);\n";
186 }
187 void writePCHReadArgs(raw_ostream &OS) const {
188 OS << getLowerName();
189 }
190 void writePCHWrite(raw_ostream &OS) const {
191 OS << " AddString(SA->get" << getUpperName() << "(), Record);\n";
192 }
193 };
194
195 class AlignedArgument : public Argument {
196 public:
197 AlignedArgument(Record &Arg, StringRef Attr)
198 : Argument(Arg, Attr)
199 {}
200
201 void writeAccessors(raw_ostream &OS) const {
202 OS << " bool is" << getUpperName() << "Dependent() const;\n";
203
204 OS << " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n";
205
206 OS << " bool is" << getUpperName() << "Expr() const {\n";
207 OS << " return is" << getLowerName() << "Expr;\n";
208 OS << " }\n";
209
210 OS << " Expr *get" << getUpperName() << "Expr() const {\n";
211 OS << " assert(is" << getLowerName() << "Expr);\n";
212 OS << " return " << getLowerName() << "Expr;\n";
213 OS << " }\n";
214
215 OS << " TypeSourceInfo *get" << getUpperName() << "Type() const {\n";
216 OS << " assert(!is" << getLowerName() << "Expr);\n";
217 OS << " return " << getLowerName() << "Type;\n";
218 OS << " }";
219 }
220 void writeAccessorDefinitions(raw_ostream &OS) const {
221 OS << "bool " << getAttrName() << "Attr::is" << getUpperName()
222 << "Dependent() const {\n";
223 OS << " if (is" << getLowerName() << "Expr)\n";
224 OS << " return " << getLowerName() << "Expr && (" << getLowerName()
225 << "Expr->isValueDependent() || " << getLowerName()
226 << "Expr->isTypeDependent());\n";
227 OS << " else\n";
228 OS << " return " << getLowerName()
229 << "Type->getType()->isDependentType();\n";
230 OS << "}\n";
231
232 // FIXME: Do not do the calculation here
233 // FIXME: Handle types correctly
234 // A null pointer means maximum alignment
235 // FIXME: Load the platform-specific maximum alignment, rather than
236 // 16, the x86 max.
237 OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName()
238 << "(ASTContext &Ctx) const {\n";
239 OS << " assert(!is" << getUpperName() << "Dependent());\n";
240 OS << " if (is" << getLowerName() << "Expr)\n";
241 OS << " return (" << getLowerName() << "Expr ? " << getLowerName()
Richard Smitha6b8b2c2011-10-10 18:28:20 +0000242 << "Expr->EvaluateKnownConstInt(Ctx).getZExtValue() : 16)"
Peter Collingbourne51d77772011-10-06 13:03:08 +0000243 << "* Ctx.getCharWidth();\n";
244 OS << " else\n";
245 OS << " return 0; // FIXME\n";
246 OS << "}\n";
247 }
248 void writeCloneArgs(raw_ostream &OS) const {
249 OS << "is" << getLowerName() << "Expr, is" << getLowerName()
250 << "Expr ? static_cast<void*>(" << getLowerName()
251 << "Expr) : " << getLowerName()
252 << "Type";
253 }
254 void writeCtorBody(raw_ostream &OS) const {
255 OS << " if (is" << getLowerName() << "Expr)\n";
256 OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>("
257 << getUpperName() << ");\n";
258 OS << " else\n";
259 OS << " " << getLowerName()
260 << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName()
261 << ");";
262 }
263 void writeCtorInitializers(raw_ostream &OS) const {
264 OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)";
265 }
266 void writeCtorParameters(raw_ostream &OS) const {
267 OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName();
268 }
269 void writeDeclarations(raw_ostream &OS) const {
270 OS << "bool is" << getLowerName() << "Expr;\n";
271 OS << "union {\n";
272 OS << "Expr *" << getLowerName() << "Expr;\n";
273 OS << "TypeSourceInfo *" << getLowerName() << "Type;\n";
274 OS << "};";
275 }
276 void writePCHReadArgs(raw_ostream &OS) const {
277 OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr";
278 }
279 void writePCHReadDecls(raw_ostream &OS) const {
280 OS << " bool is" << getLowerName() << "Expr = Record[Idx++];\n";
281 OS << " void *" << getLowerName() << "Ptr;\n";
282 OS << " if (is" << getLowerName() << "Expr)\n";
283 OS << " " << getLowerName() << "Ptr = ReadExpr(F);\n";
284 OS << " else\n";
285 OS << " " << getLowerName()
286 << "Ptr = GetTypeSourceInfo(F, Record, Idx);\n";
287 }
288 void writePCHWrite(raw_ostream &OS) const {
289 OS << " Record.push_back(SA->is" << getUpperName() << "Expr());\n";
290 OS << " if (SA->is" << getUpperName() << "Expr())\n";
291 OS << " AddStmt(SA->get" << getUpperName() << "Expr());\n";
292 OS << " else\n";
293 OS << " AddTypeSourceInfo(SA->get" << getUpperName()
294 << "Type(), Record);\n";
295 }
296 };
297
298 class VariadicArgument : public Argument {
299 std::string type;
300
301 public:
302 VariadicArgument(Record &Arg, StringRef Attr, std::string T)
303 : Argument(Arg, Attr), type(T)
304 {}
305
306 std::string getType() const { return type; }
307
308 void writeAccessors(raw_ostream &OS) const {
309 OS << " typedef " << type << "* " << getLowerName() << "_iterator;\n";
310 OS << " " << getLowerName() << "_iterator " << getLowerName()
311 << "_begin() const {\n";
312 OS << " return " << getLowerName() << ";\n";
313 OS << " }\n";
314 OS << " " << getLowerName() << "_iterator " << getLowerName()
315 << "_end() const {\n";
316 OS << " return " << getLowerName() << " + " << getLowerName()
317 << "Size;\n";
318 OS << " }\n";
319 OS << " unsigned " << getLowerName() << "_size() const {\n"
320 << " return " << getLowerName() << "Size;\n;";
321 OS << " }";
322 }
323 void writeCloneArgs(raw_ostream &OS) const {
324 OS << getLowerName() << ", " << getLowerName() << "Size";
325 }
326 void writeCtorBody(raw_ostream &OS) const {
327 // FIXME: memcpy is not safe on non-trivial types.
328 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
329 << ", " << getLowerName() << "Size * sizeof(" << getType() << "));\n";
330 }
331 void writeCtorInitializers(raw_ostream &OS) const {
332 OS << getLowerName() << "Size(" << getUpperName() << "Size), "
333 << getLowerName() << "(new (Ctx, 16) " << getType() << "["
334 << getLowerName() << "Size])";
335 }
336 void writeCtorParameters(raw_ostream &OS) const {
337 OS << getType() << " *" << getUpperName() << ", unsigned "
338 << getUpperName() << "Size";
339 }
340 void writeDeclarations(raw_ostream &OS) const {
341 OS << " unsigned " << getLowerName() << "Size;\n";
342 OS << " " << getType() << " *" << getLowerName() << ";";
343 }
344 void writePCHReadDecls(raw_ostream &OS) const {
345 OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
346 OS << " llvm::SmallVector<" << type << ", 4> " << getLowerName()
347 << ";\n";
348 OS << " " << getLowerName() << ".reserve(" << getLowerName()
349 << "Size);\n";
350 OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
351
352 std::string read = ReadPCHRecord(type);
353 OS << " " << getLowerName() << ".push_back(" << read << ");\n";
354 }
355 void writePCHReadArgs(raw_ostream &OS) const {
356 OS << getLowerName() << ".data(), " << getLowerName() << "Size";
357 }
358 void writePCHWrite(raw_ostream &OS) const{
359 OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";
360 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
361 << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
362 << getLowerName() << "_end(); i != e; ++i)\n";
363 OS << " " << WritePCHRecord(type, "(*i)");
364 }
365 };
366
367 class EnumArgument : public Argument {
368 std::string type;
369 std::vector<StringRef> values, enums;
370 public:
371 EnumArgument(Record &Arg, StringRef Attr)
372 : Argument(Arg, Attr), type(Arg.getValueAsString("Type")),
373 values(getValueAsListOfStrings(Arg, "Values")),
374 enums(getValueAsListOfStrings(Arg, "Enums"))
375 {}
376
377 void writeAccessors(raw_ostream &OS) const {
378 OS << " " << type << " get" << getUpperName() << "() const {\n";
379 OS << " return " << getLowerName() << ";\n";
380 OS << " }";
381 }
382 void writeCloneArgs(raw_ostream &OS) const {
383 OS << getLowerName();
384 }
385 void writeCtorInitializers(raw_ostream &OS) const {
386 OS << getLowerName() << "(" << getUpperName() << ")";
387 }
388 void writeCtorParameters(raw_ostream &OS) const {
389 OS << type << " " << getUpperName();
390 }
391 void writeDeclarations(raw_ostream &OS) const {
392 // Calculate the various enum values
393 std::vector<StringRef> uniques(enums);
394 std::sort(uniques.begin(), uniques.end());
395 uniques.erase(std::unique(uniques.begin(), uniques.end()),
396 uniques.end());
397 // FIXME: Emit a proper error
398 assert(!uniques.empty());
399
400 std::vector<StringRef>::iterator i = uniques.begin(),
401 e = uniques.end();
402 // The last one needs to not have a comma.
403 --e;
404
405 OS << "public:\n";
406 OS << " enum " << type << " {\n";
407 for (; i != e; ++i)
408 OS << " " << *i << ",\n";
409 OS << " " << *e << "\n";
410 OS << " };\n";
411 OS << "private:\n";
412 OS << " " << type << " " << getLowerName() << ";";
413 }
414 void writePCHReadDecls(raw_ostream &OS) const {
415 OS << " " << getAttrName() << "Attr::" << type << " " << getLowerName()
416 << "(static_cast<" << getAttrName() << "Attr::" << type
417 << ">(Record[Idx++]));\n";
418 }
419 void writePCHReadArgs(raw_ostream &OS) const {
420 OS << getLowerName();
421 }
422 void writePCHWrite(raw_ostream &OS) const {
423 OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
424 }
425 };
426
427 class VersionArgument : public Argument {
428 public:
429 VersionArgument(Record &Arg, StringRef Attr)
430 : Argument(Arg, Attr)
431 {}
432
433 void writeAccessors(raw_ostream &OS) const {
434 OS << " VersionTuple get" << getUpperName() << "() const {\n";
435 OS << " return " << getLowerName() << ";\n";
436 OS << " }\n";
437 OS << " void set" << getUpperName()
438 << "(ASTContext &C, VersionTuple V) {\n";
439 OS << " " << getLowerName() << " = V;\n";
440 OS << " }";
441 }
442 void writeCloneArgs(raw_ostream &OS) const {
443 OS << "get" << getUpperName() << "()";
444 }
445 void writeCtorBody(raw_ostream &OS) const {
446 }
447 void writeCtorInitializers(raw_ostream &OS) const {
448 OS << getLowerName() << "(" << getUpperName() << ")";
449 }
450 void writeCtorParameters(raw_ostream &OS) const {
451 OS << "VersionTuple " << getUpperName();
452 }
453 void writeDeclarations(raw_ostream &OS) const {
454 OS << "VersionTuple " << getLowerName() << ";\n";
455 }
456 void writePCHReadDecls(raw_ostream &OS) const {
457 OS << " VersionTuple " << getLowerName()
458 << "= ReadVersionTuple(Record, Idx);\n";
459 }
460 void writePCHReadArgs(raw_ostream &OS) const {
461 OS << getLowerName();
462 }
463 void writePCHWrite(raw_ostream &OS) const {
464 OS << " AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n";
465 }
466 };
467}
468
469static Argument *createArgument(Record &Arg, StringRef Attr,
470 Record *Search = 0) {
471 if (!Search)
472 Search = &Arg;
473
474 Argument *Ptr = 0;
475 llvm::StringRef ArgName = Search->getName();
476
477 if (ArgName == "AlignedArgument") Ptr = new AlignedArgument(Arg, Attr);
478 else if (ArgName == "EnumArgument") Ptr = new EnumArgument(Arg, Attr);
479 else if (ArgName == "ExprArgument") Ptr = new SimpleArgument(Arg, Attr,
480 "Expr *");
481 else if (ArgName == "FunctionArgument")
482 Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *");
483 else if (ArgName == "IdentifierArgument")
484 Ptr = new SimpleArgument(Arg, Attr, "IdentifierInfo *");
485 else if (ArgName == "BoolArgument") Ptr = new SimpleArgument(Arg, Attr,
486 "bool");
487 else if (ArgName == "IntArgument") Ptr = new SimpleArgument(Arg, Attr, "int");
488 else if (ArgName == "StringArgument") Ptr = new StringArgument(Arg, Attr);
489 else if (ArgName == "TypeArgument")
490 Ptr = new SimpleArgument(Arg, Attr, "QualType");
491 else if (ArgName == "UnsignedArgument")
492 Ptr = new SimpleArgument(Arg, Attr, "unsigned");
493 else if (ArgName == "SourceLocArgument")
494 Ptr = new SimpleArgument(Arg, Attr, "SourceLocation");
495 else if (ArgName == "VariadicUnsignedArgument")
496 Ptr = new VariadicArgument(Arg, Attr, "unsigned");
497 else if (ArgName == "VariadicExprArgument")
498 Ptr = new VariadicArgument(Arg, Attr, "Expr *");
499 else if (ArgName == "VersionArgument")
500 Ptr = new VersionArgument(Arg, Attr);
501
502 if (!Ptr) {
503 std::vector<Record*> Bases = Search->getSuperClasses();
504 for (std::vector<Record*>::iterator i = Bases.begin(), e = Bases.end();
505 i != e; ++i) {
506 Ptr = createArgument(Arg, Attr, *i);
507 if (Ptr)
508 break;
509 }
510 }
511 return Ptr;
512}
513
514void ClangAttrClassEmitter::run(raw_ostream &OS) {
515 OS << "// This file is generated by TableGen. Do not edit.\n\n";
516 OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
517 OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
518
519 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
520
521 for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
522 i != e; ++i) {
523 Record &R = **i;
524 const std::string &SuperName = R.getSuperClasses().back()->getName();
525
526 OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n";
527
528 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
529 std::vector<Argument*> Args;
530 std::vector<Argument*>::iterator ai, ae;
531 Args.reserve(ArgRecords.size());
532
533 for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
534 re = ArgRecords.end();
535 ri != re; ++ri) {
536 Record &ArgRecord = **ri;
537 Argument *Arg = createArgument(ArgRecord, R.getName());
538 assert(Arg);
539 Args.push_back(Arg);
540
541 Arg->writeDeclarations(OS);
542 OS << "\n\n";
543 }
544
545 ae = Args.end();
546
547 OS << "\n public:\n";
548 OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
549
550 for (ai = Args.begin(); ai != ae; ++ai) {
551 OS << " , ";
552 (*ai)->writeCtorParameters(OS);
553 OS << "\n";
554 }
555
556 OS << " )\n";
557 OS << " : " << SuperName << "(attr::" << R.getName() << ", R)\n";
558
559 for (ai = Args.begin(); ai != ae; ++ai) {
560 OS << " , ";
561 (*ai)->writeCtorInitializers(OS);
562 OS << "\n";
563 }
564
565 OS << " {\n";
566
567 for (ai = Args.begin(); ai != ae; ++ai) {
568 (*ai)->writeCtorBody(OS);
569 OS << "\n";
570 }
571 OS << " }\n\n";
572
573 OS << " virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n";
574
575 for (ai = Args.begin(); ai != ae; ++ai) {
576 (*ai)->writeAccessors(OS);
577 OS << "\n\n";
578 }
579
580 OS << R.getValueAsCode("AdditionalMembers");
581 OS << "\n\n";
582
583 OS << " static bool classof(const Attr *A) { return A->getKind() == "
584 << "attr::" << R.getName() << "; }\n";
585 OS << " static bool classof(const " << R.getName()
586 << "Attr *) { return true; }\n";
587 OS << "};\n\n";
588 }
589
590 OS << "#endif\n";
591}
592
593void ClangAttrImplEmitter::run(raw_ostream &OS) {
594 OS << "// This file is generated by TableGen. Do not edit.\n\n";
595
596 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
597 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ri, re;
598 std::vector<Argument*>::iterator ai, ae;
599
600 for (; i != e; ++i) {
601 Record &R = **i;
602 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
603 std::vector<Argument*> Args;
604 for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri)
605 Args.push_back(createArgument(**ri, R.getName()));
606
607 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
608 (*ai)->writeAccessorDefinitions(OS);
609
610 OS << R.getName() << "Attr *" << R.getName()
611 << "Attr::clone(ASTContext &C) const {\n";
612 OS << " return new (C) " << R.getName() << "Attr(getLocation(), C";
613 for (ai = Args.begin(); ai != ae; ++ai) {
614 OS << ", ";
615 (*ai)->writeCloneArgs(OS);
616 }
617 OS << ");\n}\n\n";
618 }
619}
620
621static void EmitAttrList(raw_ostream &OS, StringRef Class,
622 const std::vector<Record*> &AttrList) {
623 std::vector<Record*>::const_iterator i = AttrList.begin(), e = AttrList.end();
624
625 if (i != e) {
626 // Move the end iterator back to emit the last attribute.
627 for(--e; i != e; ++i)
628 OS << Class << "(" << (*i)->getName() << ")\n";
629
630 OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n";
631 }
632}
633
634void ClangAttrListEmitter::run(raw_ostream &OS) {
635 OS << "// This file is generated by TableGen. Do not edit.\n\n";
636
637 OS << "#ifndef LAST_ATTR\n";
638 OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n";
639 OS << "#endif\n\n";
640
641 OS << "#ifndef INHERITABLE_ATTR\n";
642 OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n";
643 OS << "#endif\n\n";
644
645 OS << "#ifndef LAST_INHERITABLE_ATTR\n";
646 OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n";
647 OS << "#endif\n\n";
648
649 OS << "#ifndef INHERITABLE_PARAM_ATTR\n";
650 OS << "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n";
651 OS << "#endif\n\n";
652
653 OS << "#ifndef LAST_INHERITABLE_PARAM_ATTR\n";
654 OS << "#define LAST_INHERITABLE_PARAM_ATTR(NAME)"
655 " INHERITABLE_PARAM_ATTR(NAME)\n";
656 OS << "#endif\n\n";
657
658 Record *InhClass = Records.getClass("InheritableAttr");
659 Record *InhParamClass = Records.getClass("InheritableParamAttr");
660 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
661 NonInhAttrs, InhAttrs, InhParamAttrs;
662 for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
663 i != e; ++i) {
664 if ((*i)->isSubClassOf(InhParamClass))
665 InhParamAttrs.push_back(*i);
666 else if ((*i)->isSubClassOf(InhClass))
667 InhAttrs.push_back(*i);
668 else
669 NonInhAttrs.push_back(*i);
670 }
671
672 EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs);
673 EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs);
674 EmitAttrList(OS, "ATTR", NonInhAttrs);
675
676 OS << "#undef LAST_ATTR\n";
677 OS << "#undef INHERITABLE_ATTR\n";
678 OS << "#undef LAST_INHERITABLE_ATTR\n";
679 OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n";
680 OS << "#undef ATTR\n";
681}
682
683void ClangAttrPCHReadEmitter::run(raw_ostream &OS) {
684 OS << "// This file is generated by TableGen. Do not edit.\n\n";
685
686 Record *InhClass = Records.getClass("InheritableAttr");
687 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
688 ArgRecords;
689 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
690 std::vector<Argument*> Args;
691 std::vector<Argument*>::iterator ri, re;
692
693 OS << " switch (Kind) {\n";
694 OS << " default:\n";
695 OS << " assert(0 && \"Unknown attribute!\");\n";
696 OS << " break;\n";
697 for (; i != e; ++i) {
698 Record &R = **i;
699 OS << " case attr::" << R.getName() << ": {\n";
700 if (R.isSubClassOf(InhClass))
701 OS << " bool isInherited = Record[Idx++];\n";
702 ArgRecords = R.getValueAsListOfDefs("Args");
703 Args.clear();
704 for (ai = ArgRecords.begin(), ae = ArgRecords.end(); ai != ae; ++ai) {
705 Argument *A = createArgument(**ai, R.getName());
706 Args.push_back(A);
707 A->writePCHReadDecls(OS);
708 }
709 OS << " New = new (Context) " << R.getName() << "Attr(Range, Context";
710 for (ri = Args.begin(), re = Args.end(); ri != re; ++ri) {
711 OS << ", ";
712 (*ri)->writePCHReadArgs(OS);
713 }
714 OS << ");\n";
715 if (R.isSubClassOf(InhClass))
716 OS << " cast<InheritableAttr>(New)->setInherited(isInherited);\n";
717 OS << " break;\n";
718 OS << " }\n";
719 }
720 OS << " }\n";
721}
722
723void ClangAttrPCHWriteEmitter::run(raw_ostream &OS) {
724 Record *InhClass = Records.getClass("InheritableAttr");
725 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
726 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
727
728 OS << " switch (A->getKind()) {\n";
729 OS << " default:\n";
730 OS << " llvm_unreachable(\"Unknown attribute kind!\");\n";
731 OS << " break;\n";
732 for (; i != e; ++i) {
733 Record &R = **i;
734 OS << " case attr::" << R.getName() << ": {\n";
735 Args = R.getValueAsListOfDefs("Args");
736 if (R.isSubClassOf(InhClass) || !Args.empty())
737 OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
738 << "Attr>(A);\n";
739 if (R.isSubClassOf(InhClass))
740 OS << " Record.push_back(SA->isInherited());\n";
741 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
742 createArgument(**ai, R.getName())->writePCHWrite(OS);
743 OS << " break;\n";
744 OS << " }\n";
745 }
746 OS << " }\n";
747}
748
749void ClangAttrSpellingListEmitter::run(raw_ostream &OS) {
750 OS << "// This file is generated by TableGen. Do not edit.\n\n";
751
752 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
753
754 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) {
755 Record &Attr = **I;
756
757 std::vector<StringRef> Spellings = getValueAsListOfStrings(Attr, "Spellings");
758
759 for (std::vector<StringRef>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) {
760 StringRef Spelling = *I;
761 OS << ".Case(\"" << Spelling << "\", true)\n";
762 }
763 }
764
765}
766
767void ClangAttrLateParsedListEmitter::run(raw_ostream &OS) {
768 OS << "// This file is generated by TableGen. Do not edit.\n\n";
769
770 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
771
772 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
773 I != E; ++I) {
774 Record &Attr = **I;
775
776 bool LateParsed = Attr.getValueAsBit("LateParsed");
777
778 if (LateParsed) {
779 std::vector<StringRef> Spellings =
780 getValueAsListOfStrings(Attr, "Spellings");
781
782 for (std::vector<StringRef>::const_iterator I = Spellings.begin(),
783 E = Spellings.end(); I != E; ++I) {
784 OS << ".Case(\"" << (*I) << "\", " << LateParsed << ")\n";
785 }
786 }
787 }
788}