blob: dc58b2752ce12bcbd09e490015ae5c55aa50c865 [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
Sean Hunt93f95f22012-06-18 16:13:52 +000014#include "llvm/ADT/SmallString.h"
Peter Collingbourne51d77772011-10-06 13:03:08 +000015#include "llvm/ADT/StringSwitch.h"
16#include "llvm/TableGen/Record.h"
Douglas Gregor0c19b3c2012-05-02 17:33:51 +000017#include "llvm/TableGen/StringMatcher.h"
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +000018#include "llvm/TableGen/TableGenBackend.h"
Peter Collingbourne51d77772011-10-06 13:03:08 +000019#include <algorithm>
20#include <cctype>
Michael Hane53ac8a2012-03-07 00:12:16 +000021#include <set>
Peter Collingbourne51d77772011-10-06 13:03:08 +000022
23using namespace llvm;
24
25static const std::vector<StringRef>
26getValueAsListOfStrings(Record &R, StringRef FieldName) {
27 ListInit *List = R.getValueAsListInit(FieldName);
28 assert (List && "Got a null ListInit");
29
30 std::vector<StringRef> Strings;
31 Strings.reserve(List->getSize());
32
33 for (ListInit::const_iterator i = List->begin(), e = List->end();
34 i != e;
35 ++i) {
36 assert(*i && "Got a null element in a ListInit");
37 if (StringInit *S = dynamic_cast<StringInit *>(*i))
38 Strings.push_back(S->getValue());
Peter Collingbourne51d77772011-10-06 13:03:08 +000039 else
40 assert(false && "Got a non-string, non-code element in a ListInit");
41 }
42
43 return Strings;
44}
45
46static std::string ReadPCHRecord(StringRef type) {
47 return StringSwitch<std::string>(type)
48 .EndsWith("Decl *", "GetLocalDeclAs<"
49 + std::string(type, 0, type.size()-1) + ">(F, Record[Idx++])")
50 .Case("QualType", "getLocalType(F, Record[Idx++])")
51 .Case("Expr *", "ReadSubExpr()")
52 .Case("IdentifierInfo *", "GetIdentifierInfo(F, Record, Idx)")
53 .Case("SourceLocation", "ReadSourceLocation(F, Record, Idx)")
54 .Default("Record[Idx++]");
55}
56
57// Assumes that the way to get the value is SA->getname()
58static std::string WritePCHRecord(StringRef type, StringRef name) {
59 return StringSwitch<std::string>(type)
60 .EndsWith("Decl *", "AddDeclRef(" + std::string(name) +
61 ", Record);\n")
62 .Case("QualType", "AddTypeRef(" + std::string(name) + ", Record);\n")
63 .Case("Expr *", "AddStmt(" + std::string(name) + ");\n")
64 .Case("IdentifierInfo *",
65 "AddIdentifierRef(" + std::string(name) + ", Record);\n")
66 .Case("SourceLocation",
67 "AddSourceLocation(" + std::string(name) + ", Record);\n")
68 .Default("Record.push_back(" + std::string(name) + ");\n");
69}
70
Michael Hane53ac8a2012-03-07 00:12:16 +000071// Normalize attribute name by removing leading and trailing
72// underscores. For example, __foo, foo__, __foo__ would
73// become foo.
74static StringRef NormalizeAttrName(StringRef AttrName) {
75 if (AttrName.startswith("__"))
76 AttrName = AttrName.substr(2, AttrName.size());
77
78 if (AttrName.endswith("__"))
79 AttrName = AttrName.substr(0, AttrName.size() - 2);
80
81 return AttrName;
82}
83
84// Normalize attribute spelling only if the spelling has both leading
85// and trailing underscores. For example, __ms_struct__ will be
86// normalized to "ms_struct"; __cdecl will remain intact.
87static StringRef NormalizeAttrSpelling(StringRef AttrSpelling) {
88 if (AttrSpelling.startswith("__") && AttrSpelling.endswith("__")) {
89 AttrSpelling = AttrSpelling.substr(2, AttrSpelling.size() - 4);
90 }
91
92 return AttrSpelling;
93}
94
Peter Collingbourne51d77772011-10-06 13:03:08 +000095namespace {
96 class Argument {
97 std::string lowerName, upperName;
98 StringRef attrName;
99
100 public:
101 Argument(Record &Arg, StringRef Attr)
102 : lowerName(Arg.getValueAsString("Name")), upperName(lowerName),
103 attrName(Attr) {
104 if (!lowerName.empty()) {
105 lowerName[0] = std::tolower(lowerName[0]);
106 upperName[0] = std::toupper(upperName[0]);
107 }
108 }
109 virtual ~Argument() {}
110
111 StringRef getLowerName() const { return lowerName; }
112 StringRef getUpperName() const { return upperName; }
113 StringRef getAttrName() const { return attrName; }
114
115 // These functions print the argument contents formatted in different ways.
116 virtual void writeAccessors(raw_ostream &OS) const = 0;
117 virtual void writeAccessorDefinitions(raw_ostream &OS) const {}
118 virtual void writeCloneArgs(raw_ostream &OS) const = 0;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000119 virtual void writeTemplateInstantiationArgs(raw_ostream &OS) const = 0;
Daniel Dunbarb8806092012-02-10 06:00:29 +0000120 virtual void writeTemplateInstantiation(raw_ostream &OS) const {}
Peter Collingbourne51d77772011-10-06 13:03:08 +0000121 virtual void writeCtorBody(raw_ostream &OS) const {}
122 virtual void writeCtorInitializers(raw_ostream &OS) const = 0;
123 virtual void writeCtorParameters(raw_ostream &OS) const = 0;
124 virtual void writeDeclarations(raw_ostream &OS) const = 0;
125 virtual void writePCHReadArgs(raw_ostream &OS) const = 0;
126 virtual void writePCHReadDecls(raw_ostream &OS) const = 0;
127 virtual void writePCHWrite(raw_ostream &OS) const = 0;
Douglas Gregor1bea8802011-11-19 19:22:57 +0000128 virtual void writeValue(raw_ostream &OS) const = 0;
Peter Collingbourne51d77772011-10-06 13:03:08 +0000129 };
130
131 class SimpleArgument : public Argument {
132 std::string type;
133
134 public:
135 SimpleArgument(Record &Arg, StringRef Attr, std::string T)
136 : Argument(Arg, Attr), type(T)
137 {}
138
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000139 std::string getType() const { return type; }
140
Peter Collingbourne51d77772011-10-06 13:03:08 +0000141 void writeAccessors(raw_ostream &OS) const {
142 OS << " " << type << " get" << getUpperName() << "() const {\n";
143 OS << " return " << getLowerName() << ";\n";
144 OS << " }";
145 }
146 void writeCloneArgs(raw_ostream &OS) const {
147 OS << getLowerName();
148 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000149 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
150 OS << "A->get" << getUpperName() << "()";
151 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000152 void writeCtorInitializers(raw_ostream &OS) const {
153 OS << getLowerName() << "(" << getUpperName() << ")";
154 }
155 void writeCtorParameters(raw_ostream &OS) const {
156 OS << type << " " << getUpperName();
157 }
158 void writeDeclarations(raw_ostream &OS) const {
159 OS << type << " " << getLowerName() << ";";
160 }
161 void writePCHReadDecls(raw_ostream &OS) const {
162 std::string read = ReadPCHRecord(type);
163 OS << " " << type << " " << getLowerName() << " = " << read << ";\n";
164 }
165 void writePCHReadArgs(raw_ostream &OS) const {
166 OS << getLowerName();
167 }
168 void writePCHWrite(raw_ostream &OS) const {
169 OS << " " << WritePCHRecord(type, "SA->get" +
170 std::string(getUpperName()) + "()");
171 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000172 void writeValue(raw_ostream &OS) const {
173 if (type == "FunctionDecl *") {
174 OS << "\" << get" << getUpperName() << "()->getNameInfo().getAsString() << \"";
175 } else if (type == "IdentifierInfo *") {
176 OS << "\" << get" << getUpperName() << "()->getName() << \"";
177 } else if (type == "QualType") {
178 OS << "\" << get" << getUpperName() << "().getAsString() << \"";
179 } else if (type == "SourceLocation") {
180 OS << "\" << get" << getUpperName() << "().getRawEncoding() << \"";
181 } else {
182 OS << "\" << get" << getUpperName() << "() << \"";
183 }
184 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000185 };
186
187 class StringArgument : public Argument {
188 public:
189 StringArgument(Record &Arg, StringRef Attr)
190 : Argument(Arg, Attr)
191 {}
192
193 void writeAccessors(raw_ostream &OS) const {
194 OS << " llvm::StringRef get" << getUpperName() << "() const {\n";
195 OS << " return llvm::StringRef(" << getLowerName() << ", "
196 << getLowerName() << "Length);\n";
197 OS << " }\n";
198 OS << " unsigned get" << getUpperName() << "Length() const {\n";
199 OS << " return " << getLowerName() << "Length;\n";
200 OS << " }\n";
201 OS << " void set" << getUpperName()
202 << "(ASTContext &C, llvm::StringRef S) {\n";
203 OS << " " << getLowerName() << "Length = S.size();\n";
204 OS << " this->" << getLowerName() << " = new (C, 1) char ["
205 << getLowerName() << "Length];\n";
206 OS << " std::memcpy(this->" << getLowerName() << ", S.data(), "
207 << getLowerName() << "Length);\n";
208 OS << " }";
209 }
210 void writeCloneArgs(raw_ostream &OS) const {
211 OS << "get" << getUpperName() << "()";
212 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000213 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
214 OS << "A->get" << getUpperName() << "()";
215 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000216 void writeCtorBody(raw_ostream &OS) const {
217 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
218 << ".data(), " << getLowerName() << "Length);";
219 }
220 void writeCtorInitializers(raw_ostream &OS) const {
221 OS << getLowerName() << "Length(" << getUpperName() << ".size()),"
222 << getLowerName() << "(new (Ctx, 1) char[" << getLowerName()
223 << "Length])";
224 }
225 void writeCtorParameters(raw_ostream &OS) const {
226 OS << "llvm::StringRef " << getUpperName();
227 }
228 void writeDeclarations(raw_ostream &OS) const {
229 OS << "unsigned " << getLowerName() << "Length;\n";
230 OS << "char *" << getLowerName() << ";";
231 }
232 void writePCHReadDecls(raw_ostream &OS) const {
233 OS << " std::string " << getLowerName()
234 << "= ReadString(Record, Idx);\n";
235 }
236 void writePCHReadArgs(raw_ostream &OS) const {
237 OS << getLowerName();
238 }
239 void writePCHWrite(raw_ostream &OS) const {
240 OS << " AddString(SA->get" << getUpperName() << "(), Record);\n";
241 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000242 void writeValue(raw_ostream &OS) const {
243 OS << "\\\"\" << get" << getUpperName() << "() << \"\\\"";
244 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000245 };
246
247 class AlignedArgument : public Argument {
248 public:
249 AlignedArgument(Record &Arg, StringRef Attr)
250 : Argument(Arg, Attr)
251 {}
252
253 void writeAccessors(raw_ostream &OS) const {
254 OS << " bool is" << getUpperName() << "Dependent() const;\n";
255
256 OS << " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n";
257
258 OS << " bool is" << getUpperName() << "Expr() const {\n";
259 OS << " return is" << getLowerName() << "Expr;\n";
260 OS << " }\n";
261
262 OS << " Expr *get" << getUpperName() << "Expr() const {\n";
263 OS << " assert(is" << getLowerName() << "Expr);\n";
264 OS << " return " << getLowerName() << "Expr;\n";
265 OS << " }\n";
266
267 OS << " TypeSourceInfo *get" << getUpperName() << "Type() const {\n";
268 OS << " assert(!is" << getLowerName() << "Expr);\n";
269 OS << " return " << getLowerName() << "Type;\n";
270 OS << " }";
271 }
272 void writeAccessorDefinitions(raw_ostream &OS) const {
273 OS << "bool " << getAttrName() << "Attr::is" << getUpperName()
274 << "Dependent() const {\n";
275 OS << " if (is" << getLowerName() << "Expr)\n";
276 OS << " return " << getLowerName() << "Expr && (" << getLowerName()
277 << "Expr->isValueDependent() || " << getLowerName()
278 << "Expr->isTypeDependent());\n";
279 OS << " else\n";
280 OS << " return " << getLowerName()
281 << "Type->getType()->isDependentType();\n";
282 OS << "}\n";
283
284 // FIXME: Do not do the calculation here
285 // FIXME: Handle types correctly
286 // A null pointer means maximum alignment
287 // FIXME: Load the platform-specific maximum alignment, rather than
288 // 16, the x86 max.
289 OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName()
290 << "(ASTContext &Ctx) const {\n";
291 OS << " assert(!is" << getUpperName() << "Dependent());\n";
292 OS << " if (is" << getLowerName() << "Expr)\n";
293 OS << " return (" << getLowerName() << "Expr ? " << getLowerName()
Richard Smitha6b8b2c2011-10-10 18:28:20 +0000294 << "Expr->EvaluateKnownConstInt(Ctx).getZExtValue() : 16)"
Peter Collingbourne51d77772011-10-06 13:03:08 +0000295 << "* Ctx.getCharWidth();\n";
296 OS << " else\n";
297 OS << " return 0; // FIXME\n";
298 OS << "}\n";
299 }
300 void writeCloneArgs(raw_ostream &OS) const {
301 OS << "is" << getLowerName() << "Expr, is" << getLowerName()
302 << "Expr ? static_cast<void*>(" << getLowerName()
303 << "Expr) : " << getLowerName()
304 << "Type";
305 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000306 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
307 // FIXME: move the definition in Sema::InstantiateAttrs to here.
308 // In the meantime, aligned attributes are cloned.
309 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000310 void writeCtorBody(raw_ostream &OS) const {
311 OS << " if (is" << getLowerName() << "Expr)\n";
312 OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>("
313 << getUpperName() << ");\n";
314 OS << " else\n";
315 OS << " " << getLowerName()
316 << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName()
317 << ");";
318 }
319 void writeCtorInitializers(raw_ostream &OS) const {
320 OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)";
321 }
322 void writeCtorParameters(raw_ostream &OS) const {
323 OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName();
324 }
325 void writeDeclarations(raw_ostream &OS) const {
326 OS << "bool is" << getLowerName() << "Expr;\n";
327 OS << "union {\n";
328 OS << "Expr *" << getLowerName() << "Expr;\n";
329 OS << "TypeSourceInfo *" << getLowerName() << "Type;\n";
330 OS << "};";
331 }
332 void writePCHReadArgs(raw_ostream &OS) const {
333 OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr";
334 }
335 void writePCHReadDecls(raw_ostream &OS) const {
336 OS << " bool is" << getLowerName() << "Expr = Record[Idx++];\n";
337 OS << " void *" << getLowerName() << "Ptr;\n";
338 OS << " if (is" << getLowerName() << "Expr)\n";
339 OS << " " << getLowerName() << "Ptr = ReadExpr(F);\n";
340 OS << " else\n";
341 OS << " " << getLowerName()
342 << "Ptr = GetTypeSourceInfo(F, Record, Idx);\n";
343 }
344 void writePCHWrite(raw_ostream &OS) const {
345 OS << " Record.push_back(SA->is" << getUpperName() << "Expr());\n";
346 OS << " if (SA->is" << getUpperName() << "Expr())\n";
347 OS << " AddStmt(SA->get" << getUpperName() << "Expr());\n";
348 OS << " else\n";
349 OS << " AddTypeSourceInfo(SA->get" << getUpperName()
350 << "Type(), Record);\n";
351 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000352 void writeValue(raw_ostream &OS) const {
353 OS << "\" << get" << getUpperName() << "(Ctx) << \"";
354 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000355 };
356
357 class VariadicArgument : public Argument {
358 std::string type;
359
360 public:
361 VariadicArgument(Record &Arg, StringRef Attr, std::string T)
362 : Argument(Arg, Attr), type(T)
363 {}
364
365 std::string getType() const { return type; }
366
367 void writeAccessors(raw_ostream &OS) const {
368 OS << " typedef " << type << "* " << getLowerName() << "_iterator;\n";
369 OS << " " << getLowerName() << "_iterator " << getLowerName()
370 << "_begin() const {\n";
371 OS << " return " << getLowerName() << ";\n";
372 OS << " }\n";
373 OS << " " << getLowerName() << "_iterator " << getLowerName()
374 << "_end() const {\n";
375 OS << " return " << getLowerName() << " + " << getLowerName()
376 << "Size;\n";
377 OS << " }\n";
378 OS << " unsigned " << getLowerName() << "_size() const {\n"
DeLesley Hutchins23323e02012-01-20 22:50:54 +0000379 << " return " << getLowerName() << "Size;\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000380 OS << " }";
381 }
382 void writeCloneArgs(raw_ostream &OS) const {
383 OS << getLowerName() << ", " << getLowerName() << "Size";
384 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000385 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
386 // This isn't elegant, but we have to go through public methods...
387 OS << "A->" << getLowerName() << "_begin(), "
388 << "A->" << getLowerName() << "_size()";
389 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000390 void writeCtorBody(raw_ostream &OS) const {
391 // FIXME: memcpy is not safe on non-trivial types.
392 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
393 << ", " << getLowerName() << "Size * sizeof(" << getType() << "));\n";
394 }
395 void writeCtorInitializers(raw_ostream &OS) const {
396 OS << getLowerName() << "Size(" << getUpperName() << "Size), "
397 << getLowerName() << "(new (Ctx, 16) " << getType() << "["
398 << getLowerName() << "Size])";
399 }
400 void writeCtorParameters(raw_ostream &OS) const {
401 OS << getType() << " *" << getUpperName() << ", unsigned "
402 << getUpperName() << "Size";
403 }
404 void writeDeclarations(raw_ostream &OS) const {
405 OS << " unsigned " << getLowerName() << "Size;\n";
406 OS << " " << getType() << " *" << getLowerName() << ";";
407 }
408 void writePCHReadDecls(raw_ostream &OS) const {
409 OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
410 OS << " llvm::SmallVector<" << type << ", 4> " << getLowerName()
411 << ";\n";
412 OS << " " << getLowerName() << ".reserve(" << getLowerName()
413 << "Size);\n";
414 OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
415
416 std::string read = ReadPCHRecord(type);
417 OS << " " << getLowerName() << ".push_back(" << read << ");\n";
418 }
419 void writePCHReadArgs(raw_ostream &OS) const {
420 OS << getLowerName() << ".data(), " << getLowerName() << "Size";
421 }
422 void writePCHWrite(raw_ostream &OS) const{
423 OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";
424 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
425 << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
426 << getLowerName() << "_end(); i != e; ++i)\n";
427 OS << " " << WritePCHRecord(type, "(*i)");
428 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000429 void writeValue(raw_ostream &OS) const {
430 OS << "\";\n";
431 OS << " bool isFirst = true;\n"
432 << " for (" << getAttrName() << "Attr::" << getLowerName()
433 << "_iterator i = " << getLowerName() << "_begin(), e = "
434 << getLowerName() << "_end(); i != e; ++i) {\n"
435 << " if (isFirst) isFirst = false;\n"
436 << " else OS << \", \";\n"
437 << " OS << *i;\n"
438 << " }\n";
439 OS << " OS << \"";
440 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000441 };
442
443 class EnumArgument : public Argument {
444 std::string type;
445 std::vector<StringRef> values, enums;
446 public:
447 EnumArgument(Record &Arg, StringRef Attr)
448 : Argument(Arg, Attr), type(Arg.getValueAsString("Type")),
449 values(getValueAsListOfStrings(Arg, "Values")),
450 enums(getValueAsListOfStrings(Arg, "Enums"))
451 {}
452
453 void writeAccessors(raw_ostream &OS) const {
454 OS << " " << type << " get" << getUpperName() << "() const {\n";
455 OS << " return " << getLowerName() << ";\n";
456 OS << " }";
457 }
458 void writeCloneArgs(raw_ostream &OS) const {
459 OS << getLowerName();
460 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000461 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
462 OS << "A->get" << getUpperName() << "()";
463 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000464 void writeCtorInitializers(raw_ostream &OS) const {
465 OS << getLowerName() << "(" << getUpperName() << ")";
466 }
467 void writeCtorParameters(raw_ostream &OS) const {
468 OS << type << " " << getUpperName();
469 }
470 void writeDeclarations(raw_ostream &OS) const {
471 // Calculate the various enum values
472 std::vector<StringRef> uniques(enums);
473 std::sort(uniques.begin(), uniques.end());
474 uniques.erase(std::unique(uniques.begin(), uniques.end()),
475 uniques.end());
476 // FIXME: Emit a proper error
477 assert(!uniques.empty());
478
479 std::vector<StringRef>::iterator i = uniques.begin(),
480 e = uniques.end();
481 // The last one needs to not have a comma.
482 --e;
483
484 OS << "public:\n";
485 OS << " enum " << type << " {\n";
486 for (; i != e; ++i)
487 OS << " " << *i << ",\n";
488 OS << " " << *e << "\n";
489 OS << " };\n";
490 OS << "private:\n";
491 OS << " " << type << " " << getLowerName() << ";";
492 }
493 void writePCHReadDecls(raw_ostream &OS) const {
494 OS << " " << getAttrName() << "Attr::" << type << " " << getLowerName()
495 << "(static_cast<" << getAttrName() << "Attr::" << type
496 << ">(Record[Idx++]));\n";
497 }
498 void writePCHReadArgs(raw_ostream &OS) const {
499 OS << getLowerName();
500 }
501 void writePCHWrite(raw_ostream &OS) const {
502 OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
503 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000504 void writeValue(raw_ostream &OS) const {
505 OS << "\" << get" << getUpperName() << "() << \"";
506 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000507 };
508
509 class VersionArgument : public Argument {
510 public:
511 VersionArgument(Record &Arg, StringRef Attr)
512 : Argument(Arg, Attr)
513 {}
514
515 void writeAccessors(raw_ostream &OS) const {
516 OS << " VersionTuple get" << getUpperName() << "() const {\n";
517 OS << " return " << getLowerName() << ";\n";
518 OS << " }\n";
519 OS << " void set" << getUpperName()
520 << "(ASTContext &C, VersionTuple V) {\n";
521 OS << " " << getLowerName() << " = V;\n";
522 OS << " }";
523 }
524 void writeCloneArgs(raw_ostream &OS) const {
525 OS << "get" << getUpperName() << "()";
526 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000527 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
528 OS << "A->get" << getUpperName() << "()";
529 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000530 void writeCtorBody(raw_ostream &OS) const {
531 }
532 void writeCtorInitializers(raw_ostream &OS) const {
533 OS << getLowerName() << "(" << getUpperName() << ")";
534 }
535 void writeCtorParameters(raw_ostream &OS) const {
536 OS << "VersionTuple " << getUpperName();
537 }
538 void writeDeclarations(raw_ostream &OS) const {
539 OS << "VersionTuple " << getLowerName() << ";\n";
540 }
541 void writePCHReadDecls(raw_ostream &OS) const {
542 OS << " VersionTuple " << getLowerName()
543 << "= ReadVersionTuple(Record, Idx);\n";
544 }
545 void writePCHReadArgs(raw_ostream &OS) const {
546 OS << getLowerName();
547 }
548 void writePCHWrite(raw_ostream &OS) const {
549 OS << " AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n";
550 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000551 void writeValue(raw_ostream &OS) const {
552 OS << getLowerName() << "=\" << get" << getUpperName() << "() << \"";
553 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000554 };
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000555
556 class ExprArgument : public SimpleArgument {
557 public:
558 ExprArgument(Record &Arg, StringRef Attr)
559 : SimpleArgument(Arg, Attr, "Expr *")
560 {}
561
562 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
563 OS << "tempInst" << getUpperName();
564 }
565
566 void writeTemplateInstantiation(raw_ostream &OS) const {
567 OS << " " << getType() << " tempInst" << getUpperName() << ";\n";
568 OS << " {\n";
569 OS << " EnterExpressionEvaluationContext "
570 << "Unevaluated(S, Sema::Unevaluated);\n";
571 OS << " ExprResult " << "Result = S.SubstExpr("
572 << "A->get" << getUpperName() << "(), TemplateArgs);\n";
573 OS << " tempInst" << getUpperName() << " = "
574 << "Result.takeAs<Expr>();\n";
575 OS << " }\n";
576 }
577 };
578
579 class VariadicExprArgument : public VariadicArgument {
580 public:
581 VariadicExprArgument(Record &Arg, StringRef Attr)
582 : VariadicArgument(Arg, Attr, "Expr *")
583 {}
584
585 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
586 OS << "tempInst" << getUpperName() << ", "
587 << "A->" << getLowerName() << "_size()";
588 }
589
590 void writeTemplateInstantiation(raw_ostream &OS) const {
591 OS << " " << getType() << " *tempInst" << getUpperName()
592 << " = new (C, 16) " << getType()
593 << "[A->" << getLowerName() << "_size()];\n";
594 OS << " {\n";
595 OS << " EnterExpressionEvaluationContext "
596 << "Unevaluated(S, Sema::Unevaluated);\n";
597 OS << " " << getType() << " *TI = tempInst" << getUpperName()
598 << ";\n";
599 OS << " " << getType() << " *I = A->" << getLowerName()
600 << "_begin();\n";
601 OS << " " << getType() << " *E = A->" << getLowerName()
602 << "_end();\n";
603 OS << " for (; I != E; ++I, ++TI) {\n";
604 OS << " ExprResult Result = S.SubstExpr(*I, TemplateArgs);\n";
605 OS << " *TI = Result.takeAs<Expr>();\n";
606 OS << " }\n";
607 OS << " }\n";
608 }
609 };
Peter Collingbourne51d77772011-10-06 13:03:08 +0000610}
611
612static Argument *createArgument(Record &Arg, StringRef Attr,
613 Record *Search = 0) {
614 if (!Search)
615 Search = &Arg;
616
617 Argument *Ptr = 0;
618 llvm::StringRef ArgName = Search->getName();
619
620 if (ArgName == "AlignedArgument") Ptr = new AlignedArgument(Arg, Attr);
621 else if (ArgName == "EnumArgument") Ptr = new EnumArgument(Arg, Attr);
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000622 else if (ArgName == "ExprArgument") Ptr = new ExprArgument(Arg, Attr);
Peter Collingbourne51d77772011-10-06 13:03:08 +0000623 else if (ArgName == "FunctionArgument")
624 Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *");
625 else if (ArgName == "IdentifierArgument")
626 Ptr = new SimpleArgument(Arg, Attr, "IdentifierInfo *");
627 else if (ArgName == "BoolArgument") Ptr = new SimpleArgument(Arg, Attr,
628 "bool");
629 else if (ArgName == "IntArgument") Ptr = new SimpleArgument(Arg, Attr, "int");
630 else if (ArgName == "StringArgument") Ptr = new StringArgument(Arg, Attr);
631 else if (ArgName == "TypeArgument")
632 Ptr = new SimpleArgument(Arg, Attr, "QualType");
633 else if (ArgName == "UnsignedArgument")
634 Ptr = new SimpleArgument(Arg, Attr, "unsigned");
635 else if (ArgName == "SourceLocArgument")
636 Ptr = new SimpleArgument(Arg, Attr, "SourceLocation");
637 else if (ArgName == "VariadicUnsignedArgument")
638 Ptr = new VariadicArgument(Arg, Attr, "unsigned");
639 else if (ArgName == "VariadicExprArgument")
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000640 Ptr = new VariadicExprArgument(Arg, Attr);
Peter Collingbourne51d77772011-10-06 13:03:08 +0000641 else if (ArgName == "VersionArgument")
642 Ptr = new VersionArgument(Arg, Attr);
643
644 if (!Ptr) {
645 std::vector<Record*> Bases = Search->getSuperClasses();
646 for (std::vector<Record*>::iterator i = Bases.begin(), e = Bases.end();
647 i != e; ++i) {
648 Ptr = createArgument(Arg, Attr, *i);
649 if (Ptr)
650 break;
651 }
652 }
653 return Ptr;
654}
655
Douglas Gregor1bea8802011-11-19 19:22:57 +0000656static void writeAvailabilityValue(raw_ostream &OS) {
657 OS << "\" << getPlatform()->getName();\n"
658 << " if (!getIntroduced().empty()) OS << \", introduced=\" << getIntroduced();\n"
659 << " if (!getDeprecated().empty()) OS << \", deprecated=\" << getDeprecated();\n"
660 << " if (!getObsoleted().empty()) OS << \", obsoleted=\" << getObsoleted();\n"
661 << " if (getUnavailable()) OS << \", unavailable\";\n"
662 << " OS << \"";
663}
664
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +0000665namespace clang {
666
667// Emits the class definitions for attributes.
668void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000669 OS << "// This file is generated by TableGen. Do not edit.\n\n";
670 OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
671 OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
672
673 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
674
675 for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
676 i != e; ++i) {
677 Record &R = **i;
Douglas Gregor3e7d31a2012-05-02 15:56:52 +0000678
679 if (!R.getValueAsBit("ASTNode"))
680 continue;
681
Peter Collingbourne51d77772011-10-06 13:03:08 +0000682 const std::string &SuperName = R.getSuperClasses().back()->getName();
683
684 OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n";
685
686 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
687 std::vector<Argument*> Args;
688 std::vector<Argument*>::iterator ai, ae;
689 Args.reserve(ArgRecords.size());
690
691 for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
692 re = ArgRecords.end();
693 ri != re; ++ri) {
694 Record &ArgRecord = **ri;
695 Argument *Arg = createArgument(ArgRecord, R.getName());
696 assert(Arg);
697 Args.push_back(Arg);
698
699 Arg->writeDeclarations(OS);
700 OS << "\n\n";
701 }
702
703 ae = Args.end();
704
705 OS << "\n public:\n";
706 OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
707
708 for (ai = Args.begin(); ai != ae; ++ai) {
709 OS << " , ";
710 (*ai)->writeCtorParameters(OS);
711 OS << "\n";
712 }
713
714 OS << " )\n";
715 OS << " : " << SuperName << "(attr::" << R.getName() << ", R)\n";
716
717 for (ai = Args.begin(); ai != ae; ++ai) {
718 OS << " , ";
719 (*ai)->writeCtorInitializers(OS);
720 OS << "\n";
721 }
722
723 OS << " {\n";
724
725 for (ai = Args.begin(); ai != ae; ++ai) {
726 (*ai)->writeCtorBody(OS);
727 OS << "\n";
728 }
729 OS << " }\n\n";
730
731 OS << " virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n";
Douglas Gregor1bea8802011-11-19 19:22:57 +0000732 OS << " virtual void printPretty(llvm::raw_ostream &OS, ASTContext &Ctx) const;\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000733
734 for (ai = Args.begin(); ai != ae; ++ai) {
735 (*ai)->writeAccessors(OS);
736 OS << "\n\n";
737 }
738
Jakob Stoklund Oleseneb666732012-01-13 04:57:47 +0000739 OS << R.getValueAsString("AdditionalMembers");
Peter Collingbourne51d77772011-10-06 13:03:08 +0000740 OS << "\n\n";
741
742 OS << " static bool classof(const Attr *A) { return A->getKind() == "
743 << "attr::" << R.getName() << "; }\n";
744 OS << " static bool classof(const " << R.getName()
745 << "Attr *) { return true; }\n";
DeLesley Hutchins23323e02012-01-20 22:50:54 +0000746
747 bool LateParsed = R.getValueAsBit("LateParsed");
748 OS << " virtual bool isLateParsed() const { return "
749 << LateParsed << "; }\n";
750
Peter Collingbourne51d77772011-10-06 13:03:08 +0000751 OS << "};\n\n";
752 }
753
754 OS << "#endif\n";
755}
756
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +0000757// Emits the class method definitions for attributes.
758void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000759 OS << "// This file is generated by TableGen. Do not edit.\n\n";
760
761 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
762 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ri, re;
763 std::vector<Argument*>::iterator ai, ae;
764
765 for (; i != e; ++i) {
766 Record &R = **i;
Douglas Gregor3e7d31a2012-05-02 15:56:52 +0000767
768 if (!R.getValueAsBit("ASTNode"))
769 continue;
770
Peter Collingbourne51d77772011-10-06 13:03:08 +0000771 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
Sean Hunt8e083e72012-06-19 23:57:03 +0000772 std::vector<Record*> Spellings = R.getValueAsListOfDefs("Spellings");
Peter Collingbourne51d77772011-10-06 13:03:08 +0000773 std::vector<Argument*> Args;
774 for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri)
775 Args.push_back(createArgument(**ri, R.getName()));
776
777 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
778 (*ai)->writeAccessorDefinitions(OS);
779
780 OS << R.getName() << "Attr *" << R.getName()
781 << "Attr::clone(ASTContext &C) const {\n";
782 OS << " return new (C) " << R.getName() << "Attr(getLocation(), C";
783 for (ai = Args.begin(); ai != ae; ++ai) {
784 OS << ", ";
785 (*ai)->writeCloneArgs(OS);
786 }
787 OS << ");\n}\n\n";
Douglas Gregor1bea8802011-11-19 19:22:57 +0000788
789 OS << "void " << R.getName() << "Attr::printPretty("
790 << "llvm::raw_ostream &OS, ASTContext &Ctx) const {\n";
791 if (Spellings.begin() != Spellings.end()) {
Sean Hunt8e083e72012-06-19 23:57:03 +0000792 StringRef Spelling = (*Spellings.begin())->getValueAsString("Name");
793 OS << " OS << \" __attribute__((" << Spelling;
Douglas Gregor1bea8802011-11-19 19:22:57 +0000794 if (Args.size()) OS << "(";
Sean Hunt8e083e72012-06-19 23:57:03 +0000795 if (Spelling == "availability") {
Douglas Gregor1bea8802011-11-19 19:22:57 +0000796 writeAvailabilityValue(OS);
797 } else {
798 for (ai = Args.begin(); ai != ae; ++ai) {
799 if (ai!=Args.begin()) OS <<", ";
800 (*ai)->writeValue(OS);
801 }
802 }
803 if (Args.size()) OS << ")";
804 OS << "))\";\n";
805 }
806 OS << "}\n\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000807 }
808}
809
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +0000810} // end namespace clang
811
Peter Collingbourne51d77772011-10-06 13:03:08 +0000812static void EmitAttrList(raw_ostream &OS, StringRef Class,
813 const std::vector<Record*> &AttrList) {
814 std::vector<Record*>::const_iterator i = AttrList.begin(), e = AttrList.end();
815
816 if (i != e) {
817 // Move the end iterator back to emit the last attribute.
Douglas Gregor3e7d31a2012-05-02 15:56:52 +0000818 for(--e; i != e; ++i) {
819 if (!(*i)->getValueAsBit("ASTNode"))
820 continue;
821
Peter Collingbourne51d77772011-10-06 13:03:08 +0000822 OS << Class << "(" << (*i)->getName() << ")\n";
Douglas Gregor3e7d31a2012-05-02 15:56:52 +0000823 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000824
825 OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n";
826 }
827}
828
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +0000829namespace clang {
830
831// Emits the enumeration list for attributes.
832void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000833 OS << "// This file is generated by TableGen. Do not edit.\n\n";
834
835 OS << "#ifndef LAST_ATTR\n";
836 OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n";
837 OS << "#endif\n\n";
838
839 OS << "#ifndef INHERITABLE_ATTR\n";
840 OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n";
841 OS << "#endif\n\n";
842
843 OS << "#ifndef LAST_INHERITABLE_ATTR\n";
844 OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n";
845 OS << "#endif\n\n";
846
847 OS << "#ifndef INHERITABLE_PARAM_ATTR\n";
848 OS << "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n";
849 OS << "#endif\n\n";
850
851 OS << "#ifndef LAST_INHERITABLE_PARAM_ATTR\n";
852 OS << "#define LAST_INHERITABLE_PARAM_ATTR(NAME)"
853 " INHERITABLE_PARAM_ATTR(NAME)\n";
854 OS << "#endif\n\n";
855
856 Record *InhClass = Records.getClass("InheritableAttr");
857 Record *InhParamClass = Records.getClass("InheritableParamAttr");
858 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
859 NonInhAttrs, InhAttrs, InhParamAttrs;
860 for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
861 i != e; ++i) {
Douglas Gregor3e7d31a2012-05-02 15:56:52 +0000862 if (!(*i)->getValueAsBit("ASTNode"))
863 continue;
864
Peter Collingbourne51d77772011-10-06 13:03:08 +0000865 if ((*i)->isSubClassOf(InhParamClass))
866 InhParamAttrs.push_back(*i);
867 else if ((*i)->isSubClassOf(InhClass))
868 InhAttrs.push_back(*i);
869 else
870 NonInhAttrs.push_back(*i);
871 }
872
873 EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs);
874 EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs);
875 EmitAttrList(OS, "ATTR", NonInhAttrs);
876
877 OS << "#undef LAST_ATTR\n";
878 OS << "#undef INHERITABLE_ATTR\n";
879 OS << "#undef LAST_INHERITABLE_ATTR\n";
880 OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n";
881 OS << "#undef ATTR\n";
882}
883
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +0000884// Emits the code to read an attribute from a precompiled header.
885void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000886 OS << "// This file is generated by TableGen. Do not edit.\n\n";
887
888 Record *InhClass = Records.getClass("InheritableAttr");
889 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
890 ArgRecords;
891 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
892 std::vector<Argument*> Args;
893 std::vector<Argument*>::iterator ri, re;
894
895 OS << " switch (Kind) {\n";
896 OS << " default:\n";
897 OS << " assert(0 && \"Unknown attribute!\");\n";
898 OS << " break;\n";
899 for (; i != e; ++i) {
900 Record &R = **i;
Douglas Gregor3e7d31a2012-05-02 15:56:52 +0000901 if (!R.getValueAsBit("ASTNode"))
902 continue;
903
Peter Collingbourne51d77772011-10-06 13:03:08 +0000904 OS << " case attr::" << R.getName() << ": {\n";
905 if (R.isSubClassOf(InhClass))
906 OS << " bool isInherited = Record[Idx++];\n";
907 ArgRecords = R.getValueAsListOfDefs("Args");
908 Args.clear();
909 for (ai = ArgRecords.begin(), ae = ArgRecords.end(); ai != ae; ++ai) {
910 Argument *A = createArgument(**ai, R.getName());
911 Args.push_back(A);
912 A->writePCHReadDecls(OS);
913 }
914 OS << " New = new (Context) " << R.getName() << "Attr(Range, Context";
915 for (ri = Args.begin(), re = Args.end(); ri != re; ++ri) {
916 OS << ", ";
917 (*ri)->writePCHReadArgs(OS);
918 }
919 OS << ");\n";
920 if (R.isSubClassOf(InhClass))
921 OS << " cast<InheritableAttr>(New)->setInherited(isInherited);\n";
922 OS << " break;\n";
923 OS << " }\n";
924 }
925 OS << " }\n";
926}
927
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +0000928// Emits the code to write an attribute to a precompiled header.
929void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000930 Record *InhClass = Records.getClass("InheritableAttr");
931 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
932 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
933
934 OS << " switch (A->getKind()) {\n";
935 OS << " default:\n";
936 OS << " llvm_unreachable(\"Unknown attribute kind!\");\n";
937 OS << " break;\n";
938 for (; i != e; ++i) {
939 Record &R = **i;
Douglas Gregor3e7d31a2012-05-02 15:56:52 +0000940 if (!R.getValueAsBit("ASTNode"))
941 continue;
Peter Collingbourne51d77772011-10-06 13:03:08 +0000942 OS << " case attr::" << R.getName() << ": {\n";
943 Args = R.getValueAsListOfDefs("Args");
944 if (R.isSubClassOf(InhClass) || !Args.empty())
945 OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
946 << "Attr>(A);\n";
947 if (R.isSubClassOf(InhClass))
948 OS << " Record.push_back(SA->isInherited());\n";
949 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
950 createArgument(**ai, R.getName())->writePCHWrite(OS);
951 OS << " break;\n";
952 OS << " }\n";
953 }
954 OS << " }\n";
955}
956
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +0000957// Emits the list of spellings for attributes.
958void EmitClangAttrSpellingList(RecordKeeper &Records, raw_ostream &OS) {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000959 OS << "// This file is generated by TableGen. Do not edit.\n\n";
960
961 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
962
963 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) {
964 Record &Attr = **I;
965
Sean Hunt8e083e72012-06-19 23:57:03 +0000966 std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
Peter Collingbourne51d77772011-10-06 13:03:08 +0000967
Sean Hunt8e083e72012-06-19 23:57:03 +0000968 for (std::vector<Record*>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) {
969 OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", true)\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000970 }
971 }
972
973}
974
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +0000975// Emits the LateParsed property for attributes.
976void EmitClangAttrLateParsedList(RecordKeeper &Records, raw_ostream &OS) {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000977 OS << "// This file is generated by TableGen. Do not edit.\n\n";
978
979 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
980
981 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
982 I != E; ++I) {
983 Record &Attr = **I;
984
985 bool LateParsed = Attr.getValueAsBit("LateParsed");
986
987 if (LateParsed) {
Sean Hunt8e083e72012-06-19 23:57:03 +0000988 std::vector<Record*> Spellings =
989 Attr.getValueAsListOfDefs("Spellings");
Peter Collingbourne51d77772011-10-06 13:03:08 +0000990
Sean Hunt8e083e72012-06-19 23:57:03 +0000991 // FIXME: Handle non-GNU attributes
992 for (std::vector<Record*>::const_iterator I = Spellings.begin(),
Peter Collingbourne51d77772011-10-06 13:03:08 +0000993 E = Spellings.end(); I != E; ++I) {
Sean Hunt8e083e72012-06-19 23:57:03 +0000994 if ((*I)->getValueAsString("Variety") != "GNU")
995 continue;
996 OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", "
997 << LateParsed << ")\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000998 }
999 }
1000 }
1001}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001002
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001003// Emits code to instantiate dependent attributes on templates.
1004void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001005 OS << "// This file is generated by TableGen. Do not edit.\n\n";
1006
1007 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1008
Benjamin Kramer5bbc3852012-02-06 11:13:08 +00001009 OS << "namespace clang {\n"
1010 << "namespace sema {\n\n"
1011 << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, "
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001012 << "Sema &S,\n"
1013 << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n"
1014 << " switch (At->getKind()) {\n"
1015 << " default:\n"
1016 << " break;\n";
1017
1018 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1019 I != E; ++I) {
1020 Record &R = **I;
Douglas Gregor3e7d31a2012-05-02 15:56:52 +00001021 if (!R.getValueAsBit("ASTNode"))
1022 continue;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001023
1024 OS << " case attr::" << R.getName() << ": {\n";
Rafael Espindola31c195a2012-05-15 14:09:55 +00001025 bool ShouldClone = R.getValueAsBit("Clone");
1026
1027 if (!ShouldClone) {
1028 OS << " return NULL;\n";
1029 OS << " }\n";
1030 continue;
1031 }
1032
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001033 OS << " const " << R.getName() << "Attr *A = cast<"
1034 << R.getName() << "Attr>(At);\n";
1035 bool TDependent = R.getValueAsBit("TemplateDependent");
1036
1037 if (!TDependent) {
1038 OS << " return A->clone(C);\n";
1039 OS << " }\n";
1040 continue;
1041 }
1042
1043 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
1044 std::vector<Argument*> Args;
1045 std::vector<Argument*>::iterator ai, ae;
1046 Args.reserve(ArgRecords.size());
1047
1048 for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
1049 re = ArgRecords.end();
1050 ri != re; ++ri) {
1051 Record &ArgRecord = **ri;
1052 Argument *Arg = createArgument(ArgRecord, R.getName());
1053 assert(Arg);
1054 Args.push_back(Arg);
1055 }
1056 ae = Args.end();
1057
1058 for (ai = Args.begin(); ai != ae; ++ai) {
1059 (*ai)->writeTemplateInstantiation(OS);
1060 }
1061 OS << " return new (C) " << R.getName() << "Attr(A->getLocation(), C";
1062 for (ai = Args.begin(); ai != ae; ++ai) {
1063 OS << ", ";
1064 (*ai)->writeTemplateInstantiationArgs(OS);
1065 }
1066 OS << ");\n }\n";
1067 }
1068 OS << " } // end switch\n"
1069 << " llvm_unreachable(\"Unknown attribute!\");\n"
1070 << " return 0;\n"
Benjamin Kramer5bbc3852012-02-06 11:13:08 +00001071 << "}\n\n"
1072 << "} // end namespace sema\n"
1073 << "} // end namespace clang\n";
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001074}
1075
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001076// Emits the list of parsed attributes.
1077void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) {
Michael Hane53ac8a2012-03-07 00:12:16 +00001078 OS << "// This file is generated by TableGen. Do not edit.\n\n";
1079
1080 OS << "#ifndef PARSED_ATTR\n";
1081 OS << "#define PARSED_ATTR(NAME) NAME\n";
1082 OS << "#endif\n\n";
1083
1084 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
Michael Hane53ac8a2012-03-07 00:12:16 +00001085
1086 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1087 I != E; ++I) {
1088 Record &Attr = **I;
1089
1090 bool SemaHandler = Attr.getValueAsBit("SemaHandler");
Douglas Gregor703d4122012-05-11 23:37:49 +00001091 bool DistinctSpellings = Attr.getValueAsBit("DistinctSpellings");
1092
Michael Hane53ac8a2012-03-07 00:12:16 +00001093 if (SemaHandler) {
Sean Hunt8e083e72012-06-19 23:57:03 +00001094 if (DistinctSpellings) {
1095 std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
Jakob Stoklund Olesen35329362012-06-19 21:48:43 +00001096
Sean Hunt8e083e72012-06-19 23:57:03 +00001097 for (std::vector<Record*>::const_iterator I = Spellings.begin(),
1098 E = Spellings.end(); I != E; ++I) {
1099 std::string AttrName = (*I)->getValueAsString("Name");
1100
1101 StringRef Spelling = NormalizeAttrName(AttrName);
1102
1103 OS << "PARSED_ATTR(" << Spelling << ")\n";
1104 }
1105 } else {
1106 StringRef AttrName = Attr.getName();
1107 AttrName = NormalizeAttrName(AttrName);
1108 OS << "PARSED_ATTR(" << AttrName << ")\n";
Michael Hane53ac8a2012-03-07 00:12:16 +00001109 }
1110 }
1111 }
1112}
1113
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001114// Emits the kind list of parsed attributes
1115void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
Michael Hane53ac8a2012-03-07 00:12:16 +00001116 OS << "// This file is generated by TableGen. Do not edit.\n\n";
Douglas Gregor0c19b3c2012-05-02 17:33:51 +00001117 OS << "\n";
1118
Michael Hane53ac8a2012-03-07 00:12:16 +00001119 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1120
Douglas Gregor0c19b3c2012-05-02 17:33:51 +00001121 std::vector<StringMatcher::StringPair> Matches;
Michael Hane53ac8a2012-03-07 00:12:16 +00001122 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1123 I != E; ++I) {
1124 Record &Attr = **I;
1125
1126 bool SemaHandler = Attr.getValueAsBit("SemaHandler");
Douglas Gregor331d2ec2012-05-02 16:18:45 +00001127 bool Ignored = Attr.getValueAsBit("Ignored");
Douglas Gregor703d4122012-05-11 23:37:49 +00001128 bool DistinctSpellings = Attr.getValueAsBit("DistinctSpellings");
Douglas Gregor331d2ec2012-05-02 16:18:45 +00001129 if (SemaHandler || Ignored) {
Sean Hunt8e083e72012-06-19 23:57:03 +00001130 std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
Michael Hane53ac8a2012-03-07 00:12:16 +00001131
Sean Hunt8e083e72012-06-19 23:57:03 +00001132 for (std::vector<Record*>::const_iterator I = Spellings.begin(),
Michael Hane53ac8a2012-03-07 00:12:16 +00001133 E = Spellings.end(); I != E; ++I) {
Sean Hunt8e083e72012-06-19 23:57:03 +00001134 std::string RawSpelling = (*I)->getValueAsString("Name");
Douglas Gregor703d4122012-05-11 23:37:49 +00001135 StringRef AttrName = NormalizeAttrName(DistinctSpellings
Sean Hunt8e083e72012-06-19 23:57:03 +00001136 ? StringRef(RawSpelling)
1137 : StringRef(Attr.getName()));
Michael Hane53ac8a2012-03-07 00:12:16 +00001138
Sean Hunt8e083e72012-06-19 23:57:03 +00001139 SmallString<64> Spelling;
1140 if ((*I)->getValueAsString("Variety") == "CXX11") {
1141 Spelling += (*I)->getValueAsString("Namespace");
1142 Spelling += "::";
Sean Hunt93f95f22012-06-18 16:13:52 +00001143 }
Sean Hunt8e083e72012-06-19 23:57:03 +00001144 Spelling += NormalizeAttrSpelling(RawSpelling);
Sean Hunt93f95f22012-06-18 16:13:52 +00001145
Douglas Gregor331d2ec2012-05-02 16:18:45 +00001146 if (SemaHandler)
Douglas Gregor0c19b3c2012-05-02 17:33:51 +00001147 Matches.push_back(
Douglas Gregor703d4122012-05-11 23:37:49 +00001148 StringMatcher::StringPair(
Sean Hunt8e083e72012-06-19 23:57:03 +00001149 StringRef(Spelling),
Sean Hunt93f95f22012-06-18 16:13:52 +00001150 "return AttributeList::AT_" + AttrName.str() + ";"));
Douglas Gregor331d2ec2012-05-02 16:18:45 +00001151 else
Douglas Gregor0c19b3c2012-05-02 17:33:51 +00001152 Matches.push_back(
1153 StringMatcher::StringPair(
Sean Hunt8e083e72012-06-19 23:57:03 +00001154 StringRef(Spelling),
Sean Hunt93f95f22012-06-18 16:13:52 +00001155 "return AttributeList::IgnoredAttribute;"));
Michael Hane53ac8a2012-03-07 00:12:16 +00001156 }
1157 }
1158 }
Douglas Gregor0c19b3c2012-05-02 17:33:51 +00001159
1160 OS << "static AttributeList::Kind getAttrKind(StringRef Name) {\n";
1161 StringMatcher("Name", Matches, OS).Emit();
1162 OS << "return AttributeList::UnknownAttribute;\n"
1163 << "}\n";
Michael Hane53ac8a2012-03-07 00:12:16 +00001164}
1165
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001166} // end namespace clang