blob: c1d1a1dbe6d40ba328fd092c46ddf5b760634305 [file] [log] [blame]
Peter Collingbourne51d77772011-10-06 13:03:08 +00001//===- ClangAttrEmitter.cpp - Generate Clang attribute handling =-*- C++ -*--=//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// These tablegen backends emit Clang attribute processing code
11//
12//===----------------------------------------------------------------------===//
13
Sean Hunt93f95f22012-06-18 16:13:52 +000014#include "llvm/ADT/SmallString.h"
Stephen Hines176edba2014-12-01 14:53:08 -080015#include "llvm/ADT/STLExtras.h"
Stephen Hines0e2c34f2015-03-23 12:09:02 -070016#include "llvm/ADT/SmallSet.h"
Stephen Hines176edba2014-12-01 14:53:08 -080017#include "llvm/ADT/StringExtras.h"
Stephen Hines651f13c2014-04-23 16:59:28 -070018#include "llvm/ADT/StringSwitch.h"
19#include "llvm/TableGen/Error.h"
Peter Collingbourne51d77772011-10-06 13:03:08 +000020#include "llvm/TableGen/Record.h"
Douglas Gregor0c19b3c2012-05-02 17:33:51 +000021#include "llvm/TableGen/StringMatcher.h"
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +000022#include "llvm/TableGen/TableGenBackend.h"
Peter Collingbourne51d77772011-10-06 13:03:08 +000023#include <algorithm>
24#include <cctype>
Stephen Hines651f13c2014-04-23 16:59:28 -070025#include <memory>
26#include <set>
27#include <sstream>
Peter Collingbourne51d77772011-10-06 13:03:08 +000028
29using namespace llvm;
30
Pirama Arumuga Nainar3ea9e332015-04-08 08:57:32 -070031namespace {
Stephen Hines651f13c2014-04-23 16:59:28 -070032class FlattenedSpelling {
33 std::string V, N, NS;
34 bool K;
Peter Collingbourne51d77772011-10-06 13:03:08 +000035
Stephen Hines651f13c2014-04-23 16:59:28 -070036public:
37 FlattenedSpelling(const std::string &Variety, const std::string &Name,
38 const std::string &Namespace, bool KnownToGCC) :
39 V(Variety), N(Name), NS(Namespace), K(KnownToGCC) {}
40 explicit FlattenedSpelling(const Record &Spelling) :
41 V(Spelling.getValueAsString("Variety")),
42 N(Spelling.getValueAsString("Name")) {
Peter Collingbourne51d77772011-10-06 13:03:08 +000043
Stephen Hines651f13c2014-04-23 16:59:28 -070044 assert(V != "GCC" && "Given a GCC spelling, which means this hasn't been"
45 "flattened!");
Stephen Hinesc568f1e2014-07-21 00:47:37 -070046 if (V == "CXX11" || V == "Pragma")
Stephen Hines651f13c2014-04-23 16:59:28 -070047 NS = Spelling.getValueAsString("Namespace");
48 bool Unset;
49 K = Spelling.getValueAsBitOrUnset("KnownToGCC", Unset);
Peter Collingbourne51d77772011-10-06 13:03:08 +000050 }
51
Stephen Hines651f13c2014-04-23 16:59:28 -070052 const std::string &variety() const { return V; }
53 const std::string &name() const { return N; }
54 const std::string &nameSpace() const { return NS; }
55 bool knownToGCC() const { return K; }
56};
Pirama Arumuga Nainar3ea9e332015-04-08 08:57:32 -070057} // namespace
Stephen Hines651f13c2014-04-23 16:59:28 -070058
Pirama Arumuga Nainar3ea9e332015-04-08 08:57:32 -070059static std::vector<FlattenedSpelling>
60GetFlattenedSpellings(const Record &Attr) {
Stephen Hines651f13c2014-04-23 16:59:28 -070061 std::vector<Record *> Spellings = Attr.getValueAsListOfDefs("Spellings");
62 std::vector<FlattenedSpelling> Ret;
63
64 for (const auto &Spelling : Spellings) {
65 if (Spelling->getValueAsString("Variety") == "GCC") {
66 // Gin up two new spelling objects to add into the list.
67 Ret.push_back(FlattenedSpelling("GNU", Spelling->getValueAsString("Name"),
68 "", true));
69 Ret.push_back(FlattenedSpelling(
70 "CXX11", Spelling->getValueAsString("Name"), "gnu", true));
71 } else
72 Ret.push_back(FlattenedSpelling(*Spelling));
73 }
74
75 return Ret;
Peter Collingbourne51d77772011-10-06 13:03:08 +000076}
77
78static std::string ReadPCHRecord(StringRef type) {
79 return StringSwitch<std::string>(type)
80 .EndsWith("Decl *", "GetLocalDeclAs<"
81 + std::string(type, 0, type.size()-1) + ">(F, Record[Idx++])")
Richard Smithddc2a532013-10-31 21:23:20 +000082 .Case("TypeSourceInfo *", "GetTypeSourceInfo(F, Record, Idx)")
Argyrios Kyrtzidis350aea72012-11-15 01:31:39 +000083 .Case("Expr *", "ReadExpr(F)")
Peter Collingbourne51d77772011-10-06 13:03:08 +000084 .Case("IdentifierInfo *", "GetIdentifierInfo(F, Record, Idx)")
Peter Collingbourne51d77772011-10-06 13:03:08 +000085 .Default("Record[Idx++]");
86}
87
88// Assumes that the way to get the value is SA->getname()
89static std::string WritePCHRecord(StringRef type, StringRef name) {
90 return StringSwitch<std::string>(type)
91 .EndsWith("Decl *", "AddDeclRef(" + std::string(name) +
92 ", Record);\n")
Richard Smithddc2a532013-10-31 21:23:20 +000093 .Case("TypeSourceInfo *",
94 "AddTypeSourceInfo(" + std::string(name) + ", Record);\n")
Peter Collingbourne51d77772011-10-06 13:03:08 +000095 .Case("Expr *", "AddStmt(" + std::string(name) + ");\n")
96 .Case("IdentifierInfo *",
97 "AddIdentifierRef(" + std::string(name) + ", Record);\n")
Peter Collingbourne51d77772011-10-06 13:03:08 +000098 .Default("Record.push_back(" + std::string(name) + ");\n");
99}
100
Michael Hane53ac8a2012-03-07 00:12:16 +0000101// Normalize attribute name by removing leading and trailing
102// underscores. For example, __foo, foo__, __foo__ would
103// become foo.
104static StringRef NormalizeAttrName(StringRef AttrName) {
105 if (AttrName.startswith("__"))
106 AttrName = AttrName.substr(2, AttrName.size());
107
108 if (AttrName.endswith("__"))
109 AttrName = AttrName.substr(0, AttrName.size() - 2);
110
111 return AttrName;
112}
113
Stephen Hines651f13c2014-04-23 16:59:28 -0700114// Normalize the name by removing any and all leading and trailing underscores.
115// This is different from NormalizeAttrName in that it also handles names like
116// _pascal and __pascal.
117static StringRef NormalizeNameForSpellingComparison(StringRef Name) {
Pirama Arumuga Nainar33337ca2015-05-06 11:48:57 -0700118 return Name.trim("_");
Stephen Hines651f13c2014-04-23 16:59:28 -0700119}
120
Michael Hane53ac8a2012-03-07 00:12:16 +0000121// Normalize attribute spelling only if the spelling has both leading
122// and trailing underscores. For example, __ms_struct__ will be
123// normalized to "ms_struct"; __cdecl will remain intact.
124static StringRef NormalizeAttrSpelling(StringRef AttrSpelling) {
125 if (AttrSpelling.startswith("__") && AttrSpelling.endswith("__")) {
126 AttrSpelling = AttrSpelling.substr(2, AttrSpelling.size() - 4);
127 }
128
129 return AttrSpelling;
130}
131
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700132typedef std::vector<std::pair<std::string, const Record *>> ParsedAttrMap;
Stephen Hines651f13c2014-04-23 16:59:28 -0700133
134static ParsedAttrMap getParsedAttrList(const RecordKeeper &Records,
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700135 ParsedAttrMap *Dupes = nullptr) {
Stephen Hines651f13c2014-04-23 16:59:28 -0700136 std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
137 std::set<std::string> Seen;
138 ParsedAttrMap R;
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700139 for (const auto *Attr : Attrs) {
Stephen Hines651f13c2014-04-23 16:59:28 -0700140 if (Attr->getValueAsBit("SemaHandler")) {
141 std::string AN;
142 if (Attr->isSubClassOf("TargetSpecificAttr") &&
143 !Attr->isValueUnset("ParseKind")) {
144 AN = Attr->getValueAsString("ParseKind");
145
146 // If this attribute has already been handled, it does not need to be
147 // handled again.
148 if (Seen.find(AN) != Seen.end()) {
149 if (Dupes)
150 Dupes->push_back(std::make_pair(AN, Attr));
151 continue;
152 }
153 Seen.insert(AN);
154 } else
155 AN = NormalizeAttrName(Attr->getName()).str();
156
157 R.push_back(std::make_pair(AN, Attr));
158 }
159 }
160 return R;
161}
162
Peter Collingbourne51d77772011-10-06 13:03:08 +0000163namespace {
164 class Argument {
165 std::string lowerName, upperName;
166 StringRef attrName;
Aaron Ballmanbbb3b322013-09-09 23:33:17 +0000167 bool isOpt;
Peter Collingbourne51d77772011-10-06 13:03:08 +0000168
169 public:
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700170 Argument(const Record &Arg, StringRef Attr)
Peter Collingbourne51d77772011-10-06 13:03:08 +0000171 : lowerName(Arg.getValueAsString("Name")), upperName(lowerName),
Aaron Ballmanbbb3b322013-09-09 23:33:17 +0000172 attrName(Attr), isOpt(false) {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000173 if (!lowerName.empty()) {
174 lowerName[0] = std::tolower(lowerName[0]);
175 upperName[0] = std::toupper(upperName[0]);
176 }
177 }
178 virtual ~Argument() {}
179
180 StringRef getLowerName() const { return lowerName; }
181 StringRef getUpperName() const { return upperName; }
182 StringRef getAttrName() const { return attrName; }
183
Aaron Ballmanbbb3b322013-09-09 23:33:17 +0000184 bool isOptional() const { return isOpt; }
185 void setOptional(bool set) { isOpt = set; }
186
Peter Collingbourne51d77772011-10-06 13:03:08 +0000187 // These functions print the argument contents formatted in different ways.
188 virtual void writeAccessors(raw_ostream &OS) const = 0;
189 virtual void writeAccessorDefinitions(raw_ostream &OS) const {}
Stephen Hines651f13c2014-04-23 16:59:28 -0700190 virtual void writeASTVisitorTraversal(raw_ostream &OS) const {}
Peter Collingbourne51d77772011-10-06 13:03:08 +0000191 virtual void writeCloneArgs(raw_ostream &OS) const = 0;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000192 virtual void writeTemplateInstantiationArgs(raw_ostream &OS) const = 0;
Daniel Dunbarb8806092012-02-10 06:00:29 +0000193 virtual void writeTemplateInstantiation(raw_ostream &OS) const {}
Peter Collingbourne51d77772011-10-06 13:03:08 +0000194 virtual void writeCtorBody(raw_ostream &OS) const {}
195 virtual void writeCtorInitializers(raw_ostream &OS) const = 0;
Aaron Ballmanbbb3b322013-09-09 23:33:17 +0000196 virtual void writeCtorDefaultInitializers(raw_ostream &OS) const = 0;
Peter Collingbourne51d77772011-10-06 13:03:08 +0000197 virtual void writeCtorParameters(raw_ostream &OS) const = 0;
198 virtual void writeDeclarations(raw_ostream &OS) const = 0;
199 virtual void writePCHReadArgs(raw_ostream &OS) const = 0;
200 virtual void writePCHReadDecls(raw_ostream &OS) const = 0;
201 virtual void writePCHWrite(raw_ostream &OS) const = 0;
Douglas Gregor1bea8802011-11-19 19:22:57 +0000202 virtual void writeValue(raw_ostream &OS) const = 0;
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000203 virtual void writeDump(raw_ostream &OS) const = 0;
204 virtual void writeDumpChildren(raw_ostream &OS) const {}
Richard Trieue8d41192013-01-31 01:44:26 +0000205 virtual void writeHasChildren(raw_ostream &OS) const { OS << "false"; }
Aaron Ballmand0686072013-09-11 19:47:58 +0000206
207 virtual bool isEnumArg() const { return false; }
DeLesley Hutchins66540852013-10-04 21:28:06 +0000208 virtual bool isVariadicEnumArg() const { return false; }
Stephen Hines176edba2014-12-01 14:53:08 -0800209 virtual bool isVariadic() const { return false; }
Stephen Hines651f13c2014-04-23 16:59:28 -0700210
211 virtual void writeImplicitCtorArgs(raw_ostream &OS) const {
212 OS << getUpperName();
213 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000214 };
215
216 class SimpleArgument : public Argument {
217 std::string type;
218
219 public:
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700220 SimpleArgument(const Record &Arg, StringRef Attr, std::string T)
Peter Collingbourne51d77772011-10-06 13:03:08 +0000221 : Argument(Arg, Attr), type(T)
222 {}
223
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000224 std::string getType() const { return type; }
225
Stephen Hines651f13c2014-04-23 16:59:28 -0700226 void writeAccessors(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000227 OS << " " << type << " get" << getUpperName() << "() const {\n";
228 OS << " return " << getLowerName() << ";\n";
229 OS << " }";
230 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700231 void writeCloneArgs(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000232 OS << getLowerName();
233 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700234 void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000235 OS << "A->get" << getUpperName() << "()";
236 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700237 void writeCtorInitializers(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000238 OS << getLowerName() << "(" << getUpperName() << ")";
239 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700240 void writeCtorDefaultInitializers(raw_ostream &OS) const override {
Aaron Ballmanbbb3b322013-09-09 23:33:17 +0000241 OS << getLowerName() << "()";
242 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700243 void writeCtorParameters(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000244 OS << type << " " << getUpperName();
245 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700246 void writeDeclarations(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000247 OS << type << " " << getLowerName() << ";";
248 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700249 void writePCHReadDecls(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000250 std::string read = ReadPCHRecord(type);
251 OS << " " << type << " " << getLowerName() << " = " << read << ";\n";
252 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700253 void writePCHReadArgs(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000254 OS << getLowerName();
255 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700256 void writePCHWrite(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000257 OS << " " << WritePCHRecord(type, "SA->get" +
258 std::string(getUpperName()) + "()");
259 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700260 void writeValue(raw_ostream &OS) const override {
Douglas Gregor1bea8802011-11-19 19:22:57 +0000261 if (type == "FunctionDecl *") {
Richard Smithddc2a532013-10-31 21:23:20 +0000262 OS << "\" << get" << getUpperName()
263 << "()->getNameInfo().getAsString() << \"";
Douglas Gregor1bea8802011-11-19 19:22:57 +0000264 } else if (type == "IdentifierInfo *") {
265 OS << "\" << get" << getUpperName() << "()->getName() << \"";
Richard Smithddc2a532013-10-31 21:23:20 +0000266 } else if (type == "TypeSourceInfo *") {
Douglas Gregor1bea8802011-11-19 19:22:57 +0000267 OS << "\" << get" << getUpperName() << "().getAsString() << \"";
Douglas Gregor1bea8802011-11-19 19:22:57 +0000268 } else {
269 OS << "\" << get" << getUpperName() << "() << \"";
270 }
271 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700272 void writeDump(raw_ostream &OS) const override {
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000273 if (type == "FunctionDecl *") {
274 OS << " OS << \" \";\n";
275 OS << " dumpBareDeclRef(SA->get" << getUpperName() << "());\n";
276 } else if (type == "IdentifierInfo *") {
277 OS << " OS << \" \" << SA->get" << getUpperName()
278 << "()->getName();\n";
Richard Smithddc2a532013-10-31 21:23:20 +0000279 } else if (type == "TypeSourceInfo *") {
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000280 OS << " OS << \" \" << SA->get" << getUpperName()
281 << "().getAsString();\n";
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000282 } else if (type == "bool") {
283 OS << " if (SA->get" << getUpperName() << "()) OS << \" "
284 << getUpperName() << "\";\n";
285 } else if (type == "int" || type == "unsigned") {
286 OS << " OS << \" \" << SA->get" << getUpperName() << "();\n";
287 } else {
288 llvm_unreachable("Unknown SimpleArgument type!");
289 }
290 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000291 };
292
Stephen Hines651f13c2014-04-23 16:59:28 -0700293 class DefaultSimpleArgument : public SimpleArgument {
294 int64_t Default;
295
296 public:
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700297 DefaultSimpleArgument(const Record &Arg, StringRef Attr,
Stephen Hines651f13c2014-04-23 16:59:28 -0700298 std::string T, int64_t Default)
299 : SimpleArgument(Arg, Attr, T), Default(Default) {}
300
301 void writeAccessors(raw_ostream &OS) const override {
302 SimpleArgument::writeAccessors(OS);
303
304 OS << "\n\n static const " << getType() << " Default" << getUpperName()
305 << " = " << Default << ";";
306 }
307 };
308
Peter Collingbourne51d77772011-10-06 13:03:08 +0000309 class StringArgument : public Argument {
310 public:
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700311 StringArgument(const Record &Arg, StringRef Attr)
Peter Collingbourne51d77772011-10-06 13:03:08 +0000312 : Argument(Arg, Attr)
313 {}
314
Stephen Hines651f13c2014-04-23 16:59:28 -0700315 void writeAccessors(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000316 OS << " llvm::StringRef get" << getUpperName() << "() const {\n";
317 OS << " return llvm::StringRef(" << getLowerName() << ", "
318 << getLowerName() << "Length);\n";
319 OS << " }\n";
320 OS << " unsigned get" << getUpperName() << "Length() const {\n";
321 OS << " return " << getLowerName() << "Length;\n";
322 OS << " }\n";
323 OS << " void set" << getUpperName()
324 << "(ASTContext &C, llvm::StringRef S) {\n";
325 OS << " " << getLowerName() << "Length = S.size();\n";
326 OS << " this->" << getLowerName() << " = new (C, 1) char ["
327 << getLowerName() << "Length];\n";
328 OS << " std::memcpy(this->" << getLowerName() << ", S.data(), "
329 << getLowerName() << "Length);\n";
330 OS << " }";
331 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700332 void writeCloneArgs(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000333 OS << "get" << getUpperName() << "()";
334 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700335 void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000336 OS << "A->get" << getUpperName() << "()";
337 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700338 void writeCtorBody(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000339 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
340 << ".data(), " << getLowerName() << "Length);";
341 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700342 void writeCtorInitializers(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000343 OS << getLowerName() << "Length(" << getUpperName() << ".size()),"
344 << getLowerName() << "(new (Ctx, 1) char[" << getLowerName()
345 << "Length])";
346 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700347 void writeCtorDefaultInitializers(raw_ostream &OS) const override {
Aaron Ballmanbbb3b322013-09-09 23:33:17 +0000348 OS << getLowerName() << "Length(0)," << getLowerName() << "(0)";
349 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700350 void writeCtorParameters(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000351 OS << "llvm::StringRef " << getUpperName();
352 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700353 void writeDeclarations(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000354 OS << "unsigned " << getLowerName() << "Length;\n";
355 OS << "char *" << getLowerName() << ";";
356 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700357 void writePCHReadDecls(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000358 OS << " std::string " << getLowerName()
359 << "= ReadString(Record, Idx);\n";
360 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700361 void writePCHReadArgs(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000362 OS << getLowerName();
363 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700364 void writePCHWrite(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000365 OS << " AddString(SA->get" << getUpperName() << "(), Record);\n";
366 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700367 void writeValue(raw_ostream &OS) const override {
Douglas Gregor1bea8802011-11-19 19:22:57 +0000368 OS << "\\\"\" << get" << getUpperName() << "() << \"\\\"";
369 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700370 void writeDump(raw_ostream &OS) const override {
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000371 OS << " OS << \" \\\"\" << SA->get" << getUpperName()
372 << "() << \"\\\"\";\n";
373 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000374 };
375
376 class AlignedArgument : public Argument {
377 public:
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700378 AlignedArgument(const Record &Arg, StringRef Attr)
Peter Collingbourne51d77772011-10-06 13:03:08 +0000379 : Argument(Arg, Attr)
380 {}
381
Stephen Hines651f13c2014-04-23 16:59:28 -0700382 void writeAccessors(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000383 OS << " bool is" << getUpperName() << "Dependent() const;\n";
384
385 OS << " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n";
386
387 OS << " bool is" << getUpperName() << "Expr() const {\n";
388 OS << " return is" << getLowerName() << "Expr;\n";
389 OS << " }\n";
390
391 OS << " Expr *get" << getUpperName() << "Expr() const {\n";
392 OS << " assert(is" << getLowerName() << "Expr);\n";
393 OS << " return " << getLowerName() << "Expr;\n";
394 OS << " }\n";
395
396 OS << " TypeSourceInfo *get" << getUpperName() << "Type() const {\n";
397 OS << " assert(!is" << getLowerName() << "Expr);\n";
398 OS << " return " << getLowerName() << "Type;\n";
399 OS << " }";
400 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700401 void writeAccessorDefinitions(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000402 OS << "bool " << getAttrName() << "Attr::is" << getUpperName()
403 << "Dependent() const {\n";
404 OS << " if (is" << getLowerName() << "Expr)\n";
405 OS << " return " << getLowerName() << "Expr && (" << getLowerName()
406 << "Expr->isValueDependent() || " << getLowerName()
407 << "Expr->isTypeDependent());\n";
408 OS << " else\n";
409 OS << " return " << getLowerName()
410 << "Type->getType()->isDependentType();\n";
411 OS << "}\n";
412
413 // FIXME: Do not do the calculation here
414 // FIXME: Handle types correctly
415 // A null pointer means maximum alignment
416 // FIXME: Load the platform-specific maximum alignment, rather than
417 // 16, the x86 max.
418 OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName()
419 << "(ASTContext &Ctx) const {\n";
420 OS << " assert(!is" << getUpperName() << "Dependent());\n";
421 OS << " if (is" << getLowerName() << "Expr)\n";
422 OS << " return (" << getLowerName() << "Expr ? " << getLowerName()
Richard Smitha6b8b2c2011-10-10 18:28:20 +0000423 << "Expr->EvaluateKnownConstInt(Ctx).getZExtValue() : 16)"
Peter Collingbourne51d77772011-10-06 13:03:08 +0000424 << "* Ctx.getCharWidth();\n";
425 OS << " else\n";
426 OS << " return 0; // FIXME\n";
427 OS << "}\n";
428 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700429 void writeCloneArgs(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000430 OS << "is" << getLowerName() << "Expr, is" << getLowerName()
431 << "Expr ? static_cast<void*>(" << getLowerName()
432 << "Expr) : " << getLowerName()
433 << "Type";
434 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700435 void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000436 // FIXME: move the definition in Sema::InstantiateAttrs to here.
437 // In the meantime, aligned attributes are cloned.
438 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700439 void writeCtorBody(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000440 OS << " if (is" << getLowerName() << "Expr)\n";
441 OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>("
442 << getUpperName() << ");\n";
443 OS << " else\n";
444 OS << " " << getLowerName()
445 << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName()
446 << ");";
447 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700448 void writeCtorInitializers(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000449 OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)";
450 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700451 void writeCtorDefaultInitializers(raw_ostream &OS) const override {
Aaron Ballmanbbb3b322013-09-09 23:33:17 +0000452 OS << "is" << getLowerName() << "Expr(false)";
453 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700454 void writeCtorParameters(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000455 OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName();
456 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700457 void writeImplicitCtorArgs(raw_ostream &OS) const override {
458 OS << "Is" << getUpperName() << "Expr, " << getUpperName();
459 }
460 void writeDeclarations(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000461 OS << "bool is" << getLowerName() << "Expr;\n";
462 OS << "union {\n";
463 OS << "Expr *" << getLowerName() << "Expr;\n";
464 OS << "TypeSourceInfo *" << getLowerName() << "Type;\n";
465 OS << "};";
466 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700467 void writePCHReadArgs(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000468 OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr";
469 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700470 void writePCHReadDecls(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000471 OS << " bool is" << getLowerName() << "Expr = Record[Idx++];\n";
472 OS << " void *" << getLowerName() << "Ptr;\n";
473 OS << " if (is" << getLowerName() << "Expr)\n";
474 OS << " " << getLowerName() << "Ptr = ReadExpr(F);\n";
475 OS << " else\n";
476 OS << " " << getLowerName()
477 << "Ptr = GetTypeSourceInfo(F, Record, Idx);\n";
478 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700479 void writePCHWrite(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000480 OS << " Record.push_back(SA->is" << getUpperName() << "Expr());\n";
481 OS << " if (SA->is" << getUpperName() << "Expr())\n";
482 OS << " AddStmt(SA->get" << getUpperName() << "Expr());\n";
483 OS << " else\n";
484 OS << " AddTypeSourceInfo(SA->get" << getUpperName()
485 << "Type(), Record);\n";
486 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700487 void writeValue(raw_ostream &OS) const override {
Stephen Hinesc568f1e2014-07-21 00:47:37 -0700488 OS << "\";\n";
Stephen Hines176edba2014-12-01 14:53:08 -0800489 // The aligned attribute argument expression is optional.
490 OS << " if (is" << getLowerName() << "Expr && "
491 << getLowerName() << "Expr)\n";
492 OS << " " << getLowerName() << "Expr->printPretty(OS, 0, Policy);\n";
Stephen Hinesc568f1e2014-07-21 00:47:37 -0700493 OS << " OS << \"";
Douglas Gregor1bea8802011-11-19 19:22:57 +0000494 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700495 void writeDump(raw_ostream &OS) const override {
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000496 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700497 void writeDumpChildren(raw_ostream &OS) const override {
Stephen Hines176edba2014-12-01 14:53:08 -0800498 OS << " if (SA->is" << getUpperName() << "Expr())\n";
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000499 OS << " dumpStmt(SA->get" << getUpperName() << "Expr());\n";
Stephen Hines176edba2014-12-01 14:53:08 -0800500 OS << " else\n";
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000501 OS << " dumpType(SA->get" << getUpperName()
502 << "Type()->getType());\n";
503 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700504 void writeHasChildren(raw_ostream &OS) const override {
Richard Trieue8d41192013-01-31 01:44:26 +0000505 OS << "SA->is" << getUpperName() << "Expr()";
506 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000507 };
508
509 class VariadicArgument : public Argument {
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700510 std::string Type, ArgName, ArgSizeName, RangeName;
Peter Collingbourne51d77772011-10-06 13:03:08 +0000511
Stephen Hines176edba2014-12-01 14:53:08 -0800512 protected:
513 // Assumed to receive a parameter: raw_ostream OS.
514 virtual void writeValueImpl(raw_ostream &OS) const {
515 OS << " OS << Val;\n";
516 }
517
Peter Collingbourne51d77772011-10-06 13:03:08 +0000518 public:
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700519 VariadicArgument(const Record &Arg, StringRef Attr, std::string T)
520 : Argument(Arg, Attr), Type(T), ArgName(getLowerName().str() + "_"),
521 ArgSizeName(ArgName + "Size"), RangeName(getLowerName()) {}
Peter Collingbourne51d77772011-10-06 13:03:08 +0000522
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700523 std::string getType() const { return Type; }
Stephen Hines176edba2014-12-01 14:53:08 -0800524 bool isVariadic() const override { return true; }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000525
Stephen Hines651f13c2014-04-23 16:59:28 -0700526 void writeAccessors(raw_ostream &OS) const override {
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700527 std::string IteratorType = getLowerName().str() + "_iterator";
528 std::string BeginFn = getLowerName().str() + "_begin()";
529 std::string EndFn = getLowerName().str() + "_end()";
530
531 OS << " typedef " << Type << "* " << IteratorType << ";\n";
532 OS << " " << IteratorType << " " << BeginFn << " const {"
533 << " return " << ArgName << "; }\n";
534 OS << " " << IteratorType << " " << EndFn << " const {"
535 << " return " << ArgName << " + " << ArgSizeName << "; }\n";
536 OS << " unsigned " << getLowerName() << "_size() const {"
537 << " return " << ArgSizeName << "; }\n";
538 OS << " llvm::iterator_range<" << IteratorType << "> " << RangeName
539 << "() const { return llvm::make_range(" << BeginFn << ", " << EndFn
540 << "); }\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000541 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700542 void writeCloneArgs(raw_ostream &OS) const override {
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700543 OS << ArgName << ", " << ArgSizeName;
Peter Collingbourne51d77772011-10-06 13:03:08 +0000544 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700545 void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000546 // This isn't elegant, but we have to go through public methods...
547 OS << "A->" << getLowerName() << "_begin(), "
548 << "A->" << getLowerName() << "_size()";
549 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700550 void writeCtorBody(raw_ostream &OS) const override {
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700551 OS << " std::copy(" << getUpperName() << ", " << getUpperName()
552 << " + " << ArgSizeName << ", " << ArgName << ");";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000553 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700554 void writeCtorInitializers(raw_ostream &OS) const override {
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700555 OS << ArgSizeName << "(" << getUpperName() << "Size), "
556 << ArgName << "(new (Ctx, 16) " << getType() << "["
557 << ArgSizeName << "])";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000558 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700559 void writeCtorDefaultInitializers(raw_ostream &OS) const override {
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700560 OS << ArgSizeName << "(0), " << ArgName << "(nullptr)";
Aaron Ballmanbbb3b322013-09-09 23:33:17 +0000561 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700562 void writeCtorParameters(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000563 OS << getType() << " *" << getUpperName() << ", unsigned "
564 << getUpperName() << "Size";
565 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700566 void writeImplicitCtorArgs(raw_ostream &OS) const override {
567 OS << getUpperName() << ", " << getUpperName() << "Size";
568 }
569 void writeDeclarations(raw_ostream &OS) const override {
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700570 OS << " unsigned " << ArgSizeName << ";\n";
571 OS << " " << getType() << " *" << ArgName << ";";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000572 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700573 void writePCHReadDecls(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000574 OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700575 OS << " SmallVector<" << Type << ", 4> " << getLowerName()
Peter Collingbourne51d77772011-10-06 13:03:08 +0000576 << ";\n";
577 OS << " " << getLowerName() << ".reserve(" << getLowerName()
578 << "Size);\n";
DeLesley Hutchins66540852013-10-04 21:28:06 +0000579 OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +0000580
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700581 std::string read = ReadPCHRecord(Type);
Peter Collingbourne51d77772011-10-06 13:03:08 +0000582 OS << " " << getLowerName() << ".push_back(" << read << ");\n";
583 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700584 void writePCHReadArgs(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000585 OS << getLowerName() << ".data(), " << getLowerName() << "Size";
586 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700587 void writePCHWrite(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000588 OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700589 OS << " for (auto &Val : SA->" << RangeName << "())\n";
590 OS << " " << WritePCHRecord(Type, "Val");
Peter Collingbourne51d77772011-10-06 13:03:08 +0000591 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700592 void writeValue(raw_ostream &OS) const override {
Douglas Gregor1bea8802011-11-19 19:22:57 +0000593 OS << "\";\n";
594 OS << " bool isFirst = true;\n"
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700595 << " for (const auto &Val : " << RangeName << "()) {\n"
Douglas Gregor1bea8802011-11-19 19:22:57 +0000596 << " if (isFirst) isFirst = false;\n"
Stephen Hines176edba2014-12-01 14:53:08 -0800597 << " else OS << \", \";\n";
598 writeValueImpl(OS);
599 OS << " }\n";
Douglas Gregor1bea8802011-11-19 19:22:57 +0000600 OS << " OS << \"";
601 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700602 void writeDump(raw_ostream &OS) const override {
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700603 OS << " for (const auto &Val : SA->" << RangeName << "())\n";
604 OS << " OS << \" \" << Val;\n";
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000605 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000606 };
607
Stephen Hines651f13c2014-04-23 16:59:28 -0700608 // Unique the enums, but maintain the original declaration ordering.
609 std::vector<std::string>
610 uniqueEnumsInOrder(const std::vector<std::string> &enums) {
611 std::vector<std::string> uniques;
612 std::set<std::string> unique_set(enums.begin(), enums.end());
613 for (const auto &i : enums) {
614 std::set<std::string>::iterator set_i = unique_set.find(i);
615 if (set_i != unique_set.end()) {
616 uniques.push_back(i);
617 unique_set.erase(set_i);
618 }
619 }
620 return uniques;
621 }
622
Peter Collingbourne51d77772011-10-06 13:03:08 +0000623 class EnumArgument : public Argument {
624 std::string type;
Stephen Hines651f13c2014-04-23 16:59:28 -0700625 std::vector<std::string> values, enums, uniques;
Peter Collingbourne51d77772011-10-06 13:03:08 +0000626 public:
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700627 EnumArgument(const Record &Arg, StringRef Attr)
Peter Collingbourne51d77772011-10-06 13:03:08 +0000628 : Argument(Arg, Attr), type(Arg.getValueAsString("Type")),
Stephen Hines651f13c2014-04-23 16:59:28 -0700629 values(Arg.getValueAsListOfStrings("Values")),
630 enums(Arg.getValueAsListOfStrings("Enums")),
631 uniques(uniqueEnumsInOrder(enums))
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000632 {
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000633 // FIXME: Emit a proper error
634 assert(!uniques.empty());
635 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000636
Stephen Hines651f13c2014-04-23 16:59:28 -0700637 bool isEnumArg() const override { return true; }
Aaron Ballmand0686072013-09-11 19:47:58 +0000638
Stephen Hines651f13c2014-04-23 16:59:28 -0700639 void writeAccessors(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000640 OS << " " << type << " get" << getUpperName() << "() const {\n";
641 OS << " return " << getLowerName() << ";\n";
642 OS << " }";
643 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700644 void writeCloneArgs(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000645 OS << getLowerName();
646 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700647 void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000648 OS << "A->get" << getUpperName() << "()";
649 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700650 void writeCtorInitializers(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000651 OS << getLowerName() << "(" << getUpperName() << ")";
652 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700653 void writeCtorDefaultInitializers(raw_ostream &OS) const override {
Aaron Ballmanbbb3b322013-09-09 23:33:17 +0000654 OS << getLowerName() << "(" << type << "(0))";
655 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700656 void writeCtorParameters(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000657 OS << type << " " << getUpperName();
658 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700659 void writeDeclarations(raw_ostream &OS) const override {
660 std::vector<std::string>::const_iterator i = uniques.begin(),
661 e = uniques.end();
Peter Collingbourne51d77772011-10-06 13:03:08 +0000662 // The last one needs to not have a comma.
663 --e;
664
665 OS << "public:\n";
666 OS << " enum " << type << " {\n";
667 for (; i != e; ++i)
668 OS << " " << *i << ",\n";
669 OS << " " << *e << "\n";
670 OS << " };\n";
671 OS << "private:\n";
672 OS << " " << type << " " << getLowerName() << ";";
673 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700674 void writePCHReadDecls(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000675 OS << " " << getAttrName() << "Attr::" << type << " " << getLowerName()
676 << "(static_cast<" << getAttrName() << "Attr::" << type
677 << ">(Record[Idx++]));\n";
678 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700679 void writePCHReadArgs(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000680 OS << getLowerName();
681 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700682 void writePCHWrite(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000683 OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
684 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700685 void writeValue(raw_ostream &OS) const override {
Stephen Hines176edba2014-12-01 14:53:08 -0800686 // FIXME: this isn't 100% correct -- some enum arguments require printing
687 // as a string literal, while others require printing as an identifier.
688 // Tablegen currently does not distinguish between the two forms.
689 OS << "\\\"\" << " << getAttrName() << "Attr::Convert" << type << "ToStr(get"
690 << getUpperName() << "()) << \"\\\"";
Douglas Gregor1bea8802011-11-19 19:22:57 +0000691 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700692 void writeDump(raw_ostream &OS) const override {
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000693 OS << " switch(SA->get" << getUpperName() << "()) {\n";
Stephen Hines651f13c2014-04-23 16:59:28 -0700694 for (const auto &I : uniques) {
695 OS << " case " << getAttrName() << "Attr::" << I << ":\n";
696 OS << " OS << \" " << I << "\";\n";
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000697 OS << " break;\n";
698 }
699 OS << " }\n";
700 }
Aaron Ballmand0686072013-09-11 19:47:58 +0000701
702 void writeConversion(raw_ostream &OS) const {
703 OS << " static bool ConvertStrTo" << type << "(StringRef Val, ";
704 OS << type << " &Out) {\n";
705 OS << " Optional<" << type << "> R = llvm::StringSwitch<Optional<";
Stephen Hines651f13c2014-04-23 16:59:28 -0700706 OS << type << ">>(Val)\n";
Aaron Ballmand0686072013-09-11 19:47:58 +0000707 for (size_t I = 0; I < enums.size(); ++I) {
708 OS << " .Case(\"" << values[I] << "\", ";
709 OS << getAttrName() << "Attr::" << enums[I] << ")\n";
710 }
711 OS << " .Default(Optional<" << type << ">());\n";
712 OS << " if (R) {\n";
713 OS << " Out = *R;\n return true;\n }\n";
714 OS << " return false;\n";
Stephen Hines176edba2014-12-01 14:53:08 -0800715 OS << " }\n\n";
716
717 // Mapping from enumeration values back to enumeration strings isn't
718 // trivial because some enumeration values have multiple named
719 // enumerators, such as type_visibility(internal) and
720 // type_visibility(hidden) both mapping to TypeVisibilityAttr::Hidden.
721 OS << " static const char *Convert" << type << "ToStr("
722 << type << " Val) {\n"
723 << " switch(Val) {\n";
724 std::set<std::string> Uniques;
725 for (size_t I = 0; I < enums.size(); ++I) {
726 if (Uniques.insert(enums[I]).second)
727 OS << " case " << getAttrName() << "Attr::" << enums[I]
728 << ": return \"" << values[I] << "\";\n";
729 }
730 OS << " }\n"
731 << " llvm_unreachable(\"No enumerator with that value\");\n"
732 << " }\n";
Aaron Ballmand0686072013-09-11 19:47:58 +0000733 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000734 };
DeLesley Hutchins66540852013-10-04 21:28:06 +0000735
736 class VariadicEnumArgument: public VariadicArgument {
737 std::string type, QualifiedTypeName;
Stephen Hines651f13c2014-04-23 16:59:28 -0700738 std::vector<std::string> values, enums, uniques;
Stephen Hines176edba2014-12-01 14:53:08 -0800739
740 protected:
741 void writeValueImpl(raw_ostream &OS) const override {
742 // FIXME: this isn't 100% correct -- some enum arguments require printing
743 // as a string literal, while others require printing as an identifier.
744 // Tablegen currently does not distinguish between the two forms.
745 OS << " OS << \"\\\"\" << " << getAttrName() << "Attr::Convert" << type
746 << "ToStr(Val)" << "<< \"\\\"\";\n";
747 }
748
DeLesley Hutchins66540852013-10-04 21:28:06 +0000749 public:
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700750 VariadicEnumArgument(const Record &Arg, StringRef Attr)
DeLesley Hutchins66540852013-10-04 21:28:06 +0000751 : VariadicArgument(Arg, Attr, Arg.getValueAsString("Type")),
752 type(Arg.getValueAsString("Type")),
Stephen Hines651f13c2014-04-23 16:59:28 -0700753 values(Arg.getValueAsListOfStrings("Values")),
754 enums(Arg.getValueAsListOfStrings("Enums")),
755 uniques(uniqueEnumsInOrder(enums))
DeLesley Hutchins66540852013-10-04 21:28:06 +0000756 {
DeLesley Hutchins66540852013-10-04 21:28:06 +0000757 QualifiedTypeName = getAttrName().str() + "Attr::" + type;
758
759 // FIXME: Emit a proper error
760 assert(!uniques.empty());
761 }
762
Stephen Hines651f13c2014-04-23 16:59:28 -0700763 bool isVariadicEnumArg() const override { return true; }
DeLesley Hutchins66540852013-10-04 21:28:06 +0000764
Stephen Hines651f13c2014-04-23 16:59:28 -0700765 void writeDeclarations(raw_ostream &OS) const override {
766 std::vector<std::string>::const_iterator i = uniques.begin(),
767 e = uniques.end();
DeLesley Hutchins66540852013-10-04 21:28:06 +0000768 // The last one needs to not have a comma.
769 --e;
770
771 OS << "public:\n";
772 OS << " enum " << type << " {\n";
773 for (; i != e; ++i)
774 OS << " " << *i << ",\n";
775 OS << " " << *e << "\n";
776 OS << " };\n";
777 OS << "private:\n";
778
779 VariadicArgument::writeDeclarations(OS);
780 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700781 void writeDump(raw_ostream &OS) const override {
DeLesley Hutchins66540852013-10-04 21:28:06 +0000782 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
783 << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
784 << getLowerName() << "_end(); I != E; ++I) {\n";
785 OS << " switch(*I) {\n";
Stephen Hines651f13c2014-04-23 16:59:28 -0700786 for (const auto &UI : uniques) {
787 OS << " case " << getAttrName() << "Attr::" << UI << ":\n";
788 OS << " OS << \" " << UI << "\";\n";
DeLesley Hutchins66540852013-10-04 21:28:06 +0000789 OS << " break;\n";
790 }
791 OS << " }\n";
792 OS << " }\n";
793 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700794 void writePCHReadDecls(raw_ostream &OS) const override {
DeLesley Hutchins66540852013-10-04 21:28:06 +0000795 OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n";
796 OS << " SmallVector<" << QualifiedTypeName << ", 4> " << getLowerName()
797 << ";\n";
798 OS << " " << getLowerName() << ".reserve(" << getLowerName()
799 << "Size);\n";
800 OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
801 OS << " " << getLowerName() << ".push_back(" << "static_cast<"
802 << QualifiedTypeName << ">(Record[Idx++]));\n";
803 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700804 void writePCHWrite(raw_ostream &OS) const override {
DeLesley Hutchins66540852013-10-04 21:28:06 +0000805 OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";
806 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
807 << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
808 << getLowerName() << "_end(); i != e; ++i)\n";
809 OS << " " << WritePCHRecord(QualifiedTypeName, "(*i)");
810 }
811 void writeConversion(raw_ostream &OS) const {
812 OS << " static bool ConvertStrTo" << type << "(StringRef Val, ";
813 OS << type << " &Out) {\n";
814 OS << " Optional<" << type << "> R = llvm::StringSwitch<Optional<";
Stephen Hines651f13c2014-04-23 16:59:28 -0700815 OS << type << ">>(Val)\n";
DeLesley Hutchins66540852013-10-04 21:28:06 +0000816 for (size_t I = 0; I < enums.size(); ++I) {
817 OS << " .Case(\"" << values[I] << "\", ";
818 OS << getAttrName() << "Attr::" << enums[I] << ")\n";
819 }
820 OS << " .Default(Optional<" << type << ">());\n";
821 OS << " if (R) {\n";
822 OS << " Out = *R;\n return true;\n }\n";
823 OS << " return false;\n";
Stephen Hines176edba2014-12-01 14:53:08 -0800824 OS << " }\n\n";
825
826 OS << " static const char *Convert" << type << "ToStr("
827 << type << " Val) {\n"
828 << " switch(Val) {\n";
829 std::set<std::string> Uniques;
830 for (size_t I = 0; I < enums.size(); ++I) {
831 if (Uniques.insert(enums[I]).second)
832 OS << " case " << getAttrName() << "Attr::" << enums[I]
833 << ": return \"" << values[I] << "\";\n";
834 }
835 OS << " }\n"
836 << " llvm_unreachable(\"No enumerator with that value\");\n"
837 << " }\n";
DeLesley Hutchins66540852013-10-04 21:28:06 +0000838 }
839 };
Peter Collingbourne51d77772011-10-06 13:03:08 +0000840
841 class VersionArgument : public Argument {
842 public:
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700843 VersionArgument(const Record &Arg, StringRef Attr)
Peter Collingbourne51d77772011-10-06 13:03:08 +0000844 : Argument(Arg, Attr)
845 {}
846
Stephen Hines651f13c2014-04-23 16:59:28 -0700847 void writeAccessors(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000848 OS << " VersionTuple get" << getUpperName() << "() const {\n";
849 OS << " return " << getLowerName() << ";\n";
850 OS << " }\n";
851 OS << " void set" << getUpperName()
852 << "(ASTContext &C, VersionTuple V) {\n";
853 OS << " " << getLowerName() << " = V;\n";
854 OS << " }";
855 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700856 void writeCloneArgs(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000857 OS << "get" << getUpperName() << "()";
858 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700859 void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000860 OS << "A->get" << getUpperName() << "()";
861 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700862 void writeCtorInitializers(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000863 OS << getLowerName() << "(" << getUpperName() << ")";
864 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700865 void writeCtorDefaultInitializers(raw_ostream &OS) const override {
Aaron Ballmanbbb3b322013-09-09 23:33:17 +0000866 OS << getLowerName() << "()";
867 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700868 void writeCtorParameters(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000869 OS << "VersionTuple " << getUpperName();
870 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700871 void writeDeclarations(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000872 OS << "VersionTuple " << getLowerName() << ";\n";
873 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700874 void writePCHReadDecls(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000875 OS << " VersionTuple " << getLowerName()
876 << "= ReadVersionTuple(Record, Idx);\n";
877 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700878 void writePCHReadArgs(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000879 OS << getLowerName();
880 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700881 void writePCHWrite(raw_ostream &OS) const override {
Peter Collingbourne51d77772011-10-06 13:03:08 +0000882 OS << " AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n";
883 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700884 void writeValue(raw_ostream &OS) const override {
Douglas Gregor1bea8802011-11-19 19:22:57 +0000885 OS << getLowerName() << "=\" << get" << getUpperName() << "() << \"";
886 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700887 void writeDump(raw_ostream &OS) const override {
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000888 OS << " OS << \" \" << SA->get" << getUpperName() << "();\n";
889 }
Peter Collingbourne51d77772011-10-06 13:03:08 +0000890 };
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000891
892 class ExprArgument : public SimpleArgument {
893 public:
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700894 ExprArgument(const Record &Arg, StringRef Attr)
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000895 : SimpleArgument(Arg, Attr, "Expr *")
896 {}
897
Stephen Hines651f13c2014-04-23 16:59:28 -0700898 void writeASTVisitorTraversal(raw_ostream &OS) const override {
899 OS << " if (!"
900 << "getDerived().TraverseStmt(A->get" << getUpperName() << "()))\n";
901 OS << " return false;\n";
902 }
903
904 void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000905 OS << "tempInst" << getUpperName();
906 }
907
Stephen Hines651f13c2014-04-23 16:59:28 -0700908 void writeTemplateInstantiation(raw_ostream &OS) const override {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000909 OS << " " << getType() << " tempInst" << getUpperName() << ";\n";
910 OS << " {\n";
911 OS << " EnterExpressionEvaluationContext "
912 << "Unevaluated(S, Sema::Unevaluated);\n";
913 OS << " ExprResult " << "Result = S.SubstExpr("
914 << "A->get" << getUpperName() << "(), TemplateArgs);\n";
915 OS << " tempInst" << getUpperName() << " = "
Stephen Hinesc568f1e2014-07-21 00:47:37 -0700916 << "Result.getAs<Expr>();\n";
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000917 OS << " }\n";
918 }
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000919
Stephen Hines651f13c2014-04-23 16:59:28 -0700920 void writeDump(raw_ostream &OS) const override {}
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000921
Stephen Hines651f13c2014-04-23 16:59:28 -0700922 void writeDumpChildren(raw_ostream &OS) const override {
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000923 OS << " dumpStmt(SA->get" << getUpperName() << "());\n";
924 }
Stephen Hines651f13c2014-04-23 16:59:28 -0700925 void writeHasChildren(raw_ostream &OS) const override { OS << "true"; }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000926 };
927
928 class VariadicExprArgument : public VariadicArgument {
929 public:
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700930 VariadicExprArgument(const Record &Arg, StringRef Attr)
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000931 : VariadicArgument(Arg, Attr, "Expr *")
932 {}
933
Stephen Hines651f13c2014-04-23 16:59:28 -0700934 void writeASTVisitorTraversal(raw_ostream &OS) const override {
935 OS << " {\n";
936 OS << " " << getType() << " *I = A->" << getLowerName()
937 << "_begin();\n";
938 OS << " " << getType() << " *E = A->" << getLowerName()
939 << "_end();\n";
940 OS << " for (; I != E; ++I) {\n";
941 OS << " if (!getDerived().TraverseStmt(*I))\n";
942 OS << " return false;\n";
943 OS << " }\n";
944 OS << " }\n";
945 }
946
947 void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000948 OS << "tempInst" << getUpperName() << ", "
949 << "A->" << getLowerName() << "_size()";
950 }
951
Stephen Hines651f13c2014-04-23 16:59:28 -0700952 void writeTemplateInstantiation(raw_ostream &OS) const override {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000953 OS << " " << getType() << " *tempInst" << getUpperName()
954 << " = new (C, 16) " << getType()
955 << "[A->" << getLowerName() << "_size()];\n";
956 OS << " {\n";
957 OS << " EnterExpressionEvaluationContext "
958 << "Unevaluated(S, Sema::Unevaluated);\n";
959 OS << " " << getType() << " *TI = tempInst" << getUpperName()
960 << ";\n";
961 OS << " " << getType() << " *I = A->" << getLowerName()
962 << "_begin();\n";
963 OS << " " << getType() << " *E = A->" << getLowerName()
964 << "_end();\n";
965 OS << " for (; I != E; ++I, ++TI) {\n";
966 OS << " ExprResult Result = S.SubstExpr(*I, TemplateArgs);\n";
Stephen Hinesc568f1e2014-07-21 00:47:37 -0700967 OS << " *TI = Result.getAs<Expr>();\n";
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000968 OS << " }\n";
969 OS << " }\n";
970 }
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000971
Stephen Hines651f13c2014-04-23 16:59:28 -0700972 void writeDump(raw_ostream &OS) const override {}
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000973
Stephen Hines651f13c2014-04-23 16:59:28 -0700974 void writeDumpChildren(raw_ostream &OS) const override {
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000975 OS << " for (" << getAttrName() << "Attr::" << getLowerName()
976 << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
Stephen Hines176edba2014-12-01 14:53:08 -0800977 << getLowerName() << "_end(); I != E; ++I)\n";
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000978 OS << " dumpStmt(*I);\n";
Richard Trieue8d41192013-01-31 01:44:26 +0000979 }
980
Stephen Hines651f13c2014-04-23 16:59:28 -0700981 void writeHasChildren(raw_ostream &OS) const override {
Richard Trieue8d41192013-01-31 01:44:26 +0000982 OS << "SA->" << getLowerName() << "_begin() != "
983 << "SA->" << getLowerName() << "_end()";
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +0000984 }
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +0000985 };
Richard Smithddc2a532013-10-31 21:23:20 +0000986
987 class TypeArgument : public SimpleArgument {
988 public:
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700989 TypeArgument(const Record &Arg, StringRef Attr)
Richard Smithddc2a532013-10-31 21:23:20 +0000990 : SimpleArgument(Arg, Attr, "TypeSourceInfo *")
991 {}
992
Stephen Hines651f13c2014-04-23 16:59:28 -0700993 void writeAccessors(raw_ostream &OS) const override {
Richard Smithddc2a532013-10-31 21:23:20 +0000994 OS << " QualType get" << getUpperName() << "() const {\n";
995 OS << " return " << getLowerName() << "->getType();\n";
996 OS << " }";
997 OS << " " << getType() << " get" << getUpperName() << "Loc() const {\n";
998 OS << " return " << getLowerName() << ";\n";
999 OS << " }";
1000 }
Stephen Hines651f13c2014-04-23 16:59:28 -07001001 void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
Richard Smithddc2a532013-10-31 21:23:20 +00001002 OS << "A->get" << getUpperName() << "Loc()";
1003 }
Stephen Hines651f13c2014-04-23 16:59:28 -07001004 void writePCHWrite(raw_ostream &OS) const override {
Richard Smithddc2a532013-10-31 21:23:20 +00001005 OS << " " << WritePCHRecord(
1006 getType(), "SA->get" + std::string(getUpperName()) + "Loc()");
1007 }
1008 };
Peter Collingbourne51d77772011-10-06 13:03:08 +00001009}
1010
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001011static std::unique_ptr<Argument>
1012createArgument(const Record &Arg, StringRef Attr,
1013 const Record *Search = nullptr) {
Peter Collingbourne51d77772011-10-06 13:03:08 +00001014 if (!Search)
1015 Search = &Arg;
1016
Stephen Hines176edba2014-12-01 14:53:08 -08001017 std::unique_ptr<Argument> Ptr;
Peter Collingbourne51d77772011-10-06 13:03:08 +00001018 llvm::StringRef ArgName = Search->getName();
1019
Stephen Hines176edba2014-12-01 14:53:08 -08001020 if (ArgName == "AlignedArgument")
1021 Ptr = llvm::make_unique<AlignedArgument>(Arg, Attr);
1022 else if (ArgName == "EnumArgument")
1023 Ptr = llvm::make_unique<EnumArgument>(Arg, Attr);
1024 else if (ArgName == "ExprArgument")
1025 Ptr = llvm::make_unique<ExprArgument>(Arg, Attr);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001026 else if (ArgName == "FunctionArgument")
Stephen Hines176edba2014-12-01 14:53:08 -08001027 Ptr = llvm::make_unique<SimpleArgument>(Arg, Attr, "FunctionDecl *");
Peter Collingbourne51d77772011-10-06 13:03:08 +00001028 else if (ArgName == "IdentifierArgument")
Stephen Hines176edba2014-12-01 14:53:08 -08001029 Ptr = llvm::make_unique<SimpleArgument>(Arg, Attr, "IdentifierInfo *");
Stephen Hines651f13c2014-04-23 16:59:28 -07001030 else if (ArgName == "DefaultBoolArgument")
Stephen Hines176edba2014-12-01 14:53:08 -08001031 Ptr = llvm::make_unique<DefaultSimpleArgument>(
1032 Arg, Attr, "bool", Arg.getValueAsBit("Default"));
1033 else if (ArgName == "BoolArgument")
1034 Ptr = llvm::make_unique<SimpleArgument>(Arg, Attr, "bool");
Stephen Hines651f13c2014-04-23 16:59:28 -07001035 else if (ArgName == "DefaultIntArgument")
Stephen Hines176edba2014-12-01 14:53:08 -08001036 Ptr = llvm::make_unique<DefaultSimpleArgument>(
1037 Arg, Attr, "int", Arg.getValueAsInt("Default"));
1038 else if (ArgName == "IntArgument")
1039 Ptr = llvm::make_unique<SimpleArgument>(Arg, Attr, "int");
1040 else if (ArgName == "StringArgument")
1041 Ptr = llvm::make_unique<StringArgument>(Arg, Attr);
1042 else if (ArgName == "TypeArgument")
1043 Ptr = llvm::make_unique<TypeArgument>(Arg, Attr);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001044 else if (ArgName == "UnsignedArgument")
Stephen Hines176edba2014-12-01 14:53:08 -08001045 Ptr = llvm::make_unique<SimpleArgument>(Arg, Attr, "unsigned");
Peter Collingbourne51d77772011-10-06 13:03:08 +00001046 else if (ArgName == "VariadicUnsignedArgument")
Stephen Hines176edba2014-12-01 14:53:08 -08001047 Ptr = llvm::make_unique<VariadicArgument>(Arg, Attr, "unsigned");
DeLesley Hutchins66540852013-10-04 21:28:06 +00001048 else if (ArgName == "VariadicEnumArgument")
Stephen Hines176edba2014-12-01 14:53:08 -08001049 Ptr = llvm::make_unique<VariadicEnumArgument>(Arg, Attr);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001050 else if (ArgName == "VariadicExprArgument")
Stephen Hines176edba2014-12-01 14:53:08 -08001051 Ptr = llvm::make_unique<VariadicExprArgument>(Arg, Attr);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001052 else if (ArgName == "VersionArgument")
Stephen Hines176edba2014-12-01 14:53:08 -08001053 Ptr = llvm::make_unique<VersionArgument>(Arg, Attr);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001054
1055 if (!Ptr) {
Stephen Hines651f13c2014-04-23 16:59:28 -07001056 // Search in reverse order so that the most-derived type is handled first.
Peter Collingbourne51d77772011-10-06 13:03:08 +00001057 std::vector<Record*> Bases = Search->getSuperClasses();
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001058 for (const auto *Base : llvm::make_range(Bases.rbegin(), Bases.rend())) {
Stephen Hines176edba2014-12-01 14:53:08 -08001059 if ((Ptr = createArgument(Arg, Attr, Base)))
Peter Collingbourne51d77772011-10-06 13:03:08 +00001060 break;
1061 }
1062 }
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00001063
1064 if (Ptr && Arg.getValueAsBit("Optional"))
1065 Ptr->setOptional(true);
1066
Stephen Hines176edba2014-12-01 14:53:08 -08001067 return Ptr;
Peter Collingbourne51d77772011-10-06 13:03:08 +00001068}
1069
Douglas Gregor1bea8802011-11-19 19:22:57 +00001070static void writeAvailabilityValue(raw_ostream &OS) {
1071 OS << "\" << getPlatform()->getName();\n"
1072 << " if (!getIntroduced().empty()) OS << \", introduced=\" << getIntroduced();\n"
1073 << " if (!getDeprecated().empty()) OS << \", deprecated=\" << getDeprecated();\n"
1074 << " if (!getObsoleted().empty()) OS << \", obsoleted=\" << getObsoleted();\n"
1075 << " if (getUnavailable()) OS << \", unavailable\";\n"
1076 << " OS << \"";
1077}
1078
Stephen Hines651f13c2014-04-23 16:59:28 -07001079static void writeGetSpellingFunction(Record &R, raw_ostream &OS) {
1080 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
1081
1082 OS << "const char *" << R.getName() << "Attr::getSpelling() const {\n";
1083 if (Spellings.empty()) {
1084 OS << " return \"(No spelling)\";\n}\n\n";
1085 return;
1086 }
1087
1088 OS << " switch (SpellingListIndex) {\n"
1089 " default:\n"
1090 " llvm_unreachable(\"Unknown attribute spelling!\");\n"
1091 " return \"(No spelling)\";\n";
1092
1093 for (unsigned I = 0; I < Spellings.size(); ++I)
1094 OS << " case " << I << ":\n"
1095 " return \"" << Spellings[I].name() << "\";\n";
1096 // End of the switch statement.
1097 OS << " }\n";
1098 // End of the getSpelling function.
1099 OS << "}\n\n";
1100}
1101
1102static void
1103writePrettyPrintFunction(Record &R,
1104 const std::vector<std::unique_ptr<Argument>> &Args,
1105 raw_ostream &OS) {
1106 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
Michael Han51d8c522013-01-24 16:46:58 +00001107
1108 OS << "void " << R.getName() << "Attr::printPretty("
1109 << "raw_ostream &OS, const PrintingPolicy &Policy) const {\n";
1110
Stephen Hinesc568f1e2014-07-21 00:47:37 -07001111 if (Spellings.empty()) {
Michael Han51d8c522013-01-24 16:46:58 +00001112 OS << "}\n\n";
1113 return;
1114 }
1115
1116 OS <<
1117 " switch (SpellingListIndex) {\n"
1118 " default:\n"
1119 " llvm_unreachable(\"Unknown attribute spelling!\");\n"
1120 " break;\n";
1121
1122 for (unsigned I = 0; I < Spellings.size(); ++ I) {
1123 llvm::SmallString<16> Prefix;
1124 llvm::SmallString<8> Suffix;
1125 // The actual spelling of the name and namespace (if applicable)
1126 // of an attribute without considering prefix and suffix.
1127 llvm::SmallString<64> Spelling;
Stephen Hines651f13c2014-04-23 16:59:28 -07001128 std::string Name = Spellings[I].name();
1129 std::string Variety = Spellings[I].variety();
Michael Han51d8c522013-01-24 16:46:58 +00001130
1131 if (Variety == "GNU") {
1132 Prefix = " __attribute__((";
1133 Suffix = "))";
1134 } else if (Variety == "CXX11") {
1135 Prefix = " [[";
1136 Suffix = "]]";
Stephen Hines651f13c2014-04-23 16:59:28 -07001137 std::string Namespace = Spellings[I].nameSpace();
Stephen Hinesc568f1e2014-07-21 00:47:37 -07001138 if (!Namespace.empty()) {
Michael Han51d8c522013-01-24 16:46:58 +00001139 Spelling += Namespace;
1140 Spelling += "::";
1141 }
1142 } else if (Variety == "Declspec") {
1143 Prefix = " __declspec(";
1144 Suffix = ")";
Richard Smith5cd532c2013-01-29 01:24:26 +00001145 } else if (Variety == "Keyword") {
1146 Prefix = " ";
1147 Suffix = "";
Stephen Hinesc568f1e2014-07-21 00:47:37 -07001148 } else if (Variety == "Pragma") {
1149 Prefix = "#pragma ";
1150 Suffix = "\n";
1151 std::string Namespace = Spellings[I].nameSpace();
1152 if (!Namespace.empty()) {
1153 Spelling += Namespace;
1154 Spelling += " ";
1155 }
Michael Han51d8c522013-01-24 16:46:58 +00001156 } else {
Richard Smith5cd532c2013-01-29 01:24:26 +00001157 llvm_unreachable("Unknown attribute syntax variety!");
Michael Han51d8c522013-01-24 16:46:58 +00001158 }
1159
1160 Spelling += Name;
1161
1162 OS <<
1163 " case " << I << " : {\n"
Pirama Arumuga Nainar3ea9e332015-04-08 08:57:32 -07001164 " OS << \"" << Prefix << Spelling;
Michael Han51d8c522013-01-24 16:46:58 +00001165
Stephen Hinesc568f1e2014-07-21 00:47:37 -07001166 if (Variety == "Pragma") {
1167 OS << " \";\n";
1168 OS << " printPrettyPragma(OS, Policy);\n";
1169 OS << " break;\n";
1170 OS << " }\n";
1171 continue;
1172 }
1173
Stephen Hines176edba2014-12-01 14:53:08 -08001174 // FIXME: always printing the parenthesis isn't the correct behavior for
1175 // attributes which have optional arguments that were not provided. For
1176 // instance: __attribute__((aligned)) will be pretty printed as
1177 // __attribute__((aligned())). The logic should check whether there is only
1178 // a single argument, and if it is optional, whether it has been provided.
Stephen Hines651f13c2014-04-23 16:59:28 -07001179 if (!Args.empty())
1180 OS << "(";
Michael Han51d8c522013-01-24 16:46:58 +00001181 if (Spelling == "availability") {
1182 writeAvailabilityValue(OS);
1183 } else {
Stephen Hines651f13c2014-04-23 16:59:28 -07001184 for (auto I = Args.begin(), E = Args.end(); I != E; ++ I) {
Michael Han51d8c522013-01-24 16:46:58 +00001185 if (I != Args.begin()) OS << ", ";
1186 (*I)->writeValue(OS);
1187 }
1188 }
1189
Stephen Hines651f13c2014-04-23 16:59:28 -07001190 if (!Args.empty())
1191 OS << ")";
Pirama Arumuga Nainar3ea9e332015-04-08 08:57:32 -07001192 OS << Suffix + "\";\n";
Michael Han51d8c522013-01-24 16:46:58 +00001193
1194 OS <<
1195 " break;\n"
1196 " }\n";
1197 }
1198
1199 // End of the switch statement.
1200 OS << "}\n";
1201 // End of the print function.
1202 OS << "}\n\n";
1203}
1204
Michael Hana31f65b2013-02-01 01:19:17 +00001205/// \brief Return the index of a spelling in a spelling list.
Stephen Hines651f13c2014-04-23 16:59:28 -07001206static unsigned
1207getSpellingListIndex(const std::vector<FlattenedSpelling> &SpellingList,
1208 const FlattenedSpelling &Spelling) {
Stephen Hines0e2c34f2015-03-23 12:09:02 -07001209 assert(!SpellingList.empty() && "Spelling list is empty!");
Michael Hana31f65b2013-02-01 01:19:17 +00001210
1211 for (unsigned Index = 0; Index < SpellingList.size(); ++Index) {
Stephen Hines651f13c2014-04-23 16:59:28 -07001212 const FlattenedSpelling &S = SpellingList[Index];
1213 if (S.variety() != Spelling.variety())
Michael Hana31f65b2013-02-01 01:19:17 +00001214 continue;
Stephen Hines651f13c2014-04-23 16:59:28 -07001215 if (S.nameSpace() != Spelling.nameSpace())
Michael Hana31f65b2013-02-01 01:19:17 +00001216 continue;
Stephen Hines651f13c2014-04-23 16:59:28 -07001217 if (S.name() != Spelling.name())
Michael Hana31f65b2013-02-01 01:19:17 +00001218 continue;
1219
1220 return Index;
1221 }
1222
1223 llvm_unreachable("Unknown spelling!");
1224}
1225
Stephen Hines651f13c2014-04-23 16:59:28 -07001226static void writeAttrAccessorDefinition(const Record &R, raw_ostream &OS) {
Michael Hana31f65b2013-02-01 01:19:17 +00001227 std::vector<Record*> Accessors = R.getValueAsListOfDefs("Accessors");
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001228 for (const auto *Accessor : Accessors) {
Michael Hana31f65b2013-02-01 01:19:17 +00001229 std::string Name = Accessor->getValueAsString("Name");
Stephen Hines651f13c2014-04-23 16:59:28 -07001230 std::vector<FlattenedSpelling> Spellings =
1231 GetFlattenedSpellings(*Accessor);
1232 std::vector<FlattenedSpelling> SpellingList = GetFlattenedSpellings(R);
Stephen Hines0e2c34f2015-03-23 12:09:02 -07001233 assert(!SpellingList.empty() &&
Michael Hana31f65b2013-02-01 01:19:17 +00001234 "Attribute with empty spelling list can't have accessors!");
1235
1236 OS << " bool " << Name << "() const { return SpellingListIndex == ";
1237 for (unsigned Index = 0; Index < Spellings.size(); ++Index) {
Stephen Hines651f13c2014-04-23 16:59:28 -07001238 OS << getSpellingListIndex(SpellingList, Spellings[Index]);
Michael Hana31f65b2013-02-01 01:19:17 +00001239 if (Index != Spellings.size() -1)
1240 OS << " ||\n SpellingListIndex == ";
1241 else
1242 OS << "; }\n";
1243 }
1244 }
1245}
1246
Stephen Hines651f13c2014-04-23 16:59:28 -07001247static bool
1248SpellingNamesAreCommon(const std::vector<FlattenedSpelling>& Spellings) {
1249 assert(!Spellings.empty() && "An empty list of spellings was provided");
1250 std::string FirstName = NormalizeNameForSpellingComparison(
1251 Spellings.front().name());
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001252 for (const auto &Spelling :
1253 llvm::make_range(std::next(Spellings.begin()), Spellings.end())) {
1254 std::string Name = NormalizeNameForSpellingComparison(Spelling.name());
Stephen Hines651f13c2014-04-23 16:59:28 -07001255 if (Name != FirstName)
1256 return false;
1257 }
1258 return true;
1259}
1260
1261typedef std::map<unsigned, std::string> SemanticSpellingMap;
1262static std::string
1263CreateSemanticSpellings(const std::vector<FlattenedSpelling> &Spellings,
1264 SemanticSpellingMap &Map) {
1265 // The enumerants are automatically generated based on the variety,
1266 // namespace (if present) and name for each attribute spelling. However,
1267 // care is taken to avoid trampling on the reserved namespace due to
1268 // underscores.
1269 std::string Ret(" enum Spelling {\n");
1270 std::set<std::string> Uniques;
1271 unsigned Idx = 0;
1272 for (auto I = Spellings.begin(), E = Spellings.end(); I != E; ++I, ++Idx) {
1273 const FlattenedSpelling &S = *I;
1274 std::string Variety = S.variety();
1275 std::string Spelling = S.name();
1276 std::string Namespace = S.nameSpace();
1277 std::string EnumName = "";
1278
1279 EnumName += (Variety + "_");
1280 if (!Namespace.empty())
1281 EnumName += (NormalizeNameForSpellingComparison(Namespace).str() +
1282 "_");
1283 EnumName += NormalizeNameForSpellingComparison(Spelling);
1284
1285 // Even if the name is not unique, this spelling index corresponds to a
1286 // particular enumerant name that we've calculated.
1287 Map[Idx] = EnumName;
1288
1289 // Since we have been stripping underscores to avoid trampling on the
1290 // reserved namespace, we may have inadvertently created duplicate
1291 // enumerant names. These duplicates are not considered part of the
1292 // semantic spelling, and can be elided.
1293 if (Uniques.find(EnumName) != Uniques.end())
1294 continue;
1295
1296 Uniques.insert(EnumName);
1297 if (I != Spellings.begin())
1298 Ret += ",\n";
Pirama Arumuga Nainar3ea9e332015-04-08 08:57:32 -07001299 // Duplicate spellings are not considered part of the semantic spelling
1300 // enumeration, but the spelling index and semantic spelling values are
1301 // meant to be equivalent, so we must specify a concrete value for each
1302 // enumerator.
1303 Ret += " " + EnumName + " = " + llvm::utostr(Idx);
Stephen Hines651f13c2014-04-23 16:59:28 -07001304 }
1305 Ret += "\n };\n\n";
1306 return Ret;
1307}
1308
1309void WriteSemanticSpellingSwitch(const std::string &VarName,
1310 const SemanticSpellingMap &Map,
1311 raw_ostream &OS) {
1312 OS << " switch (" << VarName << ") {\n default: "
1313 << "llvm_unreachable(\"Unknown spelling list index\");\n";
1314 for (const auto &I : Map)
1315 OS << " case " << I.first << ": return " << I.second << ";\n";
1316 OS << " }\n";
1317}
1318
1319// Emits the LateParsed property for attributes.
1320static void emitClangAttrLateParsedList(RecordKeeper &Records, raw_ostream &OS) {
1321 OS << "#if defined(CLANG_ATTR_LATE_PARSED_LIST)\n";
1322 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1323
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001324 for (const auto *Attr : Attrs) {
Stephen Hines651f13c2014-04-23 16:59:28 -07001325 bool LateParsed = Attr->getValueAsBit("LateParsed");
1326
1327 if (LateParsed) {
1328 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr);
1329
1330 // FIXME: Handle non-GNU attributes
1331 for (const auto &I : Spellings) {
1332 if (I.variety() != "GNU")
1333 continue;
1334 OS << ".Case(\"" << I.name() << "\", " << LateParsed << ")\n";
1335 }
1336 }
1337 }
1338 OS << "#endif // CLANG_ATTR_LATE_PARSED_LIST\n\n";
1339}
1340
1341/// \brief Emits the first-argument-is-type property for attributes.
1342static void emitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) {
1343 OS << "#if defined(CLANG_ATTR_TYPE_ARG_LIST)\n";
1344 std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
1345
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001346 for (const auto *Attr : Attrs) {
Stephen Hines651f13c2014-04-23 16:59:28 -07001347 // Determine whether the first argument is a type.
1348 std::vector<Record *> Args = Attr->getValueAsListOfDefs("Args");
1349 if (Args.empty())
1350 continue;
1351
1352 if (Args[0]->getSuperClasses().back()->getName() != "TypeArgument")
1353 continue;
1354
1355 // All these spellings take a single type argument.
1356 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr);
1357 std::set<std::string> Emitted;
1358 for (const auto &S : Spellings) {
1359 if (Emitted.insert(S.name()).second)
1360 OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n";
1361 }
1362 }
1363 OS << "#endif // CLANG_ATTR_TYPE_ARG_LIST\n\n";
1364}
1365
1366/// \brief Emits the parse-arguments-in-unevaluated-context property for
1367/// attributes.
1368static void emitClangAttrArgContextList(RecordKeeper &Records, raw_ostream &OS) {
1369 OS << "#if defined(CLANG_ATTR_ARG_CONTEXT_LIST)\n";
1370 ParsedAttrMap Attrs = getParsedAttrList(Records);
1371 for (const auto &I : Attrs) {
1372 const Record &Attr = *I.second;
1373
1374 if (!Attr.getValueAsBit("ParseArgumentsAsUnevaluated"))
1375 continue;
1376
1377 // All these spellings take are parsed unevaluated.
1378 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
1379 std::set<std::string> Emitted;
1380 for (const auto &S : Spellings) {
1381 if (Emitted.insert(S.name()).second)
1382 OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n";
1383 }
1384 }
1385 OS << "#endif // CLANG_ATTR_ARG_CONTEXT_LIST\n\n";
1386}
1387
1388static bool isIdentifierArgument(Record *Arg) {
1389 return !Arg->getSuperClasses().empty() &&
1390 llvm::StringSwitch<bool>(Arg->getSuperClasses().back()->getName())
1391 .Case("IdentifierArgument", true)
1392 .Case("EnumArgument", true)
Stephen Hines0e2c34f2015-03-23 12:09:02 -07001393 .Case("VariadicEnumArgument", true)
Stephen Hines651f13c2014-04-23 16:59:28 -07001394 .Default(false);
1395}
1396
1397// Emits the first-argument-is-identifier property for attributes.
1398static void emitClangAttrIdentifierArgList(RecordKeeper &Records, raw_ostream &OS) {
1399 OS << "#if defined(CLANG_ATTR_IDENTIFIER_ARG_LIST)\n";
1400 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1401
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001402 for (const auto *Attr : Attrs) {
Stephen Hines651f13c2014-04-23 16:59:28 -07001403 // Determine whether the first argument is an identifier.
1404 std::vector<Record *> Args = Attr->getValueAsListOfDefs("Args");
1405 if (Args.empty() || !isIdentifierArgument(Args[0]))
1406 continue;
1407
1408 // All these spellings take an identifier argument.
1409 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr);
1410 std::set<std::string> Emitted;
1411 for (const auto &S : Spellings) {
1412 if (Emitted.insert(S.name()).second)
1413 OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n";
1414 }
1415 }
1416 OS << "#endif // CLANG_ATTR_IDENTIFIER_ARG_LIST\n\n";
1417}
1418
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001419namespace clang {
1420
1421// Emits the class definitions for attributes.
1422void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00001423 emitSourceFileHeader("Attribute classes' definitions", OS);
1424
Peter Collingbourne51d77772011-10-06 13:03:08 +00001425 OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
1426 OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
1427
1428 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
1429
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001430 for (const auto *Attr : Attrs) {
1431 const Record &R = *Attr;
Stephen Hines651f13c2014-04-23 16:59:28 -07001432
1433 // FIXME: Currently, documentation is generated as-needed due to the fact
1434 // that there is no way to allow a generated project "reach into" the docs
1435 // directory (for instance, it may be an out-of-tree build). However, we want
1436 // to ensure that every attribute has a Documentation field, and produce an
1437 // error if it has been neglected. Otherwise, the on-demand generation which
1438 // happens server-side will fail. This code is ensuring that functionality,
1439 // even though this Emitter doesn't technically need the documentation.
1440 // When attribute documentation can be generated as part of the build
1441 // itself, this code can be removed.
1442 (void)R.getValueAsListOfDefs("Documentation");
Douglas Gregor3e7d31a2012-05-02 15:56:52 +00001443
1444 if (!R.getValueAsBit("ASTNode"))
1445 continue;
1446
Aaron Ballman201bddc2013-07-30 01:44:15 +00001447 const std::vector<Record *> Supers = R.getSuperClasses();
1448 assert(!Supers.empty() && "Forgot to specify a superclass for the attr");
Aaron Ballman201bddc2013-07-30 01:44:15 +00001449 std::string SuperName;
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001450 for (const auto *Super : llvm::make_range(Supers.rbegin(), Supers.rend())) {
1451 const Record &R = *Super;
Aaron Ballmance756522013-07-31 02:20:22 +00001452 if (R.getName() != "TargetSpecificAttr" && SuperName.empty())
Aaron Ballman201bddc2013-07-30 01:44:15 +00001453 SuperName = R.getName();
1454 }
Peter Collingbourne51d77772011-10-06 13:03:08 +00001455
1456 OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n";
1457
1458 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
Stephen Hines651f13c2014-04-23 16:59:28 -07001459 std::vector<std::unique_ptr<Argument>> Args;
Peter Collingbourne51d77772011-10-06 13:03:08 +00001460 Args.reserve(ArgRecords.size());
1461
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001462 for (const auto *ArgRecord : ArgRecords) {
Stephen Hines651f13c2014-04-23 16:59:28 -07001463 Args.emplace_back(createArgument(*ArgRecord, R.getName()));
1464 Args.back()->writeDeclarations(OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001465 OS << "\n\n";
1466 }
1467
Stephen Hines651f13c2014-04-23 16:59:28 -07001468 OS << "\npublic:\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +00001469
Stephen Hines651f13c2014-04-23 16:59:28 -07001470 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
1471
1472 // If there are zero or one spellings, all spelling-related functionality
1473 // can be elided. If all of the spellings share the same name, the spelling
1474 // functionality can also be elided.
1475 bool ElideSpelling = (Spellings.size() <= 1) ||
1476 SpellingNamesAreCommon(Spellings);
1477
1478 // This maps spelling index values to semantic Spelling enumerants.
1479 SemanticSpellingMap SemanticToSyntacticMap;
1480
1481 if (!ElideSpelling)
1482 OS << CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);
1483
1484 OS << " static " << R.getName() << "Attr *CreateImplicit(";
1485 OS << "ASTContext &Ctx";
1486 if (!ElideSpelling)
1487 OS << ", Spelling S";
1488 for (auto const &ai : Args) {
1489 OS << ", ";
1490 ai->writeCtorParameters(OS);
1491 }
1492 OS << ", SourceRange Loc = SourceRange()";
1493 OS << ") {\n";
1494 OS << " " << R.getName() << "Attr *A = new (Ctx) " << R.getName();
1495 OS << "Attr(Loc, Ctx, ";
1496 for (auto const &ai : Args) {
1497 ai->writeImplicitCtorArgs(OS);
1498 OS << ", ";
1499 }
1500 OS << (ElideSpelling ? "0" : "S") << ");\n";
1501 OS << " A->setImplicit(true);\n";
1502 OS << " return A;\n }\n\n";
1503
Peter Collingbourne51d77772011-10-06 13:03:08 +00001504 OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
1505
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00001506 bool HasOpt = false;
Stephen Hines651f13c2014-04-23 16:59:28 -07001507 for (auto const &ai : Args) {
Peter Collingbourne51d77772011-10-06 13:03:08 +00001508 OS << " , ";
Stephen Hines651f13c2014-04-23 16:59:28 -07001509 ai->writeCtorParameters(OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001510 OS << "\n";
Stephen Hines651f13c2014-04-23 16:59:28 -07001511 if (ai->isOptional())
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00001512 HasOpt = true;
Peter Collingbourne51d77772011-10-06 13:03:08 +00001513 }
Michael Han51d8c522013-01-24 16:46:58 +00001514
1515 OS << " , ";
Stephen Hines651f13c2014-04-23 16:59:28 -07001516 OS << "unsigned SI\n";
Michael Han51d8c522013-01-24 16:46:58 +00001517
Peter Collingbourne51d77772011-10-06 13:03:08 +00001518 OS << " )\n";
Pirama Arumuga Nainar3ea9e332015-04-08 08:57:32 -07001519 OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI, "
1520 << R.getValueAsBit("LateParsed") << ", "
1521 << R.getValueAsBit("DuplicatesAllowedWhileMerging") << ")\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +00001522
Stephen Hines651f13c2014-04-23 16:59:28 -07001523 for (auto const &ai : Args) {
Peter Collingbourne51d77772011-10-06 13:03:08 +00001524 OS << " , ";
Stephen Hines651f13c2014-04-23 16:59:28 -07001525 ai->writeCtorInitializers(OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001526 OS << "\n";
1527 }
1528
1529 OS << " {\n";
1530
Stephen Hines651f13c2014-04-23 16:59:28 -07001531 for (auto const &ai : Args) {
1532 ai->writeCtorBody(OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001533 OS << "\n";
1534 }
1535 OS << " }\n\n";
1536
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00001537 // If there are optional arguments, write out a constructor that elides the
1538 // optional arguments as well.
1539 if (HasOpt) {
1540 OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n";
Stephen Hines651f13c2014-04-23 16:59:28 -07001541 for (auto const &ai : Args) {
1542 if (!ai->isOptional()) {
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00001543 OS << " , ";
Stephen Hines651f13c2014-04-23 16:59:28 -07001544 ai->writeCtorParameters(OS);
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00001545 OS << "\n";
1546 }
1547 }
1548
1549 OS << " , ";
Stephen Hines651f13c2014-04-23 16:59:28 -07001550 OS << "unsigned SI\n";
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00001551
1552 OS << " )\n";
Pirama Arumuga Nainar3ea9e332015-04-08 08:57:32 -07001553 OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI, "
1554 << R.getValueAsBit("LateParsed") << ", "
1555 << R.getValueAsBit("DuplicatesAllowedWhileMerging") << ")\n";
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00001556
Stephen Hines651f13c2014-04-23 16:59:28 -07001557 for (auto const &ai : Args) {
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00001558 OS << " , ";
Stephen Hines651f13c2014-04-23 16:59:28 -07001559 ai->writeCtorDefaultInitializers(OS);
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00001560 OS << "\n";
1561 }
1562
1563 OS << " {\n";
1564
Stephen Hines651f13c2014-04-23 16:59:28 -07001565 for (auto const &ai : Args) {
1566 if (!ai->isOptional()) {
1567 ai->writeCtorBody(OS);
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00001568 OS << "\n";
1569 }
1570 }
1571 OS << " }\n\n";
1572 }
1573
Pirama Arumuga Nainar3ea9e332015-04-08 08:57:32 -07001574 OS << " " << R.getName() << "Attr *clone(ASTContext &C) const;\n";
Stephen Hines651f13c2014-04-23 16:59:28 -07001575 OS << " void printPretty(raw_ostream &OS,\n"
Pirama Arumuga Nainar3ea9e332015-04-08 08:57:32 -07001576 << " const PrintingPolicy &Policy) const;\n";
1577 OS << " const char *getSpelling() const;\n";
Stephen Hines651f13c2014-04-23 16:59:28 -07001578
1579 if (!ElideSpelling) {
1580 assert(!SemanticToSyntacticMap.empty() && "Empty semantic mapping list");
1581 OS << " Spelling getSemanticSpelling() const {\n";
1582 WriteSemanticSpellingSwitch("SpellingListIndex", SemanticToSyntacticMap,
1583 OS);
1584 OS << " }\n";
1585 }
Peter Collingbourne51d77772011-10-06 13:03:08 +00001586
Michael Hana31f65b2013-02-01 01:19:17 +00001587 writeAttrAccessorDefinition(R, OS);
1588
Stephen Hines651f13c2014-04-23 16:59:28 -07001589 for (auto const &ai : Args) {
1590 ai->writeAccessors(OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001591 OS << "\n\n";
Aaron Ballmand0686072013-09-11 19:47:58 +00001592
Stephen Hines651f13c2014-04-23 16:59:28 -07001593 if (ai->isEnumArg())
1594 static_cast<const EnumArgument *>(ai.get())->writeConversion(OS);
1595 else if (ai->isVariadicEnumArg())
1596 static_cast<const VariadicEnumArgument *>(ai.get())
1597 ->writeConversion(OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001598 }
1599
Jakob Stoklund Oleseneb666732012-01-13 04:57:47 +00001600 OS << R.getValueAsString("AdditionalMembers");
Peter Collingbourne51d77772011-10-06 13:03:08 +00001601 OS << "\n\n";
1602
1603 OS << " static bool classof(const Attr *A) { return A->getKind() == "
1604 << "attr::" << R.getName() << "; }\n";
DeLesley Hutchins23323e02012-01-20 22:50:54 +00001605
Peter Collingbourne51d77772011-10-06 13:03:08 +00001606 OS << "};\n\n";
1607 }
1608
1609 OS << "#endif\n";
1610}
1611
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001612// Emits the class method definitions for attributes.
1613void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00001614 emitSourceFileHeader("Attribute classes' member function definitions", OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001615
1616 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
Peter Collingbourne51d77772011-10-06 13:03:08 +00001617
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001618 for (auto *Attr : Attrs) {
1619 Record &R = *Attr;
Douglas Gregor3e7d31a2012-05-02 15:56:52 +00001620
1621 if (!R.getValueAsBit("ASTNode"))
1622 continue;
Peter Collingbourne51d77772011-10-06 13:03:08 +00001623
Stephen Hines651f13c2014-04-23 16:59:28 -07001624 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
1625 std::vector<std::unique_ptr<Argument>> Args;
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001626 for (const auto *Arg : ArgRecords)
1627 Args.emplace_back(createArgument(*Arg, R.getName()));
Stephen Hines651f13c2014-04-23 16:59:28 -07001628
1629 for (auto const &ai : Args)
1630 ai->writeAccessorDefinitions(OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001631
1632 OS << R.getName() << "Attr *" << R.getName()
1633 << "Attr::clone(ASTContext &C) const {\n";
Stephen Hinesc568f1e2014-07-21 00:47:37 -07001634 OS << " auto *A = new (C) " << R.getName() << "Attr(getLocation(), C";
Stephen Hines651f13c2014-04-23 16:59:28 -07001635 for (auto const &ai : Args) {
Peter Collingbourne51d77772011-10-06 13:03:08 +00001636 OS << ", ";
Stephen Hines651f13c2014-04-23 16:59:28 -07001637 ai->writeCloneArgs(OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001638 }
Stephen Hinesc568f1e2014-07-21 00:47:37 -07001639 OS << ", getSpellingListIndex());\n";
1640 OS << " A->Inherited = Inherited;\n";
1641 OS << " A->IsPackExpansion = IsPackExpansion;\n";
1642 OS << " A->Implicit = Implicit;\n";
1643 OS << " return A;\n}\n\n";
Douglas Gregor1bea8802011-11-19 19:22:57 +00001644
Michael Han51d8c522013-01-24 16:46:58 +00001645 writePrettyPrintFunction(R, Args, OS);
Stephen Hines651f13c2014-04-23 16:59:28 -07001646 writeGetSpellingFunction(R, OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001647 }
Pirama Arumuga Nainar3ea9e332015-04-08 08:57:32 -07001648
1649 // Instead of relying on virtual dispatch we just create a huge dispatch
1650 // switch. This is both smaller and faster than virtual functions.
1651 auto EmitFunc = [&](const char *Method) {
1652 OS << " switch (getKind()) {\n";
1653 for (const auto *Attr : Attrs) {
1654 const Record &R = *Attr;
1655 if (!R.getValueAsBit("ASTNode"))
1656 continue;
1657
1658 OS << " case attr::" << R.getName() << ":\n";
1659 OS << " return cast<" << R.getName() << "Attr>(this)->" << Method
1660 << ";\n";
1661 }
1662 OS << " case attr::NUM_ATTRS:\n";
1663 OS << " break;\n";
1664 OS << " }\n";
1665 OS << " llvm_unreachable(\"Unexpected attribute kind!\");\n";
1666 OS << "}\n\n";
1667 };
1668
1669 OS << "const char *Attr::getSpelling() const {\n";
1670 EmitFunc("getSpelling()");
1671
1672 OS << "Attr *Attr::clone(ASTContext &C) const {\n";
1673 EmitFunc("clone(C)");
1674
1675 OS << "void Attr::printPretty(raw_ostream &OS, "
1676 "const PrintingPolicy &Policy) const {\n";
1677 EmitFunc("printPretty(OS, Policy)");
Peter Collingbourne51d77772011-10-06 13:03:08 +00001678}
1679
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001680} // end namespace clang
1681
Peter Collingbourne51d77772011-10-06 13:03:08 +00001682static void EmitAttrList(raw_ostream &OS, StringRef Class,
1683 const std::vector<Record*> &AttrList) {
1684 std::vector<Record*>::const_iterator i = AttrList.begin(), e = AttrList.end();
1685
1686 if (i != e) {
1687 // Move the end iterator back to emit the last attribute.
Douglas Gregor3e7d31a2012-05-02 15:56:52 +00001688 for(--e; i != e; ++i) {
1689 if (!(*i)->getValueAsBit("ASTNode"))
1690 continue;
1691
Peter Collingbourne51d77772011-10-06 13:03:08 +00001692 OS << Class << "(" << (*i)->getName() << ")\n";
Douglas Gregor3e7d31a2012-05-02 15:56:52 +00001693 }
Peter Collingbourne51d77772011-10-06 13:03:08 +00001694
1695 OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n";
1696 }
1697}
1698
Stephen Hines176edba2014-12-01 14:53:08 -08001699// Determines if an attribute has a Pragma spelling.
1700static bool AttrHasPragmaSpelling(const Record *R) {
1701 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*R);
1702 return std::find_if(Spellings.begin(), Spellings.end(),
1703 [](const FlattenedSpelling &S) {
1704 return S.variety() == "Pragma";
1705 }) != Spellings.end();
1706}
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001707
Stephen Hines176edba2014-12-01 14:53:08 -08001708namespace clang {
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001709// Emits the enumeration list for attributes.
1710void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00001711 emitSourceFileHeader("List of all attributes that Clang recognizes", OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001712
1713 OS << "#ifndef LAST_ATTR\n";
1714 OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n";
1715 OS << "#endif\n\n";
1716
1717 OS << "#ifndef INHERITABLE_ATTR\n";
1718 OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n";
1719 OS << "#endif\n\n";
1720
1721 OS << "#ifndef LAST_INHERITABLE_ATTR\n";
1722 OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n";
1723 OS << "#endif\n\n";
1724
1725 OS << "#ifndef INHERITABLE_PARAM_ATTR\n";
1726 OS << "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n";
1727 OS << "#endif\n\n";
1728
1729 OS << "#ifndef LAST_INHERITABLE_PARAM_ATTR\n";
1730 OS << "#define LAST_INHERITABLE_PARAM_ATTR(NAME)"
1731 " INHERITABLE_PARAM_ATTR(NAME)\n";
1732 OS << "#endif\n\n";
1733
Stephen Hines176edba2014-12-01 14:53:08 -08001734 OS << "#ifndef PRAGMA_SPELLING_ATTR\n";
1735 OS << "#define PRAGMA_SPELLING_ATTR(NAME)\n";
1736 OS << "#endif\n\n";
1737
1738 OS << "#ifndef LAST_PRAGMA_SPELLING_ATTR\n";
1739 OS << "#define LAST_PRAGMA_SPELLING_ATTR(NAME) PRAGMA_SPELLING_ATTR(NAME)\n";
1740 OS << "#endif\n\n";
1741
Peter Collingbourne51d77772011-10-06 13:03:08 +00001742 Record *InhClass = Records.getClass("InheritableAttr");
1743 Record *InhParamClass = Records.getClass("InheritableParamAttr");
Stephen Hines176edba2014-12-01 14:53:08 -08001744 std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"),
1745 NonInhAttrs, InhAttrs, InhParamAttrs, PragmaAttrs;
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001746 for (auto *Attr : Attrs) {
1747 if (!Attr->getValueAsBit("ASTNode"))
Douglas Gregor3e7d31a2012-05-02 15:56:52 +00001748 continue;
Stephen Hines176edba2014-12-01 14:53:08 -08001749
1750 if (AttrHasPragmaSpelling(Attr))
1751 PragmaAttrs.push_back(Attr);
1752
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001753 if (Attr->isSubClassOf(InhParamClass))
1754 InhParamAttrs.push_back(Attr);
1755 else if (Attr->isSubClassOf(InhClass))
1756 InhAttrs.push_back(Attr);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001757 else
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001758 NonInhAttrs.push_back(Attr);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001759 }
1760
Stephen Hines176edba2014-12-01 14:53:08 -08001761 EmitAttrList(OS, "PRAGMA_SPELLING_ATTR", PragmaAttrs);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001762 EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs);
1763 EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs);
1764 EmitAttrList(OS, "ATTR", NonInhAttrs);
1765
1766 OS << "#undef LAST_ATTR\n";
1767 OS << "#undef INHERITABLE_ATTR\n";
1768 OS << "#undef LAST_INHERITABLE_ATTR\n";
1769 OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n";
Stephen Hines176edba2014-12-01 14:53:08 -08001770 OS << "#undef LAST_PRAGMA_ATTR\n";
1771 OS << "#undef PRAGMA_SPELLING_ATTR\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +00001772 OS << "#undef ATTR\n";
1773}
1774
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001775// Emits the code to read an attribute from a precompiled header.
1776void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00001777 emitSourceFileHeader("Attribute deserialization code", OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001778
1779 Record *InhClass = Records.getClass("InheritableAttr");
1780 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
1781 ArgRecords;
Stephen Hines651f13c2014-04-23 16:59:28 -07001782 std::vector<std::unique_ptr<Argument>> Args;
Peter Collingbourne51d77772011-10-06 13:03:08 +00001783
1784 OS << " switch (Kind) {\n";
1785 OS << " default:\n";
Stephen Hinesc568f1e2014-07-21 00:47:37 -07001786 OS << " llvm_unreachable(\"Unknown attribute!\");\n";
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001787 for (const auto *Attr : Attrs) {
1788 const Record &R = *Attr;
Douglas Gregor3e7d31a2012-05-02 15:56:52 +00001789 if (!R.getValueAsBit("ASTNode"))
1790 continue;
1791
Peter Collingbourne51d77772011-10-06 13:03:08 +00001792 OS << " case attr::" << R.getName() << ": {\n";
1793 if (R.isSubClassOf(InhClass))
1794 OS << " bool isInherited = Record[Idx++];\n";
Stephen Hines651f13c2014-04-23 16:59:28 -07001795 OS << " bool isImplicit = Record[Idx++];\n";
1796 OS << " unsigned Spelling = Record[Idx++];\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +00001797 ArgRecords = R.getValueAsListOfDefs("Args");
1798 Args.clear();
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001799 for (const auto *Arg : ArgRecords) {
1800 Args.emplace_back(createArgument(*Arg, R.getName()));
Stephen Hines651f13c2014-04-23 16:59:28 -07001801 Args.back()->writePCHReadDecls(OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001802 }
1803 OS << " New = new (Context) " << R.getName() << "Attr(Range, Context";
Stephen Hines651f13c2014-04-23 16:59:28 -07001804 for (auto const &ri : Args) {
Peter Collingbourne51d77772011-10-06 13:03:08 +00001805 OS << ", ";
Stephen Hines651f13c2014-04-23 16:59:28 -07001806 ri->writePCHReadArgs(OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001807 }
Stephen Hines651f13c2014-04-23 16:59:28 -07001808 OS << ", Spelling);\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +00001809 if (R.isSubClassOf(InhClass))
1810 OS << " cast<InheritableAttr>(New)->setInherited(isInherited);\n";
Stephen Hines651f13c2014-04-23 16:59:28 -07001811 OS << " New->setImplicit(isImplicit);\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +00001812 OS << " break;\n";
1813 OS << " }\n";
1814 }
1815 OS << " }\n";
1816}
1817
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001818// Emits the code to write an attribute to a precompiled header.
1819void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00001820 emitSourceFileHeader("Attribute serialization code", OS);
1821
Peter Collingbourne51d77772011-10-06 13:03:08 +00001822 Record *InhClass = Records.getClass("InheritableAttr");
1823 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
Peter Collingbourne51d77772011-10-06 13:03:08 +00001824
1825 OS << " switch (A->getKind()) {\n";
1826 OS << " default:\n";
1827 OS << " llvm_unreachable(\"Unknown attribute kind!\");\n";
1828 OS << " break;\n";
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001829 for (const auto *Attr : Attrs) {
1830 const Record &R = *Attr;
Douglas Gregor3e7d31a2012-05-02 15:56:52 +00001831 if (!R.getValueAsBit("ASTNode"))
1832 continue;
Peter Collingbourne51d77772011-10-06 13:03:08 +00001833 OS << " case attr::" << R.getName() << ": {\n";
1834 Args = R.getValueAsListOfDefs("Args");
1835 if (R.isSubClassOf(InhClass) || !Args.empty())
1836 OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
1837 << "Attr>(A);\n";
1838 if (R.isSubClassOf(InhClass))
1839 OS << " Record.push_back(SA->isInherited());\n";
Stephen Hines651f13c2014-04-23 16:59:28 -07001840 OS << " Record.push_back(A->isImplicit());\n";
1841 OS << " Record.push_back(A->getSpellingListIndex());\n";
1842
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001843 for (const auto *Arg : Args)
1844 createArgument(*Arg, R.getName())->writePCHWrite(OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001845 OS << " break;\n";
1846 OS << " }\n";
1847 }
1848 OS << " }\n";
1849}
1850
Stephen Hines651f13c2014-04-23 16:59:28 -07001851static void GenerateHasAttrSpellingStringSwitch(
1852 const std::vector<Record *> &Attrs, raw_ostream &OS,
1853 const std::string &Variety = "", const std::string &Scope = "") {
1854 for (const auto *Attr : Attrs) {
Stephen Hines176edba2014-12-01 14:53:08 -08001855 // C++11-style attributes have specific version information associated with
1856 // them. If the attribute has no scope, the version information must not
1857 // have the default value (1), as that's incorrect. Instead, the unscoped
1858 // attribute version information should be taken from the SD-6 standing
1859 // document, which can be found at:
1860 // https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations
1861 int Version = 1;
1862
1863 if (Variety == "CXX11") {
1864 std::vector<Record *> Spellings = Attr->getValueAsListOfDefs("Spellings");
1865 for (const auto &Spelling : Spellings) {
1866 if (Spelling->getValueAsString("Variety") == "CXX11") {
1867 Version = static_cast<int>(Spelling->getValueAsInt("Version"));
1868 if (Scope.empty() && Version == 1)
1869 PrintError(Spelling->getLoc(), "C++ standard attributes must "
1870 "have valid version information.");
1871 break;
1872 }
1873 }
1874 }
1875
Stephen Hines651f13c2014-04-23 16:59:28 -07001876 // It is assumed that there will be an llvm::Triple object named T within
1877 // scope that can be used to determine whether the attribute exists in
1878 // a given target.
1879 std::string Test;
1880 if (Attr->isSubClassOf("TargetSpecificAttr")) {
1881 const Record *R = Attr->getValueAsDef("Target");
1882 std::vector<std::string> Arches = R->getValueAsListOfStrings("Arches");
1883
1884 Test += "(";
1885 for (auto AI = Arches.begin(), AE = Arches.end(); AI != AE; ++AI) {
1886 std::string Part = *AI;
1887 Test += "T.getArch() == llvm::Triple::" + Part;
1888 if (AI + 1 != AE)
1889 Test += " || ";
1890 }
1891 Test += ")";
1892
1893 std::vector<std::string> OSes;
1894 if (!R->isValueUnset("OSes")) {
1895 Test += " && (";
1896 std::vector<std::string> OSes = R->getValueAsListOfStrings("OSes");
1897 for (auto AI = OSes.begin(), AE = OSes.end(); AI != AE; ++AI) {
1898 std::string Part = *AI;
1899
1900 Test += "T.getOS() == llvm::Triple::" + Part;
1901 if (AI + 1 != AE)
1902 Test += " || ";
1903 }
1904 Test += ")";
1905 }
1906
1907 // If this is the C++11 variety, also add in the LangOpts test.
1908 if (Variety == "CXX11")
1909 Test += " && LangOpts.CPlusPlus11";
1910 } else if (Variety == "CXX11")
1911 // C++11 mode should be checked against LangOpts, which is presumed to be
1912 // present in the caller.
1913 Test = "LangOpts.CPlusPlus11";
Stephen Hines651f13c2014-04-23 16:59:28 -07001914
Stephen Hines176edba2014-12-01 14:53:08 -08001915 std::string TestStr =
1916 !Test.empty() ? Test + " ? " + llvm::itostr(Version) + " : 0" : "1";
Stephen Hines651f13c2014-04-23 16:59:28 -07001917 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr);
1918 for (const auto &S : Spellings)
1919 if (Variety.empty() || (Variety == S.variety() &&
1920 (Scope.empty() || Scope == S.nameSpace())))
Stephen Hines176edba2014-12-01 14:53:08 -08001921 OS << " .Case(\"" << S.name() << "\", " << TestStr << ")\n";
Stephen Hines651f13c2014-04-23 16:59:28 -07001922 }
Stephen Hines176edba2014-12-01 14:53:08 -08001923 OS << " .Default(0);\n";
Stephen Hines651f13c2014-04-23 16:59:28 -07001924}
1925
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00001926// Emits the list of spellings for attributes.
Stephen Hines651f13c2014-04-23 16:59:28 -07001927void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
1928 emitSourceFileHeader("Code to implement the __has_attribute logic", OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001929
Stephen Hines651f13c2014-04-23 16:59:28 -07001930 // Separate all of the attributes out into four group: generic, C++11, GNU,
1931 // and declspecs. Then generate a big switch statement for each of them.
1932 std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
Stephen Hinesc568f1e2014-07-21 00:47:37 -07001933 std::vector<Record *> Declspec, GNU, Pragma;
Stephen Hines651f13c2014-04-23 16:59:28 -07001934 std::map<std::string, std::vector<Record *>> CXX;
Peter Collingbourne51d77772011-10-06 13:03:08 +00001935
Stephen Hines651f13c2014-04-23 16:59:28 -07001936 // Walk over the list of all attributes, and split them out based on the
1937 // spelling variety.
1938 for (auto *R : Attrs) {
1939 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*R);
1940 for (const auto &SI : Spellings) {
1941 std::string Variety = SI.variety();
1942 if (Variety == "GNU")
1943 GNU.push_back(R);
1944 else if (Variety == "Declspec")
1945 Declspec.push_back(R);
Stephen Hinesc568f1e2014-07-21 00:47:37 -07001946 else if (Variety == "CXX11")
Stephen Hines651f13c2014-04-23 16:59:28 -07001947 CXX[SI.nameSpace()].push_back(R);
Stephen Hinesc568f1e2014-07-21 00:47:37 -07001948 else if (Variety == "Pragma")
1949 Pragma.push_back(R);
Peter Collingbourne51d77772011-10-06 13:03:08 +00001950 }
1951 }
1952
Stephen Hines651f13c2014-04-23 16:59:28 -07001953 OS << "switch (Syntax) {\n";
Stephen Hines651f13c2014-04-23 16:59:28 -07001954 OS << "case AttrSyntax::GNU:\n";
Stephen Hines176edba2014-12-01 14:53:08 -08001955 OS << " return llvm::StringSwitch<int>(Name)\n";
Stephen Hines651f13c2014-04-23 16:59:28 -07001956 GenerateHasAttrSpellingStringSwitch(GNU, OS, "GNU");
1957 OS << "case AttrSyntax::Declspec:\n";
Stephen Hines176edba2014-12-01 14:53:08 -08001958 OS << " return llvm::StringSwitch<int>(Name)\n";
Stephen Hines651f13c2014-04-23 16:59:28 -07001959 GenerateHasAttrSpellingStringSwitch(Declspec, OS, "Declspec");
Stephen Hinesc568f1e2014-07-21 00:47:37 -07001960 OS << "case AttrSyntax::Pragma:\n";
Stephen Hines176edba2014-12-01 14:53:08 -08001961 OS << " return llvm::StringSwitch<int>(Name)\n";
Stephen Hinesc568f1e2014-07-21 00:47:37 -07001962 GenerateHasAttrSpellingStringSwitch(Pragma, OS, "Pragma");
Stephen Hines651f13c2014-04-23 16:59:28 -07001963 OS << "case AttrSyntax::CXX: {\n";
1964 // C++11-style attributes are further split out based on the Scope.
1965 for (std::map<std::string, std::vector<Record *>>::iterator I = CXX.begin(),
1966 E = CXX.end();
1967 I != E; ++I) {
1968 if (I != CXX.begin())
1969 OS << " else ";
1970 if (I->first.empty())
1971 OS << "if (!Scope || Scope->getName() == \"\") {\n";
1972 else
1973 OS << "if (Scope->getName() == \"" << I->first << "\") {\n";
Stephen Hines176edba2014-12-01 14:53:08 -08001974 OS << " return llvm::StringSwitch<int>(Name)\n";
Stephen Hines651f13c2014-04-23 16:59:28 -07001975 GenerateHasAttrSpellingStringSwitch(I->second, OS, "CXX11", I->first);
1976 OS << "}";
1977 }
1978 OS << "\n}\n";
1979 OS << "}\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +00001980}
1981
Michael Han51d8c522013-01-24 16:46:58 +00001982void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00001983 emitSourceFileHeader("Code to translate different attribute spellings "
1984 "into internal identifiers", OS);
Michael Han51d8c522013-01-24 16:46:58 +00001985
1986 OS <<
Michael Han51d8c522013-01-24 16:46:58 +00001987 " switch (AttrKind) {\n"
1988 " default:\n"
1989 " llvm_unreachable(\"Unknown attribute kind!\");\n"
1990 " break;\n";
1991
Stephen Hines651f13c2014-04-23 16:59:28 -07001992 ParsedAttrMap Attrs = getParsedAttrList(Records);
1993 for (const auto &I : Attrs) {
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001994 const Record &R = *I.second;
Stephen Hines651f13c2014-04-23 16:59:28 -07001995 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
1996 OS << " case AT_" << I.first << ": {\n";
1997 for (unsigned I = 0; I < Spellings.size(); ++ I) {
Stephen Hinesc568f1e2014-07-21 00:47:37 -07001998 OS << " if (Name == \"" << Spellings[I].name() << "\" && "
1999 << "SyntaxUsed == "
2000 << StringSwitch<unsigned>(Spellings[I].variety())
2001 .Case("GNU", 0)
2002 .Case("CXX11", 1)
2003 .Case("Declspec", 2)
2004 .Case("Keyword", 3)
2005 .Case("Pragma", 4)
2006 .Default(0)
2007 << " && Scope == \"" << Spellings[I].nameSpace() << "\")\n"
2008 << " return " << I << ";\n";
Michael Han51d8c522013-01-24 16:46:58 +00002009 }
Stephen Hines651f13c2014-04-23 16:59:28 -07002010
2011 OS << " break;\n";
2012 OS << " }\n";
Michael Han51d8c522013-01-24 16:46:58 +00002013 }
2014
2015 OS << " }\n";
Stephen Hines651f13c2014-04-23 16:59:28 -07002016 OS << " return 0;\n";
Michael Han51d8c522013-01-24 16:46:58 +00002017}
2018
Stephen Hines651f13c2014-04-23 16:59:28 -07002019// Emits code used by RecursiveASTVisitor to visit attributes
2020void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS) {
2021 emitSourceFileHeader("Used by RecursiveASTVisitor to visit attributes.", OS);
Peter Collingbourne51d77772011-10-06 13:03:08 +00002022
2023 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
2024
Stephen Hines651f13c2014-04-23 16:59:28 -07002025 // Write method declarations for Traverse* methods.
2026 // We emit this here because we only generate methods for attributes that
2027 // are declared as ASTNodes.
2028 OS << "#ifdef ATTR_VISITOR_DECLS_ONLY\n\n";
Stephen Hines6bcf27b2014-05-29 04:14:42 -07002029 for (const auto *Attr : Attrs) {
2030 const Record &R = *Attr;
Stephen Hines651f13c2014-04-23 16:59:28 -07002031 if (!R.getValueAsBit("ASTNode"))
2032 continue;
2033 OS << " bool Traverse"
2034 << R.getName() << "Attr(" << R.getName() << "Attr *A);\n";
2035 OS << " bool Visit"
2036 << R.getName() << "Attr(" << R.getName() << "Attr *A) {\n"
2037 << " return true; \n"
2038 << " };\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +00002039 }
Stephen Hines651f13c2014-04-23 16:59:28 -07002040 OS << "\n#else // ATTR_VISITOR_DECLS_ONLY\n\n";
2041
2042 // Write individual Traverse* methods for each attribute class.
Stephen Hines6bcf27b2014-05-29 04:14:42 -07002043 for (const auto *Attr : Attrs) {
2044 const Record &R = *Attr;
Stephen Hines651f13c2014-04-23 16:59:28 -07002045 if (!R.getValueAsBit("ASTNode"))
2046 continue;
2047
2048 OS << "template <typename Derived>\n"
2049 << "bool VISITORCLASS<Derived>::Traverse"
2050 << R.getName() << "Attr(" << R.getName() << "Attr *A) {\n"
2051 << " if (!getDerived().VisitAttr(A))\n"
2052 << " return false;\n"
2053 << " if (!getDerived().Visit" << R.getName() << "Attr(A))\n"
2054 << " return false;\n";
2055
2056 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
Stephen Hines6bcf27b2014-05-29 04:14:42 -07002057 for (const auto *Arg : ArgRecords)
2058 createArgument(*Arg, R.getName())->writeASTVisitorTraversal(OS);
Stephen Hines651f13c2014-04-23 16:59:28 -07002059
2060 OS << " return true;\n";
2061 OS << "}\n\n";
2062 }
2063
2064 // Write generic Traverse routine
2065 OS << "template <typename Derived>\n"
2066 << "bool VISITORCLASS<Derived>::TraverseAttr(Attr *A) {\n"
2067 << " if (!A)\n"
2068 << " return true;\n"
2069 << "\n"
2070 << " switch (A->getKind()) {\n"
2071 << " default:\n"
2072 << " return true;\n";
2073
Stephen Hines6bcf27b2014-05-29 04:14:42 -07002074 for (const auto *Attr : Attrs) {
2075 const Record &R = *Attr;
Stephen Hines651f13c2014-04-23 16:59:28 -07002076 if (!R.getValueAsBit("ASTNode"))
2077 continue;
2078
2079 OS << " case attr::" << R.getName() << ":\n"
2080 << " return getDerived().Traverse" << R.getName() << "Attr("
2081 << "cast<" << R.getName() << "Attr>(A));\n";
2082 }
2083 OS << " }\n"; // end case
2084 OS << "}\n"; // end function
2085 OS << "#endif // ATTR_VISITOR_DECLS_ONLY\n";
Peter Collingbourne51d77772011-10-06 13:03:08 +00002086}
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00002087
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00002088// Emits code to instantiate dependent attributes on templates.
2089void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00002090 emitSourceFileHeader("Template instantiation code for attributes", OS);
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00002091
2092 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
2093
Benjamin Kramer5bbc3852012-02-06 11:13:08 +00002094 OS << "namespace clang {\n"
2095 << "namespace sema {\n\n"
2096 << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, "
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00002097 << "Sema &S,\n"
2098 << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n"
2099 << " switch (At->getKind()) {\n"
2100 << " default:\n"
2101 << " break;\n";
2102
Stephen Hines6bcf27b2014-05-29 04:14:42 -07002103 for (const auto *Attr : Attrs) {
2104 const Record &R = *Attr;
Douglas Gregor3e7d31a2012-05-02 15:56:52 +00002105 if (!R.getValueAsBit("ASTNode"))
2106 continue;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00002107
2108 OS << " case attr::" << R.getName() << ": {\n";
Rafael Espindola31c195a2012-05-15 14:09:55 +00002109 bool ShouldClone = R.getValueAsBit("Clone");
2110
2111 if (!ShouldClone) {
2112 OS << " return NULL;\n";
2113 OS << " }\n";
2114 continue;
2115 }
2116
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00002117 OS << " const " << R.getName() << "Attr *A = cast<"
2118 << R.getName() << "Attr>(At);\n";
2119 bool TDependent = R.getValueAsBit("TemplateDependent");
2120
2121 if (!TDependent) {
2122 OS << " return A->clone(C);\n";
2123 OS << " }\n";
2124 continue;
2125 }
2126
2127 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
Stephen Hines651f13c2014-04-23 16:59:28 -07002128 std::vector<std::unique_ptr<Argument>> Args;
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00002129 Args.reserve(ArgRecords.size());
2130
Stephen Hines6bcf27b2014-05-29 04:14:42 -07002131 for (const auto *ArgRecord : ArgRecords)
Stephen Hines651f13c2014-04-23 16:59:28 -07002132 Args.emplace_back(createArgument(*ArgRecord, R.getName()));
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00002133
Stephen Hines651f13c2014-04-23 16:59:28 -07002134 for (auto const &ai : Args)
2135 ai->writeTemplateInstantiation(OS);
2136
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00002137 OS << " return new (C) " << R.getName() << "Attr(A->getLocation(), C";
Stephen Hines651f13c2014-04-23 16:59:28 -07002138 for (auto const &ai : Args) {
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00002139 OS << ", ";
Stephen Hines651f13c2014-04-23 16:59:28 -07002140 ai->writeTemplateInstantiationArgs(OS);
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00002141 }
Stephen Hines651f13c2014-04-23 16:59:28 -07002142 OS << ", A->getSpellingListIndex());\n }\n";
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00002143 }
2144 OS << " } // end switch\n"
2145 << " llvm_unreachable(\"Unknown attribute!\");\n"
2146 << " return 0;\n"
Benjamin Kramer5bbc3852012-02-06 11:13:08 +00002147 << "}\n\n"
2148 << "} // end namespace sema\n"
2149 << "} // end namespace clang\n";
DeLesley Hutchins7b9ff0c2012-01-20 22:37:06 +00002150}
2151
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00002152// Emits the list of parsed attributes.
2153void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) {
2154 emitSourceFileHeader("List of all attributes that Clang recognizes", OS);
2155
2156 OS << "#ifndef PARSED_ATTR\n";
2157 OS << "#define PARSED_ATTR(NAME) NAME\n";
2158 OS << "#endif\n\n";
2159
2160 ParsedAttrMap Names = getParsedAttrList(Records);
Stephen Hines651f13c2014-04-23 16:59:28 -07002161 for (const auto &I : Names) {
2162 OS << "PARSED_ATTR(" << I.first << ")\n";
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00002163 }
2164}
2165
Stephen Hines176edba2014-12-01 14:53:08 -08002166static bool isArgVariadic(const Record &R, StringRef AttrName) {
2167 return createArgument(R, AttrName)->isVariadic();
2168}
2169
Stephen Hines651f13c2014-04-23 16:59:28 -07002170static void emitArgInfo(const Record &R, std::stringstream &OS) {
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00002171 // This function will count the number of arguments specified for the
2172 // attribute and emit the number of required arguments followed by the
2173 // number of optional arguments.
2174 std::vector<Record *> Args = R.getValueAsListOfDefs("Args");
2175 unsigned ArgCount = 0, OptCount = 0;
Stephen Hines176edba2014-12-01 14:53:08 -08002176 bool HasVariadic = false;
Stephen Hines6bcf27b2014-05-29 04:14:42 -07002177 for (const auto *Arg : Args) {
Stephen Hines651f13c2014-04-23 16:59:28 -07002178 Arg->getValueAsBit("Optional") ? ++OptCount : ++ArgCount;
Stephen Hines176edba2014-12-01 14:53:08 -08002179 if (!HasVariadic && isArgVariadic(*Arg, R.getName()))
2180 HasVariadic = true;
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00002181 }
Stephen Hines176edba2014-12-01 14:53:08 -08002182
2183 // If there is a variadic argument, we will set the optional argument count
2184 // to its largest value. Since it's currently a 4-bit number, we set it to 15.
2185 OS << ArgCount << ", " << (HasVariadic ? 15 : OptCount);
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00002186}
2187
Stephen Hines651f13c2014-04-23 16:59:28 -07002188static void GenerateDefaultAppertainsTo(raw_ostream &OS) {
2189 OS << "static bool defaultAppertainsTo(Sema &, const AttributeList &,";
2190 OS << "const Decl *) {\n";
2191 OS << " return true;\n";
2192 OS << "}\n\n";
2193}
2194
2195static std::string CalculateDiagnostic(const Record &S) {
2196 // If the SubjectList object has a custom diagnostic associated with it,
2197 // return that directly.
2198 std::string CustomDiag = S.getValueAsString("CustomDiag");
2199 if (!CustomDiag.empty())
2200 return CustomDiag;
2201
2202 // Given the list of subjects, determine what diagnostic best fits.
2203 enum {
2204 Func = 1U << 0,
2205 Var = 1U << 1,
2206 ObjCMethod = 1U << 2,
2207 Param = 1U << 3,
2208 Class = 1U << 4,
2209 GenericRecord = 1U << 5,
2210 Type = 1U << 6,
2211 ObjCIVar = 1U << 7,
2212 ObjCProp = 1U << 8,
2213 ObjCInterface = 1U << 9,
2214 Block = 1U << 10,
2215 Namespace = 1U << 11,
Stephen Hines6bcf27b2014-05-29 04:14:42 -07002216 Field = 1U << 12,
2217 CXXMethod = 1U << 13,
Stephen Hines0e2c34f2015-03-23 12:09:02 -07002218 ObjCProtocol = 1U << 14,
2219 Enum = 1U << 15
Stephen Hines651f13c2014-04-23 16:59:28 -07002220 };
2221 uint32_t SubMask = 0;
2222
2223 std::vector<Record *> Subjects = S.getValueAsListOfDefs("Subjects");
Stephen Hines6bcf27b2014-05-29 04:14:42 -07002224 for (const auto *Subject : Subjects) {
2225 const Record &R = *Subject;
Stephen Hines651f13c2014-04-23 16:59:28 -07002226 std::string Name;
2227
2228 if (R.isSubClassOf("SubsetSubject")) {
2229 PrintError(R.getLoc(), "SubsetSubjects should use a custom diagnostic");
2230 // As a fallback, look through the SubsetSubject to see what its base
2231 // type is, and use that. This needs to be updated if SubsetSubjects
2232 // are allowed within other SubsetSubjects.
2233 Name = R.getValueAsDef("Base")->getName();
2234 } else
2235 Name = R.getName();
2236
2237 uint32_t V = StringSwitch<uint32_t>(Name)
2238 .Case("Function", Func)
2239 .Case("Var", Var)
2240 .Case("ObjCMethod", ObjCMethod)
2241 .Case("ParmVar", Param)
2242 .Case("TypedefName", Type)
2243 .Case("ObjCIvar", ObjCIVar)
2244 .Case("ObjCProperty", ObjCProp)
2245 .Case("Record", GenericRecord)
2246 .Case("ObjCInterface", ObjCInterface)
2247 .Case("ObjCProtocol", ObjCProtocol)
2248 .Case("Block", Block)
2249 .Case("CXXRecord", Class)
2250 .Case("Namespace", Namespace)
Stephen Hines651f13c2014-04-23 16:59:28 -07002251 .Case("Field", Field)
2252 .Case("CXXMethod", CXXMethod)
Stephen Hines0e2c34f2015-03-23 12:09:02 -07002253 .Case("Enum", Enum)
Stephen Hines651f13c2014-04-23 16:59:28 -07002254 .Default(0);
2255 if (!V) {
2256 // Something wasn't in our mapping, so be helpful and let the developer
2257 // know about it.
2258 PrintFatalError(R.getLoc(), "Unknown subject type: " + R.getName());
2259 return "";
2260 }
2261
2262 SubMask |= V;
2263 }
2264
2265 switch (SubMask) {
2266 // For the simple cases where there's only a single entry in the mask, we
2267 // don't have to resort to bit fiddling.
2268 case Func: return "ExpectedFunction";
2269 case Var: return "ExpectedVariable";
2270 case Param: return "ExpectedParameter";
2271 case Class: return "ExpectedClass";
Stephen Hines0e2c34f2015-03-23 12:09:02 -07002272 case Enum: return "ExpectedEnum";
Stephen Hines651f13c2014-04-23 16:59:28 -07002273 case CXXMethod:
2274 // FIXME: Currently, this maps to ExpectedMethod based on existing code,
2275 // but should map to something a bit more accurate at some point.
2276 case ObjCMethod: return "ExpectedMethod";
2277 case Type: return "ExpectedType";
2278 case ObjCInterface: return "ExpectedObjectiveCInterface";
2279 case ObjCProtocol: return "ExpectedObjectiveCProtocol";
2280
2281 // "GenericRecord" means struct, union or class; check the language options
2282 // and if not compiling for C++, strip off the class part. Note that this
2283 // relies on the fact that the context for this declares "Sema &S".
2284 case GenericRecord:
2285 return "(S.getLangOpts().CPlusPlus ? ExpectedStructOrUnionOrClass : "
2286 "ExpectedStructOrUnion)";
2287 case Func | ObjCMethod | Block: return "ExpectedFunctionMethodOrBlock";
2288 case Func | ObjCMethod | Class: return "ExpectedFunctionMethodOrClass";
2289 case Func | Param:
2290 case Func | ObjCMethod | Param: return "ExpectedFunctionMethodOrParameter";
Stephen Hines651f13c2014-04-23 16:59:28 -07002291 case Func | ObjCMethod: return "ExpectedFunctionOrMethod";
2292 case Func | Var: return "ExpectedVariableOrFunction";
2293
2294 // If not compiling for C++, the class portion does not apply.
2295 case Func | Var | Class:
2296 return "(S.getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass : "
2297 "ExpectedVariableOrFunction)";
2298
2299 case ObjCMethod | ObjCProp: return "ExpectedMethodOrProperty";
Stephen Hines176edba2014-12-01 14:53:08 -08002300 case ObjCProtocol | ObjCInterface:
2301 return "ExpectedObjectiveCInterfaceOrProtocol";
Stephen Hines651f13c2014-04-23 16:59:28 -07002302 case Field | Var: return "ExpectedFieldOrGlobalVar";
2303 }
2304
2305 PrintFatalError(S.getLoc(),
2306 "Could not deduce diagnostic argument for Attr subjects");
2307
2308 return "";
2309}
2310
2311static std::string GetSubjectWithSuffix(const Record *R) {
2312 std::string B = R->getName();
2313 if (B == "DeclBase")
2314 return "Decl";
2315 return B + "Decl";
2316}
2317static std::string GenerateCustomAppertainsTo(const Record &Subject,
2318 raw_ostream &OS) {
2319 std::string FnName = "is" + Subject.getName();
2320
2321 // If this code has already been generated, simply return the previous
2322 // instance of it.
2323 static std::set<std::string> CustomSubjectSet;
2324 std::set<std::string>::iterator I = CustomSubjectSet.find(FnName);
2325 if (I != CustomSubjectSet.end())
2326 return *I;
2327
2328 Record *Base = Subject.getValueAsDef("Base");
2329
2330 // Not currently support custom subjects within custom subjects.
2331 if (Base->isSubClassOf("SubsetSubject")) {
2332 PrintFatalError(Subject.getLoc(),
2333 "SubsetSubjects within SubsetSubjects is not supported");
2334 return "";
2335 }
2336
2337 OS << "static bool " << FnName << "(const Decl *D) {\n";
2338 OS << " if (const " << GetSubjectWithSuffix(Base) << " *S = dyn_cast<";
2339 OS << GetSubjectWithSuffix(Base);
2340 OS << ">(D))\n";
2341 OS << " return " << Subject.getValueAsString("CheckCode") << ";\n";
2342 OS << " return false;\n";
2343 OS << "}\n\n";
2344
2345 CustomSubjectSet.insert(FnName);
2346 return FnName;
2347}
2348
2349static std::string GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) {
2350 // If the attribute does not contain a Subjects definition, then use the
2351 // default appertainsTo logic.
2352 if (Attr.isValueUnset("Subjects"))
2353 return "defaultAppertainsTo";
2354
2355 const Record *SubjectObj = Attr.getValueAsDef("Subjects");
2356 std::vector<Record*> Subjects = SubjectObj->getValueAsListOfDefs("Subjects");
2357
2358 // If the list of subjects is empty, it is assumed that the attribute
2359 // appertains to everything.
2360 if (Subjects.empty())
2361 return "defaultAppertainsTo";
2362
2363 bool Warn = SubjectObj->getValueAsDef("Diag")->getValueAsBit("Warn");
2364
2365 // Otherwise, generate an appertainsTo check specific to this attribute which
2366 // checks all of the given subjects against the Decl passed in. Return the
2367 // name of that check to the caller.
2368 std::string FnName = "check" + Attr.getName() + "AppertainsTo";
2369 std::stringstream SS;
2370 SS << "static bool " << FnName << "(Sema &S, const AttributeList &Attr, ";
2371 SS << "const Decl *D) {\n";
2372 SS << " if (";
2373 for (auto I = Subjects.begin(), E = Subjects.end(); I != E; ++I) {
2374 // If the subject has custom code associated with it, generate a function
2375 // for it. The function cannot be inlined into this check (yet) because it
2376 // requires the subject to be of a specific type, and were that information
2377 // inlined here, it would not support an attribute with multiple custom
2378 // subjects.
2379 if ((*I)->isSubClassOf("SubsetSubject")) {
2380 SS << "!" << GenerateCustomAppertainsTo(**I, OS) << "(D)";
2381 } else {
2382 SS << "!isa<" << GetSubjectWithSuffix(*I) << ">(D)";
2383 }
2384
2385 if (I + 1 != E)
2386 SS << " && ";
2387 }
2388 SS << ") {\n";
2389 SS << " S.Diag(Attr.getLoc(), diag::";
2390 SS << (Warn ? "warn_attribute_wrong_decl_type" :
2391 "err_attribute_wrong_decl_type");
2392 SS << ")\n";
2393 SS << " << Attr.getName() << ";
2394 SS << CalculateDiagnostic(*SubjectObj) << ";\n";
2395 SS << " return false;\n";
2396 SS << " }\n";
2397 SS << " return true;\n";
2398 SS << "}\n\n";
2399
2400 OS << SS.str();
2401 return FnName;
2402}
2403
2404static void GenerateDefaultLangOptRequirements(raw_ostream &OS) {
2405 OS << "static bool defaultDiagnoseLangOpts(Sema &, ";
2406 OS << "const AttributeList &) {\n";
2407 OS << " return true;\n";
2408 OS << "}\n\n";
2409}
2410
2411static std::string GenerateLangOptRequirements(const Record &R,
2412 raw_ostream &OS) {
2413 // If the attribute has an empty or unset list of language requirements,
2414 // return the default handler.
2415 std::vector<Record *> LangOpts = R.getValueAsListOfDefs("LangOpts");
2416 if (LangOpts.empty())
2417 return "defaultDiagnoseLangOpts";
2418
2419 // Generate the test condition, as well as a unique function name for the
2420 // diagnostic test. The list of options should usually be short (one or two
2421 // options), and the uniqueness isn't strictly necessary (it is just for
2422 // codegen efficiency).
2423 std::string FnName = "check", Test;
2424 for (auto I = LangOpts.begin(), E = LangOpts.end(); I != E; ++I) {
2425 std::string Part = (*I)->getValueAsString("Name");
Stephen Hines0e2c34f2015-03-23 12:09:02 -07002426 if ((*I)->getValueAsBit("Negated"))
2427 Test += "!";
Stephen Hines651f13c2014-04-23 16:59:28 -07002428 Test += "S.LangOpts." + Part;
2429 if (I + 1 != E)
2430 Test += " || ";
2431 FnName += Part;
2432 }
2433 FnName += "LangOpts";
2434
2435 // If this code has already been generated, simply return the previous
2436 // instance of it.
2437 static std::set<std::string> CustomLangOptsSet;
2438 std::set<std::string>::iterator I = CustomLangOptsSet.find(FnName);
2439 if (I != CustomLangOptsSet.end())
2440 return *I;
2441
2442 OS << "static bool " << FnName << "(Sema &S, const AttributeList &Attr) {\n";
2443 OS << " if (" << Test << ")\n";
2444 OS << " return true;\n\n";
2445 OS << " S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) ";
2446 OS << "<< Attr.getName();\n";
2447 OS << " return false;\n";
2448 OS << "}\n\n";
2449
2450 CustomLangOptsSet.insert(FnName);
2451 return FnName;
2452}
2453
2454static void GenerateDefaultTargetRequirements(raw_ostream &OS) {
2455 OS << "static bool defaultTargetRequirements(const llvm::Triple &) {\n";
2456 OS << " return true;\n";
2457 OS << "}\n\n";
2458}
2459
2460static std::string GenerateTargetRequirements(const Record &Attr,
2461 const ParsedAttrMap &Dupes,
2462 raw_ostream &OS) {
2463 // If the attribute is not a target specific attribute, return the default
2464 // target handler.
2465 if (!Attr.isSubClassOf("TargetSpecificAttr"))
2466 return "defaultTargetRequirements";
2467
2468 // Get the list of architectures to be tested for.
2469 const Record *R = Attr.getValueAsDef("Target");
2470 std::vector<std::string> Arches = R->getValueAsListOfStrings("Arches");
2471 if (Arches.empty()) {
2472 PrintError(Attr.getLoc(), "Empty list of target architectures for a "
2473 "target-specific attr");
2474 return "defaultTargetRequirements";
2475 }
2476
2477 // If there are other attributes which share the same parsed attribute kind,
2478 // such as target-specific attributes with a shared spelling, collapse the
2479 // duplicate architectures. This is required because a shared target-specific
2480 // attribute has only one AttributeList::Kind enumeration value, but it
2481 // applies to multiple target architectures. In order for the attribute to be
2482 // considered valid, all of its architectures need to be included.
2483 if (!Attr.isValueUnset("ParseKind")) {
2484 std::string APK = Attr.getValueAsString("ParseKind");
2485 for (const auto &I : Dupes) {
2486 if (I.first == APK) {
2487 std::vector<std::string> DA = I.second->getValueAsDef("Target")
2488 ->getValueAsListOfStrings("Arches");
2489 std::copy(DA.begin(), DA.end(), std::back_inserter(Arches));
2490 }
2491 }
2492 }
2493
2494 std::string FnName = "isTarget", Test = "(";
2495 for (auto I = Arches.begin(), E = Arches.end(); I != E; ++I) {
2496 std::string Part = *I;
2497 Test += "Arch == llvm::Triple::" + Part;
2498 if (I + 1 != E)
2499 Test += " || ";
2500 FnName += Part;
2501 }
2502 Test += ")";
2503
2504 // If the target also requires OS testing, generate those tests as well.
2505 bool UsesOS = false;
2506 if (!R->isValueUnset("OSes")) {
2507 UsesOS = true;
2508
2509 // We know that there was at least one arch test, so we need to and in the
2510 // OS tests.
2511 Test += " && (";
2512 std::vector<std::string> OSes = R->getValueAsListOfStrings("OSes");
2513 for (auto I = OSes.begin(), E = OSes.end(); I != E; ++I) {
2514 std::string Part = *I;
2515
2516 Test += "OS == llvm::Triple::" + Part;
2517 if (I + 1 != E)
2518 Test += " || ";
2519 FnName += Part;
2520 }
2521 Test += ")";
2522 }
2523
2524 // If this code has already been generated, simply return the previous
2525 // instance of it.
2526 static std::set<std::string> CustomTargetSet;
2527 std::set<std::string>::iterator I = CustomTargetSet.find(FnName);
2528 if (I != CustomTargetSet.end())
2529 return *I;
2530
2531 OS << "static bool " << FnName << "(const llvm::Triple &T) {\n";
2532 OS << " llvm::Triple::ArchType Arch = T.getArch();\n";
2533 if (UsesOS)
2534 OS << " llvm::Triple::OSType OS = T.getOS();\n";
2535 OS << " return " << Test << ";\n";
2536 OS << "}\n\n";
2537
2538 CustomTargetSet.insert(FnName);
2539 return FnName;
2540}
2541
2542static void GenerateDefaultSpellingIndexToSemanticSpelling(raw_ostream &OS) {
2543 OS << "static unsigned defaultSpellingIndexToSemanticSpelling("
2544 << "const AttributeList &Attr) {\n";
2545 OS << " return UINT_MAX;\n";
2546 OS << "}\n\n";
2547}
2548
2549static std::string GenerateSpellingIndexToSemanticSpelling(const Record &Attr,
2550 raw_ostream &OS) {
2551 // If the attribute does not have a semantic form, we can bail out early.
2552 if (!Attr.getValueAsBit("ASTNode"))
2553 return "defaultSpellingIndexToSemanticSpelling";
2554
2555 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
2556
2557 // If there are zero or one spellings, or all of the spellings share the same
2558 // name, we can also bail out early.
2559 if (Spellings.size() <= 1 || SpellingNamesAreCommon(Spellings))
2560 return "defaultSpellingIndexToSemanticSpelling";
2561
2562 // Generate the enumeration we will use for the mapping.
2563 SemanticSpellingMap SemanticToSyntacticMap;
2564 std::string Enum = CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);
2565 std::string Name = Attr.getName() + "AttrSpellingMap";
2566
2567 OS << "static unsigned " << Name << "(const AttributeList &Attr) {\n";
2568 OS << Enum;
2569 OS << " unsigned Idx = Attr.getAttributeSpellingListIndex();\n";
2570 WriteSemanticSpellingSwitch("Idx", SemanticToSyntacticMap, OS);
2571 OS << "}\n\n";
2572
2573 return Name;
2574}
2575
2576static bool IsKnownToGCC(const Record &Attr) {
2577 // Look at the spellings for this subject; if there are any spellings which
2578 // claim to be known to GCC, the attribute is known to GCC.
2579 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
2580 for (const auto &I : Spellings) {
2581 if (I.knownToGCC())
2582 return true;
2583 }
2584 return false;
2585}
2586
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00002587/// Emits the parsed attribute helpers
2588void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
2589 emitSourceFileHeader("Parsed attribute helpers", OS);
2590
Stephen Hines651f13c2014-04-23 16:59:28 -07002591 // Get the list of parsed attributes, and accept the optional list of
2592 // duplicates due to the ParseKind.
2593 ParsedAttrMap Dupes;
2594 ParsedAttrMap Attrs = getParsedAttrList(Records, &Dupes);
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00002595
Stephen Hines651f13c2014-04-23 16:59:28 -07002596 // Generate the default appertainsTo, target and language option diagnostic,
2597 // and spelling list index mapping methods.
2598 GenerateDefaultAppertainsTo(OS);
2599 GenerateDefaultLangOptRequirements(OS);
2600 GenerateDefaultTargetRequirements(OS);
2601 GenerateDefaultSpellingIndexToSemanticSpelling(OS);
2602
2603 // Generate the appertainsTo diagnostic methods and write their names into
2604 // another mapping. At the same time, generate the AttrInfoMap object
2605 // contents. Due to the reliance on generated code, use separate streams so
2606 // that code will not be interleaved.
2607 std::stringstream SS;
2608 for (auto I = Attrs.begin(), E = Attrs.end(); I != E; ++I) {
2609 // TODO: If the attribute's kind appears in the list of duplicates, that is
2610 // because it is a target-specific attribute that appears multiple times.
2611 // It would be beneficial to test whether the duplicates are "similar
2612 // enough" to each other to not cause problems. For instance, check that
2613 // the spellings are identical, and custom parsing rules match, etc.
2614
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00002615 // We need to generate struct instances based off ParsedAttrInfo from
2616 // AttributeList.cpp.
Stephen Hines651f13c2014-04-23 16:59:28 -07002617 SS << " { ";
2618 emitArgInfo(*I->second, SS);
2619 SS << ", " << I->second->getValueAsBit("HasCustomParsing");
2620 SS << ", " << I->second->isSubClassOf("TargetSpecificAttr");
2621 SS << ", " << I->second->isSubClassOf("TypeAttr");
2622 SS << ", " << IsKnownToGCC(*I->second);
2623 SS << ", " << GenerateAppertainsTo(*I->second, OS);
2624 SS << ", " << GenerateLangOptRequirements(*I->second, OS);
2625 SS << ", " << GenerateTargetRequirements(*I->second, Dupes, OS);
2626 SS << ", " << GenerateSpellingIndexToSemanticSpelling(*I->second, OS);
2627 SS << " }";
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00002628
2629 if (I + 1 != E)
Stephen Hines651f13c2014-04-23 16:59:28 -07002630 SS << ",";
2631
2632 SS << " // AT_" << I->first << "\n";
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00002633 }
Stephen Hines651f13c2014-04-23 16:59:28 -07002634
2635 OS << "static const ParsedAttrInfo AttrInfoMap[AttributeList::UnknownAttribute + 1] = {\n";
2636 OS << SS.str();
Aaron Ballmanbbb3b322013-09-09 23:33:17 +00002637 OS << "};\n\n";
Michael Hane53ac8a2012-03-07 00:12:16 +00002638}
2639
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00002640// Emits the kind list of parsed attributes
2641void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00002642 emitSourceFileHeader("Attribute name matcher", OS);
2643
Stephen Hines651f13c2014-04-23 16:59:28 -07002644 std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
Stephen Hinesc568f1e2014-07-21 00:47:37 -07002645 std::vector<StringMatcher::StringPair> GNU, Declspec, CXX11, Keywords, Pragma;
Stephen Hines651f13c2014-04-23 16:59:28 -07002646 std::set<std::string> Seen;
Stephen Hines6bcf27b2014-05-29 04:14:42 -07002647 for (const auto *A : Attrs) {
2648 const Record &Attr = *A;
Michael Hane53ac8a2012-03-07 00:12:16 +00002649
Michael Hane53ac8a2012-03-07 00:12:16 +00002650 bool SemaHandler = Attr.getValueAsBit("SemaHandler");
Douglas Gregor331d2ec2012-05-02 16:18:45 +00002651 bool Ignored = Attr.getValueAsBit("Ignored");
Douglas Gregor331d2ec2012-05-02 16:18:45 +00002652 if (SemaHandler || Ignored) {
Stephen Hines651f13c2014-04-23 16:59:28 -07002653 // Attribute spellings can be shared between target-specific attributes,
2654 // and can be shared between syntaxes for the same attribute. For
2655 // instance, an attribute can be spelled GNU<"interrupt"> for an ARM-
2656 // specific attribute, or MSP430-specific attribute. Additionally, an
2657 // attribute can be spelled GNU<"dllexport"> and Declspec<"dllexport">
2658 // for the same semantic attribute. Ultimately, we need to map each of
2659 // these to a single AttributeList::Kind value, but the StringMatcher
2660 // class cannot handle duplicate match strings. So we generate a list of
2661 // string to match based on the syntax, and emit multiple string matchers
2662 // depending on the syntax used.
2663 std::string AttrName;
2664 if (Attr.isSubClassOf("TargetSpecificAttr") &&
2665 !Attr.isValueUnset("ParseKind")) {
2666 AttrName = Attr.getValueAsString("ParseKind");
2667 if (Seen.find(AttrName) != Seen.end())
2668 continue;
2669 Seen.insert(AttrName);
2670 } else
2671 AttrName = NormalizeAttrName(StringRef(Attr.getName())).str();
Michael Hane53ac8a2012-03-07 00:12:16 +00002672
Stephen Hines651f13c2014-04-23 16:59:28 -07002673 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
2674 for (const auto &S : Spellings) {
2675 std::string RawSpelling = S.name();
Stephen Hines6bcf27b2014-05-29 04:14:42 -07002676 std::vector<StringMatcher::StringPair> *Matches = nullptr;
Stephen Hines651f13c2014-04-23 16:59:28 -07002677 std::string Spelling, Variety = S.variety();
2678 if (Variety == "CXX11") {
2679 Matches = &CXX11;
2680 Spelling += S.nameSpace();
Sean Hunt8e083e72012-06-19 23:57:03 +00002681 Spelling += "::";
Stephen Hines651f13c2014-04-23 16:59:28 -07002682 } else if (Variety == "GNU")
2683 Matches = &GNU;
2684 else if (Variety == "Declspec")
2685 Matches = &Declspec;
2686 else if (Variety == "Keyword")
2687 Matches = &Keywords;
Stephen Hinesc568f1e2014-07-21 00:47:37 -07002688 else if (Variety == "Pragma")
2689 Matches = &Pragma;
Sean Hunt93f95f22012-06-18 16:13:52 +00002690
Stephen Hines651f13c2014-04-23 16:59:28 -07002691 assert(Matches && "Unsupported spelling variety found");
2692
2693 Spelling += NormalizeAttrSpelling(RawSpelling);
Douglas Gregor331d2ec2012-05-02 16:18:45 +00002694 if (SemaHandler)
Stephen Hines651f13c2014-04-23 16:59:28 -07002695 Matches->push_back(StringMatcher::StringPair(Spelling,
2696 "return AttributeList::AT_" + AttrName + ";"));
Douglas Gregor331d2ec2012-05-02 16:18:45 +00002697 else
Stephen Hines651f13c2014-04-23 16:59:28 -07002698 Matches->push_back(StringMatcher::StringPair(Spelling,
2699 "return AttributeList::IgnoredAttribute;"));
Michael Hane53ac8a2012-03-07 00:12:16 +00002700 }
2701 }
2702 }
Douglas Gregor0c19b3c2012-05-02 17:33:51 +00002703
Stephen Hines651f13c2014-04-23 16:59:28 -07002704 OS << "static AttributeList::Kind getAttrKind(StringRef Name, ";
2705 OS << "AttributeList::Syntax Syntax) {\n";
2706 OS << " if (AttributeList::AS_GNU == Syntax) {\n";
2707 StringMatcher("Name", GNU, OS).Emit();
2708 OS << " } else if (AttributeList::AS_Declspec == Syntax) {\n";
2709 StringMatcher("Name", Declspec, OS).Emit();
2710 OS << " } else if (AttributeList::AS_CXX11 == Syntax) {\n";
2711 StringMatcher("Name", CXX11, OS).Emit();
2712 OS << " } else if (AttributeList::AS_Keyword == Syntax) {\n";
2713 StringMatcher("Name", Keywords, OS).Emit();
Stephen Hinesc568f1e2014-07-21 00:47:37 -07002714 OS << " } else if (AttributeList::AS_Pragma == Syntax) {\n";
2715 StringMatcher("Name", Pragma, OS).Emit();
Stephen Hines651f13c2014-04-23 16:59:28 -07002716 OS << " }\n";
2717 OS << " return AttributeList::UnknownAttribute;\n"
Douglas Gregor0c19b3c2012-05-02 17:33:51 +00002718 << "}\n";
Michael Hane53ac8a2012-03-07 00:12:16 +00002719}
2720
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +00002721// Emits the code to dump an attribute.
2722void EmitClangAttrDump(RecordKeeper &Records, raw_ostream &OS) {
Dmitri Gribenko8f1fa252013-01-30 21:54:20 +00002723 emitSourceFileHeader("Attribute dumper", OS);
2724
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +00002725 OS <<
2726 " switch (A->getKind()) {\n"
2727 " default:\n"
2728 " llvm_unreachable(\"Unknown attribute kind!\");\n"
2729 " break;\n";
2730 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
Stephen Hines6bcf27b2014-05-29 04:14:42 -07002731 for (const auto *Attr : Attrs) {
2732 const Record &R = *Attr;
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +00002733 if (!R.getValueAsBit("ASTNode"))
2734 continue;
2735 OS << " case attr::" << R.getName() << ": {\n";
Stephen Hines651f13c2014-04-23 16:59:28 -07002736
2737 // If the attribute has a semantically-meaningful name (which is determined
2738 // by whether there is a Spelling enumeration for it), then write out the
2739 // spelling used for the attribute.
2740 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
2741 if (Spellings.size() > 1 && !SpellingNamesAreCommon(Spellings))
2742 OS << " OS << \" \" << A->getSpelling();\n";
2743
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +00002744 Args = R.getValueAsListOfDefs("Args");
2745 if (!Args.empty()) {
2746 OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName()
2747 << "Attr>(A);\n";
Stephen Hines6bcf27b2014-05-29 04:14:42 -07002748 for (const auto *Arg : Args)
2749 createArgument(*Arg, R.getName())->writeDump(OS);
Richard Trieue8d41192013-01-31 01:44:26 +00002750
Stephen Hines176edba2014-12-01 14:53:08 -08002751 for (auto AI = Args.begin(), AE = Args.end(); AI != AE; ++AI)
Stephen Hines651f13c2014-04-23 16:59:28 -07002752 createArgument(**AI, R.getName())->writeDumpChildren(OS);
Alexander Kornienkoc3cd2b02013-01-07 17:53:08 +00002753 }
2754 OS <<
2755 " break;\n"
2756 " }\n";
2757 }
2758 OS << " }\n";
2759}
2760
Stephen Hines651f13c2014-04-23 16:59:28 -07002761void EmitClangAttrParserStringSwitches(RecordKeeper &Records,
2762 raw_ostream &OS) {
2763 emitSourceFileHeader("Parser-related llvm::StringSwitch cases", OS);
2764 emitClangAttrArgContextList(Records, OS);
2765 emitClangAttrIdentifierArgList(Records, OS);
2766 emitClangAttrTypeArgList(Records, OS);
2767 emitClangAttrLateParsedList(Records, OS);
2768}
2769
2770class DocumentationData {
2771public:
2772 const Record *Documentation;
2773 const Record *Attribute;
2774
2775 DocumentationData(const Record &Documentation, const Record &Attribute)
2776 : Documentation(&Documentation), Attribute(&Attribute) {}
2777};
2778
2779static void WriteCategoryHeader(const Record *DocCategory,
2780 raw_ostream &OS) {
2781 const std::string &Name = DocCategory->getValueAsString("Name");
2782 OS << Name << "\n" << std::string(Name.length(), '=') << "\n";
2783
2784 // If there is content, print that as well.
2785 std::string ContentStr = DocCategory->getValueAsString("Content");
Pirama Arumuga Nainar33337ca2015-05-06 11:48:57 -07002786 // Trim leading and trailing newlines and spaces.
2787 OS << StringRef(ContentStr).trim();
2788
Stephen Hines651f13c2014-04-23 16:59:28 -07002789 OS << "\n\n";
2790}
2791
2792enum SpellingKind {
2793 GNU = 1 << 0,
2794 CXX11 = 1 << 1,
2795 Declspec = 1 << 2,
Stephen Hinesc568f1e2014-07-21 00:47:37 -07002796 Keyword = 1 << 3,
2797 Pragma = 1 << 4
Stephen Hines651f13c2014-04-23 16:59:28 -07002798};
2799
2800static void WriteDocumentation(const DocumentationData &Doc,
2801 raw_ostream &OS) {
2802 // FIXME: there is no way to have a per-spelling category for the attribute
2803 // documentation. This may not be a limiting factor since the spellings
2804 // should generally be consistently applied across the category.
2805
2806 std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Doc.Attribute);
2807
2808 // Determine the heading to be used for this attribute.
2809 std::string Heading = Doc.Documentation->getValueAsString("Heading");
2810 bool CustomHeading = !Heading.empty();
2811 if (Heading.empty()) {
2812 // If there's only one spelling, we can simply use that.
2813 if (Spellings.size() == 1)
2814 Heading = Spellings.begin()->name();
2815 else {
2816 std::set<std::string> Uniques;
2817 for (auto I = Spellings.begin(), E = Spellings.end();
2818 I != E && Uniques.size() <= 1; ++I) {
2819 std::string Spelling = NormalizeNameForSpellingComparison(I->name());
2820 Uniques.insert(Spelling);
2821 }
2822 // If the semantic map has only one spelling, that is sufficient for our
2823 // needs.
2824 if (Uniques.size() == 1)
2825 Heading = *Uniques.begin();
2826 }
2827 }
2828
2829 // If the heading is still empty, it is an error.
2830 if (Heading.empty())
2831 PrintFatalError(Doc.Attribute->getLoc(),
2832 "This attribute requires a heading to be specified");
2833
2834 // Gather a list of unique spellings; this is not the same as the semantic
2835 // spelling for the attribute. Variations in underscores and other non-
2836 // semantic characters are still acceptable.
2837 std::vector<std::string> Names;
2838
2839 unsigned SupportedSpellings = 0;
2840 for (const auto &I : Spellings) {
2841 SpellingKind Kind = StringSwitch<SpellingKind>(I.variety())
Stephen Hinesc568f1e2014-07-21 00:47:37 -07002842 .Case("GNU", GNU)
2843 .Case("CXX11", CXX11)
2844 .Case("Declspec", Declspec)
2845 .Case("Keyword", Keyword)
2846 .Case("Pragma", Pragma);
Stephen Hines651f13c2014-04-23 16:59:28 -07002847
2848 // Mask in the supported spelling.
2849 SupportedSpellings |= Kind;
2850
2851 std::string Name;
2852 if (Kind == CXX11 && !I.nameSpace().empty())
2853 Name = I.nameSpace() + "::";
2854 Name += I.name();
2855
2856 // If this name is the same as the heading, do not add it.
2857 if (Name != Heading)
2858 Names.push_back(Name);
2859 }
2860
2861 // Print out the heading for the attribute. If there are alternate spellings,
2862 // then display those after the heading.
2863 if (!CustomHeading && !Names.empty()) {
2864 Heading += " (";
2865 for (auto I = Names.begin(), E = Names.end(); I != E; ++I) {
2866 if (I != Names.begin())
2867 Heading += ", ";
2868 Heading += *I;
2869 }
2870 Heading += ")";
2871 }
2872 OS << Heading << "\n" << std::string(Heading.length(), '-') << "\n";
2873
2874 if (!SupportedSpellings)
2875 PrintFatalError(Doc.Attribute->getLoc(),
2876 "Attribute has no supported spellings; cannot be "
2877 "documented");
2878
2879 // List what spelling syntaxes the attribute supports.
2880 OS << ".. csv-table:: Supported Syntaxes\n";
Stephen Hinesc568f1e2014-07-21 00:47:37 -07002881 OS << " :header: \"GNU\", \"C++11\", \"__declspec\", \"Keyword\",";
2882 OS << " \"Pragma\"\n\n";
Stephen Hines651f13c2014-04-23 16:59:28 -07002883 OS << " \"";
2884 if (SupportedSpellings & GNU) OS << "X";
2885 OS << "\",\"";
2886 if (SupportedSpellings & CXX11) OS << "X";
2887 OS << "\",\"";
2888 if (SupportedSpellings & Declspec) OS << "X";
2889 OS << "\",\"";
2890 if (SupportedSpellings & Keyword) OS << "X";
Stephen Hinesc568f1e2014-07-21 00:47:37 -07002891 OS << "\", \"";
2892 if (SupportedSpellings & Pragma) OS << "X";
Stephen Hines651f13c2014-04-23 16:59:28 -07002893 OS << "\"\n\n";
2894
2895 // If the attribute is deprecated, print a message about it, and possibly
2896 // provide a replacement attribute.
2897 if (!Doc.Documentation->isValueUnset("Deprecated")) {
2898 OS << "This attribute has been deprecated, and may be removed in a future "
2899 << "version of Clang.";
2900 const Record &Deprecated = *Doc.Documentation->getValueAsDef("Deprecated");
2901 std::string Replacement = Deprecated.getValueAsString("Replacement");
2902 if (!Replacement.empty())
2903 OS << " This attribute has been superseded by ``"
2904 << Replacement << "``.";
2905 OS << "\n\n";
2906 }
2907
2908 std::string ContentStr = Doc.Documentation->getValueAsString("Content");
2909 // Trim leading and trailing newlines and spaces.
Pirama Arumuga Nainar33337ca2015-05-06 11:48:57 -07002910 OS << StringRef(ContentStr).trim();
Stephen Hines651f13c2014-04-23 16:59:28 -07002911
2912 OS << "\n\n\n";
2913}
2914
2915void EmitClangAttrDocs(RecordKeeper &Records, raw_ostream &OS) {
2916 // Get the documentation introduction paragraph.
2917 const Record *Documentation = Records.getDef("GlobalDocumentation");
2918 if (!Documentation) {
2919 PrintFatalError("The Documentation top-level definition is missing, "
2920 "no documentation will be generated.");
2921 return;
2922 }
2923
2924 OS << Documentation->getValueAsString("Intro") << "\n";
2925
2926 // Gather the Documentation lists from each of the attributes, based on the
2927 // category provided.
2928 std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
2929 std::map<const Record *, std::vector<DocumentationData>> SplitDocs;
Stephen Hines6bcf27b2014-05-29 04:14:42 -07002930 for (const auto *A : Attrs) {
2931 const Record &Attr = *A;
Stephen Hines651f13c2014-04-23 16:59:28 -07002932 std::vector<Record *> Docs = Attr.getValueAsListOfDefs("Documentation");
Stephen Hines6bcf27b2014-05-29 04:14:42 -07002933 for (const auto *D : Docs) {
2934 const Record &Doc = *D;
Stephen Hines651f13c2014-04-23 16:59:28 -07002935 const Record *Category = Doc.getValueAsDef("Category");
2936 // If the category is "undocumented", then there cannot be any other
2937 // documentation categories (otherwise, the attribute would become
2938 // documented).
2939 std::string Cat = Category->getValueAsString("Name");
2940 bool Undocumented = Cat == "Undocumented";
2941 if (Undocumented && Docs.size() > 1)
2942 PrintFatalError(Doc.getLoc(),
2943 "Attribute is \"Undocumented\", but has multiple "
2944 "documentation categories");
2945
2946 if (!Undocumented)
2947 SplitDocs[Category].push_back(DocumentationData(Doc, Attr));
2948 }
2949 }
2950
2951 // Having split the attributes out based on what documentation goes where,
2952 // we can begin to generate sections of documentation.
2953 for (const auto &I : SplitDocs) {
2954 WriteCategoryHeader(I.first, OS);
2955
2956 // Walk over each of the attributes in the category and write out their
2957 // documentation.
2958 for (const auto &Doc : I.second)
2959 WriteDocumentation(Doc, OS);
2960 }
2961}
2962
Jakob Stoklund Olesen3cc509b2012-06-13 05:12:41 +00002963} // end namespace clang