blob: 44f14229f70393ec75c20cd3dbabb1a81994f735 [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"
Chandler Carruth757fcd62014-03-04 10:05:20 +000015#include "llvm/ADT/STLExtras.h"
Aaron Ballman8ee40b72013-09-09 23:33:17 +000016#include "llvm/ADT/SmallSet.h"
Chandler Carruth5553d0d2014-01-07 11:51:46 +000017#include "llvm/ADT/StringSwitch.h"
18#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
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +000059 for (const auto &Spelling : Spellings) {
60 if (Spelling->getValueAsString("Variety") == "GCC") {
Aaron Ballmanc669cc02014-01-27 22:10:04 +000061 // Gin up two new spelling objects to add into the list.
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +000062 Ret.push_back(FlattenedSpelling("GNU", Spelling->getValueAsString("Name"),
Aaron Ballmanc669cc02014-01-27 22:10:04 +000063 "", true));
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +000064 Ret.push_back(FlattenedSpelling(
65 "CXX11", Spelling->getValueAsString("Name"), "gnu", true));
Aaron Ballmanc669cc02014-01-27 22:10:04 +000066 } else
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +000067 Ret.push_back(FlattenedSpelling(*Spelling));
Aaron Ballmanc669cc02014-01-27 22:10:04 +000068 }
69
70 return Ret;
71}
72
Peter Collingbournebee583f2011-10-06 13:03:08 +000073static std::string ReadPCHRecord(StringRef type) {
74 return StringSwitch<std::string>(type)
75 .EndsWith("Decl *", "GetLocalDeclAs<"
76 + std::string(type, 0, type.size()-1) + ">(F, Record[Idx++])")
Richard Smithb87c4652013-10-31 21:23:20 +000077 .Case("TypeSourceInfo *", "GetTypeSourceInfo(F, Record, Idx)")
Argyrios Kyrtzidisa660ae42012-11-15 01:31:39 +000078 .Case("Expr *", "ReadExpr(F)")
Peter Collingbournebee583f2011-10-06 13:03:08 +000079 .Case("IdentifierInfo *", "GetIdentifierInfo(F, Record, Idx)")
Peter Collingbournebee583f2011-10-06 13:03:08 +000080 .Default("Record[Idx++]");
81}
82
83// Assumes that the way to get the value is SA->getname()
84static std::string WritePCHRecord(StringRef type, StringRef name) {
85 return StringSwitch<std::string>(type)
86 .EndsWith("Decl *", "AddDeclRef(" + std::string(name) +
87 ", Record);\n")
Richard Smithb87c4652013-10-31 21:23:20 +000088 .Case("TypeSourceInfo *",
89 "AddTypeSourceInfo(" + std::string(name) + ", Record);\n")
Peter Collingbournebee583f2011-10-06 13:03:08 +000090 .Case("Expr *", "AddStmt(" + std::string(name) + ");\n")
91 .Case("IdentifierInfo *",
92 "AddIdentifierRef(" + std::string(name) + ", Record);\n")
Peter Collingbournebee583f2011-10-06 13:03:08 +000093 .Default("Record.push_back(" + std::string(name) + ");\n");
94}
95
Michael Han4a045172012-03-07 00:12:16 +000096// Normalize attribute name by removing leading and trailing
97// underscores. For example, __foo, foo__, __foo__ would
98// become foo.
99static StringRef NormalizeAttrName(StringRef AttrName) {
100 if (AttrName.startswith("__"))
101 AttrName = AttrName.substr(2, AttrName.size());
102
103 if (AttrName.endswith("__"))
104 AttrName = AttrName.substr(0, AttrName.size() - 2);
105
106 return AttrName;
107}
108
Aaron Ballman36a53502014-01-16 13:03:14 +0000109// Normalize the name by removing any and all leading and trailing underscores.
110// This is different from NormalizeAttrName in that it also handles names like
111// _pascal and __pascal.
112static StringRef NormalizeNameForSpellingComparison(StringRef Name) {
113 while (Name.startswith("_"))
114 Name = Name.substr(1, Name.size());
115 while (Name.endswith("_"))
116 Name = Name.substr(0, Name.size() - 1);
117 return Name;
118}
119
Michael Han4a045172012-03-07 00:12:16 +0000120// Normalize attribute spelling only if the spelling has both leading
121// and trailing underscores. For example, __ms_struct__ will be
122// normalized to "ms_struct"; __cdecl will remain intact.
123static StringRef NormalizeAttrSpelling(StringRef AttrSpelling) {
124 if (AttrSpelling.startswith("__") && AttrSpelling.endswith("__")) {
125 AttrSpelling = AttrSpelling.substr(2, AttrSpelling.size() - 4);
126 }
127
128 return AttrSpelling;
129}
130
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +0000131typedef std::vector<std::pair<std::string, Record *>> ParsedAttrMap;
Aaron Ballman64e69862013-12-15 13:05:48 +0000132
Aaron Ballmanab7691c2014-01-09 22:48:32 +0000133static ParsedAttrMap getParsedAttrList(const RecordKeeper &Records,
134 ParsedAttrMap *Dupes = 0) {
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +0000135 std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
Aaron Ballman64e69862013-12-15 13:05:48 +0000136 std::set<std::string> Seen;
137 ParsedAttrMap R;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +0000138 for (auto Attr : Attrs) {
139 if (Attr->getValueAsBit("SemaHandler")) {
Aaron Ballman64e69862013-12-15 13:05:48 +0000140 std::string AN;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +0000141 if (Attr->isSubClassOf("TargetSpecificAttr") &&
142 !Attr->isValueUnset("ParseKind")) {
143 AN = Attr->getValueAsString("ParseKind");
Aaron Ballman64e69862013-12-15 13:05:48 +0000144
145 // If this attribute has already been handled, it does not need to be
146 // handled again.
Aaron Ballmanab7691c2014-01-09 22:48:32 +0000147 if (Seen.find(AN) != Seen.end()) {
148 if (Dupes)
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +0000149 Dupes->push_back(std::make_pair(AN, Attr));
Aaron Ballman64e69862013-12-15 13:05:48 +0000150 continue;
Aaron Ballmanab7691c2014-01-09 22:48:32 +0000151 }
Aaron Ballman64e69862013-12-15 13:05:48 +0000152 Seen.insert(AN);
153 } else
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +0000154 AN = NormalizeAttrName(Attr->getName()).str();
Aaron Ballman64e69862013-12-15 13:05:48 +0000155
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +0000156 R.push_back(std::make_pair(AN, Attr));
Aaron Ballman64e69862013-12-15 13:05:48 +0000157 }
158 }
159 return R;
160}
161
Peter Collingbournebee583f2011-10-06 13:03:08 +0000162namespace {
163 class Argument {
164 std::string lowerName, upperName;
165 StringRef attrName;
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000166 bool isOpt;
Peter Collingbournebee583f2011-10-06 13:03:08 +0000167
168 public:
169 Argument(Record &Arg, StringRef Attr)
170 : lowerName(Arg.getValueAsString("Name")), upperName(lowerName),
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000171 attrName(Attr), isOpt(false) {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000172 if (!lowerName.empty()) {
173 lowerName[0] = std::tolower(lowerName[0]);
174 upperName[0] = std::toupper(upperName[0]);
175 }
176 }
177 virtual ~Argument() {}
178
179 StringRef getLowerName() const { return lowerName; }
180 StringRef getUpperName() const { return upperName; }
181 StringRef getAttrName() const { return attrName; }
182
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000183 bool isOptional() const { return isOpt; }
184 void setOptional(bool set) { isOpt = set; }
185
Peter Collingbournebee583f2011-10-06 13:03:08 +0000186 // These functions print the argument contents formatted in different ways.
187 virtual void writeAccessors(raw_ostream &OS) const = 0;
188 virtual void writeAccessorDefinitions(raw_ostream &OS) const {}
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +0000189 virtual void writeASTVisitorTraversal(raw_ostream &OS) const {}
Peter Collingbournebee583f2011-10-06 13:03:08 +0000190 virtual void writeCloneArgs(raw_ostream &OS) const = 0;
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000191 virtual void writeTemplateInstantiationArgs(raw_ostream &OS) const = 0;
Daniel Dunbardc51baa2012-02-10 06:00:29 +0000192 virtual void writeTemplateInstantiation(raw_ostream &OS) const {}
Peter Collingbournebee583f2011-10-06 13:03:08 +0000193 virtual void writeCtorBody(raw_ostream &OS) const {}
194 virtual void writeCtorInitializers(raw_ostream &OS) const = 0;
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000195 virtual void writeCtorDefaultInitializers(raw_ostream &OS) const = 0;
Peter Collingbournebee583f2011-10-06 13:03:08 +0000196 virtual void writeCtorParameters(raw_ostream &OS) const = 0;
197 virtual void writeDeclarations(raw_ostream &OS) const = 0;
198 virtual void writePCHReadArgs(raw_ostream &OS) const = 0;
199 virtual void writePCHReadDecls(raw_ostream &OS) const = 0;
200 virtual void writePCHWrite(raw_ostream &OS) const = 0;
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000201 virtual void writeValue(raw_ostream &OS) const = 0;
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000202 virtual void writeDump(raw_ostream &OS) const = 0;
203 virtual void writeDumpChildren(raw_ostream &OS) const {}
Richard Trieude5cc7d2013-01-31 01:44:26 +0000204 virtual void writeHasChildren(raw_ostream &OS) const { OS << "false"; }
Aaron Ballman682ee422013-09-11 19:47:58 +0000205
206 virtual bool isEnumArg() const { return false; }
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000207 virtual bool isVariadicEnumArg() const { return false; }
Aaron Ballman36a53502014-01-16 13:03:14 +0000208
209 virtual void writeImplicitCtorArgs(raw_ostream &OS) const {
210 OS << getUpperName();
211 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000212 };
213
214 class SimpleArgument : public Argument {
215 std::string type;
216
217 public:
218 SimpleArgument(Record &Arg, StringRef Attr, std::string T)
219 : Argument(Arg, Attr), type(T)
220 {}
221
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000222 std::string getType() const { return type; }
223
Peter Collingbournebee583f2011-10-06 13:03:08 +0000224 void writeAccessors(raw_ostream &OS) const {
225 OS << " " << type << " get" << getUpperName() << "() const {\n";
226 OS << " return " << getLowerName() << ";\n";
227 OS << " }";
228 }
229 void writeCloneArgs(raw_ostream &OS) const {
230 OS << getLowerName();
231 }
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000232 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
233 OS << "A->get" << getUpperName() << "()";
234 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000235 void writeCtorInitializers(raw_ostream &OS) const {
236 OS << getLowerName() << "(" << getUpperName() << ")";
237 }
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000238 void writeCtorDefaultInitializers(raw_ostream &OS) const {
239 OS << getLowerName() << "()";
240 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000241 void writeCtorParameters(raw_ostream &OS) const {
242 OS << type << " " << getUpperName();
243 }
244 void writeDeclarations(raw_ostream &OS) const {
245 OS << type << " " << getLowerName() << ";";
246 }
247 void writePCHReadDecls(raw_ostream &OS) const {
248 std::string read = ReadPCHRecord(type);
249 OS << " " << type << " " << getLowerName() << " = " << read << ";\n";
250 }
251 void writePCHReadArgs(raw_ostream &OS) const {
252 OS << getLowerName();
253 }
254 void writePCHWrite(raw_ostream &OS) const {
255 OS << " " << WritePCHRecord(type, "SA->get" +
256 std::string(getUpperName()) + "()");
257 }
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000258 void writeValue(raw_ostream &OS) const {
259 if (type == "FunctionDecl *") {
Richard Smithb87c4652013-10-31 21:23:20 +0000260 OS << "\" << get" << getUpperName()
261 << "()->getNameInfo().getAsString() << \"";
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000262 } else if (type == "IdentifierInfo *") {
263 OS << "\" << get" << getUpperName() << "()->getName() << \"";
Richard Smithb87c4652013-10-31 21:23:20 +0000264 } else if (type == "TypeSourceInfo *") {
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000265 OS << "\" << get" << getUpperName() << "().getAsString() << \"";
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000266 } else {
267 OS << "\" << get" << getUpperName() << "() << \"";
268 }
269 }
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000270 void writeDump(raw_ostream &OS) const {
271 if (type == "FunctionDecl *") {
272 OS << " OS << \" \";\n";
273 OS << " dumpBareDeclRef(SA->get" << getUpperName() << "());\n";
274 } else if (type == "IdentifierInfo *") {
275 OS << " OS << \" \" << SA->get" << getUpperName()
276 << "()->getName();\n";
Richard Smithb87c4652013-10-31 21:23:20 +0000277 } else if (type == "TypeSourceInfo *") {
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000278 OS << " OS << \" \" << SA->get" << getUpperName()
279 << "().getAsString();\n";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000280 } else if (type == "bool") {
281 OS << " if (SA->get" << getUpperName() << "()) OS << \" "
282 << getUpperName() << "\";\n";
283 } else if (type == "int" || type == "unsigned") {
284 OS << " OS << \" \" << SA->get" << getUpperName() << "();\n";
285 } else {
286 llvm_unreachable("Unknown SimpleArgument type!");
287 }
288 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000289 };
290
Aaron Ballman18a78382013-11-21 00:28:23 +0000291 class DefaultSimpleArgument : public SimpleArgument {
292 int64_t Default;
293
294 public:
295 DefaultSimpleArgument(Record &Arg, StringRef Attr,
296 std::string T, int64_t Default)
297 : SimpleArgument(Arg, Attr, T), Default(Default) {}
298
299 void writeAccessors(raw_ostream &OS) const {
300 SimpleArgument::writeAccessors(OS);
301
302 OS << "\n\n static const " << getType() << " Default" << getUpperName()
303 << " = " << Default << ";";
304 }
305 };
306
Peter Collingbournebee583f2011-10-06 13:03:08 +0000307 class StringArgument : public Argument {
308 public:
309 StringArgument(Record &Arg, StringRef Attr)
310 : Argument(Arg, Attr)
311 {}
312
313 void writeAccessors(raw_ostream &OS) const {
314 OS << " llvm::StringRef get" << getUpperName() << "() const {\n";
315 OS << " return llvm::StringRef(" << getLowerName() << ", "
316 << getLowerName() << "Length);\n";
317 OS << " }\n";
318 OS << " unsigned get" << getUpperName() << "Length() const {\n";
319 OS << " return " << getLowerName() << "Length;\n";
320 OS << " }\n";
321 OS << " void set" << getUpperName()
322 << "(ASTContext &C, llvm::StringRef S) {\n";
323 OS << " " << getLowerName() << "Length = S.size();\n";
324 OS << " this->" << getLowerName() << " = new (C, 1) char ["
325 << getLowerName() << "Length];\n";
326 OS << " std::memcpy(this->" << getLowerName() << ", S.data(), "
327 << getLowerName() << "Length);\n";
328 OS << " }";
329 }
330 void writeCloneArgs(raw_ostream &OS) const {
331 OS << "get" << getUpperName() << "()";
332 }
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000333 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
334 OS << "A->get" << getUpperName() << "()";
335 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000336 void writeCtorBody(raw_ostream &OS) const {
337 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
338 << ".data(), " << getLowerName() << "Length);";
339 }
340 void writeCtorInitializers(raw_ostream &OS) const {
341 OS << getLowerName() << "Length(" << getUpperName() << ".size()),"
342 << getLowerName() << "(new (Ctx, 1) char[" << getLowerName()
343 << "Length])";
344 }
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000345 void writeCtorDefaultInitializers(raw_ostream &OS) const {
346 OS << getLowerName() << "Length(0)," << getLowerName() << "(0)";
347 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000348 void writeCtorParameters(raw_ostream &OS) const {
349 OS << "llvm::StringRef " << getUpperName();
350 }
351 void writeDeclarations(raw_ostream &OS) const {
352 OS << "unsigned " << getLowerName() << "Length;\n";
353 OS << "char *" << getLowerName() << ";";
354 }
355 void writePCHReadDecls(raw_ostream &OS) const {
356 OS << " std::string " << getLowerName()
357 << "= ReadString(Record, Idx);\n";
358 }
359 void writePCHReadArgs(raw_ostream &OS) const {
360 OS << getLowerName();
361 }
362 void writePCHWrite(raw_ostream &OS) const {
363 OS << " AddString(SA->get" << getUpperName() << "(), Record);\n";
364 }
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000365 void writeValue(raw_ostream &OS) const {
366 OS << "\\\"\" << get" << getUpperName() << "() << \"\\\"";
367 }
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000368 void writeDump(raw_ostream &OS) const {
369 OS << " OS << \" \\\"\" << SA->get" << getUpperName()
370 << "() << \"\\\"\";\n";
371 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000372 };
373
374 class AlignedArgument : public Argument {
375 public:
376 AlignedArgument(Record &Arg, StringRef Attr)
377 : Argument(Arg, Attr)
378 {}
379
380 void writeAccessors(raw_ostream &OS) const {
381 OS << " bool is" << getUpperName() << "Dependent() const;\n";
382
383 OS << " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n";
384
385 OS << " bool is" << getUpperName() << "Expr() const {\n";
386 OS << " return is" << getLowerName() << "Expr;\n";
387 OS << " }\n";
388
389 OS << " Expr *get" << getUpperName() << "Expr() const {\n";
390 OS << " assert(is" << getLowerName() << "Expr);\n";
391 OS << " return " << getLowerName() << "Expr;\n";
392 OS << " }\n";
393
394 OS << " TypeSourceInfo *get" << getUpperName() << "Type() const {\n";
395 OS << " assert(!is" << getLowerName() << "Expr);\n";
396 OS << " return " << getLowerName() << "Type;\n";
397 OS << " }";
398 }
399 void writeAccessorDefinitions(raw_ostream &OS) const {
400 OS << "bool " << getAttrName() << "Attr::is" << getUpperName()
401 << "Dependent() const {\n";
402 OS << " if (is" << getLowerName() << "Expr)\n";
403 OS << " return " << getLowerName() << "Expr && (" << getLowerName()
404 << "Expr->isValueDependent() || " << getLowerName()
405 << "Expr->isTypeDependent());\n";
406 OS << " else\n";
407 OS << " return " << getLowerName()
408 << "Type->getType()->isDependentType();\n";
409 OS << "}\n";
410
411 // FIXME: Do not do the calculation here
412 // FIXME: Handle types correctly
413 // A null pointer means maximum alignment
414 // FIXME: Load the platform-specific maximum alignment, rather than
415 // 16, the x86 max.
416 OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName()
417 << "(ASTContext &Ctx) const {\n";
418 OS << " assert(!is" << getUpperName() << "Dependent());\n";
419 OS << " if (is" << getLowerName() << "Expr)\n";
420 OS << " return (" << getLowerName() << "Expr ? " << getLowerName()
Richard Smithcaf33902011-10-10 18:28:20 +0000421 << "Expr->EvaluateKnownConstInt(Ctx).getZExtValue() : 16)"
Peter Collingbournebee583f2011-10-06 13:03:08 +0000422 << "* Ctx.getCharWidth();\n";
423 OS << " else\n";
424 OS << " return 0; // FIXME\n";
425 OS << "}\n";
426 }
427 void writeCloneArgs(raw_ostream &OS) const {
428 OS << "is" << getLowerName() << "Expr, is" << getLowerName()
429 << "Expr ? static_cast<void*>(" << getLowerName()
430 << "Expr) : " << getLowerName()
431 << "Type";
432 }
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000433 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
434 // FIXME: move the definition in Sema::InstantiateAttrs to here.
435 // In the meantime, aligned attributes are cloned.
436 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000437 void writeCtorBody(raw_ostream &OS) const {
438 OS << " if (is" << getLowerName() << "Expr)\n";
439 OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>("
440 << getUpperName() << ");\n";
441 OS << " else\n";
442 OS << " " << getLowerName()
443 << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName()
444 << ");";
445 }
446 void writeCtorInitializers(raw_ostream &OS) const {
447 OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)";
448 }
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000449 void writeCtorDefaultInitializers(raw_ostream &OS) const {
450 OS << "is" << getLowerName() << "Expr(false)";
451 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000452 void writeCtorParameters(raw_ostream &OS) const {
453 OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName();
454 }
Aaron Ballman36a53502014-01-16 13:03:14 +0000455 void writeImplicitCtorArgs(raw_ostream &OS) const {
456 OS << "Is" << getUpperName() << "Expr, " << getUpperName();
457 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000458 void writeDeclarations(raw_ostream &OS) const {
459 OS << "bool is" << getLowerName() << "Expr;\n";
460 OS << "union {\n";
461 OS << "Expr *" << getLowerName() << "Expr;\n";
462 OS << "TypeSourceInfo *" << getLowerName() << "Type;\n";
463 OS << "};";
464 }
465 void writePCHReadArgs(raw_ostream &OS) const {
466 OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr";
467 }
468 void writePCHReadDecls(raw_ostream &OS) const {
469 OS << " bool is" << getLowerName() << "Expr = Record[Idx++];\n";
470 OS << " void *" << getLowerName() << "Ptr;\n";
471 OS << " if (is" << getLowerName() << "Expr)\n";
472 OS << " " << getLowerName() << "Ptr = ReadExpr(F);\n";
473 OS << " else\n";
474 OS << " " << getLowerName()
475 << "Ptr = GetTypeSourceInfo(F, Record, Idx);\n";
476 }
477 void writePCHWrite(raw_ostream &OS) const {
478 OS << " Record.push_back(SA->is" << getUpperName() << "Expr());\n";
479 OS << " if (SA->is" << getUpperName() << "Expr())\n";
480 OS << " AddStmt(SA->get" << getUpperName() << "Expr());\n";
481 OS << " else\n";
482 OS << " AddTypeSourceInfo(SA->get" << getUpperName()
483 << "Type(), Record);\n";
484 }
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000485 void writeValue(raw_ostream &OS) const {
Richard Smith52f04a22012-08-16 02:43:29 +0000486 OS << "\";\n"
487 << " " << getLowerName() << "Expr->printPretty(OS, 0, Policy);\n"
488 << " OS << \"";
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000489 }
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000490 void writeDump(raw_ostream &OS) const {
491 }
492 void writeDumpChildren(raw_ostream &OS) const {
Richard Trieude5cc7d2013-01-31 01:44:26 +0000493 OS << " if (SA->is" << getUpperName() << "Expr()) {\n";
494 OS << " lastChild();\n";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000495 OS << " dumpStmt(SA->get" << getUpperName() << "Expr());\n";
Richard Trieude5cc7d2013-01-31 01:44:26 +0000496 OS << " } else\n";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000497 OS << " dumpType(SA->get" << getUpperName()
498 << "Type()->getType());\n";
499 }
Richard Trieude5cc7d2013-01-31 01:44:26 +0000500 void writeHasChildren(raw_ostream &OS) const {
501 OS << "SA->is" << getUpperName() << "Expr()";
502 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000503 };
504
505 class VariadicArgument : public Argument {
506 std::string type;
507
508 public:
509 VariadicArgument(Record &Arg, StringRef Attr, std::string T)
510 : Argument(Arg, Attr), type(T)
511 {}
512
513 std::string getType() const { return type; }
514
515 void writeAccessors(raw_ostream &OS) const {
516 OS << " typedef " << type << "* " << getLowerName() << "_iterator;\n";
517 OS << " " << getLowerName() << "_iterator " << getLowerName()
518 << "_begin() const {\n";
519 OS << " return " << getLowerName() << ";\n";
520 OS << " }\n";
521 OS << " " << getLowerName() << "_iterator " << getLowerName()
522 << "_end() const {\n";
523 OS << " return " << getLowerName() << " + " << getLowerName()
524 << "Size;\n";
525 OS << " }\n";
526 OS << " unsigned " << getLowerName() << "_size() const {\n"
DeLesley Hutchins30398dd2012-01-20 22:50:54 +0000527 << " return " << getLowerName() << "Size;\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +0000528 OS << " }";
529 }
530 void writeCloneArgs(raw_ostream &OS) const {
531 OS << getLowerName() << ", " << getLowerName() << "Size";
532 }
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000533 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
534 // This isn't elegant, but we have to go through public methods...
535 OS << "A->" << getLowerName() << "_begin(), "
536 << "A->" << getLowerName() << "_size()";
537 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000538 void writeCtorBody(raw_ostream &OS) const {
539 // FIXME: memcpy is not safe on non-trivial types.
540 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
541 << ", " << getLowerName() << "Size * sizeof(" << getType() << "));\n";
542 }
543 void writeCtorInitializers(raw_ostream &OS) const {
544 OS << getLowerName() << "Size(" << getUpperName() << "Size), "
545 << getLowerName() << "(new (Ctx, 16) " << getType() << "["
546 << getLowerName() << "Size])";
547 }
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000548 void writeCtorDefaultInitializers(raw_ostream &OS) const {
549 OS << getLowerName() << "Size(0), " << getLowerName() << "(0)";
550 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000551 void writeCtorParameters(raw_ostream &OS) const {
552 OS << getType() << " *" << getUpperName() << ", unsigned "
553 << getUpperName() << "Size";
554 }
Aaron Ballman36a53502014-01-16 13:03:14 +0000555 void writeImplicitCtorArgs(raw_ostream &OS) const {
556 OS << getUpperName() << ", " << getUpperName() << "Size";
557 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000558 void writeDeclarations(raw_ostream &OS) const {
559 OS << " unsigned " << getLowerName() << "Size;\n";
560 OS << " " << getType() << " *" << getLowerName() << ";";
561 }
562 void writePCHReadDecls(raw_ostream &OS) const {
563 OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000564 OS << " SmallVector<" << type << ", 4> " << getLowerName()
Peter Collingbournebee583f2011-10-06 13:03:08 +0000565 << ";\n";
566 OS << " " << getLowerName() << ".reserve(" << getLowerName()
567 << "Size);\n";
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000568 OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +0000569
570 std::string read = ReadPCHRecord(type);
571 OS << " " << getLowerName() << ".push_back(" << read << ");\n";
572 }
573 void writePCHReadArgs(raw_ostream &OS) const {
574 OS << getLowerName() << ".data(), " << getLowerName() << "Size";
575 }
576 void writePCHWrite(raw_ostream &OS) const{
577 OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";
578 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
579 << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
580 << getLowerName() << "_end(); i != e; ++i)\n";
581 OS << " " << WritePCHRecord(type, "(*i)");
582 }
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000583 void writeValue(raw_ostream &OS) const {
584 OS << "\";\n";
585 OS << " bool isFirst = true;\n"
586 << " for (" << getAttrName() << "Attr::" << getLowerName()
587 << "_iterator i = " << getLowerName() << "_begin(), e = "
588 << getLowerName() << "_end(); i != e; ++i) {\n"
589 << " if (isFirst) isFirst = false;\n"
590 << " else OS << \", \";\n"
591 << " OS << *i;\n"
592 << " }\n";
593 OS << " OS << \"";
594 }
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000595 void writeDump(raw_ostream &OS) const {
596 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
597 << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
598 << getLowerName() << "_end(); I != E; ++I)\n";
599 OS << " OS << \" \" << *I;\n";
600 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000601 };
602
Reid Klecknerf526b9482014-02-12 18:22:18 +0000603 // Unique the enums, but maintain the original declaration ordering.
Reid Klecknerf06b2662014-02-12 19:26:24 +0000604 std::vector<std::string>
605 uniqueEnumsInOrder(const std::vector<std::string> &enums) {
Reid Klecknerf526b9482014-02-12 18:22:18 +0000606 std::vector<std::string> uniques;
607 std::set<std::string> unique_set(enums.begin(), enums.end());
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +0000608 for (const auto &i : enums) {
609 std::set<std::string>::iterator set_i = unique_set.find(i);
Reid Klecknerf526b9482014-02-12 18:22:18 +0000610 if (set_i != unique_set.end()) {
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +0000611 uniques.push_back(i);
Reid Klecknerf526b9482014-02-12 18:22:18 +0000612 unique_set.erase(set_i);
613 }
614 }
615 return uniques;
616 }
617
Peter Collingbournebee583f2011-10-06 13:03:08 +0000618 class EnumArgument : public Argument {
619 std::string type;
Aaron Ballman0e468c02014-01-05 21:08:29 +0000620 std::vector<std::string> values, enums, uniques;
Peter Collingbournebee583f2011-10-06 13:03:08 +0000621 public:
622 EnumArgument(Record &Arg, StringRef Attr)
623 : Argument(Arg, Attr), type(Arg.getValueAsString("Type")),
Aaron Ballman0e468c02014-01-05 21:08:29 +0000624 values(Arg.getValueAsListOfStrings("Values")),
625 enums(Arg.getValueAsListOfStrings("Enums")),
Reid Klecknerf526b9482014-02-12 18:22:18 +0000626 uniques(uniqueEnumsInOrder(enums))
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000627 {
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000628 // FIXME: Emit a proper error
629 assert(!uniques.empty());
630 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000631
Aaron Ballman682ee422013-09-11 19:47:58 +0000632 bool isEnumArg() const { return true; }
633
Peter Collingbournebee583f2011-10-06 13:03:08 +0000634 void writeAccessors(raw_ostream &OS) const {
635 OS << " " << type << " get" << getUpperName() << "() const {\n";
636 OS << " return " << getLowerName() << ";\n";
637 OS << " }";
638 }
639 void writeCloneArgs(raw_ostream &OS) const {
640 OS << getLowerName();
641 }
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000642 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
643 OS << "A->get" << getUpperName() << "()";
644 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000645 void writeCtorInitializers(raw_ostream &OS) const {
646 OS << getLowerName() << "(" << getUpperName() << ")";
647 }
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000648 void writeCtorDefaultInitializers(raw_ostream &OS) const {
649 OS << getLowerName() << "(" << type << "(0))";
650 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000651 void writeCtorParameters(raw_ostream &OS) const {
652 OS << type << " " << getUpperName();
653 }
654 void writeDeclarations(raw_ostream &OS) const {
Aaron Ballman0e468c02014-01-05 21:08:29 +0000655 std::vector<std::string>::const_iterator i = uniques.begin(),
656 e = uniques.end();
Peter Collingbournebee583f2011-10-06 13:03:08 +0000657 // The last one needs to not have a comma.
658 --e;
659
660 OS << "public:\n";
661 OS << " enum " << type << " {\n";
662 for (; i != e; ++i)
663 OS << " " << *i << ",\n";
664 OS << " " << *e << "\n";
665 OS << " };\n";
666 OS << "private:\n";
667 OS << " " << type << " " << getLowerName() << ";";
668 }
669 void writePCHReadDecls(raw_ostream &OS) const {
670 OS << " " << getAttrName() << "Attr::" << type << " " << getLowerName()
671 << "(static_cast<" << getAttrName() << "Attr::" << type
672 << ">(Record[Idx++]));\n";
673 }
674 void writePCHReadArgs(raw_ostream &OS) const {
675 OS << getLowerName();
676 }
677 void writePCHWrite(raw_ostream &OS) const {
678 OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
679 }
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000680 void writeValue(raw_ostream &OS) const {
681 OS << "\" << get" << getUpperName() << "() << \"";
682 }
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000683 void writeDump(raw_ostream &OS) const {
684 OS << " switch(SA->get" << getUpperName() << "()) {\n";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +0000685 for (const auto &I : uniques) {
686 OS << " case " << getAttrName() << "Attr::" << I << ":\n";
687 OS << " OS << \" " << I << "\";\n";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000688 OS << " break;\n";
689 }
690 OS << " }\n";
691 }
Aaron Ballman682ee422013-09-11 19:47:58 +0000692
693 void writeConversion(raw_ostream &OS) const {
694 OS << " static bool ConvertStrTo" << type << "(StringRef Val, ";
695 OS << type << " &Out) {\n";
696 OS << " Optional<" << type << "> R = llvm::StringSwitch<Optional<";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +0000697 OS << type << ">>(Val)\n";
Aaron Ballman682ee422013-09-11 19:47:58 +0000698 for (size_t I = 0; I < enums.size(); ++I) {
699 OS << " .Case(\"" << values[I] << "\", ";
700 OS << getAttrName() << "Attr::" << enums[I] << ")\n";
701 }
702 OS << " .Default(Optional<" << type << ">());\n";
703 OS << " if (R) {\n";
704 OS << " Out = *R;\n return true;\n }\n";
705 OS << " return false;\n";
706 OS << " }\n";
707 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000708 };
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000709
710 class VariadicEnumArgument: public VariadicArgument {
711 std::string type, QualifiedTypeName;
Aaron Ballman0e468c02014-01-05 21:08:29 +0000712 std::vector<std::string> values, enums, uniques;
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000713 public:
714 VariadicEnumArgument(Record &Arg, StringRef Attr)
715 : VariadicArgument(Arg, Attr, Arg.getValueAsString("Type")),
716 type(Arg.getValueAsString("Type")),
Aaron Ballman0e468c02014-01-05 21:08:29 +0000717 values(Arg.getValueAsListOfStrings("Values")),
718 enums(Arg.getValueAsListOfStrings("Enums")),
Reid Klecknerf526b9482014-02-12 18:22:18 +0000719 uniques(uniqueEnumsInOrder(enums))
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000720 {
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000721 QualifiedTypeName = getAttrName().str() + "Attr::" + type;
722
723 // FIXME: Emit a proper error
724 assert(!uniques.empty());
725 }
726
727 bool isVariadicEnumArg() const { return true; }
728
729 void writeDeclarations(raw_ostream &OS) const {
Aaron Ballman0e468c02014-01-05 21:08:29 +0000730 std::vector<std::string>::const_iterator i = uniques.begin(),
731 e = uniques.end();
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000732 // The last one needs to not have a comma.
733 --e;
734
735 OS << "public:\n";
736 OS << " enum " << type << " {\n";
737 for (; i != e; ++i)
738 OS << " " << *i << ",\n";
739 OS << " " << *e << "\n";
740 OS << " };\n";
741 OS << "private:\n";
742
743 VariadicArgument::writeDeclarations(OS);
744 }
745 void writeDump(raw_ostream &OS) const {
746 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
747 << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
748 << getLowerName() << "_end(); I != E; ++I) {\n";
749 OS << " switch(*I) {\n";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +0000750 for (const auto &UI : uniques) {
751 OS << " case " << getAttrName() << "Attr::" << UI << ":\n";
752 OS << " OS << \" " << UI << "\";\n";
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000753 OS << " break;\n";
754 }
755 OS << " }\n";
756 OS << " }\n";
757 }
758 void writePCHReadDecls(raw_ostream &OS) const {
759 OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
760 OS << " SmallVector<" << QualifiedTypeName << ", 4> " << getLowerName()
761 << ";\n";
762 OS << " " << getLowerName() << ".reserve(" << getLowerName()
763 << "Size);\n";
764 OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
765 OS << " " << getLowerName() << ".push_back(" << "static_cast<"
766 << QualifiedTypeName << ">(Record[Idx++]));\n";
767 }
768 void writePCHWrite(raw_ostream &OS) const{
769 OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";
770 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
771 << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
772 << getLowerName() << "_end(); i != e; ++i)\n";
773 OS << " " << WritePCHRecord(QualifiedTypeName, "(*i)");
774 }
775 void writeConversion(raw_ostream &OS) const {
776 OS << " static bool ConvertStrTo" << type << "(StringRef Val, ";
777 OS << type << " &Out) {\n";
778 OS << " Optional<" << type << "> R = llvm::StringSwitch<Optional<";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +0000779 OS << type << ">>(Val)\n";
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000780 for (size_t I = 0; I < enums.size(); ++I) {
781 OS << " .Case(\"" << values[I] << "\", ";
782 OS << getAttrName() << "Attr::" << enums[I] << ")\n";
783 }
784 OS << " .Default(Optional<" << type << ">());\n";
785 OS << " if (R) {\n";
786 OS << " Out = *R;\n return true;\n }\n";
787 OS << " return false;\n";
788 OS << " }\n";
789 }
790 };
Peter Collingbournebee583f2011-10-06 13:03:08 +0000791
792 class VersionArgument : public Argument {
793 public:
794 VersionArgument(Record &Arg, StringRef Attr)
795 : Argument(Arg, Attr)
796 {}
797
798 void writeAccessors(raw_ostream &OS) const {
799 OS << " VersionTuple get" << getUpperName() << "() const {\n";
800 OS << " return " << getLowerName() << ";\n";
801 OS << " }\n";
802 OS << " void set" << getUpperName()
803 << "(ASTContext &C, VersionTuple V) {\n";
804 OS << " " << getLowerName() << " = V;\n";
805 OS << " }";
806 }
807 void writeCloneArgs(raw_ostream &OS) const {
808 OS << "get" << getUpperName() << "()";
809 }
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000810 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
811 OS << "A->get" << getUpperName() << "()";
812 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000813 void writeCtorBody(raw_ostream &OS) const {
814 }
815 void writeCtorInitializers(raw_ostream &OS) const {
816 OS << getLowerName() << "(" << getUpperName() << ")";
817 }
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000818 void writeCtorDefaultInitializers(raw_ostream &OS) const {
819 OS << getLowerName() << "()";
820 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000821 void writeCtorParameters(raw_ostream &OS) const {
822 OS << "VersionTuple " << getUpperName();
823 }
824 void writeDeclarations(raw_ostream &OS) const {
825 OS << "VersionTuple " << getLowerName() << ";\n";
826 }
827 void writePCHReadDecls(raw_ostream &OS) const {
828 OS << " VersionTuple " << getLowerName()
829 << "= ReadVersionTuple(Record, Idx);\n";
830 }
831 void writePCHReadArgs(raw_ostream &OS) const {
832 OS << getLowerName();
833 }
834 void writePCHWrite(raw_ostream &OS) const {
835 OS << " AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n";
836 }
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000837 void writeValue(raw_ostream &OS) const {
838 OS << getLowerName() << "=\" << get" << getUpperName() << "() << \"";
839 }
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000840 void writeDump(raw_ostream &OS) const {
841 OS << " OS << \" \" << SA->get" << getUpperName() << "();\n";
842 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000843 };
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000844
845 class ExprArgument : public SimpleArgument {
846 public:
847 ExprArgument(Record &Arg, StringRef Attr)
848 : SimpleArgument(Arg, Attr, "Expr *")
849 {}
850
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +0000851 virtual void writeASTVisitorTraversal(raw_ostream &OS) const {
852 OS << " if (!"
853 << "getDerived().TraverseStmt(A->get" << getUpperName() << "()))\n";
854 OS << " return false;\n";
855 }
856
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000857 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
858 OS << "tempInst" << getUpperName();
859 }
860
861 void writeTemplateInstantiation(raw_ostream &OS) const {
862 OS << " " << getType() << " tempInst" << getUpperName() << ";\n";
863 OS << " {\n";
864 OS << " EnterExpressionEvaluationContext "
865 << "Unevaluated(S, Sema::Unevaluated);\n";
866 OS << " ExprResult " << "Result = S.SubstExpr("
867 << "A->get" << getUpperName() << "(), TemplateArgs);\n";
868 OS << " tempInst" << getUpperName() << " = "
869 << "Result.takeAs<Expr>();\n";
870 OS << " }\n";
871 }
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000872
873 void writeDump(raw_ostream &OS) const {
874 }
875
876 void writeDumpChildren(raw_ostream &OS) const {
Richard Trieude5cc7d2013-01-31 01:44:26 +0000877 OS << " lastChild();\n";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000878 OS << " dumpStmt(SA->get" << getUpperName() << "());\n";
879 }
Richard Trieude5cc7d2013-01-31 01:44:26 +0000880 void writeHasChildren(raw_ostream &OS) const { OS << "true"; }
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000881 };
882
883 class VariadicExprArgument : public VariadicArgument {
884 public:
885 VariadicExprArgument(Record &Arg, StringRef Attr)
886 : VariadicArgument(Arg, Attr, "Expr *")
887 {}
888
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +0000889 virtual void writeASTVisitorTraversal(raw_ostream &OS) const {
890 OS << " {\n";
891 OS << " " << getType() << " *I = A->" << getLowerName()
892 << "_begin();\n";
893 OS << " " << getType() << " *E = A->" << getLowerName()
894 << "_end();\n";
895 OS << " for (; I != E; ++I) {\n";
896 OS << " if (!getDerived().TraverseStmt(*I))\n";
897 OS << " return false;\n";
898 OS << " }\n";
899 OS << " }\n";
900 }
901
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000902 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
903 OS << "tempInst" << getUpperName() << ", "
904 << "A->" << getLowerName() << "_size()";
905 }
906
907 void writeTemplateInstantiation(raw_ostream &OS) const {
908 OS << " " << getType() << " *tempInst" << getUpperName()
909 << " = new (C, 16) " << getType()
910 << "[A->" << getLowerName() << "_size()];\n";
911 OS << " {\n";
912 OS << " EnterExpressionEvaluationContext "
913 << "Unevaluated(S, Sema::Unevaluated);\n";
914 OS << " " << getType() << " *TI = tempInst" << getUpperName()
915 << ";\n";
916 OS << " " << getType() << " *I = A->" << getLowerName()
917 << "_begin();\n";
918 OS << " " << getType() << " *E = A->" << getLowerName()
919 << "_end();\n";
920 OS << " for (; I != E; ++I, ++TI) {\n";
921 OS << " ExprResult Result = S.SubstExpr(*I, TemplateArgs);\n";
922 OS << " *TI = Result.takeAs<Expr>();\n";
923 OS << " }\n";
924 OS << " }\n";
925 }
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000926
927 void writeDump(raw_ostream &OS) const {
928 }
929
930 void writeDumpChildren(raw_ostream &OS) const {
931 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
932 << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
Richard Trieude5cc7d2013-01-31 01:44:26 +0000933 << getLowerName() << "_end(); I != E; ++I) {\n";
934 OS << " if (I + 1 == E)\n";
935 OS << " lastChild();\n";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000936 OS << " dumpStmt(*I);\n";
Richard Trieude5cc7d2013-01-31 01:44:26 +0000937 OS << " }\n";
938 }
939
940 void writeHasChildren(raw_ostream &OS) const {
941 OS << "SA->" << getLowerName() << "_begin() != "
942 << "SA->" << getLowerName() << "_end()";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000943 }
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000944 };
Richard Smithb87c4652013-10-31 21:23:20 +0000945
946 class TypeArgument : public SimpleArgument {
947 public:
948 TypeArgument(Record &Arg, StringRef Attr)
949 : SimpleArgument(Arg, Attr, "TypeSourceInfo *")
950 {}
951
952 void writeAccessors(raw_ostream &OS) const {
953 OS << " QualType get" << getUpperName() << "() const {\n";
954 OS << " return " << getLowerName() << "->getType();\n";
955 OS << " }";
956 OS << " " << getType() << " get" << getUpperName() << "Loc() const {\n";
957 OS << " return " << getLowerName() << ";\n";
958 OS << " }";
959 }
960 void writeTemplateInstantiationArgs(raw_ostream &OS) const {
961 OS << "A->get" << getUpperName() << "Loc()";
962 }
963 void writePCHWrite(raw_ostream &OS) const {
964 OS << " " << WritePCHRecord(
965 getType(), "SA->get" + std::string(getUpperName()) + "Loc()");
966 }
967 };
Peter Collingbournebee583f2011-10-06 13:03:08 +0000968}
969
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000970static Argument *createArgument(Record &Arg, StringRef Attr,
971 Record *Search = 0) {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000972 if (!Search)
973 Search = &Arg;
974
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000975 Argument *Ptr = 0;
Peter Collingbournebee583f2011-10-06 13:03:08 +0000976 llvm::StringRef ArgName = Search->getName();
977
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000978 if (ArgName == "AlignedArgument") Ptr = new AlignedArgument(Arg, Attr);
979 else if (ArgName == "EnumArgument") Ptr = new EnumArgument(Arg, Attr);
980 else if (ArgName == "ExprArgument") Ptr = new ExprArgument(Arg, Attr);
Peter Collingbournebee583f2011-10-06 13:03:08 +0000981 else if (ArgName == "FunctionArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000982 Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *");
Peter Collingbournebee583f2011-10-06 13:03:08 +0000983 else if (ArgName == "IdentifierArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000984 Ptr = new SimpleArgument(Arg, Attr, "IdentifierInfo *");
David Majnemer4bb09802014-02-10 19:50:15 +0000985 else if (ArgName == "DefaultBoolArgument")
986 Ptr = new DefaultSimpleArgument(Arg, Attr, "bool",
987 Arg.getValueAsBit("Default"));
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000988 else if (ArgName == "BoolArgument") Ptr = new SimpleArgument(Arg, Attr,
989 "bool");
Aaron Ballman18a78382013-11-21 00:28:23 +0000990 else if (ArgName == "DefaultIntArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000991 Ptr = new DefaultSimpleArgument(Arg, Attr, "int",
992 Arg.getValueAsInt("Default"));
993 else if (ArgName == "IntArgument") Ptr = new SimpleArgument(Arg, Attr, "int");
994 else if (ArgName == "StringArgument") Ptr = new StringArgument(Arg, Attr);
995 else if (ArgName == "TypeArgument") Ptr = new TypeArgument(Arg, Attr);
Peter Collingbournebee583f2011-10-06 13:03:08 +0000996 else if (ArgName == "UnsignedArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000997 Ptr = new SimpleArgument(Arg, Attr, "unsigned");
Peter Collingbournebee583f2011-10-06 13:03:08 +0000998 else if (ArgName == "VariadicUnsignedArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000999 Ptr = new VariadicArgument(Arg, Attr, "unsigned");
DeLesley Hutchins210791a2013-10-04 21:28:06 +00001000 else if (ArgName == "VariadicEnumArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +00001001 Ptr = new VariadicEnumArgument(Arg, Attr);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001002 else if (ArgName == "VariadicExprArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +00001003 Ptr = new VariadicExprArgument(Arg, Attr);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001004 else if (ArgName == "VersionArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +00001005 Ptr = new VersionArgument(Arg, Attr);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001006
1007 if (!Ptr) {
Aaron Ballman18a78382013-11-21 00:28:23 +00001008 // Search in reverse order so that the most-derived type is handled first.
Peter Collingbournebee583f2011-10-06 13:03:08 +00001009 std::vector<Record*> Bases = Search->getSuperClasses();
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001010 for (auto i = Bases.rbegin(), e = Bases.rend(); i != e; ++i) {
Peter Collingbournebee583f2011-10-06 13:03:08 +00001011 Ptr = createArgument(Arg, Attr, *i);
1012 if (Ptr)
1013 break;
1014 }
1015 }
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001016
1017 if (Ptr && Arg.getValueAsBit("Optional"))
1018 Ptr->setOptional(true);
1019
Peter Collingbournebee583f2011-10-06 13:03:08 +00001020 return Ptr;
1021}
1022
Douglas Gregor49ccfaa2011-11-19 19:22:57 +00001023static void writeAvailabilityValue(raw_ostream &OS) {
1024 OS << "\" << getPlatform()->getName();\n"
1025 << " if (!getIntroduced().empty()) OS << \", introduced=\" << getIntroduced();\n"
1026 << " if (!getDeprecated().empty()) OS << \", deprecated=\" << getDeprecated();\n"
1027 << " if (!getObsoleted().empty()) OS << \", obsoleted=\" << getObsoleted();\n"
1028 << " if (getUnavailable()) OS << \", unavailable\";\n"
1029 << " OS << \"";
1030}
1031
Aaron Ballman3e424b52013-12-26 18:30:57 +00001032static void writeGetSpellingFunction(Record &R, raw_ostream &OS) {
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001033 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
Aaron Ballman3e424b52013-12-26 18:30:57 +00001034
1035 OS << "const char *" << R.getName() << "Attr::getSpelling() const {\n";
1036 if (Spellings.empty()) {
1037 OS << " return \"(No spelling)\";\n}\n\n";
1038 return;
1039 }
1040
1041 OS << " switch (SpellingListIndex) {\n"
1042 " default:\n"
1043 " llvm_unreachable(\"Unknown attribute spelling!\");\n"
1044 " return \"(No spelling)\";\n";
1045
1046 for (unsigned I = 0; I < Spellings.size(); ++I)
1047 OS << " case " << I << ":\n"
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001048 " return \"" << Spellings[I].name() << "\";\n";
Aaron Ballman3e424b52013-12-26 18:30:57 +00001049 // End of the switch statement.
1050 OS << " }\n";
1051 // End of the getSpelling function.
1052 OS << "}\n\n";
1053}
1054
Michael Han99315932013-01-24 16:46:58 +00001055static void writePrettyPrintFunction(Record &R, std::vector<Argument*> &Args,
1056 raw_ostream &OS) {
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001057 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
Michael Han99315932013-01-24 16:46:58 +00001058
1059 OS << "void " << R.getName() << "Attr::printPretty("
1060 << "raw_ostream &OS, const PrintingPolicy &Policy) const {\n";
1061
1062 if (Spellings.size() == 0) {
1063 OS << "}\n\n";
1064 return;
1065 }
1066
1067 OS <<
1068 " switch (SpellingListIndex) {\n"
1069 " default:\n"
1070 " llvm_unreachable(\"Unknown attribute spelling!\");\n"
1071 " break;\n";
1072
1073 for (unsigned I = 0; I < Spellings.size(); ++ I) {
1074 llvm::SmallString<16> Prefix;
1075 llvm::SmallString<8> Suffix;
1076 // The actual spelling of the name and namespace (if applicable)
1077 // of an attribute without considering prefix and suffix.
1078 llvm::SmallString<64> Spelling;
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001079 std::string Name = Spellings[I].name();
1080 std::string Variety = Spellings[I].variety();
Michael Han99315932013-01-24 16:46:58 +00001081
1082 if (Variety == "GNU") {
1083 Prefix = " __attribute__((";
1084 Suffix = "))";
1085 } else if (Variety == "CXX11") {
1086 Prefix = " [[";
1087 Suffix = "]]";
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001088 std::string Namespace = Spellings[I].nameSpace();
Michael Han99315932013-01-24 16:46:58 +00001089 if (Namespace != "") {
1090 Spelling += Namespace;
1091 Spelling += "::";
1092 }
1093 } else if (Variety == "Declspec") {
1094 Prefix = " __declspec(";
1095 Suffix = ")";
Richard Smith0cdcc982013-01-29 01:24:26 +00001096 } else if (Variety == "Keyword") {
1097 Prefix = " ";
1098 Suffix = "";
Michael Han99315932013-01-24 16:46:58 +00001099 } else {
Richard Smith0cdcc982013-01-29 01:24:26 +00001100 llvm_unreachable("Unknown attribute syntax variety!");
Michael Han99315932013-01-24 16:46:58 +00001101 }
1102
1103 Spelling += Name;
1104
1105 OS <<
1106 " case " << I << " : {\n"
1107 " OS << \"" + Prefix.str() + Spelling.str();
1108
1109 if (Args.size()) OS << "(";
1110 if (Spelling == "availability") {
1111 writeAvailabilityValue(OS);
1112 } else {
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001113 for (auto I = Args.begin(), E = Args.end(); I != E; ++ I) {
Michael Han99315932013-01-24 16:46:58 +00001114 if (I != Args.begin()) OS << ", ";
1115 (*I)->writeValue(OS);
1116 }
1117 }
1118
1119 if (Args.size()) OS << ")";
1120 OS << Suffix.str() + "\";\n";
1121
1122 OS <<
1123 " break;\n"
1124 " }\n";
1125 }
1126
1127 // End of the switch statement.
1128 OS << "}\n";
1129 // End of the print function.
1130 OS << "}\n\n";
1131}
1132
Michael Hanaf02bbe2013-02-01 01:19:17 +00001133/// \brief Return the index of a spelling in a spelling list.
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001134static unsigned
1135getSpellingListIndex(const std::vector<FlattenedSpelling> &SpellingList,
1136 const FlattenedSpelling &Spelling) {
Michael Hanaf02bbe2013-02-01 01:19:17 +00001137 assert(SpellingList.size() && "Spelling list is empty!");
1138
1139 for (unsigned Index = 0; Index < SpellingList.size(); ++Index) {
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001140 const FlattenedSpelling &S = SpellingList[Index];
1141 if (S.variety() != Spelling.variety())
Michael Hanaf02bbe2013-02-01 01:19:17 +00001142 continue;
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001143 if (S.nameSpace() != Spelling.nameSpace())
Michael Hanaf02bbe2013-02-01 01:19:17 +00001144 continue;
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001145 if (S.name() != Spelling.name())
Michael Hanaf02bbe2013-02-01 01:19:17 +00001146 continue;
1147
1148 return Index;
1149 }
1150
1151 llvm_unreachable("Unknown spelling!");
1152}
1153
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001154static void writeAttrAccessorDefinition(const Record &R, raw_ostream &OS) {
Michael Hanaf02bbe2013-02-01 01:19:17 +00001155 std::vector<Record*> Accessors = R.getValueAsListOfDefs("Accessors");
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001156 for (auto Accessor : Accessors) {
Michael Hanaf02bbe2013-02-01 01:19:17 +00001157 std::string Name = Accessor->getValueAsString("Name");
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001158 std::vector<FlattenedSpelling> Spellings =
1159 GetFlattenedSpellings(*Accessor);
1160 std::vector<FlattenedSpelling> SpellingList = GetFlattenedSpellings(R);
Michael Hanaf02bbe2013-02-01 01:19:17 +00001161 assert(SpellingList.size() &&
1162 "Attribute with empty spelling list can't have accessors!");
1163
1164 OS << " bool " << Name << "() const { return SpellingListIndex == ";
1165 for (unsigned Index = 0; Index < Spellings.size(); ++Index) {
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001166 OS << getSpellingListIndex(SpellingList, Spellings[Index]);
Michael Hanaf02bbe2013-02-01 01:19:17 +00001167 if (Index != Spellings.size() -1)
1168 OS << " ||\n SpellingListIndex == ";
1169 else
1170 OS << "; }\n";
1171 }
1172 }
1173}
1174
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001175static bool
1176SpellingNamesAreCommon(const std::vector<FlattenedSpelling>& Spellings) {
Aaron Ballman36a53502014-01-16 13:03:14 +00001177 assert(!Spellings.empty() && "An empty list of spellings was provided");
1178 std::string FirstName = NormalizeNameForSpellingComparison(
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001179 Spellings.front().name());
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001180 for (auto I = std::next(Spellings.begin()), E = Spellings.end();
1181 I != E; ++I) {
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001182 std::string Name = NormalizeNameForSpellingComparison(I->name());
Aaron Ballman36a53502014-01-16 13:03:14 +00001183 if (Name != FirstName)
1184 return false;
1185 }
1186 return true;
1187}
1188
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001189typedef std::map<unsigned, std::string> SemanticSpellingMap;
1190static std::string
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001191CreateSemanticSpellings(const std::vector<FlattenedSpelling> &Spellings,
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001192 SemanticSpellingMap &Map) {
1193 // The enumerants are automatically generated based on the variety,
1194 // namespace (if present) and name for each attribute spelling. However,
1195 // care is taken to avoid trampling on the reserved namespace due to
1196 // underscores.
1197 std::string Ret(" enum Spelling {\n");
1198 std::set<std::string> Uniques;
1199 unsigned Idx = 0;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001200 for (auto I = Spellings.begin(), E = Spellings.end(); I != E; ++I, ++Idx) {
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001201 const FlattenedSpelling &S = *I;
1202 std::string Variety = S.variety();
1203 std::string Spelling = S.name();
1204 std::string Namespace = S.nameSpace();
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001205 std::string EnumName = "";
1206
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001207 EnumName += (Variety + "_");
1208 if (!Namespace.empty())
1209 EnumName += (NormalizeNameForSpellingComparison(Namespace).str() +
1210 "_");
1211 EnumName += NormalizeNameForSpellingComparison(Spelling);
1212
1213 // Even if the name is not unique, this spelling index corresponds to a
1214 // particular enumerant name that we've calculated.
1215 Map[Idx] = EnumName;
1216
1217 // Since we have been stripping underscores to avoid trampling on the
1218 // reserved namespace, we may have inadvertently created duplicate
1219 // enumerant names. These duplicates are not considered part of the
1220 // semantic spelling, and can be elided.
1221 if (Uniques.find(EnumName) != Uniques.end())
1222 continue;
1223
1224 Uniques.insert(EnumName);
1225 if (I != Spellings.begin())
1226 Ret += ",\n";
1227 Ret += " " + EnumName;
1228 }
1229 Ret += "\n };\n\n";
1230 return Ret;
1231}
1232
1233void WriteSemanticSpellingSwitch(const std::string &VarName,
1234 const SemanticSpellingMap &Map,
1235 raw_ostream &OS) {
1236 OS << " switch (" << VarName << ") {\n default: "
1237 << "llvm_unreachable(\"Unknown spelling list index\");\n";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001238 for (const auto &I : Map)
1239 OS << " case " << I.first << ": return " << I.second << ";\n";
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001240 OS << " }\n";
1241}
1242
Aaron Ballman35db2b32014-01-29 22:13:45 +00001243// Emits the LateParsed property for attributes.
1244static void emitClangAttrLateParsedList(RecordKeeper &Records, raw_ostream &OS) {
1245 OS << "#if defined(CLANG_ATTR_LATE_PARSED_LIST)\n";
1246 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1247
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001248 for (auto Attr : Attrs) {
1249 bool LateParsed = Attr->getValueAsBit("LateParsed");
Aaron Ballman35db2b32014-01-29 22:13:45 +00001250
1251 if (LateParsed) {
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001252 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr);
Aaron Ballman35db2b32014-01-29 22:13:45 +00001253
1254 // FIXME: Handle non-GNU attributes
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001255 for (const auto &I : Spellings) {
1256 if (I.variety() != "GNU")
Aaron Ballman35db2b32014-01-29 22:13:45 +00001257 continue;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001258 OS << ".Case(\"" << I.name() << "\", " << LateParsed << ")\n";
Aaron Ballman35db2b32014-01-29 22:13:45 +00001259 }
1260 }
1261 }
1262 OS << "#endif // CLANG_ATTR_LATE_PARSED_LIST\n\n";
1263}
1264
1265/// \brief Emits the first-argument-is-type property for attributes.
1266static void emitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) {
1267 OS << "#if defined(CLANG_ATTR_TYPE_ARG_LIST)\n";
1268 std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
1269
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001270 for (auto Attr : Attrs) {
Aaron Ballman35db2b32014-01-29 22:13:45 +00001271 // Determine whether the first argument is a type.
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001272 std::vector<Record *> Args = Attr->getValueAsListOfDefs("Args");
Aaron Ballman35db2b32014-01-29 22:13:45 +00001273 if (Args.empty())
1274 continue;
1275
1276 if (Args[0]->getSuperClasses().back()->getName() != "TypeArgument")
1277 continue;
1278
1279 // All these spellings take a single type argument.
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001280 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr);
Aaron Ballman35db2b32014-01-29 22:13:45 +00001281 std::set<std::string> Emitted;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001282 for (const auto &S : Spellings) {
1283 if (Emitted.insert(S.name()).second)
1284 OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n";
Aaron Ballman35db2b32014-01-29 22:13:45 +00001285 }
1286 }
1287 OS << "#endif // CLANG_ATTR_TYPE_ARG_LIST\n\n";
1288}
1289
1290/// \brief Emits the parse-arguments-in-unevaluated-context property for
1291/// attributes.
1292static void emitClangAttrArgContextList(RecordKeeper &Records, raw_ostream &OS) {
1293 OS << "#if defined(CLANG_ATTR_ARG_CONTEXT_LIST)\n";
1294 ParsedAttrMap Attrs = getParsedAttrList(Records);
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001295 for (const auto &I : Attrs) {
1296 const Record &Attr = *I.second;
Aaron Ballman35db2b32014-01-29 22:13:45 +00001297
1298 if (!Attr.getValueAsBit("ParseArgumentsAsUnevaluated"))
1299 continue;
1300
1301 // All these spellings take are parsed unevaluated.
1302 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
1303 std::set<std::string> Emitted;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001304 for (const auto &S : Spellings) {
1305 if (Emitted.insert(S.name()).second)
1306 OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n";
Aaron Ballman35db2b32014-01-29 22:13:45 +00001307 }
1308 }
1309 OS << "#endif // CLANG_ATTR_ARG_CONTEXT_LIST\n\n";
1310}
1311
1312static bool isIdentifierArgument(Record *Arg) {
1313 return !Arg->getSuperClasses().empty() &&
1314 llvm::StringSwitch<bool>(Arg->getSuperClasses().back()->getName())
1315 .Case("IdentifierArgument", true)
1316 .Case("EnumArgument", true)
1317 .Default(false);
1318}
1319
1320// Emits the first-argument-is-identifier property for attributes.
1321static void emitClangAttrIdentifierArgList(RecordKeeper &Records, raw_ostream &OS) {
1322 OS << "#if defined(CLANG_ATTR_IDENTIFIER_ARG_LIST)\n";
1323 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1324
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001325 for (auto Attr : Attrs) {
Aaron Ballman35db2b32014-01-29 22:13:45 +00001326 // Determine whether the first argument is an identifier.
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001327 std::vector<Record *> Args = Attr->getValueAsListOfDefs("Args");
Aaron Ballman35db2b32014-01-29 22:13:45 +00001328 if (Args.empty() || !isIdentifierArgument(Args[0]))
1329 continue;
1330
1331 // All these spellings take an identifier argument.
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001332 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr);
Aaron Ballman35db2b32014-01-29 22:13:45 +00001333 std::set<std::string> Emitted;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001334 for (const auto &S : Spellings) {
1335 if (Emitted.insert(S.name()).second)
1336 OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n";
Aaron Ballman35db2b32014-01-29 22:13:45 +00001337 }
1338 }
1339 OS << "#endif // CLANG_ATTR_IDENTIFIER_ARG_LIST\n\n";
1340}
1341
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001342namespace clang {
1343
1344// Emits the class definitions for attributes.
1345void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00001346 emitSourceFileHeader("Attribute classes' definitions", OS);
1347
Peter Collingbournebee583f2011-10-06 13:03:08 +00001348 OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
1349 OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
1350
1351 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1352
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001353 for (auto i : Attrs) {
1354 const Record &R = *i;
Aaron Ballman06bd44b2014-02-17 18:23:02 +00001355
1356 // FIXME: Currently, documentation is generated as-needed due to the fact
1357 // that there is no way to allow a generated project "reach into" the docs
1358 // directory (for instance, it may be an out-of-tree build). However, we want
1359 // to ensure that every attribute has a Documentation field, and produce an
1360 // error if it has been neglected. Otherwise, the on-demand generation which
1361 // happens server-side will fail. This code is ensuring that functionality,
1362 // even though this Emitter doesn't technically need the documentation.
1363 // When attribute documentation can be generated as part of the build
1364 // itself, this code can be removed.
1365 (void)R.getValueAsListOfDefs("Documentation");
Douglas Gregorb2daf842012-05-02 15:56:52 +00001366
1367 if (!R.getValueAsBit("ASTNode"))
1368 continue;
1369
Aaron Ballman0979e9e2013-07-30 01:44:15 +00001370 const std::vector<Record *> Supers = R.getSuperClasses();
1371 assert(!Supers.empty() && "Forgot to specify a superclass for the attr");
Aaron Ballman0979e9e2013-07-30 01:44:15 +00001372 std::string SuperName;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001373 for (auto I = Supers.rbegin(), E = Supers.rend(); I != E; ++I) {
Aaron Ballman0979e9e2013-07-30 01:44:15 +00001374 const Record &R = **I;
Aaron Ballman080cad72013-07-31 02:20:22 +00001375 if (R.getName() != "TargetSpecificAttr" && SuperName.empty())
Aaron Ballman0979e9e2013-07-30 01:44:15 +00001376 SuperName = R.getName();
1377 }
Peter Collingbournebee583f2011-10-06 13:03:08 +00001378
1379 OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n";
1380
1381 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
1382 std::vector<Argument*> Args;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001383 Args.reserve(ArgRecords.size());
1384
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001385 for (auto ArgRecord : ArgRecords) {
1386 Argument *Arg = createArgument(*ArgRecord, R.getName());
Peter Collingbournebee583f2011-10-06 13:03:08 +00001387 assert(Arg);
1388 Args.push_back(Arg);
1389
1390 Arg->writeDeclarations(OS);
1391 OS << "\n\n";
1392 }
1393
Aaron Ballman36a53502014-01-16 13:03:14 +00001394 OS << "\npublic:\n";
1395
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001396 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
Aaron Ballman36a53502014-01-16 13:03:14 +00001397
1398 // If there are zero or one spellings, all spelling-related functionality
1399 // can be elided. If all of the spellings share the same name, the spelling
1400 // functionality can also be elided.
1401 bool ElideSpelling = (Spellings.size() <= 1) ||
1402 SpellingNamesAreCommon(Spellings);
1403
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001404 // This maps spelling index values to semantic Spelling enumerants.
1405 SemanticSpellingMap SemanticToSyntacticMap;
Aaron Ballman36a53502014-01-16 13:03:14 +00001406
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001407 if (!ElideSpelling)
1408 OS << CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);
Aaron Ballman36a53502014-01-16 13:03:14 +00001409
1410 OS << " static " << R.getName() << "Attr *CreateImplicit(";
1411 OS << "ASTContext &Ctx";
1412 if (!ElideSpelling)
1413 OS << ", Spelling S";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001414 for (auto ai : Args) {
Aaron Ballman36a53502014-01-16 13:03:14 +00001415 OS << ", ";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001416 ai->writeCtorParameters(OS);
Aaron Ballman36a53502014-01-16 13:03:14 +00001417 }
1418 OS << ", SourceRange Loc = SourceRange()";
1419 OS << ") {\n";
1420 OS << " " << R.getName() << "Attr *A = new (Ctx) " << R.getName();
1421 OS << "Attr(Loc, Ctx, ";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001422 for (auto ai : Args) {
1423 ai->writeImplicitCtorArgs(OS);
Aaron Ballman36a53502014-01-16 13:03:14 +00001424 OS << ", ";
1425 }
1426 OS << (ElideSpelling ? "0" : "S") << ");\n";
1427 OS << " A->setImplicit(true);\n";
1428 OS << " return A;\n }\n\n";
1429
Peter Collingbournebee583f2011-10-06 13:03:08 +00001430 OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
1431
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001432 bool HasOpt = false;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001433 for (auto ai : Args) {
Peter Collingbournebee583f2011-10-06 13:03:08 +00001434 OS << " , ";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001435 ai->writeCtorParameters(OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001436 OS << "\n";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001437 if (ai->isOptional())
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001438 HasOpt = true;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001439 }
Michael Han99315932013-01-24 16:46:58 +00001440
1441 OS << " , ";
Aaron Ballman36a53502014-01-16 13:03:14 +00001442 OS << "unsigned SI\n";
Michael Han99315932013-01-24 16:46:58 +00001443
Peter Collingbournebee583f2011-10-06 13:03:08 +00001444 OS << " )\n";
Michael Han99315932013-01-24 16:46:58 +00001445 OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001446
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001447 for (auto ai : Args) {
Peter Collingbournebee583f2011-10-06 13:03:08 +00001448 OS << " , ";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001449 ai->writeCtorInitializers(OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001450 OS << "\n";
1451 }
1452
1453 OS << " {\n";
1454
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001455 for (auto ai : Args) {
1456 ai->writeCtorBody(OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001457 OS << "\n";
1458 }
1459 OS << " }\n\n";
1460
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001461 // If there are optional arguments, write out a constructor that elides the
1462 // optional arguments as well.
1463 if (HasOpt) {
1464 OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001465 for (auto ai : Args) {
1466 if (!ai->isOptional()) {
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001467 OS << " , ";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001468 ai->writeCtorParameters(OS);
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001469 OS << "\n";
1470 }
1471 }
1472
1473 OS << " , ";
Aaron Ballman36a53502014-01-16 13:03:14 +00001474 OS << "unsigned SI\n";
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001475
1476 OS << " )\n";
1477 OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n";
1478
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001479 for (auto ai : Args) {
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001480 OS << " , ";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001481 ai->writeCtorDefaultInitializers(OS);
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001482 OS << "\n";
1483 }
1484
1485 OS << " {\n";
1486
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001487 for (auto ai : Args) {
1488 if (!ai->isOptional()) {
1489 ai->writeCtorBody(OS);
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001490 OS << "\n";
1491 }
1492 }
1493 OS << " }\n\n";
1494 }
1495
Peter Collingbournebee583f2011-10-06 13:03:08 +00001496 OS << " virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n";
Michael Han38d96ab2013-01-27 00:06:24 +00001497 OS << " virtual void printPretty(raw_ostream &OS,\n"
Richard Smith52f04a22012-08-16 02:43:29 +00001498 << " const PrintingPolicy &Policy) const;\n";
Aaron Ballman3e424b52013-12-26 18:30:57 +00001499 OS << " virtual const char *getSpelling() const;\n";
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001500
1501 if (!ElideSpelling) {
1502 assert(!SemanticToSyntacticMap.empty() && "Empty semantic mapping list");
1503 OS << " Spelling getSemanticSpelling() const {\n";
1504 WriteSemanticSpellingSwitch("SpellingListIndex", SemanticToSyntacticMap,
1505 OS);
1506 OS << " }\n";
1507 }
Peter Collingbournebee583f2011-10-06 13:03:08 +00001508
Michael Hanaf02bbe2013-02-01 01:19:17 +00001509 writeAttrAccessorDefinition(R, OS);
1510
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001511 for (auto ai : Args) {
1512 ai->writeAccessors(OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001513 OS << "\n\n";
Aaron Ballman682ee422013-09-11 19:47:58 +00001514
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001515 if (ai->isEnumArg())
1516 static_cast<EnumArgument *>(ai)->writeConversion(OS);
1517 else if (ai->isVariadicEnumArg())
1518 static_cast<VariadicEnumArgument *>(ai)->writeConversion(OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001519 }
1520
Jakob Stoklund Olesen6f2288b62012-01-13 04:57:47 +00001521 OS << R.getValueAsString("AdditionalMembers");
Peter Collingbournebee583f2011-10-06 13:03:08 +00001522 OS << "\n\n";
1523
1524 OS << " static bool classof(const Attr *A) { return A->getKind() == "
1525 << "attr::" << R.getName() << "; }\n";
DeLesley Hutchins30398dd2012-01-20 22:50:54 +00001526
1527 bool LateParsed = R.getValueAsBit("LateParsed");
1528 OS << " virtual bool isLateParsed() const { return "
1529 << LateParsed << "; }\n";
1530
Aaron Ballmanb9023ed2014-01-20 18:07:09 +00001531 if (R.getValueAsBit("DuplicatesAllowedWhileMerging"))
1532 OS << " virtual bool duplicatesAllowed() const { return true; }\n\n";
1533
Peter Collingbournebee583f2011-10-06 13:03:08 +00001534 OS << "};\n\n";
1535 }
1536
1537 OS << "#endif\n";
1538}
1539
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001540// Emits the class method definitions for attributes.
1541void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00001542 emitSourceFileHeader("Attribute classes' member function definitions", OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001543
1544 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
Peter Collingbournebee583f2011-10-06 13:03:08 +00001545
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001546 for (auto i : Attrs) {
1547 Record &R = *i;
Douglas Gregorb2daf842012-05-02 15:56:52 +00001548
1549 if (!R.getValueAsBit("ASTNode"))
1550 continue;
1551
Peter Collingbournebee583f2011-10-06 13:03:08 +00001552 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
1553 std::vector<Argument*> Args;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001554 for (auto ri : ArgRecords)
1555 Args.push_back(createArgument(*ri, R.getName()));
Peter Collingbournebee583f2011-10-06 13:03:08 +00001556
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001557 for (auto ai : Args)
1558 ai->writeAccessorDefinitions(OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001559
1560 OS << R.getName() << "Attr *" << R.getName()
1561 << "Attr::clone(ASTContext &C) const {\n";
1562 OS << " return new (C) " << R.getName() << "Attr(getLocation(), C";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001563 for (auto ai : Args) {
Peter Collingbournebee583f2011-10-06 13:03:08 +00001564 OS << ", ";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001565 ai->writeCloneArgs(OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001566 }
Richard Smitha5aaca92013-01-29 04:21:28 +00001567 OS << ", getSpellingListIndex());\n}\n\n";
Douglas Gregor49ccfaa2011-11-19 19:22:57 +00001568
Michael Han99315932013-01-24 16:46:58 +00001569 writePrettyPrintFunction(R, Args, OS);
Aaron Ballman3e424b52013-12-26 18:30:57 +00001570 writeGetSpellingFunction(R, OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001571 }
1572}
1573
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001574} // end namespace clang
1575
Peter Collingbournebee583f2011-10-06 13:03:08 +00001576static void EmitAttrList(raw_ostream &OS, StringRef Class,
1577 const std::vector<Record*> &AttrList) {
1578 std::vector<Record*>::const_iterator i = AttrList.begin(), e = AttrList.end();
1579
1580 if (i != e) {
1581 // Move the end iterator back to emit the last attribute.
Douglas Gregorb2daf842012-05-02 15:56:52 +00001582 for(--e; i != e; ++i) {
1583 if (!(*i)->getValueAsBit("ASTNode"))
1584 continue;
1585
Peter Collingbournebee583f2011-10-06 13:03:08 +00001586 OS << Class << "(" << (*i)->getName() << ")\n";
Douglas Gregorb2daf842012-05-02 15:56:52 +00001587 }
Peter Collingbournebee583f2011-10-06 13:03:08 +00001588
1589 OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n";
1590 }
1591}
1592
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001593namespace clang {
1594
1595// Emits the enumeration list for attributes.
1596void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00001597 emitSourceFileHeader("List of all attributes that Clang recognizes", OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001598
1599 OS << "#ifndef LAST_ATTR\n";
1600 OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n";
1601 OS << "#endif\n\n";
1602
1603 OS << "#ifndef INHERITABLE_ATTR\n";
1604 OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n";
1605 OS << "#endif\n\n";
1606
1607 OS << "#ifndef LAST_INHERITABLE_ATTR\n";
1608 OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n";
1609 OS << "#endif\n\n";
1610
1611 OS << "#ifndef INHERITABLE_PARAM_ATTR\n";
1612 OS << "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n";
1613 OS << "#endif\n\n";
1614
1615 OS << "#ifndef LAST_INHERITABLE_PARAM_ATTR\n";
1616 OS << "#define LAST_INHERITABLE_PARAM_ATTR(NAME)"
1617 " INHERITABLE_PARAM_ATTR(NAME)\n";
1618 OS << "#endif\n\n";
1619
1620 Record *InhClass = Records.getClass("InheritableAttr");
1621 Record *InhParamClass = Records.getClass("InheritableParamAttr");
1622 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
Aaron Ballman8edb5c22013-12-18 23:44:18 +00001623 NonInhAttrs, InhAttrs, InhParamAttrs;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001624 for (auto i : Attrs) {
1625 if (!i->getValueAsBit("ASTNode"))
Douglas Gregorb2daf842012-05-02 15:56:52 +00001626 continue;
1627
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001628 if (i->isSubClassOf(InhParamClass))
1629 InhParamAttrs.push_back(i);
1630 else if (i->isSubClassOf(InhClass))
1631 InhAttrs.push_back(i);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001632 else
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001633 NonInhAttrs.push_back(i);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001634 }
1635
1636 EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs);
1637 EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs);
1638 EmitAttrList(OS, "ATTR", NonInhAttrs);
1639
1640 OS << "#undef LAST_ATTR\n";
1641 OS << "#undef INHERITABLE_ATTR\n";
1642 OS << "#undef LAST_INHERITABLE_ATTR\n";
1643 OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n";
1644 OS << "#undef ATTR\n";
1645}
1646
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001647// Emits the code to read an attribute from a precompiled header.
1648void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00001649 emitSourceFileHeader("Attribute deserialization code", OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001650
1651 Record *InhClass = Records.getClass("InheritableAttr");
1652 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
1653 ArgRecords;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001654 std::vector<Argument*> Args;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001655
1656 OS << " switch (Kind) {\n";
1657 OS << " default:\n";
1658 OS << " assert(0 && \"Unknown attribute!\");\n";
1659 OS << " break;\n";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001660 for (auto i : Attrs) {
1661 const Record &R = *i;
Douglas Gregorb2daf842012-05-02 15:56:52 +00001662 if (!R.getValueAsBit("ASTNode"))
1663 continue;
1664
Peter Collingbournebee583f2011-10-06 13:03:08 +00001665 OS << " case attr::" << R.getName() << ": {\n";
1666 if (R.isSubClassOf(InhClass))
1667 OS << " bool isInherited = Record[Idx++];\n";
Aaron Ballman36a53502014-01-16 13:03:14 +00001668 OS << " bool isImplicit = Record[Idx++];\n";
1669 OS << " unsigned Spelling = Record[Idx++];\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001670 ArgRecords = R.getValueAsListOfDefs("Args");
1671 Args.clear();
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001672 for (auto ai : ArgRecords) {
1673 Argument *A = createArgument(*ai, R.getName());
Peter Collingbournebee583f2011-10-06 13:03:08 +00001674 Args.push_back(A);
1675 A->writePCHReadDecls(OS);
1676 }
1677 OS << " New = new (Context) " << R.getName() << "Attr(Range, Context";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001678 for (auto ri : Args) {
Peter Collingbournebee583f2011-10-06 13:03:08 +00001679 OS << ", ";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001680 ri->writePCHReadArgs(OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001681 }
Aaron Ballman36a53502014-01-16 13:03:14 +00001682 OS << ", Spelling);\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001683 if (R.isSubClassOf(InhClass))
1684 OS << " cast<InheritableAttr>(New)->setInherited(isInherited);\n";
Aaron Ballman36a53502014-01-16 13:03:14 +00001685 OS << " New->setImplicit(isImplicit);\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001686 OS << " break;\n";
1687 OS << " }\n";
1688 }
1689 OS << " }\n";
1690}
1691
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001692// Emits the code to write an attribute to a precompiled header.
1693void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00001694 emitSourceFileHeader("Attribute serialization code", OS);
1695
Peter Collingbournebee583f2011-10-06 13:03:08 +00001696 Record *InhClass = Records.getClass("InheritableAttr");
1697 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001698
1699 OS << " switch (A->getKind()) {\n";
1700 OS << " default:\n";
1701 OS << " llvm_unreachable(\"Unknown attribute kind!\");\n";
1702 OS << " break;\n";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001703 for (auto i : Attrs) {
1704 const Record &R = *i;
Douglas Gregorb2daf842012-05-02 15:56:52 +00001705 if (!R.getValueAsBit("ASTNode"))
1706 continue;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001707 OS << " case attr::" << R.getName() << ": {\n";
1708 Args = R.getValueAsListOfDefs("Args");
1709 if (R.isSubClassOf(InhClass) || !Args.empty())
1710 OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
1711 << "Attr>(A);\n";
1712 if (R.isSubClassOf(InhClass))
1713 OS << " Record.push_back(SA->isInherited());\n";
Aaron Ballman36a53502014-01-16 13:03:14 +00001714 OS << " Record.push_back(A->isImplicit());\n";
1715 OS << " Record.push_back(A->getSpellingListIndex());\n";
1716
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001717 for (auto ai : Args)
1718 createArgument(*ai, R.getName())->writePCHWrite(OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001719 OS << " break;\n";
1720 OS << " }\n";
1721 }
1722 OS << " }\n";
1723}
1724
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001725// Emits the list of spellings for attributes.
1726void EmitClangAttrSpellingList(RecordKeeper &Records, raw_ostream &OS) {
Aaron Ballman0fa06d82014-01-09 22:57:44 +00001727 emitSourceFileHeader("llvm::StringSwitch code to match attributes based on "
1728 "the target triple, T", OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001729
1730 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1731
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001732 for (auto I : Attrs) {
1733 Record &Attr = *I;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001734
Aaron Ballman0fa06d82014-01-09 22:57:44 +00001735 // It is assumed that there will be an llvm::Triple object named T within
1736 // scope that can be used to determine whether the attribute exists in
1737 // a given target.
1738 std::string Test;
1739 if (Attr.isSubClassOf("TargetSpecificAttr")) {
1740 const Record *R = Attr.getValueAsDef("Target");
1741 std::vector<std::string> Arches = R->getValueAsListOfStrings("Arches");
Peter Collingbournebee583f2011-10-06 13:03:08 +00001742
Aaron Ballman0fa06d82014-01-09 22:57:44 +00001743 Test += "(";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001744 for (auto AI = Arches.begin(), AE = Arches.end(); AI != AE; ++AI) {
Aaron Ballman0fa06d82014-01-09 22:57:44 +00001745 std::string Part = *AI;
1746 Test += "T.getArch() == llvm::Triple::" + Part;
1747 if (AI + 1 != AE)
1748 Test += " || ";
1749 }
1750 Test += ")";
1751
1752 std::vector<std::string> OSes;
1753 if (!R->isValueUnset("OSes")) {
1754 Test += " && (";
1755 std::vector<std::string> OSes = R->getValueAsListOfStrings("OSes");
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001756 for (auto AI = OSes.begin(), AE = OSes.end(); AI != AE; ++AI) {
Aaron Ballman0fa06d82014-01-09 22:57:44 +00001757 std::string Part = *AI;
1758
1759 Test += "T.getOS() == llvm::Triple::" + Part;
1760 if (AI + 1 != AE)
1761 Test += " || ";
1762 }
1763 Test += ")";
1764 }
1765 } else
1766 Test = "true";
1767
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001768 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001769 for (const auto &S : Spellings)
1770 OS << ".Case(\"" << S.name() << "\", " << Test << ")\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001771 }
Peter Collingbournebee583f2011-10-06 13:03:08 +00001772}
1773
Michael Han99315932013-01-24 16:46:58 +00001774void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00001775 emitSourceFileHeader("Code to translate different attribute spellings "
1776 "into internal identifiers", OS);
Michael Han99315932013-01-24 16:46:58 +00001777
1778 OS <<
Michael Han99315932013-01-24 16:46:58 +00001779 " switch (AttrKind) {\n"
1780 " default:\n"
1781 " llvm_unreachable(\"Unknown attribute kind!\");\n"
1782 " break;\n";
1783
Aaron Ballman64e69862013-12-15 13:05:48 +00001784 ParsedAttrMap Attrs = getParsedAttrList(Records);
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001785 for (const auto &I : Attrs) {
1786 Record &R = *I.second;
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001787 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001788 OS << " case AT_" << I.first << ": {\n";
Richard Smith852e9ce2013-11-27 01:46:48 +00001789 for (unsigned I = 0; I < Spellings.size(); ++ I) {
Richard Smith852e9ce2013-11-27 01:46:48 +00001790 OS << " if (Name == \""
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001791 << Spellings[I].name() << "\" && "
Richard Smith852e9ce2013-11-27 01:46:48 +00001792 << "SyntaxUsed == "
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001793 << StringSwitch<unsigned>(Spellings[I].variety())
Richard Smith852e9ce2013-11-27 01:46:48 +00001794 .Case("GNU", 0)
1795 .Case("CXX11", 1)
1796 .Case("Declspec", 2)
1797 .Case("Keyword", 3)
1798 .Default(0)
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001799 << " && Scope == \"" << Spellings[I].nameSpace() << "\")\n"
Richard Smith852e9ce2013-11-27 01:46:48 +00001800 << " return " << I << ";\n";
Michael Han99315932013-01-24 16:46:58 +00001801 }
Richard Smith852e9ce2013-11-27 01:46:48 +00001802
1803 OS << " break;\n";
1804 OS << " }\n";
Michael Han99315932013-01-24 16:46:58 +00001805 }
1806
1807 OS << " }\n";
Aaron Ballman64e69862013-12-15 13:05:48 +00001808 OS << " return 0;\n";
Michael Han99315932013-01-24 16:46:58 +00001809}
1810
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +00001811// Emits code used by RecursiveASTVisitor to visit attributes
1812void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS) {
1813 emitSourceFileHeader("Used by RecursiveASTVisitor to visit attributes.", OS);
1814
1815 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1816
1817 // Write method declarations for Traverse* methods.
1818 // We emit this here because we only generate methods for attributes that
1819 // are declared as ASTNodes.
1820 OS << "#ifdef ATTR_VISITOR_DECLS_ONLY\n\n";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001821 for (auto I : Attrs) {
1822 const Record &R = *I;
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +00001823 if (!R.getValueAsBit("ASTNode"))
1824 continue;
1825 OS << " bool Traverse"
1826 << R.getName() << "Attr(" << R.getName() << "Attr *A);\n";
1827 OS << " bool Visit"
1828 << R.getName() << "Attr(" << R.getName() << "Attr *A) {\n"
1829 << " return true; \n"
1830 << " };\n";
1831 }
1832 OS << "\n#else // ATTR_VISITOR_DECLS_ONLY\n\n";
1833
1834 // Write individual Traverse* methods for each attribute class.
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001835 for (auto I : Attrs) {
1836 const Record &R = *I;
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +00001837 if (!R.getValueAsBit("ASTNode"))
1838 continue;
1839
1840 OS << "template <typename Derived>\n"
DeLesley Hutchinsbb79c332013-12-30 21:03:02 +00001841 << "bool VISITORCLASS<Derived>::Traverse"
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +00001842 << R.getName() << "Attr(" << R.getName() << "Attr *A) {\n"
1843 << " if (!getDerived().VisitAttr(A))\n"
1844 << " return false;\n"
1845 << " if (!getDerived().Visit" << R.getName() << "Attr(A))\n"
1846 << " return false;\n";
1847
1848 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001849 for (auto ri : ArgRecords) {
1850 Record &ArgRecord = *ri;
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +00001851 Argument *Arg = createArgument(ArgRecord, R.getName());
1852 assert(Arg);
1853 Arg->writeASTVisitorTraversal(OS);
1854 }
1855
1856 OS << " return true;\n";
1857 OS << "}\n\n";
1858 }
1859
1860 // Write generic Traverse routine
1861 OS << "template <typename Derived>\n"
DeLesley Hutchinsbb79c332013-12-30 21:03:02 +00001862 << "bool VISITORCLASS<Derived>::TraverseAttr(Attr *A) {\n"
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +00001863 << " if (!A)\n"
1864 << " return true;\n"
1865 << "\n"
1866 << " switch (A->getKind()) {\n"
1867 << " default:\n"
1868 << " return true;\n";
1869
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001870 for (auto I : Attrs) {
1871 const Record &R = *I;
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +00001872 if (!R.getValueAsBit("ASTNode"))
1873 continue;
1874
1875 OS << " case attr::" << R.getName() << ":\n"
1876 << " return getDerived().Traverse" << R.getName() << "Attr("
1877 << "cast<" << R.getName() << "Attr>(A));\n";
1878 }
1879 OS << " }\n"; // end case
1880 OS << "}\n"; // end function
1881 OS << "#endif // ATTR_VISITOR_DECLS_ONLY\n";
1882}
1883
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001884// Emits code to instantiate dependent attributes on templates.
1885void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00001886 emitSourceFileHeader("Template instantiation code for attributes", OS);
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001887
1888 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1889
Benjamin Kramerbf8da9d2012-02-06 11:13:08 +00001890 OS << "namespace clang {\n"
1891 << "namespace sema {\n\n"
1892 << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, "
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001893 << "Sema &S,\n"
1894 << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n"
1895 << " switch (At->getKind()) {\n"
1896 << " default:\n"
1897 << " break;\n";
1898
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001899 for (auto I : Attrs) {
1900 const Record &R = *I;
Douglas Gregorb2daf842012-05-02 15:56:52 +00001901 if (!R.getValueAsBit("ASTNode"))
1902 continue;
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001903
1904 OS << " case attr::" << R.getName() << ": {\n";
Rafael Espindola7f90b7d2012-05-15 14:09:55 +00001905 bool ShouldClone = R.getValueAsBit("Clone");
1906
1907 if (!ShouldClone) {
1908 OS << " return NULL;\n";
1909 OS << " }\n";
1910 continue;
1911 }
1912
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001913 OS << " const " << R.getName() << "Attr *A = cast<"
1914 << R.getName() << "Attr>(At);\n";
1915 bool TDependent = R.getValueAsBit("TemplateDependent");
1916
1917 if (!TDependent) {
1918 OS << " return A->clone(C);\n";
1919 OS << " }\n";
1920 continue;
1921 }
1922
1923 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
1924 std::vector<Argument*> Args;
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001925 Args.reserve(ArgRecords.size());
1926
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001927 for (auto ArgRecord : ArgRecords) {
1928 Argument *Arg = createArgument(*ArgRecord, R.getName());
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001929 assert(Arg);
1930 Args.push_back(Arg);
1931 }
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001932
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001933 for (auto ai : Args) {
1934 ai->writeTemplateInstantiation(OS);
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001935 }
1936 OS << " return new (C) " << R.getName() << "Attr(A->getLocation(), C";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001937 for (auto ai : Args) {
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001938 OS << ", ";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001939 ai->writeTemplateInstantiationArgs(OS);
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001940 }
Aaron Ballman36a53502014-01-16 13:03:14 +00001941 OS << ", A->getSpellingListIndex());\n }\n";
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001942 }
1943 OS << " } // end switch\n"
1944 << " llvm_unreachable(\"Unknown attribute!\");\n"
1945 << " return 0;\n"
Benjamin Kramerbf8da9d2012-02-06 11:13:08 +00001946 << "}\n\n"
1947 << "} // end namespace sema\n"
1948 << "} // end namespace clang\n";
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001949}
1950
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001951// Emits the list of parsed attributes.
1952void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) {
1953 emitSourceFileHeader("List of all attributes that Clang recognizes", OS);
1954
1955 OS << "#ifndef PARSED_ATTR\n";
1956 OS << "#define PARSED_ATTR(NAME) NAME\n";
1957 OS << "#endif\n\n";
1958
1959 ParsedAttrMap Names = getParsedAttrList(Records);
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001960 for (const auto &I : Names) {
1961 OS << "PARSED_ATTR(" << I.first << ")\n";
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001962 }
1963}
1964
Aaron Ballman74eeeae2013-11-27 13:27:02 +00001965static void emitArgInfo(const Record &R, std::stringstream &OS) {
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001966 // This function will count the number of arguments specified for the
1967 // attribute and emit the number of required arguments followed by the
1968 // number of optional arguments.
1969 std::vector<Record *> Args = R.getValueAsListOfDefs("Args");
1970 unsigned ArgCount = 0, OptCount = 0;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001971 for (auto Arg : Args) {
1972 Arg->getValueAsBit("Optional") ? ++OptCount : ++ArgCount;
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001973 }
1974 OS << ArgCount << ", " << OptCount;
1975}
1976
Aaron Ballman74eeeae2013-11-27 13:27:02 +00001977static void GenerateDefaultAppertainsTo(raw_ostream &OS) {
Aaron Ballman93b5cc62013-12-02 19:36:42 +00001978 OS << "static bool defaultAppertainsTo(Sema &, const AttributeList &,";
Aaron Ballman74eeeae2013-11-27 13:27:02 +00001979 OS << "const Decl *) {\n";
1980 OS << " return true;\n";
1981 OS << "}\n\n";
1982}
1983
1984static std::string CalculateDiagnostic(const Record &S) {
1985 // If the SubjectList object has a custom diagnostic associated with it,
1986 // return that directly.
1987 std::string CustomDiag = S.getValueAsString("CustomDiag");
1988 if (!CustomDiag.empty())
1989 return CustomDiag;
1990
1991 // Given the list of subjects, determine what diagnostic best fits.
1992 enum {
1993 Func = 1U << 0,
1994 Var = 1U << 1,
1995 ObjCMethod = 1U << 2,
1996 Param = 1U << 3,
1997 Class = 1U << 4,
Aaron Ballmanc1494bd2013-11-27 20:14:30 +00001998 GenericRecord = 1U << 5,
Aaron Ballman74eeeae2013-11-27 13:27:02 +00001999 Type = 1U << 6,
2000 ObjCIVar = 1U << 7,
2001 ObjCProp = 1U << 8,
2002 ObjCInterface = 1U << 9,
2003 Block = 1U << 10,
2004 Namespace = 1U << 11,
2005 FuncTemplate = 1U << 12,
2006 Field = 1U << 13,
Ted Kremenekd980da22013-12-10 19:43:42 +00002007 CXXMethod = 1U << 14,
2008 ObjCProtocol = 1U << 15
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002009 };
2010 uint32_t SubMask = 0;
2011
2012 std::vector<Record *> Subjects = S.getValueAsListOfDefs("Subjects");
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002013 for (auto I : Subjects) {
2014 const Record &R = *I;
Aaron Ballman80469032013-11-29 14:57:58 +00002015 std::string Name;
2016
2017 if (R.isSubClassOf("SubsetSubject")) {
2018 PrintError(R.getLoc(), "SubsetSubjects should use a custom diagnostic");
2019 // As a fallback, look through the SubsetSubject to see what its base
2020 // type is, and use that. This needs to be updated if SubsetSubjects
2021 // are allowed within other SubsetSubjects.
2022 Name = R.getValueAsDef("Base")->getName();
2023 } else
2024 Name = R.getName();
2025
2026 uint32_t V = StringSwitch<uint32_t>(Name)
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002027 .Case("Function", Func)
2028 .Case("Var", Var)
2029 .Case("ObjCMethod", ObjCMethod)
2030 .Case("ParmVar", Param)
2031 .Case("TypedefName", Type)
2032 .Case("ObjCIvar", ObjCIVar)
2033 .Case("ObjCProperty", ObjCProp)
Aaron Ballmanc1494bd2013-11-27 20:14:30 +00002034 .Case("Record", GenericRecord)
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002035 .Case("ObjCInterface", ObjCInterface)
Ted Kremenekd980da22013-12-10 19:43:42 +00002036 .Case("ObjCProtocol", ObjCProtocol)
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002037 .Case("Block", Block)
2038 .Case("CXXRecord", Class)
2039 .Case("Namespace", Namespace)
2040 .Case("FunctionTemplate", FuncTemplate)
2041 .Case("Field", Field)
2042 .Case("CXXMethod", CXXMethod)
2043 .Default(0);
2044 if (!V) {
2045 // Something wasn't in our mapping, so be helpful and let the developer
2046 // know about it.
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002047 PrintFatalError(R.getLoc(), "Unknown subject type: " + R.getName());
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002048 return "";
2049 }
2050
2051 SubMask |= V;
2052 }
2053
2054 switch (SubMask) {
2055 // For the simple cases where there's only a single entry in the mask, we
2056 // don't have to resort to bit fiddling.
2057 case Func: return "ExpectedFunction";
2058 case Var: return "ExpectedVariable";
2059 case Param: return "ExpectedParameter";
2060 case Class: return "ExpectedClass";
2061 case CXXMethod:
2062 // FIXME: Currently, this maps to ExpectedMethod based on existing code,
2063 // but should map to something a bit more accurate at some point.
2064 case ObjCMethod: return "ExpectedMethod";
2065 case Type: return "ExpectedType";
2066 case ObjCInterface: return "ExpectedObjectiveCInterface";
Ted Kremenekd980da22013-12-10 19:43:42 +00002067 case ObjCProtocol: return "ExpectedObjectiveCProtocol";
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002068
Aaron Ballmanc1494bd2013-11-27 20:14:30 +00002069 // "GenericRecord" means struct, union or class; check the language options
2070 // and if not compiling for C++, strip off the class part. Note that this
2071 // relies on the fact that the context for this declares "Sema &S".
2072 case GenericRecord:
Aaron Ballman17046b82013-11-27 19:16:55 +00002073 return "(S.getLangOpts().CPlusPlus ? ExpectedStructOrUnionOrClass : "
2074 "ExpectedStructOrUnion)";
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002075 case Func | ObjCMethod | Block: return "ExpectedFunctionMethodOrBlock";
2076 case Func | ObjCMethod | Class: return "ExpectedFunctionMethodOrClass";
2077 case Func | Param:
2078 case Func | ObjCMethod | Param: return "ExpectedFunctionMethodOrParameter";
2079 case Func | FuncTemplate:
2080 case Func | ObjCMethod: return "ExpectedFunctionOrMethod";
2081 case Func | Var: return "ExpectedVariableOrFunction";
Aaron Ballman604dfec2013-12-02 17:07:07 +00002082
2083 // If not compiling for C++, the class portion does not apply.
2084 case Func | Var | Class:
2085 return "(S.getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass : "
2086 "ExpectedVariableOrFunction)";
2087
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002088 case ObjCMethod | ObjCProp: return "ExpectedMethodOrProperty";
2089 case Field | Var: return "ExpectedFieldOrGlobalVar";
2090 }
2091
2092 PrintFatalError(S.getLoc(),
2093 "Could not deduce diagnostic argument for Attr subjects");
2094
2095 return "";
2096}
2097
Aaron Ballman12b9f652014-01-16 13:55:42 +00002098static std::string GetSubjectWithSuffix(const Record *R) {
2099 std::string B = R->getName();
2100 if (B == "DeclBase")
2101 return "Decl";
2102 return B + "Decl";
2103}
Aaron Ballman80469032013-11-29 14:57:58 +00002104static std::string GenerateCustomAppertainsTo(const Record &Subject,
2105 raw_ostream &OS) {
Aaron Ballmana358c902013-12-02 14:58:17 +00002106 std::string FnName = "is" + Subject.getName();
2107
Aaron Ballman80469032013-11-29 14:57:58 +00002108 // If this code has already been generated, simply return the previous
2109 // instance of it.
2110 static std::set<std::string> CustomSubjectSet;
Aaron Ballmana358c902013-12-02 14:58:17 +00002111 std::set<std::string>::iterator I = CustomSubjectSet.find(FnName);
Aaron Ballman80469032013-11-29 14:57:58 +00002112 if (I != CustomSubjectSet.end())
2113 return *I;
2114
2115 Record *Base = Subject.getValueAsDef("Base");
2116
2117 // Not currently support custom subjects within custom subjects.
2118 if (Base->isSubClassOf("SubsetSubject")) {
2119 PrintFatalError(Subject.getLoc(),
2120 "SubsetSubjects within SubsetSubjects is not supported");
2121 return "";
2122 }
2123
Aaron Ballman80469032013-11-29 14:57:58 +00002124 OS << "static bool " << FnName << "(const Decl *D) {\n";
Aaron Ballman47553042014-01-16 14:32:03 +00002125 OS << " if (const " << GetSubjectWithSuffix(Base) << " *S = dyn_cast<";
Aaron Ballman12b9f652014-01-16 13:55:42 +00002126 OS << GetSubjectWithSuffix(Base);
Aaron Ballman47553042014-01-16 14:32:03 +00002127 OS << ">(D))\n";
2128 OS << " return " << Subject.getValueAsString("CheckCode") << ";\n";
2129 OS << " return false;\n";
Aaron Ballman80469032013-11-29 14:57:58 +00002130 OS << "}\n\n";
2131
2132 CustomSubjectSet.insert(FnName);
2133 return FnName;
2134}
2135
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002136static std::string GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) {
2137 // If the attribute does not contain a Subjects definition, then use the
2138 // default appertainsTo logic.
2139 if (Attr.isValueUnset("Subjects"))
Aaron Ballman93b5cc62013-12-02 19:36:42 +00002140 return "defaultAppertainsTo";
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002141
2142 const Record *SubjectObj = Attr.getValueAsDef("Subjects");
2143 std::vector<Record*> Subjects = SubjectObj->getValueAsListOfDefs("Subjects");
2144
2145 // If the list of subjects is empty, it is assumed that the attribute
2146 // appertains to everything.
2147 if (Subjects.empty())
Aaron Ballman93b5cc62013-12-02 19:36:42 +00002148 return "defaultAppertainsTo";
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002149
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002150 bool Warn = SubjectObj->getValueAsDef("Diag")->getValueAsBit("Warn");
2151
2152 // Otherwise, generate an appertainsTo check specific to this attribute which
2153 // checks all of the given subjects against the Decl passed in. Return the
2154 // name of that check to the caller.
Aaron Ballman00dcc432013-12-03 13:45:50 +00002155 std::string FnName = "check" + Attr.getName() + "AppertainsTo";
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002156 std::stringstream SS;
2157 SS << "static bool " << FnName << "(Sema &S, const AttributeList &Attr, ";
2158 SS << "const Decl *D) {\n";
2159 SS << " if (";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002160 for (auto I = Subjects.begin(), E = Subjects.end(); I != E; ++I) {
Aaron Ballman80469032013-11-29 14:57:58 +00002161 // If the subject has custom code associated with it, generate a function
2162 // for it. The function cannot be inlined into this check (yet) because it
2163 // requires the subject to be of a specific type, and were that information
2164 // inlined here, it would not support an attribute with multiple custom
2165 // subjects.
2166 if ((*I)->isSubClassOf("SubsetSubject")) {
2167 SS << "!" << GenerateCustomAppertainsTo(**I, OS) << "(D)";
2168 } else {
Aaron Ballman12b9f652014-01-16 13:55:42 +00002169 SS << "!isa<" << GetSubjectWithSuffix(*I) << ">(D)";
Aaron Ballman80469032013-11-29 14:57:58 +00002170 }
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002171
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002172 if (I + 1 != E)
2173 SS << " && ";
2174 }
2175 SS << ") {\n";
2176 SS << " S.Diag(Attr.getLoc(), diag::";
2177 SS << (Warn ? "warn_attribute_wrong_decl_type" :
2178 "err_attribute_wrong_decl_type");
2179 SS << ")\n";
2180 SS << " << Attr.getName() << ";
2181 SS << CalculateDiagnostic(*SubjectObj) << ";\n";
2182 SS << " return false;\n";
2183 SS << " }\n";
2184 SS << " return true;\n";
2185 SS << "}\n\n";
2186
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002187 OS << SS.str();
2188 return FnName;
2189}
2190
Aaron Ballman3aff6332013-12-02 19:30:36 +00002191static void GenerateDefaultLangOptRequirements(raw_ostream &OS) {
2192 OS << "static bool defaultDiagnoseLangOpts(Sema &, ";
2193 OS << "const AttributeList &) {\n";
2194 OS << " return true;\n";
2195 OS << "}\n\n";
2196}
2197
2198static std::string GenerateLangOptRequirements(const Record &R,
2199 raw_ostream &OS) {
2200 // If the attribute has an empty or unset list of language requirements,
2201 // return the default handler.
2202 std::vector<Record *> LangOpts = R.getValueAsListOfDefs("LangOpts");
2203 if (LangOpts.empty())
2204 return "defaultDiagnoseLangOpts";
2205
2206 // Generate the test condition, as well as a unique function name for the
2207 // diagnostic test. The list of options should usually be short (one or two
2208 // options), and the uniqueness isn't strictly necessary (it is just for
2209 // codegen efficiency).
2210 std::string FnName = "check", Test;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002211 for (auto I = LangOpts.begin(), E = LangOpts.end(); I != E; ++I) {
Aaron Ballman3aff6332013-12-02 19:30:36 +00002212 std::string Part = (*I)->getValueAsString("Name");
2213 Test += "S.LangOpts." + Part;
2214 if (I + 1 != E)
2215 Test += " || ";
2216 FnName += Part;
2217 }
2218 FnName += "LangOpts";
2219
2220 // If this code has already been generated, simply return the previous
2221 // instance of it.
2222 static std::set<std::string> CustomLangOptsSet;
2223 std::set<std::string>::iterator I = CustomLangOptsSet.find(FnName);
2224 if (I != CustomLangOptsSet.end())
2225 return *I;
2226
2227 OS << "static bool " << FnName << "(Sema &S, const AttributeList &Attr) {\n";
2228 OS << " if (" << Test << ")\n";
2229 OS << " return true;\n\n";
2230 OS << " S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) ";
2231 OS << "<< Attr.getName();\n";
2232 OS << " return false;\n";
2233 OS << "}\n\n";
2234
2235 CustomLangOptsSet.insert(FnName);
2236 return FnName;
2237}
2238
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002239static void GenerateDefaultTargetRequirements(raw_ostream &OS) {
2240 OS << "static bool defaultTargetRequirements(llvm::Triple) {\n";
2241 OS << " return true;\n";
2242 OS << "}\n\n";
2243}
2244
2245static std::string GenerateTargetRequirements(const Record &Attr,
2246 const ParsedAttrMap &Dupes,
2247 raw_ostream &OS) {
2248 // If the attribute is not a target specific attribute, return the default
2249 // target handler.
2250 if (!Attr.isSubClassOf("TargetSpecificAttr"))
2251 return "defaultTargetRequirements";
2252
2253 // Get the list of architectures to be tested for.
2254 const Record *R = Attr.getValueAsDef("Target");
2255 std::vector<std::string> Arches = R->getValueAsListOfStrings("Arches");
2256 if (Arches.empty()) {
2257 PrintError(Attr.getLoc(), "Empty list of target architectures for a "
2258 "target-specific attr");
2259 return "defaultTargetRequirements";
2260 }
2261
2262 // If there are other attributes which share the same parsed attribute kind,
2263 // such as target-specific attributes with a shared spelling, collapse the
2264 // duplicate architectures. This is required because a shared target-specific
2265 // attribute has only one AttributeList::Kind enumeration value, but it
2266 // applies to multiple target architectures. In order for the attribute to be
2267 // considered valid, all of its architectures need to be included.
2268 if (!Attr.isValueUnset("ParseKind")) {
2269 std::string APK = Attr.getValueAsString("ParseKind");
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002270 for (const auto &I : Dupes) {
2271 if (I.first == APK) {
2272 std::vector<std::string> DA = I.second->getValueAsDef("Target")
2273 ->getValueAsListOfStrings("Arches");
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002274 std::copy(DA.begin(), DA.end(), std::back_inserter(Arches));
2275 }
2276 }
2277 }
2278
2279 std::string FnName = "isTarget", Test = "(";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002280 for (auto I = Arches.begin(), E = Arches.end(); I != E; ++I) {
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002281 std::string Part = *I;
2282 Test += "Arch == llvm::Triple::" + Part;
2283 if (I + 1 != E)
2284 Test += " || ";
2285 FnName += Part;
2286 }
2287 Test += ")";
2288
2289 // If the target also requires OS testing, generate those tests as well.
2290 bool UsesOS = false;
2291 if (!R->isValueUnset("OSes")) {
2292 UsesOS = true;
2293
2294 // We know that there was at least one arch test, so we need to and in the
2295 // OS tests.
2296 Test += " && (";
2297 std::vector<std::string> OSes = R->getValueAsListOfStrings("OSes");
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002298 for (auto I = OSes.begin(), E = OSes.end(); I != E; ++I) {
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002299 std::string Part = *I;
2300
2301 Test += "OS == llvm::Triple::" + Part;
2302 if (I + 1 != E)
2303 Test += " || ";
2304 FnName += Part;
2305 }
2306 Test += ")";
2307 }
2308
2309 // If this code has already been generated, simply return the previous
2310 // instance of it.
2311 static std::set<std::string> CustomTargetSet;
2312 std::set<std::string>::iterator I = CustomTargetSet.find(FnName);
2313 if (I != CustomTargetSet.end())
2314 return *I;
2315
2316 OS << "static bool " << FnName << "(llvm::Triple T) {\n";
2317 OS << " llvm::Triple::ArchType Arch = T.getArch();\n";
2318 if (UsesOS)
2319 OS << " llvm::Triple::OSType OS = T.getOS();\n";
2320 OS << " return " << Test << ";\n";
2321 OS << "}\n\n";
2322
2323 CustomTargetSet.insert(FnName);
2324 return FnName;
2325}
2326
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00002327static void GenerateDefaultSpellingIndexToSemanticSpelling(raw_ostream &OS) {
2328 OS << "static unsigned defaultSpellingIndexToSemanticSpelling("
2329 << "const AttributeList &Attr) {\n";
2330 OS << " return UINT_MAX;\n";
2331 OS << "}\n\n";
2332}
2333
2334static std::string GenerateSpellingIndexToSemanticSpelling(const Record &Attr,
2335 raw_ostream &OS) {
2336 // If the attribute does not have a semantic form, we can bail out early.
2337 if (!Attr.getValueAsBit("ASTNode"))
2338 return "defaultSpellingIndexToSemanticSpelling";
2339
Aaron Ballmanc669cc02014-01-27 22:10:04 +00002340 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00002341
2342 // If there are zero or one spellings, or all of the spellings share the same
2343 // name, we can also bail out early.
2344 if (Spellings.size() <= 1 || SpellingNamesAreCommon(Spellings))
2345 return "defaultSpellingIndexToSemanticSpelling";
2346
2347 // Generate the enumeration we will use for the mapping.
2348 SemanticSpellingMap SemanticToSyntacticMap;
2349 std::string Enum = CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);
2350 std::string Name = Attr.getName() + "AttrSpellingMap";
2351
2352 OS << "static unsigned " << Name << "(const AttributeList &Attr) {\n";
2353 OS << Enum;
2354 OS << " unsigned Idx = Attr.getAttributeSpellingListIndex();\n";
2355 WriteSemanticSpellingSwitch("Idx", SemanticToSyntacticMap, OS);
2356 OS << "}\n\n";
2357
2358 return Name;
2359}
2360
Aaron Ballmanc669cc02014-01-27 22:10:04 +00002361static bool IsKnownToGCC(const Record &Attr) {
2362 // Look at the spellings for this subject; if there are any spellings which
2363 // claim to be known to GCC, the attribute is known to GCC.
2364 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002365 for (const auto &I : Spellings) {
2366 if (I.knownToGCC())
Aaron Ballman9a99e0d2014-01-20 17:18:35 +00002367 return true;
2368 }
2369 return false;
2370}
2371
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002372/// Emits the parsed attribute helpers
2373void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
2374 emitSourceFileHeader("Parsed attribute helpers", OS);
2375
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002376 // Get the list of parsed attributes, and accept the optional list of
2377 // duplicates due to the ParseKind.
2378 ParsedAttrMap Dupes;
2379 ParsedAttrMap Attrs = getParsedAttrList(Records, &Dupes);
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002380
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00002381 // Generate the default appertainsTo, target and language option diagnostic,
2382 // and spelling list index mapping methods.
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002383 GenerateDefaultAppertainsTo(OS);
Aaron Ballman3aff6332013-12-02 19:30:36 +00002384 GenerateDefaultLangOptRequirements(OS);
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002385 GenerateDefaultTargetRequirements(OS);
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00002386 GenerateDefaultSpellingIndexToSemanticSpelling(OS);
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002387
2388 // Generate the appertainsTo diagnostic methods and write their names into
2389 // another mapping. At the same time, generate the AttrInfoMap object
2390 // contents. Due to the reliance on generated code, use separate streams so
2391 // that code will not be interleaved.
2392 std::stringstream SS;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002393 for (auto I = Attrs.begin(), E = Attrs.end(); I != E; ++I) {
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002394 // TODO: If the attribute's kind appears in the list of duplicates, that is
2395 // because it is a target-specific attribute that appears multiple times.
2396 // It would be beneficial to test whether the duplicates are "similar
2397 // enough" to each other to not cause problems. For instance, check that
Alp Toker96cf7582014-01-18 21:49:37 +00002398 // the spellings are identical, and custom parsing rules match, etc.
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002399
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002400 // We need to generate struct instances based off ParsedAttrInfo from
2401 // AttributeList.cpp.
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002402 SS << " { ";
2403 emitArgInfo(*I->second, SS);
2404 SS << ", " << I->second->getValueAsBit("HasCustomParsing");
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002405 SS << ", " << I->second->isSubClassOf("TargetSpecificAttr");
2406 SS << ", " << I->second->isSubClassOf("TypeAttr");
Aaron Ballmanc669cc02014-01-27 22:10:04 +00002407 SS << ", " << IsKnownToGCC(*I->second);
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002408 SS << ", " << GenerateAppertainsTo(*I->second, OS);
Aaron Ballman3aff6332013-12-02 19:30:36 +00002409 SS << ", " << GenerateLangOptRequirements(*I->second, OS);
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002410 SS << ", " << GenerateTargetRequirements(*I->second, Dupes, OS);
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00002411 SS << ", " << GenerateSpellingIndexToSemanticSpelling(*I->second, OS);
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002412 SS << " }";
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002413
2414 if (I + 1 != E)
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002415 SS << ",";
2416
2417 SS << " // AT_" << I->first << "\n";
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002418 }
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002419
2420 OS << "static const ParsedAttrInfo AttrInfoMap[AttributeList::UnknownAttribute + 1] = {\n";
2421 OS << SS.str();
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002422 OS << "};\n\n";
Michael Han4a045172012-03-07 00:12:16 +00002423}
2424
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00002425// Emits the kind list of parsed attributes
2426void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00002427 emitSourceFileHeader("Attribute name matcher", OS);
2428
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002429 std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
2430 std::vector<StringMatcher::StringPair> GNU, Declspec, CXX11, Keywords;
Aaron Ballman64e69862013-12-15 13:05:48 +00002431 std::set<std::string> Seen;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002432 for (auto I : Attrs) {
2433 const Record &Attr = *I;
Richard Smith852e9ce2013-11-27 01:46:48 +00002434
Michael Han4a045172012-03-07 00:12:16 +00002435 bool SemaHandler = Attr.getValueAsBit("SemaHandler");
Douglas Gregor19fbb8f2012-05-02 16:18:45 +00002436 bool Ignored = Attr.getValueAsBit("Ignored");
Douglas Gregor19fbb8f2012-05-02 16:18:45 +00002437 if (SemaHandler || Ignored) {
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002438 // Attribute spellings can be shared between target-specific attributes,
2439 // and can be shared between syntaxes for the same attribute. For
2440 // instance, an attribute can be spelled GNU<"interrupt"> for an ARM-
2441 // specific attribute, or MSP430-specific attribute. Additionally, an
2442 // attribute can be spelled GNU<"dllexport"> and Declspec<"dllexport">
2443 // for the same semantic attribute. Ultimately, we need to map each of
2444 // these to a single AttributeList::Kind value, but the StringMatcher
2445 // class cannot handle duplicate match strings. So we generate a list of
2446 // string to match based on the syntax, and emit multiple string matchers
2447 // depending on the syntax used.
Aaron Ballman64e69862013-12-15 13:05:48 +00002448 std::string AttrName;
2449 if (Attr.isSubClassOf("TargetSpecificAttr") &&
2450 !Attr.isValueUnset("ParseKind")) {
2451 AttrName = Attr.getValueAsString("ParseKind");
2452 if (Seen.find(AttrName) != Seen.end())
2453 continue;
2454 Seen.insert(AttrName);
2455 } else
2456 AttrName = NormalizeAttrName(StringRef(Attr.getName())).str();
2457
Aaron Ballmanc669cc02014-01-27 22:10:04 +00002458 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002459 for (const auto &S : Spellings) {
2460 std::string RawSpelling = S.name();
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002461 std::vector<StringMatcher::StringPair> *Matches = 0;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002462 std::string Spelling, Variety = S.variety();
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002463 if (Variety == "CXX11") {
2464 Matches = &CXX11;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002465 Spelling += S.nameSpace();
Alexis Hunt3bc72c12012-06-19 23:57:03 +00002466 Spelling += "::";
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002467 } else if (Variety == "GNU")
2468 Matches = &GNU;
2469 else if (Variety == "Declspec")
2470 Matches = &Declspec;
2471 else if (Variety == "Keyword")
2472 Matches = &Keywords;
Alexis Hunta0e54d42012-06-18 16:13:52 +00002473
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002474 assert(Matches && "Unsupported spelling variety found");
2475
2476 Spelling += NormalizeAttrSpelling(RawSpelling);
Douglas Gregor19fbb8f2012-05-02 16:18:45 +00002477 if (SemaHandler)
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002478 Matches->push_back(StringMatcher::StringPair(Spelling,
2479 "return AttributeList::AT_" + AttrName + ";"));
Douglas Gregor19fbb8f2012-05-02 16:18:45 +00002480 else
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002481 Matches->push_back(StringMatcher::StringPair(Spelling,
2482 "return AttributeList::IgnoredAttribute;"));
Michael Han4a045172012-03-07 00:12:16 +00002483 }
2484 }
2485 }
Douglas Gregor377f99b2012-05-02 17:33:51 +00002486
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002487 OS << "static AttributeList::Kind getAttrKind(StringRef Name, ";
2488 OS << "AttributeList::Syntax Syntax) {\n";
2489 OS << " if (AttributeList::AS_GNU == Syntax) {\n";
2490 StringMatcher("Name", GNU, OS).Emit();
2491 OS << " } else if (AttributeList::AS_Declspec == Syntax) {\n";
2492 StringMatcher("Name", Declspec, OS).Emit();
2493 OS << " } else if (AttributeList::AS_CXX11 == Syntax) {\n";
2494 StringMatcher("Name", CXX11, OS).Emit();
2495 OS << " } else if (AttributeList::AS_Keyword == Syntax) {\n";
2496 StringMatcher("Name", Keywords, OS).Emit();
2497 OS << " }\n";
2498 OS << " return AttributeList::UnknownAttribute;\n"
Douglas Gregor377f99b2012-05-02 17:33:51 +00002499 << "}\n";
Michael Han4a045172012-03-07 00:12:16 +00002500}
2501
Alexander Kornienko5bc364e2013-01-07 17:53:08 +00002502// Emits the code to dump an attribute.
2503void EmitClangAttrDump(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00002504 emitSourceFileHeader("Attribute dumper", OS);
2505
Alexander Kornienko5bc364e2013-01-07 17:53:08 +00002506 OS <<
2507 " switch (A->getKind()) {\n"
2508 " default:\n"
2509 " llvm_unreachable(\"Unknown attribute kind!\");\n"
2510 " break;\n";
2511 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002512 for (auto I : Attrs) {
2513 const Record &R = *I;
Alexander Kornienko5bc364e2013-01-07 17:53:08 +00002514 if (!R.getValueAsBit("ASTNode"))
2515 continue;
2516 OS << " case attr::" << R.getName() << ": {\n";
Aaron Ballmanbc909612014-01-22 21:51:20 +00002517
2518 // If the attribute has a semantically-meaningful name (which is determined
2519 // by whether there is a Spelling enumeration for it), then write out the
2520 // spelling used for the attribute.
Aaron Ballmanc669cc02014-01-27 22:10:04 +00002521 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
Aaron Ballmanbc909612014-01-22 21:51:20 +00002522 if (Spellings.size() > 1 && !SpellingNamesAreCommon(Spellings))
2523 OS << " OS << \" \" << A->getSpelling();\n";
2524
Alexander Kornienko5bc364e2013-01-07 17:53:08 +00002525 Args = R.getValueAsListOfDefs("Args");
2526 if (!Args.empty()) {
2527 OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
2528 << "Attr>(A);\n";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002529 for (auto AI : Args)
2530 createArgument(*AI, R.getName())->writeDump(OS);
Richard Trieude5cc7d2013-01-31 01:44:26 +00002531
2532 // Code for detecting the last child.
2533 OS << " bool OldMoreChildren = hasMoreChildren();\n";
2534 OS << " bool MoreChildren = OldMoreChildren;\n";
2535
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002536 for (auto AI = Args.begin(), AE = Args.end(); AI != AE; ++AI) {
Richard Trieude5cc7d2013-01-31 01:44:26 +00002537 // More code for detecting the last child.
2538 OS << " MoreChildren = OldMoreChildren";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002539 for (auto Next = AI + 1; Next != AE; ++Next) {
Richard Trieude5cc7d2013-01-31 01:44:26 +00002540 OS << " || ";
2541 createArgument(**Next, R.getName())->writeHasChildren(OS);
2542 }
2543 OS << ";\n";
2544 OS << " setMoreChildren(MoreChildren);\n";
2545
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002546 createArgument(**AI, R.getName())->writeDumpChildren(OS);
Richard Trieude5cc7d2013-01-31 01:44:26 +00002547 }
2548
2549 // Reset the last child.
2550 OS << " setMoreChildren(OldMoreChildren);\n";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +00002551 }
2552 OS <<
2553 " break;\n"
2554 " }\n";
2555 }
2556 OS << " }\n";
2557}
2558
Aaron Ballman35db2b32014-01-29 22:13:45 +00002559void EmitClangAttrParserStringSwitches(RecordKeeper &Records,
2560 raw_ostream &OS) {
2561 emitSourceFileHeader("Parser-related llvm::StringSwitch cases", OS);
2562 emitClangAttrArgContextList(Records, OS);
2563 emitClangAttrIdentifierArgList(Records, OS);
2564 emitClangAttrTypeArgList(Records, OS);
2565 emitClangAttrLateParsedList(Records, OS);
2566}
2567
Aaron Ballman97dba042014-02-17 15:27:10 +00002568class DocumentationData {
2569public:
Aaron Ballman1a3e5852014-02-17 16:18:32 +00002570 const Record *Documentation;
2571 const Record *Attribute;
Aaron Ballman97dba042014-02-17 15:27:10 +00002572
Aaron Ballman4de1b582014-02-19 22:59:32 +00002573 DocumentationData(const Record &Documentation, const Record &Attribute)
2574 : Documentation(&Documentation), Attribute(&Attribute) {}
Aaron Ballman97dba042014-02-17 15:27:10 +00002575};
2576
Aaron Ballman4de1b582014-02-19 22:59:32 +00002577static void WriteCategoryHeader(const Record *DocCategory,
Aaron Ballman97dba042014-02-17 15:27:10 +00002578 raw_ostream &OS) {
Aaron Ballman4de1b582014-02-19 22:59:32 +00002579 const std::string &Name = DocCategory->getValueAsString("Name");
2580 OS << Name << "\n" << std::string(Name.length(), '=') << "\n";
2581
2582 // If there is content, print that as well.
2583 std::string ContentStr = DocCategory->getValueAsString("Content");
2584 if (!ContentStr.empty()) {
2585 // Trim leading and trailing newlines and spaces.
2586 StringRef Content(ContentStr);
2587 while (Content.startswith("\r") || Content.startswith("\n") ||
2588 Content.startswith(" ") || Content.startswith("\t"))
2589 Content = Content.substr(1);
2590 while (Content.endswith("\r") || Content.endswith("\n") ||
2591 Content.endswith(" ") || Content.endswith("\t"))
2592 Content = Content.substr(0, Content.size() - 1);
2593 OS << Content;
Aaron Ballman97dba042014-02-17 15:27:10 +00002594 }
Aaron Ballman4de1b582014-02-19 22:59:32 +00002595 OS << "\n\n";
Aaron Ballman97dba042014-02-17 15:27:10 +00002596}
2597
Aaron Ballmana66b5742014-02-17 15:36:08 +00002598enum SpellingKind {
2599 GNU = 1 << 0,
2600 CXX11 = 1 << 1,
2601 Declspec = 1 << 2,
2602 Keyword = 1 << 3
2603};
2604
Aaron Ballman97dba042014-02-17 15:27:10 +00002605static void WriteDocumentation(const DocumentationData &Doc,
2606 raw_ostream &OS) {
2607 // FIXME: there is no way to have a per-spelling category for the attribute
2608 // documentation. This may not be a limiting factor since the spellings
2609 // should generally be consistently applied across the category.
2610
Aaron Ballman1a3e5852014-02-17 16:18:32 +00002611 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Doc.Attribute);
Aaron Ballman97dba042014-02-17 15:27:10 +00002612
2613 // Determine the heading to be used for this attribute.
Aaron Ballman1a3e5852014-02-17 16:18:32 +00002614 std::string Heading = Doc.Documentation->getValueAsString("Heading");
Aaron Ballmanea6668c2014-02-21 14:14:04 +00002615 bool CustomHeading = !Heading.empty();
Aaron Ballman97dba042014-02-17 15:27:10 +00002616 if (Heading.empty()) {
2617 // If there's only one spelling, we can simply use that.
2618 if (Spellings.size() == 1)
2619 Heading = Spellings.begin()->name();
2620 else {
2621 std::set<std::string> Uniques;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002622 for (auto I = Spellings.begin(), E = Spellings.end();
2623 I != E && Uniques.size() <= 1; ++I) {
Aaron Ballman97dba042014-02-17 15:27:10 +00002624 std::string Spelling = NormalizeNameForSpellingComparison(I->name());
2625 Uniques.insert(Spelling);
2626 }
2627 // If the semantic map has only one spelling, that is sufficient for our
2628 // needs.
2629 if (Uniques.size() == 1)
2630 Heading = *Uniques.begin();
2631 }
2632 }
2633
2634 // If the heading is still empty, it is an error.
2635 if (Heading.empty())
Aaron Ballman1a3e5852014-02-17 16:18:32 +00002636 PrintFatalError(Doc.Attribute->getLoc(),
Aaron Ballman97dba042014-02-17 15:27:10 +00002637 "This attribute requires a heading to be specified");
2638
2639 // Gather a list of unique spellings; this is not the same as the semantic
2640 // spelling for the attribute. Variations in underscores and other non-
2641 // semantic characters are still acceptable.
2642 std::vector<std::string> Names;
2643
Aaron Ballman97dba042014-02-17 15:27:10 +00002644 unsigned SupportedSpellings = 0;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002645 for (const auto &I : Spellings) {
2646 SpellingKind Kind = StringSwitch<SpellingKind>(I.variety())
Aaron Ballman97dba042014-02-17 15:27:10 +00002647 .Case("GNU", GNU)
2648 .Case("CXX11", CXX11)
2649 .Case("Declspec", Declspec)
2650 .Case("Keyword", Keyword);
2651
2652 // Mask in the supported spelling.
2653 SupportedSpellings |= Kind;
2654
2655 std::string Name;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002656 if (Kind == CXX11 && !I.nameSpace().empty())
2657 Name = I.nameSpace() + "::";
2658 Name += I.name();
Aaron Ballman97dba042014-02-17 15:27:10 +00002659
2660 // If this name is the same as the heading, do not add it.
2661 if (Name != Heading)
2662 Names.push_back(Name);
2663 }
2664
2665 // Print out the heading for the attribute. If there are alternate spellings,
2666 // then display those after the heading.
Aaron Ballmanea6668c2014-02-21 14:14:04 +00002667 if (!CustomHeading && !Names.empty()) {
Aaron Ballman97dba042014-02-17 15:27:10 +00002668 Heading += " (";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002669 for (auto I = Names.begin(), E = Names.end(); I != E; ++I) {
Aaron Ballman97dba042014-02-17 15:27:10 +00002670 if (I != Names.begin())
2671 Heading += ", ";
2672 Heading += *I;
2673 }
2674 Heading += ")";
2675 }
2676 OS << Heading << "\n" << std::string(Heading.length(), '-') << "\n";
2677
2678 if (!SupportedSpellings)
Aaron Ballman1a3e5852014-02-17 16:18:32 +00002679 PrintFatalError(Doc.Attribute->getLoc(),
Aaron Ballman97dba042014-02-17 15:27:10 +00002680 "Attribute has no supported spellings; cannot be "
2681 "documented");
2682
2683 // List what spelling syntaxes the attribute supports.
2684 OS << ".. csv-table:: Supported Syntaxes\n";
2685 OS << " :header: \"GNU\", \"C++11\", \"__declspec\", \"Keyword\"\n\n";
2686 OS << " \"";
2687 if (SupportedSpellings & GNU) OS << "X";
2688 OS << "\",\"";
2689 if (SupportedSpellings & CXX11) OS << "X";
2690 OS << "\",\"";
2691 if (SupportedSpellings & Declspec) OS << "X";
2692 OS << "\",\"";
2693 if (SupportedSpellings & Keyword) OS << "X";
2694 OS << "\"\n\n";
2695
2696 // If the attribute is deprecated, print a message about it, and possibly
2697 // provide a replacement attribute.
Aaron Ballman1a3e5852014-02-17 16:18:32 +00002698 if (!Doc.Documentation->isValueUnset("Deprecated")) {
Aaron Ballman97dba042014-02-17 15:27:10 +00002699 OS << "This attribute has been deprecated, and may be removed in a future "
2700 << "version of Clang.";
Aaron Ballman1a3e5852014-02-17 16:18:32 +00002701 const Record &Deprecated = *Doc.Documentation->getValueAsDef("Deprecated");
Aaron Ballman97dba042014-02-17 15:27:10 +00002702 std::string Replacement = Deprecated.getValueAsString("Replacement");
2703 if (!Replacement.empty())
2704 OS << " This attribute has been superseded by ``"
2705 << Replacement << "``.";
2706 OS << "\n\n";
2707 }
2708
Aaron Ballman1a3e5852014-02-17 16:18:32 +00002709 std::string ContentStr = Doc.Documentation->getValueAsString("Content");
Aaron Ballman97dba042014-02-17 15:27:10 +00002710 // Trim leading and trailing newlines and spaces.
2711 StringRef Content(ContentStr);
2712 while (Content.startswith("\r") || Content.startswith("\n") ||
2713 Content.startswith(" ") || Content.startswith("\t"))
2714 Content = Content.substr(1);
2715 while (Content.endswith("\r") || Content.endswith("\n") ||
2716 Content.endswith(" ") || Content.endswith("\t"))
2717 Content = Content.substr(0, Content.size() - 1);
2718 OS << Content;
2719
2720 OS << "\n\n\n";
2721}
2722
2723void EmitClangAttrDocs(RecordKeeper &Records, raw_ostream &OS) {
2724 // Get the documentation introduction paragraph.
2725 const Record *Documentation = Records.getDef("GlobalDocumentation");
2726 if (!Documentation) {
2727 PrintFatalError("The Documentation top-level definition is missing, "
2728 "no documentation will be generated.");
2729 return;
2730 }
2731
Aaron Ballman4de1b582014-02-19 22:59:32 +00002732 OS << Documentation->getValueAsString("Intro") << "\n";
Aaron Ballman97dba042014-02-17 15:27:10 +00002733
Aaron Ballman97dba042014-02-17 15:27:10 +00002734 // Gather the Documentation lists from each of the attributes, based on the
2735 // category provided.
2736 std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002737 std::map<const Record *, std::vector<DocumentationData>> SplitDocs;
2738 for (auto I : Attrs) {
2739 const Record &Attr = *I;
Aaron Ballman97dba042014-02-17 15:27:10 +00002740 std::vector<Record *> Docs = Attr.getValueAsListOfDefs("Documentation");
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002741 for (auto DI : Docs) {
2742 const Record &Doc = *DI;
Aaron Ballman4de1b582014-02-19 22:59:32 +00002743 const Record *Category = Doc.getValueAsDef("Category");
Aaron Ballman97dba042014-02-17 15:27:10 +00002744 // If the category is "undocumented", then there cannot be any other
2745 // documentation categories (otherwise, the attribute would become
2746 // documented).
Aaron Ballman4de1b582014-02-19 22:59:32 +00002747 std::string Cat = Category->getValueAsString("Name");
2748 bool Undocumented = Cat == "Undocumented";
Aaron Ballman97dba042014-02-17 15:27:10 +00002749 if (Undocumented && Docs.size() > 1)
2750 PrintFatalError(Doc.getLoc(),
2751 "Attribute is \"Undocumented\", but has multiple "
2752 "documentation categories");
2753
2754 if (!Undocumented)
Aaron Ballman4de1b582014-02-19 22:59:32 +00002755 SplitDocs[Category].push_back(DocumentationData(Doc, Attr));
Aaron Ballman97dba042014-02-17 15:27:10 +00002756 }
2757 }
2758
2759 // Having split the attributes out based on what documentation goes where,
2760 // we can begin to generate sections of documentation.
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002761 for (const auto &I : SplitDocs) {
2762 WriteCategoryHeader(I.first, OS);
Aaron Ballman97dba042014-02-17 15:27:10 +00002763
2764 // Walk over each of the attributes in the category and write out their
2765 // documentation.
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002766 for (const auto &Doc : I.second)
2767 WriteDocumentation(Doc, OS);
Aaron Ballman97dba042014-02-17 15:27:10 +00002768 }
2769}
2770
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00002771} // end namespace clang