blob: 58d8fc1381a12c9c4fc9eff40596e0b33c1fd8c6 [file] [log] [blame]
Peter Collingbournebee583f2011-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
Alexis Hunta0e54d42012-06-18 16:13:52 +000014#include "llvm/ADT/SmallString.h"
Aaron Ballman8ee40b72013-09-09 23:33:17 +000015#include "llvm/ADT/SmallSet.h"
Chandler Carruth5553d0d2014-01-07 11:51:46 +000016#include "llvm/ADT/StringSwitch.h"
Aaron Ballman36a53502014-01-16 13:03:14 +000017#include "llvm/ADT/STLExtras.h"
Chandler Carruth5553d0d2014-01-07 11:51:46 +000018#include "llvm/TableGen/Error.h"
Peter Collingbournebee583f2011-10-06 13:03:08 +000019#include "llvm/TableGen/Record.h"
Douglas Gregor377f99b2012-05-02 17:33:51 +000020#include "llvm/TableGen/StringMatcher.h"
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +000021#include "llvm/TableGen/TableGenBackend.h"
Peter Collingbournebee583f2011-10-06 13:03:08 +000022#include <algorithm>
23#include <cctype>
Aaron Ballman80469032013-11-29 14:57:58 +000024#include <set>
Chandler Carruth5553d0d2014-01-07 11:51:46 +000025#include <sstream>
Peter Collingbournebee583f2011-10-06 13:03:08 +000026
27using namespace llvm;
28
Aaron Ballmanc669cc02014-01-27 22:10:04 +000029class FlattenedSpelling {
30 std::string V, N, NS;
31 bool K;
32
33public:
34 FlattenedSpelling(const std::string &Variety, const std::string &Name,
35 const std::string &Namespace, bool KnownToGCC) :
36 V(Variety), N(Name), NS(Namespace), K(KnownToGCC) {}
37 explicit FlattenedSpelling(const Record &Spelling) :
38 V(Spelling.getValueAsString("Variety")),
39 N(Spelling.getValueAsString("Name")) {
40
41 assert(V != "GCC" && "Given a GCC spelling, which means this hasn't been"
42 "flattened!");
43 if (V == "CXX11")
44 NS = Spelling.getValueAsString("Namespace");
45 bool Unset;
46 K = Spelling.getValueAsBitOrUnset("KnownToGCC", Unset);
47 }
48
49 const std::string &variety() const { return V; }
50 const std::string &name() const { return N; }
51 const std::string &nameSpace() const { return NS; }
52 bool knownToGCC() const { return K; }
53};
54
55std::vector<FlattenedSpelling> GetFlattenedSpellings(const Record &Attr) {
56 std::vector<Record *> Spellings = Attr.getValueAsListOfDefs("Spellings");
57 std::vector<FlattenedSpelling> Ret;
58
59 for (std::vector<Record *>::const_iterator I = Spellings.begin(),
60 E = Spellings.end(); I != E; ++I) {
61 const Record &Spelling = **I;
62
63 if (Spelling.getValueAsString("Variety") == "GCC") {
64 // Gin up two new spelling objects to add into the list.
65 Ret.push_back(FlattenedSpelling("GNU", Spelling.getValueAsString("Name"),
66 "", true));
67 Ret.push_back(FlattenedSpelling("CXX11",
68 Spelling.getValueAsString("Name"),
69 "gnu", true));
70 } else
71 Ret.push_back(FlattenedSpelling(Spelling));
72 }
73
74 return Ret;
75}
76
Peter Collingbournebee583f2011-10-06 13:03:08 +000077static std::string ReadPCHRecord(StringRef type) {
78 return StringSwitch<std::string>(type)
79 .EndsWith("Decl *", "GetLocalDeclAs<"
80 + std::string(type, 0, type.size()-1) + ">(F, Record[Idx++])")
Richard Smithb87c4652013-10-31 21:23:20 +000081 .Case("TypeSourceInfo *", "GetTypeSourceInfo(F, Record, Idx)")
Argyrios Kyrtzidisa660ae42012-11-15 01:31:39 +000082 .Case("Expr *", "ReadExpr(F)")
Peter Collingbournebee583f2011-10-06 13:03:08 +000083 .Case("IdentifierInfo *", "GetIdentifierInfo(F, Record, Idx)")
Peter Collingbournebee583f2011-10-06 13:03:08 +000084 .Default("Record[Idx++]");
85}
86
87// Assumes that the way to get the value is SA->getname()
88static std::string WritePCHRecord(StringRef type, StringRef name) {
89 return StringSwitch<std::string>(type)
90 .EndsWith("Decl *", "AddDeclRef(" + std::string(name) +
91 ", Record);\n")
Richard Smithb87c4652013-10-31 21:23:20 +000092 .Case("TypeSourceInfo *",
93 "AddTypeSourceInfo(" + std::string(name) + ", Record);\n")
Peter Collingbournebee583f2011-10-06 13:03:08 +000094 .Case("Expr *", "AddStmt(" + std::string(name) + ");\n")
95 .Case("IdentifierInfo *",
96 "AddIdentifierRef(" + std::string(name) + ", Record);\n")
Peter Collingbournebee583f2011-10-06 13:03:08 +000097 .Default("Record.push_back(" + std::string(name) + ");\n");
98}
99
Michael Han4a045172012-03-07 00:12:16 +0000100// Normalize attribute name by removing leading and trailing
101// underscores. For example, __foo, foo__, __foo__ would
102// become foo.
103static StringRef NormalizeAttrName(StringRef AttrName) {
104 if (AttrName.startswith("__"))
105 AttrName = AttrName.substr(2, AttrName.size());
106
107 if (AttrName.endswith("__"))
108 AttrName = AttrName.substr(0, AttrName.size() - 2);
109
110 return AttrName;
111}
112
Aaron Ballman36a53502014-01-16 13:03:14 +0000113// Normalize the name by removing any and all leading and trailing underscores.
114// This is different from NormalizeAttrName in that it also handles names like
115// _pascal and __pascal.
116static StringRef NormalizeNameForSpellingComparison(StringRef Name) {
117 while (Name.startswith("_"))
118 Name = Name.substr(1, Name.size());
119 while (Name.endswith("_"))
120 Name = Name.substr(0, Name.size() - 1);
121 return Name;
122}
123
Michael Han4a045172012-03-07 00:12:16 +0000124// Normalize attribute spelling only if the spelling has both leading
125// and trailing underscores. For example, __ms_struct__ will be
126// normalized to "ms_struct"; __cdecl will remain intact.
127static StringRef NormalizeAttrSpelling(StringRef AttrSpelling) {
128 if (AttrSpelling.startswith("__") && AttrSpelling.endswith("__")) {
129 AttrSpelling = AttrSpelling.substr(2, AttrSpelling.size() - 4);
130 }
131
132 return AttrSpelling;
133}
134
Aaron Ballman64e69862013-12-15 13:05:48 +0000135typedef std::vector<std::pair<std::string, Record *> > ParsedAttrMap;
136
Aaron Ballmanab7691c2014-01-09 22:48:32 +0000137static ParsedAttrMap getParsedAttrList(const RecordKeeper &Records,
138 ParsedAttrMap *Dupes = 0) {
Aaron Ballman64e69862013-12-15 13:05:48 +0000139 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
140 std::set<std::string> Seen;
141 ParsedAttrMap R;
142 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
143 I != E; ++I) {
144 Record &Attr = **I;
145 if (Attr.getValueAsBit("SemaHandler")) {
146 std::string AN;
147 if (Attr.isSubClassOf("TargetSpecificAttr") &&
148 !Attr.isValueUnset("ParseKind")) {
149 AN = Attr.getValueAsString("ParseKind");
150
151 // If this attribute has already been handled, it does not need to be
152 // handled again.
Aaron Ballmanab7691c2014-01-09 22:48:32 +0000153 if (Seen.find(AN) != Seen.end()) {
154 if (Dupes)
155 Dupes->push_back(std::make_pair(AN, *I));
Aaron Ballman64e69862013-12-15 13:05:48 +0000156 continue;
Aaron Ballmanab7691c2014-01-09 22:48:32 +0000157 }
Aaron Ballman64e69862013-12-15 13:05:48 +0000158 Seen.insert(AN);
159 } else
160 AN = NormalizeAttrName(Attr.getName()).str();
161
162 R.push_back(std::make_pair(AN, *I));
163 }
164 }
165 return R;
166}
167
Peter Collingbournebee583f2011-10-06 13:03:08 +0000168namespace {
169 class Argument {
170 std::string lowerName, upperName;
171 StringRef attrName;
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000172 bool isOpt;
Peter Collingbournebee583f2011-10-06 13:03:08 +0000173
174 public:
175 Argument(Record &Arg, StringRef Attr)
176 : lowerName(Arg.getValueAsString("Name")), upperName(lowerName),
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000177 attrName(Attr), isOpt(false) {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000178 if (!lowerName.empty()) {
179 lowerName[0] = std::tolower(lowerName[0]);
180 upperName[0] = std::toupper(upperName[0]);
181 }
182 }
183 virtual ~Argument() {}
184
185 StringRef getLowerName() const { return lowerName; }
186 StringRef getUpperName() const { return upperName; }
187 StringRef getAttrName() const { return attrName; }
188
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000189 bool isOptional() const { return isOpt; }
190 void setOptional(bool set) { isOpt = set; }
191
Peter Collingbournebee583f2011-10-06 13:03:08 +0000192 // These functions print the argument contents formatted in different ways.
193 virtual void writeAccessors(raw_ostream &OS) const = 0;
194 virtual void writeAccessorDefinitions(raw_ostream &OS) const {}
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +0000195 virtual void writeASTVisitorTraversal(raw_ostream &OS) const {}
Peter Collingbournebee583f2011-10-06 13:03:08 +0000196 virtual void writeCloneArgs(raw_ostream &OS) const = 0;
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000197 virtual void writeTemplateInstantiationArgs(raw_ostream &OS) const = 0;
Daniel Dunbardc51baa2012-02-10 06:00:29 +0000198 virtual void writeTemplateInstantiation(raw_ostream &OS) const {}
Peter Collingbournebee583f2011-10-06 13:03:08 +0000199 virtual void writeCtorBody(raw_ostream &OS) const {}
200 virtual void writeCtorInitializers(raw_ostream &OS) const = 0;
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000201 virtual void writeCtorDefaultInitializers(raw_ostream &OS) const = 0;
Peter Collingbournebee583f2011-10-06 13:03:08 +0000202 virtual void writeCtorParameters(raw_ostream &OS) const = 0;
203 virtual void writeDeclarations(raw_ostream &OS) const = 0;
204 virtual void writePCHReadArgs(raw_ostream &OS) const = 0;
205 virtual void writePCHReadDecls(raw_ostream &OS) const = 0;
206 virtual void writePCHWrite(raw_ostream &OS) const = 0;
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000207 virtual void writeValue(raw_ostream &OS) const = 0;
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000208 virtual void writeDump(raw_ostream &OS) const = 0;
209 virtual void writeDumpChildren(raw_ostream &OS) const {}
Richard Trieude5cc7d2013-01-31 01:44:26 +0000210 virtual void writeHasChildren(raw_ostream &OS) const { OS << "false"; }
Aaron Ballman682ee422013-09-11 19:47:58 +0000211
212 virtual bool isEnumArg() const { return false; }
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000213 virtual bool isVariadicEnumArg() const { return false; }
Aaron Ballman36a53502014-01-16 13:03:14 +0000214
215 virtual void writeImplicitCtorArgs(raw_ostream &OS) const {
216 OS << getUpperName();
217 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000218 };
219
220 class SimpleArgument : public Argument {
221 std::string type;
222
223 public:
224 SimpleArgument(Record &Arg, StringRef Attr, std::string T)
225 : Argument(Arg, Attr), type(T)
226 {}
227
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000228 std::string getType() const { return type; }
229
Peter Collingbournebee583f2011-10-06 13:03:08 +0000230 void writeAccessors(raw_ostream &OS) const {
231 OS << " " << type << " get" << getUpperName() << "() const {\n";
232 OS << " return " << getLowerName() << ";\n";
233 OS << " }";
234 }
235 void writeCloneArgs(raw_ostream &OS) const {
236 OS << getLowerName();
237 }
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000238 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
239 OS << "A->get" << getUpperName() << "()";
240 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000241 void writeCtorInitializers(raw_ostream &OS) const {
242 OS << getLowerName() << "(" << getUpperName() << ")";
243 }
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000244 void writeCtorDefaultInitializers(raw_ostream &OS) const {
245 OS << getLowerName() << "()";
246 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000247 void writeCtorParameters(raw_ostream &OS) const {
248 OS << type << " " << getUpperName();
249 }
250 void writeDeclarations(raw_ostream &OS) const {
251 OS << type << " " << getLowerName() << ";";
252 }
253 void writePCHReadDecls(raw_ostream &OS) const {
254 std::string read = ReadPCHRecord(type);
255 OS << " " << type << " " << getLowerName() << " = " << read << ";\n";
256 }
257 void writePCHReadArgs(raw_ostream &OS) const {
258 OS << getLowerName();
259 }
260 void writePCHWrite(raw_ostream &OS) const {
261 OS << " " << WritePCHRecord(type, "SA->get" +
262 std::string(getUpperName()) + "()");
263 }
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000264 void writeValue(raw_ostream &OS) const {
265 if (type == "FunctionDecl *") {
Richard Smithb87c4652013-10-31 21:23:20 +0000266 OS << "\" << get" << getUpperName()
267 << "()->getNameInfo().getAsString() << \"";
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000268 } else if (type == "IdentifierInfo *") {
269 OS << "\" << get" << getUpperName() << "()->getName() << \"";
Richard Smithb87c4652013-10-31 21:23:20 +0000270 } else if (type == "TypeSourceInfo *") {
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000271 OS << "\" << get" << getUpperName() << "().getAsString() << \"";
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000272 } else {
273 OS << "\" << get" << getUpperName() << "() << \"";
274 }
275 }
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000276 void writeDump(raw_ostream &OS) const {
277 if (type == "FunctionDecl *") {
278 OS << " OS << \" \";\n";
279 OS << " dumpBareDeclRef(SA->get" << getUpperName() << "());\n";
280 } else if (type == "IdentifierInfo *") {
281 OS << " OS << \" \" << SA->get" << getUpperName()
282 << "()->getName();\n";
Richard Smithb87c4652013-10-31 21:23:20 +0000283 } else if (type == "TypeSourceInfo *") {
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000284 OS << " OS << \" \" << SA->get" << getUpperName()
285 << "().getAsString();\n";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000286 } else if (type == "bool") {
287 OS << " if (SA->get" << getUpperName() << "()) OS << \" "
288 << getUpperName() << "\";\n";
289 } else if (type == "int" || type == "unsigned") {
290 OS << " OS << \" \" << SA->get" << getUpperName() << "();\n";
291 } else {
292 llvm_unreachable("Unknown SimpleArgument type!");
293 }
294 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000295 };
296
Aaron Ballman18a78382013-11-21 00:28:23 +0000297 class DefaultSimpleArgument : public SimpleArgument {
298 int64_t Default;
299
300 public:
301 DefaultSimpleArgument(Record &Arg, StringRef Attr,
302 std::string T, int64_t Default)
303 : SimpleArgument(Arg, Attr, T), Default(Default) {}
304
305 void writeAccessors(raw_ostream &OS) const {
306 SimpleArgument::writeAccessors(OS);
307
308 OS << "\n\n static const " << getType() << " Default" << getUpperName()
309 << " = " << Default << ";";
310 }
311 };
312
Peter Collingbournebee583f2011-10-06 13:03:08 +0000313 class StringArgument : public Argument {
314 public:
315 StringArgument(Record &Arg, StringRef Attr)
316 : Argument(Arg, Attr)
317 {}
318
319 void writeAccessors(raw_ostream &OS) const {
320 OS << " llvm::StringRef get" << getUpperName() << "() const {\n";
321 OS << " return llvm::StringRef(" << getLowerName() << ", "
322 << getLowerName() << "Length);\n";
323 OS << " }\n";
324 OS << " unsigned get" << getUpperName() << "Length() const {\n";
325 OS << " return " << getLowerName() << "Length;\n";
326 OS << " }\n";
327 OS << " void set" << getUpperName()
328 << "(ASTContext &C, llvm::StringRef S) {\n";
329 OS << " " << getLowerName() << "Length = S.size();\n";
330 OS << " this->" << getLowerName() << " = new (C, 1) char ["
331 << getLowerName() << "Length];\n";
332 OS << " std::memcpy(this->" << getLowerName() << ", S.data(), "
333 << getLowerName() << "Length);\n";
334 OS << " }";
335 }
336 void writeCloneArgs(raw_ostream &OS) const {
337 OS << "get" << getUpperName() << "()";
338 }
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000339 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
340 OS << "A->get" << getUpperName() << "()";
341 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000342 void writeCtorBody(raw_ostream &OS) const {
343 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
344 << ".data(), " << getLowerName() << "Length);";
345 }
346 void writeCtorInitializers(raw_ostream &OS) const {
347 OS << getLowerName() << "Length(" << getUpperName() << ".size()),"
348 << getLowerName() << "(new (Ctx, 1) char[" << getLowerName()
349 << "Length])";
350 }
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000351 void writeCtorDefaultInitializers(raw_ostream &OS) const {
352 OS << getLowerName() << "Length(0)," << getLowerName() << "(0)";
353 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000354 void writeCtorParameters(raw_ostream &OS) const {
355 OS << "llvm::StringRef " << getUpperName();
356 }
357 void writeDeclarations(raw_ostream &OS) const {
358 OS << "unsigned " << getLowerName() << "Length;\n";
359 OS << "char *" << getLowerName() << ";";
360 }
361 void writePCHReadDecls(raw_ostream &OS) const {
362 OS << " std::string " << getLowerName()
363 << "= ReadString(Record, Idx);\n";
364 }
365 void writePCHReadArgs(raw_ostream &OS) const {
366 OS << getLowerName();
367 }
368 void writePCHWrite(raw_ostream &OS) const {
369 OS << " AddString(SA->get" << getUpperName() << "(), Record);\n";
370 }
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000371 void writeValue(raw_ostream &OS) const {
372 OS << "\\\"\" << get" << getUpperName() << "() << \"\\\"";
373 }
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000374 void writeDump(raw_ostream &OS) const {
375 OS << " OS << \" \\\"\" << SA->get" << getUpperName()
376 << "() << \"\\\"\";\n";
377 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000378 };
379
380 class AlignedArgument : public Argument {
381 public:
382 AlignedArgument(Record &Arg, StringRef Attr)
383 : Argument(Arg, Attr)
384 {}
385
386 void writeAccessors(raw_ostream &OS) const {
387 OS << " bool is" << getUpperName() << "Dependent() const;\n";
388
389 OS << " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n";
390
391 OS << " bool is" << getUpperName() << "Expr() const {\n";
392 OS << " return is" << getLowerName() << "Expr;\n";
393 OS << " }\n";
394
395 OS << " Expr *get" << getUpperName() << "Expr() const {\n";
396 OS << " assert(is" << getLowerName() << "Expr);\n";
397 OS << " return " << getLowerName() << "Expr;\n";
398 OS << " }\n";
399
400 OS << " TypeSourceInfo *get" << getUpperName() << "Type() const {\n";
401 OS << " assert(!is" << getLowerName() << "Expr);\n";
402 OS << " return " << getLowerName() << "Type;\n";
403 OS << " }";
404 }
405 void writeAccessorDefinitions(raw_ostream &OS) const {
406 OS << "bool " << getAttrName() << "Attr::is" << getUpperName()
407 << "Dependent() const {\n";
408 OS << " if (is" << getLowerName() << "Expr)\n";
409 OS << " return " << getLowerName() << "Expr && (" << getLowerName()
410 << "Expr->isValueDependent() || " << getLowerName()
411 << "Expr->isTypeDependent());\n";
412 OS << " else\n";
413 OS << " return " << getLowerName()
414 << "Type->getType()->isDependentType();\n";
415 OS << "}\n";
416
417 // FIXME: Do not do the calculation here
418 // FIXME: Handle types correctly
419 // A null pointer means maximum alignment
420 // FIXME: Load the platform-specific maximum alignment, rather than
421 // 16, the x86 max.
422 OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName()
423 << "(ASTContext &Ctx) const {\n";
424 OS << " assert(!is" << getUpperName() << "Dependent());\n";
425 OS << " if (is" << getLowerName() << "Expr)\n";
426 OS << " return (" << getLowerName() << "Expr ? " << getLowerName()
Richard Smithcaf33902011-10-10 18:28:20 +0000427 << "Expr->EvaluateKnownConstInt(Ctx).getZExtValue() : 16)"
Peter Collingbournebee583f2011-10-06 13:03:08 +0000428 << "* Ctx.getCharWidth();\n";
429 OS << " else\n";
430 OS << " return 0; // FIXME\n";
431 OS << "}\n";
432 }
433 void writeCloneArgs(raw_ostream &OS) const {
434 OS << "is" << getLowerName() << "Expr, is" << getLowerName()
435 << "Expr ? static_cast<void*>(" << getLowerName()
436 << "Expr) : " << getLowerName()
437 << "Type";
438 }
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000439 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
440 // FIXME: move the definition in Sema::InstantiateAttrs to here.
441 // In the meantime, aligned attributes are cloned.
442 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000443 void writeCtorBody(raw_ostream &OS) const {
444 OS << " if (is" << getLowerName() << "Expr)\n";
445 OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>("
446 << getUpperName() << ");\n";
447 OS << " else\n";
448 OS << " " << getLowerName()
449 << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName()
450 << ");";
451 }
452 void writeCtorInitializers(raw_ostream &OS) const {
453 OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)";
454 }
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000455 void writeCtorDefaultInitializers(raw_ostream &OS) const {
456 OS << "is" << getLowerName() << "Expr(false)";
457 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000458 void writeCtorParameters(raw_ostream &OS) const {
459 OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName();
460 }
Aaron Ballman36a53502014-01-16 13:03:14 +0000461 void writeImplicitCtorArgs(raw_ostream &OS) const {
462 OS << "Is" << getUpperName() << "Expr, " << getUpperName();
463 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000464 void writeDeclarations(raw_ostream &OS) const {
465 OS << "bool is" << getLowerName() << "Expr;\n";
466 OS << "union {\n";
467 OS << "Expr *" << getLowerName() << "Expr;\n";
468 OS << "TypeSourceInfo *" << getLowerName() << "Type;\n";
469 OS << "};";
470 }
471 void writePCHReadArgs(raw_ostream &OS) const {
472 OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr";
473 }
474 void writePCHReadDecls(raw_ostream &OS) const {
475 OS << " bool is" << getLowerName() << "Expr = Record[Idx++];\n";
476 OS << " void *" << getLowerName() << "Ptr;\n";
477 OS << " if (is" << getLowerName() << "Expr)\n";
478 OS << " " << getLowerName() << "Ptr = ReadExpr(F);\n";
479 OS << " else\n";
480 OS << " " << getLowerName()
481 << "Ptr = GetTypeSourceInfo(F, Record, Idx);\n";
482 }
483 void writePCHWrite(raw_ostream &OS) const {
484 OS << " Record.push_back(SA->is" << getUpperName() << "Expr());\n";
485 OS << " if (SA->is" << getUpperName() << "Expr())\n";
486 OS << " AddStmt(SA->get" << getUpperName() << "Expr());\n";
487 OS << " else\n";
488 OS << " AddTypeSourceInfo(SA->get" << getUpperName()
489 << "Type(), Record);\n";
490 }
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000491 void writeValue(raw_ostream &OS) const {
Richard Smith52f04a22012-08-16 02:43:29 +0000492 OS << "\";\n"
493 << " " << getLowerName() << "Expr->printPretty(OS, 0, Policy);\n"
494 << " OS << \"";
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000495 }
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000496 void writeDump(raw_ostream &OS) const {
497 }
498 void writeDumpChildren(raw_ostream &OS) const {
Richard Trieude5cc7d2013-01-31 01:44:26 +0000499 OS << " if (SA->is" << getUpperName() << "Expr()) {\n";
500 OS << " lastChild();\n";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000501 OS << " dumpStmt(SA->get" << getUpperName() << "Expr());\n";
Richard Trieude5cc7d2013-01-31 01:44:26 +0000502 OS << " } else\n";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000503 OS << " dumpType(SA->get" << getUpperName()
504 << "Type()->getType());\n";
505 }
Richard Trieude5cc7d2013-01-31 01:44:26 +0000506 void writeHasChildren(raw_ostream &OS) const {
507 OS << "SA->is" << getUpperName() << "Expr()";
508 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000509 };
510
511 class VariadicArgument : public Argument {
512 std::string type;
513
514 public:
515 VariadicArgument(Record &Arg, StringRef Attr, std::string T)
516 : Argument(Arg, Attr), type(T)
517 {}
518
519 std::string getType() const { return type; }
520
521 void writeAccessors(raw_ostream &OS) const {
522 OS << " typedef " << type << "* " << getLowerName() << "_iterator;\n";
523 OS << " " << getLowerName() << "_iterator " << getLowerName()
524 << "_begin() const {\n";
525 OS << " return " << getLowerName() << ";\n";
526 OS << " }\n";
527 OS << " " << getLowerName() << "_iterator " << getLowerName()
528 << "_end() const {\n";
529 OS << " return " << getLowerName() << " + " << getLowerName()
530 << "Size;\n";
531 OS << " }\n";
532 OS << " unsigned " << getLowerName() << "_size() const {\n"
DeLesley Hutchins30398dd2012-01-20 22:50:54 +0000533 << " return " << getLowerName() << "Size;\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +0000534 OS << " }";
535 }
536 void writeCloneArgs(raw_ostream &OS) const {
537 OS << getLowerName() << ", " << getLowerName() << "Size";
538 }
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000539 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
540 // This isn't elegant, but we have to go through public methods...
541 OS << "A->" << getLowerName() << "_begin(), "
542 << "A->" << getLowerName() << "_size()";
543 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000544 void writeCtorBody(raw_ostream &OS) const {
545 // FIXME: memcpy is not safe on non-trivial types.
546 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
547 << ", " << getLowerName() << "Size * sizeof(" << getType() << "));\n";
548 }
549 void writeCtorInitializers(raw_ostream &OS) const {
550 OS << getLowerName() << "Size(" << getUpperName() << "Size), "
551 << getLowerName() << "(new (Ctx, 16) " << getType() << "["
552 << getLowerName() << "Size])";
553 }
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000554 void writeCtorDefaultInitializers(raw_ostream &OS) const {
555 OS << getLowerName() << "Size(0), " << getLowerName() << "(0)";
556 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000557 void writeCtorParameters(raw_ostream &OS) const {
558 OS << getType() << " *" << getUpperName() << ", unsigned "
559 << getUpperName() << "Size";
560 }
Aaron Ballman36a53502014-01-16 13:03:14 +0000561 void writeImplicitCtorArgs(raw_ostream &OS) const {
562 OS << getUpperName() << ", " << getUpperName() << "Size";
563 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000564 void writeDeclarations(raw_ostream &OS) const {
565 OS << " unsigned " << getLowerName() << "Size;\n";
566 OS << " " << getType() << " *" << getLowerName() << ";";
567 }
568 void writePCHReadDecls(raw_ostream &OS) const {
569 OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000570 OS << " SmallVector<" << type << ", 4> " << getLowerName()
Peter Collingbournebee583f2011-10-06 13:03:08 +0000571 << ";\n";
572 OS << " " << getLowerName() << ".reserve(" << getLowerName()
573 << "Size);\n";
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000574 OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +0000575
576 std::string read = ReadPCHRecord(type);
577 OS << " " << getLowerName() << ".push_back(" << read << ");\n";
578 }
579 void writePCHReadArgs(raw_ostream &OS) const {
580 OS << getLowerName() << ".data(), " << getLowerName() << "Size";
581 }
582 void writePCHWrite(raw_ostream &OS) const{
583 OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";
584 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
585 << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
586 << getLowerName() << "_end(); i != e; ++i)\n";
587 OS << " " << WritePCHRecord(type, "(*i)");
588 }
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000589 void writeValue(raw_ostream &OS) const {
590 OS << "\";\n";
591 OS << " bool isFirst = true;\n"
592 << " for (" << getAttrName() << "Attr::" << getLowerName()
593 << "_iterator i = " << getLowerName() << "_begin(), e = "
594 << getLowerName() << "_end(); i != e; ++i) {\n"
595 << " if (isFirst) isFirst = false;\n"
596 << " else OS << \", \";\n"
597 << " OS << *i;\n"
598 << " }\n";
599 OS << " OS << \"";
600 }
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000601 void writeDump(raw_ostream &OS) const {
602 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
603 << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
604 << getLowerName() << "_end(); I != E; ++I)\n";
605 OS << " OS << \" \" << *I;\n";
606 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000607 };
608
Reid Klecknerf526b9482014-02-12 18:22:18 +0000609 // Unique the enums, but maintain the original declaration ordering.
Reid Klecknerf06b2662014-02-12 19:26:24 +0000610 std::vector<std::string>
611 uniqueEnumsInOrder(const std::vector<std::string> &enums) {
Reid Klecknerf526b9482014-02-12 18:22:18 +0000612 std::vector<std::string> uniques;
613 std::set<std::string> unique_set(enums.begin(), enums.end());
614 for (std::vector<std::string>::const_iterator i = enums.begin(),
615 e = enums.end();
616 i != e; ++i) {
617 std::set<std::string>::iterator set_i = unique_set.find(*i);
618 if (set_i != unique_set.end()) {
619 uniques.push_back(*i);
620 unique_set.erase(set_i);
621 }
622 }
623 return uniques;
624 }
625
Peter Collingbournebee583f2011-10-06 13:03:08 +0000626 class EnumArgument : public Argument {
627 std::string type;
Aaron Ballman0e468c02014-01-05 21:08:29 +0000628 std::vector<std::string> values, enums, uniques;
Peter Collingbournebee583f2011-10-06 13:03:08 +0000629 public:
630 EnumArgument(Record &Arg, StringRef Attr)
631 : Argument(Arg, Attr), type(Arg.getValueAsString("Type")),
Aaron Ballman0e468c02014-01-05 21:08:29 +0000632 values(Arg.getValueAsListOfStrings("Values")),
633 enums(Arg.getValueAsListOfStrings("Enums")),
Reid Klecknerf526b9482014-02-12 18:22:18 +0000634 uniques(uniqueEnumsInOrder(enums))
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000635 {
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000636 // FIXME: Emit a proper error
637 assert(!uniques.empty());
638 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000639
Aaron Ballman682ee422013-09-11 19:47:58 +0000640 bool isEnumArg() const { return true; }
641
Peter Collingbournebee583f2011-10-06 13:03:08 +0000642 void writeAccessors(raw_ostream &OS) const {
643 OS << " " << type << " get" << getUpperName() << "() const {\n";
644 OS << " return " << getLowerName() << ";\n";
645 OS << " }";
646 }
647 void writeCloneArgs(raw_ostream &OS) const {
648 OS << getLowerName();
649 }
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000650 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
651 OS << "A->get" << getUpperName() << "()";
652 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000653 void writeCtorInitializers(raw_ostream &OS) const {
654 OS << getLowerName() << "(" << getUpperName() << ")";
655 }
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000656 void writeCtorDefaultInitializers(raw_ostream &OS) const {
657 OS << getLowerName() << "(" << type << "(0))";
658 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000659 void writeCtorParameters(raw_ostream &OS) const {
660 OS << type << " " << getUpperName();
661 }
662 void writeDeclarations(raw_ostream &OS) const {
Aaron Ballman0e468c02014-01-05 21:08:29 +0000663 std::vector<std::string>::const_iterator i = uniques.begin(),
664 e = uniques.end();
Peter Collingbournebee583f2011-10-06 13:03:08 +0000665 // The last one needs to not have a comma.
666 --e;
667
668 OS << "public:\n";
669 OS << " enum " << type << " {\n";
670 for (; i != e; ++i)
671 OS << " " << *i << ",\n";
672 OS << " " << *e << "\n";
673 OS << " };\n";
674 OS << "private:\n";
675 OS << " " << type << " " << getLowerName() << ";";
676 }
677 void writePCHReadDecls(raw_ostream &OS) const {
678 OS << " " << getAttrName() << "Attr::" << type << " " << getLowerName()
679 << "(static_cast<" << getAttrName() << "Attr::" << type
680 << ">(Record[Idx++]));\n";
681 }
682 void writePCHReadArgs(raw_ostream &OS) const {
683 OS << getLowerName();
684 }
685 void writePCHWrite(raw_ostream &OS) const {
686 OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
687 }
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000688 void writeValue(raw_ostream &OS) const {
689 OS << "\" << get" << getUpperName() << "() << \"";
690 }
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000691 void writeDump(raw_ostream &OS) const {
692 OS << " switch(SA->get" << getUpperName() << "()) {\n";
Aaron Ballman0e468c02014-01-05 21:08:29 +0000693 for (std::vector<std::string>::const_iterator I = uniques.begin(),
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000694 E = uniques.end(); I != E; ++I) {
695 OS << " case " << getAttrName() << "Attr::" << *I << ":\n";
696 OS << " OS << \" " << *I << "\";\n";
697 OS << " break;\n";
698 }
699 OS << " }\n";
700 }
Aaron Ballman682ee422013-09-11 19:47:58 +0000701
702 void writeConversion(raw_ostream &OS) const {
703 OS << " static bool ConvertStrTo" << type << "(StringRef Val, ";
704 OS << type << " &Out) {\n";
705 OS << " Optional<" << type << "> R = llvm::StringSwitch<Optional<";
706 OS << type << "> >(Val)\n";
707 for (size_t I = 0; I < enums.size(); ++I) {
708 OS << " .Case(\"" << values[I] << "\", ";
709 OS << getAttrName() << "Attr::" << enums[I] << ")\n";
710 }
711 OS << " .Default(Optional<" << type << ">());\n";
712 OS << " if (R) {\n";
713 OS << " Out = *R;\n return true;\n }\n";
714 OS << " return false;\n";
715 OS << " }\n";
716 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000717 };
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000718
719 class VariadicEnumArgument: public VariadicArgument {
720 std::string type, QualifiedTypeName;
Aaron Ballman0e468c02014-01-05 21:08:29 +0000721 std::vector<std::string> values, enums, uniques;
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000722 public:
723 VariadicEnumArgument(Record &Arg, StringRef Attr)
724 : VariadicArgument(Arg, Attr, Arg.getValueAsString("Type")),
725 type(Arg.getValueAsString("Type")),
Aaron Ballman0e468c02014-01-05 21:08:29 +0000726 values(Arg.getValueAsListOfStrings("Values")),
727 enums(Arg.getValueAsListOfStrings("Enums")),
Reid Klecknerf526b9482014-02-12 18:22:18 +0000728 uniques(uniqueEnumsInOrder(enums))
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000729 {
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000730 QualifiedTypeName = getAttrName().str() + "Attr::" + type;
731
732 // FIXME: Emit a proper error
733 assert(!uniques.empty());
734 }
735
736 bool isVariadicEnumArg() const { return true; }
737
738 void writeDeclarations(raw_ostream &OS) const {
Aaron Ballman0e468c02014-01-05 21:08:29 +0000739 std::vector<std::string>::const_iterator i = uniques.begin(),
740 e = uniques.end();
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000741 // The last one needs to not have a comma.
742 --e;
743
744 OS << "public:\n";
745 OS << " enum " << type << " {\n";
746 for (; i != e; ++i)
747 OS << " " << *i << ",\n";
748 OS << " " << *e << "\n";
749 OS << " };\n";
750 OS << "private:\n";
751
752 VariadicArgument::writeDeclarations(OS);
753 }
754 void writeDump(raw_ostream &OS) const {
755 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
756 << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
757 << getLowerName() << "_end(); I != E; ++I) {\n";
758 OS << " switch(*I) {\n";
Aaron Ballman0e468c02014-01-05 21:08:29 +0000759 for (std::vector<std::string>::const_iterator UI = uniques.begin(),
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000760 UE = uniques.end(); UI != UE; ++UI) {
761 OS << " case " << getAttrName() << "Attr::" << *UI << ":\n";
762 OS << " OS << \" " << *UI << "\";\n";
763 OS << " break;\n";
764 }
765 OS << " }\n";
766 OS << " }\n";
767 }
768 void writePCHReadDecls(raw_ostream &OS) const {
769 OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
770 OS << " SmallVector<" << QualifiedTypeName << ", 4> " << getLowerName()
771 << ";\n";
772 OS << " " << getLowerName() << ".reserve(" << getLowerName()
773 << "Size);\n";
774 OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
775 OS << " " << getLowerName() << ".push_back(" << "static_cast<"
776 << QualifiedTypeName << ">(Record[Idx++]));\n";
777 }
778 void writePCHWrite(raw_ostream &OS) const{
779 OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";
780 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
781 << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
782 << getLowerName() << "_end(); i != e; ++i)\n";
783 OS << " " << WritePCHRecord(QualifiedTypeName, "(*i)");
784 }
785 void writeConversion(raw_ostream &OS) const {
786 OS << " static bool ConvertStrTo" << type << "(StringRef Val, ";
787 OS << type << " &Out) {\n";
788 OS << " Optional<" << type << "> R = llvm::StringSwitch<Optional<";
789 OS << type << "> >(Val)\n";
790 for (size_t I = 0; I < enums.size(); ++I) {
791 OS << " .Case(\"" << values[I] << "\", ";
792 OS << getAttrName() << "Attr::" << enums[I] << ")\n";
793 }
794 OS << " .Default(Optional<" << type << ">());\n";
795 OS << " if (R) {\n";
796 OS << " Out = *R;\n return true;\n }\n";
797 OS << " return false;\n";
798 OS << " }\n";
799 }
800 };
Peter Collingbournebee583f2011-10-06 13:03:08 +0000801
802 class VersionArgument : public Argument {
803 public:
804 VersionArgument(Record &Arg, StringRef Attr)
805 : Argument(Arg, Attr)
806 {}
807
808 void writeAccessors(raw_ostream &OS) const {
809 OS << " VersionTuple get" << getUpperName() << "() const {\n";
810 OS << " return " << getLowerName() << ";\n";
811 OS << " }\n";
812 OS << " void set" << getUpperName()
813 << "(ASTContext &C, VersionTuple V) {\n";
814 OS << " " << getLowerName() << " = V;\n";
815 OS << " }";
816 }
817 void writeCloneArgs(raw_ostream &OS) const {
818 OS << "get" << getUpperName() << "()";
819 }
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000820 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
821 OS << "A->get" << getUpperName() << "()";
822 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000823 void writeCtorBody(raw_ostream &OS) const {
824 }
825 void writeCtorInitializers(raw_ostream &OS) const {
826 OS << getLowerName() << "(" << getUpperName() << ")";
827 }
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000828 void writeCtorDefaultInitializers(raw_ostream &OS) const {
829 OS << getLowerName() << "()";
830 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000831 void writeCtorParameters(raw_ostream &OS) const {
832 OS << "VersionTuple " << getUpperName();
833 }
834 void writeDeclarations(raw_ostream &OS) const {
835 OS << "VersionTuple " << getLowerName() << ";\n";
836 }
837 void writePCHReadDecls(raw_ostream &OS) const {
838 OS << " VersionTuple " << getLowerName()
839 << "= ReadVersionTuple(Record, Idx);\n";
840 }
841 void writePCHReadArgs(raw_ostream &OS) const {
842 OS << getLowerName();
843 }
844 void writePCHWrite(raw_ostream &OS) const {
845 OS << " AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n";
846 }
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000847 void writeValue(raw_ostream &OS) const {
848 OS << getLowerName() << "=\" << get" << getUpperName() << "() << \"";
849 }
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000850 void writeDump(raw_ostream &OS) const {
851 OS << " OS << \" \" << SA->get" << getUpperName() << "();\n";
852 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000853 };
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000854
855 class ExprArgument : public SimpleArgument {
856 public:
857 ExprArgument(Record &Arg, StringRef Attr)
858 : SimpleArgument(Arg, Attr, "Expr *")
859 {}
860
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +0000861 virtual void writeASTVisitorTraversal(raw_ostream &OS) const {
862 OS << " if (!"
863 << "getDerived().TraverseStmt(A->get" << getUpperName() << "()))\n";
864 OS << " return false;\n";
865 }
866
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000867 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
868 OS << "tempInst" << getUpperName();
869 }
870
871 void writeTemplateInstantiation(raw_ostream &OS) const {
872 OS << " " << getType() << " tempInst" << getUpperName() << ";\n";
873 OS << " {\n";
874 OS << " EnterExpressionEvaluationContext "
875 << "Unevaluated(S, Sema::Unevaluated);\n";
876 OS << " ExprResult " << "Result = S.SubstExpr("
877 << "A->get" << getUpperName() << "(), TemplateArgs);\n";
878 OS << " tempInst" << getUpperName() << " = "
879 << "Result.takeAs<Expr>();\n";
880 OS << " }\n";
881 }
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000882
883 void writeDump(raw_ostream &OS) const {
884 }
885
886 void writeDumpChildren(raw_ostream &OS) const {
Richard Trieude5cc7d2013-01-31 01:44:26 +0000887 OS << " lastChild();\n";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000888 OS << " dumpStmt(SA->get" << getUpperName() << "());\n";
889 }
Richard Trieude5cc7d2013-01-31 01:44:26 +0000890 void writeHasChildren(raw_ostream &OS) const { OS << "true"; }
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000891 };
892
893 class VariadicExprArgument : public VariadicArgument {
894 public:
895 VariadicExprArgument(Record &Arg, StringRef Attr)
896 : VariadicArgument(Arg, Attr, "Expr *")
897 {}
898
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +0000899 virtual void writeASTVisitorTraversal(raw_ostream &OS) const {
900 OS << " {\n";
901 OS << " " << getType() << " *I = A->" << getLowerName()
902 << "_begin();\n";
903 OS << " " << getType() << " *E = A->" << getLowerName()
904 << "_end();\n";
905 OS << " for (; I != E; ++I) {\n";
906 OS << " if (!getDerived().TraverseStmt(*I))\n";
907 OS << " return false;\n";
908 OS << " }\n";
909 OS << " }\n";
910 }
911
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000912 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
913 OS << "tempInst" << getUpperName() << ", "
914 << "A->" << getLowerName() << "_size()";
915 }
916
917 void writeTemplateInstantiation(raw_ostream &OS) const {
918 OS << " " << getType() << " *tempInst" << getUpperName()
919 << " = new (C, 16) " << getType()
920 << "[A->" << getLowerName() << "_size()];\n";
921 OS << " {\n";
922 OS << " EnterExpressionEvaluationContext "
923 << "Unevaluated(S, Sema::Unevaluated);\n";
924 OS << " " << getType() << " *TI = tempInst" << getUpperName()
925 << ";\n";
926 OS << " " << getType() << " *I = A->" << getLowerName()
927 << "_begin();\n";
928 OS << " " << getType() << " *E = A->" << getLowerName()
929 << "_end();\n";
930 OS << " for (; I != E; ++I, ++TI) {\n";
931 OS << " ExprResult Result = S.SubstExpr(*I, TemplateArgs);\n";
932 OS << " *TI = Result.takeAs<Expr>();\n";
933 OS << " }\n";
934 OS << " }\n";
935 }
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000936
937 void writeDump(raw_ostream &OS) const {
938 }
939
940 void writeDumpChildren(raw_ostream &OS) const {
941 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
942 << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
Richard Trieude5cc7d2013-01-31 01:44:26 +0000943 << getLowerName() << "_end(); I != E; ++I) {\n";
944 OS << " if (I + 1 == E)\n";
945 OS << " lastChild();\n";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000946 OS << " dumpStmt(*I);\n";
Richard Trieude5cc7d2013-01-31 01:44:26 +0000947 OS << " }\n";
948 }
949
950 void writeHasChildren(raw_ostream &OS) const {
951 OS << "SA->" << getLowerName() << "_begin() != "
952 << "SA->" << getLowerName() << "_end()";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000953 }
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000954 };
Richard Smithb87c4652013-10-31 21:23:20 +0000955
956 class TypeArgument : public SimpleArgument {
957 public:
958 TypeArgument(Record &Arg, StringRef Attr)
959 : SimpleArgument(Arg, Attr, "TypeSourceInfo *")
960 {}
961
962 void writeAccessors(raw_ostream &OS) const {
963 OS << " QualType get" << getUpperName() << "() const {\n";
964 OS << " return " << getLowerName() << "->getType();\n";
965 OS << " }";
966 OS << " " << getType() << " get" << getUpperName() << "Loc() const {\n";
967 OS << " return " << getLowerName() << ";\n";
968 OS << " }";
969 }
970 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
971 OS << "A->get" << getUpperName() << "Loc()";
972 }
973 void writePCHWrite(raw_ostream &OS) const {
974 OS << " " << WritePCHRecord(
975 getType(), "SA->get" + std::string(getUpperName()) + "Loc()");
976 }
977 };
Peter Collingbournebee583f2011-10-06 13:03:08 +0000978}
979
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000980static Argument *createArgument(Record &Arg, StringRef Attr,
981 Record *Search = 0) {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000982 if (!Search)
983 Search = &Arg;
984
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000985 Argument *Ptr = 0;
Peter Collingbournebee583f2011-10-06 13:03:08 +0000986 llvm::StringRef ArgName = Search->getName();
987
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000988 if (ArgName == "AlignedArgument") Ptr = new AlignedArgument(Arg, Attr);
989 else if (ArgName == "EnumArgument") Ptr = new EnumArgument(Arg, Attr);
990 else if (ArgName == "ExprArgument") Ptr = new ExprArgument(Arg, Attr);
Peter Collingbournebee583f2011-10-06 13:03:08 +0000991 else if (ArgName == "FunctionArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000992 Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *");
Peter Collingbournebee583f2011-10-06 13:03:08 +0000993 else if (ArgName == "IdentifierArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000994 Ptr = new SimpleArgument(Arg, Attr, "IdentifierInfo *");
David Majnemer4bb09802014-02-10 19:50:15 +0000995 else if (ArgName == "DefaultBoolArgument")
996 Ptr = new DefaultSimpleArgument(Arg, Attr, "bool",
997 Arg.getValueAsBit("Default"));
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000998 else if (ArgName == "BoolArgument") Ptr = new SimpleArgument(Arg, Attr,
999 "bool");
Aaron Ballman18a78382013-11-21 00:28:23 +00001000 else if (ArgName == "DefaultIntArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +00001001 Ptr = new DefaultSimpleArgument(Arg, Attr, "int",
1002 Arg.getValueAsInt("Default"));
1003 else if (ArgName == "IntArgument") Ptr = new SimpleArgument(Arg, Attr, "int");
1004 else if (ArgName == "StringArgument") Ptr = new StringArgument(Arg, Attr);
1005 else if (ArgName == "TypeArgument") Ptr = new TypeArgument(Arg, Attr);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001006 else if (ArgName == "UnsignedArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +00001007 Ptr = new SimpleArgument(Arg, Attr, "unsigned");
Peter Collingbournebee583f2011-10-06 13:03:08 +00001008 else if (ArgName == "VariadicUnsignedArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +00001009 Ptr = new VariadicArgument(Arg, Attr, "unsigned");
DeLesley Hutchins210791a2013-10-04 21:28:06 +00001010 else if (ArgName == "VariadicEnumArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +00001011 Ptr = new VariadicEnumArgument(Arg, Attr);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001012 else if (ArgName == "VariadicExprArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +00001013 Ptr = new VariadicExprArgument(Arg, Attr);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001014 else if (ArgName == "VersionArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +00001015 Ptr = new VersionArgument(Arg, Attr);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001016
1017 if (!Ptr) {
Aaron Ballman18a78382013-11-21 00:28:23 +00001018 // Search in reverse order so that the most-derived type is handled first.
Peter Collingbournebee583f2011-10-06 13:03:08 +00001019 std::vector<Record*> Bases = Search->getSuperClasses();
Aaron Ballman18a78382013-11-21 00:28:23 +00001020 for (std::vector<Record*>::reverse_iterator i = Bases.rbegin(),
1021 e = Bases.rend(); i != e; ++i) {
Peter Collingbournebee583f2011-10-06 13:03:08 +00001022 Ptr = createArgument(Arg, Attr, *i);
1023 if (Ptr)
1024 break;
1025 }
1026 }
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001027
1028 if (Ptr && Arg.getValueAsBit("Optional"))
1029 Ptr->setOptional(true);
1030
Peter Collingbournebee583f2011-10-06 13:03:08 +00001031 return Ptr;
1032}
1033
Douglas Gregor49ccfaa2011-11-19 19:22:57 +00001034static void writeAvailabilityValue(raw_ostream &OS) {
1035 OS << "\" << getPlatform()->getName();\n"
1036 << " if (!getIntroduced().empty()) OS << \", introduced=\" << getIntroduced();\n"
1037 << " if (!getDeprecated().empty()) OS << \", deprecated=\" << getDeprecated();\n"
1038 << " if (!getObsoleted().empty()) OS << \", obsoleted=\" << getObsoleted();\n"
1039 << " if (getUnavailable()) OS << \", unavailable\";\n"
1040 << " OS << \"";
1041}
1042
Aaron Ballman3e424b52013-12-26 18:30:57 +00001043static void writeGetSpellingFunction(Record &R, raw_ostream &OS) {
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001044 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
Aaron Ballman3e424b52013-12-26 18:30:57 +00001045
1046 OS << "const char *" << R.getName() << "Attr::getSpelling() const {\n";
1047 if (Spellings.empty()) {
1048 OS << " return \"(No spelling)\";\n}\n\n";
1049 return;
1050 }
1051
1052 OS << " switch (SpellingListIndex) {\n"
1053 " default:\n"
1054 " llvm_unreachable(\"Unknown attribute spelling!\");\n"
1055 " return \"(No spelling)\";\n";
1056
1057 for (unsigned I = 0; I < Spellings.size(); ++I)
1058 OS << " case " << I << ":\n"
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001059 " return \"" << Spellings[I].name() << "\";\n";
Aaron Ballman3e424b52013-12-26 18:30:57 +00001060 // End of the switch statement.
1061 OS << " }\n";
1062 // End of the getSpelling function.
1063 OS << "}\n\n";
1064}
1065
Michael Han99315932013-01-24 16:46:58 +00001066static void writePrettyPrintFunction(Record &R, std::vector<Argument*> &Args,
1067 raw_ostream &OS) {
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001068 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
Michael Han99315932013-01-24 16:46:58 +00001069
1070 OS << "void " << R.getName() << "Attr::printPretty("
1071 << "raw_ostream &OS, const PrintingPolicy &Policy) const {\n";
1072
1073 if (Spellings.size() == 0) {
1074 OS << "}\n\n";
1075 return;
1076 }
1077
1078 OS <<
1079 " switch (SpellingListIndex) {\n"
1080 " default:\n"
1081 " llvm_unreachable(\"Unknown attribute spelling!\");\n"
1082 " break;\n";
1083
1084 for (unsigned I = 0; I < Spellings.size(); ++ I) {
1085 llvm::SmallString<16> Prefix;
1086 llvm::SmallString<8> Suffix;
1087 // The actual spelling of the name and namespace (if applicable)
1088 // of an attribute without considering prefix and suffix.
1089 llvm::SmallString<64> Spelling;
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001090 std::string Name = Spellings[I].name();
1091 std::string Variety = Spellings[I].variety();
Michael Han99315932013-01-24 16:46:58 +00001092
1093 if (Variety == "GNU") {
1094 Prefix = " __attribute__((";
1095 Suffix = "))";
1096 } else if (Variety == "CXX11") {
1097 Prefix = " [[";
1098 Suffix = "]]";
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001099 std::string Namespace = Spellings[I].nameSpace();
Michael Han99315932013-01-24 16:46:58 +00001100 if (Namespace != "") {
1101 Spelling += Namespace;
1102 Spelling += "::";
1103 }
1104 } else if (Variety == "Declspec") {
1105 Prefix = " __declspec(";
1106 Suffix = ")";
Richard Smith0cdcc982013-01-29 01:24:26 +00001107 } else if (Variety == "Keyword") {
1108 Prefix = " ";
1109 Suffix = "";
Michael Han99315932013-01-24 16:46:58 +00001110 } else {
Richard Smith0cdcc982013-01-29 01:24:26 +00001111 llvm_unreachable("Unknown attribute syntax variety!");
Michael Han99315932013-01-24 16:46:58 +00001112 }
1113
1114 Spelling += Name;
1115
1116 OS <<
1117 " case " << I << " : {\n"
1118 " OS << \"" + Prefix.str() + Spelling.str();
1119
1120 if (Args.size()) OS << "(";
1121 if (Spelling == "availability") {
1122 writeAvailabilityValue(OS);
1123 } else {
1124 for (std::vector<Argument*>::const_iterator I = Args.begin(),
1125 E = Args.end(); I != E; ++ I) {
1126 if (I != Args.begin()) OS << ", ";
1127 (*I)->writeValue(OS);
1128 }
1129 }
1130
1131 if (Args.size()) OS << ")";
1132 OS << Suffix.str() + "\";\n";
1133
1134 OS <<
1135 " break;\n"
1136 " }\n";
1137 }
1138
1139 // End of the switch statement.
1140 OS << "}\n";
1141 // End of the print function.
1142 OS << "}\n\n";
1143}
1144
Michael Hanaf02bbe2013-02-01 01:19:17 +00001145/// \brief Return the index of a spelling in a spelling list.
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001146static unsigned
1147getSpellingListIndex(const std::vector<FlattenedSpelling> &SpellingList,
1148 const FlattenedSpelling &Spelling) {
Michael Hanaf02bbe2013-02-01 01:19:17 +00001149 assert(SpellingList.size() && "Spelling list is empty!");
1150
1151 for (unsigned Index = 0; Index < SpellingList.size(); ++Index) {
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001152 const FlattenedSpelling &S = SpellingList[Index];
1153 if (S.variety() != Spelling.variety())
Michael Hanaf02bbe2013-02-01 01:19:17 +00001154 continue;
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001155 if (S.nameSpace() != Spelling.nameSpace())
Michael Hanaf02bbe2013-02-01 01:19:17 +00001156 continue;
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001157 if (S.name() != Spelling.name())
Michael Hanaf02bbe2013-02-01 01:19:17 +00001158 continue;
1159
1160 return Index;
1161 }
1162
1163 llvm_unreachable("Unknown spelling!");
1164}
1165
1166static void writeAttrAccessorDefinition(Record &R, raw_ostream &OS) {
1167 std::vector<Record*> Accessors = R.getValueAsListOfDefs("Accessors");
1168 for (std::vector<Record*>::const_iterator I = Accessors.begin(),
1169 E = Accessors.end(); I != E; ++I) {
1170 Record *Accessor = *I;
1171 std::string Name = Accessor->getValueAsString("Name");
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001172 std::vector<FlattenedSpelling> Spellings =
1173 GetFlattenedSpellings(*Accessor);
1174 std::vector<FlattenedSpelling> SpellingList = GetFlattenedSpellings(R);
Michael Hanaf02bbe2013-02-01 01:19:17 +00001175 assert(SpellingList.size() &&
1176 "Attribute with empty spelling list can't have accessors!");
1177
1178 OS << " bool " << Name << "() const { return SpellingListIndex == ";
1179 for (unsigned Index = 0; Index < Spellings.size(); ++Index) {
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001180 OS << getSpellingListIndex(SpellingList, Spellings[Index]);
Michael Hanaf02bbe2013-02-01 01:19:17 +00001181 if (Index != Spellings.size() -1)
1182 OS << " ||\n SpellingListIndex == ";
1183 else
1184 OS << "; }\n";
1185 }
1186 }
1187}
1188
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001189static bool
1190SpellingNamesAreCommon(const std::vector<FlattenedSpelling>& Spellings) {
Aaron Ballman36a53502014-01-16 13:03:14 +00001191 assert(!Spellings.empty() && "An empty list of spellings was provided");
1192 std::string FirstName = NormalizeNameForSpellingComparison(
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001193 Spellings.front().name());
1194 for (std::vector<FlattenedSpelling>::const_iterator
1195 I = llvm::next(Spellings.begin()), E = Spellings.end(); I != E; ++I) {
1196 std::string Name = NormalizeNameForSpellingComparison(I->name());
Aaron Ballman36a53502014-01-16 13:03:14 +00001197 if (Name != FirstName)
1198 return false;
1199 }
1200 return true;
1201}
1202
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001203typedef std::map<unsigned, std::string> SemanticSpellingMap;
1204static std::string
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001205CreateSemanticSpellings(const std::vector<FlattenedSpelling> &Spellings,
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001206 SemanticSpellingMap &Map) {
1207 // The enumerants are automatically generated based on the variety,
1208 // namespace (if present) and name for each attribute spelling. However,
1209 // care is taken to avoid trampling on the reserved namespace due to
1210 // underscores.
1211 std::string Ret(" enum Spelling {\n");
1212 std::set<std::string> Uniques;
1213 unsigned Idx = 0;
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001214 for (std::vector<FlattenedSpelling>::const_iterator I = Spellings.begin(),
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001215 E = Spellings.end(); I != E; ++I, ++Idx) {
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001216 const FlattenedSpelling &S = *I;
1217 std::string Variety = S.variety();
1218 std::string Spelling = S.name();
1219 std::string Namespace = S.nameSpace();
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001220 std::string EnumName = "";
1221
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001222 EnumName += (Variety + "_");
1223 if (!Namespace.empty())
1224 EnumName += (NormalizeNameForSpellingComparison(Namespace).str() +
1225 "_");
1226 EnumName += NormalizeNameForSpellingComparison(Spelling);
1227
1228 // Even if the name is not unique, this spelling index corresponds to a
1229 // particular enumerant name that we've calculated.
1230 Map[Idx] = EnumName;
1231
1232 // Since we have been stripping underscores to avoid trampling on the
1233 // reserved namespace, we may have inadvertently created duplicate
1234 // enumerant names. These duplicates are not considered part of the
1235 // semantic spelling, and can be elided.
1236 if (Uniques.find(EnumName) != Uniques.end())
1237 continue;
1238
1239 Uniques.insert(EnumName);
1240 if (I != Spellings.begin())
1241 Ret += ",\n";
1242 Ret += " " + EnumName;
1243 }
1244 Ret += "\n };\n\n";
1245 return Ret;
1246}
1247
1248void WriteSemanticSpellingSwitch(const std::string &VarName,
1249 const SemanticSpellingMap &Map,
1250 raw_ostream &OS) {
1251 OS << " switch (" << VarName << ") {\n default: "
1252 << "llvm_unreachable(\"Unknown spelling list index\");\n";
1253 for (SemanticSpellingMap::const_iterator I = Map.begin(), E = Map.end();
1254 I != E; ++I)
1255 OS << " case " << I->first << ": return " << I->second << ";\n";
1256 OS << " }\n";
1257}
1258
Aaron Ballman35db2b32014-01-29 22:13:45 +00001259// Emits the LateParsed property for attributes.
1260static void emitClangAttrLateParsedList(RecordKeeper &Records, raw_ostream &OS) {
1261 OS << "#if defined(CLANG_ATTR_LATE_PARSED_LIST)\n";
1262 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1263
1264 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1265 I != E; ++I) {
1266 Record &Attr = **I;
1267
1268 bool LateParsed = Attr.getValueAsBit("LateParsed");
1269
1270 if (LateParsed) {
1271 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
1272
1273 // FIXME: Handle non-GNU attributes
1274 for (std::vector<FlattenedSpelling>::const_iterator
1275 I = Spellings.begin(), E = Spellings.end(); I != E; ++I) {
1276 if (I->variety() != "GNU")
1277 continue;
1278 OS << ".Case(\"" << I->name() << "\", " << LateParsed << ")\n";
1279 }
1280 }
1281 }
1282 OS << "#endif // CLANG_ATTR_LATE_PARSED_LIST\n\n";
1283}
1284
1285/// \brief Emits the first-argument-is-type property for attributes.
1286static void emitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) {
1287 OS << "#if defined(CLANG_ATTR_TYPE_ARG_LIST)\n";
1288 std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
1289
1290 for (std::vector<Record *>::iterator I = Attrs.begin(), E = Attrs.end();
1291 I != E; ++I) {
1292 Record &Attr = **I;
1293
1294 // Determine whether the first argument is a type.
1295 std::vector<Record *> Args = Attr.getValueAsListOfDefs("Args");
1296 if (Args.empty())
1297 continue;
1298
1299 if (Args[0]->getSuperClasses().back()->getName() != "TypeArgument")
1300 continue;
1301
1302 // All these spellings take a single type argument.
1303 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
1304 std::set<std::string> Emitted;
1305 for (std::vector<FlattenedSpelling>::const_iterator I = Spellings.begin(),
1306 E = Spellings.end(); I != E; ++I) {
1307 if (Emitted.insert(I->name()).second)
1308 OS << ".Case(\"" << I->name() << "\", " << "true" << ")\n";
1309 }
1310 }
1311 OS << "#endif // CLANG_ATTR_TYPE_ARG_LIST\n\n";
1312}
1313
1314/// \brief Emits the parse-arguments-in-unevaluated-context property for
1315/// attributes.
1316static void emitClangAttrArgContextList(RecordKeeper &Records, raw_ostream &OS) {
1317 OS << "#if defined(CLANG_ATTR_ARG_CONTEXT_LIST)\n";
1318 ParsedAttrMap Attrs = getParsedAttrList(Records);
1319 for (ParsedAttrMap::const_iterator I = Attrs.begin(), E = Attrs.end();
1320 I != E; ++I) {
1321 const Record &Attr = *I->second;
1322
1323 if (!Attr.getValueAsBit("ParseArgumentsAsUnevaluated"))
1324 continue;
1325
1326 // All these spellings take are parsed unevaluated.
1327 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
1328 std::set<std::string> Emitted;
1329 for (std::vector<FlattenedSpelling>::const_iterator I = Spellings.begin(),
1330 E = Spellings.end(); I != E; ++I) {
1331 if (Emitted.insert(I->name()).second)
1332 OS << ".Case(\"" << I->name() << "\", " << "true" << ")\n";
1333 }
1334 }
1335 OS << "#endif // CLANG_ATTR_ARG_CONTEXT_LIST\n\n";
1336}
1337
1338static bool isIdentifierArgument(Record *Arg) {
1339 return !Arg->getSuperClasses().empty() &&
1340 llvm::StringSwitch<bool>(Arg->getSuperClasses().back()->getName())
1341 .Case("IdentifierArgument", true)
1342 .Case("EnumArgument", true)
1343 .Default(false);
1344}
1345
1346// Emits the first-argument-is-identifier property for attributes.
1347static void emitClangAttrIdentifierArgList(RecordKeeper &Records, raw_ostream &OS) {
1348 OS << "#if defined(CLANG_ATTR_IDENTIFIER_ARG_LIST)\n";
1349 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1350
1351 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1352 I != E; ++I) {
1353 Record &Attr = **I;
1354
1355 // Determine whether the first argument is an identifier.
1356 std::vector<Record *> Args = Attr.getValueAsListOfDefs("Args");
1357 if (Args.empty() || !isIdentifierArgument(Args[0]))
1358 continue;
1359
1360 // All these spellings take an identifier argument.
1361 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
1362 std::set<std::string> Emitted;
1363 for (std::vector<FlattenedSpelling>::const_iterator I = Spellings.begin(),
1364 E = Spellings.end(); I != E; ++I) {
1365 if (Emitted.insert(I->name()).second)
1366 OS << ".Case(\"" << I->name() << "\", " << "true" << ")\n";
1367 }
1368 }
1369 OS << "#endif // CLANG_ATTR_IDENTIFIER_ARG_LIST\n\n";
1370}
1371
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001372namespace clang {
1373
1374// Emits the class definitions for attributes.
1375void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00001376 emitSourceFileHeader("Attribute classes' definitions", OS);
1377
Peter Collingbournebee583f2011-10-06 13:03:08 +00001378 OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
1379 OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
1380
1381 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1382
1383 for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
1384 i != e; ++i) {
1385 Record &R = **i;
Douglas Gregorb2daf842012-05-02 15:56:52 +00001386
1387 if (!R.getValueAsBit("ASTNode"))
1388 continue;
1389
Aaron Ballman0979e9e2013-07-30 01:44:15 +00001390 const std::vector<Record *> Supers = R.getSuperClasses();
1391 assert(!Supers.empty() && "Forgot to specify a superclass for the attr");
Aaron Ballman0979e9e2013-07-30 01:44:15 +00001392 std::string SuperName;
1393 for (std::vector<Record *>::const_reverse_iterator I = Supers.rbegin(),
1394 E = Supers.rend(); I != E; ++I) {
1395 const Record &R = **I;
Aaron Ballman080cad72013-07-31 02:20:22 +00001396 if (R.getName() != "TargetSpecificAttr" && SuperName.empty())
Aaron Ballman0979e9e2013-07-30 01:44:15 +00001397 SuperName = R.getName();
1398 }
Peter Collingbournebee583f2011-10-06 13:03:08 +00001399
1400 OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n";
1401
1402 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
1403 std::vector<Argument*> Args;
1404 std::vector<Argument*>::iterator ai, ae;
1405 Args.reserve(ArgRecords.size());
1406
1407 for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
1408 re = ArgRecords.end();
1409 ri != re; ++ri) {
1410 Record &ArgRecord = **ri;
Aaron Ballmanaa47d242013-12-19 19:39:25 +00001411 Argument *Arg = createArgument(ArgRecord, R.getName());
Peter Collingbournebee583f2011-10-06 13:03:08 +00001412 assert(Arg);
1413 Args.push_back(Arg);
1414
1415 Arg->writeDeclarations(OS);
1416 OS << "\n\n";
1417 }
1418
1419 ae = Args.end();
1420
Aaron Ballman36a53502014-01-16 13:03:14 +00001421 OS << "\npublic:\n";
1422
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001423 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
Aaron Ballman36a53502014-01-16 13:03:14 +00001424
1425 // If there are zero or one spellings, all spelling-related functionality
1426 // can be elided. If all of the spellings share the same name, the spelling
1427 // functionality can also be elided.
1428 bool ElideSpelling = (Spellings.size() <= 1) ||
1429 SpellingNamesAreCommon(Spellings);
1430
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001431 // This maps spelling index values to semantic Spelling enumerants.
1432 SemanticSpellingMap SemanticToSyntacticMap;
Aaron Ballman36a53502014-01-16 13:03:14 +00001433
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001434 if (!ElideSpelling)
1435 OS << CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);
Aaron Ballman36a53502014-01-16 13:03:14 +00001436
1437 OS << " static " << R.getName() << "Attr *CreateImplicit(";
1438 OS << "ASTContext &Ctx";
1439 if (!ElideSpelling)
1440 OS << ", Spelling S";
1441 for (ai = Args.begin(); ai != ae; ++ai) {
1442 OS << ", ";
1443 (*ai)->writeCtorParameters(OS);
1444 }
1445 OS << ", SourceRange Loc = SourceRange()";
1446 OS << ") {\n";
1447 OS << " " << R.getName() << "Attr *A = new (Ctx) " << R.getName();
1448 OS << "Attr(Loc, Ctx, ";
1449 for (ai = Args.begin(); ai != ae; ++ai) {
1450 (*ai)->writeImplicitCtorArgs(OS);
1451 OS << ", ";
1452 }
1453 OS << (ElideSpelling ? "0" : "S") << ");\n";
1454 OS << " A->setImplicit(true);\n";
1455 OS << " return A;\n }\n\n";
1456
Peter Collingbournebee583f2011-10-06 13:03:08 +00001457 OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
1458
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001459 bool HasOpt = false;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001460 for (ai = Args.begin(); ai != ae; ++ai) {
1461 OS << " , ";
1462 (*ai)->writeCtorParameters(OS);
1463 OS << "\n";
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001464 if ((*ai)->isOptional())
1465 HasOpt = true;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001466 }
Michael Han99315932013-01-24 16:46:58 +00001467
1468 OS << " , ";
Aaron Ballman36a53502014-01-16 13:03:14 +00001469 OS << "unsigned SI\n";
Michael Han99315932013-01-24 16:46:58 +00001470
Peter Collingbournebee583f2011-10-06 13:03:08 +00001471 OS << " )\n";
Michael Han99315932013-01-24 16:46:58 +00001472 OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001473
1474 for (ai = Args.begin(); ai != ae; ++ai) {
1475 OS << " , ";
1476 (*ai)->writeCtorInitializers(OS);
1477 OS << "\n";
1478 }
1479
1480 OS << " {\n";
1481
1482 for (ai = Args.begin(); ai != ae; ++ai) {
1483 (*ai)->writeCtorBody(OS);
1484 OS << "\n";
1485 }
1486 OS << " }\n\n";
1487
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001488 // If there are optional arguments, write out a constructor that elides the
1489 // optional arguments as well.
1490 if (HasOpt) {
1491 OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
1492 for (ai = Args.begin(); ai != ae; ++ai) {
1493 if (!(*ai)->isOptional()) {
1494 OS << " , ";
1495 (*ai)->writeCtorParameters(OS);
1496 OS << "\n";
1497 }
1498 }
1499
1500 OS << " , ";
Aaron Ballman36a53502014-01-16 13:03:14 +00001501 OS << "unsigned SI\n";
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001502
1503 OS << " )\n";
1504 OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n";
1505
1506 for (ai = Args.begin(); ai != ae; ++ai) {
1507 OS << " , ";
1508 (*ai)->writeCtorDefaultInitializers(OS);
1509 OS << "\n";
1510 }
1511
1512 OS << " {\n";
1513
1514 for (ai = Args.begin(); ai != ae; ++ai) {
1515 if (!(*ai)->isOptional()) {
1516 (*ai)->writeCtorBody(OS);
1517 OS << "\n";
1518 }
1519 }
1520 OS << " }\n\n";
1521 }
1522
Peter Collingbournebee583f2011-10-06 13:03:08 +00001523 OS << " virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n";
Michael Han38d96ab2013-01-27 00:06:24 +00001524 OS << " virtual void printPretty(raw_ostream &OS,\n"
Richard Smith52f04a22012-08-16 02:43:29 +00001525 << " const PrintingPolicy &Policy) const;\n";
Aaron Ballman3e424b52013-12-26 18:30:57 +00001526 OS << " virtual const char *getSpelling() const;\n";
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001527
1528 if (!ElideSpelling) {
1529 assert(!SemanticToSyntacticMap.empty() && "Empty semantic mapping list");
1530 OS << " Spelling getSemanticSpelling() const {\n";
1531 WriteSemanticSpellingSwitch("SpellingListIndex", SemanticToSyntacticMap,
1532 OS);
1533 OS << " }\n";
1534 }
Peter Collingbournebee583f2011-10-06 13:03:08 +00001535
Michael Hanaf02bbe2013-02-01 01:19:17 +00001536 writeAttrAccessorDefinition(R, OS);
1537
Peter Collingbournebee583f2011-10-06 13:03:08 +00001538 for (ai = Args.begin(); ai != ae; ++ai) {
1539 (*ai)->writeAccessors(OS);
1540 OS << "\n\n";
Aaron Ballman682ee422013-09-11 19:47:58 +00001541
1542 if ((*ai)->isEnumArg()) {
1543 EnumArgument *EA = (EnumArgument *)*ai;
1544 EA->writeConversion(OS);
DeLesley Hutchins210791a2013-10-04 21:28:06 +00001545 } else if ((*ai)->isVariadicEnumArg()) {
1546 VariadicEnumArgument *VEA = (VariadicEnumArgument *)*ai;
1547 VEA->writeConversion(OS);
Aaron Ballman682ee422013-09-11 19:47:58 +00001548 }
Peter Collingbournebee583f2011-10-06 13:03:08 +00001549 }
1550
Jakob Stoklund Olesen6f2288b62012-01-13 04:57:47 +00001551 OS << R.getValueAsString("AdditionalMembers");
Peter Collingbournebee583f2011-10-06 13:03:08 +00001552 OS << "\n\n";
1553
1554 OS << " static bool classof(const Attr *A) { return A->getKind() == "
1555 << "attr::" << R.getName() << "; }\n";
DeLesley Hutchins30398dd2012-01-20 22:50:54 +00001556
1557 bool LateParsed = R.getValueAsBit("LateParsed");
1558 OS << " virtual bool isLateParsed() const { return "
1559 << LateParsed << "; }\n";
1560
Aaron Ballmanb9023ed2014-01-20 18:07:09 +00001561 if (R.getValueAsBit("DuplicatesAllowedWhileMerging"))
1562 OS << " virtual bool duplicatesAllowed() const { return true; }\n\n";
1563
Peter Collingbournebee583f2011-10-06 13:03:08 +00001564 OS << "};\n\n";
1565 }
1566
1567 OS << "#endif\n";
1568}
1569
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001570// Emits the class method definitions for attributes.
1571void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00001572 emitSourceFileHeader("Attribute classes' member function definitions", OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001573
1574 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1575 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ri, re;
1576 std::vector<Argument*>::iterator ai, ae;
1577
1578 for (; i != e; ++i) {
1579 Record &R = **i;
Douglas Gregorb2daf842012-05-02 15:56:52 +00001580
1581 if (!R.getValueAsBit("ASTNode"))
1582 continue;
1583
Peter Collingbournebee583f2011-10-06 13:03:08 +00001584 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
1585 std::vector<Argument*> Args;
1586 for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri)
Aaron Ballmanaa47d242013-12-19 19:39:25 +00001587 Args.push_back(createArgument(**ri, R.getName()));
Peter Collingbournebee583f2011-10-06 13:03:08 +00001588
1589 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
1590 (*ai)->writeAccessorDefinitions(OS);
1591
1592 OS << R.getName() << "Attr *" << R.getName()
1593 << "Attr::clone(ASTContext &C) const {\n";
1594 OS << " return new (C) " << R.getName() << "Attr(getLocation(), C";
1595 for (ai = Args.begin(); ai != ae; ++ai) {
1596 OS << ", ";
1597 (*ai)->writeCloneArgs(OS);
1598 }
Richard Smitha5aaca92013-01-29 04:21:28 +00001599 OS << ", getSpellingListIndex());\n}\n\n";
Douglas Gregor49ccfaa2011-11-19 19:22:57 +00001600
Michael Han99315932013-01-24 16:46:58 +00001601 writePrettyPrintFunction(R, Args, OS);
Aaron Ballman3e424b52013-12-26 18:30:57 +00001602 writeGetSpellingFunction(R, OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001603 }
1604}
1605
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001606} // end namespace clang
1607
Peter Collingbournebee583f2011-10-06 13:03:08 +00001608static void EmitAttrList(raw_ostream &OS, StringRef Class,
1609 const std::vector<Record*> &AttrList) {
1610 std::vector<Record*>::const_iterator i = AttrList.begin(), e = AttrList.end();
1611
1612 if (i != e) {
1613 // Move the end iterator back to emit the last attribute.
Douglas Gregorb2daf842012-05-02 15:56:52 +00001614 for(--e; i != e; ++i) {
1615 if (!(*i)->getValueAsBit("ASTNode"))
1616 continue;
1617
Peter Collingbournebee583f2011-10-06 13:03:08 +00001618 OS << Class << "(" << (*i)->getName() << ")\n";
Douglas Gregorb2daf842012-05-02 15:56:52 +00001619 }
Peter Collingbournebee583f2011-10-06 13:03:08 +00001620
1621 OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n";
1622 }
1623}
1624
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001625namespace clang {
1626
1627// Emits the enumeration list for attributes.
1628void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00001629 emitSourceFileHeader("List of all attributes that Clang recognizes", OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001630
1631 OS << "#ifndef LAST_ATTR\n";
1632 OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n";
1633 OS << "#endif\n\n";
1634
1635 OS << "#ifndef INHERITABLE_ATTR\n";
1636 OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n";
1637 OS << "#endif\n\n";
1638
1639 OS << "#ifndef LAST_INHERITABLE_ATTR\n";
1640 OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n";
1641 OS << "#endif\n\n";
1642
1643 OS << "#ifndef INHERITABLE_PARAM_ATTR\n";
1644 OS << "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n";
1645 OS << "#endif\n\n";
1646
1647 OS << "#ifndef LAST_INHERITABLE_PARAM_ATTR\n";
1648 OS << "#define LAST_INHERITABLE_PARAM_ATTR(NAME)"
1649 " INHERITABLE_PARAM_ATTR(NAME)\n";
1650 OS << "#endif\n\n";
1651
1652 Record *InhClass = Records.getClass("InheritableAttr");
1653 Record *InhParamClass = Records.getClass("InheritableParamAttr");
1654 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
Aaron Ballman8edb5c22013-12-18 23:44:18 +00001655 NonInhAttrs, InhAttrs, InhParamAttrs;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001656 for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
1657 i != e; ++i) {
Douglas Gregorb2daf842012-05-02 15:56:52 +00001658 if (!(*i)->getValueAsBit("ASTNode"))
1659 continue;
1660
Peter Collingbournebee583f2011-10-06 13:03:08 +00001661 if ((*i)->isSubClassOf(InhParamClass))
1662 InhParamAttrs.push_back(*i);
1663 else if ((*i)->isSubClassOf(InhClass))
1664 InhAttrs.push_back(*i);
1665 else
1666 NonInhAttrs.push_back(*i);
1667 }
1668
1669 EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs);
1670 EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs);
1671 EmitAttrList(OS, "ATTR", NonInhAttrs);
1672
1673 OS << "#undef LAST_ATTR\n";
1674 OS << "#undef INHERITABLE_ATTR\n";
1675 OS << "#undef LAST_INHERITABLE_ATTR\n";
1676 OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n";
1677 OS << "#undef ATTR\n";
1678}
1679
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001680// Emits the code to read an attribute from a precompiled header.
1681void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00001682 emitSourceFileHeader("Attribute deserialization code", OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001683
1684 Record *InhClass = Records.getClass("InheritableAttr");
1685 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
1686 ArgRecords;
1687 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
1688 std::vector<Argument*> Args;
1689 std::vector<Argument*>::iterator ri, re;
1690
1691 OS << " switch (Kind) {\n";
1692 OS << " default:\n";
1693 OS << " assert(0 && \"Unknown attribute!\");\n";
1694 OS << " break;\n";
1695 for (; i != e; ++i) {
1696 Record &R = **i;
Douglas Gregorb2daf842012-05-02 15:56:52 +00001697 if (!R.getValueAsBit("ASTNode"))
1698 continue;
1699
Peter Collingbournebee583f2011-10-06 13:03:08 +00001700 OS << " case attr::" << R.getName() << ": {\n";
1701 if (R.isSubClassOf(InhClass))
1702 OS << " bool isInherited = Record[Idx++];\n";
Aaron Ballman36a53502014-01-16 13:03:14 +00001703 OS << " bool isImplicit = Record[Idx++];\n";
1704 OS << " unsigned Spelling = Record[Idx++];\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001705 ArgRecords = R.getValueAsListOfDefs("Args");
1706 Args.clear();
1707 for (ai = ArgRecords.begin(), ae = ArgRecords.end(); ai != ae; ++ai) {
Aaron Ballmanaa47d242013-12-19 19:39:25 +00001708 Argument *A = createArgument(**ai, R.getName());
Peter Collingbournebee583f2011-10-06 13:03:08 +00001709 Args.push_back(A);
1710 A->writePCHReadDecls(OS);
1711 }
1712 OS << " New = new (Context) " << R.getName() << "Attr(Range, Context";
1713 for (ri = Args.begin(), re = Args.end(); ri != re; ++ri) {
1714 OS << ", ";
1715 (*ri)->writePCHReadArgs(OS);
1716 }
Aaron Ballman36a53502014-01-16 13:03:14 +00001717 OS << ", Spelling);\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001718 if (R.isSubClassOf(InhClass))
1719 OS << " cast<InheritableAttr>(New)->setInherited(isInherited);\n";
Aaron Ballman36a53502014-01-16 13:03:14 +00001720 OS << " New->setImplicit(isImplicit);\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001721 OS << " break;\n";
1722 OS << " }\n";
1723 }
1724 OS << " }\n";
1725}
1726
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001727// Emits the code to write an attribute to a precompiled header.
1728void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00001729 emitSourceFileHeader("Attribute serialization code", OS);
1730
Peter Collingbournebee583f2011-10-06 13:03:08 +00001731 Record *InhClass = Records.getClass("InheritableAttr");
1732 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
1733 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae;
1734
1735 OS << " switch (A->getKind()) {\n";
1736 OS << " default:\n";
1737 OS << " llvm_unreachable(\"Unknown attribute kind!\");\n";
1738 OS << " break;\n";
1739 for (; i != e; ++i) {
1740 Record &R = **i;
Douglas Gregorb2daf842012-05-02 15:56:52 +00001741 if (!R.getValueAsBit("ASTNode"))
1742 continue;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001743 OS << " case attr::" << R.getName() << ": {\n";
1744 Args = R.getValueAsListOfDefs("Args");
1745 if (R.isSubClassOf(InhClass) || !Args.empty())
1746 OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
1747 << "Attr>(A);\n";
1748 if (R.isSubClassOf(InhClass))
1749 OS << " Record.push_back(SA->isInherited());\n";
Aaron Ballman36a53502014-01-16 13:03:14 +00001750 OS << " Record.push_back(A->isImplicit());\n";
1751 OS << " Record.push_back(A->getSpellingListIndex());\n";
1752
Peter Collingbournebee583f2011-10-06 13:03:08 +00001753 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai)
1754 createArgument(**ai, R.getName())->writePCHWrite(OS);
1755 OS << " break;\n";
1756 OS << " }\n";
1757 }
1758 OS << " }\n";
1759}
1760
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001761// Emits the list of spellings for attributes.
1762void EmitClangAttrSpellingList(RecordKeeper &Records, raw_ostream &OS) {
Aaron Ballman0fa06d82014-01-09 22:57:44 +00001763 emitSourceFileHeader("llvm::StringSwitch code to match attributes based on "
1764 "the target triple, T", OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001765
1766 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1767
Aaron Ballman0fa06d82014-01-09 22:57:44 +00001768 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1769 I != E; ++I) {
Peter Collingbournebee583f2011-10-06 13:03:08 +00001770 Record &Attr = **I;
1771
Aaron Ballman0fa06d82014-01-09 22:57:44 +00001772 // It is assumed that there will be an llvm::Triple object named T within
1773 // scope that can be used to determine whether the attribute exists in
1774 // a given target.
1775 std::string Test;
1776 if (Attr.isSubClassOf("TargetSpecificAttr")) {
1777 const Record *R = Attr.getValueAsDef("Target");
1778 std::vector<std::string> Arches = R->getValueAsListOfStrings("Arches");
Peter Collingbournebee583f2011-10-06 13:03:08 +00001779
Aaron Ballman0fa06d82014-01-09 22:57:44 +00001780 Test += "(";
1781 for (std::vector<std::string>::const_iterator AI = Arches.begin(),
1782 AE = Arches.end(); AI != AE; ++AI) {
1783 std::string Part = *AI;
1784 Test += "T.getArch() == llvm::Triple::" + Part;
1785 if (AI + 1 != AE)
1786 Test += " || ";
1787 }
1788 Test += ")";
1789
1790 std::vector<std::string> OSes;
1791 if (!R->isValueUnset("OSes")) {
1792 Test += " && (";
1793 std::vector<std::string> OSes = R->getValueAsListOfStrings("OSes");
1794 for (std::vector<std::string>::const_iterator AI = OSes.begin(),
1795 AE = OSes.end(); AI != AE; ++AI) {
1796 std::string Part = *AI;
1797
1798 Test += "T.getOS() == llvm::Triple::" + Part;
1799 if (AI + 1 != AE)
1800 Test += " || ";
1801 }
1802 Test += ")";
1803 }
1804 } else
1805 Test = "true";
1806
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001807 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
1808 for (std::vector<FlattenedSpelling>::const_iterator I = Spellings.begin(),
1809 E = Spellings.end(); I != E; ++I)
1810 OS << ".Case(\"" << I->name() << "\", " << Test << ")\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001811 }
1812
1813}
1814
Michael Han99315932013-01-24 16:46:58 +00001815void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00001816 emitSourceFileHeader("Code to translate different attribute spellings "
1817 "into internal identifiers", OS);
Michael Han99315932013-01-24 16:46:58 +00001818
1819 OS <<
Michael Han99315932013-01-24 16:46:58 +00001820 " switch (AttrKind) {\n"
1821 " default:\n"
1822 " llvm_unreachable(\"Unknown attribute kind!\");\n"
1823 " break;\n";
1824
Aaron Ballman64e69862013-12-15 13:05:48 +00001825 ParsedAttrMap Attrs = getParsedAttrList(Records);
1826 for (ParsedAttrMap::const_iterator I = Attrs.begin(), E = Attrs.end();
Michael Han99315932013-01-24 16:46:58 +00001827 I != E; ++I) {
Aaron Ballman64e69862013-12-15 13:05:48 +00001828 Record &R = *I->second;
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001829 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
Aaron Ballman64e69862013-12-15 13:05:48 +00001830 OS << " case AT_" << I->first << ": {\n";
Richard Smith852e9ce2013-11-27 01:46:48 +00001831 for (unsigned I = 0; I < Spellings.size(); ++ I) {
Richard Smith852e9ce2013-11-27 01:46:48 +00001832 OS << " if (Name == \""
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001833 << Spellings[I].name() << "\" && "
Richard Smith852e9ce2013-11-27 01:46:48 +00001834 << "SyntaxUsed == "
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001835 << StringSwitch<unsigned>(Spellings[I].variety())
Richard Smith852e9ce2013-11-27 01:46:48 +00001836 .Case("GNU", 0)
1837 .Case("CXX11", 1)
1838 .Case("Declspec", 2)
1839 .Case("Keyword", 3)
1840 .Default(0)
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001841 << " && Scope == \"" << Spellings[I].nameSpace() << "\")\n"
Richard Smith852e9ce2013-11-27 01:46:48 +00001842 << " return " << I << ";\n";
Michael Han99315932013-01-24 16:46:58 +00001843 }
Richard Smith852e9ce2013-11-27 01:46:48 +00001844
1845 OS << " break;\n";
1846 OS << " }\n";
Michael Han99315932013-01-24 16:46:58 +00001847 }
1848
1849 OS << " }\n";
Aaron Ballman64e69862013-12-15 13:05:48 +00001850 OS << " return 0;\n";
Michael Han99315932013-01-24 16:46:58 +00001851}
1852
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +00001853// Emits code used by RecursiveASTVisitor to visit attributes
1854void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS) {
1855 emitSourceFileHeader("Used by RecursiveASTVisitor to visit attributes.", OS);
1856
1857 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1858
1859 // Write method declarations for Traverse* methods.
1860 // We emit this here because we only generate methods for attributes that
1861 // are declared as ASTNodes.
1862 OS << "#ifdef ATTR_VISITOR_DECLS_ONLY\n\n";
1863 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1864 I != E; ++I) {
1865 Record &R = **I;
1866 if (!R.getValueAsBit("ASTNode"))
1867 continue;
1868 OS << " bool Traverse"
1869 << R.getName() << "Attr(" << R.getName() << "Attr *A);\n";
1870 OS << " bool Visit"
1871 << R.getName() << "Attr(" << R.getName() << "Attr *A) {\n"
1872 << " return true; \n"
1873 << " };\n";
1874 }
1875 OS << "\n#else // ATTR_VISITOR_DECLS_ONLY\n\n";
1876
1877 // Write individual Traverse* methods for each attribute class.
1878 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1879 I != E; ++I) {
1880 Record &R = **I;
1881 if (!R.getValueAsBit("ASTNode"))
1882 continue;
1883
1884 OS << "template <typename Derived>\n"
DeLesley Hutchinsbb79c332013-12-30 21:03:02 +00001885 << "bool VISITORCLASS<Derived>::Traverse"
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +00001886 << R.getName() << "Attr(" << R.getName() << "Attr *A) {\n"
1887 << " if (!getDerived().VisitAttr(A))\n"
1888 << " return false;\n"
1889 << " if (!getDerived().Visit" << R.getName() << "Attr(A))\n"
1890 << " return false;\n";
1891
1892 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
1893 for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
1894 re = ArgRecords.end();
1895 ri != re; ++ri) {
1896 Record &ArgRecord = **ri;
1897 Argument *Arg = createArgument(ArgRecord, R.getName());
1898 assert(Arg);
1899 Arg->writeASTVisitorTraversal(OS);
1900 }
1901
1902 OS << " return true;\n";
1903 OS << "}\n\n";
1904 }
1905
1906 // Write generic Traverse routine
1907 OS << "template <typename Derived>\n"
DeLesley Hutchinsbb79c332013-12-30 21:03:02 +00001908 << "bool VISITORCLASS<Derived>::TraverseAttr(Attr *A) {\n"
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +00001909 << " if (!A)\n"
1910 << " return true;\n"
1911 << "\n"
1912 << " switch (A->getKind()) {\n"
1913 << " default:\n"
1914 << " return true;\n";
1915
1916 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1917 I != E; ++I) {
1918 Record &R = **I;
1919 if (!R.getValueAsBit("ASTNode"))
1920 continue;
1921
1922 OS << " case attr::" << R.getName() << ":\n"
1923 << " return getDerived().Traverse" << R.getName() << "Attr("
1924 << "cast<" << R.getName() << "Attr>(A));\n";
1925 }
1926 OS << " }\n"; // end case
1927 OS << "}\n"; // end function
1928 OS << "#endif // ATTR_VISITOR_DECLS_ONLY\n";
1929}
1930
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001931// Emits code to instantiate dependent attributes on templates.
1932void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00001933 emitSourceFileHeader("Template instantiation code for attributes", OS);
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001934
1935 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1936
Benjamin Kramerbf8da9d2012-02-06 11:13:08 +00001937 OS << "namespace clang {\n"
1938 << "namespace sema {\n\n"
1939 << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, "
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001940 << "Sema &S,\n"
1941 << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n"
1942 << " switch (At->getKind()) {\n"
1943 << " default:\n"
1944 << " break;\n";
1945
1946 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
1947 I != E; ++I) {
1948 Record &R = **I;
Douglas Gregorb2daf842012-05-02 15:56:52 +00001949 if (!R.getValueAsBit("ASTNode"))
1950 continue;
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001951
1952 OS << " case attr::" << R.getName() << ": {\n";
Rafael Espindola7f90b7d2012-05-15 14:09:55 +00001953 bool ShouldClone = R.getValueAsBit("Clone");
1954
1955 if (!ShouldClone) {
1956 OS << " return NULL;\n";
1957 OS << " }\n";
1958 continue;
1959 }
1960
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001961 OS << " const " << R.getName() << "Attr *A = cast<"
1962 << R.getName() << "Attr>(At);\n";
1963 bool TDependent = R.getValueAsBit("TemplateDependent");
1964
1965 if (!TDependent) {
1966 OS << " return A->clone(C);\n";
1967 OS << " }\n";
1968 continue;
1969 }
1970
1971 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
1972 std::vector<Argument*> Args;
1973 std::vector<Argument*>::iterator ai, ae;
1974 Args.reserve(ArgRecords.size());
1975
1976 for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
1977 re = ArgRecords.end();
1978 ri != re; ++ri) {
1979 Record &ArgRecord = **ri;
Aaron Ballmanaa47d242013-12-19 19:39:25 +00001980 Argument *Arg = createArgument(ArgRecord, R.getName());
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001981 assert(Arg);
1982 Args.push_back(Arg);
1983 }
1984 ae = Args.end();
1985
1986 for (ai = Args.begin(); ai != ae; ++ai) {
1987 (*ai)->writeTemplateInstantiation(OS);
1988 }
1989 OS << " return new (C) " << R.getName() << "Attr(A->getLocation(), C";
1990 for (ai = Args.begin(); ai != ae; ++ai) {
1991 OS << ", ";
1992 (*ai)->writeTemplateInstantiationArgs(OS);
1993 }
Aaron Ballman36a53502014-01-16 13:03:14 +00001994 OS << ", A->getSpellingListIndex());\n }\n";
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001995 }
1996 OS << " } // end switch\n"
1997 << " llvm_unreachable(\"Unknown attribute!\");\n"
1998 << " return 0;\n"
Benjamin Kramerbf8da9d2012-02-06 11:13:08 +00001999 << "}\n\n"
2000 << "} // end namespace sema\n"
2001 << "} // end namespace clang\n";
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00002002}
2003
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002004// Emits the list of parsed attributes.
2005void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) {
2006 emitSourceFileHeader("List of all attributes that Clang recognizes", OS);
2007
2008 OS << "#ifndef PARSED_ATTR\n";
2009 OS << "#define PARSED_ATTR(NAME) NAME\n";
2010 OS << "#endif\n\n";
2011
2012 ParsedAttrMap Names = getParsedAttrList(Records);
2013 for (ParsedAttrMap::iterator I = Names.begin(), E = Names.end(); I != E;
2014 ++I) {
2015 OS << "PARSED_ATTR(" << I->first << ")\n";
2016 }
2017}
2018
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002019static void emitArgInfo(const Record &R, std::stringstream &OS) {
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002020 // This function will count the number of arguments specified for the
2021 // attribute and emit the number of required arguments followed by the
2022 // number of optional arguments.
2023 std::vector<Record *> Args = R.getValueAsListOfDefs("Args");
2024 unsigned ArgCount = 0, OptCount = 0;
2025 for (std::vector<Record *>::const_iterator I = Args.begin(), E = Args.end();
2026 I != E; ++I) {
2027 const Record &Arg = **I;
2028 Arg.getValueAsBit("Optional") ? ++OptCount : ++ArgCount;
2029 }
2030 OS << ArgCount << ", " << OptCount;
2031}
2032
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002033static void GenerateDefaultAppertainsTo(raw_ostream &OS) {
Aaron Ballman93b5cc62013-12-02 19:36:42 +00002034 OS << "static bool defaultAppertainsTo(Sema &, const AttributeList &,";
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002035 OS << "const Decl *) {\n";
2036 OS << " return true;\n";
2037 OS << "}\n\n";
2038}
2039
2040static std::string CalculateDiagnostic(const Record &S) {
2041 // If the SubjectList object has a custom diagnostic associated with it,
2042 // return that directly.
2043 std::string CustomDiag = S.getValueAsString("CustomDiag");
2044 if (!CustomDiag.empty())
2045 return CustomDiag;
2046
2047 // Given the list of subjects, determine what diagnostic best fits.
2048 enum {
2049 Func = 1U << 0,
2050 Var = 1U << 1,
2051 ObjCMethod = 1U << 2,
2052 Param = 1U << 3,
2053 Class = 1U << 4,
Aaron Ballmanc1494bd2013-11-27 20:14:30 +00002054 GenericRecord = 1U << 5,
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002055 Type = 1U << 6,
2056 ObjCIVar = 1U << 7,
2057 ObjCProp = 1U << 8,
2058 ObjCInterface = 1U << 9,
2059 Block = 1U << 10,
2060 Namespace = 1U << 11,
2061 FuncTemplate = 1U << 12,
2062 Field = 1U << 13,
Ted Kremenekd980da22013-12-10 19:43:42 +00002063 CXXMethod = 1U << 14,
2064 ObjCProtocol = 1U << 15
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002065 };
2066 uint32_t SubMask = 0;
2067
2068 std::vector<Record *> Subjects = S.getValueAsListOfDefs("Subjects");
2069 for (std::vector<Record *>::const_iterator I = Subjects.begin(),
2070 E = Subjects.end(); I != E; ++I) {
Aaron Ballman80469032013-11-29 14:57:58 +00002071 const Record &R = (**I);
2072 std::string Name;
2073
2074 if (R.isSubClassOf("SubsetSubject")) {
2075 PrintError(R.getLoc(), "SubsetSubjects should use a custom diagnostic");
2076 // As a fallback, look through the SubsetSubject to see what its base
2077 // type is, and use that. This needs to be updated if SubsetSubjects
2078 // are allowed within other SubsetSubjects.
2079 Name = R.getValueAsDef("Base")->getName();
2080 } else
2081 Name = R.getName();
2082
2083 uint32_t V = StringSwitch<uint32_t>(Name)
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002084 .Case("Function", Func)
2085 .Case("Var", Var)
2086 .Case("ObjCMethod", ObjCMethod)
2087 .Case("ParmVar", Param)
2088 .Case("TypedefName", Type)
2089 .Case("ObjCIvar", ObjCIVar)
2090 .Case("ObjCProperty", ObjCProp)
Aaron Ballmanc1494bd2013-11-27 20:14:30 +00002091 .Case("Record", GenericRecord)
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002092 .Case("ObjCInterface", ObjCInterface)
Ted Kremenekd980da22013-12-10 19:43:42 +00002093 .Case("ObjCProtocol", ObjCProtocol)
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002094 .Case("Block", Block)
2095 .Case("CXXRecord", Class)
2096 .Case("Namespace", Namespace)
2097 .Case("FunctionTemplate", FuncTemplate)
2098 .Case("Field", Field)
2099 .Case("CXXMethod", CXXMethod)
2100 .Default(0);
2101 if (!V) {
2102 // Something wasn't in our mapping, so be helpful and let the developer
2103 // know about it.
2104 PrintFatalError((*I)->getLoc(), "Unknown subject type: " +
2105 (*I)->getName());
2106 return "";
2107 }
2108
2109 SubMask |= V;
2110 }
2111
2112 switch (SubMask) {
2113 // For the simple cases where there's only a single entry in the mask, we
2114 // don't have to resort to bit fiddling.
2115 case Func: return "ExpectedFunction";
2116 case Var: return "ExpectedVariable";
2117 case Param: return "ExpectedParameter";
2118 case Class: return "ExpectedClass";
2119 case CXXMethod:
2120 // FIXME: Currently, this maps to ExpectedMethod based on existing code,
2121 // but should map to something a bit more accurate at some point.
2122 case ObjCMethod: return "ExpectedMethod";
2123 case Type: return "ExpectedType";
2124 case ObjCInterface: return "ExpectedObjectiveCInterface";
Ted Kremenekd980da22013-12-10 19:43:42 +00002125 case ObjCProtocol: return "ExpectedObjectiveCProtocol";
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002126
Aaron Ballmanc1494bd2013-11-27 20:14:30 +00002127 // "GenericRecord" means struct, union or class; check the language options
2128 // and if not compiling for C++, strip off the class part. Note that this
2129 // relies on the fact that the context for this declares "Sema &S".
2130 case GenericRecord:
Aaron Ballman17046b82013-11-27 19:16:55 +00002131 return "(S.getLangOpts().CPlusPlus ? ExpectedStructOrUnionOrClass : "
2132 "ExpectedStructOrUnion)";
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002133 case Func | ObjCMethod | Block: return "ExpectedFunctionMethodOrBlock";
2134 case Func | ObjCMethod | Class: return "ExpectedFunctionMethodOrClass";
2135 case Func | Param:
2136 case Func | ObjCMethod | Param: return "ExpectedFunctionMethodOrParameter";
2137 case Func | FuncTemplate:
2138 case Func | ObjCMethod: return "ExpectedFunctionOrMethod";
2139 case Func | Var: return "ExpectedVariableOrFunction";
Aaron Ballman604dfec2013-12-02 17:07:07 +00002140
2141 // If not compiling for C++, the class portion does not apply.
2142 case Func | Var | Class:
2143 return "(S.getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass : "
2144 "ExpectedVariableOrFunction)";
2145
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002146 case ObjCMethod | ObjCProp: return "ExpectedMethodOrProperty";
2147 case Field | Var: return "ExpectedFieldOrGlobalVar";
2148 }
2149
2150 PrintFatalError(S.getLoc(),
2151 "Could not deduce diagnostic argument for Attr subjects");
2152
2153 return "";
2154}
2155
Aaron Ballman12b9f652014-01-16 13:55:42 +00002156static std::string GetSubjectWithSuffix(const Record *R) {
2157 std::string B = R->getName();
2158 if (B == "DeclBase")
2159 return "Decl";
2160 return B + "Decl";
2161}
Aaron Ballman80469032013-11-29 14:57:58 +00002162static std::string GenerateCustomAppertainsTo(const Record &Subject,
2163 raw_ostream &OS) {
Aaron Ballmana358c902013-12-02 14:58:17 +00002164 std::string FnName = "is" + Subject.getName();
2165
Aaron Ballman80469032013-11-29 14:57:58 +00002166 // If this code has already been generated, simply return the previous
2167 // instance of it.
2168 static std::set<std::string> CustomSubjectSet;
Aaron Ballmana358c902013-12-02 14:58:17 +00002169 std::set<std::string>::iterator I = CustomSubjectSet.find(FnName);
Aaron Ballman80469032013-11-29 14:57:58 +00002170 if (I != CustomSubjectSet.end())
2171 return *I;
2172
2173 Record *Base = Subject.getValueAsDef("Base");
2174
2175 // Not currently support custom subjects within custom subjects.
2176 if (Base->isSubClassOf("SubsetSubject")) {
2177 PrintFatalError(Subject.getLoc(),
2178 "SubsetSubjects within SubsetSubjects is not supported");
2179 return "";
2180 }
2181
Aaron Ballman80469032013-11-29 14:57:58 +00002182 OS << "static bool " << FnName << "(const Decl *D) {\n";
Aaron Ballman47553042014-01-16 14:32:03 +00002183 OS << " if (const " << GetSubjectWithSuffix(Base) << " *S = dyn_cast<";
Aaron Ballman12b9f652014-01-16 13:55:42 +00002184 OS << GetSubjectWithSuffix(Base);
Aaron Ballman47553042014-01-16 14:32:03 +00002185 OS << ">(D))\n";
2186 OS << " return " << Subject.getValueAsString("CheckCode") << ";\n";
2187 OS << " return false;\n";
Aaron Ballman80469032013-11-29 14:57:58 +00002188 OS << "}\n\n";
2189
2190 CustomSubjectSet.insert(FnName);
2191 return FnName;
2192}
2193
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002194static std::string GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) {
2195 // If the attribute does not contain a Subjects definition, then use the
2196 // default appertainsTo logic.
2197 if (Attr.isValueUnset("Subjects"))
Aaron Ballman93b5cc62013-12-02 19:36:42 +00002198 return "defaultAppertainsTo";
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002199
2200 const Record *SubjectObj = Attr.getValueAsDef("Subjects");
2201 std::vector<Record*> Subjects = SubjectObj->getValueAsListOfDefs("Subjects");
2202
2203 // If the list of subjects is empty, it is assumed that the attribute
2204 // appertains to everything.
2205 if (Subjects.empty())
Aaron Ballman93b5cc62013-12-02 19:36:42 +00002206 return "defaultAppertainsTo";
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002207
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002208 bool Warn = SubjectObj->getValueAsDef("Diag")->getValueAsBit("Warn");
2209
2210 // Otherwise, generate an appertainsTo check specific to this attribute which
2211 // checks all of the given subjects against the Decl passed in. Return the
2212 // name of that check to the caller.
Aaron Ballman00dcc432013-12-03 13:45:50 +00002213 std::string FnName = "check" + Attr.getName() + "AppertainsTo";
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002214 std::stringstream SS;
2215 SS << "static bool " << FnName << "(Sema &S, const AttributeList &Attr, ";
2216 SS << "const Decl *D) {\n";
2217 SS << " if (";
2218 for (std::vector<Record *>::const_iterator I = Subjects.begin(),
2219 E = Subjects.end(); I != E; ++I) {
Aaron Ballman80469032013-11-29 14:57:58 +00002220 // If the subject has custom code associated with it, generate a function
2221 // for it. The function cannot be inlined into this check (yet) because it
2222 // requires the subject to be of a specific type, and were that information
2223 // inlined here, it would not support an attribute with multiple custom
2224 // subjects.
2225 if ((*I)->isSubClassOf("SubsetSubject")) {
2226 SS << "!" << GenerateCustomAppertainsTo(**I, OS) << "(D)";
2227 } else {
Aaron Ballman12b9f652014-01-16 13:55:42 +00002228 SS << "!isa<" << GetSubjectWithSuffix(*I) << ">(D)";
Aaron Ballman80469032013-11-29 14:57:58 +00002229 }
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002230
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002231 if (I + 1 != E)
2232 SS << " && ";
2233 }
2234 SS << ") {\n";
2235 SS << " S.Diag(Attr.getLoc(), diag::";
2236 SS << (Warn ? "warn_attribute_wrong_decl_type" :
2237 "err_attribute_wrong_decl_type");
2238 SS << ")\n";
2239 SS << " << Attr.getName() << ";
2240 SS << CalculateDiagnostic(*SubjectObj) << ";\n";
2241 SS << " return false;\n";
2242 SS << " }\n";
2243 SS << " return true;\n";
2244 SS << "}\n\n";
2245
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002246 OS << SS.str();
2247 return FnName;
2248}
2249
Aaron Ballman3aff6332013-12-02 19:30:36 +00002250static void GenerateDefaultLangOptRequirements(raw_ostream &OS) {
2251 OS << "static bool defaultDiagnoseLangOpts(Sema &, ";
2252 OS << "const AttributeList &) {\n";
2253 OS << " return true;\n";
2254 OS << "}\n\n";
2255}
2256
2257static std::string GenerateLangOptRequirements(const Record &R,
2258 raw_ostream &OS) {
2259 // If the attribute has an empty or unset list of language requirements,
2260 // return the default handler.
2261 std::vector<Record *> LangOpts = R.getValueAsListOfDefs("LangOpts");
2262 if (LangOpts.empty())
2263 return "defaultDiagnoseLangOpts";
2264
2265 // Generate the test condition, as well as a unique function name for the
2266 // diagnostic test. The list of options should usually be short (one or two
2267 // options), and the uniqueness isn't strictly necessary (it is just for
2268 // codegen efficiency).
2269 std::string FnName = "check", Test;
2270 for (std::vector<Record *>::const_iterator I = LangOpts.begin(),
2271 E = LangOpts.end(); I != E; ++I) {
2272 std::string Part = (*I)->getValueAsString("Name");
2273 Test += "S.LangOpts." + Part;
2274 if (I + 1 != E)
2275 Test += " || ";
2276 FnName += Part;
2277 }
2278 FnName += "LangOpts";
2279
2280 // If this code has already been generated, simply return the previous
2281 // instance of it.
2282 static std::set<std::string> CustomLangOptsSet;
2283 std::set<std::string>::iterator I = CustomLangOptsSet.find(FnName);
2284 if (I != CustomLangOptsSet.end())
2285 return *I;
2286
2287 OS << "static bool " << FnName << "(Sema &S, const AttributeList &Attr) {\n";
2288 OS << " if (" << Test << ")\n";
2289 OS << " return true;\n\n";
2290 OS << " S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) ";
2291 OS << "<< Attr.getName();\n";
2292 OS << " return false;\n";
2293 OS << "}\n\n";
2294
2295 CustomLangOptsSet.insert(FnName);
2296 return FnName;
2297}
2298
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002299static void GenerateDefaultTargetRequirements(raw_ostream &OS) {
2300 OS << "static bool defaultTargetRequirements(llvm::Triple) {\n";
2301 OS << " return true;\n";
2302 OS << "}\n\n";
2303}
2304
2305static std::string GenerateTargetRequirements(const Record &Attr,
2306 const ParsedAttrMap &Dupes,
2307 raw_ostream &OS) {
2308 // If the attribute is not a target specific attribute, return the default
2309 // target handler.
2310 if (!Attr.isSubClassOf("TargetSpecificAttr"))
2311 return "defaultTargetRequirements";
2312
2313 // Get the list of architectures to be tested for.
2314 const Record *R = Attr.getValueAsDef("Target");
2315 std::vector<std::string> Arches = R->getValueAsListOfStrings("Arches");
2316 if (Arches.empty()) {
2317 PrintError(Attr.getLoc(), "Empty list of target architectures for a "
2318 "target-specific attr");
2319 return "defaultTargetRequirements";
2320 }
2321
2322 // If there are other attributes which share the same parsed attribute kind,
2323 // such as target-specific attributes with a shared spelling, collapse the
2324 // duplicate architectures. This is required because a shared target-specific
2325 // attribute has only one AttributeList::Kind enumeration value, but it
2326 // applies to multiple target architectures. In order for the attribute to be
2327 // considered valid, all of its architectures need to be included.
2328 if (!Attr.isValueUnset("ParseKind")) {
2329 std::string APK = Attr.getValueAsString("ParseKind");
2330 for (ParsedAttrMap::const_iterator I = Dupes.begin(), E = Dupes.end();
2331 I != E; ++I) {
2332 if (I->first == APK) {
2333 std::vector<std::string> DA = I->second->getValueAsDef("Target")->
2334 getValueAsListOfStrings("Arches");
2335 std::copy(DA.begin(), DA.end(), std::back_inserter(Arches));
2336 }
2337 }
2338 }
2339
2340 std::string FnName = "isTarget", Test = "(";
2341 for (std::vector<std::string>::const_iterator I = Arches.begin(),
2342 E = Arches.end(); I != E; ++I) {
2343 std::string Part = *I;
2344 Test += "Arch == llvm::Triple::" + Part;
2345 if (I + 1 != E)
2346 Test += " || ";
2347 FnName += Part;
2348 }
2349 Test += ")";
2350
2351 // If the target also requires OS testing, generate those tests as well.
2352 bool UsesOS = false;
2353 if (!R->isValueUnset("OSes")) {
2354 UsesOS = true;
2355
2356 // We know that there was at least one arch test, so we need to and in the
2357 // OS tests.
2358 Test += " && (";
2359 std::vector<std::string> OSes = R->getValueAsListOfStrings("OSes");
2360 for (std::vector<std::string>::const_iterator I = OSes.begin(),
2361 E = OSes.end(); I != E; ++I) {
2362 std::string Part = *I;
2363
2364 Test += "OS == llvm::Triple::" + Part;
2365 if (I + 1 != E)
2366 Test += " || ";
2367 FnName += Part;
2368 }
2369 Test += ")";
2370 }
2371
2372 // If this code has already been generated, simply return the previous
2373 // instance of it.
2374 static std::set<std::string> CustomTargetSet;
2375 std::set<std::string>::iterator I = CustomTargetSet.find(FnName);
2376 if (I != CustomTargetSet.end())
2377 return *I;
2378
2379 OS << "static bool " << FnName << "(llvm::Triple T) {\n";
2380 OS << " llvm::Triple::ArchType Arch = T.getArch();\n";
2381 if (UsesOS)
2382 OS << " llvm::Triple::OSType OS = T.getOS();\n";
2383 OS << " return " << Test << ";\n";
2384 OS << "}\n\n";
2385
2386 CustomTargetSet.insert(FnName);
2387 return FnName;
2388}
2389
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00002390static void GenerateDefaultSpellingIndexToSemanticSpelling(raw_ostream &OS) {
2391 OS << "static unsigned defaultSpellingIndexToSemanticSpelling("
2392 << "const AttributeList &Attr) {\n";
2393 OS << " return UINT_MAX;\n";
2394 OS << "}\n\n";
2395}
2396
2397static std::string GenerateSpellingIndexToSemanticSpelling(const Record &Attr,
2398 raw_ostream &OS) {
2399 // If the attribute does not have a semantic form, we can bail out early.
2400 if (!Attr.getValueAsBit("ASTNode"))
2401 return "defaultSpellingIndexToSemanticSpelling";
2402
Aaron Ballmanc669cc02014-01-27 22:10:04 +00002403 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00002404
2405 // If there are zero or one spellings, or all of the spellings share the same
2406 // name, we can also bail out early.
2407 if (Spellings.size() <= 1 || SpellingNamesAreCommon(Spellings))
2408 return "defaultSpellingIndexToSemanticSpelling";
2409
2410 // Generate the enumeration we will use for the mapping.
2411 SemanticSpellingMap SemanticToSyntacticMap;
2412 std::string Enum = CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);
2413 std::string Name = Attr.getName() + "AttrSpellingMap";
2414
2415 OS << "static unsigned " << Name << "(const AttributeList &Attr) {\n";
2416 OS << Enum;
2417 OS << " unsigned Idx = Attr.getAttributeSpellingListIndex();\n";
2418 WriteSemanticSpellingSwitch("Idx", SemanticToSyntacticMap, OS);
2419 OS << "}\n\n";
2420
2421 return Name;
2422}
2423
Aaron Ballmanc669cc02014-01-27 22:10:04 +00002424static bool IsKnownToGCC(const Record &Attr) {
2425 // Look at the spellings for this subject; if there are any spellings which
2426 // claim to be known to GCC, the attribute is known to GCC.
2427 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
2428 for (std::vector<FlattenedSpelling>::const_iterator I = Spellings.begin(),
2429 E = Spellings.end(); I != E; ++I) {
2430 if (I->knownToGCC())
Aaron Ballman9a99e0d2014-01-20 17:18:35 +00002431 return true;
2432 }
2433 return false;
2434}
2435
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002436/// Emits the parsed attribute helpers
2437void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
2438 emitSourceFileHeader("Parsed attribute helpers", OS);
2439
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002440 // Get the list of parsed attributes, and accept the optional list of
2441 // duplicates due to the ParseKind.
2442 ParsedAttrMap Dupes;
2443 ParsedAttrMap Attrs = getParsedAttrList(Records, &Dupes);
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002444
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00002445 // Generate the default appertainsTo, target and language option diagnostic,
2446 // and spelling list index mapping methods.
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002447 GenerateDefaultAppertainsTo(OS);
Aaron Ballman3aff6332013-12-02 19:30:36 +00002448 GenerateDefaultLangOptRequirements(OS);
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002449 GenerateDefaultTargetRequirements(OS);
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00002450 GenerateDefaultSpellingIndexToSemanticSpelling(OS);
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002451
2452 // Generate the appertainsTo diagnostic methods and write their names into
2453 // another mapping. At the same time, generate the AttrInfoMap object
2454 // contents. Due to the reliance on generated code, use separate streams so
2455 // that code will not be interleaved.
2456 std::stringstream SS;
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002457 for (ParsedAttrMap::iterator I = Attrs.begin(), E = Attrs.end(); I != E;
2458 ++I) {
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002459 // TODO: If the attribute's kind appears in the list of duplicates, that is
2460 // because it is a target-specific attribute that appears multiple times.
2461 // It would be beneficial to test whether the duplicates are "similar
2462 // enough" to each other to not cause problems. For instance, check that
Alp Toker96cf7582014-01-18 21:49:37 +00002463 // the spellings are identical, and custom parsing rules match, etc.
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002464
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002465 // We need to generate struct instances based off ParsedAttrInfo from
2466 // AttributeList.cpp.
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002467 SS << " { ";
2468 emitArgInfo(*I->second, SS);
2469 SS << ", " << I->second->getValueAsBit("HasCustomParsing");
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002470 SS << ", " << I->second->isSubClassOf("TargetSpecificAttr");
2471 SS << ", " << I->second->isSubClassOf("TypeAttr");
Aaron Ballmanc669cc02014-01-27 22:10:04 +00002472 SS << ", " << IsKnownToGCC(*I->second);
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002473 SS << ", " << GenerateAppertainsTo(*I->second, OS);
Aaron Ballman3aff6332013-12-02 19:30:36 +00002474 SS << ", " << GenerateLangOptRequirements(*I->second, OS);
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002475 SS << ", " << GenerateTargetRequirements(*I->second, Dupes, OS);
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00002476 SS << ", " << GenerateSpellingIndexToSemanticSpelling(*I->second, OS);
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002477 SS << " }";
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002478
2479 if (I + 1 != E)
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002480 SS << ",";
2481
2482 SS << " // AT_" << I->first << "\n";
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002483 }
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002484
2485 OS << "static const ParsedAttrInfo AttrInfoMap[AttributeList::UnknownAttribute + 1] = {\n";
2486 OS << SS.str();
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002487 OS << "};\n\n";
Michael Han4a045172012-03-07 00:12:16 +00002488}
2489
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00002490// Emits the kind list of parsed attributes
2491void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00002492 emitSourceFileHeader("Attribute name matcher", OS);
2493
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002494 std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
2495 std::vector<StringMatcher::StringPair> GNU, Declspec, CXX11, Keywords;
Aaron Ballman64e69862013-12-15 13:05:48 +00002496 std::set<std::string> Seen;
Michael Han4a045172012-03-07 00:12:16 +00002497 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
2498 I != E; ++I) {
2499 Record &Attr = **I;
Richard Smith852e9ce2013-11-27 01:46:48 +00002500
Michael Han4a045172012-03-07 00:12:16 +00002501 bool SemaHandler = Attr.getValueAsBit("SemaHandler");
Douglas Gregor19fbb8f2012-05-02 16:18:45 +00002502 bool Ignored = Attr.getValueAsBit("Ignored");
Douglas Gregor19fbb8f2012-05-02 16:18:45 +00002503 if (SemaHandler || Ignored) {
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002504 // Attribute spellings can be shared between target-specific attributes,
2505 // and can be shared between syntaxes for the same attribute. For
2506 // instance, an attribute can be spelled GNU<"interrupt"> for an ARM-
2507 // specific attribute, or MSP430-specific attribute. Additionally, an
2508 // attribute can be spelled GNU<"dllexport"> and Declspec<"dllexport">
2509 // for the same semantic attribute. Ultimately, we need to map each of
2510 // these to a single AttributeList::Kind value, but the StringMatcher
2511 // class cannot handle duplicate match strings. So we generate a list of
2512 // string to match based on the syntax, and emit multiple string matchers
2513 // depending on the syntax used.
Aaron Ballman64e69862013-12-15 13:05:48 +00002514 std::string AttrName;
2515 if (Attr.isSubClassOf("TargetSpecificAttr") &&
2516 !Attr.isValueUnset("ParseKind")) {
2517 AttrName = Attr.getValueAsString("ParseKind");
2518 if (Seen.find(AttrName) != Seen.end())
2519 continue;
2520 Seen.insert(AttrName);
2521 } else
2522 AttrName = NormalizeAttrName(StringRef(Attr.getName())).str();
2523
Aaron Ballmanc669cc02014-01-27 22:10:04 +00002524 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
2525 for (std::vector<FlattenedSpelling>::const_iterator
2526 I = Spellings.begin(), E = Spellings.end(); I != E; ++I) {
2527 std::string RawSpelling = I->name();
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002528 std::vector<StringMatcher::StringPair> *Matches = 0;
Aaron Ballmanc669cc02014-01-27 22:10:04 +00002529 std::string Spelling, Variety = I->variety();
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002530 if (Variety == "CXX11") {
2531 Matches = &CXX11;
Aaron Ballmanc669cc02014-01-27 22:10:04 +00002532 Spelling += I->nameSpace();
Alexis Hunt3bc72c12012-06-19 23:57:03 +00002533 Spelling += "::";
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002534 } else if (Variety == "GNU")
2535 Matches = &GNU;
2536 else if (Variety == "Declspec")
2537 Matches = &Declspec;
2538 else if (Variety == "Keyword")
2539 Matches = &Keywords;
Alexis Hunta0e54d42012-06-18 16:13:52 +00002540
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002541 assert(Matches && "Unsupported spelling variety found");
2542
2543 Spelling += NormalizeAttrSpelling(RawSpelling);
Douglas Gregor19fbb8f2012-05-02 16:18:45 +00002544 if (SemaHandler)
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002545 Matches->push_back(StringMatcher::StringPair(Spelling,
2546 "return AttributeList::AT_" + AttrName + ";"));
Douglas Gregor19fbb8f2012-05-02 16:18:45 +00002547 else
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002548 Matches->push_back(StringMatcher::StringPair(Spelling,
2549 "return AttributeList::IgnoredAttribute;"));
Michael Han4a045172012-03-07 00:12:16 +00002550 }
2551 }
2552 }
Douglas Gregor377f99b2012-05-02 17:33:51 +00002553
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002554 OS << "static AttributeList::Kind getAttrKind(StringRef Name, ";
2555 OS << "AttributeList::Syntax Syntax) {\n";
2556 OS << " if (AttributeList::AS_GNU == Syntax) {\n";
2557 StringMatcher("Name", GNU, OS).Emit();
2558 OS << " } else if (AttributeList::AS_Declspec == Syntax) {\n";
2559 StringMatcher("Name", Declspec, OS).Emit();
2560 OS << " } else if (AttributeList::AS_CXX11 == Syntax) {\n";
2561 StringMatcher("Name", CXX11, OS).Emit();
2562 OS << " } else if (AttributeList::AS_Keyword == Syntax) {\n";
2563 StringMatcher("Name", Keywords, OS).Emit();
2564 OS << " }\n";
2565 OS << " return AttributeList::UnknownAttribute;\n"
Douglas Gregor377f99b2012-05-02 17:33:51 +00002566 << "}\n";
Michael Han4a045172012-03-07 00:12:16 +00002567}
2568
Alexander Kornienko5bc364e2013-01-07 17:53:08 +00002569// Emits the code to dump an attribute.
2570void EmitClangAttrDump(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00002571 emitSourceFileHeader("Attribute dumper", OS);
2572
Alexander Kornienko5bc364e2013-01-07 17:53:08 +00002573 OS <<
2574 " switch (A->getKind()) {\n"
2575 " default:\n"
2576 " llvm_unreachable(\"Unknown attribute kind!\");\n"
2577 " break;\n";
2578 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
2579 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
2580 I != E; ++I) {
2581 Record &R = **I;
2582 if (!R.getValueAsBit("ASTNode"))
2583 continue;
2584 OS << " case attr::" << R.getName() << ": {\n";
Aaron Ballmanbc909612014-01-22 21:51:20 +00002585
2586 // If the attribute has a semantically-meaningful name (which is determined
2587 // by whether there is a Spelling enumeration for it), then write out the
2588 // spelling used for the attribute.
Aaron Ballmanc669cc02014-01-27 22:10:04 +00002589 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
Aaron Ballmanbc909612014-01-22 21:51:20 +00002590 if (Spellings.size() > 1 && !SpellingNamesAreCommon(Spellings))
2591 OS << " OS << \" \" << A->getSpelling();\n";
2592
Alexander Kornienko5bc364e2013-01-07 17:53:08 +00002593 Args = R.getValueAsListOfDefs("Args");
2594 if (!Args.empty()) {
2595 OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
2596 << "Attr>(A);\n";
2597 for (std::vector<Record*>::iterator I = Args.begin(), E = Args.end();
2598 I != E; ++I)
2599 createArgument(**I, R.getName())->writeDump(OS);
Richard Trieude5cc7d2013-01-31 01:44:26 +00002600
2601 // Code for detecting the last child.
2602 OS << " bool OldMoreChildren = hasMoreChildren();\n";
2603 OS << " bool MoreChildren = OldMoreChildren;\n";
2604
Alexander Kornienko5bc364e2013-01-07 17:53:08 +00002605 for (std::vector<Record*>::iterator I = Args.begin(), E = Args.end();
Richard Trieude5cc7d2013-01-31 01:44:26 +00002606 I != E; ++I) {
2607 // More code for detecting the last child.
2608 OS << " MoreChildren = OldMoreChildren";
2609 for (std::vector<Record*>::iterator Next = I + 1; Next != E; ++Next) {
2610 OS << " || ";
2611 createArgument(**Next, R.getName())->writeHasChildren(OS);
2612 }
2613 OS << ";\n";
2614 OS << " setMoreChildren(MoreChildren);\n";
2615
Alexander Kornienko5bc364e2013-01-07 17:53:08 +00002616 createArgument(**I, R.getName())->writeDumpChildren(OS);
Richard Trieude5cc7d2013-01-31 01:44:26 +00002617 }
2618
2619 // Reset the last child.
2620 OS << " setMoreChildren(OldMoreChildren);\n";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +00002621 }
2622 OS <<
2623 " break;\n"
2624 " }\n";
2625 }
2626 OS << " }\n";
2627}
2628
Aaron Ballman35db2b32014-01-29 22:13:45 +00002629void EmitClangAttrParserStringSwitches(RecordKeeper &Records,
2630 raw_ostream &OS) {
2631 emitSourceFileHeader("Parser-related llvm::StringSwitch cases", OS);
2632 emitClangAttrArgContextList(Records, OS);
2633 emitClangAttrIdentifierArgList(Records, OS);
2634 emitClangAttrTypeArgList(Records, OS);
2635 emitClangAttrLateParsedList(Records, OS);
2636}
2637
Aaron Ballman97dba042014-02-17 15:27:10 +00002638class DocumentationData {
2639public:
2640 enum DocCategory {
2641 Function,
2642 Variable,
2643 Type,
2644 Undocumented
2645 };
2646
2647 DocCategory Category;
2648 const Record &Documentation;
2649 const Record &Attribute;
2650
2651 DocumentationData(DocCategory Category, const Record &Documentation,
2652 const Record &Attribute)
2653 : Category(Category), Documentation(Documentation), Attribute(Attribute) {
2654 }
2655};
2656
2657static void WriteCategoryHeader(DocumentationData::DocCategory Category,
2658 raw_ostream &OS) {
2659 OS << "\n";
2660 switch (Category) {
2661 case DocumentationData::Undocumented:
2662 assert(false && "Undocumented attributes are not documented!");
2663 break;
2664 case DocumentationData::Function:
2665 OS << "Function Attributes\n";
2666 OS << "===================\n";
2667 break;
2668 case DocumentationData::Variable:
2669 OS << "Variable Attributes\n";
2670 OS << "===================\n";
2671 break;
2672 case DocumentationData::Type:
2673 OS << "Type Attributes\n";
2674 OS << "===============\n";
2675 break;
2676 }
2677 OS << "\n";
2678}
2679
Aaron Ballmana66b5742014-02-17 15:36:08 +00002680enum SpellingKind {
2681 GNU = 1 << 0,
2682 CXX11 = 1 << 1,
2683 Declspec = 1 << 2,
2684 Keyword = 1 << 3
2685};
2686
Aaron Ballman97dba042014-02-17 15:27:10 +00002687static void WriteDocumentation(const DocumentationData &Doc,
2688 raw_ostream &OS) {
2689 // FIXME: there is no way to have a per-spelling category for the attribute
2690 // documentation. This may not be a limiting factor since the spellings
2691 // should generally be consistently applied across the category.
2692
2693 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Doc.Attribute);
2694
2695 // Determine the heading to be used for this attribute.
2696 std::string Heading = Doc.Documentation.getValueAsString("Heading");
2697 if (Heading.empty()) {
2698 // If there's only one spelling, we can simply use that.
2699 if (Spellings.size() == 1)
2700 Heading = Spellings.begin()->name();
2701 else {
2702 std::set<std::string> Uniques;
2703 for (std::vector<FlattenedSpelling>::const_iterator I = Spellings.begin(),
2704 E = Spellings.end(); I != E && Uniques.size() <= 1; ++I) {
2705 std::string Spelling = NormalizeNameForSpellingComparison(I->name());
2706 Uniques.insert(Spelling);
2707 }
2708 // If the semantic map has only one spelling, that is sufficient for our
2709 // needs.
2710 if (Uniques.size() == 1)
2711 Heading = *Uniques.begin();
2712 }
2713 }
2714
2715 // If the heading is still empty, it is an error.
2716 if (Heading.empty())
2717 PrintFatalError(Doc.Attribute.getLoc(),
2718 "This attribute requires a heading to be specified");
2719
2720 // Gather a list of unique spellings; this is not the same as the semantic
2721 // spelling for the attribute. Variations in underscores and other non-
2722 // semantic characters are still acceptable.
2723 std::vector<std::string> Names;
2724
Aaron Ballman97dba042014-02-17 15:27:10 +00002725 unsigned SupportedSpellings = 0;
2726 for (std::vector<FlattenedSpelling>::const_iterator I = Spellings.begin(),
2727 E = Spellings.end(); I != E; ++I) {
2728 SpellingKind Kind = StringSwitch<SpellingKind>(I->variety())
2729 .Case("GNU", GNU)
2730 .Case("CXX11", CXX11)
2731 .Case("Declspec", Declspec)
2732 .Case("Keyword", Keyword);
2733
2734 // Mask in the supported spelling.
2735 SupportedSpellings |= Kind;
2736
2737 std::string Name;
2738 if (Kind == CXX11 && !I->nameSpace().empty())
2739 Name = I->nameSpace() + "::";
2740 Name += I->name();
2741
2742 // If this name is the same as the heading, do not add it.
2743 if (Name != Heading)
2744 Names.push_back(Name);
2745 }
2746
2747 // Print out the heading for the attribute. If there are alternate spellings,
2748 // then display those after the heading.
2749 if (!Names.empty()) {
2750 Heading += " (";
2751 for (std::vector<std::string>::const_iterator I = Names.begin(),
2752 E = Names.end(); I != E; ++I) {
2753 if (I != Names.begin())
2754 Heading += ", ";
2755 Heading += *I;
2756 }
2757 Heading += ")";
2758 }
2759 OS << Heading << "\n" << std::string(Heading.length(), '-') << "\n";
2760
2761 if (!SupportedSpellings)
2762 PrintFatalError(Doc.Attribute.getLoc(),
2763 "Attribute has no supported spellings; cannot be "
2764 "documented");
2765
2766 // List what spelling syntaxes the attribute supports.
2767 OS << ".. csv-table:: Supported Syntaxes\n";
2768 OS << " :header: \"GNU\", \"C++11\", \"__declspec\", \"Keyword\"\n\n";
2769 OS << " \"";
2770 if (SupportedSpellings & GNU) OS << "X";
2771 OS << "\",\"";
2772 if (SupportedSpellings & CXX11) OS << "X";
2773 OS << "\",\"";
2774 if (SupportedSpellings & Declspec) OS << "X";
2775 OS << "\",\"";
2776 if (SupportedSpellings & Keyword) OS << "X";
2777 OS << "\"\n\n";
2778
2779 // If the attribute is deprecated, print a message about it, and possibly
2780 // provide a replacement attribute.
2781 if (!Doc.Documentation.isValueUnset("Deprecated")) {
2782 OS << "This attribute has been deprecated, and may be removed in a future "
2783 << "version of Clang.";
2784 const Record &Deprecated = *Doc.Documentation.getValueAsDef("Deprecated");
2785 std::string Replacement = Deprecated.getValueAsString("Replacement");
2786 if (!Replacement.empty())
2787 OS << " This attribute has been superseded by ``"
2788 << Replacement << "``.";
2789 OS << "\n\n";
2790 }
2791
2792 std::string ContentStr = Doc.Documentation.getValueAsString("Content");
2793 // Trim leading and trailing newlines and spaces.
2794 StringRef Content(ContentStr);
2795 while (Content.startswith("\r") || Content.startswith("\n") ||
2796 Content.startswith(" ") || Content.startswith("\t"))
2797 Content = Content.substr(1);
2798 while (Content.endswith("\r") || Content.endswith("\n") ||
2799 Content.endswith(" ") || Content.endswith("\t"))
2800 Content = Content.substr(0, Content.size() - 1);
2801 OS << Content;
2802
2803 OS << "\n\n\n";
2804}
2805
2806void EmitClangAttrDocs(RecordKeeper &Records, raw_ostream &OS) {
2807 // Get the documentation introduction paragraph.
2808 const Record *Documentation = Records.getDef("GlobalDocumentation");
2809 if (!Documentation) {
2810 PrintFatalError("The Documentation top-level definition is missing, "
2811 "no documentation will be generated.");
2812 return;
2813 }
2814
2815 OS << Documentation->getValueAsString("Intro");
2816
2817 typedef std::map<DocumentationData::DocCategory,
2818 std::vector<DocumentationData> > CategoryMap;
2819 CategoryMap SplitDocs;
2820
2821 // Gather the Documentation lists from each of the attributes, based on the
2822 // category provided.
2823 std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
2824 for (std::vector<Record *>::const_iterator I = Attrs.begin(),
2825 E = Attrs.end(); I != E; ++I) {
2826 const Record &Attr = **I;
2827 std::vector<Record *> Docs = Attr.getValueAsListOfDefs("Documentation");
2828 for (std::vector<Record *>::const_iterator DI = Docs.begin(),
2829 DE = Docs.end(); DI != DE; ++DI) {
2830 const Record &Doc = **DI;
2831 DocumentationData::DocCategory Cat =
2832 StringSwitch<DocumentationData::DocCategory>(
2833 Doc.getValueAsDef("Category")->getValueAsString("Name"))
2834 .Case("Functions", DocumentationData::Function)
2835 .Case("Variables", DocumentationData::Variable)
2836 .Case("Types", DocumentationData::Type)
2837 .Case("Undocumented", DocumentationData::Undocumented);
2838
2839 // If the category is "undocumented", then there cannot be any other
2840 // documentation categories (otherwise, the attribute would become
2841 // documented).
2842 bool Undocumented = DocumentationData::Undocumented == Cat;
2843 if (Undocumented && Docs.size() > 1)
2844 PrintFatalError(Doc.getLoc(),
2845 "Attribute is \"Undocumented\", but has multiple "
2846 "documentation categories");
2847
2848 if (!Undocumented)
2849 SplitDocs[Cat].push_back(DocumentationData(Cat, Doc, Attr));
2850 }
2851 }
2852
2853 // Having split the attributes out based on what documentation goes where,
2854 // we can begin to generate sections of documentation.
2855 for (CategoryMap::const_iterator I = SplitDocs.begin(), E = SplitDocs.end();
2856 I != E; ++I) {
2857 WriteCategoryHeader(I->first, OS);
2858
2859 // Walk over each of the attributes in the category and write out their
2860 // documentation.
2861 for (auto D : I->second)
2862 WriteDocumentation(D, OS);
2863 }
2864}
2865
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00002866} // end namespace clang