blob: 3530e7e738b065a686e88d68332987e04b9b2a97 [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>
21
22using namespace llvm;
23
24static const std::vector<StringRef>
25getValueAsListOfStrings(Record &R, StringRef FieldName) {
26 ListInit *List = R.getValueAsListInit(FieldName);
27 assert (List && "Got a null ListInit");
28
29 std::vector<StringRef> Strings;
30 Strings.reserve(List->getSize());
31
32 for (ListInit::const_iterator i = List->begin(), e = List->end();
33 i != e;
34 ++i) {
35 assert(*i && "Got a null element in a ListInit");
Sean Silva1ab46322012-10-10 20:25:43 +000036 if (StringInit *S = dyn_cast<StringInit>(*i))
Peter Collingbourne51d77772011-10-06 13:03:08 +000037 Strings.push_back(S->getValue());
Peter Collingbourne51d77772011-10-06 13:03:08 +000038 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++])")
Argyrios Kyrtzidis350aea72012-11-15 01:31:39 +000050 .Case("Expr *", "ReadExpr(F)")
Peter Collingbourne51d77772011-10-06 13:03:08 +000051 .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
Michael Hane53ac8a2012-03-07 00:12:16 +000070// Normalize attribute name by removing leading and trailing
71// underscores. For example, __foo, foo__, __foo__ would
72// become foo.
73static StringRef NormalizeAttrName(StringRef AttrName) {
74 if (AttrName.startswith("__"))
75 AttrName = AttrName.substr(2, AttrName.size());
76
77 if (AttrName.endswith("__"))
78 AttrName = AttrName.substr(0, AttrName.size() - 2);
79
80 return AttrName;
81}
82
83// Normalize attribute spelling only if the spelling has both leading
84// and trailing underscores. For example, __ms_struct__ will be
85// normalized to "ms_struct"; __cdecl will remain intact.
86static StringRef NormalizeAttrSpelling(StringRef AttrSpelling) {
87 if (AttrSpelling.startswith("__") && AttrSpelling.endswith("__")) {
88 AttrSpelling = AttrSpelling.substr(2, AttrSpelling.size() - 4);
89 }
90
91 return AttrSpelling;
92}
93
Peter Collingbourne51d77772011-10-06 13:03:08 +000094namespace {
95 class Argument {
96 std::string lowerName, upperName;
97 StringRef attrName;
98
99 public:
100 Argument(Record &Arg, StringRef Attr)
101 : lowerName(Arg.getValueAsString("Name")), upperName(lowerName),
102 attrName(Attr) {
103 if (!lowerName.empty()) {
104 lowerName[0] = std::tolower(lowerName[0]);
105 upperName[0] = std::toupper(upperName[0]);
106 }
107 }
108 virtual ~Argument() {}
109
110 StringRef getLowerName() const { return lowerName; }
111 StringRef getUpperName() const { return upperName; }
112 StringRef getAttrName() const { return attrName; }
113
114 // These functions print the argument contents formatted in different ways.
115 virtual void writeAccessors(raw_ostream &OS) const = 0;
116 virtual void writeAccessorDefinitions(raw_ostream &OS) const {}
117 virtual void writeCloneArgs(raw_ostream &OS) const = 0;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000118 virtual void writeTemplateInstantiationArgs(raw_ostream &OS) const = 0;
Daniel Dunbarb8806092012-02-10 06:00:29 +0000119 virtual void writeTemplateInstantiation(raw_ostream &OS) const {}
Peter Collingbourne51d77772011-10-06 13:03:08 +0000120 virtual void writeCtorBody(raw_ostream &OS) const {}
121 virtual void writeCtorInitializers(raw_ostream &OS) const = 0;
122 virtual void writeCtorParameters(raw_ostream &OS) const = 0;
123 virtual void writeDeclarations(raw_ostream &OS) const = 0;
124 virtual void writePCHReadArgs(raw_ostream &OS) const = 0;
125 virtual void writePCHReadDecls(raw_ostream &OS) const = 0;
126 virtual void writePCHWrite(raw_ostream &OS) const = 0;
Douglas Gregor1bea8802011-11-19 19:22:57 +0000127 virtual void writeValue(raw_ostream &OS) const = 0;
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000128 virtual void writeDump(raw_ostream &OS) const = 0;
129 virtual void writeDumpChildren(raw_ostream &OS) const {}
Peter Collingbourne51d77772011-10-06 13:03:08 +0000130 };
131
132 class SimpleArgument : public Argument {
133 std::string type;
134
135 public:
136 SimpleArgument(Record &Arg, StringRef Attr, std::string T)
137 : Argument(Arg, Attr), type(T)
138 {}
139
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000140 std::string getType() const { return type; }
141
Peter Collingbourne51d77772011-10-06 13:03:08 +0000142 void writeAccessors(raw_ostream &OS) const {
143 OS << " " << type << " get" << getUpperName() << "() const {\n";
144 OS << " return " << getLowerName() << ";\n";
145 OS << " }";
146 }
147 void writeCloneArgs(raw_ostream &OS) const {
148 OS << getLowerName();
149 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000150 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
151 OS << "A->get" << getUpperName() << "()";
152 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000153 void writeCtorInitializers(raw_ostream &OS) const {
154 OS << getLowerName() << "(" << getUpperName() << ")";
155 }
156 void writeCtorParameters(raw_ostream &OS) const {
157 OS << type << " " << getUpperName();
158 }
159 void writeDeclarations(raw_ostream &OS) const {
160 OS << type << " " << getLowerName() << ";";
161 }
162 void writePCHReadDecls(raw_ostream &OS) const {
163 std::string read = ReadPCHRecord(type);
164 OS << " " << type << " " << getLowerName() << " = " << read << ";\n";
165 }
166 void writePCHReadArgs(raw_ostream &OS) const {
167 OS << getLowerName();
168 }
169 void writePCHWrite(raw_ostream &OS) const {
170 OS << " " << WritePCHRecord(type, "SA->get" +
171 std::string(getUpperName()) + "()");
172 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000173 void writeValue(raw_ostream &OS) const {
174 if (type == "FunctionDecl *") {
175 OS << "\" << get" << getUpperName() << "()->getNameInfo().getAsString() << \"";
176 } else if (type == "IdentifierInfo *") {
177 OS << "\" << get" << getUpperName() << "()->getName() << \"";
178 } else if (type == "QualType") {
179 OS << "\" << get" << getUpperName() << "().getAsString() << \"";
180 } else if (type == "SourceLocation") {
181 OS << "\" << get" << getUpperName() << "().getRawEncoding() << \"";
182 } else {
183 OS << "\" << get" << getUpperName() << "() << \"";
184 }
185 }
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000186 void writeDump(raw_ostream &OS) const {
187 if (type == "FunctionDecl *") {
188 OS << " OS << \" \";\n";
189 OS << " dumpBareDeclRef(SA->get" << getUpperName() << "());\n";
190 } else if (type == "IdentifierInfo *") {
191 OS << " OS << \" \" << SA->get" << getUpperName()
192 << "()->getName();\n";
193 } else if (type == "QualType") {
194 OS << " OS << \" \" << SA->get" << getUpperName()
195 << "().getAsString();\n";
196 } else if (type == "SourceLocation") {
197 OS << " OS << \" \";\n";
198 OS << " SA->get" << getUpperName() << "().print(OS, *SM);\n";
199 } else if (type == "bool") {
200 OS << " if (SA->get" << getUpperName() << "()) OS << \" "
201 << getUpperName() << "\";\n";
202 } else if (type == "int" || type == "unsigned") {
203 OS << " OS << \" \" << SA->get" << getUpperName() << "();\n";
204 } else {
205 llvm_unreachable("Unknown SimpleArgument type!");
206 }
207 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000208 };
209
210 class StringArgument : public Argument {
211 public:
212 StringArgument(Record &Arg, StringRef Attr)
213 : Argument(Arg, Attr)
214 {}
215
216 void writeAccessors(raw_ostream &OS) const {
217 OS << " llvm::StringRef get" << getUpperName() << "() const {\n";
218 OS << " return llvm::StringRef(" << getLowerName() << ", "
219 << getLowerName() << "Length);\n";
220 OS << " }\n";
221 OS << " unsigned get" << getUpperName() << "Length() const {\n";
222 OS << " return " << getLowerName() << "Length;\n";
223 OS << " }\n";
224 OS << " void set" << getUpperName()
225 << "(ASTContext &C, llvm::StringRef S) {\n";
226 OS << " " << getLowerName() << "Length = S.size();\n";
227 OS << " this->" << getLowerName() << " = new (C, 1) char ["
228 << getLowerName() << "Length];\n";
229 OS << " std::memcpy(this->" << getLowerName() << ", S.data(), "
230 << getLowerName() << "Length);\n";
231 OS << " }";
232 }
233 void writeCloneArgs(raw_ostream &OS) const {
234 OS << "get" << getUpperName() << "()";
235 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000236 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
237 OS << "A->get" << getUpperName() << "()";
238 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000239 void writeCtorBody(raw_ostream &OS) const {
240 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
241 << ".data(), " << getLowerName() << "Length);";
242 }
243 void writeCtorInitializers(raw_ostream &OS) const {
244 OS << getLowerName() << "Length(" << getUpperName() << ".size()),"
245 << getLowerName() << "(new (Ctx, 1) char[" << getLowerName()
246 << "Length])";
247 }
248 void writeCtorParameters(raw_ostream &OS) const {
249 OS << "llvm::StringRef " << getUpperName();
250 }
251 void writeDeclarations(raw_ostream &OS) const {
252 OS << "unsigned " << getLowerName() << "Length;\n";
253 OS << "char *" << getLowerName() << ";";
254 }
255 void writePCHReadDecls(raw_ostream &OS) const {
256 OS << " std::string " << getLowerName()
257 << "= ReadString(Record, Idx);\n";
258 }
259 void writePCHReadArgs(raw_ostream &OS) const {
260 OS << getLowerName();
261 }
262 void writePCHWrite(raw_ostream &OS) const {
263 OS << " AddString(SA->get" << getUpperName() << "(), Record);\n";
264 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000265 void writeValue(raw_ostream &OS) const {
266 OS << "\\\"\" << get" << getUpperName() << "() << \"\\\"";
267 }
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000268 void writeDump(raw_ostream &OS) const {
269 OS << " OS << \" \\\"\" << SA->get" << getUpperName()
270 << "() << \"\\\"\";\n";
271 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000272 };
273
274 class AlignedArgument : public Argument {
275 public:
276 AlignedArgument(Record &Arg, StringRef Attr)
277 : Argument(Arg, Attr)
278 {}
279
280 void writeAccessors(raw_ostream &OS) const {
281 OS << " bool is" << getUpperName() << "Dependent() const;\n";
282
283 OS << " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n";
284
285 OS << " bool is" << getUpperName() << "Expr() const {\n";
286 OS << " return is" << getLowerName() << "Expr;\n";
287 OS << " }\n";
288
289 OS << " Expr *get" << getUpperName() << "Expr() const {\n";
290 OS << " assert(is" << getLowerName() << "Expr);\n";
291 OS << " return " << getLowerName() << "Expr;\n";
292 OS << " }\n";
293
294 OS << " TypeSourceInfo *get" << getUpperName() << "Type() const {\n";
295 OS << " assert(!is" << getLowerName() << "Expr);\n";
296 OS << " return " << getLowerName() << "Type;\n";
297 OS << " }";
298 }
299 void writeAccessorDefinitions(raw_ostream &OS) const {
300 OS << "bool " << getAttrName() << "Attr::is" << getUpperName()
301 << "Dependent() const {\n";
302 OS << " if (is" << getLowerName() << "Expr)\n";
303 OS << " return " << getLowerName() << "Expr && (" << getLowerName()
304 << "Expr->isValueDependent() || " << getLowerName()
305 << "Expr->isTypeDependent());\n";
306 OS << " else\n";
307 OS << " return " << getLowerName()
308 << "Type->getType()->isDependentType();\n";
309 OS << "}\n";
310
311 // FIXME: Do not do the calculation here
312 // FIXME: Handle types correctly
313 // A null pointer means maximum alignment
314 // FIXME: Load the platform-specific maximum alignment, rather than
315 // 16, the x86 max.
316 OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName()
317 << "(ASTContext &Ctx) const {\n";
318 OS << " assert(!is" << getUpperName() << "Dependent());\n";
319 OS << " if (is" << getLowerName() << "Expr)\n";
320 OS << " return (" << getLowerName() << "Expr ? " << getLowerName()
Richard Smitha6b8b2c2011-10-10 18:28:20 +0000321 << "Expr->EvaluateKnownConstInt(Ctx).getZExtValue() : 16)"
Peter Collingbourne51d77772011-10-06 13:03:08 +0000322 << "* Ctx.getCharWidth();\n";
323 OS << " else\n";
324 OS << " return 0; // FIXME\n";
325 OS << "}\n";
326 }
327 void writeCloneArgs(raw_ostream &OS) const {
328 OS << "is" << getLowerName() << "Expr, is" << getLowerName()
329 << "Expr ? static_cast<void*>(" << getLowerName()
330 << "Expr) : " << getLowerName()
331 << "Type";
332 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000333 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
334 // FIXME: move the definition in Sema::InstantiateAttrs to here.
335 // In the meantime, aligned attributes are cloned.
336 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000337 void writeCtorBody(raw_ostream &OS) const {
338 OS << " if (is" << getLowerName() << "Expr)\n";
339 OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>("
340 << getUpperName() << ");\n";
341 OS << " else\n";
342 OS << " " << getLowerName()
343 << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName()
344 << ");";
345 }
346 void writeCtorInitializers(raw_ostream &OS) const {
347 OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)";
348 }
349 void writeCtorParameters(raw_ostream &OS) const {
350 OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName();
351 }
352 void writeDeclarations(raw_ostream &OS) const {
353 OS << "bool is" << getLowerName() << "Expr;\n";
354 OS << "union {\n";
355 OS << "Expr *" << getLowerName() << "Expr;\n";
356 OS << "TypeSourceInfo *" << getLowerName() << "Type;\n";
357 OS << "};";
358 }
359 void writePCHReadArgs(raw_ostream &OS) const {
360 OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr";
361 }
362 void writePCHReadDecls(raw_ostream &OS) const {
363 OS << " bool is" << getLowerName() << "Expr = Record[Idx++];\n";
364 OS << " void *" << getLowerName() << "Ptr;\n";
365 OS << " if (is" << getLowerName() << "Expr)\n";
366 OS << " " << getLowerName() << "Ptr = ReadExpr(F);\n";
367 OS << " else\n";
368 OS << " " << getLowerName()
369 << "Ptr = GetTypeSourceInfo(F, Record, Idx);\n";
370 }
371 void writePCHWrite(raw_ostream &OS) const {
372 OS << " Record.push_back(SA->is" << getUpperName() << "Expr());\n";
373 OS << " if (SA->is" << getUpperName() << "Expr())\n";
374 OS << " AddStmt(SA->get" << getUpperName() << "Expr());\n";
375 OS << " else\n";
376 OS << " AddTypeSourceInfo(SA->get" << getUpperName()
377 << "Type(), Record);\n";
378 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000379 void writeValue(raw_ostream &OS) const {
Richard Smith0dae7292012-08-16 02:43:29 +0000380 OS << "\";\n"
381 << " " << getLowerName() << "Expr->printPretty(OS, 0, Policy);\n"
382 << " OS << \"";
Douglas Gregor1bea8802011-11-19 19:22:57 +0000383 }
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000384 void writeDump(raw_ostream &OS) const {
385 }
386 void writeDumpChildren(raw_ostream &OS) const {
387 OS << " if (SA->is" << getUpperName() << "Expr())\n";
388 OS << " dumpStmt(SA->get" << getUpperName() << "Expr());\n";
389 OS << " else\n";
390 OS << " dumpType(SA->get" << getUpperName()
391 << "Type()->getType());\n";
392 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000393 };
394
395 class VariadicArgument : public Argument {
396 std::string type;
397
398 public:
399 VariadicArgument(Record &Arg, StringRef Attr, std::string T)
400 : Argument(Arg, Attr), type(T)
401 {}
402
403 std::string getType() const { return type; }
404
405 void writeAccessors(raw_ostream &OS) const {
406 OS << " typedef " << type << "* " << getLowerName() << "_iterator;\n";
407 OS << " " << getLowerName() << "_iterator " << getLowerName()
408 << "_begin() const {\n";
409 OS << " return " << getLowerName() << ";\n";
410 OS << " }\n";
411 OS << " " << getLowerName() << "_iterator " << getLowerName()
412 << "_end() const {\n";
413 OS << " return " << getLowerName() << " + " << getLowerName()
414 << "Size;\n";
415 OS << " }\n";
416 OS << " unsigned " << getLowerName() << "_size() const {\n"
DeLesley Hutchins23323e02012-01-20 22:50:54 +0000417 << " return " << getLowerName() << "Size;\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000418 OS << " }";
419 }
420 void writeCloneArgs(raw_ostream &OS) const {
421 OS << getLowerName() << ", " << getLowerName() << "Size";
422 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000423 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
424 // This isn't elegant, but we have to go through public methods...
425 OS << "A->" << getLowerName() << "_begin(), "
426 << "A->" << getLowerName() << "_size()";
427 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000428 void writeCtorBody(raw_ostream &OS) const {
429 // FIXME: memcpy is not safe on non-trivial types.
430 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
431 << ", " << getLowerName() << "Size * sizeof(" << getType() << "));\n";
432 }
433 void writeCtorInitializers(raw_ostream &OS) const {
434 OS << getLowerName() << "Size(" << getUpperName() << "Size), "
435 << getLowerName() << "(new (Ctx, 16) " << getType() << "["
436 << getLowerName() << "Size])";
437 }
438 void writeCtorParameters(raw_ostream &OS) const {
439 OS << getType() << " *" << getUpperName() << ", unsigned "
440 << getUpperName() << "Size";
441 }
442 void writeDeclarations(raw_ostream &OS) const {
443 OS << " unsigned " << getLowerName() << "Size;\n";
444 OS << " " << getType() << " *" << getLowerName() << ";";
445 }
446 void writePCHReadDecls(raw_ostream &OS) const {
447 OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +0000448 OS << " SmallVector<" << type << ", 4> " << getLowerName()
Peter Collingbourne51d77772011-10-06 13:03:08 +0000449 << ";\n";
450 OS << " " << getLowerName() << ".reserve(" << getLowerName()
451 << "Size);\n";
452 OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
453
454 std::string read = ReadPCHRecord(type);
455 OS << " " << getLowerName() << ".push_back(" << read << ");\n";
456 }
457 void writePCHReadArgs(raw_ostream &OS) const {
458 OS << getLowerName() << ".data(), " << getLowerName() << "Size";
459 }
460 void writePCHWrite(raw_ostream &OS) const{
461 OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";
462 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
463 << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
464 << getLowerName() << "_end(); i != e; ++i)\n";
465 OS << " " << WritePCHRecord(type, "(*i)");
466 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000467 void writeValue(raw_ostream &OS) const {
468 OS << "\";\n";
469 OS << " bool isFirst = true;\n"
470 << " for (" << getAttrName() << "Attr::" << getLowerName()
471 << "_iterator i = " << getLowerName() << "_begin(), e = "
472 << getLowerName() << "_end(); i != e; ++i) {\n"
473 << " if (isFirst) isFirst = false;\n"
474 << " else OS << \", \";\n"
475 << " OS << *i;\n"
476 << " }\n";
477 OS << " OS << \"";
478 }
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000479 void writeDump(raw_ostream &OS) const {
480 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
481 << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
482 << getLowerName() << "_end(); I != E; ++I)\n";
483 OS << " OS << \" \" << *I;\n";
484 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000485 };
486
487 class EnumArgument : public Argument {
488 std::string type;
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000489 std::vector<StringRef> values, enums, uniques;
Peter Collingbourne51d77772011-10-06 13:03:08 +0000490 public:
491 EnumArgument(Record &Arg, StringRef Attr)
492 : Argument(Arg, Attr), type(Arg.getValueAsString("Type")),
493 values(getValueAsListOfStrings(Arg, "Values")),
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000494 enums(getValueAsListOfStrings(Arg, "Enums")),
495 uniques(enums)
496 {
497 // Calculate the various enum values
498 std::sort(uniques.begin(), uniques.end());
499 uniques.erase(std::unique(uniques.begin(), uniques.end()), uniques.end());
500 // FIXME: Emit a proper error
501 assert(!uniques.empty());
502 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000503
504 void writeAccessors(raw_ostream &OS) const {
505 OS << " " << type << " get" << getUpperName() << "() const {\n";
506 OS << " return " << getLowerName() << ";\n";
507 OS << " }";
508 }
509 void writeCloneArgs(raw_ostream &OS) const {
510 OS << getLowerName();
511 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000512 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
513 OS << "A->get" << getUpperName() << "()";
514 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000515 void writeCtorInitializers(raw_ostream &OS) const {
516 OS << getLowerName() << "(" << getUpperName() << ")";
517 }
518 void writeCtorParameters(raw_ostream &OS) const {
519 OS << type << " " << getUpperName();
520 }
521 void writeDeclarations(raw_ostream &OS) const {
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000522 std::vector<StringRef>::const_iterator i = uniques.begin(),
523 e = uniques.end();
Peter Collingbourne51d77772011-10-06 13:03:08 +0000524 // The last one needs to not have a comma.
525 --e;
526
527 OS << "public:\n";
528 OS << " enum " << type << " {\n";
529 for (; i != e; ++i)
530 OS << " " << *i << ",\n";
531 OS << " " << *e << "\n";
532 OS << " };\n";
533 OS << "private:\n";
534 OS << " " << type << " " << getLowerName() << ";";
535 }
536 void writePCHReadDecls(raw_ostream &OS) const {
537 OS << " " << getAttrName() << "Attr::" << type << " " << getLowerName()
538 << "(static_cast<" << getAttrName() << "Attr::" << type
539 << ">(Record[Idx++]));\n";
540 }
541 void writePCHReadArgs(raw_ostream &OS) const {
542 OS << getLowerName();
543 }
544 void writePCHWrite(raw_ostream &OS) const {
545 OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
546 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000547 void writeValue(raw_ostream &OS) const {
548 OS << "\" << get" << getUpperName() << "() << \"";
549 }
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000550 void writeDump(raw_ostream &OS) const {
551 OS << " switch(SA->get" << getUpperName() << "()) {\n";
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000552 for (std::vector<StringRef>::const_iterator I = uniques.begin(),
553 E = uniques.end(); I != E; ++I) {
554 OS << " case " << getAttrName() << "Attr::" << *I << ":\n";
555 OS << " OS << \" " << *I << "\";\n";
556 OS << " break;\n";
557 }
558 OS << " }\n";
559 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000560 };
561
562 class VersionArgument : public Argument {
563 public:
564 VersionArgument(Record &Arg, StringRef Attr)
565 : Argument(Arg, Attr)
566 {}
567
568 void writeAccessors(raw_ostream &OS) const {
569 OS << " VersionTuple get" << getUpperName() << "() const {\n";
570 OS << " return " << getLowerName() << ";\n";
571 OS << " }\n";
572 OS << " void set" << getUpperName()
573 << "(ASTContext &C, VersionTuple V) {\n";
574 OS << " " << getLowerName() << " = V;\n";
575 OS << " }";
576 }
577 void writeCloneArgs(raw_ostream &OS) const {
578 OS << "get" << getUpperName() << "()";
579 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000580 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
581 OS << "A->get" << getUpperName() << "()";
582 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000583 void writeCtorBody(raw_ostream &OS) const {
584 }
585 void writeCtorInitializers(raw_ostream &OS) const {
586 OS << getLowerName() << "(" << getUpperName() << ")";
587 }
588 void writeCtorParameters(raw_ostream &OS) const {
589 OS << "VersionTuple " << getUpperName();
590 }
591 void writeDeclarations(raw_ostream &OS) const {
592 OS << "VersionTuple " << getLowerName() << ";\n";
593 }
594 void writePCHReadDecls(raw_ostream &OS) const {
595 OS << " VersionTuple " << getLowerName()
596 << "= ReadVersionTuple(Record, Idx);\n";
597 }
598 void writePCHReadArgs(raw_ostream &OS) const {
599 OS << getLowerName();
600 }
601 void writePCHWrite(raw_ostream &OS) const {
602 OS << " AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n";
603 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000604 void writeValue(raw_ostream &OS) const {
605 OS << getLowerName() << "=\" << get" << getUpperName() << "() << \"";
606 }
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000607 void writeDump(raw_ostream &OS) const {
608 OS << " OS << \" \" << SA->get" << getUpperName() << "();\n";
609 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000610 };
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000611
612 class ExprArgument : public SimpleArgument {
613 public:
614 ExprArgument(Record &Arg, StringRef Attr)
615 : SimpleArgument(Arg, Attr, "Expr *")
616 {}
617
618 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
619 OS << "tempInst" << getUpperName();
620 }
621
622 void writeTemplateInstantiation(raw_ostream &OS) const {
623 OS << " " << getType() << " tempInst" << getUpperName() << ";\n";
624 OS << " {\n";
625 OS << " EnterExpressionEvaluationContext "
626 << "Unevaluated(S, Sema::Unevaluated);\n";
627 OS << " ExprResult " << "Result = S.SubstExpr("
628 << "A->get" << getUpperName() << "(), TemplateArgs);\n";
629 OS << " tempInst" << getUpperName() << " = "
630 << "Result.takeAs<Expr>();\n";
631 OS << " }\n";
632 }
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000633
634 void writeDump(raw_ostream &OS) const {
635 }
636
637 void writeDumpChildren(raw_ostream &OS) const {
638 OS << " dumpStmt(SA->get" << getUpperName() << "());\n";
639 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000640 };
641
642 class VariadicExprArgument : public VariadicArgument {
643 public:
644 VariadicExprArgument(Record &Arg, StringRef Attr)
645 : VariadicArgument(Arg, Attr, "Expr *")
646 {}
647
648 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
649 OS << "tempInst" << getUpperName() << ", "
650 << "A->" << getLowerName() << "_size()";
651 }
652
653 void writeTemplateInstantiation(raw_ostream &OS) const {
654 OS << " " << getType() << " *tempInst" << getUpperName()
655 << " = new (C, 16) " << getType()
656 << "[A->" << getLowerName() << "_size()];\n";
657 OS << " {\n";
658 OS << " EnterExpressionEvaluationContext "
659 << "Unevaluated(S, Sema::Unevaluated);\n";
660 OS << " " << getType() << " *TI = tempInst" << getUpperName()
661 << ";\n";
662 OS << " " << getType() << " *I = A->" << getLowerName()
663 << "_begin();\n";
664 OS << " " << getType() << " *E = A->" << getLowerName()
665 << "_end();\n";
666 OS << " for (; I != E; ++I, ++TI) {\n";
667 OS << " ExprResult Result = S.SubstExpr(*I, TemplateArgs);\n";
668 OS << " *TI = Result.takeAs<Expr>();\n";
669 OS << " }\n";
670 OS << " }\n";
671 }
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000672
673 void writeDump(raw_ostream &OS) const {
674 }
675
676 void writeDumpChildren(raw_ostream &OS) const {
677 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
678 << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
679 << getLowerName() << "_end(); I != E; ++I)\n";
680 OS << " dumpStmt(*I);\n";
681 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000682 };
Peter Collingbourne51d77772011-10-06 13:03:08 +0000683}
684
685static Argument *createArgument(Record &Arg, StringRef Attr,
686 Record *Search = 0) {
687 if (!Search)
688 Search = &Arg;
689
690 Argument *Ptr = 0;
691 llvm::StringRef ArgName = Search->getName();
692
693 if (ArgName == "AlignedArgument") Ptr = new AlignedArgument(Arg, Attr);
694 else if (ArgName == "EnumArgument") Ptr = new EnumArgument(Arg, Attr);
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000695 else if (ArgName == "ExprArgument") Ptr = new ExprArgument(Arg, Attr);
Peter Collingbourne51d77772011-10-06 13:03:08 +0000696 else if (ArgName == "FunctionArgument")
697 Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *");
698 else if (ArgName == "IdentifierArgument")
699 Ptr = new SimpleArgument(Arg, Attr, "IdentifierInfo *");
700 else if (ArgName == "BoolArgument") Ptr = new SimpleArgument(Arg, Attr,
701 "bool");
702 else if (ArgName == "IntArgument") Ptr = new SimpleArgument(Arg, Attr, "int");
703 else if (ArgName == "StringArgument") Ptr = new StringArgument(Arg, Attr);
704 else if (ArgName == "TypeArgument")
705 Ptr = new SimpleArgument(Arg, Attr, "QualType");
706 else if (ArgName == "UnsignedArgument")
707 Ptr = new SimpleArgument(Arg, Attr, "unsigned");
708 else if (ArgName == "SourceLocArgument")
709 Ptr = new SimpleArgument(Arg, Attr, "SourceLocation");
710 else if (ArgName == "VariadicUnsignedArgument")
711 Ptr = new VariadicArgument(Arg, Attr, "unsigned");
712 else if (ArgName == "VariadicExprArgument")
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000713 Ptr = new VariadicExprArgument(Arg, Attr);
Peter Collingbourne51d77772011-10-06 13:03:08 +0000714 else if (ArgName == "VersionArgument")
715 Ptr = new VersionArgument(Arg, Attr);
716
717 if (!Ptr) {
718 std::vector<Record*> Bases = Search->getSuperClasses();
719 for (std::vector<Record*>::iterator i = Bases.begin(), e = Bases.end();
720 i != e; ++i) {
721 Ptr = createArgument(Arg, Attr, *i);
722 if (Ptr)
723 break;
724 }
725 }
726 return Ptr;
727}
728
Douglas Gregor1bea8802011-11-19 19:22:57 +0000729static void writeAvailabilityValue(raw_ostream &OS) {
730 OS << "\" << getPlatform()->getName();\n"
731 << " if (!getIntroduced().empty()) OS << \", introduced=\" << getIntroduced();\n"
732 << " if (!getDeprecated().empty()) OS << \", deprecated=\" << getDeprecated();\n"
733 << " if (!getObsoleted().empty()) OS << \", obsoleted=\" << getObsoleted();\n"
734 << " if (getUnavailable()) OS << \", unavailable\";\n"
735 << " OS << \"";
736}
737
Michael Han51d8c522013-01-24 16:46:58 +0000738static void writePrettyPrintFunction(Record &R, std::vector<Argument*> &Args,
739 raw_ostream &OS) {
740 std::vector<Record*> Spellings = R.getValueAsListOfDefs("Spellings");
741
742 OS << "void " << R.getName() << "Attr::printPretty("
743 << "raw_ostream &OS, const PrintingPolicy &Policy) const {\n";
744
745 if (Spellings.size() == 0) {
746 OS << "}\n\n";
747 return;
748 }
749
750 OS <<
751 " switch (SpellingListIndex) {\n"
752 " default:\n"
753 " llvm_unreachable(\"Unknown attribute spelling!\");\n"
754 " break;\n";
755
756 for (unsigned I = 0; I < Spellings.size(); ++ I) {
757 llvm::SmallString<16> Prefix;
758 llvm::SmallString<8> Suffix;
759 // The actual spelling of the name and namespace (if applicable)
760 // of an attribute without considering prefix and suffix.
761 llvm::SmallString<64> Spelling;
762 std::string Name = Spellings[I]->getValueAsString("Name");
763 std::string Variety = Spellings[I]->getValueAsString("Variety");
764
765 if (Variety == "GNU") {
766 Prefix = " __attribute__((";
767 Suffix = "))";
768 } else if (Variety == "CXX11") {
769 Prefix = " [[";
770 Suffix = "]]";
771 std::string Namespace = Spellings[I]->getValueAsString("Namespace");
772 if (Namespace != "") {
773 Spelling += Namespace;
774 Spelling += "::";
775 }
776 } else if (Variety == "Declspec") {
777 Prefix = " __declspec(";
778 Suffix = ")";
Richard Smith5cd532c2013-01-29 01:24:26 +0000779 } else if (Variety == "Keyword") {
780 Prefix = " ";
781 Suffix = "";
Michael Han51d8c522013-01-24 16:46:58 +0000782 } else {
Richard Smith5cd532c2013-01-29 01:24:26 +0000783 llvm_unreachable("Unknown attribute syntax variety!");
Michael Han51d8c522013-01-24 16:46:58 +0000784 }
785
786 Spelling += Name;
787
788 OS <<
789 " case " << I << " : {\n"
790 " OS << \"" + Prefix.str() + Spelling.str();
791
792 if (Args.size()) OS << "(";
793 if (Spelling == "availability") {
794 writeAvailabilityValue(OS);
795 } else {
796 for (std::vector<Argument*>::const_iterator I = Args.begin(),
797 E = Args.end(); I != E; ++ I) {
798 if (I != Args.begin()) OS << ", ";
799 (*I)->writeValue(OS);
800 }
801 }
802
803 if (Args.size()) OS << ")";
804 OS << Suffix.str() + "\";\n";
805
806 OS <<
807 " break;\n"
808 " }\n";
809 }
810
811 // End of the switch statement.
812 OS << "}\n";
813 // End of the print function.
814 OS << "}\n\n";
815}
816
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +0000817namespace clang {
818
819// Emits the class definitions for attributes.
820void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000821 OS << "// This file is generated by TableGen. Do not edit.\n\n";
822 OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
823 OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
824
825 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
826
827 for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
828 i != e; ++i) {
829 Record &R = **i;
Douglas Gregor3e7d31a2012-05-02 15:56:52 +0000830
831 if (!R.getValueAsBit("ASTNode"))
832 continue;
833
Peter Collingbourne51d77772011-10-06 13:03:08 +0000834 const std::string &SuperName = R.getSuperClasses().back()->getName();
835
836 OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n";
837
838 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
839 std::vector<Argument*> Args;
840 std::vector<Argument*>::iterator ai, ae;
841 Args.reserve(ArgRecords.size());
842
843 for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
844 re = ArgRecords.end();
845 ri != re; ++ri) {
846 Record &ArgRecord = **ri;
847 Argument *Arg = createArgument(ArgRecord, R.getName());
848 assert(Arg);
849 Args.push_back(Arg);
850
851 Arg->writeDeclarations(OS);
852 OS << "\n\n";
853 }
854
855 ae = Args.end();
856
857 OS << "\n public:\n";
858 OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
859
860 for (ai = Args.begin(); ai != ae; ++ai) {
861 OS << " , ";
862 (*ai)->writeCtorParameters(OS);
863 OS << "\n";
864 }
Michael Han51d8c522013-01-24 16:46:58 +0000865
866 OS << " , ";
867 OS << "unsigned SI = 0\n";
868
Peter Collingbourne51d77772011-10-06 13:03:08 +0000869 OS << " )\n";
Michael Han51d8c522013-01-24 16:46:58 +0000870 OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000871
872 for (ai = Args.begin(); ai != ae; ++ai) {
873 OS << " , ";
874 (*ai)->writeCtorInitializers(OS);
875 OS << "\n";
876 }
877
878 OS << " {\n";
879
880 for (ai = Args.begin(); ai != ae; ++ai) {
881 (*ai)->writeCtorBody(OS);
882 OS << "\n";
883 }
884 OS << " }\n\n";
885
886 OS << " virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n";
Michael Han7d470532013-01-27 00:06:24 +0000887 OS << " virtual void printPretty(raw_ostream &OS,\n"
Richard Smith0dae7292012-08-16 02:43:29 +0000888 << " const PrintingPolicy &Policy) const;\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000889
890 for (ai = Args.begin(); ai != ae; ++ai) {
891 (*ai)->writeAccessors(OS);
892 OS << "\n\n";
893 }
894
Jakob Stoklund Oleseneb666732012-01-13 04:57:47 +0000895 OS << R.getValueAsString("AdditionalMembers");
Peter Collingbourne51d77772011-10-06 13:03:08 +0000896 OS << "\n\n";
897
898 OS << " static bool classof(const Attr *A) { return A->getKind() == "
899 << "attr::" << R.getName() << "; }\n";
DeLesley Hutchins23323e02012-01-20 22:50:54 +0000900
901 bool LateParsed = R.getValueAsBit("LateParsed");
902 OS << " virtual bool isLateParsed() const { return "
903 << LateParsed << "; }\n";
904
Peter Collingbourne51d77772011-10-06 13:03:08 +0000905 OS << "};\n\n";
906 }
907
908 OS << "#endif\n";
909}
910
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +0000911// Emits the class method definitions for attributes.
912void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000913 OS << "// This file is generated by TableGen. Do not edit.\n\n";
914
915 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
916 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ri, re;
917 std::vector<Argument*>::iterator ai, ae;
918
919 for (; i != e; ++i) {
920 Record &R = **i;
Douglas Gregor3e7d31a2012-05-02 15:56:52 +0000921
922 if (!R.getValueAsBit("ASTNode"))
923 continue;
924
Peter Collingbourne51d77772011-10-06 13:03:08 +0000925 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
926 std::vector<Argument*> Args;
927 for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri)
928 Args.push_back(createArgument(**ri, R.getName()));
929
930 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
931 (*ai)->writeAccessorDefinitions(OS);
932
933 OS << R.getName() << "Attr *" << R.getName()
934 << "Attr::clone(ASTContext &C) const {\n";
935 OS << " return new (C) " << R.getName() << "Attr(getLocation(), C";
936 for (ai = Args.begin(); ai != ae; ++ai) {
937 OS << ", ";
938 (*ai)->writeCloneArgs(OS);
939 }
Richard Smith8f3aacc2013-01-29 04:21:28 +0000940 OS << ", getSpellingListIndex());\n}\n\n";
Douglas Gregor1bea8802011-11-19 19:22:57 +0000941
Michael Han51d8c522013-01-24 16:46:58 +0000942 writePrettyPrintFunction(R, Args, OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +0000943 }
944}
945
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +0000946} // end namespace clang
947
Peter Collingbourne51d77772011-10-06 13:03:08 +0000948static void EmitAttrList(raw_ostream &OS, StringRef Class,
949 const std::vector<Record*> &AttrList) {
950 std::vector<Record*>::const_iterator i = AttrList.begin(), e = AttrList.end();
951
952 if (i != e) {
953 // Move the end iterator back to emit the last attribute.
Douglas Gregor3e7d31a2012-05-02 15:56:52 +0000954 for(--e; i != e; ++i) {
955 if (!(*i)->getValueAsBit("ASTNode"))
956 continue;
957
Peter Collingbourne51d77772011-10-06 13:03:08 +0000958 OS << Class << "(" << (*i)->getName() << ")\n";
Douglas Gregor3e7d31a2012-05-02 15:56:52 +0000959 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000960
961 OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n";
962 }
963}
964
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +0000965namespace clang {
966
967// Emits the enumeration list for attributes.
968void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000969 OS << "// This file is generated by TableGen. Do not edit.\n\n";
970
971 OS << "#ifndef LAST_ATTR\n";
972 OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n";
973 OS << "#endif\n\n";
974
975 OS << "#ifndef INHERITABLE_ATTR\n";
976 OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n";
977 OS << "#endif\n\n";
978
979 OS << "#ifndef LAST_INHERITABLE_ATTR\n";
980 OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n";
981 OS << "#endif\n\n";
982
983 OS << "#ifndef INHERITABLE_PARAM_ATTR\n";
984 OS << "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n";
985 OS << "#endif\n\n";
986
987 OS << "#ifndef LAST_INHERITABLE_PARAM_ATTR\n";
988 OS << "#define LAST_INHERITABLE_PARAM_ATTR(NAME)"
989 " INHERITABLE_PARAM_ATTR(NAME)\n";
990 OS << "#endif\n\n";
991
992 Record *InhClass = Records.getClass("InheritableAttr");
993 Record *InhParamClass = Records.getClass("InheritableParamAttr");
994 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
995 NonInhAttrs, InhAttrs, InhParamAttrs;
996 for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
997 i != e; ++i) {
Douglas Gregor3e7d31a2012-05-02 15:56:52 +0000998 if (!(*i)->getValueAsBit("ASTNode"))
999 continue;
1000
Peter Collingbourne51d77772011-10-06 13:03:08 +00001001 if ((*i)->isSubClassOf(InhParamClass))
1002 InhParamAttrs.push_back(*i);
1003 else if ((*i)->isSubClassOf(InhClass))
1004 InhAttrs.push_back(*i);
1005 else
1006 NonInhAttrs.push_back(*i);
1007 }
1008
1009 EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs);
1010 EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs);
1011 EmitAttrList(OS, "ATTR", NonInhAttrs);
1012
1013 OS << "#undef LAST_ATTR\n";
1014 OS << "#undef INHERITABLE_ATTR\n";
1015 OS << "#undef LAST_INHERITABLE_ATTR\n";
1016 OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n";
1017 OS << "#undef ATTR\n";
1018}
1019
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001020// Emits the code to read an attribute from a precompiled header.
1021void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) {
Peter Collingbourne51d77772011-10-06 13:03:08 +00001022 OS << "// This file is generated by TableGen. Do not edit.\n\n";
1023
1024 Record *InhClass = Records.getClass("InheritableAttr");
1025 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
1026 ArgRecords;
1027 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
1028 std::vector<Argument*> Args;
1029 std::vector<Argument*>::iterator ri, re;
1030
1031 OS << " switch (Kind) {\n";
1032 OS << " default:\n";
1033 OS << " assert(0 && \"Unknown attribute!\");\n";
1034 OS << " break;\n";
1035 for (; i != e; ++i) {
1036 Record &R = **i;
Douglas Gregor3e7d31a2012-05-02 15:56:52 +00001037 if (!R.getValueAsBit("ASTNode"))
1038 continue;
1039
Peter Collingbourne51d77772011-10-06 13:03:08 +00001040 OS << " case attr::" << R.getName() << ": {\n";
1041 if (R.isSubClassOf(InhClass))
1042 OS << " bool isInherited = Record[Idx++];\n";
1043 ArgRecords = R.getValueAsListOfDefs("Args");
1044 Args.clear();
1045 for (ai = ArgRecords.begin(), ae = ArgRecords.end(); ai != ae; ++ai) {
1046 Argument *A = createArgument(**ai, R.getName());
1047 Args.push_back(A);
1048 A->writePCHReadDecls(OS);
1049 }
1050 OS << " New = new (Context) " << R.getName() << "Attr(Range, Context";
1051 for (ri = Args.begin(), re = Args.end(); ri != re; ++ri) {
1052 OS << ", ";
1053 (*ri)->writePCHReadArgs(OS);
1054 }
1055 OS << ");\n";
1056 if (R.isSubClassOf(InhClass))
1057 OS << " cast<InheritableAttr>(New)->setInherited(isInherited);\n";
1058 OS << " break;\n";
1059 OS << " }\n";
1060 }
1061 OS << " }\n";
1062}
1063
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001064// Emits the code to write an attribute to a precompiled header.
1065void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) {
Peter Collingbourne51d77772011-10-06 13:03:08 +00001066 Record *InhClass = Records.getClass("InheritableAttr");
1067 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
1068 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
1069
1070 OS << " switch (A->getKind()) {\n";
1071 OS << " default:\n";
1072 OS << " llvm_unreachable(\"Unknown attribute kind!\");\n";
1073 OS << " break;\n";
1074 for (; i != e; ++i) {
1075 Record &R = **i;
Douglas Gregor3e7d31a2012-05-02 15:56:52 +00001076 if (!R.getValueAsBit("ASTNode"))
1077 continue;
Peter Collingbourne51d77772011-10-06 13:03:08 +00001078 OS << " case attr::" << R.getName() << ": {\n";
1079 Args = R.getValueAsListOfDefs("Args");
1080 if (R.isSubClassOf(InhClass) || !Args.empty())
1081 OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
1082 << "Attr>(A);\n";
1083 if (R.isSubClassOf(InhClass))
1084 OS << " Record.push_back(SA->isInherited());\n";
1085 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
1086 createArgument(**ai, R.getName())->writePCHWrite(OS);
1087 OS << " break;\n";
1088 OS << " }\n";
1089 }
1090 OS << " }\n";
1091}
1092
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001093// Emits the list of spellings for attributes.
1094void EmitClangAttrSpellingList(RecordKeeper &Records, raw_ostream &OS) {
Peter Collingbourne51d77772011-10-06 13:03:08 +00001095 OS << "// This file is generated by TableGen. Do not edit.\n\n";
1096
1097 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1098
1099 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) {
1100 Record &Attr = **I;
1101
Sean Hunt8e083e72012-06-19 23:57:03 +00001102 std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
Peter Collingbourne51d77772011-10-06 13:03:08 +00001103
Sean Hunt8e083e72012-06-19 23:57:03 +00001104 for (std::vector<Record*>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) {
1105 OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", true)\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +00001106 }
1107 }
1108
1109}
1110
Michael Han51d8c522013-01-24 16:46:58 +00001111void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) {
1112 OS << "// This file is generated by TableGen. Do not edit it. \n\n";
1113
1114 OS <<
1115 " unsigned Index = 0;\n"
1116 " switch (AttrKind) {\n"
1117 " default:\n"
1118 " llvm_unreachable(\"Unknown attribute kind!\");\n"
1119 " break;\n";
1120
1121 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1122 for (std::vector<Record*>::const_iterator I = Attrs.begin(), E = Attrs.end();
1123 I != E; ++I) {
1124 Record &R = **I;
1125 // We only care about attributes that participate in Sema checking, so
1126 // skip those attributes that are not able to make their way to Sema.
1127 if (!R.getValueAsBit("SemaHandler"))
1128 continue;
1129
1130 std::vector<Record*> Spellings = R.getValueAsListOfDefs("Spellings");
1131 // Each distinct spelling yields an attribute kind.
1132 if (R.getValueAsBit("DistinctSpellings")) {
1133 for (unsigned I = 0; I < Spellings.size(); ++ I) {
1134 OS <<
1135 " case AT_" << Spellings[I]->getValueAsString("Name") << ": \n"
1136 " Index = " << I << ";\n"
1137 " break;\n";
1138 }
1139 } else {
1140 OS << " case AT_" << R.getName() << " : {\n";
1141 for (unsigned I = 0; I < Spellings.size(); ++ I) {
1142 SmallString<16> Namespace;
1143 if (Spellings[I]->getValueAsString("Variety") == "CXX11")
1144 Namespace = Spellings[I]->getValueAsString("Namespace");
1145 else
1146 Namespace = "";
1147
1148 OS << " if (Name == \""
1149 << Spellings[I]->getValueAsString("Name") << "\" && "
1150 << "SyntaxUsed == "
1151 << StringSwitch<unsigned>(Spellings[I]->getValueAsString("Variety"))
1152 .Case("GNU", 0)
1153 .Case("CXX11", 1)
1154 .Case("Declspec", 2)
Richard Smith5cd532c2013-01-29 01:24:26 +00001155 .Case("Keyword", 3)
Michael Han51d8c522013-01-24 16:46:58 +00001156 .Default(0)
1157 << " && Scope == \"" << Namespace << "\")\n"
1158 << " return " << I << ";\n";
1159 }
1160
1161 OS << " break;\n";
1162 OS << " }\n";
1163 }
1164 }
1165
1166 OS << " }\n";
1167 OS << " return Index;\n";
1168}
1169
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001170// Emits the LateParsed property for attributes.
1171void EmitClangAttrLateParsedList(RecordKeeper &Records, raw_ostream &OS) {
Peter Collingbourne51d77772011-10-06 13:03:08 +00001172 OS << "// This file is generated by TableGen. Do not edit.\n\n";
1173
1174 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1175
1176 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1177 I != E; ++I) {
1178 Record &Attr = **I;
1179
1180 bool LateParsed = Attr.getValueAsBit("LateParsed");
1181
1182 if (LateParsed) {
Sean Hunt8e083e72012-06-19 23:57:03 +00001183 std::vector<Record*> Spellings =
1184 Attr.getValueAsListOfDefs("Spellings");
Peter Collingbourne51d77772011-10-06 13:03:08 +00001185
Sean Hunt8e083e72012-06-19 23:57:03 +00001186 // FIXME: Handle non-GNU attributes
1187 for (std::vector<Record*>::const_iterator I = Spellings.begin(),
Peter Collingbourne51d77772011-10-06 13:03:08 +00001188 E = Spellings.end(); I != E; ++I) {
Sean Hunt8e083e72012-06-19 23:57:03 +00001189 if ((*I)->getValueAsString("Variety") != "GNU")
1190 continue;
1191 OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", "
1192 << LateParsed << ")\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +00001193 }
1194 }
1195 }
1196}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001197
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001198// Emits code to instantiate dependent attributes on templates.
1199void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001200 OS << "// This file is generated by TableGen. Do not edit.\n\n";
1201
1202 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1203
Benjamin Kramer5bbc3852012-02-06 11:13:08 +00001204 OS << "namespace clang {\n"
1205 << "namespace sema {\n\n"
1206 << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, "
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001207 << "Sema &S,\n"
1208 << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n"
1209 << " switch (At->getKind()) {\n"
1210 << " default:\n"
1211 << " break;\n";
1212
1213 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1214 I != E; ++I) {
1215 Record &R = **I;
Douglas Gregor3e7d31a2012-05-02 15:56:52 +00001216 if (!R.getValueAsBit("ASTNode"))
1217 continue;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001218
1219 OS << " case attr::" << R.getName() << ": {\n";
Rafael Espindola31c195a2012-05-15 14:09:55 +00001220 bool ShouldClone = R.getValueAsBit("Clone");
1221
1222 if (!ShouldClone) {
1223 OS << " return NULL;\n";
1224 OS << " }\n";
1225 continue;
1226 }
1227
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001228 OS << " const " << R.getName() << "Attr *A = cast<"
1229 << R.getName() << "Attr>(At);\n";
1230 bool TDependent = R.getValueAsBit("TemplateDependent");
1231
1232 if (!TDependent) {
1233 OS << " return A->clone(C);\n";
1234 OS << " }\n";
1235 continue;
1236 }
1237
1238 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
1239 std::vector<Argument*> Args;
1240 std::vector<Argument*>::iterator ai, ae;
1241 Args.reserve(ArgRecords.size());
1242
1243 for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
1244 re = ArgRecords.end();
1245 ri != re; ++ri) {
1246 Record &ArgRecord = **ri;
1247 Argument *Arg = createArgument(ArgRecord, R.getName());
1248 assert(Arg);
1249 Args.push_back(Arg);
1250 }
1251 ae = Args.end();
1252
1253 for (ai = Args.begin(); ai != ae; ++ai) {
1254 (*ai)->writeTemplateInstantiation(OS);
1255 }
1256 OS << " return new (C) " << R.getName() << "Attr(A->getLocation(), C";
1257 for (ai = Args.begin(); ai != ae; ++ai) {
1258 OS << ", ";
1259 (*ai)->writeTemplateInstantiationArgs(OS);
1260 }
1261 OS << ");\n }\n";
1262 }
1263 OS << " } // end switch\n"
1264 << " llvm_unreachable(\"Unknown attribute!\");\n"
1265 << " return 0;\n"
Benjamin Kramer5bbc3852012-02-06 11:13:08 +00001266 << "}\n\n"
1267 << "} // end namespace sema\n"
1268 << "} // end namespace clang\n";
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001269}
1270
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001271// Emits the list of parsed attributes.
1272void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) {
Michael Hane53ac8a2012-03-07 00:12:16 +00001273 OS << "// This file is generated by TableGen. Do not edit.\n\n";
1274
1275 OS << "#ifndef PARSED_ATTR\n";
1276 OS << "#define PARSED_ATTR(NAME) NAME\n";
1277 OS << "#endif\n\n";
1278
1279 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
Michael Hane53ac8a2012-03-07 00:12:16 +00001280
1281 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1282 I != E; ++I) {
1283 Record &Attr = **I;
1284
1285 bool SemaHandler = Attr.getValueAsBit("SemaHandler");
Douglas Gregor703d4122012-05-11 23:37:49 +00001286 bool DistinctSpellings = Attr.getValueAsBit("DistinctSpellings");
1287
Michael Hane53ac8a2012-03-07 00:12:16 +00001288 if (SemaHandler) {
Sean Hunt8e083e72012-06-19 23:57:03 +00001289 if (DistinctSpellings) {
1290 std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
Jakob Stoklund Olesen35329362012-06-19 21:48:43 +00001291
Sean Hunt8e083e72012-06-19 23:57:03 +00001292 for (std::vector<Record*>::const_iterator I = Spellings.begin(),
1293 E = Spellings.end(); I != E; ++I) {
1294 std::string AttrName = (*I)->getValueAsString("Name");
1295
1296 StringRef Spelling = NormalizeAttrName(AttrName);
1297
1298 OS << "PARSED_ATTR(" << Spelling << ")\n";
1299 }
1300 } else {
1301 StringRef AttrName = Attr.getName();
1302 AttrName = NormalizeAttrName(AttrName);
1303 OS << "PARSED_ATTR(" << AttrName << ")\n";
Michael Hane53ac8a2012-03-07 00:12:16 +00001304 }
1305 }
1306 }
1307}
1308
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001309// Emits the kind list of parsed attributes
1310void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
Michael Hane53ac8a2012-03-07 00:12:16 +00001311 OS << "// This file is generated by TableGen. Do not edit.\n\n";
Douglas Gregor0c19b3c2012-05-02 17:33:51 +00001312 OS << "\n";
1313
Michael Hane53ac8a2012-03-07 00:12:16 +00001314 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1315
Douglas Gregor0c19b3c2012-05-02 17:33:51 +00001316 std::vector<StringMatcher::StringPair> Matches;
Michael Hane53ac8a2012-03-07 00:12:16 +00001317 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1318 I != E; ++I) {
1319 Record &Attr = **I;
1320
1321 bool SemaHandler = Attr.getValueAsBit("SemaHandler");
Douglas Gregor331d2ec2012-05-02 16:18:45 +00001322 bool Ignored = Attr.getValueAsBit("Ignored");
Douglas Gregor703d4122012-05-11 23:37:49 +00001323 bool DistinctSpellings = Attr.getValueAsBit("DistinctSpellings");
Douglas Gregor331d2ec2012-05-02 16:18:45 +00001324 if (SemaHandler || Ignored) {
Sean Hunt8e083e72012-06-19 23:57:03 +00001325 std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
Michael Hane53ac8a2012-03-07 00:12:16 +00001326
Sean Hunt8e083e72012-06-19 23:57:03 +00001327 for (std::vector<Record*>::const_iterator I = Spellings.begin(),
Michael Hane53ac8a2012-03-07 00:12:16 +00001328 E = Spellings.end(); I != E; ++I) {
Sean Hunt8e083e72012-06-19 23:57:03 +00001329 std::string RawSpelling = (*I)->getValueAsString("Name");
Douglas Gregor703d4122012-05-11 23:37:49 +00001330 StringRef AttrName = NormalizeAttrName(DistinctSpellings
Sean Hunt8e083e72012-06-19 23:57:03 +00001331 ? StringRef(RawSpelling)
1332 : StringRef(Attr.getName()));
Michael Hane53ac8a2012-03-07 00:12:16 +00001333
Sean Hunt8e083e72012-06-19 23:57:03 +00001334 SmallString<64> Spelling;
1335 if ((*I)->getValueAsString("Variety") == "CXX11") {
1336 Spelling += (*I)->getValueAsString("Namespace");
1337 Spelling += "::";
Sean Hunt93f95f22012-06-18 16:13:52 +00001338 }
Sean Hunt8e083e72012-06-19 23:57:03 +00001339 Spelling += NormalizeAttrSpelling(RawSpelling);
Sean Hunt93f95f22012-06-18 16:13:52 +00001340
Douglas Gregor331d2ec2012-05-02 16:18:45 +00001341 if (SemaHandler)
Douglas Gregor0c19b3c2012-05-02 17:33:51 +00001342 Matches.push_back(
Douglas Gregor703d4122012-05-11 23:37:49 +00001343 StringMatcher::StringPair(
Sean Hunt8e083e72012-06-19 23:57:03 +00001344 StringRef(Spelling),
Sean Hunt93f95f22012-06-18 16:13:52 +00001345 "return AttributeList::AT_" + AttrName.str() + ";"));
Douglas Gregor331d2ec2012-05-02 16:18:45 +00001346 else
Douglas Gregor0c19b3c2012-05-02 17:33:51 +00001347 Matches.push_back(
1348 StringMatcher::StringPair(
Sean Hunt8e083e72012-06-19 23:57:03 +00001349 StringRef(Spelling),
Sean Hunt93f95f22012-06-18 16:13:52 +00001350 "return AttributeList::IgnoredAttribute;"));
Michael Hane53ac8a2012-03-07 00:12:16 +00001351 }
1352 }
1353 }
Douglas Gregor0c19b3c2012-05-02 17:33:51 +00001354
1355 OS << "static AttributeList::Kind getAttrKind(StringRef Name) {\n";
1356 StringMatcher("Name", Matches, OS).Emit();
1357 OS << "return AttributeList::UnknownAttribute;\n"
1358 << "}\n";
Michael Hane53ac8a2012-03-07 00:12:16 +00001359}
1360
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +00001361// Emits the code to dump an attribute.
1362void EmitClangAttrDump(RecordKeeper &Records, raw_ostream &OS) {
1363 OS <<
1364 " switch (A->getKind()) {\n"
1365 " default:\n"
1366 " llvm_unreachable(\"Unknown attribute kind!\");\n"
1367 " break;\n";
1368 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
1369 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1370 I != E; ++I) {
1371 Record &R = **I;
1372 if (!R.getValueAsBit("ASTNode"))
1373 continue;
1374 OS << " case attr::" << R.getName() << ": {\n";
1375 Args = R.getValueAsListOfDefs("Args");
1376 if (!Args.empty()) {
1377 OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
1378 << "Attr>(A);\n";
1379 for (std::vector<Record*>::iterator I = Args.begin(), E = Args.end();
1380 I != E; ++I)
1381 createArgument(**I, R.getName())->writeDump(OS);
1382 for (std::vector<Record*>::iterator I = Args.begin(), E = Args.end();
1383 I != E; ++I)
1384 createArgument(**I, R.getName())->writeDumpChildren(OS);
1385 }
1386 OS <<
1387 " break;\n"
1388 " }\n";
1389 }
1390 OS << " }\n";
1391}
1392
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001393} // end namespace clang