blob: c40921821d91c55a250713a10404347215eadac5 [file] [log] [blame]
Peter Collingbourne51d77772011-10-06 13:03:08 +00001//===- ClangAttrEmitter.cpp - Generate Clang attribute handling =-*- C++ -*--=//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// These tablegen backends emit Clang attribute processing code
11//
12//===----------------------------------------------------------------------===//
13
Sean Hunt93f95f22012-06-18 16:13:52 +000014#include "llvm/ADT/SmallString.h"
Stephen Hines651f13c2014-04-23 16:59:28 -070015#include "llvm/ADT/STLExtras.h"
Aaron Ballmanbbb3b322013-09-09 23:33:17 +000016#include "llvm/ADT/SmallSet.h"
Stephen Hines651f13c2014-04-23 16:59:28 -070017#include "llvm/ADT/StringSwitch.h"
18#include "llvm/TableGen/Error.h"
Peter Collingbourne51d77772011-10-06 13:03:08 +000019#include "llvm/TableGen/Record.h"
Douglas Gregor0c19b3c2012-05-02 17:33:51 +000020#include "llvm/TableGen/StringMatcher.h"
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +000021#include "llvm/TableGen/TableGenBackend.h"
Peter Collingbourne51d77772011-10-06 13:03:08 +000022#include <algorithm>
23#include <cctype>
Stephen Hines651f13c2014-04-23 16:59:28 -070024#include <memory>
25#include <set>
26#include <sstream>
Peter Collingbourne51d77772011-10-06 13:03:08 +000027
28using namespace llvm;
29
Stephen Hines651f13c2014-04-23 16:59:28 -070030class FlattenedSpelling {
31 std::string V, N, NS;
32 bool K;
Peter Collingbourne51d77772011-10-06 13:03:08 +000033
Stephen Hines651f13c2014-04-23 16:59:28 -070034public:
35 FlattenedSpelling(const std::string &Variety, const std::string &Name,
36 const std::string &Namespace, bool KnownToGCC) :
37 V(Variety), N(Name), NS(Namespace), K(KnownToGCC) {}
38 explicit FlattenedSpelling(const Record &Spelling) :
39 V(Spelling.getValueAsString("Variety")),
40 N(Spelling.getValueAsString("Name")) {
Peter Collingbourne51d77772011-10-06 13:03:08 +000041
Stephen Hines651f13c2014-04-23 16:59:28 -070042 assert(V != "GCC" && "Given a GCC spelling, which means this hasn't been"
43 "flattened!");
44 if (V == "CXX11")
45 NS = Spelling.getValueAsString("Namespace");
46 bool Unset;
47 K = Spelling.getValueAsBitOrUnset("KnownToGCC", Unset);
Peter Collingbourne51d77772011-10-06 13:03:08 +000048 }
49
Stephen Hines651f13c2014-04-23 16:59:28 -070050 const std::string &variety() const { return V; }
51 const std::string &name() const { return N; }
52 const std::string &nameSpace() const { return NS; }
53 bool knownToGCC() const { return K; }
54};
55
56std::vector<FlattenedSpelling> GetFlattenedSpellings(const Record &Attr) {
57 std::vector<Record *> Spellings = Attr.getValueAsListOfDefs("Spellings");
58 std::vector<FlattenedSpelling> Ret;
59
60 for (const auto &Spelling : Spellings) {
61 if (Spelling->getValueAsString("Variety") == "GCC") {
62 // Gin up two new spelling objects to add into the list.
63 Ret.push_back(FlattenedSpelling("GNU", Spelling->getValueAsString("Name"),
64 "", true));
65 Ret.push_back(FlattenedSpelling(
66 "CXX11", Spelling->getValueAsString("Name"), "gnu", true));
67 } else
68 Ret.push_back(FlattenedSpelling(*Spelling));
69 }
70
71 return Ret;
Peter Collingbourne51d77772011-10-06 13:03:08 +000072}
73
74static std::string ReadPCHRecord(StringRef type) {
75 return StringSwitch<std::string>(type)
76 .EndsWith("Decl *", "GetLocalDeclAs<"
77 + std::string(type, 0, type.size()-1) + ">(F, Record[Idx++])")
Richard Smithddc2a532013-10-31 21:23:20 +000078 .Case("TypeSourceInfo *", "GetTypeSourceInfo(F, Record, Idx)")
Argyrios Kyrtzidis350aea72012-11-15 01:31:39 +000079 .Case("Expr *", "ReadExpr(F)")
Peter Collingbourne51d77772011-10-06 13:03:08 +000080 .Case("IdentifierInfo *", "GetIdentifierInfo(F, Record, Idx)")
Peter Collingbourne51d77772011-10-06 13:03:08 +000081 .Default("Record[Idx++]");
82}
83
84// Assumes that the way to get the value is SA->getname()
85static std::string WritePCHRecord(StringRef type, StringRef name) {
86 return StringSwitch<std::string>(type)
87 .EndsWith("Decl *", "AddDeclRef(" + std::string(name) +
88 ", Record);\n")
Richard Smithddc2a532013-10-31 21:23:20 +000089 .Case("TypeSourceInfo *",
90 "AddTypeSourceInfo(" + std::string(name) + ", Record);\n")
Peter Collingbourne51d77772011-10-06 13:03:08 +000091 .Case("Expr *", "AddStmt(" + std::string(name) + ");\n")
92 .Case("IdentifierInfo *",
93 "AddIdentifierRef(" + std::string(name) + ", Record);\n")
Peter Collingbourne51d77772011-10-06 13:03:08 +000094 .Default("Record.push_back(" + std::string(name) + ");\n");
95}
96
Michael Hane53ac8a2012-03-07 00:12:16 +000097// Normalize attribute name by removing leading and trailing
98// underscores. For example, __foo, foo__, __foo__ would
99// become foo.
100static StringRef NormalizeAttrName(StringRef AttrName) {
101 if (AttrName.startswith("__"))
102 AttrName = AttrName.substr(2, AttrName.size());
103
104 if (AttrName.endswith("__"))
105 AttrName = AttrName.substr(0, AttrName.size() - 2);
106
107 return AttrName;
108}
109
Stephen Hines651f13c2014-04-23 16:59:28 -0700110// Normalize the name by removing any and all leading and trailing underscores.
111// This is different from NormalizeAttrName in that it also handles names like
112// _pascal and __pascal.
113static StringRef NormalizeNameForSpellingComparison(StringRef Name) {
114 while (Name.startswith("_"))
115 Name = Name.substr(1, Name.size());
116 while (Name.endswith("_"))
117 Name = Name.substr(0, Name.size() - 1);
118 return Name;
119}
120
Michael Hane53ac8a2012-03-07 00:12:16 +0000121// Normalize attribute spelling only if the spelling has both leading
122// and trailing underscores. For example, __ms_struct__ will be
123// normalized to "ms_struct"; __cdecl will remain intact.
124static StringRef NormalizeAttrSpelling(StringRef AttrSpelling) {
125 if (AttrSpelling.startswith("__") && AttrSpelling.endswith("__")) {
126 AttrSpelling = AttrSpelling.substr(2, AttrSpelling.size() - 4);
127 }
128
129 return AttrSpelling;
130}
131
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700132typedef std::vector<std::pair<std::string, const Record *>> ParsedAttrMap;
Stephen Hines651f13c2014-04-23 16:59:28 -0700133
134static ParsedAttrMap getParsedAttrList(const RecordKeeper &Records,
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700135 ParsedAttrMap *Dupes = nullptr) {
Stephen Hines651f13c2014-04-23 16:59:28 -0700136 std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
137 std::set<std::string> Seen;
138 ParsedAttrMap R;
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700139 for (const auto *Attr : Attrs) {
Stephen Hines651f13c2014-04-23 16:59:28 -0700140 if (Attr->getValueAsBit("SemaHandler")) {
141 std::string AN;
142 if (Attr->isSubClassOf("TargetSpecificAttr") &&
143 !Attr->isValueUnset("ParseKind")) {
144 AN = Attr->getValueAsString("ParseKind");
145
146 // If this attribute has already been handled, it does not need to be
147 // handled again.
148 if (Seen.find(AN) != Seen.end()) {
149 if (Dupes)
150 Dupes->push_back(std::make_pair(AN, Attr));
151 continue;
152 }
153 Seen.insert(AN);
154 } else
155 AN = NormalizeAttrName(Attr->getName()).str();
156
157 R.push_back(std::make_pair(AN, Attr));
158 }
159 }
160 return R;
161}
162
Peter Collingbourne51d77772011-10-06 13:03:08 +0000163namespace {
164 class Argument {
165 std::string lowerName, upperName;
166 StringRef attrName;
Aaron Ballmanbbb3b322013-09-09 23:33:17 +0000167 bool isOpt;
Peter Collingbourne51d77772011-10-06 13:03:08 +0000168
169 public:
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700170 Argument(const Record &Arg, StringRef Attr)
Peter Collingbourne51d77772011-10-06 13:03:08 +0000171 : lowerName(Arg.getValueAsString("Name")), upperName(lowerName),
Aaron Ballmanbbb3b322013-09-09 23:33:17 +0000172 attrName(Attr), isOpt(false) {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000173 if (!lowerName.empty()) {
174 lowerName[0] = std::tolower(lowerName[0]);
175 upperName[0] = std::toupper(upperName[0]);
176 }
177 }
178 virtual ~Argument() {}
179
180 StringRef getLowerName() const { return lowerName; }
181 StringRef getUpperName() const { return upperName; }
182 StringRef getAttrName() const { return attrName; }
183
Aaron Ballmanbbb3b322013-09-09 23:33:17 +0000184 bool isOptional() const { return isOpt; }
185 void setOptional(bool set) { isOpt = set; }
186
Peter Collingbourne51d77772011-10-06 13:03:08 +0000187 // These functions print the argument contents formatted in different ways.
188 virtual void writeAccessors(raw_ostream &OS) const = 0;
189 virtual void writeAccessorDefinitions(raw_ostream &OS) const {}
Stephen Hines651f13c2014-04-23 16:59:28 -0700190 virtual void writeASTVisitorTraversal(raw_ostream &OS) const {}
Peter Collingbourne51d77772011-10-06 13:03:08 +0000191 virtual void writeCloneArgs(raw_ostream &OS) const = 0;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000192 virtual void writeTemplateInstantiationArgs(raw_ostream &OS) const = 0;
Daniel Dunbarb8806092012-02-10 06:00:29 +0000193 virtual void writeTemplateInstantiation(raw_ostream &OS) const {}
Peter Collingbourne51d77772011-10-06 13:03:08 +0000194 virtual void writeCtorBody(raw_ostream &OS) const {}
195 virtual void writeCtorInitializers(raw_ostream &OS) const = 0;
Aaron Ballmanbbb3b322013-09-09 23:33:17 +0000196 virtual void writeCtorDefaultInitializers(raw_ostream &OS) const = 0;
Peter Collingbourne51d77772011-10-06 13:03:08 +0000197 virtual void writeCtorParameters(raw_ostream &OS) const = 0;
198 virtual void writeDeclarations(raw_ostream &OS) const = 0;
199 virtual void writePCHReadArgs(raw_ostream &OS) const = 0;
200 virtual void writePCHReadDecls(raw_ostream &OS) const = 0;
201 virtual void writePCHWrite(raw_ostream &OS) const = 0;
Douglas Gregor1bea8802011-11-19 19:22:57 +0000202 virtual void writeValue(raw_ostream &OS) const = 0;
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000203 virtual void writeDump(raw_ostream &OS) const = 0;
204 virtual void writeDumpChildren(raw_ostream &OS) const {}
Richard Trieue8d41192013-01-31 01:44:26 +0000205 virtual void writeHasChildren(raw_ostream &OS) const { OS << "false"; }
Aaron Ballmand0686072013-09-11 19:47:58 +0000206
207 virtual bool isEnumArg() const { return false; }
DeLesley Hutchins66540852013-10-04 21:28:06 +0000208 virtual bool isVariadicEnumArg() const { return false; }
Stephen Hines651f13c2014-04-23 16:59:28 -0700209
210 virtual void writeImplicitCtorArgs(raw_ostream &OS) const {
211 OS << getUpperName();
212 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000213 };
214
215 class SimpleArgument : public Argument {
216 std::string type;
217
218 public:
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700219 SimpleArgument(const Record &Arg, StringRef Attr, std::string T)
Peter Collingbourne51d77772011-10-06 13:03:08 +0000220 : Argument(Arg, Attr), type(T)
221 {}
222
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000223 std::string getType() const { return type; }
224
Stephen Hines651f13c2014-04-23 16:59:28 -0700225 void writeAccessors(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000226 OS << " " << type << " get" << getUpperName() << "() const {\n";
227 OS << " return " << getLowerName() << ";\n";
228 OS << " }";
229 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700230 void writeCloneArgs(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000231 OS << getLowerName();
232 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700233 void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000234 OS << "A->get" << getUpperName() << "()";
235 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700236 void writeCtorInitializers(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000237 OS << getLowerName() << "(" << getUpperName() << ")";
238 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700239 void writeCtorDefaultInitializers(raw_ostream &OS) const override {
Aaron Ballmanbbb3b322013-09-09 23:33:17 +0000240 OS << getLowerName() << "()";
241 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700242 void writeCtorParameters(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000243 OS << type << " " << getUpperName();
244 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700245 void writeDeclarations(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000246 OS << type << " " << getLowerName() << ";";
247 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700248 void writePCHReadDecls(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000249 std::string read = ReadPCHRecord(type);
250 OS << " " << type << " " << getLowerName() << " = " << read << ";\n";
251 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700252 void writePCHReadArgs(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000253 OS << getLowerName();
254 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700255 void writePCHWrite(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000256 OS << " " << WritePCHRecord(type, "SA->get" +
257 std::string(getUpperName()) + "()");
258 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700259 void writeValue(raw_ostream &OS) const override {
Douglas Gregor1bea8802011-11-19 19:22:57 +0000260 if (type == "FunctionDecl *") {
Richard Smithddc2a532013-10-31 21:23:20 +0000261 OS << "\" << get" << getUpperName()
262 << "()->getNameInfo().getAsString() << \"";
Douglas Gregor1bea8802011-11-19 19:22:57 +0000263 } else if (type == "IdentifierInfo *") {
264 OS << "\" << get" << getUpperName() << "()->getName() << \"";
Richard Smithddc2a532013-10-31 21:23:20 +0000265 } else if (type == "TypeSourceInfo *") {
Douglas Gregor1bea8802011-11-19 19:22:57 +0000266 OS << "\" << get" << getUpperName() << "().getAsString() << \"";
Douglas Gregor1bea8802011-11-19 19:22:57 +0000267 } else {
268 OS << "\" << get" << getUpperName() << "() << \"";
269 }
270 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700271 void writeDump(raw_ostream &OS) const override {
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000272 if (type == "FunctionDecl *") {
273 OS << " OS << \" \";\n";
274 OS << " dumpBareDeclRef(SA->get" << getUpperName() << "());\n";
275 } else if (type == "IdentifierInfo *") {
276 OS << " OS << \" \" << SA->get" << getUpperName()
277 << "()->getName();\n";
Richard Smithddc2a532013-10-31 21:23:20 +0000278 } else if (type == "TypeSourceInfo *") {
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000279 OS << " OS << \" \" << SA->get" << getUpperName()
280 << "().getAsString();\n";
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000281 } else if (type == "bool") {
282 OS << " if (SA->get" << getUpperName() << "()) OS << \" "
283 << getUpperName() << "\";\n";
284 } else if (type == "int" || type == "unsigned") {
285 OS << " OS << \" \" << SA->get" << getUpperName() << "();\n";
286 } else {
287 llvm_unreachable("Unknown SimpleArgument type!");
288 }
289 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000290 };
291
Stephen Hines651f13c2014-04-23 16:59:28 -0700292 class DefaultSimpleArgument : public SimpleArgument {
293 int64_t Default;
294
295 public:
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700296 DefaultSimpleArgument(const Record &Arg, StringRef Attr,
Stephen Hines651f13c2014-04-23 16:59:28 -0700297 std::string T, int64_t Default)
298 : SimpleArgument(Arg, Attr, T), Default(Default) {}
299
300 void writeAccessors(raw_ostream &OS) const override {
301 SimpleArgument::writeAccessors(OS);
302
303 OS << "\n\n static const " << getType() << " Default" << getUpperName()
304 << " = " << Default << ";";
305 }
306 };
307
Peter Collingbourne51d77772011-10-06 13:03:08 +0000308 class StringArgument : public Argument {
309 public:
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700310 StringArgument(const Record &Arg, StringRef Attr)
Peter Collingbourne51d77772011-10-06 13:03:08 +0000311 : Argument(Arg, Attr)
312 {}
313
Stephen Hines651f13c2014-04-23 16:59:28 -0700314 void writeAccessors(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000315 OS << " llvm::StringRef get" << getUpperName() << "() const {\n";
316 OS << " return llvm::StringRef(" << getLowerName() << ", "
317 << getLowerName() << "Length);\n";
318 OS << " }\n";
319 OS << " unsigned get" << getUpperName() << "Length() const {\n";
320 OS << " return " << getLowerName() << "Length;\n";
321 OS << " }\n";
322 OS << " void set" << getUpperName()
323 << "(ASTContext &C, llvm::StringRef S) {\n";
324 OS << " " << getLowerName() << "Length = S.size();\n";
325 OS << " this->" << getLowerName() << " = new (C, 1) char ["
326 << getLowerName() << "Length];\n";
327 OS << " std::memcpy(this->" << getLowerName() << ", S.data(), "
328 << getLowerName() << "Length);\n";
329 OS << " }";
330 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700331 void writeCloneArgs(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000332 OS << "get" << getUpperName() << "()";
333 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700334 void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000335 OS << "A->get" << getUpperName() << "()";
336 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700337 void writeCtorBody(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000338 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
339 << ".data(), " << getLowerName() << "Length);";
340 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700341 void writeCtorInitializers(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000342 OS << getLowerName() << "Length(" << getUpperName() << ".size()),"
343 << getLowerName() << "(new (Ctx, 1) char[" << getLowerName()
344 << "Length])";
345 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700346 void writeCtorDefaultInitializers(raw_ostream &OS) const override {
Aaron Ballmanbbb3b322013-09-09 23:33:17 +0000347 OS << getLowerName() << "Length(0)," << getLowerName() << "(0)";
348 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700349 void writeCtorParameters(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000350 OS << "llvm::StringRef " << getUpperName();
351 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700352 void writeDeclarations(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000353 OS << "unsigned " << getLowerName() << "Length;\n";
354 OS << "char *" << getLowerName() << ";";
355 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700356 void writePCHReadDecls(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000357 OS << " std::string " << getLowerName()
358 << "= ReadString(Record, Idx);\n";
359 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700360 void writePCHReadArgs(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000361 OS << getLowerName();
362 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700363 void writePCHWrite(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000364 OS << " AddString(SA->get" << getUpperName() << "(), Record);\n";
365 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700366 void writeValue(raw_ostream &OS) const override {
Douglas Gregor1bea8802011-11-19 19:22:57 +0000367 OS << "\\\"\" << get" << getUpperName() << "() << \"\\\"";
368 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700369 void writeDump(raw_ostream &OS) const override {
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000370 OS << " OS << \" \\\"\" << SA->get" << getUpperName()
371 << "() << \"\\\"\";\n";
372 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000373 };
374
375 class AlignedArgument : public Argument {
376 public:
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700377 AlignedArgument(const Record &Arg, StringRef Attr)
Peter Collingbourne51d77772011-10-06 13:03:08 +0000378 : Argument(Arg, Attr)
379 {}
380
Stephen Hines651f13c2014-04-23 16:59:28 -0700381 void writeAccessors(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000382 OS << " bool is" << getUpperName() << "Dependent() const;\n";
383
384 OS << " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n";
385
386 OS << " bool is" << getUpperName() << "Expr() const {\n";
387 OS << " return is" << getLowerName() << "Expr;\n";
388 OS << " }\n";
389
390 OS << " Expr *get" << getUpperName() << "Expr() const {\n";
391 OS << " assert(is" << getLowerName() << "Expr);\n";
392 OS << " return " << getLowerName() << "Expr;\n";
393 OS << " }\n";
394
395 OS << " TypeSourceInfo *get" << getUpperName() << "Type() const {\n";
396 OS << " assert(!is" << getLowerName() << "Expr);\n";
397 OS << " return " << getLowerName() << "Type;\n";
398 OS << " }";
399 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700400 void writeAccessorDefinitions(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000401 OS << "bool " << getAttrName() << "Attr::is" << getUpperName()
402 << "Dependent() const {\n";
403 OS << " if (is" << getLowerName() << "Expr)\n";
404 OS << " return " << getLowerName() << "Expr && (" << getLowerName()
405 << "Expr->isValueDependent() || " << getLowerName()
406 << "Expr->isTypeDependent());\n";
407 OS << " else\n";
408 OS << " return " << getLowerName()
409 << "Type->getType()->isDependentType();\n";
410 OS << "}\n";
411
412 // FIXME: Do not do the calculation here
413 // FIXME: Handle types correctly
414 // A null pointer means maximum alignment
415 // FIXME: Load the platform-specific maximum alignment, rather than
416 // 16, the x86 max.
417 OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName()
418 << "(ASTContext &Ctx) const {\n";
419 OS << " assert(!is" << getUpperName() << "Dependent());\n";
420 OS << " if (is" << getLowerName() << "Expr)\n";
421 OS << " return (" << getLowerName() << "Expr ? " << getLowerName()
Richard Smitha6b8b2c2011-10-10 18:28:20 +0000422 << "Expr->EvaluateKnownConstInt(Ctx).getZExtValue() : 16)"
Peter Collingbourne51d77772011-10-06 13:03:08 +0000423 << "* Ctx.getCharWidth();\n";
424 OS << " else\n";
425 OS << " return 0; // FIXME\n";
426 OS << "}\n";
427 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700428 void writeCloneArgs(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000429 OS << "is" << getLowerName() << "Expr, is" << getLowerName()
430 << "Expr ? static_cast<void*>(" << getLowerName()
431 << "Expr) : " << getLowerName()
432 << "Type";
433 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700434 void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000435 // FIXME: move the definition in Sema::InstantiateAttrs to here.
436 // In the meantime, aligned attributes are cloned.
437 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700438 void writeCtorBody(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000439 OS << " if (is" << getLowerName() << "Expr)\n";
440 OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>("
441 << getUpperName() << ");\n";
442 OS << " else\n";
443 OS << " " << getLowerName()
444 << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName()
445 << ");";
446 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700447 void writeCtorInitializers(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000448 OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)";
449 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700450 void writeCtorDefaultInitializers(raw_ostream &OS) const override {
Aaron Ballmanbbb3b322013-09-09 23:33:17 +0000451 OS << "is" << getLowerName() << "Expr(false)";
452 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700453 void writeCtorParameters(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000454 OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName();
455 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700456 void writeImplicitCtorArgs(raw_ostream &OS) const override {
457 OS << "Is" << getUpperName() << "Expr, " << getUpperName();
458 }
459 void writeDeclarations(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000460 OS << "bool is" << getLowerName() << "Expr;\n";
461 OS << "union {\n";
462 OS << "Expr *" << getLowerName() << "Expr;\n";
463 OS << "TypeSourceInfo *" << getLowerName() << "Type;\n";
464 OS << "};";
465 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700466 void writePCHReadArgs(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000467 OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr";
468 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700469 void writePCHReadDecls(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000470 OS << " bool is" << getLowerName() << "Expr = Record[Idx++];\n";
471 OS << " void *" << getLowerName() << "Ptr;\n";
472 OS << " if (is" << getLowerName() << "Expr)\n";
473 OS << " " << getLowerName() << "Ptr = ReadExpr(F);\n";
474 OS << " else\n";
475 OS << " " << getLowerName()
476 << "Ptr = GetTypeSourceInfo(F, Record, Idx);\n";
477 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700478 void writePCHWrite(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000479 OS << " Record.push_back(SA->is" << getUpperName() << "Expr());\n";
480 OS << " if (SA->is" << getUpperName() << "Expr())\n";
481 OS << " AddStmt(SA->get" << getUpperName() << "Expr());\n";
482 OS << " else\n";
483 OS << " AddTypeSourceInfo(SA->get" << getUpperName()
484 << "Type(), Record);\n";
485 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700486 void writeValue(raw_ostream &OS) const override {
Richard Smith0dae7292012-08-16 02:43:29 +0000487 OS << "\";\n"
488 << " " << getLowerName() << "Expr->printPretty(OS, 0, Policy);\n"
489 << " OS << \"";
Douglas Gregor1bea8802011-11-19 19:22:57 +0000490 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700491 void writeDump(raw_ostream &OS) const override {
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000492 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700493 void writeDumpChildren(raw_ostream &OS) const override {
Richard Trieue8d41192013-01-31 01:44:26 +0000494 OS << " if (SA->is" << getUpperName() << "Expr()) {\n";
495 OS << " lastChild();\n";
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000496 OS << " dumpStmt(SA->get" << getUpperName() << "Expr());\n";
Richard Trieue8d41192013-01-31 01:44:26 +0000497 OS << " } else\n";
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000498 OS << " dumpType(SA->get" << getUpperName()
499 << "Type()->getType());\n";
500 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700501 void writeHasChildren(raw_ostream &OS) const override {
Richard Trieue8d41192013-01-31 01:44:26 +0000502 OS << "SA->is" << getUpperName() << "Expr()";
503 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000504 };
505
506 class VariadicArgument : public Argument {
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700507 std::string Type, ArgName, ArgSizeName, RangeName;
Peter Collingbourne51d77772011-10-06 13:03:08 +0000508
509 public:
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700510 VariadicArgument(const Record &Arg, StringRef Attr, std::string T)
511 : Argument(Arg, Attr), Type(T), ArgName(getLowerName().str() + "_"),
512 ArgSizeName(ArgName + "Size"), RangeName(getLowerName()) {}
Peter Collingbourne51d77772011-10-06 13:03:08 +0000513
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700514 std::string getType() const { return Type; }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000515
Stephen Hines651f13c2014-04-23 16:59:28 -0700516 void writeAccessors(raw_ostream &OS) const override {
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700517 std::string IteratorType = getLowerName().str() + "_iterator";
518 std::string BeginFn = getLowerName().str() + "_begin()";
519 std::string EndFn = getLowerName().str() + "_end()";
520
521 OS << " typedef " << Type << "* " << IteratorType << ";\n";
522 OS << " " << IteratorType << " " << BeginFn << " const {"
523 << " return " << ArgName << "; }\n";
524 OS << " " << IteratorType << " " << EndFn << " const {"
525 << " return " << ArgName << " + " << ArgSizeName << "; }\n";
526 OS << " unsigned " << getLowerName() << "_size() const {"
527 << " return " << ArgSizeName << "; }\n";
528 OS << " llvm::iterator_range<" << IteratorType << "> " << RangeName
529 << "() const { return llvm::make_range(" << BeginFn << ", " << EndFn
530 << "); }\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000531 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700532 void writeCloneArgs(raw_ostream &OS) const override {
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700533 OS << ArgName << ", " << ArgSizeName;
Peter Collingbourne51d77772011-10-06 13:03:08 +0000534 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700535 void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000536 // This isn't elegant, but we have to go through public methods...
537 OS << "A->" << getLowerName() << "_begin(), "
538 << "A->" << getLowerName() << "_size()";
539 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700540 void writeCtorBody(raw_ostream &OS) const override {
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700541 OS << " std::copy(" << getUpperName() << ", " << getUpperName()
542 << " + " << ArgSizeName << ", " << ArgName << ");";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000543 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700544 void writeCtorInitializers(raw_ostream &OS) const override {
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700545 OS << ArgSizeName << "(" << getUpperName() << "Size), "
546 << ArgName << "(new (Ctx, 16) " << getType() << "["
547 << ArgSizeName << "])";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000548 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700549 void writeCtorDefaultInitializers(raw_ostream &OS) const override {
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700550 OS << ArgSizeName << "(0), " << ArgName << "(nullptr)";
Aaron Ballmanbbb3b322013-09-09 23:33:17 +0000551 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700552 void writeCtorParameters(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000553 OS << getType() << " *" << getUpperName() << ", unsigned "
554 << getUpperName() << "Size";
555 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700556 void writeImplicitCtorArgs(raw_ostream &OS) const override {
557 OS << getUpperName() << ", " << getUpperName() << "Size";
558 }
559 void writeDeclarations(raw_ostream &OS) const override {
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700560 OS << " unsigned " << ArgSizeName << ";\n";
561 OS << " " << getType() << " *" << ArgName << ";";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000562 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700563 void writePCHReadDecls(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000564 OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700565 OS << " SmallVector<" << Type << ", 4> " << getLowerName()
Peter Collingbourne51d77772011-10-06 13:03:08 +0000566 << ";\n";
567 OS << " " << getLowerName() << ".reserve(" << getLowerName()
568 << "Size);\n";
DeLesley Hutchins66540852013-10-04 21:28:06 +0000569 OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000570
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700571 std::string read = ReadPCHRecord(Type);
Peter Collingbourne51d77772011-10-06 13:03:08 +0000572 OS << " " << getLowerName() << ".push_back(" << read << ");\n";
573 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700574 void writePCHReadArgs(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000575 OS << getLowerName() << ".data(), " << getLowerName() << "Size";
576 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700577 void writePCHWrite(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000578 OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700579 OS << " for (auto &Val : SA->" << RangeName << "())\n";
580 OS << " " << WritePCHRecord(Type, "Val");
Peter Collingbourne51d77772011-10-06 13:03:08 +0000581 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700582 void writeValue(raw_ostream &OS) const override {
Douglas Gregor1bea8802011-11-19 19:22:57 +0000583 OS << "\";\n";
584 OS << " bool isFirst = true;\n"
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700585 << " for (const auto &Val : " << RangeName << "()) {\n"
Douglas Gregor1bea8802011-11-19 19:22:57 +0000586 << " if (isFirst) isFirst = false;\n"
587 << " else OS << \", \";\n"
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700588 << " OS << Val;\n"
Douglas Gregor1bea8802011-11-19 19:22:57 +0000589 << " }\n";
590 OS << " OS << \"";
591 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700592 void writeDump(raw_ostream &OS) const override {
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700593 OS << " for (const auto &Val : SA->" << RangeName << "())\n";
594 OS << " OS << \" \" << Val;\n";
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000595 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000596 };
597
Stephen Hines651f13c2014-04-23 16:59:28 -0700598 // Unique the enums, but maintain the original declaration ordering.
599 std::vector<std::string>
600 uniqueEnumsInOrder(const std::vector<std::string> &enums) {
601 std::vector<std::string> uniques;
602 std::set<std::string> unique_set(enums.begin(), enums.end());
603 for (const auto &i : enums) {
604 std::set<std::string>::iterator set_i = unique_set.find(i);
605 if (set_i != unique_set.end()) {
606 uniques.push_back(i);
607 unique_set.erase(set_i);
608 }
609 }
610 return uniques;
611 }
612
Peter Collingbourne51d77772011-10-06 13:03:08 +0000613 class EnumArgument : public Argument {
614 std::string type;
Stephen Hines651f13c2014-04-23 16:59:28 -0700615 std::vector<std::string> values, enums, uniques;
Peter Collingbourne51d77772011-10-06 13:03:08 +0000616 public:
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700617 EnumArgument(const Record &Arg, StringRef Attr)
Peter Collingbourne51d77772011-10-06 13:03:08 +0000618 : Argument(Arg, Attr), type(Arg.getValueAsString("Type")),
Stephen Hines651f13c2014-04-23 16:59:28 -0700619 values(Arg.getValueAsListOfStrings("Values")),
620 enums(Arg.getValueAsListOfStrings("Enums")),
621 uniques(uniqueEnumsInOrder(enums))
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000622 {
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000623 // FIXME: Emit a proper error
624 assert(!uniques.empty());
625 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000626
Stephen Hines651f13c2014-04-23 16:59:28 -0700627 bool isEnumArg() const override { return true; }
Aaron Ballmand0686072013-09-11 19:47:58 +0000628
Stephen Hines651f13c2014-04-23 16:59:28 -0700629 void writeAccessors(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000630 OS << " " << type << " get" << getUpperName() << "() const {\n";
631 OS << " return " << getLowerName() << ";\n";
632 OS << " }";
633 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700634 void writeCloneArgs(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000635 OS << getLowerName();
636 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700637 void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000638 OS << "A->get" << getUpperName() << "()";
639 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700640 void writeCtorInitializers(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000641 OS << getLowerName() << "(" << getUpperName() << ")";
642 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700643 void writeCtorDefaultInitializers(raw_ostream &OS) const override {
Aaron Ballmanbbb3b322013-09-09 23:33:17 +0000644 OS << getLowerName() << "(" << type << "(0))";
645 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700646 void writeCtorParameters(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000647 OS << type << " " << getUpperName();
648 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700649 void writeDeclarations(raw_ostream &OS) const override {
650 std::vector<std::string>::const_iterator i = uniques.begin(),
651 e = uniques.end();
Peter Collingbourne51d77772011-10-06 13:03:08 +0000652 // The last one needs to not have a comma.
653 --e;
654
655 OS << "public:\n";
656 OS << " enum " << type << " {\n";
657 for (; i != e; ++i)
658 OS << " " << *i << ",\n";
659 OS << " " << *e << "\n";
660 OS << " };\n";
661 OS << "private:\n";
662 OS << " " << type << " " << getLowerName() << ";";
663 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700664 void writePCHReadDecls(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000665 OS << " " << getAttrName() << "Attr::" << type << " " << getLowerName()
666 << "(static_cast<" << getAttrName() << "Attr::" << type
667 << ">(Record[Idx++]));\n";
668 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700669 void writePCHReadArgs(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000670 OS << getLowerName();
671 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700672 void writePCHWrite(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000673 OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
674 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700675 void writeValue(raw_ostream &OS) const override {
Douglas Gregor1bea8802011-11-19 19:22:57 +0000676 OS << "\" << get" << getUpperName() << "() << \"";
677 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700678 void writeDump(raw_ostream &OS) const override {
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000679 OS << " switch(SA->get" << getUpperName() << "()) {\n";
Stephen Hines651f13c2014-04-23 16:59:28 -0700680 for (const auto &I : uniques) {
681 OS << " case " << getAttrName() << "Attr::" << I << ":\n";
682 OS << " OS << \" " << I << "\";\n";
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000683 OS << " break;\n";
684 }
685 OS << " }\n";
686 }
Aaron Ballmand0686072013-09-11 19:47:58 +0000687
688 void writeConversion(raw_ostream &OS) const {
689 OS << " static bool ConvertStrTo" << type << "(StringRef Val, ";
690 OS << type << " &Out) {\n";
691 OS << " Optional<" << type << "> R = llvm::StringSwitch<Optional<";
Stephen Hines651f13c2014-04-23 16:59:28 -0700692 OS << type << ">>(Val)\n";
Aaron Ballmand0686072013-09-11 19:47:58 +0000693 for (size_t I = 0; I < enums.size(); ++I) {
694 OS << " .Case(\"" << values[I] << "\", ";
695 OS << getAttrName() << "Attr::" << enums[I] << ")\n";
696 }
697 OS << " .Default(Optional<" << type << ">());\n";
698 OS << " if (R) {\n";
699 OS << " Out = *R;\n return true;\n }\n";
700 OS << " return false;\n";
701 OS << " }\n";
702 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000703 };
DeLesley Hutchins66540852013-10-04 21:28:06 +0000704
705 class VariadicEnumArgument: public VariadicArgument {
706 std::string type, QualifiedTypeName;
Stephen Hines651f13c2014-04-23 16:59:28 -0700707 std::vector<std::string> values, enums, uniques;
DeLesley Hutchins66540852013-10-04 21:28:06 +0000708 public:
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700709 VariadicEnumArgument(const Record &Arg, StringRef Attr)
DeLesley Hutchins66540852013-10-04 21:28:06 +0000710 : VariadicArgument(Arg, Attr, Arg.getValueAsString("Type")),
711 type(Arg.getValueAsString("Type")),
Stephen Hines651f13c2014-04-23 16:59:28 -0700712 values(Arg.getValueAsListOfStrings("Values")),
713 enums(Arg.getValueAsListOfStrings("Enums")),
714 uniques(uniqueEnumsInOrder(enums))
DeLesley Hutchins66540852013-10-04 21:28:06 +0000715 {
DeLesley Hutchins66540852013-10-04 21:28:06 +0000716 QualifiedTypeName = getAttrName().str() + "Attr::" + type;
717
718 // FIXME: Emit a proper error
719 assert(!uniques.empty());
720 }
721
Stephen Hines651f13c2014-04-23 16:59:28 -0700722 bool isVariadicEnumArg() const override { return true; }
DeLesley Hutchins66540852013-10-04 21:28:06 +0000723
Stephen Hines651f13c2014-04-23 16:59:28 -0700724 void writeDeclarations(raw_ostream &OS) const override {
725 std::vector<std::string>::const_iterator i = uniques.begin(),
726 e = uniques.end();
DeLesley Hutchins66540852013-10-04 21:28:06 +0000727 // The last one needs to not have a comma.
728 --e;
729
730 OS << "public:\n";
731 OS << " enum " << type << " {\n";
732 for (; i != e; ++i)
733 OS << " " << *i << ",\n";
734 OS << " " << *e << "\n";
735 OS << " };\n";
736 OS << "private:\n";
737
738 VariadicArgument::writeDeclarations(OS);
739 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700740 void writeDump(raw_ostream &OS) const override {
DeLesley Hutchins66540852013-10-04 21:28:06 +0000741 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
742 << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
743 << getLowerName() << "_end(); I != E; ++I) {\n";
744 OS << " switch(*I) {\n";
Stephen Hines651f13c2014-04-23 16:59:28 -0700745 for (const auto &UI : uniques) {
746 OS << " case " << getAttrName() << "Attr::" << UI << ":\n";
747 OS << " OS << \" " << UI << "\";\n";
DeLesley Hutchins66540852013-10-04 21:28:06 +0000748 OS << " break;\n";
749 }
750 OS << " }\n";
751 OS << " }\n";
752 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700753 void writePCHReadDecls(raw_ostream &OS) const override {
DeLesley Hutchins66540852013-10-04 21:28:06 +0000754 OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
755 OS << " SmallVector<" << QualifiedTypeName << ", 4> " << getLowerName()
756 << ";\n";
757 OS << " " << getLowerName() << ".reserve(" << getLowerName()
758 << "Size);\n";
759 OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
760 OS << " " << getLowerName() << ".push_back(" << "static_cast<"
761 << QualifiedTypeName << ">(Record[Idx++]));\n";
762 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700763 void writePCHWrite(raw_ostream &OS) const override {
DeLesley Hutchins66540852013-10-04 21:28:06 +0000764 OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";
765 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
766 << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
767 << getLowerName() << "_end(); i != e; ++i)\n";
768 OS << " " << WritePCHRecord(QualifiedTypeName, "(*i)");
769 }
770 void writeConversion(raw_ostream &OS) const {
771 OS << " static bool ConvertStrTo" << type << "(StringRef Val, ";
772 OS << type << " &Out) {\n";
773 OS << " Optional<" << type << "> R = llvm::StringSwitch<Optional<";
Stephen Hines651f13c2014-04-23 16:59:28 -0700774 OS << type << ">>(Val)\n";
DeLesley Hutchins66540852013-10-04 21:28:06 +0000775 for (size_t I = 0; I < enums.size(); ++I) {
776 OS << " .Case(\"" << values[I] << "\", ";
777 OS << getAttrName() << "Attr::" << enums[I] << ")\n";
778 }
779 OS << " .Default(Optional<" << type << ">());\n";
780 OS << " if (R) {\n";
781 OS << " Out = *R;\n return true;\n }\n";
782 OS << " return false;\n";
783 OS << " }\n";
784 }
785 };
Peter Collingbourne51d77772011-10-06 13:03:08 +0000786
787 class VersionArgument : public Argument {
788 public:
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700789 VersionArgument(const Record &Arg, StringRef Attr)
Peter Collingbourne51d77772011-10-06 13:03:08 +0000790 : Argument(Arg, Attr)
791 {}
792
Stephen Hines651f13c2014-04-23 16:59:28 -0700793 void writeAccessors(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000794 OS << " VersionTuple get" << getUpperName() << "() const {\n";
795 OS << " return " << getLowerName() << ";\n";
796 OS << " }\n";
797 OS << " void set" << getUpperName()
798 << "(ASTContext &C, VersionTuple V) {\n";
799 OS << " " << getLowerName() << " = V;\n";
800 OS << " }";
801 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700802 void writeCloneArgs(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000803 OS << "get" << getUpperName() << "()";
804 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700805 void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000806 OS << "A->get" << getUpperName() << "()";
807 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700808 void writeCtorInitializers(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000809 OS << getLowerName() << "(" << getUpperName() << ")";
810 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700811 void writeCtorDefaultInitializers(raw_ostream &OS) const override {
Aaron Ballmanbbb3b322013-09-09 23:33:17 +0000812 OS << getLowerName() << "()";
813 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700814 void writeCtorParameters(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000815 OS << "VersionTuple " << getUpperName();
816 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700817 void writeDeclarations(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000818 OS << "VersionTuple " << getLowerName() << ";\n";
819 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700820 void writePCHReadDecls(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000821 OS << " VersionTuple " << getLowerName()
822 << "= ReadVersionTuple(Record, Idx);\n";
823 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700824 void writePCHReadArgs(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000825 OS << getLowerName();
826 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700827 void writePCHWrite(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000828 OS << " AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n";
829 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700830 void writeValue(raw_ostream &OS) const override {
Douglas Gregor1bea8802011-11-19 19:22:57 +0000831 OS << getLowerName() << "=\" << get" << getUpperName() << "() << \"";
832 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700833 void writeDump(raw_ostream &OS) const override {
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000834 OS << " OS << \" \" << SA->get" << getUpperName() << "();\n";
835 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000836 };
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000837
838 class ExprArgument : public SimpleArgument {
839 public:
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700840 ExprArgument(const Record &Arg, StringRef Attr)
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000841 : SimpleArgument(Arg, Attr, "Expr *")
842 {}
843
Stephen Hines651f13c2014-04-23 16:59:28 -0700844 void writeASTVisitorTraversal(raw_ostream &OS) const override {
845 OS << " if (!"
846 << "getDerived().TraverseStmt(A->get" << getUpperName() << "()))\n";
847 OS << " return false;\n";
848 }
849
850 void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000851 OS << "tempInst" << getUpperName();
852 }
853
Stephen Hines651f13c2014-04-23 16:59:28 -0700854 void writeTemplateInstantiation(raw_ostream &OS) const override {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000855 OS << " " << getType() << " tempInst" << getUpperName() << ";\n";
856 OS << " {\n";
857 OS << " EnterExpressionEvaluationContext "
858 << "Unevaluated(S, Sema::Unevaluated);\n";
859 OS << " ExprResult " << "Result = S.SubstExpr("
860 << "A->get" << getUpperName() << "(), TemplateArgs);\n";
861 OS << " tempInst" << getUpperName() << " = "
862 << "Result.takeAs<Expr>();\n";
863 OS << " }\n";
864 }
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000865
Stephen Hines651f13c2014-04-23 16:59:28 -0700866 void writeDump(raw_ostream &OS) const override {}
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000867
Stephen Hines651f13c2014-04-23 16:59:28 -0700868 void writeDumpChildren(raw_ostream &OS) const override {
Richard Trieue8d41192013-01-31 01:44:26 +0000869 OS << " lastChild();\n";
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000870 OS << " dumpStmt(SA->get" << getUpperName() << "());\n";
871 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700872 void writeHasChildren(raw_ostream &OS) const override { OS << "true"; }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000873 };
874
875 class VariadicExprArgument : public VariadicArgument {
876 public:
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700877 VariadicExprArgument(const Record &Arg, StringRef Attr)
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000878 : VariadicArgument(Arg, Attr, "Expr *")
879 {}
880
Stephen Hines651f13c2014-04-23 16:59:28 -0700881 void writeASTVisitorTraversal(raw_ostream &OS) const override {
882 OS << " {\n";
883 OS << " " << getType() << " *I = A->" << getLowerName()
884 << "_begin();\n";
885 OS << " " << getType() << " *E = A->" << getLowerName()
886 << "_end();\n";
887 OS << " for (; I != E; ++I) {\n";
888 OS << " if (!getDerived().TraverseStmt(*I))\n";
889 OS << " return false;\n";
890 OS << " }\n";
891 OS << " }\n";
892 }
893
894 void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000895 OS << "tempInst" << getUpperName() << ", "
896 << "A->" << getLowerName() << "_size()";
897 }
898
Stephen Hines651f13c2014-04-23 16:59:28 -0700899 void writeTemplateInstantiation(raw_ostream &OS) const override {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000900 OS << " " << getType() << " *tempInst" << getUpperName()
901 << " = new (C, 16) " << getType()
902 << "[A->" << getLowerName() << "_size()];\n";
903 OS << " {\n";
904 OS << " EnterExpressionEvaluationContext "
905 << "Unevaluated(S, Sema::Unevaluated);\n";
906 OS << " " << getType() << " *TI = tempInst" << getUpperName()
907 << ";\n";
908 OS << " " << getType() << " *I = A->" << getLowerName()
909 << "_begin();\n";
910 OS << " " << getType() << " *E = A->" << getLowerName()
911 << "_end();\n";
912 OS << " for (; I != E; ++I, ++TI) {\n";
913 OS << " ExprResult Result = S.SubstExpr(*I, TemplateArgs);\n";
914 OS << " *TI = Result.takeAs<Expr>();\n";
915 OS << " }\n";
916 OS << " }\n";
917 }
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000918
Stephen Hines651f13c2014-04-23 16:59:28 -0700919 void writeDump(raw_ostream &OS) const override {}
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000920
Stephen Hines651f13c2014-04-23 16:59:28 -0700921 void writeDumpChildren(raw_ostream &OS) const override {
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000922 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
923 << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
Richard Trieue8d41192013-01-31 01:44:26 +0000924 << getLowerName() << "_end(); I != E; ++I) {\n";
925 OS << " if (I + 1 == E)\n";
926 OS << " lastChild();\n";
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000927 OS << " dumpStmt(*I);\n";
Richard Trieue8d41192013-01-31 01:44:26 +0000928 OS << " }\n";
929 }
930
Stephen Hines651f13c2014-04-23 16:59:28 -0700931 void writeHasChildren(raw_ostream &OS) const override {
Richard Trieue8d41192013-01-31 01:44:26 +0000932 OS << "SA->" << getLowerName() << "_begin() != "
933 << "SA->" << getLowerName() << "_end()";
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000934 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000935 };
Richard Smithddc2a532013-10-31 21:23:20 +0000936
937 class TypeArgument : public SimpleArgument {
938 public:
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700939 TypeArgument(const Record &Arg, StringRef Attr)
Richard Smithddc2a532013-10-31 21:23:20 +0000940 : SimpleArgument(Arg, Attr, "TypeSourceInfo *")
941 {}
942
Stephen Hines651f13c2014-04-23 16:59:28 -0700943 void writeAccessors(raw_ostream &OS) const override {
Richard Smithddc2a532013-10-31 21:23:20 +0000944 OS << " QualType get" << getUpperName() << "() const {\n";
945 OS << " return " << getLowerName() << "->getType();\n";
946 OS << " }";
947 OS << " " << getType() << " get" << getUpperName() << "Loc() const {\n";
948 OS << " return " << getLowerName() << ";\n";
949 OS << " }";
950 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700951 void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
Richard Smithddc2a532013-10-31 21:23:20 +0000952 OS << "A->get" << getUpperName() << "Loc()";
953 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700954 void writePCHWrite(raw_ostream &OS) const override {
Richard Smithddc2a532013-10-31 21:23:20 +0000955 OS << " " << WritePCHRecord(
956 getType(), "SA->get" + std::string(getUpperName()) + "Loc()");
957 }
958 };
Peter Collingbourne51d77772011-10-06 13:03:08 +0000959}
960
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700961static std::unique_ptr<Argument>
962createArgument(const Record &Arg, StringRef Attr,
963 const Record *Search = nullptr) {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000964 if (!Search)
965 Search = &Arg;
966
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700967 Argument *Ptr = nullptr;
Peter Collingbourne51d77772011-10-06 13:03:08 +0000968 llvm::StringRef ArgName = Search->getName();
969
970 if (ArgName == "AlignedArgument") Ptr = new AlignedArgument(Arg, Attr);
971 else if (ArgName == "EnumArgument") Ptr = new EnumArgument(Arg, Attr);
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000972 else if (ArgName == "ExprArgument") Ptr = new ExprArgument(Arg, Attr);
Peter Collingbourne51d77772011-10-06 13:03:08 +0000973 else if (ArgName == "FunctionArgument")
974 Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *");
975 else if (ArgName == "IdentifierArgument")
976 Ptr = new SimpleArgument(Arg, Attr, "IdentifierInfo *");
Stephen Hines651f13c2014-04-23 16:59:28 -0700977 else if (ArgName == "DefaultBoolArgument")
978 Ptr = new DefaultSimpleArgument(Arg, Attr, "bool",
979 Arg.getValueAsBit("Default"));
Peter Collingbourne51d77772011-10-06 13:03:08 +0000980 else if (ArgName == "BoolArgument") Ptr = new SimpleArgument(Arg, Attr,
981 "bool");
Stephen Hines651f13c2014-04-23 16:59:28 -0700982 else if (ArgName == "DefaultIntArgument")
983 Ptr = new DefaultSimpleArgument(Arg, Attr, "int",
984 Arg.getValueAsInt("Default"));
Peter Collingbourne51d77772011-10-06 13:03:08 +0000985 else if (ArgName == "IntArgument") Ptr = new SimpleArgument(Arg, Attr, "int");
986 else if (ArgName == "StringArgument") Ptr = new StringArgument(Arg, Attr);
Richard Smithddc2a532013-10-31 21:23:20 +0000987 else if (ArgName == "TypeArgument") Ptr = new TypeArgument(Arg, Attr);
Peter Collingbourne51d77772011-10-06 13:03:08 +0000988 else if (ArgName == "UnsignedArgument")
989 Ptr = new SimpleArgument(Arg, Attr, "unsigned");
Peter Collingbourne51d77772011-10-06 13:03:08 +0000990 else if (ArgName == "VariadicUnsignedArgument")
991 Ptr = new VariadicArgument(Arg, Attr, "unsigned");
DeLesley Hutchins66540852013-10-04 21:28:06 +0000992 else if (ArgName == "VariadicEnumArgument")
993 Ptr = new VariadicEnumArgument(Arg, Attr);
Peter Collingbourne51d77772011-10-06 13:03:08 +0000994 else if (ArgName == "VariadicExprArgument")
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000995 Ptr = new VariadicExprArgument(Arg, Attr);
Peter Collingbourne51d77772011-10-06 13:03:08 +0000996 else if (ArgName == "VersionArgument")
997 Ptr = new VersionArgument(Arg, Attr);
998
999 if (!Ptr) {
Stephen Hines651f13c2014-04-23 16:59:28 -07001000 // Search in reverse order so that the most-derived type is handled first.
Peter Collingbourne51d77772011-10-06 13:03:08 +00001001 std::vector<Record*> Bases = Search->getSuperClasses();
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001002 for (const auto *Base : llvm::make_range(Bases.rbegin(), Bases.rend())) {
1003 Ptr = createArgument(Arg, Attr, Base).release();
Peter Collingbourne51d77772011-10-06 13:03:08 +00001004 if (Ptr)
1005 break;
1006 }
1007 }
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00001008
1009 if (Ptr && Arg.getValueAsBit("Optional"))
1010 Ptr->setOptional(true);
1011
Stephen Hines651f13c2014-04-23 16:59:28 -07001012 return std::unique_ptr<Argument>(Ptr);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001013}
1014
Douglas Gregor1bea8802011-11-19 19:22:57 +00001015static void writeAvailabilityValue(raw_ostream &OS) {
1016 OS << "\" << getPlatform()->getName();\n"
1017 << " if (!getIntroduced().empty()) OS << \", introduced=\" << getIntroduced();\n"
1018 << " if (!getDeprecated().empty()) OS << \", deprecated=\" << getDeprecated();\n"
1019 << " if (!getObsoleted().empty()) OS << \", obsoleted=\" << getObsoleted();\n"
1020 << " if (getUnavailable()) OS << \", unavailable\";\n"
1021 << " OS << \"";
1022}
1023
Stephen Hines651f13c2014-04-23 16:59:28 -07001024static void writeGetSpellingFunction(Record &R, raw_ostream &OS) {
1025 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
1026
1027 OS << "const char *" << R.getName() << "Attr::getSpelling() const {\n";
1028 if (Spellings.empty()) {
1029 OS << " return \"(No spelling)\";\n}\n\n";
1030 return;
1031 }
1032
1033 OS << " switch (SpellingListIndex) {\n"
1034 " default:\n"
1035 " llvm_unreachable(\"Unknown attribute spelling!\");\n"
1036 " return \"(No spelling)\";\n";
1037
1038 for (unsigned I = 0; I < Spellings.size(); ++I)
1039 OS << " case " << I << ":\n"
1040 " return \"" << Spellings[I].name() << "\";\n";
1041 // End of the switch statement.
1042 OS << " }\n";
1043 // End of the getSpelling function.
1044 OS << "}\n\n";
1045}
1046
1047static void
1048writePrettyPrintFunction(Record &R,
1049 const std::vector<std::unique_ptr<Argument>> &Args,
1050 raw_ostream &OS) {
1051 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
Michael Han51d8c522013-01-24 16:46:58 +00001052
1053 OS << "void " << R.getName() << "Attr::printPretty("
1054 << "raw_ostream &OS, const PrintingPolicy &Policy) const {\n";
1055
1056 if (Spellings.size() == 0) {
1057 OS << "}\n\n";
1058 return;
1059 }
1060
1061 OS <<
1062 " switch (SpellingListIndex) {\n"
1063 " default:\n"
1064 " llvm_unreachable(\"Unknown attribute spelling!\");\n"
1065 " break;\n";
1066
1067 for (unsigned I = 0; I < Spellings.size(); ++ I) {
1068 llvm::SmallString<16> Prefix;
1069 llvm::SmallString<8> Suffix;
1070 // The actual spelling of the name and namespace (if applicable)
1071 // of an attribute without considering prefix and suffix.
1072 llvm::SmallString<64> Spelling;
Stephen Hines651f13c2014-04-23 16:59:28 -07001073 std::string Name = Spellings[I].name();
1074 std::string Variety = Spellings[I].variety();
Michael Han51d8c522013-01-24 16:46:58 +00001075
1076 if (Variety == "GNU") {
1077 Prefix = " __attribute__((";
1078 Suffix = "))";
1079 } else if (Variety == "CXX11") {
1080 Prefix = " [[";
1081 Suffix = "]]";
Stephen Hines651f13c2014-04-23 16:59:28 -07001082 std::string Namespace = Spellings[I].nameSpace();
Michael Han51d8c522013-01-24 16:46:58 +00001083 if (Namespace != "") {
1084 Spelling += Namespace;
1085 Spelling += "::";
1086 }
1087 } else if (Variety == "Declspec") {
1088 Prefix = " __declspec(";
1089 Suffix = ")";
Richard Smith5cd532c2013-01-29 01:24:26 +00001090 } else if (Variety == "Keyword") {
1091 Prefix = " ";
1092 Suffix = "";
Michael Han51d8c522013-01-24 16:46:58 +00001093 } else {
Richard Smith5cd532c2013-01-29 01:24:26 +00001094 llvm_unreachable("Unknown attribute syntax variety!");
Michael Han51d8c522013-01-24 16:46:58 +00001095 }
1096
1097 Spelling += Name;
1098
1099 OS <<
1100 " case " << I << " : {\n"
1101 " OS << \"" + Prefix.str() + Spelling.str();
1102
Stephen Hines651f13c2014-04-23 16:59:28 -07001103 if (!Args.empty())
1104 OS << "(";
Michael Han51d8c522013-01-24 16:46:58 +00001105 if (Spelling == "availability") {
1106 writeAvailabilityValue(OS);
1107 } else {
Stephen Hines651f13c2014-04-23 16:59:28 -07001108 for (auto I = Args.begin(), E = Args.end(); I != E; ++ I) {
Michael Han51d8c522013-01-24 16:46:58 +00001109 if (I != Args.begin()) OS << ", ";
1110 (*I)->writeValue(OS);
1111 }
1112 }
1113
Stephen Hines651f13c2014-04-23 16:59:28 -07001114 if (!Args.empty())
1115 OS << ")";
Michael Han51d8c522013-01-24 16:46:58 +00001116 OS << Suffix.str() + "\";\n";
1117
1118 OS <<
1119 " break;\n"
1120 " }\n";
1121 }
1122
1123 // End of the switch statement.
1124 OS << "}\n";
1125 // End of the print function.
1126 OS << "}\n\n";
1127}
1128
Michael Hana31f65b2013-02-01 01:19:17 +00001129/// \brief Return the index of a spelling in a spelling list.
Stephen Hines651f13c2014-04-23 16:59:28 -07001130static unsigned
1131getSpellingListIndex(const std::vector<FlattenedSpelling> &SpellingList,
1132 const FlattenedSpelling &Spelling) {
Michael Hana31f65b2013-02-01 01:19:17 +00001133 assert(SpellingList.size() && "Spelling list is empty!");
1134
1135 for (unsigned Index = 0; Index < SpellingList.size(); ++Index) {
Stephen Hines651f13c2014-04-23 16:59:28 -07001136 const FlattenedSpelling &S = SpellingList[Index];
1137 if (S.variety() != Spelling.variety())
Michael Hana31f65b2013-02-01 01:19:17 +00001138 continue;
Stephen Hines651f13c2014-04-23 16:59:28 -07001139 if (S.nameSpace() != Spelling.nameSpace())
Michael Hana31f65b2013-02-01 01:19:17 +00001140 continue;
Stephen Hines651f13c2014-04-23 16:59:28 -07001141 if (S.name() != Spelling.name())
Michael Hana31f65b2013-02-01 01:19:17 +00001142 continue;
1143
1144 return Index;
1145 }
1146
1147 llvm_unreachable("Unknown spelling!");
1148}
1149
Stephen Hines651f13c2014-04-23 16:59:28 -07001150static void writeAttrAccessorDefinition(const Record &R, raw_ostream &OS) {
Michael Hana31f65b2013-02-01 01:19:17 +00001151 std::vector<Record*> Accessors = R.getValueAsListOfDefs("Accessors");
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001152 for (const auto *Accessor : Accessors) {
Michael Hana31f65b2013-02-01 01:19:17 +00001153 std::string Name = Accessor->getValueAsString("Name");
Stephen Hines651f13c2014-04-23 16:59:28 -07001154 std::vector<FlattenedSpelling> Spellings =
1155 GetFlattenedSpellings(*Accessor);
1156 std::vector<FlattenedSpelling> SpellingList = GetFlattenedSpellings(R);
Michael Hana31f65b2013-02-01 01:19:17 +00001157 assert(SpellingList.size() &&
1158 "Attribute with empty spelling list can't have accessors!");
1159
1160 OS << " bool " << Name << "() const { return SpellingListIndex == ";
1161 for (unsigned Index = 0; Index < Spellings.size(); ++Index) {
Stephen Hines651f13c2014-04-23 16:59:28 -07001162 OS << getSpellingListIndex(SpellingList, Spellings[Index]);
Michael Hana31f65b2013-02-01 01:19:17 +00001163 if (Index != Spellings.size() -1)
1164 OS << " ||\n SpellingListIndex == ";
1165 else
1166 OS << "; }\n";
1167 }
1168 }
1169}
1170
Stephen Hines651f13c2014-04-23 16:59:28 -07001171static bool
1172SpellingNamesAreCommon(const std::vector<FlattenedSpelling>& Spellings) {
1173 assert(!Spellings.empty() && "An empty list of spellings was provided");
1174 std::string FirstName = NormalizeNameForSpellingComparison(
1175 Spellings.front().name());
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001176 for (const auto &Spelling :
1177 llvm::make_range(std::next(Spellings.begin()), Spellings.end())) {
1178 std::string Name = NormalizeNameForSpellingComparison(Spelling.name());
Stephen Hines651f13c2014-04-23 16:59:28 -07001179 if (Name != FirstName)
1180 return false;
1181 }
1182 return true;
1183}
1184
1185typedef std::map<unsigned, std::string> SemanticSpellingMap;
1186static std::string
1187CreateSemanticSpellings(const std::vector<FlattenedSpelling> &Spellings,
1188 SemanticSpellingMap &Map) {
1189 // The enumerants are automatically generated based on the variety,
1190 // namespace (if present) and name for each attribute spelling. However,
1191 // care is taken to avoid trampling on the reserved namespace due to
1192 // underscores.
1193 std::string Ret(" enum Spelling {\n");
1194 std::set<std::string> Uniques;
1195 unsigned Idx = 0;
1196 for (auto I = Spellings.begin(), E = Spellings.end(); I != E; ++I, ++Idx) {
1197 const FlattenedSpelling &S = *I;
1198 std::string Variety = S.variety();
1199 std::string Spelling = S.name();
1200 std::string Namespace = S.nameSpace();
1201 std::string EnumName = "";
1202
1203 EnumName += (Variety + "_");
1204 if (!Namespace.empty())
1205 EnumName += (NormalizeNameForSpellingComparison(Namespace).str() +
1206 "_");
1207 EnumName += NormalizeNameForSpellingComparison(Spelling);
1208
1209 // Even if the name is not unique, this spelling index corresponds to a
1210 // particular enumerant name that we've calculated.
1211 Map[Idx] = EnumName;
1212
1213 // Since we have been stripping underscores to avoid trampling on the
1214 // reserved namespace, we may have inadvertently created duplicate
1215 // enumerant names. These duplicates are not considered part of the
1216 // semantic spelling, and can be elided.
1217 if (Uniques.find(EnumName) != Uniques.end())
1218 continue;
1219
1220 Uniques.insert(EnumName);
1221 if (I != Spellings.begin())
1222 Ret += ",\n";
1223 Ret += " " + EnumName;
1224 }
1225 Ret += "\n };\n\n";
1226 return Ret;
1227}
1228
1229void WriteSemanticSpellingSwitch(const std::string &VarName,
1230 const SemanticSpellingMap &Map,
1231 raw_ostream &OS) {
1232 OS << " switch (" << VarName << ") {\n default: "
1233 << "llvm_unreachable(\"Unknown spelling list index\");\n";
1234 for (const auto &I : Map)
1235 OS << " case " << I.first << ": return " << I.second << ";\n";
1236 OS << " }\n";
1237}
1238
1239// Emits the LateParsed property for attributes.
1240static void emitClangAttrLateParsedList(RecordKeeper &Records, raw_ostream &OS) {
1241 OS << "#if defined(CLANG_ATTR_LATE_PARSED_LIST)\n";
1242 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1243
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001244 for (const auto *Attr : Attrs) {
Stephen Hines651f13c2014-04-23 16:59:28 -07001245 bool LateParsed = Attr->getValueAsBit("LateParsed");
1246
1247 if (LateParsed) {
1248 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr);
1249
1250 // FIXME: Handle non-GNU attributes
1251 for (const auto &I : Spellings) {
1252 if (I.variety() != "GNU")
1253 continue;
1254 OS << ".Case(\"" << I.name() << "\", " << LateParsed << ")\n";
1255 }
1256 }
1257 }
1258 OS << "#endif // CLANG_ATTR_LATE_PARSED_LIST\n\n";
1259}
1260
1261/// \brief Emits the first-argument-is-type property for attributes.
1262static void emitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) {
1263 OS << "#if defined(CLANG_ATTR_TYPE_ARG_LIST)\n";
1264 std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
1265
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001266 for (const auto *Attr : Attrs) {
Stephen Hines651f13c2014-04-23 16:59:28 -07001267 // Determine whether the first argument is a type.
1268 std::vector<Record *> Args = Attr->getValueAsListOfDefs("Args");
1269 if (Args.empty())
1270 continue;
1271
1272 if (Args[0]->getSuperClasses().back()->getName() != "TypeArgument")
1273 continue;
1274
1275 // All these spellings take a single type argument.
1276 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr);
1277 std::set<std::string> Emitted;
1278 for (const auto &S : Spellings) {
1279 if (Emitted.insert(S.name()).second)
1280 OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n";
1281 }
1282 }
1283 OS << "#endif // CLANG_ATTR_TYPE_ARG_LIST\n\n";
1284}
1285
1286/// \brief Emits the parse-arguments-in-unevaluated-context property for
1287/// attributes.
1288static void emitClangAttrArgContextList(RecordKeeper &Records, raw_ostream &OS) {
1289 OS << "#if defined(CLANG_ATTR_ARG_CONTEXT_LIST)\n";
1290 ParsedAttrMap Attrs = getParsedAttrList(Records);
1291 for (const auto &I : Attrs) {
1292 const Record &Attr = *I.second;
1293
1294 if (!Attr.getValueAsBit("ParseArgumentsAsUnevaluated"))
1295 continue;
1296
1297 // All these spellings take are parsed unevaluated.
1298 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
1299 std::set<std::string> Emitted;
1300 for (const auto &S : Spellings) {
1301 if (Emitted.insert(S.name()).second)
1302 OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n";
1303 }
1304 }
1305 OS << "#endif // CLANG_ATTR_ARG_CONTEXT_LIST\n\n";
1306}
1307
1308static bool isIdentifierArgument(Record *Arg) {
1309 return !Arg->getSuperClasses().empty() &&
1310 llvm::StringSwitch<bool>(Arg->getSuperClasses().back()->getName())
1311 .Case("IdentifierArgument", true)
1312 .Case("EnumArgument", true)
1313 .Default(false);
1314}
1315
1316// Emits the first-argument-is-identifier property for attributes.
1317static void emitClangAttrIdentifierArgList(RecordKeeper &Records, raw_ostream &OS) {
1318 OS << "#if defined(CLANG_ATTR_IDENTIFIER_ARG_LIST)\n";
1319 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1320
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001321 for (const auto *Attr : Attrs) {
Stephen Hines651f13c2014-04-23 16:59:28 -07001322 // Determine whether the first argument is an identifier.
1323 std::vector<Record *> Args = Attr->getValueAsListOfDefs("Args");
1324 if (Args.empty() || !isIdentifierArgument(Args[0]))
1325 continue;
1326
1327 // All these spellings take an identifier argument.
1328 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr);
1329 std::set<std::string> Emitted;
1330 for (const auto &S : Spellings) {
1331 if (Emitted.insert(S.name()).second)
1332 OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n";
1333 }
1334 }
1335 OS << "#endif // CLANG_ATTR_IDENTIFIER_ARG_LIST\n\n";
1336}
1337
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001338namespace clang {
1339
1340// Emits the class definitions for attributes.
1341void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00001342 emitSourceFileHeader("Attribute classes' definitions", OS);
1343
Peter Collingbourne51d77772011-10-06 13:03:08 +00001344 OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
1345 OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
1346
1347 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1348
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001349 for (const auto *Attr : Attrs) {
1350 const Record &R = *Attr;
Stephen Hines651f13c2014-04-23 16:59:28 -07001351
1352 // FIXME: Currently, documentation is generated as-needed due to the fact
1353 // that there is no way to allow a generated project "reach into" the docs
1354 // directory (for instance, it may be an out-of-tree build). However, we want
1355 // to ensure that every attribute has a Documentation field, and produce an
1356 // error if it has been neglected. Otherwise, the on-demand generation which
1357 // happens server-side will fail. This code is ensuring that functionality,
1358 // even though this Emitter doesn't technically need the documentation.
1359 // When attribute documentation can be generated as part of the build
1360 // itself, this code can be removed.
1361 (void)R.getValueAsListOfDefs("Documentation");
Douglas Gregor3e7d31a2012-05-02 15:56:52 +00001362
1363 if (!R.getValueAsBit("ASTNode"))
1364 continue;
1365
Aaron Ballman201bddc2013-07-30 01:44:15 +00001366 const std::vector<Record *> Supers = R.getSuperClasses();
1367 assert(!Supers.empty() && "Forgot to specify a superclass for the attr");
Aaron Ballman201bddc2013-07-30 01:44:15 +00001368 std::string SuperName;
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001369 for (const auto *Super : llvm::make_range(Supers.rbegin(), Supers.rend())) {
1370 const Record &R = *Super;
Aaron Ballmance756522013-07-31 02:20:22 +00001371 if (R.getName() != "TargetSpecificAttr" && SuperName.empty())
Aaron Ballman201bddc2013-07-30 01:44:15 +00001372 SuperName = R.getName();
1373 }
Peter Collingbourne51d77772011-10-06 13:03:08 +00001374
1375 OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n";
1376
1377 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
Stephen Hines651f13c2014-04-23 16:59:28 -07001378 std::vector<std::unique_ptr<Argument>> Args;
Peter Collingbourne51d77772011-10-06 13:03:08 +00001379 Args.reserve(ArgRecords.size());
1380
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001381 for (const auto *ArgRecord : ArgRecords) {
Stephen Hines651f13c2014-04-23 16:59:28 -07001382 Args.emplace_back(createArgument(*ArgRecord, R.getName()));
1383 Args.back()->writeDeclarations(OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001384 OS << "\n\n";
1385 }
1386
Stephen Hines651f13c2014-04-23 16:59:28 -07001387 OS << "\npublic:\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +00001388
Stephen Hines651f13c2014-04-23 16:59:28 -07001389 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
1390
1391 // If there are zero or one spellings, all spelling-related functionality
1392 // can be elided. If all of the spellings share the same name, the spelling
1393 // functionality can also be elided.
1394 bool ElideSpelling = (Spellings.size() <= 1) ||
1395 SpellingNamesAreCommon(Spellings);
1396
1397 // This maps spelling index values to semantic Spelling enumerants.
1398 SemanticSpellingMap SemanticToSyntacticMap;
1399
1400 if (!ElideSpelling)
1401 OS << CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);
1402
1403 OS << " static " << R.getName() << "Attr *CreateImplicit(";
1404 OS << "ASTContext &Ctx";
1405 if (!ElideSpelling)
1406 OS << ", Spelling S";
1407 for (auto const &ai : Args) {
1408 OS << ", ";
1409 ai->writeCtorParameters(OS);
1410 }
1411 OS << ", SourceRange Loc = SourceRange()";
1412 OS << ") {\n";
1413 OS << " " << R.getName() << "Attr *A = new (Ctx) " << R.getName();
1414 OS << "Attr(Loc, Ctx, ";
1415 for (auto const &ai : Args) {
1416 ai->writeImplicitCtorArgs(OS);
1417 OS << ", ";
1418 }
1419 OS << (ElideSpelling ? "0" : "S") << ");\n";
1420 OS << " A->setImplicit(true);\n";
1421 OS << " return A;\n }\n\n";
1422
Peter Collingbourne51d77772011-10-06 13:03:08 +00001423 OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
1424
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00001425 bool HasOpt = false;
Stephen Hines651f13c2014-04-23 16:59:28 -07001426 for (auto const &ai : Args) {
Peter Collingbourne51d77772011-10-06 13:03:08 +00001427 OS << " , ";
Stephen Hines651f13c2014-04-23 16:59:28 -07001428 ai->writeCtorParameters(OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001429 OS << "\n";
Stephen Hines651f13c2014-04-23 16:59:28 -07001430 if (ai->isOptional())
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00001431 HasOpt = true;
Peter Collingbourne51d77772011-10-06 13:03:08 +00001432 }
Michael Han51d8c522013-01-24 16:46:58 +00001433
1434 OS << " , ";
Stephen Hines651f13c2014-04-23 16:59:28 -07001435 OS << "unsigned SI\n";
Michael Han51d8c522013-01-24 16:46:58 +00001436
Peter Collingbourne51d77772011-10-06 13:03:08 +00001437 OS << " )\n";
Michael Han51d8c522013-01-24 16:46:58 +00001438 OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +00001439
Stephen Hines651f13c2014-04-23 16:59:28 -07001440 for (auto const &ai : Args) {
Peter Collingbourne51d77772011-10-06 13:03:08 +00001441 OS << " , ";
Stephen Hines651f13c2014-04-23 16:59:28 -07001442 ai->writeCtorInitializers(OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001443 OS << "\n";
1444 }
1445
1446 OS << " {\n";
1447
Stephen Hines651f13c2014-04-23 16:59:28 -07001448 for (auto const &ai : Args) {
1449 ai->writeCtorBody(OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001450 OS << "\n";
1451 }
1452 OS << " }\n\n";
1453
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00001454 // If there are optional arguments, write out a constructor that elides the
1455 // optional arguments as well.
1456 if (HasOpt) {
1457 OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
Stephen Hines651f13c2014-04-23 16:59:28 -07001458 for (auto const &ai : Args) {
1459 if (!ai->isOptional()) {
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00001460 OS << " , ";
Stephen Hines651f13c2014-04-23 16:59:28 -07001461 ai->writeCtorParameters(OS);
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00001462 OS << "\n";
1463 }
1464 }
1465
1466 OS << " , ";
Stephen Hines651f13c2014-04-23 16:59:28 -07001467 OS << "unsigned SI\n";
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00001468
1469 OS << " )\n";
1470 OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n";
1471
Stephen Hines651f13c2014-04-23 16:59:28 -07001472 for (auto const &ai : Args) {
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00001473 OS << " , ";
Stephen Hines651f13c2014-04-23 16:59:28 -07001474 ai->writeCtorDefaultInitializers(OS);
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00001475 OS << "\n";
1476 }
1477
1478 OS << " {\n";
1479
Stephen Hines651f13c2014-04-23 16:59:28 -07001480 for (auto const &ai : Args) {
1481 if (!ai->isOptional()) {
1482 ai->writeCtorBody(OS);
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00001483 OS << "\n";
1484 }
1485 }
1486 OS << " }\n\n";
1487 }
1488
Stephen Hines651f13c2014-04-23 16:59:28 -07001489 OS << " " << R.getName() << "Attr *clone(ASTContext &C) const override;\n";
1490 OS << " void printPretty(raw_ostream &OS,\n"
1491 << " const PrintingPolicy &Policy) const override;\n";
1492 OS << " const char *getSpelling() const override;\n";
1493
1494 if (!ElideSpelling) {
1495 assert(!SemanticToSyntacticMap.empty() && "Empty semantic mapping list");
1496 OS << " Spelling getSemanticSpelling() const {\n";
1497 WriteSemanticSpellingSwitch("SpellingListIndex", SemanticToSyntacticMap,
1498 OS);
1499 OS << " }\n";
1500 }
Peter Collingbourne51d77772011-10-06 13:03:08 +00001501
Michael Hana31f65b2013-02-01 01:19:17 +00001502 writeAttrAccessorDefinition(R, OS);
1503
Stephen Hines651f13c2014-04-23 16:59:28 -07001504 for (auto const &ai : Args) {
1505 ai->writeAccessors(OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001506 OS << "\n\n";
Aaron Ballmand0686072013-09-11 19:47:58 +00001507
Stephen Hines651f13c2014-04-23 16:59:28 -07001508 if (ai->isEnumArg())
1509 static_cast<const EnumArgument *>(ai.get())->writeConversion(OS);
1510 else if (ai->isVariadicEnumArg())
1511 static_cast<const VariadicEnumArgument *>(ai.get())
1512 ->writeConversion(OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001513 }
1514
Jakob Stoklund Oleseneb666732012-01-13 04:57:47 +00001515 OS << R.getValueAsString("AdditionalMembers");
Peter Collingbourne51d77772011-10-06 13:03:08 +00001516 OS << "\n\n";
1517
1518 OS << " static bool classof(const Attr *A) { return A->getKind() == "
1519 << "attr::" << R.getName() << "; }\n";
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001520
1521 bool LateParsed = R.getValueAsBit("LateParsed");
Stephen Hines651f13c2014-04-23 16:59:28 -07001522 OS << " bool isLateParsed() const override { return "
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001523 << LateParsed << "; }\n";
1524
Stephen Hines651f13c2014-04-23 16:59:28 -07001525 if (R.getValueAsBit("DuplicatesAllowedWhileMerging"))
1526 OS << " bool duplicatesAllowed() const override { return true; }\n\n";
1527
Peter Collingbourne51d77772011-10-06 13:03:08 +00001528 OS << "};\n\n";
1529 }
1530
1531 OS << "#endif\n";
1532}
1533
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001534// Emits the class method definitions for attributes.
1535void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00001536 emitSourceFileHeader("Attribute classes' member function definitions", OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001537
1538 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
Peter Collingbourne51d77772011-10-06 13:03:08 +00001539
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001540 for (auto *Attr : Attrs) {
1541 Record &R = *Attr;
Douglas Gregor3e7d31a2012-05-02 15:56:52 +00001542
1543 if (!R.getValueAsBit("ASTNode"))
1544 continue;
Peter Collingbourne51d77772011-10-06 13:03:08 +00001545
Stephen Hines651f13c2014-04-23 16:59:28 -07001546 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
1547 std::vector<std::unique_ptr<Argument>> Args;
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001548 for (const auto *Arg : ArgRecords)
1549 Args.emplace_back(createArgument(*Arg, R.getName()));
Stephen Hines651f13c2014-04-23 16:59:28 -07001550
1551 for (auto const &ai : Args)
1552 ai->writeAccessorDefinitions(OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001553
1554 OS << R.getName() << "Attr *" << R.getName()
1555 << "Attr::clone(ASTContext &C) const {\n";
1556 OS << " return new (C) " << R.getName() << "Attr(getLocation(), C";
Stephen Hines651f13c2014-04-23 16:59:28 -07001557 for (auto const &ai : Args) {
Peter Collingbourne51d77772011-10-06 13:03:08 +00001558 OS << ", ";
Stephen Hines651f13c2014-04-23 16:59:28 -07001559 ai->writeCloneArgs(OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001560 }
Richard Smith8f3aacc2013-01-29 04:21:28 +00001561 OS << ", getSpellingListIndex());\n}\n\n";
Douglas Gregor1bea8802011-11-19 19:22:57 +00001562
Michael Han51d8c522013-01-24 16:46:58 +00001563 writePrettyPrintFunction(R, Args, OS);
Stephen Hines651f13c2014-04-23 16:59:28 -07001564 writeGetSpellingFunction(R, OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001565 }
1566}
1567
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001568} // end namespace clang
1569
Peter Collingbourne51d77772011-10-06 13:03:08 +00001570static void EmitAttrList(raw_ostream &OS, StringRef Class,
1571 const std::vector<Record*> &AttrList) {
1572 std::vector<Record*>::const_iterator i = AttrList.begin(), e = AttrList.end();
1573
1574 if (i != e) {
1575 // Move the end iterator back to emit the last attribute.
Douglas Gregor3e7d31a2012-05-02 15:56:52 +00001576 for(--e; i != e; ++i) {
1577 if (!(*i)->getValueAsBit("ASTNode"))
1578 continue;
1579
Peter Collingbourne51d77772011-10-06 13:03:08 +00001580 OS << Class << "(" << (*i)->getName() << ")\n";
Douglas Gregor3e7d31a2012-05-02 15:56:52 +00001581 }
Peter Collingbourne51d77772011-10-06 13:03:08 +00001582
1583 OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n";
1584 }
1585}
1586
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001587namespace clang {
1588
1589// Emits the enumeration list for attributes.
1590void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00001591 emitSourceFileHeader("List of all attributes that Clang recognizes", OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001592
1593 OS << "#ifndef LAST_ATTR\n";
1594 OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n";
1595 OS << "#endif\n\n";
1596
1597 OS << "#ifndef INHERITABLE_ATTR\n";
1598 OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n";
1599 OS << "#endif\n\n";
1600
1601 OS << "#ifndef LAST_INHERITABLE_ATTR\n";
1602 OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n";
1603 OS << "#endif\n\n";
1604
1605 OS << "#ifndef INHERITABLE_PARAM_ATTR\n";
1606 OS << "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n";
1607 OS << "#endif\n\n";
1608
1609 OS << "#ifndef LAST_INHERITABLE_PARAM_ATTR\n";
1610 OS << "#define LAST_INHERITABLE_PARAM_ATTR(NAME)"
1611 " INHERITABLE_PARAM_ATTR(NAME)\n";
1612 OS << "#endif\n\n";
1613
1614 Record *InhClass = Records.getClass("InheritableAttr");
1615 Record *InhParamClass = Records.getClass("InheritableParamAttr");
1616 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
Stephen Hines651f13c2014-04-23 16:59:28 -07001617 NonInhAttrs, InhAttrs, InhParamAttrs;
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001618 for (auto *Attr : Attrs) {
1619 if (!Attr->getValueAsBit("ASTNode"))
Douglas Gregor3e7d31a2012-05-02 15:56:52 +00001620 continue;
1621
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001622 if (Attr->isSubClassOf(InhParamClass))
1623 InhParamAttrs.push_back(Attr);
1624 else if (Attr->isSubClassOf(InhClass))
1625 InhAttrs.push_back(Attr);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001626 else
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001627 NonInhAttrs.push_back(Attr);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001628 }
1629
1630 EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs);
1631 EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs);
1632 EmitAttrList(OS, "ATTR", NonInhAttrs);
1633
1634 OS << "#undef LAST_ATTR\n";
1635 OS << "#undef INHERITABLE_ATTR\n";
1636 OS << "#undef LAST_INHERITABLE_ATTR\n";
1637 OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n";
1638 OS << "#undef ATTR\n";
1639}
1640
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001641// Emits the code to read an attribute from a precompiled header.
1642void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00001643 emitSourceFileHeader("Attribute deserialization code", OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001644
1645 Record *InhClass = Records.getClass("InheritableAttr");
1646 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
1647 ArgRecords;
Stephen Hines651f13c2014-04-23 16:59:28 -07001648 std::vector<std::unique_ptr<Argument>> Args;
Peter Collingbourne51d77772011-10-06 13:03:08 +00001649
1650 OS << " switch (Kind) {\n";
1651 OS << " default:\n";
1652 OS << " assert(0 && \"Unknown attribute!\");\n";
1653 OS << " break;\n";
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001654 for (const auto *Attr : Attrs) {
1655 const Record &R = *Attr;
Douglas Gregor3e7d31a2012-05-02 15:56:52 +00001656 if (!R.getValueAsBit("ASTNode"))
1657 continue;
1658
Peter Collingbourne51d77772011-10-06 13:03:08 +00001659 OS << " case attr::" << R.getName() << ": {\n";
1660 if (R.isSubClassOf(InhClass))
1661 OS << " bool isInherited = Record[Idx++];\n";
Stephen Hines651f13c2014-04-23 16:59:28 -07001662 OS << " bool isImplicit = Record[Idx++];\n";
1663 OS << " unsigned Spelling = Record[Idx++];\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +00001664 ArgRecords = R.getValueAsListOfDefs("Args");
1665 Args.clear();
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001666 for (const auto *Arg : ArgRecords) {
1667 Args.emplace_back(createArgument(*Arg, R.getName()));
Stephen Hines651f13c2014-04-23 16:59:28 -07001668 Args.back()->writePCHReadDecls(OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001669 }
1670 OS << " New = new (Context) " << R.getName() << "Attr(Range, Context";
Stephen Hines651f13c2014-04-23 16:59:28 -07001671 for (auto const &ri : Args) {
Peter Collingbourne51d77772011-10-06 13:03:08 +00001672 OS << ", ";
Stephen Hines651f13c2014-04-23 16:59:28 -07001673 ri->writePCHReadArgs(OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001674 }
Stephen Hines651f13c2014-04-23 16:59:28 -07001675 OS << ", Spelling);\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +00001676 if (R.isSubClassOf(InhClass))
1677 OS << " cast<InheritableAttr>(New)->setInherited(isInherited);\n";
Stephen Hines651f13c2014-04-23 16:59:28 -07001678 OS << " New->setImplicit(isImplicit);\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +00001679 OS << " break;\n";
1680 OS << " }\n";
1681 }
1682 OS << " }\n";
1683}
1684
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001685// Emits the code to write an attribute to a precompiled header.
1686void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00001687 emitSourceFileHeader("Attribute serialization code", OS);
1688
Peter Collingbourne51d77772011-10-06 13:03:08 +00001689 Record *InhClass = Records.getClass("InheritableAttr");
1690 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
Peter Collingbourne51d77772011-10-06 13:03:08 +00001691
1692 OS << " switch (A->getKind()) {\n";
1693 OS << " default:\n";
1694 OS << " llvm_unreachable(\"Unknown attribute kind!\");\n";
1695 OS << " break;\n";
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001696 for (const auto *Attr : Attrs) {
1697 const Record &R = *Attr;
Douglas Gregor3e7d31a2012-05-02 15:56:52 +00001698 if (!R.getValueAsBit("ASTNode"))
1699 continue;
Peter Collingbourne51d77772011-10-06 13:03:08 +00001700 OS << " case attr::" << R.getName() << ": {\n";
1701 Args = R.getValueAsListOfDefs("Args");
1702 if (R.isSubClassOf(InhClass) || !Args.empty())
1703 OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
1704 << "Attr>(A);\n";
1705 if (R.isSubClassOf(InhClass))
1706 OS << " Record.push_back(SA->isInherited());\n";
Stephen Hines651f13c2014-04-23 16:59:28 -07001707 OS << " Record.push_back(A->isImplicit());\n";
1708 OS << " Record.push_back(A->getSpellingListIndex());\n";
1709
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001710 for (const auto *Arg : Args)
1711 createArgument(*Arg, R.getName())->writePCHWrite(OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001712 OS << " break;\n";
1713 OS << " }\n";
1714 }
1715 OS << " }\n";
1716}
1717
Stephen Hines651f13c2014-04-23 16:59:28 -07001718static void GenerateHasAttrSpellingStringSwitch(
1719 const std::vector<Record *> &Attrs, raw_ostream &OS,
1720 const std::string &Variety = "", const std::string &Scope = "") {
1721 for (const auto *Attr : Attrs) {
1722 // It is assumed that there will be an llvm::Triple object named T within
1723 // scope that can be used to determine whether the attribute exists in
1724 // a given target.
1725 std::string Test;
1726 if (Attr->isSubClassOf("TargetSpecificAttr")) {
1727 const Record *R = Attr->getValueAsDef("Target");
1728 std::vector<std::string> Arches = R->getValueAsListOfStrings("Arches");
1729
1730 Test += "(";
1731 for (auto AI = Arches.begin(), AE = Arches.end(); AI != AE; ++AI) {
1732 std::string Part = *AI;
1733 Test += "T.getArch() == llvm::Triple::" + Part;
1734 if (AI + 1 != AE)
1735 Test += " || ";
1736 }
1737 Test += ")";
1738
1739 std::vector<std::string> OSes;
1740 if (!R->isValueUnset("OSes")) {
1741 Test += " && (";
1742 std::vector<std::string> OSes = R->getValueAsListOfStrings("OSes");
1743 for (auto AI = OSes.begin(), AE = OSes.end(); AI != AE; ++AI) {
1744 std::string Part = *AI;
1745
1746 Test += "T.getOS() == llvm::Triple::" + Part;
1747 if (AI + 1 != AE)
1748 Test += " || ";
1749 }
1750 Test += ")";
1751 }
1752
1753 // If this is the C++11 variety, also add in the LangOpts test.
1754 if (Variety == "CXX11")
1755 Test += " && LangOpts.CPlusPlus11";
1756 } else if (Variety == "CXX11")
1757 // C++11 mode should be checked against LangOpts, which is presumed to be
1758 // present in the caller.
1759 Test = "LangOpts.CPlusPlus11";
1760 else
1761 Test = "true";
1762
1763 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr);
1764 for (const auto &S : Spellings)
1765 if (Variety.empty() || (Variety == S.variety() &&
1766 (Scope.empty() || Scope == S.nameSpace())))
1767 OS << " .Case(\"" << S.name() << "\", " << Test << ")\n";
1768 }
1769 OS << " .Default(false);\n";
1770}
1771
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001772// Emits the list of spellings for attributes.
Stephen Hines651f13c2014-04-23 16:59:28 -07001773void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
1774 emitSourceFileHeader("Code to implement the __has_attribute logic", OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001775
Stephen Hines651f13c2014-04-23 16:59:28 -07001776 // Separate all of the attributes out into four group: generic, C++11, GNU,
1777 // and declspecs. Then generate a big switch statement for each of them.
1778 std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
1779 std::vector<Record *> Declspec, GNU;
1780 std::map<std::string, std::vector<Record *>> CXX;
Peter Collingbourne51d77772011-10-06 13:03:08 +00001781
Stephen Hines651f13c2014-04-23 16:59:28 -07001782 // Walk over the list of all attributes, and split them out based on the
1783 // spelling variety.
1784 for (auto *R : Attrs) {
1785 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*R);
1786 for (const auto &SI : Spellings) {
1787 std::string Variety = SI.variety();
1788 if (Variety == "GNU")
1789 GNU.push_back(R);
1790 else if (Variety == "Declspec")
1791 Declspec.push_back(R);
1792 else if (Variety == "CXX11") {
1793 CXX[SI.nameSpace()].push_back(R);
1794 }
Peter Collingbourne51d77772011-10-06 13:03:08 +00001795 }
1796 }
1797
Stephen Hines651f13c2014-04-23 16:59:28 -07001798 OS << "switch (Syntax) {\n";
1799 OS << "case AttrSyntax::Generic:\n";
1800 OS << " return llvm::StringSwitch<bool>(Name)\n";
1801 GenerateHasAttrSpellingStringSwitch(Attrs, OS);
1802 OS << "case AttrSyntax::GNU:\n";
1803 OS << " return llvm::StringSwitch<bool>(Name)\n";
1804 GenerateHasAttrSpellingStringSwitch(GNU, OS, "GNU");
1805 OS << "case AttrSyntax::Declspec:\n";
1806 OS << " return llvm::StringSwitch<bool>(Name)\n";
1807 GenerateHasAttrSpellingStringSwitch(Declspec, OS, "Declspec");
1808 OS << "case AttrSyntax::CXX: {\n";
1809 // C++11-style attributes are further split out based on the Scope.
1810 for (std::map<std::string, std::vector<Record *>>::iterator I = CXX.begin(),
1811 E = CXX.end();
1812 I != E; ++I) {
1813 if (I != CXX.begin())
1814 OS << " else ";
1815 if (I->first.empty())
1816 OS << "if (!Scope || Scope->getName() == \"\") {\n";
1817 else
1818 OS << "if (Scope->getName() == \"" << I->first << "\") {\n";
1819 OS << " return llvm::StringSwitch<bool>(Name)\n";
1820 GenerateHasAttrSpellingStringSwitch(I->second, OS, "CXX11", I->first);
1821 OS << "}";
1822 }
1823 OS << "\n}\n";
1824 OS << "}\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +00001825}
1826
Michael Han51d8c522013-01-24 16:46:58 +00001827void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00001828 emitSourceFileHeader("Code to translate different attribute spellings "
1829 "into internal identifiers", OS);
Michael Han51d8c522013-01-24 16:46:58 +00001830
1831 OS <<
Michael Han51d8c522013-01-24 16:46:58 +00001832 " switch (AttrKind) {\n"
1833 " default:\n"
1834 " llvm_unreachable(\"Unknown attribute kind!\");\n"
1835 " break;\n";
1836
Stephen Hines651f13c2014-04-23 16:59:28 -07001837 ParsedAttrMap Attrs = getParsedAttrList(Records);
1838 for (const auto &I : Attrs) {
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001839 const Record &R = *I.second;
Stephen Hines651f13c2014-04-23 16:59:28 -07001840 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
1841 OS << " case AT_" << I.first << ": {\n";
1842 for (unsigned I = 0; I < Spellings.size(); ++ I) {
1843 OS << " if (Name == \""
1844 << Spellings[I].name() << "\" && "
1845 << "SyntaxUsed == "
1846 << StringSwitch<unsigned>(Spellings[I].variety())
1847 .Case("GNU", 0)
1848 .Case("CXX11", 1)
1849 .Case("Declspec", 2)
1850 .Case("Keyword", 3)
1851 .Default(0)
1852 << " && Scope == \"" << Spellings[I].nameSpace() << "\")\n"
1853 << " return " << I << ";\n";
Michael Han51d8c522013-01-24 16:46:58 +00001854 }
Stephen Hines651f13c2014-04-23 16:59:28 -07001855
1856 OS << " break;\n";
1857 OS << " }\n";
Michael Han51d8c522013-01-24 16:46:58 +00001858 }
1859
1860 OS << " }\n";
Stephen Hines651f13c2014-04-23 16:59:28 -07001861 OS << " return 0;\n";
Michael Han51d8c522013-01-24 16:46:58 +00001862}
1863
Stephen Hines651f13c2014-04-23 16:59:28 -07001864// Emits code used by RecursiveASTVisitor to visit attributes
1865void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS) {
1866 emitSourceFileHeader("Used by RecursiveASTVisitor to visit attributes.", OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001867
1868 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1869
Stephen Hines651f13c2014-04-23 16:59:28 -07001870 // Write method declarations for Traverse* methods.
1871 // We emit this here because we only generate methods for attributes that
1872 // are declared as ASTNodes.
1873 OS << "#ifdef ATTR_VISITOR_DECLS_ONLY\n\n";
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001874 for (const auto *Attr : Attrs) {
1875 const Record &R = *Attr;
Stephen Hines651f13c2014-04-23 16:59:28 -07001876 if (!R.getValueAsBit("ASTNode"))
1877 continue;
1878 OS << " bool Traverse"
1879 << R.getName() << "Attr(" << R.getName() << "Attr *A);\n";
1880 OS << " bool Visit"
1881 << R.getName() << "Attr(" << R.getName() << "Attr *A) {\n"
1882 << " return true; \n"
1883 << " };\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +00001884 }
Stephen Hines651f13c2014-04-23 16:59:28 -07001885 OS << "\n#else // ATTR_VISITOR_DECLS_ONLY\n\n";
1886
1887 // Write individual Traverse* methods for each attribute class.
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001888 for (const auto *Attr : Attrs) {
1889 const Record &R = *Attr;
Stephen Hines651f13c2014-04-23 16:59:28 -07001890 if (!R.getValueAsBit("ASTNode"))
1891 continue;
1892
1893 OS << "template <typename Derived>\n"
1894 << "bool VISITORCLASS<Derived>::Traverse"
1895 << R.getName() << "Attr(" << R.getName() << "Attr *A) {\n"
1896 << " if (!getDerived().VisitAttr(A))\n"
1897 << " return false;\n"
1898 << " if (!getDerived().Visit" << R.getName() << "Attr(A))\n"
1899 << " return false;\n";
1900
1901 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001902 for (const auto *Arg : ArgRecords)
1903 createArgument(*Arg, R.getName())->writeASTVisitorTraversal(OS);
Stephen Hines651f13c2014-04-23 16:59:28 -07001904
1905 OS << " return true;\n";
1906 OS << "}\n\n";
1907 }
1908
1909 // Write generic Traverse routine
1910 OS << "template <typename Derived>\n"
1911 << "bool VISITORCLASS<Derived>::TraverseAttr(Attr *A) {\n"
1912 << " if (!A)\n"
1913 << " return true;\n"
1914 << "\n"
1915 << " switch (A->getKind()) {\n"
1916 << " default:\n"
1917 << " return true;\n";
1918
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001919 for (const auto *Attr : Attrs) {
1920 const Record &R = *Attr;
Stephen Hines651f13c2014-04-23 16:59:28 -07001921 if (!R.getValueAsBit("ASTNode"))
1922 continue;
1923
1924 OS << " case attr::" << R.getName() << ":\n"
1925 << " return getDerived().Traverse" << R.getName() << "Attr("
1926 << "cast<" << R.getName() << "Attr>(A));\n";
1927 }
1928 OS << " }\n"; // end case
1929 OS << "}\n"; // end function
1930 OS << "#endif // ATTR_VISITOR_DECLS_ONLY\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +00001931}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001932
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001933// Emits code to instantiate dependent attributes on templates.
1934void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00001935 emitSourceFileHeader("Template instantiation code for attributes", OS);
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001936
1937 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1938
Benjamin Kramer5bbc3852012-02-06 11:13:08 +00001939 OS << "namespace clang {\n"
1940 << "namespace sema {\n\n"
1941 << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, "
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001942 << "Sema &S,\n"
1943 << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n"
1944 << " switch (At->getKind()) {\n"
1945 << " default:\n"
1946 << " break;\n";
1947
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001948 for (const auto *Attr : Attrs) {
1949 const Record &R = *Attr;
Douglas Gregor3e7d31a2012-05-02 15:56:52 +00001950 if (!R.getValueAsBit("ASTNode"))
1951 continue;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001952
1953 OS << " case attr::" << R.getName() << ": {\n";
Rafael Espindola31c195a2012-05-15 14:09:55 +00001954 bool ShouldClone = R.getValueAsBit("Clone");
1955
1956 if (!ShouldClone) {
1957 OS << " return NULL;\n";
1958 OS << " }\n";
1959 continue;
1960 }
1961
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001962 OS << " const " << R.getName() << "Attr *A = cast<"
1963 << R.getName() << "Attr>(At);\n";
1964 bool TDependent = R.getValueAsBit("TemplateDependent");
1965
1966 if (!TDependent) {
1967 OS << " return A->clone(C);\n";
1968 OS << " }\n";
1969 continue;
1970 }
1971
1972 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
Stephen Hines651f13c2014-04-23 16:59:28 -07001973 std::vector<std::unique_ptr<Argument>> Args;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001974 Args.reserve(ArgRecords.size());
1975
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001976 for (const auto *ArgRecord : ArgRecords)
Stephen Hines651f13c2014-04-23 16:59:28 -07001977 Args.emplace_back(createArgument(*ArgRecord, R.getName()));
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001978
Stephen Hines651f13c2014-04-23 16:59:28 -07001979 for (auto const &ai : Args)
1980 ai->writeTemplateInstantiation(OS);
1981
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001982 OS << " return new (C) " << R.getName() << "Attr(A->getLocation(), C";
Stephen Hines651f13c2014-04-23 16:59:28 -07001983 for (auto const &ai : Args) {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001984 OS << ", ";
Stephen Hines651f13c2014-04-23 16:59:28 -07001985 ai->writeTemplateInstantiationArgs(OS);
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001986 }
Stephen Hines651f13c2014-04-23 16:59:28 -07001987 OS << ", A->getSpellingListIndex());\n }\n";
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001988 }
1989 OS << " } // end switch\n"
1990 << " llvm_unreachable(\"Unknown attribute!\");\n"
1991 << " return 0;\n"
Benjamin Kramer5bbc3852012-02-06 11:13:08 +00001992 << "}\n\n"
1993 << "} // end namespace sema\n"
1994 << "} // end namespace clang\n";
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00001995}
1996
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00001997// Emits the list of parsed attributes.
1998void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) {
1999 emitSourceFileHeader("List of all attributes that Clang recognizes", OS);
2000
2001 OS << "#ifndef PARSED_ATTR\n";
2002 OS << "#define PARSED_ATTR(NAME) NAME\n";
2003 OS << "#endif\n\n";
2004
2005 ParsedAttrMap Names = getParsedAttrList(Records);
Stephen Hines651f13c2014-04-23 16:59:28 -07002006 for (const auto &I : Names) {
2007 OS << "PARSED_ATTR(" << I.first << ")\n";
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00002008 }
2009}
2010
Stephen Hines651f13c2014-04-23 16:59:28 -07002011static void emitArgInfo(const Record &R, std::stringstream &OS) {
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00002012 // This function will count the number of arguments specified for the
2013 // attribute and emit the number of required arguments followed by the
2014 // number of optional arguments.
2015 std::vector<Record *> Args = R.getValueAsListOfDefs("Args");
2016 unsigned ArgCount = 0, OptCount = 0;
Stephen Hines6bcf27b2014-05-29 04:14:42 -07002017 for (const auto *Arg : Args) {
Stephen Hines651f13c2014-04-23 16:59:28 -07002018 Arg->getValueAsBit("Optional") ? ++OptCount : ++ArgCount;
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00002019 }
2020 OS << ArgCount << ", " << OptCount;
2021}
2022
Stephen Hines651f13c2014-04-23 16:59:28 -07002023static void GenerateDefaultAppertainsTo(raw_ostream &OS) {
2024 OS << "static bool defaultAppertainsTo(Sema &, const AttributeList &,";
2025 OS << "const Decl *) {\n";
2026 OS << " return true;\n";
2027 OS << "}\n\n";
2028}
2029
2030static std::string CalculateDiagnostic(const Record &S) {
2031 // If the SubjectList object has a custom diagnostic associated with it,
2032 // return that directly.
2033 std::string CustomDiag = S.getValueAsString("CustomDiag");
2034 if (!CustomDiag.empty())
2035 return CustomDiag;
2036
2037 // Given the list of subjects, determine what diagnostic best fits.
2038 enum {
2039 Func = 1U << 0,
2040 Var = 1U << 1,
2041 ObjCMethod = 1U << 2,
2042 Param = 1U << 3,
2043 Class = 1U << 4,
2044 GenericRecord = 1U << 5,
2045 Type = 1U << 6,
2046 ObjCIVar = 1U << 7,
2047 ObjCProp = 1U << 8,
2048 ObjCInterface = 1U << 9,
2049 Block = 1U << 10,
2050 Namespace = 1U << 11,
Stephen Hines6bcf27b2014-05-29 04:14:42 -07002051 Field = 1U << 12,
2052 CXXMethod = 1U << 13,
2053 ObjCProtocol = 1U << 14
Stephen Hines651f13c2014-04-23 16:59:28 -07002054 };
2055 uint32_t SubMask = 0;
2056
2057 std::vector<Record *> Subjects = S.getValueAsListOfDefs("Subjects");
Stephen Hines6bcf27b2014-05-29 04:14:42 -07002058 for (const auto *Subject : Subjects) {
2059 const Record &R = *Subject;
Stephen Hines651f13c2014-04-23 16:59:28 -07002060 std::string Name;
2061
2062 if (R.isSubClassOf("SubsetSubject")) {
2063 PrintError(R.getLoc(), "SubsetSubjects should use a custom diagnostic");
2064 // As a fallback, look through the SubsetSubject to see what its base
2065 // type is, and use that. This needs to be updated if SubsetSubjects
2066 // are allowed within other SubsetSubjects.
2067 Name = R.getValueAsDef("Base")->getName();
2068 } else
2069 Name = R.getName();
2070
2071 uint32_t V = StringSwitch<uint32_t>(Name)
2072 .Case("Function", Func)
2073 .Case("Var", Var)
2074 .Case("ObjCMethod", ObjCMethod)
2075 .Case("ParmVar", Param)
2076 .Case("TypedefName", Type)
2077 .Case("ObjCIvar", ObjCIVar)
2078 .Case("ObjCProperty", ObjCProp)
2079 .Case("Record", GenericRecord)
2080 .Case("ObjCInterface", ObjCInterface)
2081 .Case("ObjCProtocol", ObjCProtocol)
2082 .Case("Block", Block)
2083 .Case("CXXRecord", Class)
2084 .Case("Namespace", Namespace)
Stephen Hines651f13c2014-04-23 16:59:28 -07002085 .Case("Field", Field)
2086 .Case("CXXMethod", CXXMethod)
2087 .Default(0);
2088 if (!V) {
2089 // Something wasn't in our mapping, so be helpful and let the developer
2090 // know about it.
2091 PrintFatalError(R.getLoc(), "Unknown subject type: " + R.getName());
2092 return "";
2093 }
2094
2095 SubMask |= V;
2096 }
2097
2098 switch (SubMask) {
2099 // For the simple cases where there's only a single entry in the mask, we
2100 // don't have to resort to bit fiddling.
2101 case Func: return "ExpectedFunction";
2102 case Var: return "ExpectedVariable";
2103 case Param: return "ExpectedParameter";
2104 case Class: return "ExpectedClass";
2105 case CXXMethod:
2106 // FIXME: Currently, this maps to ExpectedMethod based on existing code,
2107 // but should map to something a bit more accurate at some point.
2108 case ObjCMethod: return "ExpectedMethod";
2109 case Type: return "ExpectedType";
2110 case ObjCInterface: return "ExpectedObjectiveCInterface";
2111 case ObjCProtocol: return "ExpectedObjectiveCProtocol";
2112
2113 // "GenericRecord" means struct, union or class; check the language options
2114 // and if not compiling for C++, strip off the class part. Note that this
2115 // relies on the fact that the context for this declares "Sema &S".
2116 case GenericRecord:
2117 return "(S.getLangOpts().CPlusPlus ? ExpectedStructOrUnionOrClass : "
2118 "ExpectedStructOrUnion)";
2119 case Func | ObjCMethod | Block: return "ExpectedFunctionMethodOrBlock";
2120 case Func | ObjCMethod | Class: return "ExpectedFunctionMethodOrClass";
2121 case Func | Param:
2122 case Func | ObjCMethod | Param: return "ExpectedFunctionMethodOrParameter";
Stephen Hines651f13c2014-04-23 16:59:28 -07002123 case Func | ObjCMethod: return "ExpectedFunctionOrMethod";
2124 case Func | Var: return "ExpectedVariableOrFunction";
2125
2126 // If not compiling for C++, the class portion does not apply.
2127 case Func | Var | Class:
2128 return "(S.getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass : "
2129 "ExpectedVariableOrFunction)";
2130
2131 case ObjCMethod | ObjCProp: return "ExpectedMethodOrProperty";
2132 case Field | Var: return "ExpectedFieldOrGlobalVar";
2133 }
2134
2135 PrintFatalError(S.getLoc(),
2136 "Could not deduce diagnostic argument for Attr subjects");
2137
2138 return "";
2139}
2140
2141static std::string GetSubjectWithSuffix(const Record *R) {
2142 std::string B = R->getName();
2143 if (B == "DeclBase")
2144 return "Decl";
2145 return B + "Decl";
2146}
2147static std::string GenerateCustomAppertainsTo(const Record &Subject,
2148 raw_ostream &OS) {
2149 std::string FnName = "is" + Subject.getName();
2150
2151 // If this code has already been generated, simply return the previous
2152 // instance of it.
2153 static std::set<std::string> CustomSubjectSet;
2154 std::set<std::string>::iterator I = CustomSubjectSet.find(FnName);
2155 if (I != CustomSubjectSet.end())
2156 return *I;
2157
2158 Record *Base = Subject.getValueAsDef("Base");
2159
2160 // Not currently support custom subjects within custom subjects.
2161 if (Base->isSubClassOf("SubsetSubject")) {
2162 PrintFatalError(Subject.getLoc(),
2163 "SubsetSubjects within SubsetSubjects is not supported");
2164 return "";
2165 }
2166
2167 OS << "static bool " << FnName << "(const Decl *D) {\n";
2168 OS << " if (const " << GetSubjectWithSuffix(Base) << " *S = dyn_cast<";
2169 OS << GetSubjectWithSuffix(Base);
2170 OS << ">(D))\n";
2171 OS << " return " << Subject.getValueAsString("CheckCode") << ";\n";
2172 OS << " return false;\n";
2173 OS << "}\n\n";
2174
2175 CustomSubjectSet.insert(FnName);
2176 return FnName;
2177}
2178
2179static std::string GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) {
2180 // If the attribute does not contain a Subjects definition, then use the
2181 // default appertainsTo logic.
2182 if (Attr.isValueUnset("Subjects"))
2183 return "defaultAppertainsTo";
2184
2185 const Record *SubjectObj = Attr.getValueAsDef("Subjects");
2186 std::vector<Record*> Subjects = SubjectObj->getValueAsListOfDefs("Subjects");
2187
2188 // If the list of subjects is empty, it is assumed that the attribute
2189 // appertains to everything.
2190 if (Subjects.empty())
2191 return "defaultAppertainsTo";
2192
2193 bool Warn = SubjectObj->getValueAsDef("Diag")->getValueAsBit("Warn");
2194
2195 // Otherwise, generate an appertainsTo check specific to this attribute which
2196 // checks all of the given subjects against the Decl passed in. Return the
2197 // name of that check to the caller.
2198 std::string FnName = "check" + Attr.getName() + "AppertainsTo";
2199 std::stringstream SS;
2200 SS << "static bool " << FnName << "(Sema &S, const AttributeList &Attr, ";
2201 SS << "const Decl *D) {\n";
2202 SS << " if (";
2203 for (auto I = Subjects.begin(), E = Subjects.end(); I != E; ++I) {
2204 // If the subject has custom code associated with it, generate a function
2205 // for it. The function cannot be inlined into this check (yet) because it
2206 // requires the subject to be of a specific type, and were that information
2207 // inlined here, it would not support an attribute with multiple custom
2208 // subjects.
2209 if ((*I)->isSubClassOf("SubsetSubject")) {
2210 SS << "!" << GenerateCustomAppertainsTo(**I, OS) << "(D)";
2211 } else {
2212 SS << "!isa<" << GetSubjectWithSuffix(*I) << ">(D)";
2213 }
2214
2215 if (I + 1 != E)
2216 SS << " && ";
2217 }
2218 SS << ") {\n";
2219 SS << " S.Diag(Attr.getLoc(), diag::";
2220 SS << (Warn ? "warn_attribute_wrong_decl_type" :
2221 "err_attribute_wrong_decl_type");
2222 SS << ")\n";
2223 SS << " << Attr.getName() << ";
2224 SS << CalculateDiagnostic(*SubjectObj) << ";\n";
2225 SS << " return false;\n";
2226 SS << " }\n";
2227 SS << " return true;\n";
2228 SS << "}\n\n";
2229
2230 OS << SS.str();
2231 return FnName;
2232}
2233
2234static void GenerateDefaultLangOptRequirements(raw_ostream &OS) {
2235 OS << "static bool defaultDiagnoseLangOpts(Sema &, ";
2236 OS << "const AttributeList &) {\n";
2237 OS << " return true;\n";
2238 OS << "}\n\n";
2239}
2240
2241static std::string GenerateLangOptRequirements(const Record &R,
2242 raw_ostream &OS) {
2243 // If the attribute has an empty or unset list of language requirements,
2244 // return the default handler.
2245 std::vector<Record *> LangOpts = R.getValueAsListOfDefs("LangOpts");
2246 if (LangOpts.empty())
2247 return "defaultDiagnoseLangOpts";
2248
2249 // Generate the test condition, as well as a unique function name for the
2250 // diagnostic test. The list of options should usually be short (one or two
2251 // options), and the uniqueness isn't strictly necessary (it is just for
2252 // codegen efficiency).
2253 std::string FnName = "check", Test;
2254 for (auto I = LangOpts.begin(), E = LangOpts.end(); I != E; ++I) {
2255 std::string Part = (*I)->getValueAsString("Name");
2256 Test += "S.LangOpts." + Part;
2257 if (I + 1 != E)
2258 Test += " || ";
2259 FnName += Part;
2260 }
2261 FnName += "LangOpts";
2262
2263 // If this code has already been generated, simply return the previous
2264 // instance of it.
2265 static std::set<std::string> CustomLangOptsSet;
2266 std::set<std::string>::iterator I = CustomLangOptsSet.find(FnName);
2267 if (I != CustomLangOptsSet.end())
2268 return *I;
2269
2270 OS << "static bool " << FnName << "(Sema &S, const AttributeList &Attr) {\n";
2271 OS << " if (" << Test << ")\n";
2272 OS << " return true;\n\n";
2273 OS << " S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) ";
2274 OS << "<< Attr.getName();\n";
2275 OS << " return false;\n";
2276 OS << "}\n\n";
2277
2278 CustomLangOptsSet.insert(FnName);
2279 return FnName;
2280}
2281
2282static void GenerateDefaultTargetRequirements(raw_ostream &OS) {
2283 OS << "static bool defaultTargetRequirements(const llvm::Triple &) {\n";
2284 OS << " return true;\n";
2285 OS << "}\n\n";
2286}
2287
2288static std::string GenerateTargetRequirements(const Record &Attr,
2289 const ParsedAttrMap &Dupes,
2290 raw_ostream &OS) {
2291 // If the attribute is not a target specific attribute, return the default
2292 // target handler.
2293 if (!Attr.isSubClassOf("TargetSpecificAttr"))
2294 return "defaultTargetRequirements";
2295
2296 // Get the list of architectures to be tested for.
2297 const Record *R = Attr.getValueAsDef("Target");
2298 std::vector<std::string> Arches = R->getValueAsListOfStrings("Arches");
2299 if (Arches.empty()) {
2300 PrintError(Attr.getLoc(), "Empty list of target architectures for a "
2301 "target-specific attr");
2302 return "defaultTargetRequirements";
2303 }
2304
2305 // If there are other attributes which share the same parsed attribute kind,
2306 // such as target-specific attributes with a shared spelling, collapse the
2307 // duplicate architectures. This is required because a shared target-specific
2308 // attribute has only one AttributeList::Kind enumeration value, but it
2309 // applies to multiple target architectures. In order for the attribute to be
2310 // considered valid, all of its architectures need to be included.
2311 if (!Attr.isValueUnset("ParseKind")) {
2312 std::string APK = Attr.getValueAsString("ParseKind");
2313 for (const auto &I : Dupes) {
2314 if (I.first == APK) {
2315 std::vector<std::string> DA = I.second->getValueAsDef("Target")
2316 ->getValueAsListOfStrings("Arches");
2317 std::copy(DA.begin(), DA.end(), std::back_inserter(Arches));
2318 }
2319 }
2320 }
2321
2322 std::string FnName = "isTarget", Test = "(";
2323 for (auto I = Arches.begin(), E = Arches.end(); I != E; ++I) {
2324 std::string Part = *I;
2325 Test += "Arch == llvm::Triple::" + Part;
2326 if (I + 1 != E)
2327 Test += " || ";
2328 FnName += Part;
2329 }
2330 Test += ")";
2331
2332 // If the target also requires OS testing, generate those tests as well.
2333 bool UsesOS = false;
2334 if (!R->isValueUnset("OSes")) {
2335 UsesOS = true;
2336
2337 // We know that there was at least one arch test, so we need to and in the
2338 // OS tests.
2339 Test += " && (";
2340 std::vector<std::string> OSes = R->getValueAsListOfStrings("OSes");
2341 for (auto I = OSes.begin(), E = OSes.end(); I != E; ++I) {
2342 std::string Part = *I;
2343
2344 Test += "OS == llvm::Triple::" + Part;
2345 if (I + 1 != E)
2346 Test += " || ";
2347 FnName += Part;
2348 }
2349 Test += ")";
2350 }
2351
2352 // If this code has already been generated, simply return the previous
2353 // instance of it.
2354 static std::set<std::string> CustomTargetSet;
2355 std::set<std::string>::iterator I = CustomTargetSet.find(FnName);
2356 if (I != CustomTargetSet.end())
2357 return *I;
2358
2359 OS << "static bool " << FnName << "(const llvm::Triple &T) {\n";
2360 OS << " llvm::Triple::ArchType Arch = T.getArch();\n";
2361 if (UsesOS)
2362 OS << " llvm::Triple::OSType OS = T.getOS();\n";
2363 OS << " return " << Test << ";\n";
2364 OS << "}\n\n";
2365
2366 CustomTargetSet.insert(FnName);
2367 return FnName;
2368}
2369
2370static void GenerateDefaultSpellingIndexToSemanticSpelling(raw_ostream &OS) {
2371 OS << "static unsigned defaultSpellingIndexToSemanticSpelling("
2372 << "const AttributeList &Attr) {\n";
2373 OS << " return UINT_MAX;\n";
2374 OS << "}\n\n";
2375}
2376
2377static std::string GenerateSpellingIndexToSemanticSpelling(const Record &Attr,
2378 raw_ostream &OS) {
2379 // If the attribute does not have a semantic form, we can bail out early.
2380 if (!Attr.getValueAsBit("ASTNode"))
2381 return "defaultSpellingIndexToSemanticSpelling";
2382
2383 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
2384
2385 // If there are zero or one spellings, or all of the spellings share the same
2386 // name, we can also bail out early.
2387 if (Spellings.size() <= 1 || SpellingNamesAreCommon(Spellings))
2388 return "defaultSpellingIndexToSemanticSpelling";
2389
2390 // Generate the enumeration we will use for the mapping.
2391 SemanticSpellingMap SemanticToSyntacticMap;
2392 std::string Enum = CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);
2393 std::string Name = Attr.getName() + "AttrSpellingMap";
2394
2395 OS << "static unsigned " << Name << "(const AttributeList &Attr) {\n";
2396 OS << Enum;
2397 OS << " unsigned Idx = Attr.getAttributeSpellingListIndex();\n";
2398 WriteSemanticSpellingSwitch("Idx", SemanticToSyntacticMap, OS);
2399 OS << "}\n\n";
2400
2401 return Name;
2402}
2403
2404static bool IsKnownToGCC(const Record &Attr) {
2405 // Look at the spellings for this subject; if there are any spellings which
2406 // claim to be known to GCC, the attribute is known to GCC.
2407 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
2408 for (const auto &I : Spellings) {
2409 if (I.knownToGCC())
2410 return true;
2411 }
2412 return false;
2413}
2414
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00002415/// Emits the parsed attribute helpers
2416void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
2417 emitSourceFileHeader("Parsed attribute helpers", OS);
2418
Stephen Hines651f13c2014-04-23 16:59:28 -07002419 // Get the list of parsed attributes, and accept the optional list of
2420 // duplicates due to the ParseKind.
2421 ParsedAttrMap Dupes;
2422 ParsedAttrMap Attrs = getParsedAttrList(Records, &Dupes);
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00002423
Stephen Hines651f13c2014-04-23 16:59:28 -07002424 // Generate the default appertainsTo, target and language option diagnostic,
2425 // and spelling list index mapping methods.
2426 GenerateDefaultAppertainsTo(OS);
2427 GenerateDefaultLangOptRequirements(OS);
2428 GenerateDefaultTargetRequirements(OS);
2429 GenerateDefaultSpellingIndexToSemanticSpelling(OS);
2430
2431 // Generate the appertainsTo diagnostic methods and write their names into
2432 // another mapping. At the same time, generate the AttrInfoMap object
2433 // contents. Due to the reliance on generated code, use separate streams so
2434 // that code will not be interleaved.
2435 std::stringstream SS;
2436 for (auto I = Attrs.begin(), E = Attrs.end(); I != E; ++I) {
2437 // TODO: If the attribute's kind appears in the list of duplicates, that is
2438 // because it is a target-specific attribute that appears multiple times.
2439 // It would be beneficial to test whether the duplicates are "similar
2440 // enough" to each other to not cause problems. For instance, check that
2441 // the spellings are identical, and custom parsing rules match, etc.
2442
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00002443 // We need to generate struct instances based off ParsedAttrInfo from
2444 // AttributeList.cpp.
Stephen Hines651f13c2014-04-23 16:59:28 -07002445 SS << " { ";
2446 emitArgInfo(*I->second, SS);
2447 SS << ", " << I->second->getValueAsBit("HasCustomParsing");
2448 SS << ", " << I->second->isSubClassOf("TargetSpecificAttr");
2449 SS << ", " << I->second->isSubClassOf("TypeAttr");
2450 SS << ", " << IsKnownToGCC(*I->second);
2451 SS << ", " << GenerateAppertainsTo(*I->second, OS);
2452 SS << ", " << GenerateLangOptRequirements(*I->second, OS);
2453 SS << ", " << GenerateTargetRequirements(*I->second, Dupes, OS);
2454 SS << ", " << GenerateSpellingIndexToSemanticSpelling(*I->second, OS);
2455 SS << " }";
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00002456
2457 if (I + 1 != E)
Stephen Hines651f13c2014-04-23 16:59:28 -07002458 SS << ",";
2459
2460 SS << " // AT_" << I->first << "\n";
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00002461 }
Stephen Hines651f13c2014-04-23 16:59:28 -07002462
2463 OS << "static const ParsedAttrInfo AttrInfoMap[AttributeList::UnknownAttribute + 1] = {\n";
2464 OS << SS.str();
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00002465 OS << "};\n\n";
Michael Hane53ac8a2012-03-07 00:12:16 +00002466}
2467
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00002468// Emits the kind list of parsed attributes
2469void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00002470 emitSourceFileHeader("Attribute name matcher", OS);
2471
Stephen Hines651f13c2014-04-23 16:59:28 -07002472 std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
2473 std::vector<StringMatcher::StringPair> GNU, Declspec, CXX11, Keywords;
2474 std::set<std::string> Seen;
Stephen Hines6bcf27b2014-05-29 04:14:42 -07002475 for (const auto *A : Attrs) {
2476 const Record &Attr = *A;
Michael Hane53ac8a2012-03-07 00:12:16 +00002477
Michael Hane53ac8a2012-03-07 00:12:16 +00002478 bool SemaHandler = Attr.getValueAsBit("SemaHandler");
Douglas Gregor331d2ec2012-05-02 16:18:45 +00002479 bool Ignored = Attr.getValueAsBit("Ignored");
Douglas Gregor331d2ec2012-05-02 16:18:45 +00002480 if (SemaHandler || Ignored) {
Stephen Hines651f13c2014-04-23 16:59:28 -07002481 // Attribute spellings can be shared between target-specific attributes,
2482 // and can be shared between syntaxes for the same attribute. For
2483 // instance, an attribute can be spelled GNU<"interrupt"> for an ARM-
2484 // specific attribute, or MSP430-specific attribute. Additionally, an
2485 // attribute can be spelled GNU<"dllexport"> and Declspec<"dllexport">
2486 // for the same semantic attribute. Ultimately, we need to map each of
2487 // these to a single AttributeList::Kind value, but the StringMatcher
2488 // class cannot handle duplicate match strings. So we generate a list of
2489 // string to match based on the syntax, and emit multiple string matchers
2490 // depending on the syntax used.
2491 std::string AttrName;
2492 if (Attr.isSubClassOf("TargetSpecificAttr") &&
2493 !Attr.isValueUnset("ParseKind")) {
2494 AttrName = Attr.getValueAsString("ParseKind");
2495 if (Seen.find(AttrName) != Seen.end())
2496 continue;
2497 Seen.insert(AttrName);
2498 } else
2499 AttrName = NormalizeAttrName(StringRef(Attr.getName())).str();
Michael Hane53ac8a2012-03-07 00:12:16 +00002500
Stephen Hines651f13c2014-04-23 16:59:28 -07002501 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
2502 for (const auto &S : Spellings) {
2503 std::string RawSpelling = S.name();
Stephen Hines6bcf27b2014-05-29 04:14:42 -07002504 std::vector<StringMatcher::StringPair> *Matches = nullptr;
Stephen Hines651f13c2014-04-23 16:59:28 -07002505 std::string Spelling, Variety = S.variety();
2506 if (Variety == "CXX11") {
2507 Matches = &CXX11;
2508 Spelling += S.nameSpace();
Sean Hunt8e083e72012-06-19 23:57:03 +00002509 Spelling += "::";
Stephen Hines651f13c2014-04-23 16:59:28 -07002510 } else if (Variety == "GNU")
2511 Matches = &GNU;
2512 else if (Variety == "Declspec")
2513 Matches = &Declspec;
2514 else if (Variety == "Keyword")
2515 Matches = &Keywords;
Sean Hunt93f95f22012-06-18 16:13:52 +00002516
Stephen Hines651f13c2014-04-23 16:59:28 -07002517 assert(Matches && "Unsupported spelling variety found");
2518
2519 Spelling += NormalizeAttrSpelling(RawSpelling);
Douglas Gregor331d2ec2012-05-02 16:18:45 +00002520 if (SemaHandler)
Stephen Hines651f13c2014-04-23 16:59:28 -07002521 Matches->push_back(StringMatcher::StringPair(Spelling,
2522 "return AttributeList::AT_" + AttrName + ";"));
Douglas Gregor331d2ec2012-05-02 16:18:45 +00002523 else
Stephen Hines651f13c2014-04-23 16:59:28 -07002524 Matches->push_back(StringMatcher::StringPair(Spelling,
2525 "return AttributeList::IgnoredAttribute;"));
Michael Hane53ac8a2012-03-07 00:12:16 +00002526 }
2527 }
2528 }
Douglas Gregor0c19b3c2012-05-02 17:33:51 +00002529
Stephen Hines651f13c2014-04-23 16:59:28 -07002530 OS << "static AttributeList::Kind getAttrKind(StringRef Name, ";
2531 OS << "AttributeList::Syntax Syntax) {\n";
2532 OS << " if (AttributeList::AS_GNU == Syntax) {\n";
2533 StringMatcher("Name", GNU, OS).Emit();
2534 OS << " } else if (AttributeList::AS_Declspec == Syntax) {\n";
2535 StringMatcher("Name", Declspec, OS).Emit();
2536 OS << " } else if (AttributeList::AS_CXX11 == Syntax) {\n";
2537 StringMatcher("Name", CXX11, OS).Emit();
2538 OS << " } else if (AttributeList::AS_Keyword == Syntax) {\n";
2539 StringMatcher("Name", Keywords, OS).Emit();
2540 OS << " }\n";
2541 OS << " return AttributeList::UnknownAttribute;\n"
Douglas Gregor0c19b3c2012-05-02 17:33:51 +00002542 << "}\n";
Michael Hane53ac8a2012-03-07 00:12:16 +00002543}
2544
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +00002545// Emits the code to dump an attribute.
2546void EmitClangAttrDump(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00002547 emitSourceFileHeader("Attribute dumper", OS);
2548
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +00002549 OS <<
2550 " switch (A->getKind()) {\n"
2551 " default:\n"
2552 " llvm_unreachable(\"Unknown attribute kind!\");\n"
2553 " break;\n";
2554 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
Stephen Hines6bcf27b2014-05-29 04:14:42 -07002555 for (const auto *Attr : Attrs) {
2556 const Record &R = *Attr;
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +00002557 if (!R.getValueAsBit("ASTNode"))
2558 continue;
2559 OS << " case attr::" << R.getName() << ": {\n";
Stephen Hines651f13c2014-04-23 16:59:28 -07002560
2561 // If the attribute has a semantically-meaningful name (which is determined
2562 // by whether there is a Spelling enumeration for it), then write out the
2563 // spelling used for the attribute.
2564 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
2565 if (Spellings.size() > 1 && !SpellingNamesAreCommon(Spellings))
2566 OS << " OS << \" \" << A->getSpelling();\n";
2567
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +00002568 Args = R.getValueAsListOfDefs("Args");
2569 if (!Args.empty()) {
2570 OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
2571 << "Attr>(A);\n";
Stephen Hines6bcf27b2014-05-29 04:14:42 -07002572 for (const auto *Arg : Args)
2573 createArgument(*Arg, R.getName())->writeDump(OS);
Richard Trieue8d41192013-01-31 01:44:26 +00002574
2575 // Code for detecting the last child.
2576 OS << " bool OldMoreChildren = hasMoreChildren();\n";
Stephen Hines651f13c2014-04-23 16:59:28 -07002577 OS << " bool MoreChildren;\n";
Richard Trieue8d41192013-01-31 01:44:26 +00002578
Stephen Hines651f13c2014-04-23 16:59:28 -07002579 for (auto AI = Args.begin(), AE = Args.end(); AI != AE; ++AI) {
Richard Trieue8d41192013-01-31 01:44:26 +00002580 // More code for detecting the last child.
2581 OS << " MoreChildren = OldMoreChildren";
Stephen Hines651f13c2014-04-23 16:59:28 -07002582 for (auto Next = AI + 1; Next != AE; ++Next) {
Richard Trieue8d41192013-01-31 01:44:26 +00002583 OS << " || ";
2584 createArgument(**Next, R.getName())->writeHasChildren(OS);
2585 }
2586 OS << ";\n";
2587 OS << " setMoreChildren(MoreChildren);\n";
2588
Stephen Hines651f13c2014-04-23 16:59:28 -07002589 createArgument(**AI, R.getName())->writeDumpChildren(OS);
Richard Trieue8d41192013-01-31 01:44:26 +00002590 }
2591
2592 // Reset the last child.
2593 OS << " setMoreChildren(OldMoreChildren);\n";
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +00002594 }
2595 OS <<
2596 " break;\n"
2597 " }\n";
2598 }
2599 OS << " }\n";
2600}
2601
Stephen Hines651f13c2014-04-23 16:59:28 -07002602void EmitClangAttrParserStringSwitches(RecordKeeper &Records,
2603 raw_ostream &OS) {
2604 emitSourceFileHeader("Parser-related llvm::StringSwitch cases", OS);
2605 emitClangAttrArgContextList(Records, OS);
2606 emitClangAttrIdentifierArgList(Records, OS);
2607 emitClangAttrTypeArgList(Records, OS);
2608 emitClangAttrLateParsedList(Records, OS);
2609}
2610
2611class DocumentationData {
2612public:
2613 const Record *Documentation;
2614 const Record *Attribute;
2615
2616 DocumentationData(const Record &Documentation, const Record &Attribute)
2617 : Documentation(&Documentation), Attribute(&Attribute) {}
2618};
2619
2620static void WriteCategoryHeader(const Record *DocCategory,
2621 raw_ostream &OS) {
2622 const std::string &Name = DocCategory->getValueAsString("Name");
2623 OS << Name << "\n" << std::string(Name.length(), '=') << "\n";
2624
2625 // If there is content, print that as well.
2626 std::string ContentStr = DocCategory->getValueAsString("Content");
2627 if (!ContentStr.empty()) {
2628 // Trim leading and trailing newlines and spaces.
2629 StringRef Content(ContentStr);
2630 while (Content.startswith("\r") || Content.startswith("\n") ||
2631 Content.startswith(" ") || Content.startswith("\t"))
2632 Content = Content.substr(1);
2633 while (Content.endswith("\r") || Content.endswith("\n") ||
2634 Content.endswith(" ") || Content.endswith("\t"))
2635 Content = Content.substr(0, Content.size() - 1);
2636 OS << Content;
2637 }
2638 OS << "\n\n";
2639}
2640
2641enum SpellingKind {
2642 GNU = 1 << 0,
2643 CXX11 = 1 << 1,
2644 Declspec = 1 << 2,
2645 Keyword = 1 << 3
2646};
2647
2648static void WriteDocumentation(const DocumentationData &Doc,
2649 raw_ostream &OS) {
2650 // FIXME: there is no way to have a per-spelling category for the attribute
2651 // documentation. This may not be a limiting factor since the spellings
2652 // should generally be consistently applied across the category.
2653
2654 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Doc.Attribute);
2655
2656 // Determine the heading to be used for this attribute.
2657 std::string Heading = Doc.Documentation->getValueAsString("Heading");
2658 bool CustomHeading = !Heading.empty();
2659 if (Heading.empty()) {
2660 // If there's only one spelling, we can simply use that.
2661 if (Spellings.size() == 1)
2662 Heading = Spellings.begin()->name();
2663 else {
2664 std::set<std::string> Uniques;
2665 for (auto I = Spellings.begin(), E = Spellings.end();
2666 I != E && Uniques.size() <= 1; ++I) {
2667 std::string Spelling = NormalizeNameForSpellingComparison(I->name());
2668 Uniques.insert(Spelling);
2669 }
2670 // If the semantic map has only one spelling, that is sufficient for our
2671 // needs.
2672 if (Uniques.size() == 1)
2673 Heading = *Uniques.begin();
2674 }
2675 }
2676
2677 // If the heading is still empty, it is an error.
2678 if (Heading.empty())
2679 PrintFatalError(Doc.Attribute->getLoc(),
2680 "This attribute requires a heading to be specified");
2681
2682 // Gather a list of unique spellings; this is not the same as the semantic
2683 // spelling for the attribute. Variations in underscores and other non-
2684 // semantic characters are still acceptable.
2685 std::vector<std::string> Names;
2686
2687 unsigned SupportedSpellings = 0;
2688 for (const auto &I : Spellings) {
2689 SpellingKind Kind = StringSwitch<SpellingKind>(I.variety())
2690 .Case("GNU", GNU)
2691 .Case("CXX11", CXX11)
2692 .Case("Declspec", Declspec)
2693 .Case("Keyword", Keyword);
2694
2695 // Mask in the supported spelling.
2696 SupportedSpellings |= Kind;
2697
2698 std::string Name;
2699 if (Kind == CXX11 && !I.nameSpace().empty())
2700 Name = I.nameSpace() + "::";
2701 Name += I.name();
2702
2703 // If this name is the same as the heading, do not add it.
2704 if (Name != Heading)
2705 Names.push_back(Name);
2706 }
2707
2708 // Print out the heading for the attribute. If there are alternate spellings,
2709 // then display those after the heading.
2710 if (!CustomHeading && !Names.empty()) {
2711 Heading += " (";
2712 for (auto I = Names.begin(), E = Names.end(); I != E; ++I) {
2713 if (I != Names.begin())
2714 Heading += ", ";
2715 Heading += *I;
2716 }
2717 Heading += ")";
2718 }
2719 OS << Heading << "\n" << std::string(Heading.length(), '-') << "\n";
2720
2721 if (!SupportedSpellings)
2722 PrintFatalError(Doc.Attribute->getLoc(),
2723 "Attribute has no supported spellings; cannot be "
2724 "documented");
2725
2726 // List what spelling syntaxes the attribute supports.
2727 OS << ".. csv-table:: Supported Syntaxes\n";
2728 OS << " :header: \"GNU\", \"C++11\", \"__declspec\", \"Keyword\"\n\n";
2729 OS << " \"";
2730 if (SupportedSpellings & GNU) OS << "X";
2731 OS << "\",\"";
2732 if (SupportedSpellings & CXX11) OS << "X";
2733 OS << "\",\"";
2734 if (SupportedSpellings & Declspec) OS << "X";
2735 OS << "\",\"";
2736 if (SupportedSpellings & Keyword) OS << "X";
2737 OS << "\"\n\n";
2738
2739 // If the attribute is deprecated, print a message about it, and possibly
2740 // provide a replacement attribute.
2741 if (!Doc.Documentation->isValueUnset("Deprecated")) {
2742 OS << "This attribute has been deprecated, and may be removed in a future "
2743 << "version of Clang.";
2744 const Record &Deprecated = *Doc.Documentation->getValueAsDef("Deprecated");
2745 std::string Replacement = Deprecated.getValueAsString("Replacement");
2746 if (!Replacement.empty())
2747 OS << " This attribute has been superseded by ``"
2748 << Replacement << "``.";
2749 OS << "\n\n";
2750 }
2751
2752 std::string ContentStr = Doc.Documentation->getValueAsString("Content");
2753 // Trim leading and trailing newlines and spaces.
2754 StringRef Content(ContentStr);
2755 while (Content.startswith("\r") || Content.startswith("\n") ||
2756 Content.startswith(" ") || Content.startswith("\t"))
2757 Content = Content.substr(1);
2758 while (Content.endswith("\r") || Content.endswith("\n") ||
2759 Content.endswith(" ") || Content.endswith("\t"))
2760 Content = Content.substr(0, Content.size() - 1);
2761 OS << Content;
2762
2763 OS << "\n\n\n";
2764}
2765
2766void EmitClangAttrDocs(RecordKeeper &Records, raw_ostream &OS) {
2767 // Get the documentation introduction paragraph.
2768 const Record *Documentation = Records.getDef("GlobalDocumentation");
2769 if (!Documentation) {
2770 PrintFatalError("The Documentation top-level definition is missing, "
2771 "no documentation will be generated.");
2772 return;
2773 }
2774
2775 OS << Documentation->getValueAsString("Intro") << "\n";
2776
2777 // Gather the Documentation lists from each of the attributes, based on the
2778 // category provided.
2779 std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
2780 std::map<const Record *, std::vector<DocumentationData>> SplitDocs;
Stephen Hines6bcf27b2014-05-29 04:14:42 -07002781 for (const auto *A : Attrs) {
2782 const Record &Attr = *A;
Stephen Hines651f13c2014-04-23 16:59:28 -07002783 std::vector<Record *> Docs = Attr.getValueAsListOfDefs("Documentation");
Stephen Hines6bcf27b2014-05-29 04:14:42 -07002784 for (const auto *D : Docs) {
2785 const Record &Doc = *D;
Stephen Hines651f13c2014-04-23 16:59:28 -07002786 const Record *Category = Doc.getValueAsDef("Category");
2787 // If the category is "undocumented", then there cannot be any other
2788 // documentation categories (otherwise, the attribute would become
2789 // documented).
2790 std::string Cat = Category->getValueAsString("Name");
2791 bool Undocumented = Cat == "Undocumented";
2792 if (Undocumented && Docs.size() > 1)
2793 PrintFatalError(Doc.getLoc(),
2794 "Attribute is \"Undocumented\", but has multiple "
2795 "documentation categories");
2796
2797 if (!Undocumented)
2798 SplitDocs[Category].push_back(DocumentationData(Doc, Attr));
2799 }
2800 }
2801
2802 // Having split the attributes out based on what documentation goes where,
2803 // we can begin to generate sections of documentation.
2804 for (const auto &I : SplitDocs) {
2805 WriteCategoryHeader(I.first, OS);
2806
2807 // Walk over each of the attributes in the category and write out their
2808 // documentation.
2809 for (const auto &Doc : I.second)
2810 WriteDocumentation(Doc, OS);
2811 }
2812}
2813
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00002814} // end namespace clang