blob: 9ad0603bdbfbe8390b6aa6797fb251468f633b2a [file] [log] [blame]
Sean Hunt16171442010-06-16 23:45:50 +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 "Record.h"
Sean Hunt726a3d22010-08-18 23:23:09 +000016#include "llvm/ADT/StringSwitch.h"
Sean Hunt16171442010-06-16 23:45:50 +000017#include <algorithm>
Sean Hunt5c5f4662010-08-19 00:19:03 +000018#include <cctype>
Sean Hunt16171442010-06-16 23:45:50 +000019
20using namespace llvm;
21
Jim Grosbachbb168242010-10-08 18:13:57 +000022static const std::vector<StringRef>
23getValueAsListOfStrings(Record &R, StringRef FieldName) {
Eric Christopherd568b3f2011-07-11 23:06:52 +000024 ListInit *List = R.getValueAsListInit(FieldName);
Sean Hunt726a3d22010-08-18 23:23:09 +000025 assert (List && "Got a null ListInit");
26
27 std::vector<StringRef> Strings;
28 Strings.reserve(List->getSize());
29
Eric Christopherd568b3f2011-07-11 23:06:52 +000030 for (ListInit::iterator i = List->begin(), e = List->end(); i != e; ++i) {
Sean Hunt726a3d22010-08-18 23:23:09 +000031 assert(*i && "Got a null element in a ListInit");
Eric Christopherd568b3f2011-07-11 23:06:52 +000032 if (StringInit *S = dynamic_cast<StringInit *>(*i))
Sean Hunt726a3d22010-08-18 23:23:09 +000033 Strings.push_back(S->getValue());
Eric Christopherd568b3f2011-07-11 23:06:52 +000034 else if (CodeInit *C = dynamic_cast<CodeInit *>(*i))
Sean Hunt726a3d22010-08-18 23:23:09 +000035 Strings.push_back(C->getValue());
36 else
37 assert(false && "Got a non-string, non-code element in a ListInit");
38 }
39
40 return Strings;
41}
42
43std::string ReadPCHRecord(StringRef type) {
44 return StringSwitch<std::string>(type)
Douglas Gregor6bd48422011-07-28 20:55:16 +000045 .EndsWith("Decl *", "GetLocalDeclAs<"
46 + std::string(type, 0, type.size()-1) + ">(F, Record[Idx++])")
47 .Case("QualType", "getLocalType(F, Record[Idx++])")
Sean Huntc85094f2011-02-17 03:30:09 +000048 .Case("Expr *", "ReadSubExpr()")
Douglas Gregor6bd48422011-07-28 20:55:16 +000049 .Case("IdentifierInfo *", "GetIdentifierInfo(F, Record, Idx)")
Sean Hunt726a3d22010-08-18 23:23:09 +000050 .Default("Record[Idx++]");
51}
52
53// Assumes that the way to get the value is SA->getname()
54std::string WritePCHRecord(StringRef type, StringRef name) {
55 return StringSwitch<std::string>(type)
56 .EndsWith("Decl *", "AddDeclRef(" + std::string(name) +
57 ", Record);\n")
58 .Case("QualType", "AddTypeRef(" + std::string(name) + ", Record);\n")
Sean Huntc85094f2011-02-17 03:30:09 +000059 .Case("Expr *", "AddStmt(" + std::string(name) + ");\n")
Douglas Gregor095a3f32011-03-23 01:05:46 +000060 .Case("IdentifierInfo *",
61 "AddIdentifierRef(" + std::string(name) + ", Record);\n")
Sean Hunt726a3d22010-08-18 23:23:09 +000062 .Default("Record.push_back(" + std::string(name) + ");\n");
63}
64
65namespace {
66 class Argument {
67 std::string lowerName, upperName;
68 StringRef attrName;
69
70 public:
71 Argument(Record &Arg, StringRef Attr)
72 : lowerName(Arg.getValueAsString("Name")), upperName(lowerName),
73 attrName(Attr) {
74 if (!lowerName.empty()) {
75 lowerName[0] = std::tolower(lowerName[0]);
76 upperName[0] = std::toupper(upperName[0]);
77 }
78 }
Chandler Carruth54f61632010-08-23 08:25:07 +000079 virtual ~Argument() {}
Sean Hunt726a3d22010-08-18 23:23:09 +000080
Sean Hunt5b385002010-08-19 00:03:05 +000081 StringRef getLowerName() const { return lowerName; }
82 StringRef getUpperName() const { return upperName; }
83 StringRef getAttrName() const { return attrName; }
Sean Hunt726a3d22010-08-18 23:23:09 +000084
85 // These functions print the argument contents formatted in different ways.
86 virtual void writeAccessors(raw_ostream &OS) const = 0;
87 virtual void writeAccessorDefinitions(raw_ostream &OS) const {}
88 virtual void writeCloneArgs(raw_ostream &OS) const = 0;
89 virtual void writeCtorBody(raw_ostream &OS) const {}
90 virtual void writeCtorInitializers(raw_ostream &OS) const = 0;
91 virtual void writeCtorParameters(raw_ostream &OS) const = 0;
92 virtual void writeDeclarations(raw_ostream &OS) const = 0;
93 virtual void writePCHReadArgs(raw_ostream &OS) const = 0;
94 virtual void writePCHReadDecls(raw_ostream &OS) const = 0;
95 virtual void writePCHWrite(raw_ostream &OS) const = 0;
96 };
97
98 class SimpleArgument : public Argument {
99 std::string type;
100
101 public:
102 SimpleArgument(Record &Arg, StringRef Attr, std::string T)
103 : Argument(Arg, Attr), type(T)
104 {}
105
Sean Hunt726a3d22010-08-18 23:23:09 +0000106 void writeAccessors(raw_ostream &OS) const {
107 OS << " " << type << " get" << getUpperName() << "() const {\n";
108 OS << " return " << getLowerName() << ";\n";
109 OS << " }";
110 }
111 void writeCloneArgs(raw_ostream &OS) const {
112 OS << getLowerName();
113 }
114 void writeCtorInitializers(raw_ostream &OS) const {
115 OS << getLowerName() << "(" << getUpperName() << ")";
116 }
117 void writeCtorParameters(raw_ostream &OS) const {
118 OS << type << " " << getUpperName();
119 }
120 void writeDeclarations(raw_ostream &OS) const {
121 OS << type << " " << getLowerName() << ";";
122 }
123 void writePCHReadDecls(raw_ostream &OS) const {
124 std::string read = ReadPCHRecord(type);
125 OS << " " << type << " " << getLowerName() << " = " << read << ";\n";
126 }
127 void writePCHReadArgs(raw_ostream &OS) const {
128 OS << getLowerName();
129 }
130 void writePCHWrite(raw_ostream &OS) const {
131 OS << " " << WritePCHRecord(type, "SA->get" +
132 std::string(getUpperName()) + "()");
133 }
134 };
135
136 class StringArgument : public Argument {
137 public:
138 StringArgument(Record &Arg, StringRef Attr)
139 : Argument(Arg, Attr)
140 {}
141
142 void writeAccessors(raw_ostream &OS) const {
143 OS << " llvm::StringRef get" << getUpperName() << "() const {\n";
144 OS << " return llvm::StringRef(" << getLowerName() << ", "
145 << getLowerName() << "Length);\n";
146 OS << " }\n";
147 OS << " unsigned get" << getUpperName() << "Length() const {\n";
148 OS << " return " << getLowerName() << "Length;\n";
149 OS << " }\n";
150 OS << " void set" << getUpperName()
151 << "(ASTContext &C, llvm::StringRef S) {\n";
152 OS << " " << getLowerName() << "Length = S.size();\n";
153 OS << " this->" << getLowerName() << " = new (C, 1) char ["
154 << getLowerName() << "Length];\n";
155 OS << " std::memcpy(this->" << getLowerName() << ", S.data(), "
156 << getLowerName() << "Length);\n";
157 OS << " }";
158 }
159 void writeCloneArgs(raw_ostream &OS) const {
160 OS << "get" << getUpperName() << "()";
161 }
162 void writeCtorBody(raw_ostream &OS) const {
163 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
164 << ".data(), " << getLowerName() << "Length);";
165 }
166 void writeCtorInitializers(raw_ostream &OS) const {
167 OS << getLowerName() << "Length(" << getUpperName() << ".size()),"
168 << getLowerName() << "(new (Ctx, 1) char[" << getLowerName()
169 << "Length])";
170 }
171 void writeCtorParameters(raw_ostream &OS) const {
172 OS << "llvm::StringRef " << getUpperName();
173 }
174 void writeDeclarations(raw_ostream &OS) const {
175 OS << "unsigned " << getLowerName() << "Length;\n";
176 OS << "char *" << getLowerName() << ";";
177 }
178 void writePCHReadDecls(raw_ostream &OS) const {
Jim Grosbachbb168242010-10-08 18:13:57 +0000179 OS << " std::string " << getLowerName()
180 << "= ReadString(Record, Idx);\n";
Sean Hunt726a3d22010-08-18 23:23:09 +0000181 }
182 void writePCHReadArgs(raw_ostream &OS) const {
183 OS << getLowerName();
184 }
185 void writePCHWrite(raw_ostream &OS) const {
186 OS << " AddString(SA->get" << getUpperName() << "(), Record);\n";
187 }
188 };
189
190 class AlignedArgument : public Argument {
191 public:
192 AlignedArgument(Record &Arg, StringRef Attr)
193 : Argument(Arg, Attr)
194 {}
195
196 void writeAccessors(raw_ostream &OS) const {
197 OS << " bool is" << getUpperName() << "Dependent() const;\n";
198
199 OS << " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n";
200
201 OS << " bool is" << getUpperName() << "Expr() const {\n";
202 OS << " return is" << getLowerName() << "Expr;\n";
203 OS << " }\n";
204
205 OS << " Expr *get" << getUpperName() << "Expr() const {\n";
206 OS << " assert(is" << getLowerName() << "Expr);\n";
207 OS << " return " << getLowerName() << "Expr;\n";
208 OS << " }\n";
209
210 OS << " TypeSourceInfo *get" << getUpperName() << "Type() const {\n";
211 OS << " assert(!is" << getLowerName() << "Expr);\n";
212 OS << " return " << getLowerName() << "Type;\n";
213 OS << " }";
214 }
215 void writeAccessorDefinitions(raw_ostream &OS) const {
216 OS << "bool " << getAttrName() << "Attr::is" << getUpperName()
217 << "Dependent() const {\n";
218 OS << " if (is" << getLowerName() << "Expr)\n";
219 OS << " return " << getLowerName() << "Expr && (" << getLowerName()
220 << "Expr->isValueDependent() || " << getLowerName()
221 << "Expr->isTypeDependent());\n";
222 OS << " else\n";
223 OS << " return " << getLowerName()
224 << "Type->getType()->isDependentType();\n";
225 OS << "}\n";
226
227 // FIXME: Do not do the calculation here
228 // FIXME: Handle types correctly
229 // A null pointer means maximum alignment
230 // FIXME: Load the platform-specific maximum alignment, rather than
231 // 16, the x86 max.
232 OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName()
233 << "(ASTContext &Ctx) const {\n";
234 OS << " assert(!is" << getUpperName() << "Dependent());\n";
235 OS << " if (is" << getLowerName() << "Expr)\n";
236 OS << " return (" << getLowerName() << "Expr ? " << getLowerName()
237 << "Expr->EvaluateAsInt(Ctx).getZExtValue() : 16)"
238 << "* Ctx.getCharWidth();\n";
239 OS << " else\n";
240 OS << " return 0; // FIXME\n";
241 OS << "}\n";
242 }
243 void writeCloneArgs(raw_ostream &OS) const {
244 OS << "is" << getLowerName() << "Expr, is" << getLowerName()
245 << "Expr ? static_cast<void*>(" << getLowerName()
246 << "Expr) : " << getLowerName()
247 << "Type";
248 }
249 void writeCtorBody(raw_ostream &OS) const {
250 OS << " if (is" << getLowerName() << "Expr)\n";
251 OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>("
252 << getUpperName() << ");\n";
253 OS << " else\n";
254 OS << " " << getLowerName()
255 << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName()
256 << ");";
257 }
258 void writeCtorInitializers(raw_ostream &OS) const {
259 OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)";
260 }
261 void writeCtorParameters(raw_ostream &OS) const {
262 OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName();
263 }
264 void writeDeclarations(raw_ostream &OS) const {
265 OS << "bool is" << getLowerName() << "Expr;\n";
266 OS << "union {\n";
267 OS << "Expr *" << getLowerName() << "Expr;\n";
268 OS << "TypeSourceInfo *" << getLowerName() << "Type;\n";
269 OS << "};";
270 }
271 void writePCHReadArgs(raw_ostream &OS) const {
272 OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr";
273 }
274 void writePCHReadDecls(raw_ostream &OS) const {
275 OS << " bool is" << getLowerName() << "Expr = Record[Idx++];\n";
276 OS << " void *" << getLowerName() << "Ptr;\n";
277 OS << " if (is" << getLowerName() << "Expr)\n";
Sebastian Redl2dc91642010-10-05 15:59:36 +0000278 OS << " " << getLowerName() << "Ptr = ReadExpr(F);\n";
Sean Hunt726a3d22010-08-18 23:23:09 +0000279 OS << " else\n";
280 OS << " " << getLowerName()
Sebastian Redl2dc91642010-10-05 15:59:36 +0000281 << "Ptr = GetTypeSourceInfo(F, Record, Idx);\n";
Sean Hunt726a3d22010-08-18 23:23:09 +0000282 }
283 void writePCHWrite(raw_ostream &OS) const {
284 OS << " Record.push_back(SA->is" << getUpperName() << "Expr());\n";
285 OS << " if (SA->is" << getUpperName() << "Expr())\n";
286 OS << " AddStmt(SA->get" << getUpperName() << "Expr());\n";
287 OS << " else\n";
288 OS << " AddTypeSourceInfo(SA->get" << getUpperName()
289 << "Type(), Record);\n";
290 }
291 };
292
293 class VariadicArgument : public Argument {
294 std::string type;
295
296 public:
297 VariadicArgument(Record &Arg, StringRef Attr, std::string T)
298 : Argument(Arg, Attr), type(T)
299 {}
300
301 std::string getType() const { return type; }
302
303 void writeAccessors(raw_ostream &OS) const {
304 OS << " typedef " << type << "* " << getLowerName() << "_iterator;\n";
305 OS << " " << getLowerName() << "_iterator " << getLowerName()
306 << "_begin() const {\n";
307 OS << " return " << getLowerName() << ";\n";
308 OS << " }\n";
309 OS << " " << getLowerName() << "_iterator " << getLowerName()
310 << "_end() const {\n";
311 OS << " return " << getLowerName() << " + " << getLowerName()
312 << "Size;\n";
313 OS << " }\n";
314 OS << " unsigned " << getLowerName() << "_size() const {\n"
315 << " return " << getLowerName() << "Size;\n;";
316 OS << " }";
317 }
318 void writeCloneArgs(raw_ostream &OS) const {
319 OS << getLowerName() << ", " << getLowerName() << "Size";
320 }
321 void writeCtorBody(raw_ostream &OS) const {
322 // FIXME: memcpy is not safe on non-trivial types.
323 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
324 << ", " << getLowerName() << "Size * sizeof(" << getType() << "));\n";
325 }
326 void writeCtorInitializers(raw_ostream &OS) const {
327 OS << getLowerName() << "Size(" << getUpperName() << "Size), "
328 << getLowerName() << "(new (Ctx, 16) " << getType() << "["
329 << getLowerName() << "Size])";
330 }
331 void writeCtorParameters(raw_ostream &OS) const {
332 OS << getType() << " *" << getUpperName() << ", unsigned "
333 << getUpperName() << "Size";
334 }
335 void writeDeclarations(raw_ostream &OS) const {
336 OS << " unsigned " << getLowerName() << "Size;\n";
337 OS << " " << getType() << " *" << getLowerName() << ";";
338 }
339 void writePCHReadDecls(raw_ostream &OS) const {
340 OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
341 OS << " llvm::SmallVector<" << type << ", 4> " << getLowerName()
342 << ";\n";
343 OS << " " << getLowerName() << ".reserve(" << getLowerName()
344 << "Size);\n";
345 OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
346
347 std::string read = ReadPCHRecord(type);
348 OS << " " << getLowerName() << ".push_back(" << read << ");\n";
349 }
350 void writePCHReadArgs(raw_ostream &OS) const {
351 OS << getLowerName() << ".data(), " << getLowerName() << "Size";
352 }
353 void writePCHWrite(raw_ostream &OS) const{
354 OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";
355 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
356 << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
357 << getLowerName() << "_end(); i != e; ++i)\n";
358 OS << " " << WritePCHRecord(type, "(*i)");
359 }
360 };
361
362 class EnumArgument : public Argument {
Eli Friedmana8fa3922010-08-19 06:11:05 +0000363 std::string type;
Sean Hunt726a3d22010-08-18 23:23:09 +0000364 std::vector<StringRef> values, enums;
365 public:
366 EnumArgument(Record &Arg, StringRef Attr)
367 : Argument(Arg, Attr), type(Arg.getValueAsString("Type")),
368 values(getValueAsListOfStrings(Arg, "Values")),
369 enums(getValueAsListOfStrings(Arg, "Enums"))
370 {}
371
372 void writeAccessors(raw_ostream &OS) const {
373 OS << " " << type << " get" << getUpperName() << "() const {\n";
374 OS << " return " << getLowerName() << ";\n";
375 OS << " }";
376 }
377 void writeCloneArgs(raw_ostream &OS) const {
378 OS << getLowerName();
379 }
380 void writeCtorInitializers(raw_ostream &OS) const {
381 OS << getLowerName() << "(" << getUpperName() << ")";
382 }
383 void writeCtorParameters(raw_ostream &OS) const {
384 OS << type << " " << getUpperName();
385 }
386 void writeDeclarations(raw_ostream &OS) const {
387 // Calculate the various enum values
388 std::vector<StringRef> uniques(enums);
389 std::sort(uniques.begin(), uniques.end());
390 uniques.erase(std::unique(uniques.begin(), uniques.end()),
391 uniques.end());
392 // FIXME: Emit a proper error
393 assert(!uniques.empty());
394
395 std::vector<StringRef>::iterator i = uniques.begin(),
396 e = uniques.end();
397 // The last one needs to not have a comma.
398 --e;
399
400 OS << "public:\n";
401 OS << " enum " << type << " {\n";
402 for (; i != e; ++i)
403 OS << " " << *i << ",\n";
404 OS << " " << *e << "\n";
405 OS << " };\n";
406 OS << "private:\n";
407 OS << " " << type << " " << getLowerName() << ";";
408 }
409 void writePCHReadDecls(raw_ostream &OS) const {
410 OS << " " << getAttrName() << "Attr::" << type << " " << getLowerName()
411 << "(static_cast<" << getAttrName() << "Attr::" << type
412 << ">(Record[Idx++]));\n";
413 }
414 void writePCHReadArgs(raw_ostream &OS) const {
415 OS << getLowerName();
416 }
417 void writePCHWrite(raw_ostream &OS) const {
418 OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
419 }
420 };
Douglas Gregor095a3f32011-03-23 01:05:46 +0000421
422 class VersionArgument : public Argument {
423 public:
424 VersionArgument(Record &Arg, StringRef Attr)
425 : Argument(Arg, Attr)
426 {}
427
428 void writeAccessors(raw_ostream &OS) const {
429 OS << " VersionTuple get" << getUpperName() << "() const {\n";
430 OS << " return " << getLowerName() << ";\n";
431 OS << " }\n";
432 OS << " void set" << getUpperName()
433 << "(ASTContext &C, VersionTuple V) {\n";
434 OS << " " << getLowerName() << " = V;\n";
435 OS << " }";
436 }
437 void writeCloneArgs(raw_ostream &OS) const {
438 OS << "get" << getUpperName() << "()";
439 }
440 void writeCtorBody(raw_ostream &OS) const {
441 }
442 void writeCtorInitializers(raw_ostream &OS) const {
443 OS << getLowerName() << "(" << getUpperName() << ")";
444 }
445 void writeCtorParameters(raw_ostream &OS) const {
446 OS << "VersionTuple " << getUpperName();
447 }
448 void writeDeclarations(raw_ostream &OS) const {
449 OS << "VersionTuple " << getLowerName() << ";\n";
450 }
451 void writePCHReadDecls(raw_ostream &OS) const {
452 OS << " VersionTuple " << getLowerName()
453 << "= ReadVersionTuple(Record, Idx);\n";
454 }
455 void writePCHReadArgs(raw_ostream &OS) const {
456 OS << getLowerName();
457 }
458 void writePCHWrite(raw_ostream &OS) const {
459 OS << " AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n";
460 }
461 };
Sean Hunt726a3d22010-08-18 23:23:09 +0000462}
463
464static Argument *createArgument(Record &Arg, StringRef Attr,
465 Record *Search = 0) {
466 if (!Search)
467 Search = &Arg;
468
469 Argument *Ptr = 0;
470 llvm::StringRef ArgName = Search->getName();
471
472 if (ArgName == "AlignedArgument") Ptr = new AlignedArgument(Arg, Attr);
473 else if (ArgName == "EnumArgument") Ptr = new EnumArgument(Arg, Attr);
474 else if (ArgName == "ExprArgument") Ptr = new SimpleArgument(Arg, Attr,
475 "Expr *");
476 else if (ArgName == "FunctionArgument")
477 Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *");
478 else if (ArgName == "IdentifierArgument")
479 Ptr = new SimpleArgument(Arg, Attr, "IdentifierInfo *");
Douglas Gregor32ce3f92011-03-26 03:40:01 +0000480 else if (ArgName == "BoolArgument") Ptr = new SimpleArgument(Arg, Attr,
481 "bool");
Sean Hunt726a3d22010-08-18 23:23:09 +0000482 else if (ArgName == "IntArgument") Ptr = new SimpleArgument(Arg, Attr, "int");
483 else if (ArgName == "StringArgument") Ptr = new StringArgument(Arg, Attr);
484 else if (ArgName == "TypeArgument")
485 Ptr = new SimpleArgument(Arg, Attr, "QualType");
486 else if (ArgName == "UnsignedArgument")
487 Ptr = new SimpleArgument(Arg, Attr, "unsigned");
488 else if (ArgName == "VariadicUnsignedArgument")
489 Ptr = new VariadicArgument(Arg, Attr, "unsigned");
Douglas Gregor095a3f32011-03-23 01:05:46 +0000490 else if (ArgName == "VersionArgument")
491 Ptr = new VersionArgument(Arg, Attr);
Sean Hunt726a3d22010-08-18 23:23:09 +0000492
493 if (!Ptr) {
494 std::vector<Record*> Bases = Search->getSuperClasses();
495 for (std::vector<Record*>::iterator i = Bases.begin(), e = Bases.end();
496 i != e; ++i) {
497 Ptr = createArgument(Arg, Attr, *i);
498 if (Ptr)
499 break;
500 }
501 }
502 return Ptr;
503}
504
Sean Hunt16171442010-06-16 23:45:50 +0000505void ClangAttrClassEmitter::run(raw_ostream &OS) {
506 OS << "// This file is generated by TableGen. Do not edit.\n\n";
507 OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
508 OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
509
510 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
511
512 for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
513 i != e; ++i) {
514 Record &R = **i;
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000515 const std::string &SuperName = R.getSuperClasses().back()->getName();
Sean Hunt16171442010-06-16 23:45:50 +0000516
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000517 OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n";
Sean Hunt16171442010-06-16 23:45:50 +0000518
Sean Hunt726a3d22010-08-18 23:23:09 +0000519 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
520 std::vector<Argument*> Args;
521 std::vector<Argument*>::iterator ai, ae;
522 Args.reserve(ArgRecords.size());
Sean Hunt16171442010-06-16 23:45:50 +0000523
Sean Hunt726a3d22010-08-18 23:23:09 +0000524 for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
525 re = ArgRecords.end();
526 ri != re; ++ri) {
527 Record &ArgRecord = **ri;
528 Argument *Arg = createArgument(ArgRecord, R.getName());
529 assert(Arg);
530 Args.push_back(Arg);
531
532 Arg->writeDeclarations(OS);
533 OS << "\n\n";
534 }
535
536 ae = Args.end();
Sean Hunt16171442010-06-16 23:45:50 +0000537
538 OS << "\n public:\n";
Sean Hunt726a3d22010-08-18 23:23:09 +0000539 OS << " " << R.getName() << "Attr(SourceLocation L, ASTContext &Ctx\n";
Sean Hunt16171442010-06-16 23:45:50 +0000540
Sean Hunt726a3d22010-08-18 23:23:09 +0000541 for (ai = Args.begin(); ai != ae; ++ai) {
542 OS << " , ";
543 (*ai)->writeCtorParameters(OS);
544 OS << "\n";
545 }
Sean Hunt16171442010-06-16 23:45:50 +0000546
Sean Hunt726a3d22010-08-18 23:23:09 +0000547 OS << " )\n";
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000548 OS << " : " << SuperName << "(attr::" << R.getName() << ", L)\n";
Sean Hunt16171442010-06-16 23:45:50 +0000549
Sean Hunt726a3d22010-08-18 23:23:09 +0000550 for (ai = Args.begin(); ai != ae; ++ai) {
551 OS << " , ";
552 (*ai)->writeCtorInitializers(OS);
553 OS << "\n";
554 }
Sean Hunt16171442010-06-16 23:45:50 +0000555
Sean Hunt726a3d22010-08-18 23:23:09 +0000556 OS << " {\n";
557
558 for (ai = Args.begin(); ai != ae; ++ai) {
559 (*ai)->writeCtorBody(OS);
560 OS << "\n";
561 }
562 OS << " }\n\n";
563
564 OS << " virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n";
565
566 for (ai = Args.begin(); ai != ae; ++ai) {
567 (*ai)->writeAccessors(OS);
568 OS << "\n\n";
569 }
570
571 OS << R.getValueAsCode("AdditionalMembers");
572 OS << "\n\n";
573
Sean Hunt16171442010-06-16 23:45:50 +0000574 OS << " static bool classof(const Attr *A) { return A->getKind() == "
575 << "attr::" << R.getName() << "; }\n";
576 OS << " static bool classof(const " << R.getName()
577 << "Attr *) { return true; }\n";
578 OS << "};\n\n";
579 }
580
581 OS << "#endif\n";
582}
583
Sean Hunt726a3d22010-08-18 23:23:09 +0000584void ClangAttrImplEmitter::run(raw_ostream &OS) {
585 OS << "// This file is generated by TableGen. Do not edit.\n\n";
586
587 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
588 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ri, re;
589 std::vector<Argument*>::iterator ai, ae;
590
591 for (; i != e; ++i) {
592 Record &R = **i;
593 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
594 std::vector<Argument*> Args;
595 for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri)
596 Args.push_back(createArgument(**ri, R.getName()));
597
598 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
599 (*ai)->writeAccessorDefinitions(OS);
600
601 OS << R.getName() << "Attr *" << R.getName()
602 << "Attr::clone(ASTContext &C) const {\n";
603 OS << " return new (C) " << R.getName() << "Attr(getLocation(), C";
604 for (ai = Args.begin(); ai != ae; ++ai) {
605 OS << ", ";
606 (*ai)->writeCloneArgs(OS);
607 }
608 OS << ");\n}\n\n";
609 }
610}
611
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000612static void EmitAttrList(raw_ostream &OS, StringRef Class,
613 const std::vector<Record*> &AttrList) {
614 std::vector<Record*>::const_iterator i = AttrList.begin(), e = AttrList.end();
615
616 if (i != e) {
617 // Move the end iterator back to emit the last attribute.
618 for(--e; i != e; ++i)
619 OS << Class << "(" << (*i)->getName() << ")\n";
620
621 OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n";
622 }
623}
624
Sean Hunt16171442010-06-16 23:45:50 +0000625void ClangAttrListEmitter::run(raw_ostream &OS) {
626 OS << "// This file is generated by TableGen. Do not edit.\n\n";
627
628 OS << "#ifndef LAST_ATTR\n";
629 OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n";
630 OS << "#endif\n\n";
Sean Hunt16171442010-06-16 23:45:50 +0000631
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000632 OS << "#ifndef INHERITABLE_ATTR\n";
633 OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n";
634 OS << "#endif\n\n";
635
636 OS << "#ifndef LAST_INHERITABLE_ATTR\n";
637 OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n";
638 OS << "#endif\n\n";
639
John McCall9977e522011-03-02 04:00:52 +0000640 OS << "#ifndef INHERITABLE_PARAM_ATTR\n";
641 OS << "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n";
642 OS << "#endif\n\n";
643
644 OS << "#ifndef LAST_INHERITABLE_PARAM_ATTR\n";
645 OS << "#define LAST_INHERITABLE_PARAM_ATTR(NAME)"
646 " INHERITABLE_PARAM_ATTR(NAME)\n";
647 OS << "#endif\n\n";
648
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000649 Record *InhClass = Records.getClass("InheritableAttr");
John McCall9977e522011-03-02 04:00:52 +0000650 Record *InhParamClass = Records.getClass("InheritableParamAttr");
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000651 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
John McCall9977e522011-03-02 04:00:52 +0000652 NonInhAttrs, InhAttrs, InhParamAttrs;
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000653 for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
654 i != e; ++i) {
John McCall9977e522011-03-02 04:00:52 +0000655 if ((*i)->isSubClassOf(InhParamClass))
656 InhParamAttrs.push_back(*i);
657 else if ((*i)->isSubClassOf(InhClass))
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000658 InhAttrs.push_back(*i);
659 else
660 NonInhAttrs.push_back(*i);
Sean Hunt16171442010-06-16 23:45:50 +0000661 }
662
John McCall9977e522011-03-02 04:00:52 +0000663 EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs);
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000664 EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs);
665 EmitAttrList(OS, "ATTR", NonInhAttrs);
666
Sean Hunt16171442010-06-16 23:45:50 +0000667 OS << "#undef LAST_ATTR\n";
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000668 OS << "#undef INHERITABLE_ATTR\n";
669 OS << "#undef LAST_INHERITABLE_ATTR\n";
John McCall9977e522011-03-02 04:00:52 +0000670 OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n";
Sean Hunt16171442010-06-16 23:45:50 +0000671 OS << "#undef ATTR\n";
672}
Sean Hunt726a3d22010-08-18 23:23:09 +0000673
674void ClangAttrPCHReadEmitter::run(raw_ostream &OS) {
Francois Pichet8ec055d2010-10-01 21:20:39 +0000675 OS << "// This file is generated by TableGen. Do not edit.\n\n";
Sean Hunt726a3d22010-08-18 23:23:09 +0000676
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000677 Record *InhClass = Records.getClass("InheritableAttr");
Sean Hunt726a3d22010-08-18 23:23:09 +0000678 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
679 ArgRecords;
680 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
681 std::vector<Argument*> Args;
682 std::vector<Argument*>::iterator ri, re;
683
684 OS << " switch (Kind) {\n";
685 OS << " default:\n";
686 OS << " assert(0 && \"Unknown attribute!\");\n";
687 OS << " break;\n";
688 for (; i != e; ++i) {
689 Record &R = **i;
690 OS << " case attr::" << R.getName() << ": {\n";
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000691 if (R.isSubClassOf(InhClass))
692 OS << " bool isInherited = Record[Idx++];\n";
Sean Hunt726a3d22010-08-18 23:23:09 +0000693 ArgRecords = R.getValueAsListOfDefs("Args");
694 Args.clear();
695 for (ai = ArgRecords.begin(), ae = ArgRecords.end(); ai != ae; ++ai) {
696 Argument *A = createArgument(**ai, R.getName());
697 Args.push_back(A);
698 A->writePCHReadDecls(OS);
699 }
700 OS << " New = new (*Context) " << R.getName() << "Attr(Loc, *Context";
701 for (ri = Args.begin(), re = Args.end(); ri != re; ++ri) {
702 OS << ", ";
703 (*ri)->writePCHReadArgs(OS);
704 }
705 OS << ");\n";
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000706 if (R.isSubClassOf(InhClass))
707 OS << " cast<InheritableAttr>(New)->setInherited(isInherited);\n";
Sean Hunt726a3d22010-08-18 23:23:09 +0000708 OS << " break;\n";
709 OS << " }\n";
710 }
711 OS << " }\n";
712}
713
714void ClangAttrPCHWriteEmitter::run(raw_ostream &OS) {
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000715 Record *InhClass = Records.getClass("InheritableAttr");
Sean Hunt726a3d22010-08-18 23:23:09 +0000716 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
717 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
718
719 OS << " switch (A->getKind()) {\n";
720 OS << " default:\n";
721 OS << " llvm_unreachable(\"Unknown attribute kind!\");\n";
722 OS << " break;\n";
723 for (; i != e; ++i) {
724 Record &R = **i;
725 OS << " case attr::" << R.getName() << ": {\n";
726 Args = R.getValueAsListOfDefs("Args");
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000727 if (R.isSubClassOf(InhClass) || !Args.empty())
Sean Hunt726a3d22010-08-18 23:23:09 +0000728 OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
729 << "Attr>(A);\n";
Peter Collingbournebe111ef2011-01-21 02:08:26 +0000730 if (R.isSubClassOf(InhClass))
731 OS << " Record.push_back(SA->isInherited());\n";
Sean Hunt726a3d22010-08-18 23:23:09 +0000732 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
733 createArgument(**ai, R.getName())->writePCHWrite(OS);
734 OS << " break;\n";
735 OS << " }\n";
736 }
737 OS << " }\n";
738}
Anders Carlsson238777e2010-10-20 01:21:53 +0000739
740void ClangAttrSpellingListEmitter::run(raw_ostream &OS) {
741 OS << "// This file is generated by TableGen. Do not edit.\n\n";
742
743 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
744
745 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) {
746 Record &Attr = **I;
747
748 std::vector<StringRef> Spellings = getValueAsListOfStrings(Attr, "Spellings");
749
750 for (std::vector<StringRef>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) {
751 StringRef Spelling = *I;
752 OS << ".Case(\"" << Spelling << "\", true)\n";
753 }
754 }
755
756}