blob: 3982fc3f31c28f131dd86a24c790b22d3f8d1e36 [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 {}
Richard Trieue8d41192013-01-31 01:44:26 +0000130 virtual void writeHasChildren(raw_ostream &OS) const { OS << "false"; }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000131 };
132
133 class SimpleArgument : public Argument {
134 std::string type;
135
136 public:
137 SimpleArgument(Record &Arg, StringRef Attr, std::string T)
138 : Argument(Arg, Attr), type(T)
139 {}
140
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000141 std::string getType() const { return type; }
142
Peter Collingbourne51d77772011-10-06 13:03:08 +0000143 void writeAccessors(raw_ostream &OS) const {
144 OS << " " << type << " get" << getUpperName() << "() const {\n";
145 OS << " return " << getLowerName() << ";\n";
146 OS << " }";
147 }
148 void writeCloneArgs(raw_ostream &OS) const {
149 OS << getLowerName();
150 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000151 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
152 OS << "A->get" << getUpperName() << "()";
153 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000154 void writeCtorInitializers(raw_ostream &OS) const {
155 OS << getLowerName() << "(" << getUpperName() << ")";
156 }
157 void writeCtorParameters(raw_ostream &OS) const {
158 OS << type << " " << getUpperName();
159 }
160 void writeDeclarations(raw_ostream &OS) const {
161 OS << type << " " << getLowerName() << ";";
162 }
163 void writePCHReadDecls(raw_ostream &OS) const {
164 std::string read = ReadPCHRecord(type);
165 OS << " " << type << " " << getLowerName() << " = " << read << ";\n";
166 }
167 void writePCHReadArgs(raw_ostream &OS) const {
168 OS << getLowerName();
169 }
170 void writePCHWrite(raw_ostream &OS) const {
171 OS << " " << WritePCHRecord(type, "SA->get" +
172 std::string(getUpperName()) + "()");
173 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000174 void writeValue(raw_ostream &OS) const {
175 if (type == "FunctionDecl *") {
176 OS << "\" << get" << getUpperName() << "()->getNameInfo().getAsString() << \"";
177 } else if (type == "IdentifierInfo *") {
178 OS << "\" << get" << getUpperName() << "()->getName() << \"";
179 } else if (type == "QualType") {
180 OS << "\" << get" << getUpperName() << "().getAsString() << \"";
181 } else if (type == "SourceLocation") {
182 OS << "\" << get" << getUpperName() << "().getRawEncoding() << \"";
183 } else {
184 OS << "\" << get" << getUpperName() << "() << \"";
185 }
186 }
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000187 void writeDump(raw_ostream &OS) const {
188 if (type == "FunctionDecl *") {
189 OS << " OS << \" \";\n";
190 OS << " dumpBareDeclRef(SA->get" << getUpperName() << "());\n";
191 } else if (type == "IdentifierInfo *") {
192 OS << " OS << \" \" << SA->get" << getUpperName()
193 << "()->getName();\n";
194 } else if (type == "QualType") {
195 OS << " OS << \" \" << SA->get" << getUpperName()
196 << "().getAsString();\n";
197 } else if (type == "SourceLocation") {
198 OS << " OS << \" \";\n";
199 OS << " SA->get" << getUpperName() << "().print(OS, *SM);\n";
200 } else if (type == "bool") {
201 OS << " if (SA->get" << getUpperName() << "()) OS << \" "
202 << getUpperName() << "\";\n";
203 } else if (type == "int" || type == "unsigned") {
204 OS << " OS << \" \" << SA->get" << getUpperName() << "();\n";
205 } else {
206 llvm_unreachable("Unknown SimpleArgument type!");
207 }
208 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000209 };
210
211 class StringArgument : public Argument {
212 public:
213 StringArgument(Record &Arg, StringRef Attr)
214 : Argument(Arg, Attr)
215 {}
216
217 void writeAccessors(raw_ostream &OS) const {
218 OS << " llvm::StringRef get" << getUpperName() << "() const {\n";
219 OS << " return llvm::StringRef(" << getLowerName() << ", "
220 << getLowerName() << "Length);\n";
221 OS << " }\n";
222 OS << " unsigned get" << getUpperName() << "Length() const {\n";
223 OS << " return " << getLowerName() << "Length;\n";
224 OS << " }\n";
225 OS << " void set" << getUpperName()
226 << "(ASTContext &C, llvm::StringRef S) {\n";
227 OS << " " << getLowerName() << "Length = S.size();\n";
228 OS << " this->" << getLowerName() << " = new (C, 1) char ["
229 << getLowerName() << "Length];\n";
230 OS << " std::memcpy(this->" << getLowerName() << ", S.data(), "
231 << getLowerName() << "Length);\n";
232 OS << " }";
233 }
234 void writeCloneArgs(raw_ostream &OS) const {
235 OS << "get" << getUpperName() << "()";
236 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000237 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
238 OS << "A->get" << getUpperName() << "()";
239 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000240 void writeCtorBody(raw_ostream &OS) const {
241 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
242 << ".data(), " << getLowerName() << "Length);";
243 }
244 void writeCtorInitializers(raw_ostream &OS) const {
245 OS << getLowerName() << "Length(" << getUpperName() << ".size()),"
246 << getLowerName() << "(new (Ctx, 1) char[" << getLowerName()
247 << "Length])";
248 }
249 void writeCtorParameters(raw_ostream &OS) const {
250 OS << "llvm::StringRef " << getUpperName();
251 }
252 void writeDeclarations(raw_ostream &OS) const {
253 OS << "unsigned " << getLowerName() << "Length;\n";
254 OS << "char *" << getLowerName() << ";";
255 }
256 void writePCHReadDecls(raw_ostream &OS) const {
257 OS << " std::string " << getLowerName()
258 << "= ReadString(Record, Idx);\n";
259 }
260 void writePCHReadArgs(raw_ostream &OS) const {
261 OS << getLowerName();
262 }
263 void writePCHWrite(raw_ostream &OS) const {
264 OS << " AddString(SA->get" << getUpperName() << "(), Record);\n";
265 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000266 void writeValue(raw_ostream &OS) const {
267 OS << "\\\"\" << get" << getUpperName() << "() << \"\\\"";
268 }
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000269 void writeDump(raw_ostream &OS) const {
270 OS << " OS << \" \\\"\" << SA->get" << getUpperName()
271 << "() << \"\\\"\";\n";
272 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000273 };
274
275 class AlignedArgument : public Argument {
276 public:
277 AlignedArgument(Record &Arg, StringRef Attr)
278 : Argument(Arg, Attr)
279 {}
280
281 void writeAccessors(raw_ostream &OS) const {
282 OS << " bool is" << getUpperName() << "Dependent() const;\n";
283
284 OS << " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n";
285
286 OS << " bool is" << getUpperName() << "Expr() const {\n";
287 OS << " return is" << getLowerName() << "Expr;\n";
288 OS << " }\n";
289
290 OS << " Expr *get" << getUpperName() << "Expr() const {\n";
291 OS << " assert(is" << getLowerName() << "Expr);\n";
292 OS << " return " << getLowerName() << "Expr;\n";
293 OS << " }\n";
294
295 OS << " TypeSourceInfo *get" << getUpperName() << "Type() const {\n";
296 OS << " assert(!is" << getLowerName() << "Expr);\n";
297 OS << " return " << getLowerName() << "Type;\n";
298 OS << " }";
299 }
300 void writeAccessorDefinitions(raw_ostream &OS) const {
301 OS << "bool " << getAttrName() << "Attr::is" << getUpperName()
302 << "Dependent() const {\n";
303 OS << " if (is" << getLowerName() << "Expr)\n";
304 OS << " return " << getLowerName() << "Expr && (" << getLowerName()
305 << "Expr->isValueDependent() || " << getLowerName()
306 << "Expr->isTypeDependent());\n";
307 OS << " else\n";
308 OS << " return " << getLowerName()
309 << "Type->getType()->isDependentType();\n";
310 OS << "}\n";
311
312 // FIXME: Do not do the calculation here
313 // FIXME: Handle types correctly
314 // A null pointer means maximum alignment
315 // FIXME: Load the platform-specific maximum alignment, rather than
316 // 16, the x86 max.
317 OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName()
318 << "(ASTContext &Ctx) const {\n";
319 OS << " assert(!is" << getUpperName() << "Dependent());\n";
320 OS << " if (is" << getLowerName() << "Expr)\n";
321 OS << " return (" << getLowerName() << "Expr ? " << getLowerName()
Richard Smitha6b8b2c2011-10-10 18:28:20 +0000322 << "Expr->EvaluateKnownConstInt(Ctx).getZExtValue() : 16)"
Peter Collingbourne51d77772011-10-06 13:03:08 +0000323 << "* Ctx.getCharWidth();\n";
324 OS << " else\n";
325 OS << " return 0; // FIXME\n";
326 OS << "}\n";
327 }
328 void writeCloneArgs(raw_ostream &OS) const {
329 OS << "is" << getLowerName() << "Expr, is" << getLowerName()
330 << "Expr ? static_cast<void*>(" << getLowerName()
331 << "Expr) : " << getLowerName()
332 << "Type";
333 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000334 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
335 // FIXME: move the definition in Sema::InstantiateAttrs to here.
336 // In the meantime, aligned attributes are cloned.
337 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000338 void writeCtorBody(raw_ostream &OS) const {
339 OS << " if (is" << getLowerName() << "Expr)\n";
340 OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>("
341 << getUpperName() << ");\n";
342 OS << " else\n";
343 OS << " " << getLowerName()
344 << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName()
345 << ");";
346 }
347 void writeCtorInitializers(raw_ostream &OS) const {
348 OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)";
349 }
350 void writeCtorParameters(raw_ostream &OS) const {
351 OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName();
352 }
353 void writeDeclarations(raw_ostream &OS) const {
354 OS << "bool is" << getLowerName() << "Expr;\n";
355 OS << "union {\n";
356 OS << "Expr *" << getLowerName() << "Expr;\n";
357 OS << "TypeSourceInfo *" << getLowerName() << "Type;\n";
358 OS << "};";
359 }
360 void writePCHReadArgs(raw_ostream &OS) const {
361 OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr";
362 }
363 void writePCHReadDecls(raw_ostream &OS) const {
364 OS << " bool is" << getLowerName() << "Expr = Record[Idx++];\n";
365 OS << " void *" << getLowerName() << "Ptr;\n";
366 OS << " if (is" << getLowerName() << "Expr)\n";
367 OS << " " << getLowerName() << "Ptr = ReadExpr(F);\n";
368 OS << " else\n";
369 OS << " " << getLowerName()
370 << "Ptr = GetTypeSourceInfo(F, Record, Idx);\n";
371 }
372 void writePCHWrite(raw_ostream &OS) const {
373 OS << " Record.push_back(SA->is" << getUpperName() << "Expr());\n";
374 OS << " if (SA->is" << getUpperName() << "Expr())\n";
375 OS << " AddStmt(SA->get" << getUpperName() << "Expr());\n";
376 OS << " else\n";
377 OS << " AddTypeSourceInfo(SA->get" << getUpperName()
378 << "Type(), Record);\n";
379 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000380 void writeValue(raw_ostream &OS) const {
Richard Smith0dae7292012-08-16 02:43:29 +0000381 OS << "\";\n"
382 << " " << getLowerName() << "Expr->printPretty(OS, 0, Policy);\n"
383 << " OS << \"";
Douglas Gregor1bea8802011-11-19 19:22:57 +0000384 }
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000385 void writeDump(raw_ostream &OS) const {
386 }
387 void writeDumpChildren(raw_ostream &OS) const {
Richard Trieue8d41192013-01-31 01:44:26 +0000388 OS << " if (SA->is" << getUpperName() << "Expr()) {\n";
389 OS << " lastChild();\n";
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000390 OS << " dumpStmt(SA->get" << getUpperName() << "Expr());\n";
Richard Trieue8d41192013-01-31 01:44:26 +0000391 OS << " } else\n";
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000392 OS << " dumpType(SA->get" << getUpperName()
393 << "Type()->getType());\n";
394 }
Richard Trieue8d41192013-01-31 01:44:26 +0000395 void writeHasChildren(raw_ostream &OS) const {
396 OS << "SA->is" << getUpperName() << "Expr()";
397 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000398 };
399
400 class VariadicArgument : public Argument {
401 std::string type;
402
403 public:
404 VariadicArgument(Record &Arg, StringRef Attr, std::string T)
405 : Argument(Arg, Attr), type(T)
406 {}
407
408 std::string getType() const { return type; }
409
410 void writeAccessors(raw_ostream &OS) const {
411 OS << " typedef " << type << "* " << getLowerName() << "_iterator;\n";
412 OS << " " << getLowerName() << "_iterator " << getLowerName()
413 << "_begin() const {\n";
414 OS << " return " << getLowerName() << ";\n";
415 OS << " }\n";
416 OS << " " << getLowerName() << "_iterator " << getLowerName()
417 << "_end() const {\n";
418 OS << " return " << getLowerName() << " + " << getLowerName()
419 << "Size;\n";
420 OS << " }\n";
421 OS << " unsigned " << getLowerName() << "_size() const {\n"
DeLesley Hutchins23323e02012-01-20 22:50:54 +0000422 << " return " << getLowerName() << "Size;\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000423 OS << " }";
424 }
425 void writeCloneArgs(raw_ostream &OS) const {
426 OS << getLowerName() << ", " << getLowerName() << "Size";
427 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000428 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
429 // This isn't elegant, but we have to go through public methods...
430 OS << "A->" << getLowerName() << "_begin(), "
431 << "A->" << getLowerName() << "_size()";
432 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000433 void writeCtorBody(raw_ostream &OS) const {
434 // FIXME: memcpy is not safe on non-trivial types.
435 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
436 << ", " << getLowerName() << "Size * sizeof(" << getType() << "));\n";
437 }
438 void writeCtorInitializers(raw_ostream &OS) const {
439 OS << getLowerName() << "Size(" << getUpperName() << "Size), "
440 << getLowerName() << "(new (Ctx, 16) " << getType() << "["
441 << getLowerName() << "Size])";
442 }
443 void writeCtorParameters(raw_ostream &OS) const {
444 OS << getType() << " *" << getUpperName() << ", unsigned "
445 << getUpperName() << "Size";
446 }
447 void writeDeclarations(raw_ostream &OS) const {
448 OS << " unsigned " << getLowerName() << "Size;\n";
449 OS << " " << getType() << " *" << getLowerName() << ";";
450 }
451 void writePCHReadDecls(raw_ostream &OS) const {
452 OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +0000453 OS << " SmallVector<" << type << ", 4> " << getLowerName()
Peter Collingbourne51d77772011-10-06 13:03:08 +0000454 << ";\n";
455 OS << " " << getLowerName() << ".reserve(" << getLowerName()
456 << "Size);\n";
457 OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
458
459 std::string read = ReadPCHRecord(type);
460 OS << " " << getLowerName() << ".push_back(" << read << ");\n";
461 }
462 void writePCHReadArgs(raw_ostream &OS) const {
463 OS << getLowerName() << ".data(), " << getLowerName() << "Size";
464 }
465 void writePCHWrite(raw_ostream &OS) const{
466 OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";
467 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
468 << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
469 << getLowerName() << "_end(); i != e; ++i)\n";
470 OS << " " << WritePCHRecord(type, "(*i)");
471 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000472 void writeValue(raw_ostream &OS) const {
473 OS << "\";\n";
474 OS << " bool isFirst = true;\n"
475 << " for (" << getAttrName() << "Attr::" << getLowerName()
476 << "_iterator i = " << getLowerName() << "_begin(), e = "
477 << getLowerName() << "_end(); i != e; ++i) {\n"
478 << " if (isFirst) isFirst = false;\n"
479 << " else OS << \", \";\n"
480 << " OS << *i;\n"
481 << " }\n";
482 OS << " OS << \"";
483 }
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000484 void writeDump(raw_ostream &OS) const {
485 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
486 << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
487 << getLowerName() << "_end(); I != E; ++I)\n";
488 OS << " OS << \" \" << *I;\n";
489 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000490 };
491
492 class EnumArgument : public Argument {
493 std::string type;
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000494 std::vector<StringRef> values, enums, uniques;
Peter Collingbourne51d77772011-10-06 13:03:08 +0000495 public:
496 EnumArgument(Record &Arg, StringRef Attr)
497 : Argument(Arg, Attr), type(Arg.getValueAsString("Type")),
498 values(getValueAsListOfStrings(Arg, "Values")),
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000499 enums(getValueAsListOfStrings(Arg, "Enums")),
500 uniques(enums)
501 {
502 // Calculate the various enum values
503 std::sort(uniques.begin(), uniques.end());
504 uniques.erase(std::unique(uniques.begin(), uniques.end()), uniques.end());
505 // FIXME: Emit a proper error
506 assert(!uniques.empty());
507 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000508
509 void writeAccessors(raw_ostream &OS) const {
510 OS << " " << type << " get" << getUpperName() << "() const {\n";
511 OS << " return " << getLowerName() << ";\n";
512 OS << " }";
513 }
514 void writeCloneArgs(raw_ostream &OS) const {
515 OS << getLowerName();
516 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000517 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
518 OS << "A->get" << getUpperName() << "()";
519 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000520 void writeCtorInitializers(raw_ostream &OS) const {
521 OS << getLowerName() << "(" << getUpperName() << ")";
522 }
523 void writeCtorParameters(raw_ostream &OS) const {
524 OS << type << " " << getUpperName();
525 }
526 void writeDeclarations(raw_ostream &OS) const {
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000527 std::vector<StringRef>::const_iterator i = uniques.begin(),
528 e = uniques.end();
Peter Collingbourne51d77772011-10-06 13:03:08 +0000529 // The last one needs to not have a comma.
530 --e;
531
532 OS << "public:\n";
533 OS << " enum " << type << " {\n";
534 for (; i != e; ++i)
535 OS << " " << *i << ",\n";
536 OS << " " << *e << "\n";
537 OS << " };\n";
538 OS << "private:\n";
539 OS << " " << type << " " << getLowerName() << ";";
540 }
541 void writePCHReadDecls(raw_ostream &OS) const {
542 OS << " " << getAttrName() << "Attr::" << type << " " << getLowerName()
543 << "(static_cast<" << getAttrName() << "Attr::" << type
544 << ">(Record[Idx++]));\n";
545 }
546 void writePCHReadArgs(raw_ostream &OS) const {
547 OS << getLowerName();
548 }
549 void writePCHWrite(raw_ostream &OS) const {
550 OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
551 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000552 void writeValue(raw_ostream &OS) const {
553 OS << "\" << get" << getUpperName() << "() << \"";
554 }
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000555 void writeDump(raw_ostream &OS) const {
556 OS << " switch(SA->get" << getUpperName() << "()) {\n";
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000557 for (std::vector<StringRef>::const_iterator I = uniques.begin(),
558 E = uniques.end(); I != E; ++I) {
559 OS << " case " << getAttrName() << "Attr::" << *I << ":\n";
560 OS << " OS << \" " << *I << "\";\n";
561 OS << " break;\n";
562 }
563 OS << " }\n";
564 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000565 };
566
567 class VersionArgument : public Argument {
568 public:
569 VersionArgument(Record &Arg, StringRef Attr)
570 : Argument(Arg, Attr)
571 {}
572
573 void writeAccessors(raw_ostream &OS) const {
574 OS << " VersionTuple get" << getUpperName() << "() const {\n";
575 OS << " return " << getLowerName() << ";\n";
576 OS << " }\n";
577 OS << " void set" << getUpperName()
578 << "(ASTContext &C, VersionTuple V) {\n";
579 OS << " " << getLowerName() << " = V;\n";
580 OS << " }";
581 }
582 void writeCloneArgs(raw_ostream &OS) const {
583 OS << "get" << getUpperName() << "()";
584 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000585 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
586 OS << "A->get" << getUpperName() << "()";
587 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000588 void writeCtorBody(raw_ostream &OS) const {
589 }
590 void writeCtorInitializers(raw_ostream &OS) const {
591 OS << getLowerName() << "(" << getUpperName() << ")";
592 }
593 void writeCtorParameters(raw_ostream &OS) const {
594 OS << "VersionTuple " << getUpperName();
595 }
596 void writeDeclarations(raw_ostream &OS) const {
597 OS << "VersionTuple " << getLowerName() << ";\n";
598 }
599 void writePCHReadDecls(raw_ostream &OS) const {
600 OS << " VersionTuple " << getLowerName()
601 << "= ReadVersionTuple(Record, Idx);\n";
602 }
603 void writePCHReadArgs(raw_ostream &OS) const {
604 OS << getLowerName();
605 }
606 void writePCHWrite(raw_ostream &OS) const {
607 OS << " AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n";
608 }
Douglas Gregor1bea8802011-11-19 19:22:57 +0000609 void writeValue(raw_ostream &OS) const {
610 OS << getLowerName() << "=\" << get" << getUpperName() << "() << \"";
611 }
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000612 void writeDump(raw_ostream &OS) const {
613 OS << " OS << \" \" << SA->get" << getUpperName() << "();\n";
614 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000615 };
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000616
617 class ExprArgument : public SimpleArgument {
618 public:
619 ExprArgument(Record &Arg, StringRef Attr)
620 : SimpleArgument(Arg, Attr, "Expr *")
621 {}
622
623 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
624 OS << "tempInst" << getUpperName();
625 }
626
627 void writeTemplateInstantiation(raw_ostream &OS) const {
628 OS << " " << getType() << " tempInst" << getUpperName() << ";\n";
629 OS << " {\n";
630 OS << " EnterExpressionEvaluationContext "
631 << "Unevaluated(S, Sema::Unevaluated);\n";
632 OS << " ExprResult " << "Result = S.SubstExpr("
633 << "A->get" << getUpperName() << "(), TemplateArgs);\n";
634 OS << " tempInst" << getUpperName() << " = "
635 << "Result.takeAs<Expr>();\n";
636 OS << " }\n";
637 }
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000638
639 void writeDump(raw_ostream &OS) const {
640 }
641
642 void writeDumpChildren(raw_ostream &OS) const {
Richard Trieue8d41192013-01-31 01:44:26 +0000643 OS << " lastChild();\n";
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000644 OS << " dumpStmt(SA->get" << getUpperName() << "());\n";
645 }
Richard Trieue8d41192013-01-31 01:44:26 +0000646 void writeHasChildren(raw_ostream &OS) const { OS << "true"; }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000647 };
648
649 class VariadicExprArgument : public VariadicArgument {
650 public:
651 VariadicExprArgument(Record &Arg, StringRef Attr)
652 : VariadicArgument(Arg, Attr, "Expr *")
653 {}
654
655 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
656 OS << "tempInst" << getUpperName() << ", "
657 << "A->" << getLowerName() << "_size()";
658 }
659
660 void writeTemplateInstantiation(raw_ostream &OS) const {
661 OS << " " << getType() << " *tempInst" << getUpperName()
662 << " = new (C, 16) " << getType()
663 << "[A->" << getLowerName() << "_size()];\n";
664 OS << " {\n";
665 OS << " EnterExpressionEvaluationContext "
666 << "Unevaluated(S, Sema::Unevaluated);\n";
667 OS << " " << getType() << " *TI = tempInst" << getUpperName()
668 << ";\n";
669 OS << " " << getType() << " *I = A->" << getLowerName()
670 << "_begin();\n";
671 OS << " " << getType() << " *E = A->" << getLowerName()
672 << "_end();\n";
673 OS << " for (; I != E; ++I, ++TI) {\n";
674 OS << " ExprResult Result = S.SubstExpr(*I, TemplateArgs);\n";
675 OS << " *TI = Result.takeAs<Expr>();\n";
676 OS << " }\n";
677 OS << " }\n";
678 }
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000679
680 void writeDump(raw_ostream &OS) const {
681 }
682
683 void writeDumpChildren(raw_ostream &OS) const {
684 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
685 << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
Richard Trieue8d41192013-01-31 01:44:26 +0000686 << getLowerName() << "_end(); I != E; ++I) {\n";
687 OS << " if (I + 1 == E)\n";
688 OS << " lastChild();\n";
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000689 OS << " dumpStmt(*I);\n";
Richard Trieue8d41192013-01-31 01:44:26 +0000690 OS << " }\n";
691 }
692
693 void writeHasChildren(raw_ostream &OS) const {
694 OS << "SA->" << getLowerName() << "_begin() != "
695 << "SA->" << getLowerName() << "_end()";
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000696 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000697 };
Peter Collingbourne51d77772011-10-06 13:03:08 +0000698}
699
700static Argument *createArgument(Record &Arg, StringRef Attr,
701 Record *Search = 0) {
702 if (!Search)
703 Search = &Arg;
704
705 Argument *Ptr = 0;
706 llvm::StringRef ArgName = Search->getName();
707
708 if (ArgName == "AlignedArgument") Ptr = new AlignedArgument(Arg, Attr);
709 else if (ArgName == "EnumArgument") Ptr = new EnumArgument(Arg, Attr);
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000710 else if (ArgName == "ExprArgument") Ptr = new ExprArgument(Arg, Attr);
Peter Collingbourne51d77772011-10-06 13:03:08 +0000711 else if (ArgName == "FunctionArgument")
712 Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *");
713 else if (ArgName == "IdentifierArgument")
714 Ptr = new SimpleArgument(Arg, Attr, "IdentifierInfo *");
715 else if (ArgName == "BoolArgument") Ptr = new SimpleArgument(Arg, Attr,
716 "bool");
717 else if (ArgName == "IntArgument") Ptr = new SimpleArgument(Arg, Attr, "int");
718 else if (ArgName == "StringArgument") Ptr = new StringArgument(Arg, Attr);
719 else if (ArgName == "TypeArgument")
720 Ptr = new SimpleArgument(Arg, Attr, "QualType");
721 else if (ArgName == "UnsignedArgument")
722 Ptr = new SimpleArgument(Arg, Attr, "unsigned");
723 else if (ArgName == "SourceLocArgument")
724 Ptr = new SimpleArgument(Arg, Attr, "SourceLocation");
725 else if (ArgName == "VariadicUnsignedArgument")
726 Ptr = new VariadicArgument(Arg, Attr, "unsigned");
727 else if (ArgName == "VariadicExprArgument")
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000728 Ptr = new VariadicExprArgument(Arg, Attr);
Peter Collingbourne51d77772011-10-06 13:03:08 +0000729 else if (ArgName == "VersionArgument")
730 Ptr = new VersionArgument(Arg, Attr);
731
732 if (!Ptr) {
733 std::vector<Record*> Bases = Search->getSuperClasses();
734 for (std::vector<Record*>::iterator i = Bases.begin(), e = Bases.end();
735 i != e; ++i) {
736 Ptr = createArgument(Arg, Attr, *i);
737 if (Ptr)
738 break;
739 }
740 }
741 return Ptr;
742}
743
Douglas Gregor1bea8802011-11-19 19:22:57 +0000744static void writeAvailabilityValue(raw_ostream &OS) {
745 OS << "\" << getPlatform()->getName();\n"
746 << " if (!getIntroduced().empty()) OS << \", introduced=\" << getIntroduced();\n"
747 << " if (!getDeprecated().empty()) OS << \", deprecated=\" << getDeprecated();\n"
748 << " if (!getObsoleted().empty()) OS << \", obsoleted=\" << getObsoleted();\n"
749 << " if (getUnavailable()) OS << \", unavailable\";\n"
750 << " OS << \"";
751}
752
Michael Han51d8c522013-01-24 16:46:58 +0000753static void writePrettyPrintFunction(Record &R, std::vector<Argument*> &Args,
754 raw_ostream &OS) {
755 std::vector<Record*> Spellings = R.getValueAsListOfDefs("Spellings");
756
757 OS << "void " << R.getName() << "Attr::printPretty("
758 << "raw_ostream &OS, const PrintingPolicy &Policy) const {\n";
759
760 if (Spellings.size() == 0) {
761 OS << "}\n\n";
762 return;
763 }
764
765 OS <<
766 " switch (SpellingListIndex) {\n"
767 " default:\n"
768 " llvm_unreachable(\"Unknown attribute spelling!\");\n"
769 " break;\n";
770
771 for (unsigned I = 0; I < Spellings.size(); ++ I) {
772 llvm::SmallString<16> Prefix;
773 llvm::SmallString<8> Suffix;
774 // The actual spelling of the name and namespace (if applicable)
775 // of an attribute without considering prefix and suffix.
776 llvm::SmallString<64> Spelling;
777 std::string Name = Spellings[I]->getValueAsString("Name");
778 std::string Variety = Spellings[I]->getValueAsString("Variety");
779
780 if (Variety == "GNU") {
781 Prefix = " __attribute__((";
782 Suffix = "))";
783 } else if (Variety == "CXX11") {
784 Prefix = " [[";
785 Suffix = "]]";
786 std::string Namespace = Spellings[I]->getValueAsString("Namespace");
787 if (Namespace != "") {
788 Spelling += Namespace;
789 Spelling += "::";
790 }
791 } else if (Variety == "Declspec") {
792 Prefix = " __declspec(";
793 Suffix = ")";
Richard Smith5cd532c2013-01-29 01:24:26 +0000794 } else if (Variety == "Keyword") {
795 Prefix = " ";
796 Suffix = "";
Michael Han51d8c522013-01-24 16:46:58 +0000797 } else {
Richard Smith5cd532c2013-01-29 01:24:26 +0000798 llvm_unreachable("Unknown attribute syntax variety!");
Michael Han51d8c522013-01-24 16:46:58 +0000799 }
800
801 Spelling += Name;
802
803 OS <<
804 " case " << I << " : {\n"
805 " OS << \"" + Prefix.str() + Spelling.str();
806
807 if (Args.size()) OS << "(";
808 if (Spelling == "availability") {
809 writeAvailabilityValue(OS);
810 } else {
811 for (std::vector<Argument*>::const_iterator I = Args.begin(),
812 E = Args.end(); I != E; ++ I) {
813 if (I != Args.begin()) OS << ", ";
814 (*I)->writeValue(OS);
815 }
816 }
817
818 if (Args.size()) OS << ")";
819 OS << Suffix.str() + "\";\n";
820
821 OS <<
822 " break;\n"
823 " }\n";
824 }
825
826 // End of the switch statement.
827 OS << "}\n";
828 // End of the print function.
829 OS << "}\n\n";
830}
831
Michael Hana31f65b2013-02-01 01:19:17 +0000832/// \brief Return the index of a spelling in a spelling list.
833static unsigned getSpellingListIndex(const std::vector<Record*> &SpellingList,
834 const Record &Spelling) {
835 assert(SpellingList.size() && "Spelling list is empty!");
836
837 for (unsigned Index = 0; Index < SpellingList.size(); ++Index) {
838 Record *S = SpellingList[Index];
839 if (S->getValueAsString("Variety") != Spelling.getValueAsString("Variety"))
840 continue;
841 if (S->getValueAsString("Variety") == "CXX11" &&
842 S->getValueAsString("Namespace") !=
843 Spelling.getValueAsString("Namespace"))
844 continue;
845 if (S->getValueAsString("Name") != Spelling.getValueAsString("Name"))
846 continue;
847
848 return Index;
849 }
850
851 llvm_unreachable("Unknown spelling!");
852}
853
854static void writeAttrAccessorDefinition(Record &R, raw_ostream &OS) {
855 std::vector<Record*> Accessors = R.getValueAsListOfDefs("Accessors");
856 for (std::vector<Record*>::const_iterator I = Accessors.begin(),
857 E = Accessors.end(); I != E; ++I) {
858 Record *Accessor = *I;
859 std::string Name = Accessor->getValueAsString("Name");
860 std::vector<Record*> Spellings = Accessor->getValueAsListOfDefs(
861 "Spellings");
862 std::vector<Record*> SpellingList = R.getValueAsListOfDefs("Spellings");
863 assert(SpellingList.size() &&
864 "Attribute with empty spelling list can't have accessors!");
865
866 OS << " bool " << Name << "() const { return SpellingListIndex == ";
867 for (unsigned Index = 0; Index < Spellings.size(); ++Index) {
868 OS << getSpellingListIndex(SpellingList, *Spellings[Index]);
869 if (Index != Spellings.size() -1)
870 OS << " ||\n SpellingListIndex == ";
871 else
872 OS << "; }\n";
873 }
874 }
875}
876
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +0000877namespace clang {
878
879// Emits the class definitions for attributes.
880void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +0000881 emitSourceFileHeader("Attribute classes' definitions", OS);
882
Peter Collingbourne51d77772011-10-06 13:03:08 +0000883 OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
884 OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
885
886 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
887
888 for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
889 i != e; ++i) {
890 Record &R = **i;
Douglas Gregor3e7d31a2012-05-02 15:56:52 +0000891
892 if (!R.getValueAsBit("ASTNode"))
893 continue;
894
Peter Collingbourne51d77772011-10-06 13:03:08 +0000895 const std::string &SuperName = R.getSuperClasses().back()->getName();
896
897 OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n";
898
899 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
900 std::vector<Argument*> Args;
901 std::vector<Argument*>::iterator ai, ae;
902 Args.reserve(ArgRecords.size());
903
904 for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
905 re = ArgRecords.end();
906 ri != re; ++ri) {
907 Record &ArgRecord = **ri;
908 Argument *Arg = createArgument(ArgRecord, R.getName());
909 assert(Arg);
910 Args.push_back(Arg);
911
912 Arg->writeDeclarations(OS);
913 OS << "\n\n";
914 }
915
916 ae = Args.end();
917
918 OS << "\n public:\n";
919 OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
920
921 for (ai = Args.begin(); ai != ae; ++ai) {
922 OS << " , ";
923 (*ai)->writeCtorParameters(OS);
924 OS << "\n";
925 }
Michael Han51d8c522013-01-24 16:46:58 +0000926
927 OS << " , ";
928 OS << "unsigned SI = 0\n";
929
Peter Collingbourne51d77772011-10-06 13:03:08 +0000930 OS << " )\n";
Michael Han51d8c522013-01-24 16:46:58 +0000931 OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000932
933 for (ai = Args.begin(); ai != ae; ++ai) {
934 OS << " , ";
935 (*ai)->writeCtorInitializers(OS);
936 OS << "\n";
937 }
938
939 OS << " {\n";
940
941 for (ai = Args.begin(); ai != ae; ++ai) {
942 (*ai)->writeCtorBody(OS);
943 OS << "\n";
944 }
945 OS << " }\n\n";
946
947 OS << " virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n";
Michael Han7d470532013-01-27 00:06:24 +0000948 OS << " virtual void printPretty(raw_ostream &OS,\n"
Richard Smith0dae7292012-08-16 02:43:29 +0000949 << " const PrintingPolicy &Policy) const;\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000950
Michael Hana31f65b2013-02-01 01:19:17 +0000951 writeAttrAccessorDefinition(R, OS);
952
Peter Collingbourne51d77772011-10-06 13:03:08 +0000953 for (ai = Args.begin(); ai != ae; ++ai) {
954 (*ai)->writeAccessors(OS);
955 OS << "\n\n";
956 }
957
Jakob Stoklund Oleseneb666732012-01-13 04:57:47 +0000958 OS << R.getValueAsString("AdditionalMembers");
Peter Collingbourne51d77772011-10-06 13:03:08 +0000959 OS << "\n\n";
960
961 OS << " static bool classof(const Attr *A) { return A->getKind() == "
962 << "attr::" << R.getName() << "; }\n";
DeLesley Hutchins23323e02012-01-20 22:50:54 +0000963
964 bool LateParsed = R.getValueAsBit("LateParsed");
965 OS << " virtual bool isLateParsed() const { return "
966 << LateParsed << "; }\n";
967
Peter Collingbourne51d77772011-10-06 13:03:08 +0000968 OS << "};\n\n";
969 }
970
971 OS << "#endif\n";
972}
973
Douglas Gregor4761b102013-05-03 18:51:59 +0000974// Emits the all-arguments-are-expressions property for attributes.
Douglas Gregor92eb7d82013-05-02 23:25:32 +0000975void EmitClangAttrExprArgsList(RecordKeeper &Records, raw_ostream &OS) {
976 emitSourceFileHeader("llvm::StringSwitch code to match attributes with "
977 "expression arguments", OS);
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 // Determine whether the first argument is something that is always
986 // an expression.
987 std::vector<Record *> Args = Attr.getValueAsListOfDefs("Args");
988 if (Args.empty() || Args[0]->getSuperClasses().empty())
989 continue;
990
991 // Check whether this is one of the argument kinds that implies an
992 // expression.
993 // FIXME: Aligned is weird.
994 if (!llvm::StringSwitch<bool>(Args[0]->getSuperClasses().back()->getName())
995 .Case("AlignedArgument", true)
996 .Case("BoolArgument", true)
997 .Case("DefaultIntArgument", true)
998 .Case("IntArgument", true)
999 .Case("ExprArgument", true)
1000 .Case("UnsignedArgument", true)
1001 .Case("VariadicUnsignedArgument", true)
1002 .Case("VariadicExprArgument", true)
1003 .Default(false))
1004 continue;
1005
1006 std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
1007
1008 for (std::vector<Record*>::const_iterator I = Spellings.begin(),
1009 E = Spellings.end(); I != E; ++I) {
1010 OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", "
1011 << "true" << ")\n";
1012 }
1013 }
1014}
1015
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001016// Emits the class method definitions for attributes.
1017void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00001018 emitSourceFileHeader("Attribute classes' member function definitions", OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001019
1020 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1021 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ri, re;
1022 std::vector<Argument*>::iterator ai, ae;
1023
1024 for (; i != e; ++i) {
1025 Record &R = **i;
Douglas Gregor3e7d31a2012-05-02 15:56:52 +00001026
1027 if (!R.getValueAsBit("ASTNode"))
1028 continue;
1029
Peter Collingbourne51d77772011-10-06 13:03:08 +00001030 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
1031 std::vector<Argument*> Args;
1032 for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri)
1033 Args.push_back(createArgument(**ri, R.getName()));
1034
1035 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
1036 (*ai)->writeAccessorDefinitions(OS);
1037
1038 OS << R.getName() << "Attr *" << R.getName()
1039 << "Attr::clone(ASTContext &C) const {\n";
1040 OS << " return new (C) " << R.getName() << "Attr(getLocation(), C";
1041 for (ai = Args.begin(); ai != ae; ++ai) {
1042 OS << ", ";
1043 (*ai)->writeCloneArgs(OS);
1044 }
Richard Smith8f3aacc2013-01-29 04:21:28 +00001045 OS << ", getSpellingListIndex());\n}\n\n";
Douglas Gregor1bea8802011-11-19 19:22:57 +00001046
Michael Han51d8c522013-01-24 16:46:58 +00001047 writePrettyPrintFunction(R, Args, OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001048 }
1049}
1050
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001051} // end namespace clang
1052
Peter Collingbourne51d77772011-10-06 13:03:08 +00001053static void EmitAttrList(raw_ostream &OS, StringRef Class,
1054 const std::vector<Record*> &AttrList) {
1055 std::vector<Record*>::const_iterator i = AttrList.begin(), e = AttrList.end();
1056
1057 if (i != e) {
1058 // Move the end iterator back to emit the last attribute.
Douglas Gregor3e7d31a2012-05-02 15:56:52 +00001059 for(--e; i != e; ++i) {
1060 if (!(*i)->getValueAsBit("ASTNode"))
1061 continue;
1062
Peter Collingbourne51d77772011-10-06 13:03:08 +00001063 OS << Class << "(" << (*i)->getName() << ")\n";
Douglas Gregor3e7d31a2012-05-02 15:56:52 +00001064 }
Peter Collingbourne51d77772011-10-06 13:03:08 +00001065
1066 OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n";
1067 }
1068}
1069
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001070namespace clang {
1071
1072// Emits the enumeration list for attributes.
1073void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00001074 emitSourceFileHeader("List of all attributes that Clang recognizes", OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001075
1076 OS << "#ifndef LAST_ATTR\n";
1077 OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n";
1078 OS << "#endif\n\n";
1079
1080 OS << "#ifndef INHERITABLE_ATTR\n";
1081 OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n";
1082 OS << "#endif\n\n";
1083
1084 OS << "#ifndef LAST_INHERITABLE_ATTR\n";
1085 OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n";
1086 OS << "#endif\n\n";
1087
1088 OS << "#ifndef INHERITABLE_PARAM_ATTR\n";
1089 OS << "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n";
1090 OS << "#endif\n\n";
1091
1092 OS << "#ifndef LAST_INHERITABLE_PARAM_ATTR\n";
1093 OS << "#define LAST_INHERITABLE_PARAM_ATTR(NAME)"
1094 " INHERITABLE_PARAM_ATTR(NAME)\n";
1095 OS << "#endif\n\n";
1096
Reid Klecknera3d813a2013-05-14 20:55:49 +00001097 OS << "#ifndef MS_INHERITANCE_ATTR\n";
1098 OS << "#define MS_INHERITANCE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n";
Reid Kleckner852e3d72013-03-26 18:30:28 +00001099 OS << "#endif\n\n";
1100
Reid Klecknera3d813a2013-05-14 20:55:49 +00001101 OS << "#ifndef LAST_MS_INHERITANCE_ATTR\n";
1102 OS << "#define LAST_MS_INHERITANCE_ATTR(NAME)"
1103 " MS_INHERITANCE_ATTR(NAME)\n";
Reid Kleckner852e3d72013-03-26 18:30:28 +00001104 OS << "#endif\n\n";
1105
Peter Collingbourne51d77772011-10-06 13:03:08 +00001106 Record *InhClass = Records.getClass("InheritableAttr");
1107 Record *InhParamClass = Records.getClass("InheritableParamAttr");
Reid Kleckner852e3d72013-03-26 18:30:28 +00001108 Record *MSInheritanceClass = Records.getClass("MSInheritanceAttr");
Peter Collingbourne51d77772011-10-06 13:03:08 +00001109 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
Reid Kleckner852e3d72013-03-26 18:30:28 +00001110 NonInhAttrs, InhAttrs, InhParamAttrs, MSInhAttrs;
Peter Collingbourne51d77772011-10-06 13:03:08 +00001111 for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
1112 i != e; ++i) {
Douglas Gregor3e7d31a2012-05-02 15:56:52 +00001113 if (!(*i)->getValueAsBit("ASTNode"))
1114 continue;
1115
Peter Collingbourne51d77772011-10-06 13:03:08 +00001116 if ((*i)->isSubClassOf(InhParamClass))
1117 InhParamAttrs.push_back(*i);
Reid Kleckner852e3d72013-03-26 18:30:28 +00001118 else if ((*i)->isSubClassOf(MSInheritanceClass))
1119 MSInhAttrs.push_back(*i);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001120 else if ((*i)->isSubClassOf(InhClass))
1121 InhAttrs.push_back(*i);
1122 else
1123 NonInhAttrs.push_back(*i);
1124 }
1125
1126 EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs);
Reid Klecknera3d813a2013-05-14 20:55:49 +00001127 EmitAttrList(OS, "MS_INHERITANCE_ATTR", MSInhAttrs);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001128 EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs);
1129 EmitAttrList(OS, "ATTR", NonInhAttrs);
1130
1131 OS << "#undef LAST_ATTR\n";
1132 OS << "#undef INHERITABLE_ATTR\n";
Reid Klecknera3d813a2013-05-14 20:55:49 +00001133 OS << "#undef MS_INHERITANCE_ATTR\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +00001134 OS << "#undef LAST_INHERITABLE_ATTR\n";
1135 OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n";
Reid Klecknera3d813a2013-05-14 20:55:49 +00001136 OS << "#undef LAST_MS_INHERITANCE_ATTR\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +00001137 OS << "#undef ATTR\n";
1138}
1139
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001140// Emits the code to read an attribute from a precompiled header.
1141void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00001142 emitSourceFileHeader("Attribute deserialization code", OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001143
1144 Record *InhClass = Records.getClass("InheritableAttr");
1145 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
1146 ArgRecords;
1147 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
1148 std::vector<Argument*> Args;
1149 std::vector<Argument*>::iterator ri, re;
1150
1151 OS << " switch (Kind) {\n";
1152 OS << " default:\n";
1153 OS << " assert(0 && \"Unknown attribute!\");\n";
1154 OS << " break;\n";
1155 for (; i != e; ++i) {
1156 Record &R = **i;
Douglas Gregor3e7d31a2012-05-02 15:56:52 +00001157 if (!R.getValueAsBit("ASTNode"))
1158 continue;
1159
Peter Collingbourne51d77772011-10-06 13:03:08 +00001160 OS << " case attr::" << R.getName() << ": {\n";
1161 if (R.isSubClassOf(InhClass))
1162 OS << " bool isInherited = Record[Idx++];\n";
1163 ArgRecords = R.getValueAsListOfDefs("Args");
1164 Args.clear();
1165 for (ai = ArgRecords.begin(), ae = ArgRecords.end(); ai != ae; ++ai) {
1166 Argument *A = createArgument(**ai, R.getName());
1167 Args.push_back(A);
1168 A->writePCHReadDecls(OS);
1169 }
1170 OS << " New = new (Context) " << R.getName() << "Attr(Range, Context";
1171 for (ri = Args.begin(), re = Args.end(); ri != re; ++ri) {
1172 OS << ", ";
1173 (*ri)->writePCHReadArgs(OS);
1174 }
1175 OS << ");\n";
1176 if (R.isSubClassOf(InhClass))
1177 OS << " cast<InheritableAttr>(New)->setInherited(isInherited);\n";
1178 OS << " break;\n";
1179 OS << " }\n";
1180 }
1181 OS << " }\n";
1182}
1183
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001184// Emits the code to write an attribute to a precompiled header.
1185void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00001186 emitSourceFileHeader("Attribute serialization code", OS);
1187
Peter Collingbourne51d77772011-10-06 13:03:08 +00001188 Record *InhClass = Records.getClass("InheritableAttr");
1189 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
1190 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
1191
1192 OS << " switch (A->getKind()) {\n";
1193 OS << " default:\n";
1194 OS << " llvm_unreachable(\"Unknown attribute kind!\");\n";
1195 OS << " break;\n";
1196 for (; i != e; ++i) {
1197 Record &R = **i;
Douglas Gregor3e7d31a2012-05-02 15:56:52 +00001198 if (!R.getValueAsBit("ASTNode"))
1199 continue;
Peter Collingbourne51d77772011-10-06 13:03:08 +00001200 OS << " case attr::" << R.getName() << ": {\n";
1201 Args = R.getValueAsListOfDefs("Args");
1202 if (R.isSubClassOf(InhClass) || !Args.empty())
1203 OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
1204 << "Attr>(A);\n";
1205 if (R.isSubClassOf(InhClass))
1206 OS << " Record.push_back(SA->isInherited());\n";
1207 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
1208 createArgument(**ai, R.getName())->writePCHWrite(OS);
1209 OS << " break;\n";
1210 OS << " }\n";
1211 }
1212 OS << " }\n";
1213}
1214
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001215// Emits the list of spellings for attributes.
1216void EmitClangAttrSpellingList(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00001217 emitSourceFileHeader("llvm::StringSwitch code to match all known attributes",
1218 OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001219
1220 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1221
1222 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) {
1223 Record &Attr = **I;
1224
Sean Hunt8e083e72012-06-19 23:57:03 +00001225 std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
Peter Collingbourne51d77772011-10-06 13:03:08 +00001226
Sean Hunt8e083e72012-06-19 23:57:03 +00001227 for (std::vector<Record*>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) {
1228 OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", true)\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +00001229 }
1230 }
1231
1232}
1233
Michael Han51d8c522013-01-24 16:46:58 +00001234void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00001235 emitSourceFileHeader("Code to translate different attribute spellings "
1236 "into internal identifiers", OS);
Michael Han51d8c522013-01-24 16:46:58 +00001237
1238 OS <<
1239 " unsigned Index = 0;\n"
1240 " switch (AttrKind) {\n"
1241 " default:\n"
1242 " llvm_unreachable(\"Unknown attribute kind!\");\n"
1243 " break;\n";
1244
1245 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1246 for (std::vector<Record*>::const_iterator I = Attrs.begin(), E = Attrs.end();
1247 I != E; ++I) {
1248 Record &R = **I;
1249 // We only care about attributes that participate in Sema checking, so
1250 // skip those attributes that are not able to make their way to Sema.
1251 if (!R.getValueAsBit("SemaHandler"))
1252 continue;
1253
1254 std::vector<Record*> Spellings = R.getValueAsListOfDefs("Spellings");
1255 // Each distinct spelling yields an attribute kind.
1256 if (R.getValueAsBit("DistinctSpellings")) {
1257 for (unsigned I = 0; I < Spellings.size(); ++ I) {
1258 OS <<
1259 " case AT_" << Spellings[I]->getValueAsString("Name") << ": \n"
1260 " Index = " << I << ";\n"
1261 " break;\n";
1262 }
1263 } else {
1264 OS << " case AT_" << R.getName() << " : {\n";
1265 for (unsigned I = 0; I < Spellings.size(); ++ I) {
1266 SmallString<16> Namespace;
1267 if (Spellings[I]->getValueAsString("Variety") == "CXX11")
1268 Namespace = Spellings[I]->getValueAsString("Namespace");
1269 else
1270 Namespace = "";
1271
1272 OS << " if (Name == \""
1273 << Spellings[I]->getValueAsString("Name") << "\" && "
1274 << "SyntaxUsed == "
1275 << StringSwitch<unsigned>(Spellings[I]->getValueAsString("Variety"))
1276 .Case("GNU", 0)
1277 .Case("CXX11", 1)
1278 .Case("Declspec", 2)
Richard Smith5cd532c2013-01-29 01:24:26 +00001279 .Case("Keyword", 3)
Michael Han51d8c522013-01-24 16:46:58 +00001280 .Default(0)
1281 << " && Scope == \"" << Namespace << "\")\n"
1282 << " return " << I << ";\n";
1283 }
1284
1285 OS << " break;\n";
1286 OS << " }\n";
1287 }
1288 }
1289
1290 OS << " }\n";
1291 OS << " return Index;\n";
1292}
1293
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001294// Emits the LateParsed property for attributes.
1295void EmitClangAttrLateParsedList(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00001296 emitSourceFileHeader("llvm::StringSwitch code to match late parsed "
1297 "attributes", OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001298
1299 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1300
1301 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1302 I != E; ++I) {
1303 Record &Attr = **I;
1304
1305 bool LateParsed = Attr.getValueAsBit("LateParsed");
1306
1307 if (LateParsed) {
Sean Hunt8e083e72012-06-19 23:57:03 +00001308 std::vector<Record*> Spellings =
1309 Attr.getValueAsListOfDefs("Spellings");
Peter Collingbourne51d77772011-10-06 13:03:08 +00001310
Sean Hunt8e083e72012-06-19 23:57:03 +00001311 // FIXME: Handle non-GNU attributes
1312 for (std::vector<Record*>::const_iterator I = Spellings.begin(),
Peter Collingbourne51d77772011-10-06 13:03:08 +00001313 E = Spellings.end(); I != E; ++I) {
Sean Hunt8e083e72012-06-19 23:57:03 +00001314 if ((*I)->getValueAsString("Variety") != "GNU")
1315 continue;
1316 OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", "
1317 << LateParsed << ")\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +00001318 }
1319 }
1320 }
1321}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001322
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001323// Emits code to instantiate dependent attributes on templates.
1324void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00001325 emitSourceFileHeader("Template instantiation code for attributes", OS);
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001326
1327 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1328
Benjamin Kramer5bbc3852012-02-06 11:13:08 +00001329 OS << "namespace clang {\n"
1330 << "namespace sema {\n\n"
1331 << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, "
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001332 << "Sema &S,\n"
1333 << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n"
1334 << " switch (At->getKind()) {\n"
1335 << " default:\n"
1336 << " break;\n";
1337
1338 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1339 I != E; ++I) {
1340 Record &R = **I;
Douglas Gregor3e7d31a2012-05-02 15:56:52 +00001341 if (!R.getValueAsBit("ASTNode"))
1342 continue;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001343
1344 OS << " case attr::" << R.getName() << ": {\n";
Rafael Espindola31c195a2012-05-15 14:09:55 +00001345 bool ShouldClone = R.getValueAsBit("Clone");
1346
1347 if (!ShouldClone) {
1348 OS << " return NULL;\n";
1349 OS << " }\n";
1350 continue;
1351 }
1352
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001353 OS << " const " << R.getName() << "Attr *A = cast<"
1354 << R.getName() << "Attr>(At);\n";
1355 bool TDependent = R.getValueAsBit("TemplateDependent");
1356
1357 if (!TDependent) {
1358 OS << " return A->clone(C);\n";
1359 OS << " }\n";
1360 continue;
1361 }
1362
1363 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
1364 std::vector<Argument*> Args;
1365 std::vector<Argument*>::iterator ai, ae;
1366 Args.reserve(ArgRecords.size());
1367
1368 for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
1369 re = ArgRecords.end();
1370 ri != re; ++ri) {
1371 Record &ArgRecord = **ri;
1372 Argument *Arg = createArgument(ArgRecord, R.getName());
1373 assert(Arg);
1374 Args.push_back(Arg);
1375 }
1376 ae = Args.end();
1377
1378 for (ai = Args.begin(); ai != ae; ++ai) {
1379 (*ai)->writeTemplateInstantiation(OS);
1380 }
1381 OS << " return new (C) " << R.getName() << "Attr(A->getLocation(), C";
1382 for (ai = Args.begin(); ai != ae; ++ai) {
1383 OS << ", ";
1384 (*ai)->writeTemplateInstantiationArgs(OS);
1385 }
1386 OS << ");\n }\n";
1387 }
1388 OS << " } // end switch\n"
1389 << " llvm_unreachable(\"Unknown attribute!\");\n"
1390 << " return 0;\n"
Benjamin Kramer5bbc3852012-02-06 11:13:08 +00001391 << "}\n\n"
1392 << "} // end namespace sema\n"
1393 << "} // end namespace clang\n";
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001394}
1395
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001396// Emits the list of parsed attributes.
1397void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00001398 emitSourceFileHeader("List of all attributes that Clang recognizes", OS);
1399
Michael Hane53ac8a2012-03-07 00:12:16 +00001400 OS << "#ifndef PARSED_ATTR\n";
1401 OS << "#define PARSED_ATTR(NAME) NAME\n";
1402 OS << "#endif\n\n";
1403
1404 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
Michael Hane53ac8a2012-03-07 00:12:16 +00001405
1406 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1407 I != E; ++I) {
1408 Record &Attr = **I;
1409
1410 bool SemaHandler = Attr.getValueAsBit("SemaHandler");
Douglas Gregor703d4122012-05-11 23:37:49 +00001411 bool DistinctSpellings = Attr.getValueAsBit("DistinctSpellings");
1412
Michael Hane53ac8a2012-03-07 00:12:16 +00001413 if (SemaHandler) {
Sean Hunt8e083e72012-06-19 23:57:03 +00001414 if (DistinctSpellings) {
1415 std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
Jakob Stoklund Olesen35329362012-06-19 21:48:43 +00001416
Sean Hunt8e083e72012-06-19 23:57:03 +00001417 for (std::vector<Record*>::const_iterator I = Spellings.begin(),
1418 E = Spellings.end(); I != E; ++I) {
1419 std::string AttrName = (*I)->getValueAsString("Name");
1420
1421 StringRef Spelling = NormalizeAttrName(AttrName);
1422
1423 OS << "PARSED_ATTR(" << Spelling << ")\n";
1424 }
1425 } else {
1426 StringRef AttrName = Attr.getName();
1427 AttrName = NormalizeAttrName(AttrName);
1428 OS << "PARSED_ATTR(" << AttrName << ")\n";
Michael Hane53ac8a2012-03-07 00:12:16 +00001429 }
1430 }
1431 }
1432}
1433
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001434// Emits the kind list of parsed attributes
1435void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00001436 emitSourceFileHeader("Attribute name matcher", OS);
1437
Michael Hane53ac8a2012-03-07 00:12:16 +00001438 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1439
Douglas Gregor0c19b3c2012-05-02 17:33:51 +00001440 std::vector<StringMatcher::StringPair> Matches;
Michael Hane53ac8a2012-03-07 00:12:16 +00001441 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1442 I != E; ++I) {
1443 Record &Attr = **I;
1444
1445 bool SemaHandler = Attr.getValueAsBit("SemaHandler");
Douglas Gregor331d2ec2012-05-02 16:18:45 +00001446 bool Ignored = Attr.getValueAsBit("Ignored");
Douglas Gregor703d4122012-05-11 23:37:49 +00001447 bool DistinctSpellings = Attr.getValueAsBit("DistinctSpellings");
Douglas Gregor331d2ec2012-05-02 16:18:45 +00001448 if (SemaHandler || Ignored) {
Sean Hunt8e083e72012-06-19 23:57:03 +00001449 std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
Michael Hane53ac8a2012-03-07 00:12:16 +00001450
Sean Hunt8e083e72012-06-19 23:57:03 +00001451 for (std::vector<Record*>::const_iterator I = Spellings.begin(),
Michael Hane53ac8a2012-03-07 00:12:16 +00001452 E = Spellings.end(); I != E; ++I) {
Sean Hunt8e083e72012-06-19 23:57:03 +00001453 std::string RawSpelling = (*I)->getValueAsString("Name");
Douglas Gregor703d4122012-05-11 23:37:49 +00001454 StringRef AttrName = NormalizeAttrName(DistinctSpellings
Sean Hunt8e083e72012-06-19 23:57:03 +00001455 ? StringRef(RawSpelling)
1456 : StringRef(Attr.getName()));
Michael Hane53ac8a2012-03-07 00:12:16 +00001457
Sean Hunt8e083e72012-06-19 23:57:03 +00001458 SmallString<64> Spelling;
1459 if ((*I)->getValueAsString("Variety") == "CXX11") {
1460 Spelling += (*I)->getValueAsString("Namespace");
1461 Spelling += "::";
Sean Hunt93f95f22012-06-18 16:13:52 +00001462 }
Sean Hunt8e083e72012-06-19 23:57:03 +00001463 Spelling += NormalizeAttrSpelling(RawSpelling);
Sean Hunt93f95f22012-06-18 16:13:52 +00001464
Douglas Gregor331d2ec2012-05-02 16:18:45 +00001465 if (SemaHandler)
Douglas Gregor0c19b3c2012-05-02 17:33:51 +00001466 Matches.push_back(
Douglas Gregor703d4122012-05-11 23:37:49 +00001467 StringMatcher::StringPair(
Sean Hunt8e083e72012-06-19 23:57:03 +00001468 StringRef(Spelling),
Sean Hunt93f95f22012-06-18 16:13:52 +00001469 "return AttributeList::AT_" + AttrName.str() + ";"));
Douglas Gregor331d2ec2012-05-02 16:18:45 +00001470 else
Douglas Gregor0c19b3c2012-05-02 17:33:51 +00001471 Matches.push_back(
1472 StringMatcher::StringPair(
Sean Hunt8e083e72012-06-19 23:57:03 +00001473 StringRef(Spelling),
Sean Hunt93f95f22012-06-18 16:13:52 +00001474 "return AttributeList::IgnoredAttribute;"));
Michael Hane53ac8a2012-03-07 00:12:16 +00001475 }
1476 }
1477 }
Douglas Gregor0c19b3c2012-05-02 17:33:51 +00001478
1479 OS << "static AttributeList::Kind getAttrKind(StringRef Name) {\n";
1480 StringMatcher("Name", Matches, OS).Emit();
1481 OS << "return AttributeList::UnknownAttribute;\n"
1482 << "}\n";
Michael Hane53ac8a2012-03-07 00:12:16 +00001483}
1484
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +00001485// Emits the code to dump an attribute.
1486void EmitClangAttrDump(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00001487 emitSourceFileHeader("Attribute dumper", OS);
1488
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +00001489 OS <<
1490 " switch (A->getKind()) {\n"
1491 " default:\n"
1492 " llvm_unreachable(\"Unknown attribute kind!\");\n"
1493 " break;\n";
1494 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
1495 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1496 I != E; ++I) {
1497 Record &R = **I;
1498 if (!R.getValueAsBit("ASTNode"))
1499 continue;
1500 OS << " case attr::" << R.getName() << ": {\n";
1501 Args = R.getValueAsListOfDefs("Args");
1502 if (!Args.empty()) {
1503 OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
1504 << "Attr>(A);\n";
1505 for (std::vector<Record*>::iterator I = Args.begin(), E = Args.end();
1506 I != E; ++I)
1507 createArgument(**I, R.getName())->writeDump(OS);
Richard Trieue8d41192013-01-31 01:44:26 +00001508
1509 // Code for detecting the last child.
1510 OS << " bool OldMoreChildren = hasMoreChildren();\n";
1511 OS << " bool MoreChildren = OldMoreChildren;\n";
1512
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +00001513 for (std::vector<Record*>::iterator I = Args.begin(), E = Args.end();
Richard Trieue8d41192013-01-31 01:44:26 +00001514 I != E; ++I) {
1515 // More code for detecting the last child.
1516 OS << " MoreChildren = OldMoreChildren";
1517 for (std::vector<Record*>::iterator Next = I + 1; Next != E; ++Next) {
1518 OS << " || ";
1519 createArgument(**Next, R.getName())->writeHasChildren(OS);
1520 }
1521 OS << ";\n";
1522 OS << " setMoreChildren(MoreChildren);\n";
1523
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +00001524 createArgument(**I, R.getName())->writeDumpChildren(OS);
Richard Trieue8d41192013-01-31 01:44:26 +00001525 }
1526
1527 // Reset the last child.
1528 OS << " setMoreChildren(OldMoreChildren);\n";
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +00001529 }
1530 OS <<
1531 " break;\n"
1532 " }\n";
1533 }
1534 OS << " }\n";
1535}
1536
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001537} // end namespace clang