1 //===- ClangAttrEmitter.cpp - Generate Clang attribute handling =-*- C++ -*--=//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // These tablegen backends emit Clang attribute processing code
12 //===----------------------------------------------------------------------===//
14 #include "ClangAttrEmitter.h"
16 #include "llvm/ADT/StringSwitch.h"
22 static const std::vector
<StringRef
>
23 getValueAsListOfStrings(Record
&R
, StringRef FieldName
) {
24 ListInit
*List
= R
.getValueAsListInit(FieldName
);
25 assert (List
&& "Got a null ListInit");
27 std::vector
<StringRef
> Strings
;
28 Strings
.reserve(List
->getSize());
30 for (ListInit::iterator i
= List
->begin(), e
= List
->end(); i
!= e
; ++i
) {
31 assert(*i
&& "Got a null element in a ListInit");
32 if (StringInit
*S
= dynamic_cast<StringInit
*>(*i
))
33 Strings
.push_back(S
->getValue());
34 else if (CodeInit
*C
= dynamic_cast<CodeInit
*>(*i
))
35 Strings
.push_back(C
->getValue());
37 assert(false && "Got a non-string, non-code element in a ListInit");
43 std::string
ReadPCHRecord(StringRef type
) {
44 return StringSwitch
<std::string
>(type
)
45 .EndsWith("Decl *", "cast_or_null<" + std::string(type
, 0, type
.size()-1) +
46 ">(GetDecl(Record[Idx++]))")
47 .Case("QualType", "GetType(Record[Idx++])")
48 .Case("Expr *", "ReadSubExpr()")
49 .Case("IdentifierInfo *", "GetIdentifierInfo(Record, Idx)")
50 .Default("Record[Idx++]");
53 // Assumes that the way to get the value is SA->getname()
54 std::string
WritePCHRecord(StringRef type
, StringRef name
) {
55 return StringSwitch
<std::string
>(type
)
56 .EndsWith("Decl *", "AddDeclRef(" + std::string(name
) +
58 .Case("QualType", "AddTypeRef(" + std::string(name
) + ", Record);\n")
59 .Case("Expr *", "AddStmt(" + std::string(name
) + ");\n")
60 .Case("IdentifierInfo *",
61 "AddIdentifierRef(" + std::string(name
) + ", Record);\n")
62 .Default("Record.push_back(" + std::string(name
) + ");\n");
67 std::string lowerName
, upperName
;
71 Argument(Record
&Arg
, StringRef Attr
)
72 : lowerName(Arg
.getValueAsString("Name")), upperName(lowerName
),
74 if (!lowerName
.empty()) {
75 lowerName
[0] = std::tolower(lowerName
[0]);
76 upperName
[0] = std::toupper(upperName
[0]);
79 virtual ~Argument() {}
81 StringRef
getLowerName() const { return lowerName
; }
82 StringRef
getUpperName() const { return upperName
; }
83 StringRef
getAttrName() const { return attrName
; }
85 // These functions print the argument contents formatted in different ways.
86 virtual void writeAccessors(raw_ostream
&OS
) const = 0;
87 virtual void writeAccessorDefinitions(raw_ostream
&OS
) const {}
88 virtual void writeCloneArgs(raw_ostream
&OS
) const = 0;
89 virtual void writeCtorBody(raw_ostream
&OS
) const {}
90 virtual void writeCtorInitializers(raw_ostream
&OS
) const = 0;
91 virtual void writeCtorParameters(raw_ostream
&OS
) const = 0;
92 virtual void writeDeclarations(raw_ostream
&OS
) const = 0;
93 virtual void writePCHReadArgs(raw_ostream
&OS
) const = 0;
94 virtual void writePCHReadDecls(raw_ostream
&OS
) const = 0;
95 virtual void writePCHWrite(raw_ostream
&OS
) const = 0;
98 class SimpleArgument
: public Argument
{
102 SimpleArgument(Record
&Arg
, StringRef Attr
, std::string T
)
103 : Argument(Arg
, Attr
), type(T
)
106 void writeAccessors(raw_ostream
&OS
) const {
107 OS
<< " " << type
<< " get" << getUpperName() << "() const {\n";
108 OS
<< " return " << getLowerName() << ";\n";
111 void writeCloneArgs(raw_ostream
&OS
) const {
112 OS
<< getLowerName();
114 void writeCtorInitializers(raw_ostream
&OS
) const {
115 OS
<< getLowerName() << "(" << getUpperName() << ")";
117 void writeCtorParameters(raw_ostream
&OS
) const {
118 OS
<< type
<< " " << getUpperName();
120 void writeDeclarations(raw_ostream
&OS
) const {
121 OS
<< type
<< " " << getLowerName() << ";";
123 void writePCHReadDecls(raw_ostream
&OS
) const {
124 std::string read
= ReadPCHRecord(type
);
125 OS
<< " " << type
<< " " << getLowerName() << " = " << read
<< ";\n";
127 void writePCHReadArgs(raw_ostream
&OS
) const {
128 OS
<< getLowerName();
130 void writePCHWrite(raw_ostream
&OS
) const {
131 OS
<< " " << WritePCHRecord(type
, "SA->get" +
132 std::string(getUpperName()) + "()");
136 class StringArgument
: public Argument
{
138 StringArgument(Record
&Arg
, StringRef Attr
)
139 : Argument(Arg
, Attr
)
142 void writeAccessors(raw_ostream
&OS
) const {
143 OS
<< " llvm::StringRef get" << getUpperName() << "() const {\n";
144 OS
<< " return llvm::StringRef(" << getLowerName() << ", "
145 << getLowerName() << "Length);\n";
147 OS
<< " unsigned get" << getUpperName() << "Length() const {\n";
148 OS
<< " return " << getLowerName() << "Length;\n";
150 OS
<< " void set" << getUpperName()
151 << "(ASTContext &C, llvm::StringRef S) {\n";
152 OS
<< " " << getLowerName() << "Length = S.size();\n";
153 OS
<< " this->" << getLowerName() << " = new (C, 1) char ["
154 << getLowerName() << "Length];\n";
155 OS
<< " std::memcpy(this->" << getLowerName() << ", S.data(), "
156 << getLowerName() << "Length);\n";
159 void writeCloneArgs(raw_ostream
&OS
) const {
160 OS
<< "get" << getUpperName() << "()";
162 void writeCtorBody(raw_ostream
&OS
) const {
163 OS
<< " std::memcpy(" << getLowerName() << ", " << getUpperName()
164 << ".data(), " << getLowerName() << "Length);";
166 void writeCtorInitializers(raw_ostream
&OS
) const {
167 OS
<< getLowerName() << "Length(" << getUpperName() << ".size()),"
168 << getLowerName() << "(new (Ctx, 1) char[" << getLowerName()
171 void writeCtorParameters(raw_ostream
&OS
) const {
172 OS
<< "llvm::StringRef " << getUpperName();
174 void writeDeclarations(raw_ostream
&OS
) const {
175 OS
<< "unsigned " << getLowerName() << "Length;\n";
176 OS
<< "char *" << getLowerName() << ";";
178 void writePCHReadDecls(raw_ostream
&OS
) const {
179 OS
<< " std::string " << getLowerName()
180 << "= ReadString(Record, Idx);\n";
182 void writePCHReadArgs(raw_ostream
&OS
) const {
183 OS
<< getLowerName();
185 void writePCHWrite(raw_ostream
&OS
) const {
186 OS
<< " AddString(SA->get" << getUpperName() << "(), Record);\n";
190 class AlignedArgument
: public Argument
{
192 AlignedArgument(Record
&Arg
, StringRef Attr
)
193 : Argument(Arg
, Attr
)
196 void writeAccessors(raw_ostream
&OS
) const {
197 OS
<< " bool is" << getUpperName() << "Dependent() const;\n";
199 OS
<< " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n";
201 OS
<< " bool is" << getUpperName() << "Expr() const {\n";
202 OS
<< " return is" << getLowerName() << "Expr;\n";
205 OS
<< " Expr *get" << getUpperName() << "Expr() const {\n";
206 OS
<< " assert(is" << getLowerName() << "Expr);\n";
207 OS
<< " return " << getLowerName() << "Expr;\n";
210 OS
<< " TypeSourceInfo *get" << getUpperName() << "Type() const {\n";
211 OS
<< " assert(!is" << getLowerName() << "Expr);\n";
212 OS
<< " return " << getLowerName() << "Type;\n";
215 void writeAccessorDefinitions(raw_ostream
&OS
) const {
216 OS
<< "bool " << getAttrName() << "Attr::is" << getUpperName()
217 << "Dependent() const {\n";
218 OS
<< " if (is" << getLowerName() << "Expr)\n";
219 OS
<< " return " << getLowerName() << "Expr && (" << getLowerName()
220 << "Expr->isValueDependent() || " << getLowerName()
221 << "Expr->isTypeDependent());\n";
223 OS
<< " return " << getLowerName()
224 << "Type->getType()->isDependentType();\n";
227 // FIXME: Do not do the calculation here
228 // FIXME: Handle types correctly
229 // A null pointer means maximum alignment
230 // FIXME: Load the platform-specific maximum alignment, rather than
232 OS
<< "unsigned " << getAttrName() << "Attr::get" << getUpperName()
233 << "(ASTContext &Ctx) const {\n";
234 OS
<< " assert(!is" << getUpperName() << "Dependent());\n";
235 OS
<< " if (is" << getLowerName() << "Expr)\n";
236 OS
<< " return (" << getLowerName() << "Expr ? " << getLowerName()
237 << "Expr->EvaluateAsInt(Ctx).getZExtValue() : 16)"
238 << "* Ctx.getCharWidth();\n";
240 OS
<< " return 0; // FIXME\n";
243 void writeCloneArgs(raw_ostream
&OS
) const {
244 OS
<< "is" << getLowerName() << "Expr, is" << getLowerName()
245 << "Expr ? static_cast<void*>(" << getLowerName()
246 << "Expr) : " << getLowerName()
249 void writeCtorBody(raw_ostream
&OS
) const {
250 OS
<< " if (is" << getLowerName() << "Expr)\n";
251 OS
<< " " << getLowerName() << "Expr = reinterpret_cast<Expr *>("
252 << getUpperName() << ");\n";
254 OS
<< " " << getLowerName()
255 << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName()
258 void writeCtorInitializers(raw_ostream
&OS
) const {
259 OS
<< "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)";
261 void writeCtorParameters(raw_ostream
&OS
) const {
262 OS
<< "bool Is" << getUpperName() << "Expr, void *" << getUpperName();
264 void writeDeclarations(raw_ostream
&OS
) const {
265 OS
<< "bool is" << getLowerName() << "Expr;\n";
267 OS
<< "Expr *" << getLowerName() << "Expr;\n";
268 OS
<< "TypeSourceInfo *" << getLowerName() << "Type;\n";
271 void writePCHReadArgs(raw_ostream
&OS
) const {
272 OS
<< "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr";
274 void writePCHReadDecls(raw_ostream
&OS
) const {
275 OS
<< " bool is" << getLowerName() << "Expr = Record[Idx++];\n";
276 OS
<< " void *" << getLowerName() << "Ptr;\n";
277 OS
<< " if (is" << getLowerName() << "Expr)\n";
278 OS
<< " " << getLowerName() << "Ptr = ReadExpr(F);\n";
280 OS
<< " " << getLowerName()
281 << "Ptr = GetTypeSourceInfo(F, Record, Idx);\n";
283 void writePCHWrite(raw_ostream
&OS
) const {
284 OS
<< " Record.push_back(SA->is" << getUpperName() << "Expr());\n";
285 OS
<< " if (SA->is" << getUpperName() << "Expr())\n";
286 OS
<< " AddStmt(SA->get" << getUpperName() << "Expr());\n";
288 OS
<< " AddTypeSourceInfo(SA->get" << getUpperName()
289 << "Type(), Record);\n";
293 class VariadicArgument
: public Argument
{
297 VariadicArgument(Record
&Arg
, StringRef Attr
, std::string T
)
298 : Argument(Arg
, Attr
), type(T
)
301 std::string
getType() const { return type
; }
303 void writeAccessors(raw_ostream
&OS
) const {
304 OS
<< " typedef " << type
<< "* " << getLowerName() << "_iterator;\n";
305 OS
<< " " << getLowerName() << "_iterator " << getLowerName()
306 << "_begin() const {\n";
307 OS
<< " return " << getLowerName() << ";\n";
309 OS
<< " " << getLowerName() << "_iterator " << getLowerName()
310 << "_end() const {\n";
311 OS
<< " return " << getLowerName() << " + " << getLowerName()
314 OS
<< " unsigned " << getLowerName() << "_size() const {\n"
315 << " return " << getLowerName() << "Size;\n;";
318 void writeCloneArgs(raw_ostream
&OS
) const {
319 OS
<< getLowerName() << ", " << getLowerName() << "Size";
321 void writeCtorBody(raw_ostream
&OS
) const {
322 // FIXME: memcpy is not safe on non-trivial types.
323 OS
<< " std::memcpy(" << getLowerName() << ", " << getUpperName()
324 << ", " << getLowerName() << "Size * sizeof(" << getType() << "));\n";
326 void writeCtorInitializers(raw_ostream
&OS
) const {
327 OS
<< getLowerName() << "Size(" << getUpperName() << "Size), "
328 << getLowerName() << "(new (Ctx, 16) " << getType() << "["
329 << getLowerName() << "Size])";
331 void writeCtorParameters(raw_ostream
&OS
) const {
332 OS
<< getType() << " *" << getUpperName() << ", unsigned "
333 << getUpperName() << "Size";
335 void writeDeclarations(raw_ostream
&OS
) const {
336 OS
<< " unsigned " << getLowerName() << "Size;\n";
337 OS
<< " " << getType() << " *" << getLowerName() << ";";
339 void writePCHReadDecls(raw_ostream
&OS
) const {
340 OS
<< " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
341 OS
<< " llvm::SmallVector<" << type
<< ", 4> " << getLowerName()
343 OS
<< " " << getLowerName() << ".reserve(" << getLowerName()
345 OS
<< " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
347 std::string read
= ReadPCHRecord(type
);
348 OS
<< " " << getLowerName() << ".push_back(" << read
<< ");\n";
350 void writePCHReadArgs(raw_ostream
&OS
) const {
351 OS
<< getLowerName() << ".data(), " << getLowerName() << "Size";
353 void writePCHWrite(raw_ostream
&OS
) const{
354 OS
<< " Record.push_back(SA->" << getLowerName() << "_size());\n";
355 OS
<< " for (" << getAttrName() << "Attr::" << getLowerName()
356 << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
357 << getLowerName() << "_end(); i != e; ++i)\n";
358 OS
<< " " << WritePCHRecord(type
, "(*i)");
362 class EnumArgument
: public Argument
{
364 std::vector
<StringRef
> values
, enums
;
366 EnumArgument(Record
&Arg
, StringRef Attr
)
367 : Argument(Arg
, Attr
), type(Arg
.getValueAsString("Type")),
368 values(getValueAsListOfStrings(Arg
, "Values")),
369 enums(getValueAsListOfStrings(Arg
, "Enums"))
372 void writeAccessors(raw_ostream
&OS
) const {
373 OS
<< " " << type
<< " get" << getUpperName() << "() const {\n";
374 OS
<< " return " << getLowerName() << ";\n";
377 void writeCloneArgs(raw_ostream
&OS
) const {
378 OS
<< getLowerName();
380 void writeCtorInitializers(raw_ostream
&OS
) const {
381 OS
<< getLowerName() << "(" << getUpperName() << ")";
383 void writeCtorParameters(raw_ostream
&OS
) const {
384 OS
<< type
<< " " << getUpperName();
386 void writeDeclarations(raw_ostream
&OS
) const {
387 // Calculate the various enum values
388 std::vector
<StringRef
> uniques(enums
);
389 std::sort(uniques
.begin(), uniques
.end());
390 uniques
.erase(std::unique(uniques
.begin(), uniques
.end()),
392 // FIXME: Emit a proper error
393 assert(!uniques
.empty());
395 std::vector
<StringRef
>::iterator i
= uniques
.begin(),
397 // The last one needs to not have a comma.
401 OS
<< " enum " << type
<< " {\n";
403 OS
<< " " << *i
<< ",\n";
404 OS
<< " " << *e
<< "\n";
407 OS
<< " " << type
<< " " << getLowerName() << ";";
409 void writePCHReadDecls(raw_ostream
&OS
) const {
410 OS
<< " " << getAttrName() << "Attr::" << type
<< " " << getLowerName()
411 << "(static_cast<" << getAttrName() << "Attr::" << type
412 << ">(Record[Idx++]));\n";
414 void writePCHReadArgs(raw_ostream
&OS
) const {
415 OS
<< getLowerName();
417 void writePCHWrite(raw_ostream
&OS
) const {
418 OS
<< "Record.push_back(SA->get" << getUpperName() << "());\n";
422 class VersionArgument
: public Argument
{
424 VersionArgument(Record
&Arg
, StringRef Attr
)
425 : Argument(Arg
, Attr
)
428 void writeAccessors(raw_ostream
&OS
) const {
429 OS
<< " VersionTuple get" << getUpperName() << "() const {\n";
430 OS
<< " return " << getLowerName() << ";\n";
432 OS
<< " void set" << getUpperName()
433 << "(ASTContext &C, VersionTuple V) {\n";
434 OS
<< " " << getLowerName() << " = V;\n";
437 void writeCloneArgs(raw_ostream
&OS
) const {
438 OS
<< "get" << getUpperName() << "()";
440 void writeCtorBody(raw_ostream
&OS
) const {
442 void writeCtorInitializers(raw_ostream
&OS
) const {
443 OS
<< getLowerName() << "(" << getUpperName() << ")";
445 void writeCtorParameters(raw_ostream
&OS
) const {
446 OS
<< "VersionTuple " << getUpperName();
448 void writeDeclarations(raw_ostream
&OS
) const {
449 OS
<< "VersionTuple " << getLowerName() << ";\n";
451 void writePCHReadDecls(raw_ostream
&OS
) const {
452 OS
<< " VersionTuple " << getLowerName()
453 << "= ReadVersionTuple(Record, Idx);\n";
455 void writePCHReadArgs(raw_ostream
&OS
) const {
456 OS
<< getLowerName();
458 void writePCHWrite(raw_ostream
&OS
) const {
459 OS
<< " AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n";
464 static Argument
*createArgument(Record
&Arg
, StringRef Attr
,
465 Record
*Search
= 0) {
470 llvm::StringRef ArgName
= Search
->getName();
472 if (ArgName
== "AlignedArgument") Ptr
= new AlignedArgument(Arg
, Attr
);
473 else if (ArgName
== "EnumArgument") Ptr
= new EnumArgument(Arg
, Attr
);
474 else if (ArgName
== "ExprArgument") Ptr
= new SimpleArgument(Arg
, Attr
,
476 else if (ArgName
== "FunctionArgument")
477 Ptr
= new SimpleArgument(Arg
, Attr
, "FunctionDecl *");
478 else if (ArgName
== "IdentifierArgument")
479 Ptr
= new SimpleArgument(Arg
, Attr
, "IdentifierInfo *");
480 else if (ArgName
== "BoolArgument") Ptr
= new SimpleArgument(Arg
, Attr
,
482 else if (ArgName
== "IntArgument") Ptr
= new SimpleArgument(Arg
, Attr
, "int");
483 else if (ArgName
== "StringArgument") Ptr
= new StringArgument(Arg
, Attr
);
484 else if (ArgName
== "TypeArgument")
485 Ptr
= new SimpleArgument(Arg
, Attr
, "QualType");
486 else if (ArgName
== "UnsignedArgument")
487 Ptr
= new SimpleArgument(Arg
, Attr
, "unsigned");
488 else if (ArgName
== "VariadicUnsignedArgument")
489 Ptr
= new VariadicArgument(Arg
, Attr
, "unsigned");
490 else if (ArgName
== "VersionArgument")
491 Ptr
= new VersionArgument(Arg
, Attr
);
494 std::vector
<Record
*> Bases
= Search
->getSuperClasses();
495 for (std::vector
<Record
*>::iterator i
= Bases
.begin(), e
= Bases
.end();
497 Ptr
= createArgument(Arg
, Attr
, *i
);
505 void ClangAttrClassEmitter::run(raw_ostream
&OS
) {
506 OS
<< "// This file is generated by TableGen. Do not edit.\n\n";
507 OS
<< "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
508 OS
<< "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
510 std::vector
<Record
*> Attrs
= Records
.getAllDerivedDefinitions("Attr");
512 for (std::vector
<Record
*>::iterator i
= Attrs
.begin(), e
= Attrs
.end();
515 const std::string
&SuperName
= R
.getSuperClasses().back()->getName();
517 OS
<< "class " << R
.getName() << "Attr : public " << SuperName
<< " {\n";
519 std::vector
<Record
*> ArgRecords
= R
.getValueAsListOfDefs("Args");
520 std::vector
<Argument
*> Args
;
521 std::vector
<Argument
*>::iterator ai
, ae
;
522 Args
.reserve(ArgRecords
.size());
524 for (std::vector
<Record
*>::iterator ri
= ArgRecords
.begin(),
525 re
= ArgRecords
.end();
527 Record
&ArgRecord
= **ri
;
528 Argument
*Arg
= createArgument(ArgRecord
, R
.getName());
532 Arg
->writeDeclarations(OS
);
538 OS
<< "\n public:\n";
539 OS
<< " " << R
.getName() << "Attr(SourceLocation L, ASTContext &Ctx\n";
541 for (ai
= Args
.begin(); ai
!= ae
; ++ai
) {
543 (*ai
)->writeCtorParameters(OS
);
548 OS
<< " : " << SuperName
<< "(attr::" << R
.getName() << ", L)\n";
550 for (ai
= Args
.begin(); ai
!= ae
; ++ai
) {
552 (*ai
)->writeCtorInitializers(OS
);
558 for (ai
= Args
.begin(); ai
!= ae
; ++ai
) {
559 (*ai
)->writeCtorBody(OS
);
564 OS
<< " virtual " << R
.getName() << "Attr *clone (ASTContext &C) const;\n";
566 for (ai
= Args
.begin(); ai
!= ae
; ++ai
) {
567 (*ai
)->writeAccessors(OS
);
571 OS
<< R
.getValueAsCode("AdditionalMembers");
574 OS
<< " static bool classof(const Attr *A) { return A->getKind() == "
575 << "attr::" << R
.getName() << "; }\n";
576 OS
<< " static bool classof(const " << R
.getName()
577 << "Attr *) { return true; }\n";
584 void ClangAttrImplEmitter::run(raw_ostream
&OS
) {
585 OS
<< "// This file is generated by TableGen. Do not edit.\n\n";
587 std::vector
<Record
*> Attrs
= Records
.getAllDerivedDefinitions("Attr");
588 std::vector
<Record
*>::iterator i
= Attrs
.begin(), e
= Attrs
.end(), ri
, re
;
589 std::vector
<Argument
*>::iterator ai
, ae
;
591 for (; i
!= e
; ++i
) {
593 std::vector
<Record
*> ArgRecords
= R
.getValueAsListOfDefs("Args");
594 std::vector
<Argument
*> Args
;
595 for (ri
= ArgRecords
.begin(), re
= ArgRecords
.end(); ri
!= re
; ++ri
)
596 Args
.push_back(createArgument(**ri
, R
.getName()));
598 for (ai
= Args
.begin(), ae
= Args
.end(); ai
!= ae
; ++ai
)
599 (*ai
)->writeAccessorDefinitions(OS
);
601 OS
<< R
.getName() << "Attr *" << R
.getName()
602 << "Attr::clone(ASTContext &C) const {\n";
603 OS
<< " return new (C) " << R
.getName() << "Attr(getLocation(), C";
604 for (ai
= Args
.begin(); ai
!= ae
; ++ai
) {
606 (*ai
)->writeCloneArgs(OS
);
612 static void EmitAttrList(raw_ostream
&OS
, StringRef Class
,
613 const std::vector
<Record
*> &AttrList
) {
614 std::vector
<Record
*>::const_iterator i
= AttrList
.begin(), e
= AttrList
.end();
617 // Move the end iterator back to emit the last attribute.
618 for(--e
; i
!= e
; ++i
)
619 OS
<< Class
<< "(" << (*i
)->getName() << ")\n";
621 OS
<< "LAST_" << Class
<< "(" << (*i
)->getName() << ")\n\n";
625 void ClangAttrListEmitter::run(raw_ostream
&OS
) {
626 OS
<< "// This file is generated by TableGen. Do not edit.\n\n";
628 OS
<< "#ifndef LAST_ATTR\n";
629 OS
<< "#define LAST_ATTR(NAME) ATTR(NAME)\n";
632 OS
<< "#ifndef INHERITABLE_ATTR\n";
633 OS
<< "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n";
636 OS
<< "#ifndef LAST_INHERITABLE_ATTR\n";
637 OS
<< "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n";
640 OS
<< "#ifndef INHERITABLE_PARAM_ATTR\n";
641 OS
<< "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n";
644 OS
<< "#ifndef LAST_INHERITABLE_PARAM_ATTR\n";
645 OS
<< "#define LAST_INHERITABLE_PARAM_ATTR(NAME)"
646 " INHERITABLE_PARAM_ATTR(NAME)\n";
649 Record
*InhClass
= Records
.getClass("InheritableAttr");
650 Record
*InhParamClass
= Records
.getClass("InheritableParamAttr");
651 std::vector
<Record
*> Attrs
= Records
.getAllDerivedDefinitions("Attr"),
652 NonInhAttrs
, InhAttrs
, InhParamAttrs
;
653 for (std::vector
<Record
*>::iterator i
= Attrs
.begin(), e
= Attrs
.end();
655 if ((*i
)->isSubClassOf(InhParamClass
))
656 InhParamAttrs
.push_back(*i
);
657 else if ((*i
)->isSubClassOf(InhClass
))
658 InhAttrs
.push_back(*i
);
660 NonInhAttrs
.push_back(*i
);
663 EmitAttrList(OS
, "INHERITABLE_PARAM_ATTR", InhParamAttrs
);
664 EmitAttrList(OS
, "INHERITABLE_ATTR", InhAttrs
);
665 EmitAttrList(OS
, "ATTR", NonInhAttrs
);
667 OS
<< "#undef LAST_ATTR\n";
668 OS
<< "#undef INHERITABLE_ATTR\n";
669 OS
<< "#undef LAST_INHERITABLE_ATTR\n";
670 OS
<< "#undef LAST_INHERITABLE_PARAM_ATTR\n";
671 OS
<< "#undef ATTR\n";
674 void ClangAttrPCHReadEmitter::run(raw_ostream
&OS
) {
675 OS
<< "// This file is generated by TableGen. Do not edit.\n\n";
677 Record
*InhClass
= Records
.getClass("InheritableAttr");
678 std::vector
<Record
*> Attrs
= Records
.getAllDerivedDefinitions("Attr"),
680 std::vector
<Record
*>::iterator i
= Attrs
.begin(), e
= Attrs
.end(), ai
, ae
;
681 std::vector
<Argument
*> Args
;
682 std::vector
<Argument
*>::iterator ri
, re
;
684 OS
<< " switch (Kind) {\n";
686 OS
<< " assert(0 && \"Unknown attribute!\");\n";
688 for (; i
!= e
; ++i
) {
690 OS
<< " case attr::" << R
.getName() << ": {\n";
691 if (R
.isSubClassOf(InhClass
))
692 OS
<< " bool isInherited = Record[Idx++];\n";
693 ArgRecords
= R
.getValueAsListOfDefs("Args");
695 for (ai
= ArgRecords
.begin(), ae
= ArgRecords
.end(); ai
!= ae
; ++ai
) {
696 Argument
*A
= createArgument(**ai
, R
.getName());
698 A
->writePCHReadDecls(OS
);
700 OS
<< " New = new (*Context) " << R
.getName() << "Attr(Loc, *Context";
701 for (ri
= Args
.begin(), re
= Args
.end(); ri
!= re
; ++ri
) {
703 (*ri
)->writePCHReadArgs(OS
);
706 if (R
.isSubClassOf(InhClass
))
707 OS
<< " cast<InheritableAttr>(New)->setInherited(isInherited);\n";
714 void ClangAttrPCHWriteEmitter::run(raw_ostream
&OS
) {
715 Record
*InhClass
= Records
.getClass("InheritableAttr");
716 std::vector
<Record
*> Attrs
= Records
.getAllDerivedDefinitions("Attr"), Args
;
717 std::vector
<Record
*>::iterator i
= Attrs
.begin(), e
= Attrs
.end(), ai
, ae
;
719 OS
<< " switch (A->getKind()) {\n";
721 OS
<< " llvm_unreachable(\"Unknown attribute kind!\");\n";
723 for (; i
!= e
; ++i
) {
725 OS
<< " case attr::" << R
.getName() << ": {\n";
726 Args
= R
.getValueAsListOfDefs("Args");
727 if (R
.isSubClassOf(InhClass
) || !Args
.empty())
728 OS
<< " const " << R
.getName() << "Attr *SA = cast<" << R
.getName()
730 if (R
.isSubClassOf(InhClass
))
731 OS
<< " Record.push_back(SA->isInherited());\n";
732 for (ai
= Args
.begin(), ae
= Args
.end(); ai
!= ae
; ++ai
)
733 createArgument(**ai
, R
.getName())->writePCHWrite(OS
);
740 void ClangAttrSpellingListEmitter::run(raw_ostream
&OS
) {
741 OS
<< "// This file is generated by TableGen. Do not edit.\n\n";
743 std::vector
<Record
*> Attrs
= Records
.getAllDerivedDefinitions("Attr");
745 for (std::vector
<Record
*>::iterator I
= Attrs
.begin(), E
= Attrs
.end(); I
!= E
; ++I
) {
748 std::vector
<StringRef
> Spellings
= getValueAsListOfStrings(Attr
, "Spellings");
750 for (std::vector
<StringRef
>::const_iterator I
= Spellings
.begin(), E
= Spellings
.end(); I
!= E
; ++I
) {
751 StringRef Spelling
= *I
;
752 OS
<< ".Case(\"" << Spelling
<< "\", true)\n";