blob: c03ff901d1b9396085bb2a5841ffb6b945917a59 [file] [log] [blame]
Peter Collingbournebee583f2011-10-06 13:03:08 +00001//===- ClangAttrEmitter.cpp - Generate Clang attribute handling =-*- C++ -*--=//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// These tablegen backends emit Clang attribute processing code
11//
12//===----------------------------------------------------------------------===//
13
Alexis Hunta0e54d42012-06-18 16:13:52 +000014#include "llvm/ADT/SmallString.h"
Chandler Carruth757fcd62014-03-04 10:05:20 +000015#include "llvm/ADT/STLExtras.h"
Aaron Ballman8ee40b72013-09-09 23:33:17 +000016#include "llvm/ADT/SmallSet.h"
Chandler Carruth5553d0d2014-01-07 11:51:46 +000017#include "llvm/ADT/StringSwitch.h"
18#include "llvm/TableGen/Error.h"
Peter Collingbournebee583f2011-10-06 13:03:08 +000019#include "llvm/TableGen/Record.h"
Douglas Gregor377f99b2012-05-02 17:33:51 +000020#include "llvm/TableGen/StringMatcher.h"
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +000021#include "llvm/TableGen/TableGenBackend.h"
Peter Collingbournebee583f2011-10-06 13:03:08 +000022#include <algorithm>
23#include <cctype>
Aaron Ballman8f1439b2014-03-05 16:49:55 +000024#include <memory>
Aaron Ballman80469032013-11-29 14:57:58 +000025#include <set>
Chandler Carruth5553d0d2014-01-07 11:51:46 +000026#include <sstream>
Peter Collingbournebee583f2011-10-06 13:03:08 +000027
28using namespace llvm;
29
Aaron Ballmanc669cc02014-01-27 22:10:04 +000030class FlattenedSpelling {
31 std::string V, N, NS;
32 bool K;
33
34public:
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")) {
41
42 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);
48 }
49
50 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
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +000060 for (const auto &Spelling : Spellings) {
61 if (Spelling->getValueAsString("Variety") == "GCC") {
Aaron Ballmanc669cc02014-01-27 22:10:04 +000062 // Gin up two new spelling objects to add into the list.
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +000063 Ret.push_back(FlattenedSpelling("GNU", Spelling->getValueAsString("Name"),
Aaron Ballmanc669cc02014-01-27 22:10:04 +000064 "", true));
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +000065 Ret.push_back(FlattenedSpelling(
66 "CXX11", Spelling->getValueAsString("Name"), "gnu", true));
Aaron Ballmanc669cc02014-01-27 22:10:04 +000067 } else
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +000068 Ret.push_back(FlattenedSpelling(*Spelling));
Aaron Ballmanc669cc02014-01-27 22:10:04 +000069 }
70
71 return Ret;
72}
73
Peter Collingbournebee583f2011-10-06 13:03:08 +000074static 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 Smithb87c4652013-10-31 21:23:20 +000078 .Case("TypeSourceInfo *", "GetTypeSourceInfo(F, Record, Idx)")
Argyrios Kyrtzidisa660ae42012-11-15 01:31:39 +000079 .Case("Expr *", "ReadExpr(F)")
Peter Collingbournebee583f2011-10-06 13:03:08 +000080 .Case("IdentifierInfo *", "GetIdentifierInfo(F, Record, Idx)")
Peter Collingbournebee583f2011-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 Smithb87c4652013-10-31 21:23:20 +000089 .Case("TypeSourceInfo *",
90 "AddTypeSourceInfo(" + std::string(name) + ", Record);\n")
Peter Collingbournebee583f2011-10-06 13:03:08 +000091 .Case("Expr *", "AddStmt(" + std::string(name) + ");\n")
92 .Case("IdentifierInfo *",
93 "AddIdentifierRef(" + std::string(name) + ", Record);\n")
Peter Collingbournebee583f2011-10-06 13:03:08 +000094 .Default("Record.push_back(" + std::string(name) + ");\n");
95}
96
Michael Han4a045172012-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
Aaron Ballman36a53502014-01-16 13:03:14 +0000110// 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 Han4a045172012-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
Aaron Ballman2f22b942014-05-20 19:47:14 +0000132typedef std::vector<std::pair<std::string, const Record *>> ParsedAttrMap;
Aaron Ballman64e69862013-12-15 13:05:48 +0000133
Aaron Ballmanab7691c2014-01-09 22:48:32 +0000134static ParsedAttrMap getParsedAttrList(const RecordKeeper &Records,
Craig Topper8ae12032014-05-07 06:21:57 +0000135 ParsedAttrMap *Dupes = nullptr) {
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +0000136 std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
Aaron Ballman64e69862013-12-15 13:05:48 +0000137 std::set<std::string> Seen;
138 ParsedAttrMap R;
Aaron Ballman2f22b942014-05-20 19:47:14 +0000139 for (const auto *Attr : Attrs) {
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +0000140 if (Attr->getValueAsBit("SemaHandler")) {
Aaron Ballman64e69862013-12-15 13:05:48 +0000141 std::string AN;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +0000142 if (Attr->isSubClassOf("TargetSpecificAttr") &&
143 !Attr->isValueUnset("ParseKind")) {
144 AN = Attr->getValueAsString("ParseKind");
Aaron Ballman64e69862013-12-15 13:05:48 +0000145
146 // If this attribute has already been handled, it does not need to be
147 // handled again.
Aaron Ballmanab7691c2014-01-09 22:48:32 +0000148 if (Seen.find(AN) != Seen.end()) {
149 if (Dupes)
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +0000150 Dupes->push_back(std::make_pair(AN, Attr));
Aaron Ballman64e69862013-12-15 13:05:48 +0000151 continue;
Aaron Ballmanab7691c2014-01-09 22:48:32 +0000152 }
Aaron Ballman64e69862013-12-15 13:05:48 +0000153 Seen.insert(AN);
154 } else
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +0000155 AN = NormalizeAttrName(Attr->getName()).str();
Aaron Ballman64e69862013-12-15 13:05:48 +0000156
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +0000157 R.push_back(std::make_pair(AN, Attr));
Aaron Ballman64e69862013-12-15 13:05:48 +0000158 }
159 }
160 return R;
161}
162
Peter Collingbournebee583f2011-10-06 13:03:08 +0000163namespace {
164 class Argument {
165 std::string lowerName, upperName;
166 StringRef attrName;
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000167 bool isOpt;
Peter Collingbournebee583f2011-10-06 13:03:08 +0000168
169 public:
Aaron Ballman2f22b942014-05-20 19:47:14 +0000170 Argument(const Record &Arg, StringRef Attr)
Peter Collingbournebee583f2011-10-06 13:03:08 +0000171 : lowerName(Arg.getValueAsString("Name")), upperName(lowerName),
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000172 attrName(Attr), isOpt(false) {
Peter Collingbournebee583f2011-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 Ballman8ee40b72013-09-09 23:33:17 +0000184 bool isOptional() const { return isOpt; }
185 void setOptional(bool set) { isOpt = set; }
186
Peter Collingbournebee583f2011-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 {}
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +0000190 virtual void writeASTVisitorTraversal(raw_ostream &OS) const {}
Peter Collingbournebee583f2011-10-06 13:03:08 +0000191 virtual void writeCloneArgs(raw_ostream &OS) const = 0;
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000192 virtual void writeTemplateInstantiationArgs(raw_ostream &OS) const = 0;
Daniel Dunbardc51baa2012-02-10 06:00:29 +0000193 virtual void writeTemplateInstantiation(raw_ostream &OS) const {}
Peter Collingbournebee583f2011-10-06 13:03:08 +0000194 virtual void writeCtorBody(raw_ostream &OS) const {}
195 virtual void writeCtorInitializers(raw_ostream &OS) const = 0;
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000196 virtual void writeCtorDefaultInitializers(raw_ostream &OS) const = 0;
Peter Collingbournebee583f2011-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 Gregor49ccfaa2011-11-19 19:22:57 +0000202 virtual void writeValue(raw_ostream &OS) const = 0;
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000203 virtual void writeDump(raw_ostream &OS) const = 0;
204 virtual void writeDumpChildren(raw_ostream &OS) const {}
Richard Trieude5cc7d2013-01-31 01:44:26 +0000205 virtual void writeHasChildren(raw_ostream &OS) const { OS << "false"; }
Aaron Ballman682ee422013-09-11 19:47:58 +0000206
207 virtual bool isEnumArg() const { return false; }
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000208 virtual bool isVariadicEnumArg() const { return false; }
Aaron Ballman36a53502014-01-16 13:03:14 +0000209
210 virtual void writeImplicitCtorArgs(raw_ostream &OS) const {
211 OS << getUpperName();
212 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000213 };
214
215 class SimpleArgument : public Argument {
216 std::string type;
217
218 public:
Aaron Ballman2f22b942014-05-20 19:47:14 +0000219 SimpleArgument(const Record &Arg, StringRef Attr, std::string T)
Peter Collingbournebee583f2011-10-06 13:03:08 +0000220 : Argument(Arg, Attr), type(T)
221 {}
222
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000223 std::string getType() const { return type; }
224
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000225 void writeAccessors(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000226 OS << " " << type << " get" << getUpperName() << "() const {\n";
227 OS << " return " << getLowerName() << ";\n";
228 OS << " }";
229 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000230 void writeCloneArgs(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000231 OS << getLowerName();
232 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000233 void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000234 OS << "A->get" << getUpperName() << "()";
235 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000236 void writeCtorInitializers(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000237 OS << getLowerName() << "(" << getUpperName() << ")";
238 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000239 void writeCtorDefaultInitializers(raw_ostream &OS) const override {
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000240 OS << getLowerName() << "()";
241 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000242 void writeCtorParameters(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000243 OS << type << " " << getUpperName();
244 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000245 void writeDeclarations(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000246 OS << type << " " << getLowerName() << ";";
247 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000248 void writePCHReadDecls(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000249 std::string read = ReadPCHRecord(type);
250 OS << " " << type << " " << getLowerName() << " = " << read << ";\n";
251 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000252 void writePCHReadArgs(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000253 OS << getLowerName();
254 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000255 void writePCHWrite(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000256 OS << " " << WritePCHRecord(type, "SA->get" +
257 std::string(getUpperName()) + "()");
258 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000259 void writeValue(raw_ostream &OS) const override {
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000260 if (type == "FunctionDecl *") {
Richard Smithb87c4652013-10-31 21:23:20 +0000261 OS << "\" << get" << getUpperName()
262 << "()->getNameInfo().getAsString() << \"";
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000263 } else if (type == "IdentifierInfo *") {
264 OS << "\" << get" << getUpperName() << "()->getName() << \"";
Richard Smithb87c4652013-10-31 21:23:20 +0000265 } else if (type == "TypeSourceInfo *") {
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000266 OS << "\" << get" << getUpperName() << "().getAsString() << \"";
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000267 } else {
268 OS << "\" << get" << getUpperName() << "() << \"";
269 }
270 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000271 void writeDump(raw_ostream &OS) const override {
Alexander Kornienko5bc364e2013-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 Smithb87c4652013-10-31 21:23:20 +0000278 } else if (type == "TypeSourceInfo *") {
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000279 OS << " OS << \" \" << SA->get" << getUpperName()
280 << "().getAsString();\n";
Alexander Kornienko5bc364e2013-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 Collingbournebee583f2011-10-06 13:03:08 +0000290 };
291
Aaron Ballman18a78382013-11-21 00:28:23 +0000292 class DefaultSimpleArgument : public SimpleArgument {
293 int64_t Default;
294
295 public:
Aaron Ballman2f22b942014-05-20 19:47:14 +0000296 DefaultSimpleArgument(const Record &Arg, StringRef Attr,
Aaron Ballman18a78382013-11-21 00:28:23 +0000297 std::string T, int64_t Default)
298 : SimpleArgument(Arg, Attr, T), Default(Default) {}
299
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000300 void writeAccessors(raw_ostream &OS) const override {
Aaron Ballman18a78382013-11-21 00:28:23 +0000301 SimpleArgument::writeAccessors(OS);
302
303 OS << "\n\n static const " << getType() << " Default" << getUpperName()
304 << " = " << Default << ";";
305 }
306 };
307
Peter Collingbournebee583f2011-10-06 13:03:08 +0000308 class StringArgument : public Argument {
309 public:
Aaron Ballman2f22b942014-05-20 19:47:14 +0000310 StringArgument(const Record &Arg, StringRef Attr)
Peter Collingbournebee583f2011-10-06 13:03:08 +0000311 : Argument(Arg, Attr)
312 {}
313
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000314 void writeAccessors(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-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 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000331 void writeCloneArgs(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000332 OS << "get" << getUpperName() << "()";
333 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000334 void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000335 OS << "A->get" << getUpperName() << "()";
336 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000337 void writeCtorBody(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000338 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
339 << ".data(), " << getLowerName() << "Length);";
340 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000341 void writeCtorInitializers(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000342 OS << getLowerName() << "Length(" << getUpperName() << ".size()),"
343 << getLowerName() << "(new (Ctx, 1) char[" << getLowerName()
344 << "Length])";
345 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000346 void writeCtorDefaultInitializers(raw_ostream &OS) const override {
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000347 OS << getLowerName() << "Length(0)," << getLowerName() << "(0)";
348 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000349 void writeCtorParameters(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000350 OS << "llvm::StringRef " << getUpperName();
351 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000352 void writeDeclarations(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000353 OS << "unsigned " << getLowerName() << "Length;\n";
354 OS << "char *" << getLowerName() << ";";
355 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000356 void writePCHReadDecls(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000357 OS << " std::string " << getLowerName()
358 << "= ReadString(Record, Idx);\n";
359 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000360 void writePCHReadArgs(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000361 OS << getLowerName();
362 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000363 void writePCHWrite(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000364 OS << " AddString(SA->get" << getUpperName() << "(), Record);\n";
365 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000366 void writeValue(raw_ostream &OS) const override {
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000367 OS << "\\\"\" << get" << getUpperName() << "() << \"\\\"";
368 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000369 void writeDump(raw_ostream &OS) const override {
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000370 OS << " OS << \" \\\"\" << SA->get" << getUpperName()
371 << "() << \"\\\"\";\n";
372 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000373 };
374
375 class AlignedArgument : public Argument {
376 public:
Aaron Ballman2f22b942014-05-20 19:47:14 +0000377 AlignedArgument(const Record &Arg, StringRef Attr)
Peter Collingbournebee583f2011-10-06 13:03:08 +0000378 : Argument(Arg, Attr)
379 {}
380
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000381 void writeAccessors(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-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 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000400 void writeAccessorDefinitions(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-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 Smithcaf33902011-10-10 18:28:20 +0000422 << "Expr->EvaluateKnownConstInt(Ctx).getZExtValue() : 16)"
Peter Collingbournebee583f2011-10-06 13:03:08 +0000423 << "* Ctx.getCharWidth();\n";
424 OS << " else\n";
425 OS << " return 0; // FIXME\n";
426 OS << "}\n";
427 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000428 void writeCloneArgs(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000429 OS << "is" << getLowerName() << "Expr, is" << getLowerName()
430 << "Expr ? static_cast<void*>(" << getLowerName()
431 << "Expr) : " << getLowerName()
432 << "Type";
433 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000434 void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000435 // FIXME: move the definition in Sema::InstantiateAttrs to here.
436 // In the meantime, aligned attributes are cloned.
437 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000438 void writeCtorBody(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-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 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000447 void writeCtorInitializers(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000448 OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)";
449 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000450 void writeCtorDefaultInitializers(raw_ostream &OS) const override {
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000451 OS << "is" << getLowerName() << "Expr(false)";
452 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000453 void writeCtorParameters(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000454 OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName();
455 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000456 void writeImplicitCtorArgs(raw_ostream &OS) const override {
Aaron Ballman36a53502014-01-16 13:03:14 +0000457 OS << "Is" << getUpperName() << "Expr, " << getUpperName();
458 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000459 void writeDeclarations(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-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 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000466 void writePCHReadArgs(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000467 OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr";
468 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000469 void writePCHReadDecls(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-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 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000478 void writePCHWrite(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-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 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000486 void writeValue(raw_ostream &OS) const override {
Richard Smith52f04a22012-08-16 02:43:29 +0000487 OS << "\";\n"
488 << " " << getLowerName() << "Expr->printPretty(OS, 0, Policy);\n"
489 << " OS << \"";
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000490 }
Craig Topper3164f332014-03-11 03:39:26 +0000491 void writeDump(raw_ostream &OS) const override {
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000492 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000493 void writeDumpChildren(raw_ostream &OS) const override {
Richard Trieude5cc7d2013-01-31 01:44:26 +0000494 OS << " if (SA->is" << getUpperName() << "Expr()) {\n";
495 OS << " lastChild();\n";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000496 OS << " dumpStmt(SA->get" << getUpperName() << "Expr());\n";
Richard Trieude5cc7d2013-01-31 01:44:26 +0000497 OS << " } else\n";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000498 OS << " dumpType(SA->get" << getUpperName()
499 << "Type()->getType());\n";
500 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000501 void writeHasChildren(raw_ostream &OS) const override {
Richard Trieude5cc7d2013-01-31 01:44:26 +0000502 OS << "SA->is" << getUpperName() << "Expr()";
503 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000504 };
505
506 class VariadicArgument : public Argument {
Aaron Ballmana82eaa72014-05-02 13:35:42 +0000507 std::string Type, ArgName, ArgSizeName, RangeName;
Peter Collingbournebee583f2011-10-06 13:03:08 +0000508
509 public:
Aaron Ballman2f22b942014-05-20 19:47:14 +0000510 VariadicArgument(const Record &Arg, StringRef Attr, std::string T)
Aaron Ballmana82eaa72014-05-02 13:35:42 +0000511 : Argument(Arg, Attr), Type(T), ArgName(getLowerName().str() + "_"),
512 ArgSizeName(ArgName + "Size"), RangeName(getLowerName()) {}
Peter Collingbournebee583f2011-10-06 13:03:08 +0000513
Aaron Ballmana82eaa72014-05-02 13:35:42 +0000514 std::string getType() const { return Type; }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000515
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000516 void writeAccessors(raw_ostream &OS) const override {
Aaron Ballmana82eaa72014-05-02 13:35:42 +0000517 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 Collingbournebee583f2011-10-06 13:03:08 +0000531 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000532 void writeCloneArgs(raw_ostream &OS) const override {
Aaron Ballmana82eaa72014-05-02 13:35:42 +0000533 OS << ArgName << ", " << ArgSizeName;
Peter Collingbournebee583f2011-10-06 13:03:08 +0000534 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000535 void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
DeLesley Hutchinsceec3062012-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 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000540 void writeCtorBody(raw_ostream &OS) const override {
Aaron Ballmand6459e52014-05-01 15:21:03 +0000541 OS << " std::copy(" << getUpperName() << ", " << getUpperName()
Aaron Ballmana82eaa72014-05-02 13:35:42 +0000542 << " + " << ArgSizeName << ", " << ArgName << ");";
Peter Collingbournebee583f2011-10-06 13:03:08 +0000543 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000544 void writeCtorInitializers(raw_ostream &OS) const override {
Aaron Ballmana82eaa72014-05-02 13:35:42 +0000545 OS << ArgSizeName << "(" << getUpperName() << "Size), "
546 << ArgName << "(new (Ctx, 16) " << getType() << "["
547 << ArgSizeName << "])";
Peter Collingbournebee583f2011-10-06 13:03:08 +0000548 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000549 void writeCtorDefaultInitializers(raw_ostream &OS) const override {
Aaron Ballmana82eaa72014-05-02 13:35:42 +0000550 OS << ArgSizeName << "(0), " << ArgName << "(nullptr)";
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000551 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000552 void writeCtorParameters(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000553 OS << getType() << " *" << getUpperName() << ", unsigned "
554 << getUpperName() << "Size";
555 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000556 void writeImplicitCtorArgs(raw_ostream &OS) const override {
Aaron Ballman36a53502014-01-16 13:03:14 +0000557 OS << getUpperName() << ", " << getUpperName() << "Size";
558 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000559 void writeDeclarations(raw_ostream &OS) const override {
Aaron Ballmana82eaa72014-05-02 13:35:42 +0000560 OS << " unsigned " << ArgSizeName << ";\n";
561 OS << " " << getType() << " *" << ArgName << ";";
Peter Collingbournebee583f2011-10-06 13:03:08 +0000562 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000563 void writePCHReadDecls(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000564 OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
Aaron Ballmana82eaa72014-05-02 13:35:42 +0000565 OS << " SmallVector<" << Type << ", 4> " << getLowerName()
Peter Collingbournebee583f2011-10-06 13:03:08 +0000566 << ";\n";
567 OS << " " << getLowerName() << ".reserve(" << getLowerName()
568 << "Size);\n";
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000569 OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +0000570
Aaron Ballmana82eaa72014-05-02 13:35:42 +0000571 std::string read = ReadPCHRecord(Type);
Peter Collingbournebee583f2011-10-06 13:03:08 +0000572 OS << " " << getLowerName() << ".push_back(" << read << ");\n";
573 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000574 void writePCHReadArgs(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000575 OS << getLowerName() << ".data(), " << getLowerName() << "Size";
576 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000577 void writePCHWrite(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000578 OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";
Aaron Ballmana82eaa72014-05-02 13:35:42 +0000579 OS << " for (auto &Val : SA->" << RangeName << "())\n";
580 OS << " " << WritePCHRecord(Type, "Val");
Peter Collingbournebee583f2011-10-06 13:03:08 +0000581 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000582 void writeValue(raw_ostream &OS) const override {
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000583 OS << "\";\n";
584 OS << " bool isFirst = true;\n"
Aaron Ballmana82eaa72014-05-02 13:35:42 +0000585 << " for (const auto &Val : " << RangeName << "()) {\n"
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000586 << " if (isFirst) isFirst = false;\n"
587 << " else OS << \", \";\n"
Aaron Ballmana82eaa72014-05-02 13:35:42 +0000588 << " OS << Val;\n"
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000589 << " }\n";
590 OS << " OS << \"";
591 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000592 void writeDump(raw_ostream &OS) const override {
Aaron Ballmana82eaa72014-05-02 13:35:42 +0000593 OS << " for (const auto &Val : SA->" << RangeName << "())\n";
594 OS << " OS << \" \" << Val;\n";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000595 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000596 };
597
Reid Klecknerf526b9482014-02-12 18:22:18 +0000598 // Unique the enums, but maintain the original declaration ordering.
Reid Klecknerf06b2662014-02-12 19:26:24 +0000599 std::vector<std::string>
600 uniqueEnumsInOrder(const std::vector<std::string> &enums) {
Reid Klecknerf526b9482014-02-12 18:22:18 +0000601 std::vector<std::string> uniques;
602 std::set<std::string> unique_set(enums.begin(), enums.end());
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +0000603 for (const auto &i : enums) {
604 std::set<std::string>::iterator set_i = unique_set.find(i);
Reid Klecknerf526b9482014-02-12 18:22:18 +0000605 if (set_i != unique_set.end()) {
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +0000606 uniques.push_back(i);
Reid Klecknerf526b9482014-02-12 18:22:18 +0000607 unique_set.erase(set_i);
608 }
609 }
610 return uniques;
611 }
612
Peter Collingbournebee583f2011-10-06 13:03:08 +0000613 class EnumArgument : public Argument {
614 std::string type;
Aaron Ballman0e468c02014-01-05 21:08:29 +0000615 std::vector<std::string> values, enums, uniques;
Peter Collingbournebee583f2011-10-06 13:03:08 +0000616 public:
Aaron Ballman2f22b942014-05-20 19:47:14 +0000617 EnumArgument(const Record &Arg, StringRef Attr)
Peter Collingbournebee583f2011-10-06 13:03:08 +0000618 : Argument(Arg, Attr), type(Arg.getValueAsString("Type")),
Aaron Ballman0e468c02014-01-05 21:08:29 +0000619 values(Arg.getValueAsListOfStrings("Values")),
620 enums(Arg.getValueAsListOfStrings("Enums")),
Reid Klecknerf526b9482014-02-12 18:22:18 +0000621 uniques(uniqueEnumsInOrder(enums))
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000622 {
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000623 // FIXME: Emit a proper error
624 assert(!uniques.empty());
625 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000626
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000627 bool isEnumArg() const override { return true; }
Aaron Ballman682ee422013-09-11 19:47:58 +0000628
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000629 void writeAccessors(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000630 OS << " " << type << " get" << getUpperName() << "() const {\n";
631 OS << " return " << getLowerName() << ";\n";
632 OS << " }";
633 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000634 void writeCloneArgs(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000635 OS << getLowerName();
636 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000637 void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000638 OS << "A->get" << getUpperName() << "()";
639 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000640 void writeCtorInitializers(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000641 OS << getLowerName() << "(" << getUpperName() << ")";
642 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000643 void writeCtorDefaultInitializers(raw_ostream &OS) const override {
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000644 OS << getLowerName() << "(" << type << "(0))";
645 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000646 void writeCtorParameters(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000647 OS << type << " " << getUpperName();
648 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000649 void writeDeclarations(raw_ostream &OS) const override {
Aaron Ballman0e468c02014-01-05 21:08:29 +0000650 std::vector<std::string>::const_iterator i = uniques.begin(),
651 e = uniques.end();
Peter Collingbournebee583f2011-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 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000664 void writePCHReadDecls(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000665 OS << " " << getAttrName() << "Attr::" << type << " " << getLowerName()
666 << "(static_cast<" << getAttrName() << "Attr::" << type
667 << ">(Record[Idx++]));\n";
668 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000669 void writePCHReadArgs(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000670 OS << getLowerName();
671 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000672 void writePCHWrite(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000673 OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
674 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000675 void writeValue(raw_ostream &OS) const override {
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000676 OS << "\" << get" << getUpperName() << "() << \"";
677 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000678 void writeDump(raw_ostream &OS) const override {
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000679 OS << " switch(SA->get" << getUpperName() << "()) {\n";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +0000680 for (const auto &I : uniques) {
681 OS << " case " << getAttrName() << "Attr::" << I << ":\n";
682 OS << " OS << \" " << I << "\";\n";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000683 OS << " break;\n";
684 }
685 OS << " }\n";
686 }
Aaron Ballman682ee422013-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<";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +0000692 OS << type << ">>(Val)\n";
Aaron Ballman682ee422013-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 Collingbournebee583f2011-10-06 13:03:08 +0000703 };
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000704
705 class VariadicEnumArgument: public VariadicArgument {
706 std::string type, QualifiedTypeName;
Aaron Ballman0e468c02014-01-05 21:08:29 +0000707 std::vector<std::string> values, enums, uniques;
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000708 public:
Aaron Ballman2f22b942014-05-20 19:47:14 +0000709 VariadicEnumArgument(const Record &Arg, StringRef Attr)
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000710 : VariadicArgument(Arg, Attr, Arg.getValueAsString("Type")),
711 type(Arg.getValueAsString("Type")),
Aaron Ballman0e468c02014-01-05 21:08:29 +0000712 values(Arg.getValueAsListOfStrings("Values")),
713 enums(Arg.getValueAsListOfStrings("Enums")),
Reid Klecknerf526b9482014-02-12 18:22:18 +0000714 uniques(uniqueEnumsInOrder(enums))
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000715 {
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000716 QualifiedTypeName = getAttrName().str() + "Attr::" + type;
717
718 // FIXME: Emit a proper error
719 assert(!uniques.empty());
720 }
721
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000722 bool isVariadicEnumArg() const override { return true; }
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000723
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000724 void writeDeclarations(raw_ostream &OS) const override {
Aaron Ballman0e468c02014-01-05 21:08:29 +0000725 std::vector<std::string>::const_iterator i = uniques.begin(),
726 e = uniques.end();
DeLesley Hutchins210791a2013-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 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000740 void writeDump(raw_ostream &OS) const override {
DeLesley Hutchins210791a2013-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";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +0000745 for (const auto &UI : uniques) {
746 OS << " case " << getAttrName() << "Attr::" << UI << ":\n";
747 OS << " OS << \" " << UI << "\";\n";
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000748 OS << " break;\n";
749 }
750 OS << " }\n";
751 OS << " }\n";
752 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000753 void writePCHReadDecls(raw_ostream &OS) const override {
DeLesley Hutchins210791a2013-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 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000763 void writePCHWrite(raw_ostream &OS) const override {
DeLesley Hutchins210791a2013-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<";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +0000774 OS << type << ">>(Val)\n";
DeLesley Hutchins210791a2013-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 Collingbournebee583f2011-10-06 13:03:08 +0000786
787 class VersionArgument : public Argument {
788 public:
Aaron Ballman2f22b942014-05-20 19:47:14 +0000789 VersionArgument(const Record &Arg, StringRef Attr)
Peter Collingbournebee583f2011-10-06 13:03:08 +0000790 : Argument(Arg, Attr)
791 {}
792
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000793 void writeAccessors(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-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 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000802 void writeCloneArgs(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000803 OS << "get" << getUpperName() << "()";
804 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000805 void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000806 OS << "A->get" << getUpperName() << "()";
807 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000808 void writeCtorInitializers(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000809 OS << getLowerName() << "(" << getUpperName() << ")";
810 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000811 void writeCtorDefaultInitializers(raw_ostream &OS) const override {
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000812 OS << getLowerName() << "()";
813 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000814 void writeCtorParameters(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000815 OS << "VersionTuple " << getUpperName();
816 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000817 void writeDeclarations(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000818 OS << "VersionTuple " << getLowerName() << ";\n";
819 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000820 void writePCHReadDecls(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000821 OS << " VersionTuple " << getLowerName()
822 << "= ReadVersionTuple(Record, Idx);\n";
823 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000824 void writePCHReadArgs(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000825 OS << getLowerName();
826 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000827 void writePCHWrite(raw_ostream &OS) const override {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000828 OS << " AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n";
829 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000830 void writeValue(raw_ostream &OS) const override {
Douglas Gregor49ccfaa2011-11-19 19:22:57 +0000831 OS << getLowerName() << "=\" << get" << getUpperName() << "() << \"";
832 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000833 void writeDump(raw_ostream &OS) const override {
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000834 OS << " OS << \" \" << SA->get" << getUpperName() << "();\n";
835 }
Peter Collingbournebee583f2011-10-06 13:03:08 +0000836 };
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000837
838 class ExprArgument : public SimpleArgument {
839 public:
Aaron Ballman2f22b942014-05-20 19:47:14 +0000840 ExprArgument(const Record &Arg, StringRef Attr)
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000841 : SimpleArgument(Arg, Attr, "Expr *")
842 {}
843
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000844 void writeASTVisitorTraversal(raw_ostream &OS) const override {
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +0000845 OS << " if (!"
846 << "getDerived().TraverseStmt(A->get" << getUpperName() << "()))\n";
847 OS << " return false;\n";
848 }
849
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000850 void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000851 OS << "tempInst" << getUpperName();
852 }
853
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000854 void writeTemplateInstantiation(raw_ostream &OS) const override {
DeLesley Hutchinsceec3062012-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() << " = "
Nikola Smiljanic01a75982014-05-29 10:55:11 +0000862 << "Result.getAs<Expr>();\n";
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000863 OS << " }\n";
864 }
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000865
Craig Topper3164f332014-03-11 03:39:26 +0000866 void writeDump(raw_ostream &OS) const override {}
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000867
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000868 void writeDumpChildren(raw_ostream &OS) const override {
Richard Trieude5cc7d2013-01-31 01:44:26 +0000869 OS << " lastChild();\n";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000870 OS << " dumpStmt(SA->get" << getUpperName() << "());\n";
871 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000872 void writeHasChildren(raw_ostream &OS) const override { OS << "true"; }
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000873 };
874
875 class VariadicExprArgument : public VariadicArgument {
876 public:
Aaron Ballman2f22b942014-05-20 19:47:14 +0000877 VariadicExprArgument(const Record &Arg, StringRef Attr)
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000878 : VariadicArgument(Arg, Attr, "Expr *")
879 {}
880
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000881 void writeASTVisitorTraversal(raw_ostream &OS) const override {
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +0000882 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
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000894 void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000895 OS << "tempInst" << getUpperName() << ", "
896 << "A->" << getLowerName() << "_size()";
897 }
898
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000899 void writeTemplateInstantiation(raw_ostream &OS) const override {
DeLesley Hutchinsceec3062012-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";
Nikola Smiljanic01a75982014-05-29 10:55:11 +0000914 OS << " *TI = Result.getAs<Expr>();\n";
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000915 OS << " }\n";
916 OS << " }\n";
917 }
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000918
Craig Topper3164f332014-03-11 03:39:26 +0000919 void writeDump(raw_ostream &OS) const override {}
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000920
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000921 void writeDumpChildren(raw_ostream &OS) const override {
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000922 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
923 << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
Richard Trieude5cc7d2013-01-31 01:44:26 +0000924 << getLowerName() << "_end(); I != E; ++I) {\n";
925 OS << " if (I + 1 == E)\n";
926 OS << " lastChild();\n";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000927 OS << " dumpStmt(*I);\n";
Richard Trieude5cc7d2013-01-31 01:44:26 +0000928 OS << " }\n";
929 }
930
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000931 void writeHasChildren(raw_ostream &OS) const override {
Richard Trieude5cc7d2013-01-31 01:44:26 +0000932 OS << "SA->" << getLowerName() << "_begin() != "
933 << "SA->" << getLowerName() << "_end()";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +0000934 }
DeLesley Hutchinsceec3062012-01-20 22:37:06 +0000935 };
Richard Smithb87c4652013-10-31 21:23:20 +0000936
937 class TypeArgument : public SimpleArgument {
938 public:
Aaron Ballman2f22b942014-05-20 19:47:14 +0000939 TypeArgument(const Record &Arg, StringRef Attr)
Richard Smithb87c4652013-10-31 21:23:20 +0000940 : SimpleArgument(Arg, Attr, "TypeSourceInfo *")
941 {}
942
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000943 void writeAccessors(raw_ostream &OS) const override {
Richard Smithb87c4652013-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 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000951 void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
Richard Smithb87c4652013-10-31 21:23:20 +0000952 OS << "A->get" << getUpperName() << "Loc()";
953 }
Aaron Ballman8cbf6332014-03-06 15:09:50 +0000954 void writePCHWrite(raw_ostream &OS) const override {
Richard Smithb87c4652013-10-31 21:23:20 +0000955 OS << " " << WritePCHRecord(
956 getType(), "SA->get" + std::string(getUpperName()) + "Loc()");
957 }
958 };
Peter Collingbournebee583f2011-10-06 13:03:08 +0000959}
960
Aaron Ballman2f22b942014-05-20 19:47:14 +0000961static std::unique_ptr<Argument>
962createArgument(const Record &Arg, StringRef Attr,
963 const Record *Search = nullptr) {
Peter Collingbournebee583f2011-10-06 13:03:08 +0000964 if (!Search)
965 Search = &Arg;
966
Craig Topper8ae12032014-05-07 06:21:57 +0000967 Argument *Ptr = nullptr;
Peter Collingbournebee583f2011-10-06 13:03:08 +0000968 llvm::StringRef ArgName = Search->getName();
969
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000970 if (ArgName == "AlignedArgument") Ptr = new AlignedArgument(Arg, Attr);
971 else if (ArgName == "EnumArgument") Ptr = new EnumArgument(Arg, Attr);
972 else if (ArgName == "ExprArgument") Ptr = new ExprArgument(Arg, Attr);
Peter Collingbournebee583f2011-10-06 13:03:08 +0000973 else if (ArgName == "FunctionArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000974 Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *");
Peter Collingbournebee583f2011-10-06 13:03:08 +0000975 else if (ArgName == "IdentifierArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000976 Ptr = new SimpleArgument(Arg, Attr, "IdentifierInfo *");
David Majnemer4bb09802014-02-10 19:50:15 +0000977 else if (ArgName == "DefaultBoolArgument")
978 Ptr = new DefaultSimpleArgument(Arg, Attr, "bool",
979 Arg.getValueAsBit("Default"));
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000980 else if (ArgName == "BoolArgument") Ptr = new SimpleArgument(Arg, Attr,
981 "bool");
Aaron Ballman18a78382013-11-21 00:28:23 +0000982 else if (ArgName == "DefaultIntArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000983 Ptr = new DefaultSimpleArgument(Arg, Attr, "int",
984 Arg.getValueAsInt("Default"));
985 else if (ArgName == "IntArgument") Ptr = new SimpleArgument(Arg, Attr, "int");
986 else if (ArgName == "StringArgument") Ptr = new StringArgument(Arg, Attr);
987 else if (ArgName == "TypeArgument") Ptr = new TypeArgument(Arg, Attr);
Peter Collingbournebee583f2011-10-06 13:03:08 +0000988 else if (ArgName == "UnsignedArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000989 Ptr = new SimpleArgument(Arg, Attr, "unsigned");
Peter Collingbournebee583f2011-10-06 13:03:08 +0000990 else if (ArgName == "VariadicUnsignedArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000991 Ptr = new VariadicArgument(Arg, Attr, "unsigned");
DeLesley Hutchins210791a2013-10-04 21:28:06 +0000992 else if (ArgName == "VariadicEnumArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000993 Ptr = new VariadicEnumArgument(Arg, Attr);
Peter Collingbournebee583f2011-10-06 13:03:08 +0000994 else if (ArgName == "VariadicExprArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000995 Ptr = new VariadicExprArgument(Arg, Attr);
Peter Collingbournebee583f2011-10-06 13:03:08 +0000996 else if (ArgName == "VersionArgument")
Aaron Ballmanaa47d242013-12-19 19:39:25 +0000997 Ptr = new VersionArgument(Arg, Attr);
Peter Collingbournebee583f2011-10-06 13:03:08 +0000998
999 if (!Ptr) {
Aaron Ballman18a78382013-11-21 00:28:23 +00001000 // Search in reverse order so that the most-derived type is handled first.
Peter Collingbournebee583f2011-10-06 13:03:08 +00001001 std::vector<Record*> Bases = Search->getSuperClasses();
Aaron Ballman2f22b942014-05-20 19:47:14 +00001002 for (const auto *Base : llvm::make_range(Bases.rbegin(), Bases.rend())) {
1003 Ptr = createArgument(Arg, Attr, Base).release();
Peter Collingbournebee583f2011-10-06 13:03:08 +00001004 if (Ptr)
1005 break;
1006 }
1007 }
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001008
1009 if (Ptr && Arg.getValueAsBit("Optional"))
1010 Ptr->setOptional(true);
1011
Aaron Ballman8f1439b2014-03-05 16:49:55 +00001012 return std::unique_ptr<Argument>(Ptr);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001013}
1014
Douglas Gregor49ccfaa2011-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
Aaron Ballman3e424b52013-12-26 18:30:57 +00001024static void writeGetSpellingFunction(Record &R, raw_ostream &OS) {
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001025 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
Aaron Ballman3e424b52013-12-26 18:30:57 +00001026
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"
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001040 " return \"" << Spellings[I].name() << "\";\n";
Aaron Ballman3e424b52013-12-26 18:30:57 +00001041 // End of the switch statement.
1042 OS << " }\n";
1043 // End of the getSpelling function.
1044 OS << "}\n\n";
1045}
1046
Aaron Ballman8f1439b2014-03-05 16:49:55 +00001047static void
1048writePrettyPrintFunction(Record &R,
1049 const std::vector<std::unique_ptr<Argument>> &Args,
1050 raw_ostream &OS) {
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001051 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
Michael Han99315932013-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;
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001073 std::string Name = Spellings[I].name();
1074 std::string Variety = Spellings[I].variety();
Michael Han99315932013-01-24 16:46:58 +00001075
1076 if (Variety == "GNU") {
1077 Prefix = " __attribute__((";
1078 Suffix = "))";
1079 } else if (Variety == "CXX11") {
1080 Prefix = " [[";
1081 Suffix = "]]";
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001082 std::string Namespace = Spellings[I].nameSpace();
Michael Han99315932013-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 Smith0cdcc982013-01-29 01:24:26 +00001090 } else if (Variety == "Keyword") {
1091 Prefix = " ";
1092 Suffix = "";
Michael Han99315932013-01-24 16:46:58 +00001093 } else {
Richard Smith0cdcc982013-01-29 01:24:26 +00001094 llvm_unreachable("Unknown attribute syntax variety!");
Michael Han99315932013-01-24 16:46:58 +00001095 }
1096
1097 Spelling += Name;
1098
1099 OS <<
1100 " case " << I << " : {\n"
1101 " OS << \"" + Prefix.str() + Spelling.str();
1102
Aaron Ballman8f1439b2014-03-05 16:49:55 +00001103 if (!Args.empty())
1104 OS << "(";
Michael Han99315932013-01-24 16:46:58 +00001105 if (Spelling == "availability") {
1106 writeAvailabilityValue(OS);
1107 } else {
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001108 for (auto I = Args.begin(), E = Args.end(); I != E; ++ I) {
Michael Han99315932013-01-24 16:46:58 +00001109 if (I != Args.begin()) OS << ", ";
1110 (*I)->writeValue(OS);
1111 }
1112 }
1113
Aaron Ballman8f1439b2014-03-05 16:49:55 +00001114 if (!Args.empty())
1115 OS << ")";
Michael Han99315932013-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 Hanaf02bbe2013-02-01 01:19:17 +00001129/// \brief Return the index of a spelling in a spelling list.
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001130static unsigned
1131getSpellingListIndex(const std::vector<FlattenedSpelling> &SpellingList,
1132 const FlattenedSpelling &Spelling) {
Michael Hanaf02bbe2013-02-01 01:19:17 +00001133 assert(SpellingList.size() && "Spelling list is empty!");
1134
1135 for (unsigned Index = 0; Index < SpellingList.size(); ++Index) {
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001136 const FlattenedSpelling &S = SpellingList[Index];
1137 if (S.variety() != Spelling.variety())
Michael Hanaf02bbe2013-02-01 01:19:17 +00001138 continue;
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001139 if (S.nameSpace() != Spelling.nameSpace())
Michael Hanaf02bbe2013-02-01 01:19:17 +00001140 continue;
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001141 if (S.name() != Spelling.name())
Michael Hanaf02bbe2013-02-01 01:19:17 +00001142 continue;
1143
1144 return Index;
1145 }
1146
1147 llvm_unreachable("Unknown spelling!");
1148}
1149
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001150static void writeAttrAccessorDefinition(const Record &R, raw_ostream &OS) {
Michael Hanaf02bbe2013-02-01 01:19:17 +00001151 std::vector<Record*> Accessors = R.getValueAsListOfDefs("Accessors");
Aaron Ballman2f22b942014-05-20 19:47:14 +00001152 for (const auto *Accessor : Accessors) {
Michael Hanaf02bbe2013-02-01 01:19:17 +00001153 std::string Name = Accessor->getValueAsString("Name");
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001154 std::vector<FlattenedSpelling> Spellings =
1155 GetFlattenedSpellings(*Accessor);
1156 std::vector<FlattenedSpelling> SpellingList = GetFlattenedSpellings(R);
Michael Hanaf02bbe2013-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) {
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001162 OS << getSpellingListIndex(SpellingList, Spellings[Index]);
Michael Hanaf02bbe2013-02-01 01:19:17 +00001163 if (Index != Spellings.size() -1)
1164 OS << " ||\n SpellingListIndex == ";
1165 else
1166 OS << "; }\n";
1167 }
1168 }
1169}
1170
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001171static bool
1172SpellingNamesAreCommon(const std::vector<FlattenedSpelling>& Spellings) {
Aaron Ballman36a53502014-01-16 13:03:14 +00001173 assert(!Spellings.empty() && "An empty list of spellings was provided");
1174 std::string FirstName = NormalizeNameForSpellingComparison(
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001175 Spellings.front().name());
Aaron Ballman2f22b942014-05-20 19:47:14 +00001176 for (const auto &Spelling :
1177 llvm::make_range(std::next(Spellings.begin()), Spellings.end())) {
1178 std::string Name = NormalizeNameForSpellingComparison(Spelling.name());
Aaron Ballman36a53502014-01-16 13:03:14 +00001179 if (Name != FirstName)
1180 return false;
1181 }
1182 return true;
1183}
1184
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001185typedef std::map<unsigned, std::string> SemanticSpellingMap;
1186static std::string
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001187CreateSemanticSpellings(const std::vector<FlattenedSpelling> &Spellings,
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001188 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;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001196 for (auto I = Spellings.begin(), E = Spellings.end(); I != E; ++I, ++Idx) {
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001197 const FlattenedSpelling &S = *I;
1198 std::string Variety = S.variety();
1199 std::string Spelling = S.name();
1200 std::string Namespace = S.nameSpace();
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001201 std::string EnumName = "";
1202
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001203 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";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001234 for (const auto &I : Map)
1235 OS << " case " << I.first << ": return " << I.second << ";\n";
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001236 OS << " }\n";
1237}
1238
Aaron Ballman35db2b32014-01-29 22:13:45 +00001239// 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
Aaron Ballman2f22b942014-05-20 19:47:14 +00001244 for (const auto *Attr : Attrs) {
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001245 bool LateParsed = Attr->getValueAsBit("LateParsed");
Aaron Ballman35db2b32014-01-29 22:13:45 +00001246
1247 if (LateParsed) {
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001248 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr);
Aaron Ballman35db2b32014-01-29 22:13:45 +00001249
1250 // FIXME: Handle non-GNU attributes
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001251 for (const auto &I : Spellings) {
1252 if (I.variety() != "GNU")
Aaron Ballman35db2b32014-01-29 22:13:45 +00001253 continue;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001254 OS << ".Case(\"" << I.name() << "\", " << LateParsed << ")\n";
Aaron Ballman35db2b32014-01-29 22:13:45 +00001255 }
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
Aaron Ballman2f22b942014-05-20 19:47:14 +00001266 for (const auto *Attr : Attrs) {
Aaron Ballman35db2b32014-01-29 22:13:45 +00001267 // Determine whether the first argument is a type.
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001268 std::vector<Record *> Args = Attr->getValueAsListOfDefs("Args");
Aaron Ballman35db2b32014-01-29 22:13:45 +00001269 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.
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001276 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr);
Aaron Ballman35db2b32014-01-29 22:13:45 +00001277 std::set<std::string> Emitted;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001278 for (const auto &S : Spellings) {
1279 if (Emitted.insert(S.name()).second)
1280 OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n";
Aaron Ballman35db2b32014-01-29 22:13:45 +00001281 }
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);
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001291 for (const auto &I : Attrs) {
1292 const Record &Attr = *I.second;
Aaron Ballman35db2b32014-01-29 22:13:45 +00001293
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;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001300 for (const auto &S : Spellings) {
1301 if (Emitted.insert(S.name()).second)
1302 OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n";
Aaron Ballman35db2b32014-01-29 22:13:45 +00001303 }
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
Aaron Ballman2f22b942014-05-20 19:47:14 +00001321 for (const auto *Attr : Attrs) {
Aaron Ballman35db2b32014-01-29 22:13:45 +00001322 // Determine whether the first argument is an identifier.
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001323 std::vector<Record *> Args = Attr->getValueAsListOfDefs("Args");
Aaron Ballman35db2b32014-01-29 22:13:45 +00001324 if (Args.empty() || !isIdentifierArgument(Args[0]))
1325 continue;
1326
1327 // All these spellings take an identifier argument.
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001328 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr);
Aaron Ballman35db2b32014-01-29 22:13:45 +00001329 std::set<std::string> Emitted;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001330 for (const auto &S : Spellings) {
1331 if (Emitted.insert(S.name()).second)
1332 OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n";
Aaron Ballman35db2b32014-01-29 22:13:45 +00001333 }
1334 }
1335 OS << "#endif // CLANG_ATTR_IDENTIFIER_ARG_LIST\n\n";
1336}
1337
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001338namespace clang {
1339
1340// Emits the class definitions for attributes.
1341void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00001342 emitSourceFileHeader("Attribute classes' definitions", OS);
1343
Peter Collingbournebee583f2011-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
Aaron Ballman2f22b942014-05-20 19:47:14 +00001349 for (const auto *Attr : Attrs) {
1350 const Record &R = *Attr;
Aaron Ballman06bd44b2014-02-17 18:23:02 +00001351
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 Gregorb2daf842012-05-02 15:56:52 +00001362
1363 if (!R.getValueAsBit("ASTNode"))
1364 continue;
1365
Aaron Ballman0979e9e2013-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 Ballman0979e9e2013-07-30 01:44:15 +00001368 std::string SuperName;
Aaron Ballman2f22b942014-05-20 19:47:14 +00001369 for (const auto *Super : llvm::make_range(Supers.rbegin(), Supers.rend())) {
1370 const Record &R = *Super;
Aaron Ballman080cad72013-07-31 02:20:22 +00001371 if (R.getName() != "TargetSpecificAttr" && SuperName.empty())
Aaron Ballman0979e9e2013-07-30 01:44:15 +00001372 SuperName = R.getName();
1373 }
Peter Collingbournebee583f2011-10-06 13:03:08 +00001374
1375 OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n";
1376
1377 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
Aaron Ballman8f1439b2014-03-05 16:49:55 +00001378 std::vector<std::unique_ptr<Argument>> Args;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001379 Args.reserve(ArgRecords.size());
1380
Aaron Ballman2f22b942014-05-20 19:47:14 +00001381 for (const auto *ArgRecord : ArgRecords) {
Aaron Ballman8f1439b2014-03-05 16:49:55 +00001382 Args.emplace_back(createArgument(*ArgRecord, R.getName()));
1383 Args.back()->writeDeclarations(OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001384 OS << "\n\n";
1385 }
1386
Aaron Ballman36a53502014-01-16 13:03:14 +00001387 OS << "\npublic:\n";
1388
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001389 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
Aaron Ballman36a53502014-01-16 13:03:14 +00001390
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
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001397 // This maps spelling index values to semantic Spelling enumerants.
1398 SemanticSpellingMap SemanticToSyntacticMap;
Aaron Ballman36a53502014-01-16 13:03:14 +00001399
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001400 if (!ElideSpelling)
1401 OS << CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);
Aaron Ballman36a53502014-01-16 13:03:14 +00001402
1403 OS << " static " << R.getName() << "Attr *CreateImplicit(";
1404 OS << "ASTContext &Ctx";
1405 if (!ElideSpelling)
1406 OS << ", Spelling S";
Aaron Ballman8f1439b2014-03-05 16:49:55 +00001407 for (auto const &ai : Args) {
Aaron Ballman36a53502014-01-16 13:03:14 +00001408 OS << ", ";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001409 ai->writeCtorParameters(OS);
Aaron Ballman36a53502014-01-16 13:03:14 +00001410 }
1411 OS << ", SourceRange Loc = SourceRange()";
1412 OS << ") {\n";
1413 OS << " " << R.getName() << "Attr *A = new (Ctx) " << R.getName();
1414 OS << "Attr(Loc, Ctx, ";
Aaron Ballman8f1439b2014-03-05 16:49:55 +00001415 for (auto const &ai : Args) {
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001416 ai->writeImplicitCtorArgs(OS);
Aaron Ballman36a53502014-01-16 13:03:14 +00001417 OS << ", ";
1418 }
1419 OS << (ElideSpelling ? "0" : "S") << ");\n";
1420 OS << " A->setImplicit(true);\n";
1421 OS << " return A;\n }\n\n";
1422
Peter Collingbournebee583f2011-10-06 13:03:08 +00001423 OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
1424
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001425 bool HasOpt = false;
Aaron Ballman8f1439b2014-03-05 16:49:55 +00001426 for (auto const &ai : Args) {
Peter Collingbournebee583f2011-10-06 13:03:08 +00001427 OS << " , ";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001428 ai->writeCtorParameters(OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001429 OS << "\n";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001430 if (ai->isOptional())
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001431 HasOpt = true;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001432 }
Michael Han99315932013-01-24 16:46:58 +00001433
1434 OS << " , ";
Aaron Ballman36a53502014-01-16 13:03:14 +00001435 OS << "unsigned SI\n";
Michael Han99315932013-01-24 16:46:58 +00001436
Peter Collingbournebee583f2011-10-06 13:03:08 +00001437 OS << " )\n";
Michael Han99315932013-01-24 16:46:58 +00001438 OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001439
Aaron Ballman8f1439b2014-03-05 16:49:55 +00001440 for (auto const &ai : Args) {
Peter Collingbournebee583f2011-10-06 13:03:08 +00001441 OS << " , ";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001442 ai->writeCtorInitializers(OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001443 OS << "\n";
1444 }
1445
1446 OS << " {\n";
1447
Aaron Ballman8f1439b2014-03-05 16:49:55 +00001448 for (auto const &ai : Args) {
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001449 ai->writeCtorBody(OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001450 OS << "\n";
1451 }
1452 OS << " }\n\n";
1453
Aaron Ballman8ee40b72013-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";
Aaron Ballman8f1439b2014-03-05 16:49:55 +00001458 for (auto const &ai : Args) {
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001459 if (!ai->isOptional()) {
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001460 OS << " , ";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001461 ai->writeCtorParameters(OS);
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001462 OS << "\n";
1463 }
1464 }
1465
1466 OS << " , ";
Aaron Ballman36a53502014-01-16 13:03:14 +00001467 OS << "unsigned SI\n";
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001468
1469 OS << " )\n";
1470 OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n";
1471
Aaron Ballman8f1439b2014-03-05 16:49:55 +00001472 for (auto const &ai : Args) {
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001473 OS << " , ";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001474 ai->writeCtorDefaultInitializers(OS);
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001475 OS << "\n";
1476 }
1477
1478 OS << " {\n";
1479
Aaron Ballman8f1439b2014-03-05 16:49:55 +00001480 for (auto const &ai : Args) {
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001481 if (!ai->isOptional()) {
1482 ai->writeCtorBody(OS);
Aaron Ballman8ee40b72013-09-09 23:33:17 +00001483 OS << "\n";
1484 }
1485 }
1486 OS << " }\n\n";
1487 }
1488
Craig Toppercbce6e92014-03-11 06:22:39 +00001489 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";
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00001493
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 Collingbournebee583f2011-10-06 13:03:08 +00001501
Michael Hanaf02bbe2013-02-01 01:19:17 +00001502 writeAttrAccessorDefinition(R, OS);
1503
Aaron Ballman8f1439b2014-03-05 16:49:55 +00001504 for (auto const &ai : Args) {
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001505 ai->writeAccessors(OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001506 OS << "\n\n";
Aaron Ballman682ee422013-09-11 19:47:58 +00001507
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001508 if (ai->isEnumArg())
Aaron Ballman8f1439b2014-03-05 16:49:55 +00001509 static_cast<const EnumArgument *>(ai.get())->writeConversion(OS);
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001510 else if (ai->isVariadicEnumArg())
Aaron Ballman8f1439b2014-03-05 16:49:55 +00001511 static_cast<const VariadicEnumArgument *>(ai.get())
1512 ->writeConversion(OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001513 }
1514
Jakob Stoklund Olesen6f2288b62012-01-13 04:57:47 +00001515 OS << R.getValueAsString("AdditionalMembers");
Peter Collingbournebee583f2011-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 Hutchins30398dd2012-01-20 22:50:54 +00001520
1521 bool LateParsed = R.getValueAsBit("LateParsed");
Craig Toppercbce6e92014-03-11 06:22:39 +00001522 OS << " bool isLateParsed() const override { return "
DeLesley Hutchins30398dd2012-01-20 22:50:54 +00001523 << LateParsed << "; }\n";
1524
Aaron Ballmanb9023ed2014-01-20 18:07:09 +00001525 if (R.getValueAsBit("DuplicatesAllowedWhileMerging"))
Craig Toppercbce6e92014-03-11 06:22:39 +00001526 OS << " bool duplicatesAllowed() const override { return true; }\n\n";
Aaron Ballmanb9023ed2014-01-20 18:07:09 +00001527
Peter Collingbournebee583f2011-10-06 13:03:08 +00001528 OS << "};\n\n";
1529 }
1530
1531 OS << "#endif\n";
1532}
1533
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001534// Emits the class method definitions for attributes.
1535void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00001536 emitSourceFileHeader("Attribute classes' member function definitions", OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001537
1538 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
Peter Collingbournebee583f2011-10-06 13:03:08 +00001539
Aaron Ballman2f22b942014-05-20 19:47:14 +00001540 for (auto *Attr : Attrs) {
1541 Record &R = *Attr;
Douglas Gregorb2daf842012-05-02 15:56:52 +00001542
1543 if (!R.getValueAsBit("ASTNode"))
1544 continue;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001545
Aaron Ballman8f1439b2014-03-05 16:49:55 +00001546 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
1547 std::vector<std::unique_ptr<Argument>> Args;
Aaron Ballman2f22b942014-05-20 19:47:14 +00001548 for (const auto *Arg : ArgRecords)
1549 Args.emplace_back(createArgument(*Arg, R.getName()));
Aaron Ballman8f1439b2014-03-05 16:49:55 +00001550
1551 for (auto const &ai : Args)
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001552 ai->writeAccessorDefinitions(OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001553
1554 OS << R.getName() << "Attr *" << R.getName()
1555 << "Attr::clone(ASTContext &C) const {\n";
Hans Wennborg613807b2014-05-31 01:30:30 +00001556 OS << " auto *A = new (C) " << R.getName() << "Attr(getLocation(), C";
Aaron Ballman8f1439b2014-03-05 16:49:55 +00001557 for (auto const &ai : Args) {
Peter Collingbournebee583f2011-10-06 13:03:08 +00001558 OS << ", ";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001559 ai->writeCloneArgs(OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001560 }
Hans Wennborg613807b2014-05-31 01:30:30 +00001561 OS << ", getSpellingListIndex());\n";
1562 OS << " A->Inherited = Inherited;\n";
1563 OS << " A->IsPackExpansion = IsPackExpansion;\n";
1564 OS << " A->Implicit = Implicit;\n";
1565 OS << " return A;\n}\n\n";
Douglas Gregor49ccfaa2011-11-19 19:22:57 +00001566
Michael Han99315932013-01-24 16:46:58 +00001567 writePrettyPrintFunction(R, Args, OS);
Aaron Ballman3e424b52013-12-26 18:30:57 +00001568 writeGetSpellingFunction(R, OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001569 }
1570}
1571
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001572} // end namespace clang
1573
Peter Collingbournebee583f2011-10-06 13:03:08 +00001574static void EmitAttrList(raw_ostream &OS, StringRef Class,
1575 const std::vector<Record*> &AttrList) {
1576 std::vector<Record*>::const_iterator i = AttrList.begin(), e = AttrList.end();
1577
1578 if (i != e) {
1579 // Move the end iterator back to emit the last attribute.
Douglas Gregorb2daf842012-05-02 15:56:52 +00001580 for(--e; i != e; ++i) {
1581 if (!(*i)->getValueAsBit("ASTNode"))
1582 continue;
1583
Peter Collingbournebee583f2011-10-06 13:03:08 +00001584 OS << Class << "(" << (*i)->getName() << ")\n";
Douglas Gregorb2daf842012-05-02 15:56:52 +00001585 }
Peter Collingbournebee583f2011-10-06 13:03:08 +00001586
1587 OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n";
1588 }
1589}
1590
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001591namespace clang {
1592
1593// Emits the enumeration list for attributes.
1594void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00001595 emitSourceFileHeader("List of all attributes that Clang recognizes", OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001596
1597 OS << "#ifndef LAST_ATTR\n";
1598 OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n";
1599 OS << "#endif\n\n";
1600
1601 OS << "#ifndef INHERITABLE_ATTR\n";
1602 OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n";
1603 OS << "#endif\n\n";
1604
1605 OS << "#ifndef LAST_INHERITABLE_ATTR\n";
1606 OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n";
1607 OS << "#endif\n\n";
1608
1609 OS << "#ifndef INHERITABLE_PARAM_ATTR\n";
1610 OS << "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n";
1611 OS << "#endif\n\n";
1612
1613 OS << "#ifndef LAST_INHERITABLE_PARAM_ATTR\n";
1614 OS << "#define LAST_INHERITABLE_PARAM_ATTR(NAME)"
1615 " INHERITABLE_PARAM_ATTR(NAME)\n";
1616 OS << "#endif\n\n";
1617
1618 Record *InhClass = Records.getClass("InheritableAttr");
1619 Record *InhParamClass = Records.getClass("InheritableParamAttr");
1620 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
Aaron Ballman8edb5c22013-12-18 23:44:18 +00001621 NonInhAttrs, InhAttrs, InhParamAttrs;
Aaron Ballman2f22b942014-05-20 19:47:14 +00001622 for (auto *Attr : Attrs) {
1623 if (!Attr->getValueAsBit("ASTNode"))
Douglas Gregorb2daf842012-05-02 15:56:52 +00001624 continue;
1625
Aaron Ballman2f22b942014-05-20 19:47:14 +00001626 if (Attr->isSubClassOf(InhParamClass))
1627 InhParamAttrs.push_back(Attr);
1628 else if (Attr->isSubClassOf(InhClass))
1629 InhAttrs.push_back(Attr);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001630 else
Aaron Ballman2f22b942014-05-20 19:47:14 +00001631 NonInhAttrs.push_back(Attr);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001632 }
1633
1634 EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs);
1635 EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs);
1636 EmitAttrList(OS, "ATTR", NonInhAttrs);
1637
1638 OS << "#undef LAST_ATTR\n";
1639 OS << "#undef INHERITABLE_ATTR\n";
1640 OS << "#undef LAST_INHERITABLE_ATTR\n";
1641 OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n";
1642 OS << "#undef ATTR\n";
1643}
1644
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001645// Emits the code to read an attribute from a precompiled header.
1646void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00001647 emitSourceFileHeader("Attribute deserialization code", OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001648
1649 Record *InhClass = Records.getClass("InheritableAttr");
1650 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
1651 ArgRecords;
Aaron Ballman8f1439b2014-03-05 16:49:55 +00001652 std::vector<std::unique_ptr<Argument>> Args;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001653
1654 OS << " switch (Kind) {\n";
1655 OS << " default:\n";
1656 OS << " assert(0 && \"Unknown attribute!\");\n";
1657 OS << " break;\n";
Aaron Ballman2f22b942014-05-20 19:47:14 +00001658 for (const auto *Attr : Attrs) {
1659 const Record &R = *Attr;
Douglas Gregorb2daf842012-05-02 15:56:52 +00001660 if (!R.getValueAsBit("ASTNode"))
1661 continue;
1662
Peter Collingbournebee583f2011-10-06 13:03:08 +00001663 OS << " case attr::" << R.getName() << ": {\n";
1664 if (R.isSubClassOf(InhClass))
1665 OS << " bool isInherited = Record[Idx++];\n";
Aaron Ballman36a53502014-01-16 13:03:14 +00001666 OS << " bool isImplicit = Record[Idx++];\n";
1667 OS << " unsigned Spelling = Record[Idx++];\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001668 ArgRecords = R.getValueAsListOfDefs("Args");
1669 Args.clear();
Aaron Ballman2f22b942014-05-20 19:47:14 +00001670 for (const auto *Arg : ArgRecords) {
1671 Args.emplace_back(createArgument(*Arg, R.getName()));
Aaron Ballman8f1439b2014-03-05 16:49:55 +00001672 Args.back()->writePCHReadDecls(OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001673 }
1674 OS << " New = new (Context) " << R.getName() << "Attr(Range, Context";
Aaron Ballman8f1439b2014-03-05 16:49:55 +00001675 for (auto const &ri : Args) {
Peter Collingbournebee583f2011-10-06 13:03:08 +00001676 OS << ", ";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001677 ri->writePCHReadArgs(OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001678 }
Aaron Ballman36a53502014-01-16 13:03:14 +00001679 OS << ", Spelling);\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001680 if (R.isSubClassOf(InhClass))
1681 OS << " cast<InheritableAttr>(New)->setInherited(isInherited);\n";
Aaron Ballman36a53502014-01-16 13:03:14 +00001682 OS << " New->setImplicit(isImplicit);\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001683 OS << " break;\n";
1684 OS << " }\n";
1685 }
1686 OS << " }\n";
1687}
1688
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001689// Emits the code to write an attribute to a precompiled header.
1690void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00001691 emitSourceFileHeader("Attribute serialization code", OS);
1692
Peter Collingbournebee583f2011-10-06 13:03:08 +00001693 Record *InhClass = Records.getClass("InheritableAttr");
1694 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001695
1696 OS << " switch (A->getKind()) {\n";
1697 OS << " default:\n";
1698 OS << " llvm_unreachable(\"Unknown attribute kind!\");\n";
1699 OS << " break;\n";
Aaron Ballman2f22b942014-05-20 19:47:14 +00001700 for (const auto *Attr : Attrs) {
1701 const Record &R = *Attr;
Douglas Gregorb2daf842012-05-02 15:56:52 +00001702 if (!R.getValueAsBit("ASTNode"))
1703 continue;
Peter Collingbournebee583f2011-10-06 13:03:08 +00001704 OS << " case attr::" << R.getName() << ": {\n";
1705 Args = R.getValueAsListOfDefs("Args");
1706 if (R.isSubClassOf(InhClass) || !Args.empty())
1707 OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
1708 << "Attr>(A);\n";
1709 if (R.isSubClassOf(InhClass))
1710 OS << " Record.push_back(SA->isInherited());\n";
Aaron Ballman36a53502014-01-16 13:03:14 +00001711 OS << " Record.push_back(A->isImplicit());\n";
1712 OS << " Record.push_back(A->getSpellingListIndex());\n";
1713
Aaron Ballman2f22b942014-05-20 19:47:14 +00001714 for (const auto *Arg : Args)
1715 createArgument(*Arg, R.getName())->writePCHWrite(OS);
Peter Collingbournebee583f2011-10-06 13:03:08 +00001716 OS << " break;\n";
1717 OS << " }\n";
1718 }
1719 OS << " }\n";
1720}
1721
Aaron Ballman2fbf9942014-03-31 13:14:44 +00001722static void GenerateHasAttrSpellingStringSwitch(
1723 const std::vector<Record *> &Attrs, raw_ostream &OS,
1724 const std::string &Variety = "", const std::string &Scope = "") {
1725 for (const auto *Attr : Attrs) {
Aaron Ballman0fa06d82014-01-09 22:57:44 +00001726 // It is assumed that there will be an llvm::Triple object named T within
1727 // scope that can be used to determine whether the attribute exists in
1728 // a given target.
1729 std::string Test;
Aaron Ballman2fbf9942014-03-31 13:14:44 +00001730 if (Attr->isSubClassOf("TargetSpecificAttr")) {
1731 const Record *R = Attr->getValueAsDef("Target");
Aaron Ballman0fa06d82014-01-09 22:57:44 +00001732 std::vector<std::string> Arches = R->getValueAsListOfStrings("Arches");
Peter Collingbournebee583f2011-10-06 13:03:08 +00001733
Aaron Ballman0fa06d82014-01-09 22:57:44 +00001734 Test += "(";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001735 for (auto AI = Arches.begin(), AE = Arches.end(); AI != AE; ++AI) {
Aaron Ballman0fa06d82014-01-09 22:57:44 +00001736 std::string Part = *AI;
1737 Test += "T.getArch() == llvm::Triple::" + Part;
1738 if (AI + 1 != AE)
1739 Test += " || ";
1740 }
1741 Test += ")";
1742
1743 std::vector<std::string> OSes;
1744 if (!R->isValueUnset("OSes")) {
1745 Test += " && (";
1746 std::vector<std::string> OSes = R->getValueAsListOfStrings("OSes");
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001747 for (auto AI = OSes.begin(), AE = OSes.end(); AI != AE; ++AI) {
Aaron Ballman0fa06d82014-01-09 22:57:44 +00001748 std::string Part = *AI;
1749
1750 Test += "T.getOS() == llvm::Triple::" + Part;
1751 if (AI + 1 != AE)
1752 Test += " || ";
1753 }
1754 Test += ")";
1755 }
Aaron Ballman2fbf9942014-03-31 13:14:44 +00001756
1757 // If this is the C++11 variety, also add in the LangOpts test.
1758 if (Variety == "CXX11")
1759 Test += " && LangOpts.CPlusPlus11";
1760 } else if (Variety == "CXX11")
1761 // C++11 mode should be checked against LangOpts, which is presumed to be
1762 // present in the caller.
1763 Test = "LangOpts.CPlusPlus11";
1764 else
Aaron Ballman0fa06d82014-01-09 22:57:44 +00001765 Test = "true";
1766
Aaron Ballman2fbf9942014-03-31 13:14:44 +00001767 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr);
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001768 for (const auto &S : Spellings)
Aaron Ballman2fbf9942014-03-31 13:14:44 +00001769 if (Variety.empty() || (Variety == S.variety() &&
1770 (Scope.empty() || Scope == S.nameSpace())))
1771 OS << " .Case(\"" << S.name() << "\", " << Test << ")\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001772 }
Aaron Ballman2fbf9942014-03-31 13:14:44 +00001773 OS << " .Default(false);\n";
1774}
1775
1776// Emits the list of spellings for attributes.
1777void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
1778 emitSourceFileHeader("Code to implement the __has_attribute logic", OS);
1779
1780 // Separate all of the attributes out into four group: generic, C++11, GNU,
1781 // and declspecs. Then generate a big switch statement for each of them.
1782 std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
1783 std::vector<Record *> Declspec, GNU;
1784 std::map<std::string, std::vector<Record *>> CXX;
1785
1786 // Walk over the list of all attributes, and split them out based on the
1787 // spelling variety.
1788 for (auto *R : Attrs) {
1789 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*R);
1790 for (const auto &SI : Spellings) {
1791 std::string Variety = SI.variety();
1792 if (Variety == "GNU")
1793 GNU.push_back(R);
1794 else if (Variety == "Declspec")
1795 Declspec.push_back(R);
1796 else if (Variety == "CXX11") {
1797 CXX[SI.nameSpace()].push_back(R);
1798 }
1799 }
1800 }
1801
1802 OS << "switch (Syntax) {\n";
1803 OS << "case AttrSyntax::Generic:\n";
1804 OS << " return llvm::StringSwitch<bool>(Name)\n";
1805 GenerateHasAttrSpellingStringSwitch(Attrs, OS);
1806 OS << "case AttrSyntax::GNU:\n";
1807 OS << " return llvm::StringSwitch<bool>(Name)\n";
1808 GenerateHasAttrSpellingStringSwitch(GNU, OS, "GNU");
1809 OS << "case AttrSyntax::Declspec:\n";
1810 OS << " return llvm::StringSwitch<bool>(Name)\n";
1811 GenerateHasAttrSpellingStringSwitch(Declspec, OS, "Declspec");
1812 OS << "case AttrSyntax::CXX: {\n";
1813 // C++11-style attributes are further split out based on the Scope.
1814 for (std::map<std::string, std::vector<Record *>>::iterator I = CXX.begin(),
1815 E = CXX.end();
1816 I != E; ++I) {
1817 if (I != CXX.begin())
1818 OS << " else ";
1819 if (I->first.empty())
1820 OS << "if (!Scope || Scope->getName() == \"\") {\n";
1821 else
1822 OS << "if (Scope->getName() == \"" << I->first << "\") {\n";
1823 OS << " return llvm::StringSwitch<bool>(Name)\n";
1824 GenerateHasAttrSpellingStringSwitch(I->second, OS, "CXX11", I->first);
1825 OS << "}";
1826 }
1827 OS << "\n}\n";
1828 OS << "}\n";
Peter Collingbournebee583f2011-10-06 13:03:08 +00001829}
1830
Michael Han99315932013-01-24 16:46:58 +00001831void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00001832 emitSourceFileHeader("Code to translate different attribute spellings "
1833 "into internal identifiers", OS);
Michael Han99315932013-01-24 16:46:58 +00001834
1835 OS <<
Michael Han99315932013-01-24 16:46:58 +00001836 " switch (AttrKind) {\n"
1837 " default:\n"
1838 " llvm_unreachable(\"Unknown attribute kind!\");\n"
1839 " break;\n";
1840
Aaron Ballman64e69862013-12-15 13:05:48 +00001841 ParsedAttrMap Attrs = getParsedAttrList(Records);
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001842 for (const auto &I : Attrs) {
Aaron Ballman2f22b942014-05-20 19:47:14 +00001843 const Record &R = *I.second;
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001844 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001845 OS << " case AT_" << I.first << ": {\n";
Richard Smith852e9ce2013-11-27 01:46:48 +00001846 for (unsigned I = 0; I < Spellings.size(); ++ I) {
Richard Smith852e9ce2013-11-27 01:46:48 +00001847 OS << " if (Name == \""
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001848 << Spellings[I].name() << "\" && "
Richard Smith852e9ce2013-11-27 01:46:48 +00001849 << "SyntaxUsed == "
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001850 << StringSwitch<unsigned>(Spellings[I].variety())
Richard Smith852e9ce2013-11-27 01:46:48 +00001851 .Case("GNU", 0)
1852 .Case("CXX11", 1)
1853 .Case("Declspec", 2)
1854 .Case("Keyword", 3)
1855 .Default(0)
Aaron Ballmanc669cc02014-01-27 22:10:04 +00001856 << " && Scope == \"" << Spellings[I].nameSpace() << "\")\n"
Richard Smith852e9ce2013-11-27 01:46:48 +00001857 << " return " << I << ";\n";
Michael Han99315932013-01-24 16:46:58 +00001858 }
Richard Smith852e9ce2013-11-27 01:46:48 +00001859
1860 OS << " break;\n";
1861 OS << " }\n";
Michael Han99315932013-01-24 16:46:58 +00001862 }
1863
1864 OS << " }\n";
Aaron Ballman64e69862013-12-15 13:05:48 +00001865 OS << " return 0;\n";
Michael Han99315932013-01-24 16:46:58 +00001866}
1867
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +00001868// Emits code used by RecursiveASTVisitor to visit attributes
1869void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS) {
1870 emitSourceFileHeader("Used by RecursiveASTVisitor to visit attributes.", OS);
1871
1872 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1873
1874 // Write method declarations for Traverse* methods.
1875 // We emit this here because we only generate methods for attributes that
1876 // are declared as ASTNodes.
1877 OS << "#ifdef ATTR_VISITOR_DECLS_ONLY\n\n";
Aaron Ballman2f22b942014-05-20 19:47:14 +00001878 for (const auto *Attr : Attrs) {
1879 const Record &R = *Attr;
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +00001880 if (!R.getValueAsBit("ASTNode"))
1881 continue;
1882 OS << " bool Traverse"
1883 << R.getName() << "Attr(" << R.getName() << "Attr *A);\n";
1884 OS << " bool Visit"
1885 << R.getName() << "Attr(" << R.getName() << "Attr *A) {\n"
1886 << " return true; \n"
1887 << " };\n";
1888 }
1889 OS << "\n#else // ATTR_VISITOR_DECLS_ONLY\n\n";
1890
1891 // Write individual Traverse* methods for each attribute class.
Aaron Ballman2f22b942014-05-20 19:47:14 +00001892 for (const auto *Attr : Attrs) {
1893 const Record &R = *Attr;
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +00001894 if (!R.getValueAsBit("ASTNode"))
1895 continue;
1896
1897 OS << "template <typename Derived>\n"
DeLesley Hutchinsbb79c332013-12-30 21:03:02 +00001898 << "bool VISITORCLASS<Derived>::Traverse"
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +00001899 << R.getName() << "Attr(" << R.getName() << "Attr *A) {\n"
1900 << " if (!getDerived().VisitAttr(A))\n"
1901 << " return false;\n"
1902 << " if (!getDerived().Visit" << R.getName() << "Attr(A))\n"
1903 << " return false;\n";
1904
1905 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
Aaron Ballman2f22b942014-05-20 19:47:14 +00001906 for (const auto *Arg : ArgRecords)
1907 createArgument(*Arg, R.getName())->writeASTVisitorTraversal(OS);
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +00001908
1909 OS << " return true;\n";
1910 OS << "}\n\n";
1911 }
1912
1913 // Write generic Traverse routine
1914 OS << "template <typename Derived>\n"
DeLesley Hutchinsbb79c332013-12-30 21:03:02 +00001915 << "bool VISITORCLASS<Derived>::TraverseAttr(Attr *A) {\n"
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +00001916 << " if (!A)\n"
1917 << " return true;\n"
1918 << "\n"
1919 << " switch (A->getKind()) {\n"
1920 << " default:\n"
1921 << " return true;\n";
1922
Aaron Ballman2f22b942014-05-20 19:47:14 +00001923 for (const auto *Attr : Attrs) {
1924 const Record &R = *Attr;
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +00001925 if (!R.getValueAsBit("ASTNode"))
1926 continue;
1927
1928 OS << " case attr::" << R.getName() << ":\n"
1929 << " return getDerived().Traverse" << R.getName() << "Attr("
1930 << "cast<" << R.getName() << "Attr>(A));\n";
1931 }
1932 OS << " }\n"; // end case
1933 OS << "}\n"; // end function
1934 OS << "#endif // ATTR_VISITOR_DECLS_ONLY\n";
1935}
1936
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00001937// Emits code to instantiate dependent attributes on templates.
1938void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00001939 emitSourceFileHeader("Template instantiation code for attributes", OS);
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001940
1941 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1942
Benjamin Kramerbf8da9d2012-02-06 11:13:08 +00001943 OS << "namespace clang {\n"
1944 << "namespace sema {\n\n"
1945 << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, "
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001946 << "Sema &S,\n"
1947 << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n"
1948 << " switch (At->getKind()) {\n"
1949 << " default:\n"
1950 << " break;\n";
1951
Aaron Ballman2f22b942014-05-20 19:47:14 +00001952 for (const auto *Attr : Attrs) {
1953 const Record &R = *Attr;
Douglas Gregorb2daf842012-05-02 15:56:52 +00001954 if (!R.getValueAsBit("ASTNode"))
1955 continue;
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001956
1957 OS << " case attr::" << R.getName() << ": {\n";
Rafael Espindola7f90b7d2012-05-15 14:09:55 +00001958 bool ShouldClone = R.getValueAsBit("Clone");
1959
1960 if (!ShouldClone) {
1961 OS << " return NULL;\n";
1962 OS << " }\n";
1963 continue;
1964 }
1965
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001966 OS << " const " << R.getName() << "Attr *A = cast<"
1967 << R.getName() << "Attr>(At);\n";
1968 bool TDependent = R.getValueAsBit("TemplateDependent");
1969
1970 if (!TDependent) {
1971 OS << " return A->clone(C);\n";
1972 OS << " }\n";
1973 continue;
1974 }
1975
1976 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
Aaron Ballman8f1439b2014-03-05 16:49:55 +00001977 std::vector<std::unique_ptr<Argument>> Args;
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001978 Args.reserve(ArgRecords.size());
1979
Aaron Ballman2f22b942014-05-20 19:47:14 +00001980 for (const auto *ArgRecord : ArgRecords)
Aaron Ballman8f1439b2014-03-05 16:49:55 +00001981 Args.emplace_back(createArgument(*ArgRecord, R.getName()));
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001982
Aaron Ballman8f1439b2014-03-05 16:49:55 +00001983 for (auto const &ai : Args)
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001984 ai->writeTemplateInstantiation(OS);
Aaron Ballman8f1439b2014-03-05 16:49:55 +00001985
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001986 OS << " return new (C) " << R.getName() << "Attr(A->getLocation(), C";
Aaron Ballman8f1439b2014-03-05 16:49:55 +00001987 for (auto const &ai : Args) {
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001988 OS << ", ";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00001989 ai->writeTemplateInstantiationArgs(OS);
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001990 }
Aaron Ballman36a53502014-01-16 13:03:14 +00001991 OS << ", A->getSpellingListIndex());\n }\n";
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001992 }
1993 OS << " } // end switch\n"
1994 << " llvm_unreachable(\"Unknown attribute!\");\n"
1995 << " return 0;\n"
Benjamin Kramerbf8da9d2012-02-06 11:13:08 +00001996 << "}\n\n"
1997 << "} // end namespace sema\n"
1998 << "} // end namespace clang\n";
DeLesley Hutchinsceec3062012-01-20 22:37:06 +00001999}
2000
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002001// Emits the list of parsed attributes.
2002void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) {
2003 emitSourceFileHeader("List of all attributes that Clang recognizes", OS);
2004
2005 OS << "#ifndef PARSED_ATTR\n";
2006 OS << "#define PARSED_ATTR(NAME) NAME\n";
2007 OS << "#endif\n\n";
2008
2009 ParsedAttrMap Names = getParsedAttrList(Records);
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002010 for (const auto &I : Names) {
2011 OS << "PARSED_ATTR(" << I.first << ")\n";
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002012 }
2013}
2014
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002015static void emitArgInfo(const Record &R, std::stringstream &OS) {
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002016 // This function will count the number of arguments specified for the
2017 // attribute and emit the number of required arguments followed by the
2018 // number of optional arguments.
2019 std::vector<Record *> Args = R.getValueAsListOfDefs("Args");
2020 unsigned ArgCount = 0, OptCount = 0;
Aaron Ballman2f22b942014-05-20 19:47:14 +00002021 for (const auto *Arg : Args) {
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002022 Arg->getValueAsBit("Optional") ? ++OptCount : ++ArgCount;
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002023 }
2024 OS << ArgCount << ", " << OptCount;
2025}
2026
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002027static void GenerateDefaultAppertainsTo(raw_ostream &OS) {
Aaron Ballman93b5cc62013-12-02 19:36:42 +00002028 OS << "static bool defaultAppertainsTo(Sema &, const AttributeList &,";
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002029 OS << "const Decl *) {\n";
2030 OS << " return true;\n";
2031 OS << "}\n\n";
2032}
2033
2034static std::string CalculateDiagnostic(const Record &S) {
2035 // If the SubjectList object has a custom diagnostic associated with it,
2036 // return that directly.
2037 std::string CustomDiag = S.getValueAsString("CustomDiag");
2038 if (!CustomDiag.empty())
2039 return CustomDiag;
2040
2041 // Given the list of subjects, determine what diagnostic best fits.
2042 enum {
2043 Func = 1U << 0,
2044 Var = 1U << 1,
2045 ObjCMethod = 1U << 2,
2046 Param = 1U << 3,
2047 Class = 1U << 4,
Aaron Ballmanc1494bd2013-11-27 20:14:30 +00002048 GenericRecord = 1U << 5,
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002049 Type = 1U << 6,
2050 ObjCIVar = 1U << 7,
2051 ObjCProp = 1U << 8,
2052 ObjCInterface = 1U << 9,
2053 Block = 1U << 10,
2054 Namespace = 1U << 11,
Aaron Ballman981ba242014-05-20 14:10:53 +00002055 Field = 1U << 12,
2056 CXXMethod = 1U << 13,
2057 ObjCProtocol = 1U << 14
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002058 };
2059 uint32_t SubMask = 0;
2060
2061 std::vector<Record *> Subjects = S.getValueAsListOfDefs("Subjects");
Aaron Ballman2f22b942014-05-20 19:47:14 +00002062 for (const auto *Subject : Subjects) {
2063 const Record &R = *Subject;
Aaron Ballman80469032013-11-29 14:57:58 +00002064 std::string Name;
2065
2066 if (R.isSubClassOf("SubsetSubject")) {
2067 PrintError(R.getLoc(), "SubsetSubjects should use a custom diagnostic");
2068 // As a fallback, look through the SubsetSubject to see what its base
2069 // type is, and use that. This needs to be updated if SubsetSubjects
2070 // are allowed within other SubsetSubjects.
2071 Name = R.getValueAsDef("Base")->getName();
2072 } else
2073 Name = R.getName();
2074
2075 uint32_t V = StringSwitch<uint32_t>(Name)
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002076 .Case("Function", Func)
2077 .Case("Var", Var)
2078 .Case("ObjCMethod", ObjCMethod)
2079 .Case("ParmVar", Param)
2080 .Case("TypedefName", Type)
2081 .Case("ObjCIvar", ObjCIVar)
2082 .Case("ObjCProperty", ObjCProp)
Aaron Ballmanc1494bd2013-11-27 20:14:30 +00002083 .Case("Record", GenericRecord)
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002084 .Case("ObjCInterface", ObjCInterface)
Ted Kremenekd980da22013-12-10 19:43:42 +00002085 .Case("ObjCProtocol", ObjCProtocol)
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002086 .Case("Block", Block)
2087 .Case("CXXRecord", Class)
2088 .Case("Namespace", Namespace)
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002089 .Case("Field", Field)
2090 .Case("CXXMethod", CXXMethod)
2091 .Default(0);
2092 if (!V) {
2093 // Something wasn't in our mapping, so be helpful and let the developer
2094 // know about it.
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002095 PrintFatalError(R.getLoc(), "Unknown subject type: " + R.getName());
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002096 return "";
2097 }
2098
2099 SubMask |= V;
2100 }
2101
2102 switch (SubMask) {
2103 // For the simple cases where there's only a single entry in the mask, we
2104 // don't have to resort to bit fiddling.
2105 case Func: return "ExpectedFunction";
2106 case Var: return "ExpectedVariable";
2107 case Param: return "ExpectedParameter";
2108 case Class: return "ExpectedClass";
2109 case CXXMethod:
2110 // FIXME: Currently, this maps to ExpectedMethod based on existing code,
2111 // but should map to something a bit more accurate at some point.
2112 case ObjCMethod: return "ExpectedMethod";
2113 case Type: return "ExpectedType";
2114 case ObjCInterface: return "ExpectedObjectiveCInterface";
Ted Kremenekd980da22013-12-10 19:43:42 +00002115 case ObjCProtocol: return "ExpectedObjectiveCProtocol";
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002116
Aaron Ballmanc1494bd2013-11-27 20:14:30 +00002117 // "GenericRecord" means struct, union or class; check the language options
2118 // and if not compiling for C++, strip off the class part. Note that this
2119 // relies on the fact that the context for this declares "Sema &S".
2120 case GenericRecord:
Aaron Ballman17046b82013-11-27 19:16:55 +00002121 return "(S.getLangOpts().CPlusPlus ? ExpectedStructOrUnionOrClass : "
2122 "ExpectedStructOrUnion)";
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002123 case Func | ObjCMethod | Block: return "ExpectedFunctionMethodOrBlock";
2124 case Func | ObjCMethod | Class: return "ExpectedFunctionMethodOrClass";
2125 case Func | Param:
2126 case Func | ObjCMethod | Param: return "ExpectedFunctionMethodOrParameter";
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002127 case Func | ObjCMethod: return "ExpectedFunctionOrMethod";
2128 case Func | Var: return "ExpectedVariableOrFunction";
Aaron Ballman604dfec2013-12-02 17:07:07 +00002129
2130 // If not compiling for C++, the class portion does not apply.
2131 case Func | Var | Class:
2132 return "(S.getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass : "
2133 "ExpectedVariableOrFunction)";
2134
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002135 case ObjCMethod | ObjCProp: return "ExpectedMethodOrProperty";
2136 case Field | Var: return "ExpectedFieldOrGlobalVar";
2137 }
2138
2139 PrintFatalError(S.getLoc(),
2140 "Could not deduce diagnostic argument for Attr subjects");
2141
2142 return "";
2143}
2144
Aaron Ballman12b9f652014-01-16 13:55:42 +00002145static std::string GetSubjectWithSuffix(const Record *R) {
2146 std::string B = R->getName();
2147 if (B == "DeclBase")
2148 return "Decl";
2149 return B + "Decl";
2150}
Aaron Ballman80469032013-11-29 14:57:58 +00002151static std::string GenerateCustomAppertainsTo(const Record &Subject,
2152 raw_ostream &OS) {
Aaron Ballmana358c902013-12-02 14:58:17 +00002153 std::string FnName = "is" + Subject.getName();
2154
Aaron Ballman80469032013-11-29 14:57:58 +00002155 // If this code has already been generated, simply return the previous
2156 // instance of it.
2157 static std::set<std::string> CustomSubjectSet;
Aaron Ballmana358c902013-12-02 14:58:17 +00002158 std::set<std::string>::iterator I = CustomSubjectSet.find(FnName);
Aaron Ballman80469032013-11-29 14:57:58 +00002159 if (I != CustomSubjectSet.end())
2160 return *I;
2161
2162 Record *Base = Subject.getValueAsDef("Base");
2163
2164 // Not currently support custom subjects within custom subjects.
2165 if (Base->isSubClassOf("SubsetSubject")) {
2166 PrintFatalError(Subject.getLoc(),
2167 "SubsetSubjects within SubsetSubjects is not supported");
2168 return "";
2169 }
2170
Aaron Ballman80469032013-11-29 14:57:58 +00002171 OS << "static bool " << FnName << "(const Decl *D) {\n";
Aaron Ballman47553042014-01-16 14:32:03 +00002172 OS << " if (const " << GetSubjectWithSuffix(Base) << " *S = dyn_cast<";
Aaron Ballman12b9f652014-01-16 13:55:42 +00002173 OS << GetSubjectWithSuffix(Base);
Aaron Ballman47553042014-01-16 14:32:03 +00002174 OS << ">(D))\n";
2175 OS << " return " << Subject.getValueAsString("CheckCode") << ";\n";
2176 OS << " return false;\n";
Aaron Ballman80469032013-11-29 14:57:58 +00002177 OS << "}\n\n";
2178
2179 CustomSubjectSet.insert(FnName);
2180 return FnName;
2181}
2182
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002183static std::string GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) {
2184 // If the attribute does not contain a Subjects definition, then use the
2185 // default appertainsTo logic.
2186 if (Attr.isValueUnset("Subjects"))
Aaron Ballman93b5cc62013-12-02 19:36:42 +00002187 return "defaultAppertainsTo";
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002188
2189 const Record *SubjectObj = Attr.getValueAsDef("Subjects");
2190 std::vector<Record*> Subjects = SubjectObj->getValueAsListOfDefs("Subjects");
2191
2192 // If the list of subjects is empty, it is assumed that the attribute
2193 // appertains to everything.
2194 if (Subjects.empty())
Aaron Ballman93b5cc62013-12-02 19:36:42 +00002195 return "defaultAppertainsTo";
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002196
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002197 bool Warn = SubjectObj->getValueAsDef("Diag")->getValueAsBit("Warn");
2198
2199 // Otherwise, generate an appertainsTo check specific to this attribute which
2200 // checks all of the given subjects against the Decl passed in. Return the
2201 // name of that check to the caller.
Aaron Ballman00dcc432013-12-03 13:45:50 +00002202 std::string FnName = "check" + Attr.getName() + "AppertainsTo";
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002203 std::stringstream SS;
2204 SS << "static bool " << FnName << "(Sema &S, const AttributeList &Attr, ";
2205 SS << "const Decl *D) {\n";
2206 SS << " if (";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002207 for (auto I = Subjects.begin(), E = Subjects.end(); I != E; ++I) {
Aaron Ballman80469032013-11-29 14:57:58 +00002208 // If the subject has custom code associated with it, generate a function
2209 // for it. The function cannot be inlined into this check (yet) because it
2210 // requires the subject to be of a specific type, and were that information
2211 // inlined here, it would not support an attribute with multiple custom
2212 // subjects.
2213 if ((*I)->isSubClassOf("SubsetSubject")) {
2214 SS << "!" << GenerateCustomAppertainsTo(**I, OS) << "(D)";
2215 } else {
Aaron Ballman12b9f652014-01-16 13:55:42 +00002216 SS << "!isa<" << GetSubjectWithSuffix(*I) << ">(D)";
Aaron Ballman80469032013-11-29 14:57:58 +00002217 }
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002218
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002219 if (I + 1 != E)
2220 SS << " && ";
2221 }
2222 SS << ") {\n";
2223 SS << " S.Diag(Attr.getLoc(), diag::";
2224 SS << (Warn ? "warn_attribute_wrong_decl_type" :
2225 "err_attribute_wrong_decl_type");
2226 SS << ")\n";
2227 SS << " << Attr.getName() << ";
2228 SS << CalculateDiagnostic(*SubjectObj) << ";\n";
2229 SS << " return false;\n";
2230 SS << " }\n";
2231 SS << " return true;\n";
2232 SS << "}\n\n";
2233
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002234 OS << SS.str();
2235 return FnName;
2236}
2237
Aaron Ballman3aff6332013-12-02 19:30:36 +00002238static void GenerateDefaultLangOptRequirements(raw_ostream &OS) {
2239 OS << "static bool defaultDiagnoseLangOpts(Sema &, ";
2240 OS << "const AttributeList &) {\n";
2241 OS << " return true;\n";
2242 OS << "}\n\n";
2243}
2244
2245static std::string GenerateLangOptRequirements(const Record &R,
2246 raw_ostream &OS) {
2247 // If the attribute has an empty or unset list of language requirements,
2248 // return the default handler.
2249 std::vector<Record *> LangOpts = R.getValueAsListOfDefs("LangOpts");
2250 if (LangOpts.empty())
2251 return "defaultDiagnoseLangOpts";
2252
2253 // Generate the test condition, as well as a unique function name for the
2254 // diagnostic test. The list of options should usually be short (one or two
2255 // options), and the uniqueness isn't strictly necessary (it is just for
2256 // codegen efficiency).
2257 std::string FnName = "check", Test;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002258 for (auto I = LangOpts.begin(), E = LangOpts.end(); I != E; ++I) {
Aaron Ballman3aff6332013-12-02 19:30:36 +00002259 std::string Part = (*I)->getValueAsString("Name");
2260 Test += "S.LangOpts." + Part;
2261 if (I + 1 != E)
2262 Test += " || ";
2263 FnName += Part;
2264 }
2265 FnName += "LangOpts";
2266
2267 // If this code has already been generated, simply return the previous
2268 // instance of it.
2269 static std::set<std::string> CustomLangOptsSet;
2270 std::set<std::string>::iterator I = CustomLangOptsSet.find(FnName);
2271 if (I != CustomLangOptsSet.end())
2272 return *I;
2273
2274 OS << "static bool " << FnName << "(Sema &S, const AttributeList &Attr) {\n";
2275 OS << " if (" << Test << ")\n";
2276 OS << " return true;\n\n";
2277 OS << " S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) ";
2278 OS << "<< Attr.getName();\n";
2279 OS << " return false;\n";
2280 OS << "}\n\n";
2281
2282 CustomLangOptsSet.insert(FnName);
2283 return FnName;
2284}
2285
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002286static void GenerateDefaultTargetRequirements(raw_ostream &OS) {
Benjamin Kramer9299637dc2014-03-04 19:31:42 +00002287 OS << "static bool defaultTargetRequirements(const llvm::Triple &) {\n";
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002288 OS << " return true;\n";
2289 OS << "}\n\n";
2290}
2291
2292static std::string GenerateTargetRequirements(const Record &Attr,
2293 const ParsedAttrMap &Dupes,
2294 raw_ostream &OS) {
2295 // If the attribute is not a target specific attribute, return the default
2296 // target handler.
2297 if (!Attr.isSubClassOf("TargetSpecificAttr"))
2298 return "defaultTargetRequirements";
2299
2300 // Get the list of architectures to be tested for.
2301 const Record *R = Attr.getValueAsDef("Target");
2302 std::vector<std::string> Arches = R->getValueAsListOfStrings("Arches");
2303 if (Arches.empty()) {
2304 PrintError(Attr.getLoc(), "Empty list of target architectures for a "
2305 "target-specific attr");
2306 return "defaultTargetRequirements";
2307 }
2308
2309 // If there are other attributes which share the same parsed attribute kind,
2310 // such as target-specific attributes with a shared spelling, collapse the
2311 // duplicate architectures. This is required because a shared target-specific
2312 // attribute has only one AttributeList::Kind enumeration value, but it
2313 // applies to multiple target architectures. In order for the attribute to be
2314 // considered valid, all of its architectures need to be included.
2315 if (!Attr.isValueUnset("ParseKind")) {
2316 std::string APK = Attr.getValueAsString("ParseKind");
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002317 for (const auto &I : Dupes) {
2318 if (I.first == APK) {
2319 std::vector<std::string> DA = I.second->getValueAsDef("Target")
2320 ->getValueAsListOfStrings("Arches");
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002321 std::copy(DA.begin(), DA.end(), std::back_inserter(Arches));
2322 }
2323 }
2324 }
2325
2326 std::string FnName = "isTarget", Test = "(";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002327 for (auto I = Arches.begin(), E = Arches.end(); I != E; ++I) {
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002328 std::string Part = *I;
2329 Test += "Arch == llvm::Triple::" + Part;
2330 if (I + 1 != E)
2331 Test += " || ";
2332 FnName += Part;
2333 }
2334 Test += ")";
2335
2336 // If the target also requires OS testing, generate those tests as well.
2337 bool UsesOS = false;
2338 if (!R->isValueUnset("OSes")) {
2339 UsesOS = true;
2340
2341 // We know that there was at least one arch test, so we need to and in the
2342 // OS tests.
2343 Test += " && (";
2344 std::vector<std::string> OSes = R->getValueAsListOfStrings("OSes");
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002345 for (auto I = OSes.begin(), E = OSes.end(); I != E; ++I) {
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002346 std::string Part = *I;
2347
2348 Test += "OS == llvm::Triple::" + Part;
2349 if (I + 1 != E)
2350 Test += " || ";
2351 FnName += Part;
2352 }
2353 Test += ")";
2354 }
2355
2356 // If this code has already been generated, simply return the previous
2357 // instance of it.
2358 static std::set<std::string> CustomTargetSet;
2359 std::set<std::string>::iterator I = CustomTargetSet.find(FnName);
2360 if (I != CustomTargetSet.end())
2361 return *I;
2362
Benjamin Kramer9299637dc2014-03-04 19:31:42 +00002363 OS << "static bool " << FnName << "(const llvm::Triple &T) {\n";
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002364 OS << " llvm::Triple::ArchType Arch = T.getArch();\n";
2365 if (UsesOS)
2366 OS << " llvm::Triple::OSType OS = T.getOS();\n";
2367 OS << " return " << Test << ";\n";
2368 OS << "}\n\n";
2369
2370 CustomTargetSet.insert(FnName);
2371 return FnName;
2372}
2373
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00002374static void GenerateDefaultSpellingIndexToSemanticSpelling(raw_ostream &OS) {
2375 OS << "static unsigned defaultSpellingIndexToSemanticSpelling("
2376 << "const AttributeList &Attr) {\n";
2377 OS << " return UINT_MAX;\n";
2378 OS << "}\n\n";
2379}
2380
2381static std::string GenerateSpellingIndexToSemanticSpelling(const Record &Attr,
2382 raw_ostream &OS) {
2383 // If the attribute does not have a semantic form, we can bail out early.
2384 if (!Attr.getValueAsBit("ASTNode"))
2385 return "defaultSpellingIndexToSemanticSpelling";
2386
Aaron Ballmanc669cc02014-01-27 22:10:04 +00002387 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00002388
2389 // If there are zero or one spellings, or all of the spellings share the same
2390 // name, we can also bail out early.
2391 if (Spellings.size() <= 1 || SpellingNamesAreCommon(Spellings))
2392 return "defaultSpellingIndexToSemanticSpelling";
2393
2394 // Generate the enumeration we will use for the mapping.
2395 SemanticSpellingMap SemanticToSyntacticMap;
2396 std::string Enum = CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);
2397 std::string Name = Attr.getName() + "AttrSpellingMap";
2398
2399 OS << "static unsigned " << Name << "(const AttributeList &Attr) {\n";
2400 OS << Enum;
2401 OS << " unsigned Idx = Attr.getAttributeSpellingListIndex();\n";
2402 WriteSemanticSpellingSwitch("Idx", SemanticToSyntacticMap, OS);
2403 OS << "}\n\n";
2404
2405 return Name;
2406}
2407
Aaron Ballmanc669cc02014-01-27 22:10:04 +00002408static bool IsKnownToGCC(const Record &Attr) {
2409 // Look at the spellings for this subject; if there are any spellings which
2410 // claim to be known to GCC, the attribute is known to GCC.
2411 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002412 for (const auto &I : Spellings) {
2413 if (I.knownToGCC())
Aaron Ballman9a99e0d2014-01-20 17:18:35 +00002414 return true;
2415 }
2416 return false;
2417}
2418
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002419/// Emits the parsed attribute helpers
2420void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
2421 emitSourceFileHeader("Parsed attribute helpers", OS);
2422
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002423 // Get the list of parsed attributes, and accept the optional list of
2424 // duplicates due to the ParseKind.
2425 ParsedAttrMap Dupes;
2426 ParsedAttrMap Attrs = getParsedAttrList(Records, &Dupes);
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002427
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00002428 // Generate the default appertainsTo, target and language option diagnostic,
2429 // and spelling list index mapping methods.
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002430 GenerateDefaultAppertainsTo(OS);
Aaron Ballman3aff6332013-12-02 19:30:36 +00002431 GenerateDefaultLangOptRequirements(OS);
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002432 GenerateDefaultTargetRequirements(OS);
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00002433 GenerateDefaultSpellingIndexToSemanticSpelling(OS);
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002434
2435 // Generate the appertainsTo diagnostic methods and write their names into
2436 // another mapping. At the same time, generate the AttrInfoMap object
2437 // contents. Due to the reliance on generated code, use separate streams so
2438 // that code will not be interleaved.
2439 std::stringstream SS;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002440 for (auto I = Attrs.begin(), E = Attrs.end(); I != E; ++I) {
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002441 // TODO: If the attribute's kind appears in the list of duplicates, that is
2442 // because it is a target-specific attribute that appears multiple times.
2443 // It would be beneficial to test whether the duplicates are "similar
2444 // enough" to each other to not cause problems. For instance, check that
Alp Toker96cf7582014-01-18 21:49:37 +00002445 // the spellings are identical, and custom parsing rules match, etc.
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002446
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002447 // We need to generate struct instances based off ParsedAttrInfo from
2448 // AttributeList.cpp.
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002449 SS << " { ";
2450 emitArgInfo(*I->second, SS);
2451 SS << ", " << I->second->getValueAsBit("HasCustomParsing");
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002452 SS << ", " << I->second->isSubClassOf("TargetSpecificAttr");
2453 SS << ", " << I->second->isSubClassOf("TypeAttr");
Aaron Ballmanc669cc02014-01-27 22:10:04 +00002454 SS << ", " << IsKnownToGCC(*I->second);
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002455 SS << ", " << GenerateAppertainsTo(*I->second, OS);
Aaron Ballman3aff6332013-12-02 19:30:36 +00002456 SS << ", " << GenerateLangOptRequirements(*I->second, OS);
Aaron Ballmanab7691c2014-01-09 22:48:32 +00002457 SS << ", " << GenerateTargetRequirements(*I->second, Dupes, OS);
Aaron Ballman81cb8cb2014-01-24 21:32:49 +00002458 SS << ", " << GenerateSpellingIndexToSemanticSpelling(*I->second, OS);
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002459 SS << " }";
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002460
2461 if (I + 1 != E)
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002462 SS << ",";
2463
2464 SS << " // AT_" << I->first << "\n";
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002465 }
Aaron Ballman74eeeae2013-11-27 13:27:02 +00002466
2467 OS << "static const ParsedAttrInfo AttrInfoMap[AttributeList::UnknownAttribute + 1] = {\n";
2468 OS << SS.str();
Aaron Ballman8ee40b72013-09-09 23:33:17 +00002469 OS << "};\n\n";
Michael Han4a045172012-03-07 00:12:16 +00002470}
2471
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00002472// Emits the kind list of parsed attributes
2473void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00002474 emitSourceFileHeader("Attribute name matcher", OS);
2475
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002476 std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
2477 std::vector<StringMatcher::StringPair> GNU, Declspec, CXX11, Keywords;
Aaron Ballman64e69862013-12-15 13:05:48 +00002478 std::set<std::string> Seen;
Aaron Ballman2f22b942014-05-20 19:47:14 +00002479 for (const auto *A : Attrs) {
2480 const Record &Attr = *A;
Richard Smith852e9ce2013-11-27 01:46:48 +00002481
Michael Han4a045172012-03-07 00:12:16 +00002482 bool SemaHandler = Attr.getValueAsBit("SemaHandler");
Douglas Gregor19fbb8f2012-05-02 16:18:45 +00002483 bool Ignored = Attr.getValueAsBit("Ignored");
Douglas Gregor19fbb8f2012-05-02 16:18:45 +00002484 if (SemaHandler || Ignored) {
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002485 // Attribute spellings can be shared between target-specific attributes,
2486 // and can be shared between syntaxes for the same attribute. For
2487 // instance, an attribute can be spelled GNU<"interrupt"> for an ARM-
2488 // specific attribute, or MSP430-specific attribute. Additionally, an
2489 // attribute can be spelled GNU<"dllexport"> and Declspec<"dllexport">
2490 // for the same semantic attribute. Ultimately, we need to map each of
2491 // these to a single AttributeList::Kind value, but the StringMatcher
2492 // class cannot handle duplicate match strings. So we generate a list of
2493 // string to match based on the syntax, and emit multiple string matchers
2494 // depending on the syntax used.
Aaron Ballman64e69862013-12-15 13:05:48 +00002495 std::string AttrName;
2496 if (Attr.isSubClassOf("TargetSpecificAttr") &&
2497 !Attr.isValueUnset("ParseKind")) {
2498 AttrName = Attr.getValueAsString("ParseKind");
2499 if (Seen.find(AttrName) != Seen.end())
2500 continue;
2501 Seen.insert(AttrName);
2502 } else
2503 AttrName = NormalizeAttrName(StringRef(Attr.getName())).str();
2504
Aaron Ballmanc669cc02014-01-27 22:10:04 +00002505 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002506 for (const auto &S : Spellings) {
2507 std::string RawSpelling = S.name();
Craig Topper8ae12032014-05-07 06:21:57 +00002508 std::vector<StringMatcher::StringPair> *Matches = nullptr;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002509 std::string Spelling, Variety = S.variety();
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002510 if (Variety == "CXX11") {
2511 Matches = &CXX11;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002512 Spelling += S.nameSpace();
Alexis Hunt3bc72c12012-06-19 23:57:03 +00002513 Spelling += "::";
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002514 } else if (Variety == "GNU")
2515 Matches = &GNU;
2516 else if (Variety == "Declspec")
2517 Matches = &Declspec;
2518 else if (Variety == "Keyword")
2519 Matches = &Keywords;
Alexis Hunta0e54d42012-06-18 16:13:52 +00002520
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002521 assert(Matches && "Unsupported spelling variety found");
2522
2523 Spelling += NormalizeAttrSpelling(RawSpelling);
Douglas Gregor19fbb8f2012-05-02 16:18:45 +00002524 if (SemaHandler)
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002525 Matches->push_back(StringMatcher::StringPair(Spelling,
2526 "return AttributeList::AT_" + AttrName + ";"));
Douglas Gregor19fbb8f2012-05-02 16:18:45 +00002527 else
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002528 Matches->push_back(StringMatcher::StringPair(Spelling,
2529 "return AttributeList::IgnoredAttribute;"));
Michael Han4a045172012-03-07 00:12:16 +00002530 }
2531 }
2532 }
Douglas Gregor377f99b2012-05-02 17:33:51 +00002533
Aaron Ballman09e98ff2014-01-13 21:42:39 +00002534 OS << "static AttributeList::Kind getAttrKind(StringRef Name, ";
2535 OS << "AttributeList::Syntax Syntax) {\n";
2536 OS << " if (AttributeList::AS_GNU == Syntax) {\n";
2537 StringMatcher("Name", GNU, OS).Emit();
2538 OS << " } else if (AttributeList::AS_Declspec == Syntax) {\n";
2539 StringMatcher("Name", Declspec, OS).Emit();
2540 OS << " } else if (AttributeList::AS_CXX11 == Syntax) {\n";
2541 StringMatcher("Name", CXX11, OS).Emit();
2542 OS << " } else if (AttributeList::AS_Keyword == Syntax) {\n";
2543 StringMatcher("Name", Keywords, OS).Emit();
2544 OS << " }\n";
2545 OS << " return AttributeList::UnknownAttribute;\n"
Douglas Gregor377f99b2012-05-02 17:33:51 +00002546 << "}\n";
Michael Han4a045172012-03-07 00:12:16 +00002547}
2548
Alexander Kornienko5bc364e2013-01-07 17:53:08 +00002549// Emits the code to dump an attribute.
2550void EmitClangAttrDump(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko6b11fca2013-01-30 21:54:20 +00002551 emitSourceFileHeader("Attribute dumper", OS);
2552
Alexander Kornienko5bc364e2013-01-07 17:53:08 +00002553 OS <<
2554 " switch (A->getKind()) {\n"
2555 " default:\n"
2556 " llvm_unreachable(\"Unknown attribute kind!\");\n"
2557 " break;\n";
2558 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
Aaron Ballman2f22b942014-05-20 19:47:14 +00002559 for (const auto *Attr : Attrs) {
2560 const Record &R = *Attr;
Alexander Kornienko5bc364e2013-01-07 17:53:08 +00002561 if (!R.getValueAsBit("ASTNode"))
2562 continue;
2563 OS << " case attr::" << R.getName() << ": {\n";
Aaron Ballmanbc909612014-01-22 21:51:20 +00002564
2565 // If the attribute has a semantically-meaningful name (which is determined
2566 // by whether there is a Spelling enumeration for it), then write out the
2567 // spelling used for the attribute.
Aaron Ballmanc669cc02014-01-27 22:10:04 +00002568 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
Aaron Ballmanbc909612014-01-22 21:51:20 +00002569 if (Spellings.size() > 1 && !SpellingNamesAreCommon(Spellings))
2570 OS << " OS << \" \" << A->getSpelling();\n";
2571
Alexander Kornienko5bc364e2013-01-07 17:53:08 +00002572 Args = R.getValueAsListOfDefs("Args");
2573 if (!Args.empty()) {
2574 OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
2575 << "Attr>(A);\n";
Aaron Ballman2f22b942014-05-20 19:47:14 +00002576 for (const auto *Arg : Args)
2577 createArgument(*Arg, R.getName())->writeDump(OS);
Richard Trieude5cc7d2013-01-31 01:44:26 +00002578
2579 // Code for detecting the last child.
2580 OS << " bool OldMoreChildren = hasMoreChildren();\n";
Arnaud A. de Grandmaisonc6b40452014-03-21 22:35:34 +00002581 OS << " bool MoreChildren;\n";
Richard Trieude5cc7d2013-01-31 01:44:26 +00002582
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002583 for (auto AI = Args.begin(), AE = Args.end(); AI != AE; ++AI) {
Richard Trieude5cc7d2013-01-31 01:44:26 +00002584 // More code for detecting the last child.
2585 OS << " MoreChildren = OldMoreChildren";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002586 for (auto Next = AI + 1; Next != AE; ++Next) {
Richard Trieude5cc7d2013-01-31 01:44:26 +00002587 OS << " || ";
2588 createArgument(**Next, R.getName())->writeHasChildren(OS);
2589 }
2590 OS << ";\n";
2591 OS << " setMoreChildren(MoreChildren);\n";
2592
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002593 createArgument(**AI, R.getName())->writeDumpChildren(OS);
Richard Trieude5cc7d2013-01-31 01:44:26 +00002594 }
2595
2596 // Reset the last child.
2597 OS << " setMoreChildren(OldMoreChildren);\n";
Alexander Kornienko5bc364e2013-01-07 17:53:08 +00002598 }
2599 OS <<
2600 " break;\n"
2601 " }\n";
2602 }
2603 OS << " }\n";
2604}
2605
Aaron Ballman35db2b32014-01-29 22:13:45 +00002606void EmitClangAttrParserStringSwitches(RecordKeeper &Records,
2607 raw_ostream &OS) {
2608 emitSourceFileHeader("Parser-related llvm::StringSwitch cases", OS);
2609 emitClangAttrArgContextList(Records, OS);
2610 emitClangAttrIdentifierArgList(Records, OS);
2611 emitClangAttrTypeArgList(Records, OS);
2612 emitClangAttrLateParsedList(Records, OS);
2613}
2614
Aaron Ballman97dba042014-02-17 15:27:10 +00002615class DocumentationData {
2616public:
Aaron Ballman1a3e5852014-02-17 16:18:32 +00002617 const Record *Documentation;
2618 const Record *Attribute;
Aaron Ballman97dba042014-02-17 15:27:10 +00002619
Aaron Ballman4de1b582014-02-19 22:59:32 +00002620 DocumentationData(const Record &Documentation, const Record &Attribute)
2621 : Documentation(&Documentation), Attribute(&Attribute) {}
Aaron Ballman97dba042014-02-17 15:27:10 +00002622};
2623
Aaron Ballman4de1b582014-02-19 22:59:32 +00002624static void WriteCategoryHeader(const Record *DocCategory,
Aaron Ballman97dba042014-02-17 15:27:10 +00002625 raw_ostream &OS) {
Aaron Ballman4de1b582014-02-19 22:59:32 +00002626 const std::string &Name = DocCategory->getValueAsString("Name");
2627 OS << Name << "\n" << std::string(Name.length(), '=') << "\n";
2628
2629 // If there is content, print that as well.
2630 std::string ContentStr = DocCategory->getValueAsString("Content");
2631 if (!ContentStr.empty()) {
2632 // Trim leading and trailing newlines and spaces.
2633 StringRef Content(ContentStr);
2634 while (Content.startswith("\r") || Content.startswith("\n") ||
2635 Content.startswith(" ") || Content.startswith("\t"))
2636 Content = Content.substr(1);
2637 while (Content.endswith("\r") || Content.endswith("\n") ||
2638 Content.endswith(" ") || Content.endswith("\t"))
2639 Content = Content.substr(0, Content.size() - 1);
2640 OS << Content;
Aaron Ballman97dba042014-02-17 15:27:10 +00002641 }
Aaron Ballman4de1b582014-02-19 22:59:32 +00002642 OS << "\n\n";
Aaron Ballman97dba042014-02-17 15:27:10 +00002643}
2644
Aaron Ballmana66b5742014-02-17 15:36:08 +00002645enum SpellingKind {
2646 GNU = 1 << 0,
2647 CXX11 = 1 << 1,
2648 Declspec = 1 << 2,
2649 Keyword = 1 << 3
2650};
2651
Aaron Ballman97dba042014-02-17 15:27:10 +00002652static void WriteDocumentation(const DocumentationData &Doc,
2653 raw_ostream &OS) {
2654 // FIXME: there is no way to have a per-spelling category for the attribute
2655 // documentation. This may not be a limiting factor since the spellings
2656 // should generally be consistently applied across the category.
2657
Aaron Ballman1a3e5852014-02-17 16:18:32 +00002658 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Doc.Attribute);
Aaron Ballman97dba042014-02-17 15:27:10 +00002659
2660 // Determine the heading to be used for this attribute.
Aaron Ballman1a3e5852014-02-17 16:18:32 +00002661 std::string Heading = Doc.Documentation->getValueAsString("Heading");
Aaron Ballmanea6668c2014-02-21 14:14:04 +00002662 bool CustomHeading = !Heading.empty();
Aaron Ballman97dba042014-02-17 15:27:10 +00002663 if (Heading.empty()) {
2664 // If there's only one spelling, we can simply use that.
2665 if (Spellings.size() == 1)
2666 Heading = Spellings.begin()->name();
2667 else {
2668 std::set<std::string> Uniques;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002669 for (auto I = Spellings.begin(), E = Spellings.end();
2670 I != E && Uniques.size() <= 1; ++I) {
Aaron Ballman97dba042014-02-17 15:27:10 +00002671 std::string Spelling = NormalizeNameForSpellingComparison(I->name());
2672 Uniques.insert(Spelling);
2673 }
2674 // If the semantic map has only one spelling, that is sufficient for our
2675 // needs.
2676 if (Uniques.size() == 1)
2677 Heading = *Uniques.begin();
2678 }
2679 }
2680
2681 // If the heading is still empty, it is an error.
2682 if (Heading.empty())
Aaron Ballman1a3e5852014-02-17 16:18:32 +00002683 PrintFatalError(Doc.Attribute->getLoc(),
Aaron Ballman97dba042014-02-17 15:27:10 +00002684 "This attribute requires a heading to be specified");
2685
2686 // Gather a list of unique spellings; this is not the same as the semantic
2687 // spelling for the attribute. Variations in underscores and other non-
2688 // semantic characters are still acceptable.
2689 std::vector<std::string> Names;
2690
Aaron Ballman97dba042014-02-17 15:27:10 +00002691 unsigned SupportedSpellings = 0;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002692 for (const auto &I : Spellings) {
2693 SpellingKind Kind = StringSwitch<SpellingKind>(I.variety())
Aaron Ballman97dba042014-02-17 15:27:10 +00002694 .Case("GNU", GNU)
2695 .Case("CXX11", CXX11)
2696 .Case("Declspec", Declspec)
2697 .Case("Keyword", Keyword);
2698
2699 // Mask in the supported spelling.
2700 SupportedSpellings |= Kind;
2701
2702 std::string Name;
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002703 if (Kind == CXX11 && !I.nameSpace().empty())
2704 Name = I.nameSpace() + "::";
2705 Name += I.name();
Aaron Ballman97dba042014-02-17 15:27:10 +00002706
2707 // If this name is the same as the heading, do not add it.
2708 if (Name != Heading)
2709 Names.push_back(Name);
2710 }
2711
2712 // Print out the heading for the attribute. If there are alternate spellings,
2713 // then display those after the heading.
Aaron Ballmanea6668c2014-02-21 14:14:04 +00002714 if (!CustomHeading && !Names.empty()) {
Aaron Ballman97dba042014-02-17 15:27:10 +00002715 Heading += " (";
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002716 for (auto I = Names.begin(), E = Names.end(); I != E; ++I) {
Aaron Ballman97dba042014-02-17 15:27:10 +00002717 if (I != Names.begin())
2718 Heading += ", ";
2719 Heading += *I;
2720 }
2721 Heading += ")";
2722 }
2723 OS << Heading << "\n" << std::string(Heading.length(), '-') << "\n";
2724
2725 if (!SupportedSpellings)
Aaron Ballman1a3e5852014-02-17 16:18:32 +00002726 PrintFatalError(Doc.Attribute->getLoc(),
Aaron Ballman97dba042014-02-17 15:27:10 +00002727 "Attribute has no supported spellings; cannot be "
2728 "documented");
2729
2730 // List what spelling syntaxes the attribute supports.
2731 OS << ".. csv-table:: Supported Syntaxes\n";
2732 OS << " :header: \"GNU\", \"C++11\", \"__declspec\", \"Keyword\"\n\n";
2733 OS << " \"";
2734 if (SupportedSpellings & GNU) OS << "X";
2735 OS << "\",\"";
2736 if (SupportedSpellings & CXX11) OS << "X";
2737 OS << "\",\"";
2738 if (SupportedSpellings & Declspec) OS << "X";
2739 OS << "\",\"";
2740 if (SupportedSpellings & Keyword) OS << "X";
2741 OS << "\"\n\n";
2742
2743 // If the attribute is deprecated, print a message about it, and possibly
2744 // provide a replacement attribute.
Aaron Ballman1a3e5852014-02-17 16:18:32 +00002745 if (!Doc.Documentation->isValueUnset("Deprecated")) {
Aaron Ballman97dba042014-02-17 15:27:10 +00002746 OS << "This attribute has been deprecated, and may be removed in a future "
2747 << "version of Clang.";
Aaron Ballman1a3e5852014-02-17 16:18:32 +00002748 const Record &Deprecated = *Doc.Documentation->getValueAsDef("Deprecated");
Aaron Ballman97dba042014-02-17 15:27:10 +00002749 std::string Replacement = Deprecated.getValueAsString("Replacement");
2750 if (!Replacement.empty())
2751 OS << " This attribute has been superseded by ``"
2752 << Replacement << "``.";
2753 OS << "\n\n";
2754 }
2755
Aaron Ballman1a3e5852014-02-17 16:18:32 +00002756 std::string ContentStr = Doc.Documentation->getValueAsString("Content");
Aaron Ballman97dba042014-02-17 15:27:10 +00002757 // Trim leading and trailing newlines and spaces.
2758 StringRef Content(ContentStr);
2759 while (Content.startswith("\r") || Content.startswith("\n") ||
2760 Content.startswith(" ") || Content.startswith("\t"))
2761 Content = Content.substr(1);
2762 while (Content.endswith("\r") || Content.endswith("\n") ||
2763 Content.endswith(" ") || Content.endswith("\t"))
2764 Content = Content.substr(0, Content.size() - 1);
2765 OS << Content;
2766
2767 OS << "\n\n\n";
2768}
2769
2770void EmitClangAttrDocs(RecordKeeper &Records, raw_ostream &OS) {
2771 // Get the documentation introduction paragraph.
2772 const Record *Documentation = Records.getDef("GlobalDocumentation");
2773 if (!Documentation) {
2774 PrintFatalError("The Documentation top-level definition is missing, "
2775 "no documentation will be generated.");
2776 return;
2777 }
2778
Aaron Ballman4de1b582014-02-19 22:59:32 +00002779 OS << Documentation->getValueAsString("Intro") << "\n";
Aaron Ballman97dba042014-02-17 15:27:10 +00002780
Aaron Ballman97dba042014-02-17 15:27:10 +00002781 // Gather the Documentation lists from each of the attributes, based on the
2782 // category provided.
2783 std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002784 std::map<const Record *, std::vector<DocumentationData>> SplitDocs;
Aaron Ballman2f22b942014-05-20 19:47:14 +00002785 for (const auto *A : Attrs) {
2786 const Record &Attr = *A;
Aaron Ballman97dba042014-02-17 15:27:10 +00002787 std::vector<Record *> Docs = Attr.getValueAsListOfDefs("Documentation");
Aaron Ballman2f22b942014-05-20 19:47:14 +00002788 for (const auto *D : Docs) {
2789 const Record &Doc = *D;
Aaron Ballman4de1b582014-02-19 22:59:32 +00002790 const Record *Category = Doc.getValueAsDef("Category");
Aaron Ballman97dba042014-02-17 15:27:10 +00002791 // If the category is "undocumented", then there cannot be any other
2792 // documentation categories (otherwise, the attribute would become
2793 // documented).
Aaron Ballman4de1b582014-02-19 22:59:32 +00002794 std::string Cat = Category->getValueAsString("Name");
2795 bool Undocumented = Cat == "Undocumented";
Aaron Ballman97dba042014-02-17 15:27:10 +00002796 if (Undocumented && Docs.size() > 1)
2797 PrintFatalError(Doc.getLoc(),
2798 "Attribute is \"Undocumented\", but has multiple "
2799 "documentation categories");
2800
2801 if (!Undocumented)
Aaron Ballman4de1b582014-02-19 22:59:32 +00002802 SplitDocs[Category].push_back(DocumentationData(Doc, Attr));
Aaron Ballman97dba042014-02-17 15:27:10 +00002803 }
2804 }
2805
2806 // Having split the attributes out based on what documentation goes where,
2807 // we can begin to generate sections of documentation.
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002808 for (const auto &I : SplitDocs) {
2809 WriteCategoryHeader(I.first, OS);
Aaron Ballman97dba042014-02-17 15:27:10 +00002810
2811 // Walk over each of the attributes in the category and write out their
2812 // documentation.
Aaron Ballmanb097f7fe2014-03-02 17:38:37 +00002813 for (const auto &Doc : I.second)
2814 WriteDocumentation(Doc, OS);
Aaron Ballman97dba042014-02-17 15:27:10 +00002815 }
2816}
2817
Jakob Stoklund Olesen995e0e12012-06-13 05:12:41 +00002818} // end namespace clang