1 | //===- ClangAttrEmitter.cpp - Generate Clang attribute handling =-*- C++ -*--=// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // These tablegen backends emit Clang attribute processing code |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "TableGenBackends.h" |
14 | #include "ASTTableGen.h" |
15 | |
16 | #include "llvm/ADT/ArrayRef.h" |
17 | #include "llvm/ADT/DenseMap.h" |
18 | #include "llvm/ADT/DenseSet.h" |
19 | #include "llvm/ADT/MapVector.h" |
20 | #include "llvm/ADT/STLExtras.h" |
21 | #include "llvm/ADT/SmallString.h" |
22 | #include "llvm/ADT/StringExtras.h" |
23 | #include "llvm/ADT/StringRef.h" |
24 | #include "llvm/ADT/StringSet.h" |
25 | #include "llvm/ADT/StringSwitch.h" |
26 | #include "llvm/ADT/iterator_range.h" |
27 | #include "llvm/Support/ErrorHandling.h" |
28 | #include "llvm/Support/raw_ostream.h" |
29 | #include "llvm/TableGen/Error.h" |
30 | #include "llvm/TableGen/Record.h" |
31 | #include "llvm/TableGen/StringMatcher.h" |
32 | #include "llvm/TableGen/TableGenBackend.h" |
33 | #include <algorithm> |
34 | #include <cassert> |
35 | #include <cctype> |
36 | #include <cstddef> |
37 | #include <cstdint> |
38 | #include <map> |
39 | #include <memory> |
40 | #include <optional> |
41 | #include <set> |
42 | #include <sstream> |
43 | #include <string> |
44 | #include <utility> |
45 | #include <vector> |
46 | |
47 | using namespace llvm; |
48 | |
49 | namespace { |
50 | |
51 | class FlattenedSpelling { |
52 | std::string V, N, NS; |
53 | bool K = false; |
54 | const Record &OriginalSpelling; |
55 | |
56 | public: |
57 | FlattenedSpelling(const std::string &Variety, const std::string &Name, |
58 | const std::string &Namespace, bool KnownToGCC, |
59 | const Record &OriginalSpelling) |
60 | : V(Variety), N(Name), NS(Namespace), K(KnownToGCC), |
61 | OriginalSpelling(OriginalSpelling) {} |
62 | explicit FlattenedSpelling(const Record &Spelling) |
63 | : V(std::string(Spelling.getValueAsString(FieldName: "Variety" ))), |
64 | N(std::string(Spelling.getValueAsString(FieldName: "Name" ))), |
65 | OriginalSpelling(Spelling) { |
66 | assert(V != "GCC" && V != "Clang" && |
67 | "Given a GCC spelling, which means this hasn't been flattened!" ); |
68 | if (V == "CXX11" || V == "C23" || V == "Pragma" ) |
69 | NS = std::string(Spelling.getValueAsString(FieldName: "Namespace" )); |
70 | } |
71 | |
72 | const std::string &variety() const { return V; } |
73 | const std::string &name() const { return N; } |
74 | const std::string &nameSpace() const { return NS; } |
75 | bool knownToGCC() const { return K; } |
76 | const Record &getSpellingRecord() const { return OriginalSpelling; } |
77 | }; |
78 | |
79 | } // end anonymous namespace |
80 | |
81 | static std::vector<FlattenedSpelling> |
82 | GetFlattenedSpellings(const Record &Attr) { |
83 | std::vector<Record *> Spellings = Attr.getValueAsListOfDefs(FieldName: "Spellings" ); |
84 | std::vector<FlattenedSpelling> Ret; |
85 | |
86 | for (const auto &Spelling : Spellings) { |
87 | StringRef Variety = Spelling->getValueAsString(FieldName: "Variety" ); |
88 | StringRef Name = Spelling->getValueAsString(FieldName: "Name" ); |
89 | if (Variety == "GCC" ) { |
90 | Ret.emplace_back(args: "GNU" , args: std::string(Name), args: "" , args: true, args&: *Spelling); |
91 | Ret.emplace_back(args: "CXX11" , args: std::string(Name), args: "gnu" , args: true, args&: *Spelling); |
92 | if (Spelling->getValueAsBit(FieldName: "AllowInC" )) |
93 | Ret.emplace_back(args: "C23" , args: std::string(Name), args: "gnu" , args: true, args&: *Spelling); |
94 | } else if (Variety == "Clang" ) { |
95 | Ret.emplace_back(args: "GNU" , args: std::string(Name), args: "" , args: false, args&: *Spelling); |
96 | Ret.emplace_back(args: "CXX11" , args: std::string(Name), args: "clang" , args: false, args&: *Spelling); |
97 | if (Spelling->getValueAsBit(FieldName: "AllowInC" )) |
98 | Ret.emplace_back(args: "C23" , args: std::string(Name), args: "clang" , args: false, args&: *Spelling); |
99 | } else |
100 | Ret.push_back(x: FlattenedSpelling(*Spelling)); |
101 | } |
102 | |
103 | return Ret; |
104 | } |
105 | |
106 | static std::string ReadPCHRecord(StringRef type) { |
107 | return StringSwitch<std::string>(type) |
108 | .EndsWith(S: "Decl *" , Value: "Record.readDeclAs<" + |
109 | std::string(type.data(), 0, type.size() - 1) + |
110 | ">()" ) |
111 | .Case(S: "TypeSourceInfo *" , Value: "Record.readTypeSourceInfo()" ) |
112 | .Case(S: "Expr *" , Value: "Record.readExpr()" ) |
113 | .Case(S: "IdentifierInfo *" , Value: "Record.readIdentifier()" ) |
114 | .Case(S: "StringRef" , Value: "Record.readString()" ) |
115 | .Case(S: "ParamIdx" , Value: "ParamIdx::deserialize(Record.readInt())" ) |
116 | .Case(S: "OMPTraitInfo *" , Value: "Record.readOMPTraitInfo()" ) |
117 | .Default(Value: "Record.readInt()" ); |
118 | } |
119 | |
120 | // Get a type that is suitable for storing an object of the specified type. |
121 | static StringRef getStorageType(StringRef type) { |
122 | return StringSwitch<StringRef>(type) |
123 | .Case(S: "StringRef" , Value: "std::string" ) |
124 | .Default(Value: type); |
125 | } |
126 | |
127 | // Assumes that the way to get the value is SA->getname() |
128 | static std::string WritePCHRecord(StringRef type, StringRef name) { |
129 | return "Record." + |
130 | StringSwitch<std::string>(type) |
131 | .EndsWith(S: "Decl *" , Value: "AddDeclRef(" + std::string(name) + ");\n" ) |
132 | .Case(S: "TypeSourceInfo *" , |
133 | Value: "AddTypeSourceInfo(" + std::string(name) + ");\n" ) |
134 | .Case(S: "Expr *" , Value: "AddStmt(" + std::string(name) + ");\n" ) |
135 | .Case(S: "IdentifierInfo *" , |
136 | Value: "AddIdentifierRef(" + std::string(name) + ");\n" ) |
137 | .Case(S: "StringRef" , Value: "AddString(" + std::string(name) + ");\n" ) |
138 | .Case(S: "ParamIdx" , |
139 | Value: "push_back(" + std::string(name) + ".serialize());\n" ) |
140 | .Case(S: "OMPTraitInfo *" , |
141 | Value: "writeOMPTraitInfo(" + std::string(name) + ");\n" ) |
142 | .Default(Value: "push_back(" + std::string(name) + ");\n" ); |
143 | } |
144 | |
145 | // Normalize attribute name by removing leading and trailing |
146 | // underscores. For example, __foo, foo__, __foo__ would |
147 | // become foo. |
148 | static StringRef NormalizeAttrName(StringRef AttrName) { |
149 | AttrName.consume_front(Prefix: "__" ); |
150 | AttrName.consume_back(Suffix: "__" ); |
151 | return AttrName; |
152 | } |
153 | |
154 | // Normalize the name by removing any and all leading and trailing underscores. |
155 | // This is different from NormalizeAttrName in that it also handles names like |
156 | // _pascal and __pascal. |
157 | static StringRef NormalizeNameForSpellingComparison(StringRef Name) { |
158 | return Name.trim(Chars: "_" ); |
159 | } |
160 | |
161 | // Normalize the spelling of a GNU attribute (i.e. "x" in "__attribute__((x))"), |
162 | // removing "__" if it appears at the beginning and end of the attribute's name. |
163 | static StringRef NormalizeGNUAttrSpelling(StringRef AttrSpelling) { |
164 | if (AttrSpelling.starts_with(Prefix: "__" ) && AttrSpelling.ends_with(Suffix: "__" )) { |
165 | AttrSpelling = AttrSpelling.substr(Start: 2, N: AttrSpelling.size() - 4); |
166 | } |
167 | |
168 | return AttrSpelling; |
169 | } |
170 | |
171 | typedef std::vector<std::pair<std::string, const Record *>> ParsedAttrMap; |
172 | |
173 | static ParsedAttrMap getParsedAttrList(const RecordKeeper &Records, |
174 | ParsedAttrMap *Dupes = nullptr, |
175 | bool SemaOnly = true) { |
176 | std::vector<Record *> Attrs = Records.getAllDerivedDefinitions(ClassName: "Attr" ); |
177 | std::set<std::string> Seen; |
178 | ParsedAttrMap R; |
179 | for (const auto *Attr : Attrs) { |
180 | if (!SemaOnly || Attr->getValueAsBit(FieldName: "SemaHandler" )) { |
181 | std::string AN; |
182 | if (Attr->isSubClassOf(Name: "TargetSpecificAttr" ) && |
183 | !Attr->isValueUnset(FieldName: "ParseKind" )) { |
184 | AN = std::string(Attr->getValueAsString(FieldName: "ParseKind" )); |
185 | |
186 | // If this attribute has already been handled, it does not need to be |
187 | // handled again. |
188 | if (Seen.find(x: AN) != Seen.end()) { |
189 | if (Dupes) |
190 | Dupes->push_back(x: std::make_pair(x&: AN, y&: Attr)); |
191 | continue; |
192 | } |
193 | Seen.insert(x: AN); |
194 | } else |
195 | AN = NormalizeAttrName(AttrName: Attr->getName()).str(); |
196 | |
197 | R.push_back(x: std::make_pair(x&: AN, y&: Attr)); |
198 | } |
199 | } |
200 | return R; |
201 | } |
202 | |
203 | namespace { |
204 | |
205 | class Argument { |
206 | std::string lowerName, upperName; |
207 | StringRef attrName; |
208 | bool isOpt; |
209 | bool Fake; |
210 | |
211 | public: |
212 | Argument(StringRef Arg, StringRef Attr) |
213 | : lowerName(std::string(Arg)), upperName(lowerName), attrName(Attr), |
214 | isOpt(false), Fake(false) { |
215 | if (!lowerName.empty()) { |
216 | lowerName[0] = std::tolower(c: lowerName[0]); |
217 | upperName[0] = std::toupper(c: upperName[0]); |
218 | } |
219 | // Work around MinGW's macro definition of 'interface' to 'struct'. We |
220 | // have an attribute argument called 'Interface', so only the lower case |
221 | // name conflicts with the macro definition. |
222 | if (lowerName == "interface" ) |
223 | lowerName = "interface_" ; |
224 | } |
225 | Argument(const Record &Arg, StringRef Attr) |
226 | : Argument(Arg.getValueAsString(FieldName: "Name" ), Attr) {} |
227 | virtual ~Argument() = default; |
228 | |
229 | StringRef getLowerName() const { return lowerName; } |
230 | StringRef getUpperName() const { return upperName; } |
231 | StringRef getAttrName() const { return attrName; } |
232 | |
233 | bool isOptional() const { return isOpt; } |
234 | void setOptional(bool set) { isOpt = set; } |
235 | |
236 | bool isFake() const { return Fake; } |
237 | void setFake(bool fake) { Fake = fake; } |
238 | |
239 | // These functions print the argument contents formatted in different ways. |
240 | virtual void writeAccessors(raw_ostream &OS) const = 0; |
241 | virtual void writeAccessorDefinitions(raw_ostream &OS) const {} |
242 | virtual void writeASTVisitorTraversal(raw_ostream &OS) const {} |
243 | virtual void writeCloneArgs(raw_ostream &OS) const = 0; |
244 | virtual void writeTemplateInstantiationArgs(raw_ostream &OS) const = 0; |
245 | virtual void writeTemplateInstantiation(raw_ostream &OS) const {} |
246 | virtual void writeCtorBody(raw_ostream &OS) const {} |
247 | virtual void writeCtorInitializers(raw_ostream &OS) const = 0; |
248 | virtual void writeCtorDefaultInitializers(raw_ostream &OS) const = 0; |
249 | virtual void writeCtorParameters(raw_ostream &OS) const = 0; |
250 | virtual void writeDeclarations(raw_ostream &OS) const = 0; |
251 | virtual void writePCHReadArgs(raw_ostream &OS) const = 0; |
252 | virtual void writePCHReadDecls(raw_ostream &OS) const = 0; |
253 | virtual void writePCHWrite(raw_ostream &OS) const = 0; |
254 | virtual std::string getIsOmitted() const { return "false" ; } |
255 | virtual void writeValue(raw_ostream &OS) const = 0; |
256 | virtual void writeDump(raw_ostream &OS) const = 0; |
257 | virtual void writeDumpChildren(raw_ostream &OS) const {} |
258 | virtual void writeHasChildren(raw_ostream &OS) const { OS << "false" ; } |
259 | |
260 | virtual bool isEnumArg() const { return false; } |
261 | virtual bool isVariadicEnumArg() const { return false; } |
262 | virtual bool isVariadic() const { return false; } |
263 | |
264 | virtual void writeImplicitCtorArgs(raw_ostream &OS) const { |
265 | OS << getUpperName(); |
266 | } |
267 | }; |
268 | |
269 | class SimpleArgument : public Argument { |
270 | std::string type; |
271 | |
272 | public: |
273 | SimpleArgument(const Record &Arg, StringRef Attr, std::string T) |
274 | : Argument(Arg, Attr), type(std::move(T)) {} |
275 | |
276 | std::string getType() const { return type; } |
277 | |
278 | void writeAccessors(raw_ostream &OS) const override { |
279 | OS << " " << type << " get" << getUpperName() << "() const {\n" ; |
280 | OS << " return " << getLowerName() << ";\n" ; |
281 | OS << " }" ; |
282 | } |
283 | |
284 | void writeCloneArgs(raw_ostream &OS) const override { |
285 | OS << getLowerName(); |
286 | } |
287 | |
288 | void writeTemplateInstantiationArgs(raw_ostream &OS) const override { |
289 | OS << "A->get" << getUpperName() << "()" ; |
290 | } |
291 | |
292 | void writeCtorInitializers(raw_ostream &OS) const override { |
293 | OS << getLowerName() << "(" << getUpperName() << ")" ; |
294 | } |
295 | |
296 | void writeCtorDefaultInitializers(raw_ostream &OS) const override { |
297 | OS << getLowerName() << "()" ; |
298 | } |
299 | |
300 | void writeCtorParameters(raw_ostream &OS) const override { |
301 | OS << type << " " << getUpperName(); |
302 | } |
303 | |
304 | void writeDeclarations(raw_ostream &OS) const override { |
305 | OS << type << " " << getLowerName() << ";" ; |
306 | } |
307 | |
308 | void writePCHReadDecls(raw_ostream &OS) const override { |
309 | std::string read = ReadPCHRecord(type); |
310 | OS << " " << type << " " << getLowerName() << " = " << read << ";\n" ; |
311 | } |
312 | |
313 | void writePCHReadArgs(raw_ostream &OS) const override { |
314 | OS << getLowerName(); |
315 | } |
316 | |
317 | void writePCHWrite(raw_ostream &OS) const override { |
318 | OS << " " |
319 | << WritePCHRecord(type, |
320 | name: "SA->get" + std::string(getUpperName()) + "()" ); |
321 | } |
322 | |
323 | std::string getIsOmitted() const override { |
324 | auto IsOneOf = [](StringRef subject, auto... list) { |
325 | return ((subject == list) || ...); |
326 | }; |
327 | |
328 | if (IsOneOf(type, "IdentifierInfo *" , "Expr *" )) |
329 | return "!get" + getUpperName().str() + "()" ; |
330 | if (IsOneOf(type, "TypeSourceInfo *" )) |
331 | return "!get" + getUpperName().str() + "Loc()" ; |
332 | if (IsOneOf(type, "ParamIdx" )) |
333 | return "!get" + getUpperName().str() + "().isValid()" ; |
334 | |
335 | assert(IsOneOf(type, "unsigned" , "int" , "bool" , "FunctionDecl *" , |
336 | "VarDecl *" )); |
337 | return "false" ; |
338 | } |
339 | |
340 | void writeValue(raw_ostream &OS) const override { |
341 | if (type == "FunctionDecl *" ) |
342 | OS << "\" << get" << getUpperName() |
343 | << "()->getNameInfo().getAsString() << \"" ; |
344 | else if (type == "IdentifierInfo *" ) |
345 | // Some non-optional (comma required) identifier arguments can be the |
346 | // empty string but are then recorded as a nullptr. |
347 | OS << "\" << (get" << getUpperName() << "() ? get" << getUpperName() |
348 | << "()->getName() : \"\") << \"" ; |
349 | else if (type == "VarDecl *" ) |
350 | OS << "\" << get" << getUpperName() << "()->getName() << \"" ; |
351 | else if (type == "TypeSourceInfo *" ) |
352 | OS << "\" << get" << getUpperName() << "().getAsString() << \"" ; |
353 | else if (type == "ParamIdx" ) |
354 | OS << "\" << get" << getUpperName() << "().getSourceIndex() << \"" ; |
355 | else |
356 | OS << "\" << get" << getUpperName() << "() << \"" ; |
357 | } |
358 | |
359 | void writeDump(raw_ostream &OS) const override { |
360 | if (StringRef(type).ends_with(Suffix: "Decl *" )) { |
361 | OS << " OS << \" \";\n" ; |
362 | OS << " dumpBareDeclRef(SA->get" << getUpperName() << "());\n" ; |
363 | } else if (type == "IdentifierInfo *" ) { |
364 | // Some non-optional (comma required) identifier arguments can be the |
365 | // empty string but are then recorded as a nullptr. |
366 | OS << " if (SA->get" << getUpperName() << "())\n" |
367 | << " OS << \" \" << SA->get" << getUpperName() |
368 | << "()->getName();\n" ; |
369 | } else if (type == "TypeSourceInfo *" ) { |
370 | if (isOptional()) |
371 | OS << " if (SA->get" << getUpperName() << "Loc())" ; |
372 | OS << " OS << \" \" << SA->get" << getUpperName() |
373 | << "().getAsString();\n" ; |
374 | } else if (type == "bool" ) { |
375 | OS << " if (SA->get" << getUpperName() << "()) OS << \" " |
376 | << getUpperName() << "\";\n" ; |
377 | } else if (type == "int" || type == "unsigned" ) { |
378 | OS << " OS << \" \" << SA->get" << getUpperName() << "();\n" ; |
379 | } else if (type == "ParamIdx" ) { |
380 | if (isOptional()) |
381 | OS << " if (SA->get" << getUpperName() << "().isValid())\n " ; |
382 | OS << " OS << \" \" << SA->get" << getUpperName() |
383 | << "().getSourceIndex();\n" ; |
384 | } else if (type == "OMPTraitInfo *" ) { |
385 | OS << " OS << \" \" << SA->get" << getUpperName() << "();\n" ; |
386 | } else { |
387 | llvm_unreachable("Unknown SimpleArgument type!" ); |
388 | } |
389 | } |
390 | }; |
391 | |
392 | class DefaultSimpleArgument : public SimpleArgument { |
393 | int64_t Default; |
394 | |
395 | public: |
396 | DefaultSimpleArgument(const Record &Arg, StringRef Attr, |
397 | std::string T, int64_t Default) |
398 | : SimpleArgument(Arg, Attr, T), Default(Default) {} |
399 | |
400 | void writeAccessors(raw_ostream &OS) const override { |
401 | SimpleArgument::writeAccessors(OS); |
402 | |
403 | OS << "\n\n static const " << getType() << " Default" << getUpperName() |
404 | << " = " ; |
405 | if (getType() == "bool" ) |
406 | OS << (Default != 0 ? "true" : "false" ); |
407 | else |
408 | OS << Default; |
409 | OS << ";" ; |
410 | } |
411 | }; |
412 | |
413 | class StringArgument : public Argument { |
414 | public: |
415 | StringArgument(const Record &Arg, StringRef Attr) |
416 | : Argument(Arg, Attr) |
417 | {} |
418 | |
419 | void writeAccessors(raw_ostream &OS) const override { |
420 | OS << " llvm::StringRef get" << getUpperName() << "() const {\n" ; |
421 | OS << " return llvm::StringRef(" << getLowerName() << ", " |
422 | << getLowerName() << "Length);\n" ; |
423 | OS << " }\n" ; |
424 | OS << " unsigned get" << getUpperName() << "Length() const {\n" ; |
425 | OS << " return " << getLowerName() << "Length;\n" ; |
426 | OS << " }\n" ; |
427 | OS << " void set" << getUpperName() |
428 | << "(ASTContext &C, llvm::StringRef S) {\n" ; |
429 | OS << " " << getLowerName() << "Length = S.size();\n" ; |
430 | OS << " this->" << getLowerName() << " = new (C, 1) char [" |
431 | << getLowerName() << "Length];\n" ; |
432 | OS << " if (!S.empty())\n" ; |
433 | OS << " std::memcpy(this->" << getLowerName() << ", S.data(), " |
434 | << getLowerName() << "Length);\n" ; |
435 | OS << " }" ; |
436 | } |
437 | |
438 | void writeCloneArgs(raw_ostream &OS) const override { |
439 | OS << "get" << getUpperName() << "()" ; |
440 | } |
441 | |
442 | void writeTemplateInstantiationArgs(raw_ostream &OS) const override { |
443 | OS << "A->get" << getUpperName() << "()" ; |
444 | } |
445 | |
446 | void writeCtorBody(raw_ostream &OS) const override { |
447 | OS << " if (!" << getUpperName() << ".empty())\n" ; |
448 | OS << " std::memcpy(" << getLowerName() << ", " << getUpperName() |
449 | << ".data(), " << getLowerName() << "Length);\n" ; |
450 | } |
451 | |
452 | void writeCtorInitializers(raw_ostream &OS) const override { |
453 | OS << getLowerName() << "Length(" << getUpperName() << ".size())," |
454 | << getLowerName() << "(new (Ctx, 1) char[" << getLowerName() |
455 | << "Length])" ; |
456 | } |
457 | |
458 | void writeCtorDefaultInitializers(raw_ostream &OS) const override { |
459 | OS << getLowerName() << "Length(0)," << getLowerName() << "(nullptr)" ; |
460 | } |
461 | |
462 | void writeCtorParameters(raw_ostream &OS) const override { |
463 | OS << "llvm::StringRef " << getUpperName(); |
464 | } |
465 | |
466 | void writeDeclarations(raw_ostream &OS) const override { |
467 | OS << "unsigned " << getLowerName() << "Length;\n" ; |
468 | OS << "char *" << getLowerName() << ";" ; |
469 | } |
470 | |
471 | void writePCHReadDecls(raw_ostream &OS) const override { |
472 | OS << " std::string " << getLowerName() |
473 | << "= Record.readString();\n" ; |
474 | } |
475 | |
476 | void writePCHReadArgs(raw_ostream &OS) const override { |
477 | OS << getLowerName(); |
478 | } |
479 | |
480 | void writePCHWrite(raw_ostream &OS) const override { |
481 | OS << " Record.AddString(SA->get" << getUpperName() << "());\n" ; |
482 | } |
483 | |
484 | void writeValue(raw_ostream &OS) const override { |
485 | OS << "\\\"\" << get" << getUpperName() << "() << \"\\\"" ; |
486 | } |
487 | |
488 | void writeDump(raw_ostream &OS) const override { |
489 | OS << " OS << \" \\\"\" << SA->get" << getUpperName() |
490 | << "() << \"\\\"\";\n" ; |
491 | } |
492 | }; |
493 | |
494 | class AlignedArgument : public Argument { |
495 | public: |
496 | AlignedArgument(const Record &Arg, StringRef Attr) |
497 | : Argument(Arg, Attr) |
498 | {} |
499 | |
500 | void writeAccessors(raw_ostream &OS) const override { |
501 | OS << " bool is" << getUpperName() << "Dependent() const;\n" ; |
502 | OS << " bool is" << getUpperName() << "ErrorDependent() const;\n" ; |
503 | |
504 | OS << " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n" ; |
505 | |
506 | OS << " bool is" << getUpperName() << "Expr() const {\n" ; |
507 | OS << " return is" << getLowerName() << "Expr;\n" ; |
508 | OS << " }\n" ; |
509 | |
510 | OS << " Expr *get" << getUpperName() << "Expr() const {\n" ; |
511 | OS << " assert(is" << getLowerName() << "Expr);\n" ; |
512 | OS << " return " << getLowerName() << "Expr;\n" ; |
513 | OS << " }\n" ; |
514 | |
515 | OS << " TypeSourceInfo *get" << getUpperName() << "Type() const {\n" ; |
516 | OS << " assert(!is" << getLowerName() << "Expr);\n" ; |
517 | OS << " return " << getLowerName() << "Type;\n" ; |
518 | OS << " }" ; |
519 | |
520 | OS << " std::optional<unsigned> getCached" << getUpperName() |
521 | << "Value() const {\n" ; |
522 | OS << " return " << getLowerName() << "Cache;\n" ; |
523 | OS << " }" ; |
524 | |
525 | OS << " void setCached" << getUpperName() |
526 | << "Value(unsigned AlignVal) {\n" ; |
527 | OS << " " << getLowerName() << "Cache = AlignVal;\n" ; |
528 | OS << " }" ; |
529 | } |
530 | |
531 | void writeAccessorDefinitions(raw_ostream &OS) const override { |
532 | OS << "bool " << getAttrName() << "Attr::is" << getUpperName() |
533 | << "Dependent() const {\n" ; |
534 | OS << " if (is" << getLowerName() << "Expr)\n" ; |
535 | OS << " return " << getLowerName() << "Expr && (" << getLowerName() |
536 | << "Expr->isValueDependent() || " << getLowerName() |
537 | << "Expr->isTypeDependent());\n" ; |
538 | OS << " else\n" ; |
539 | OS << " return " << getLowerName() |
540 | << "Type->getType()->isDependentType();\n" ; |
541 | OS << "}\n" ; |
542 | |
543 | OS << "bool " << getAttrName() << "Attr::is" << getUpperName() |
544 | << "ErrorDependent() const {\n" ; |
545 | OS << " if (is" << getLowerName() << "Expr)\n" ; |
546 | OS << " return " << getLowerName() << "Expr && " << getLowerName() |
547 | << "Expr->containsErrors();\n" ; |
548 | OS << " return " << getLowerName() |
549 | << "Type->getType()->containsErrors();\n" ; |
550 | OS << "}\n" ; |
551 | } |
552 | |
553 | void writeASTVisitorTraversal(raw_ostream &OS) const override { |
554 | StringRef Name = getUpperName(); |
555 | OS << " if (A->is" << Name << "Expr()) {\n" |
556 | << " if (!getDerived().TraverseStmt(A->get" << Name << "Expr()))\n" |
557 | << " return false;\n" |
558 | << " } else if (auto *TSI = A->get" << Name << "Type()) {\n" |
559 | << " if (!getDerived().TraverseTypeLoc(TSI->getTypeLoc()))\n" |
560 | << " return false;\n" |
561 | << " }\n" ; |
562 | } |
563 | |
564 | void writeCloneArgs(raw_ostream &OS) const override { |
565 | OS << "is" << getLowerName() << "Expr, is" << getLowerName() |
566 | << "Expr ? static_cast<void*>(" << getLowerName() |
567 | << "Expr) : " << getLowerName() |
568 | << "Type" ; |
569 | } |
570 | |
571 | void writeTemplateInstantiationArgs(raw_ostream &OS) const override { |
572 | // FIXME: move the definition in Sema::InstantiateAttrs to here. |
573 | // In the meantime, aligned attributes are cloned. |
574 | } |
575 | |
576 | void writeCtorBody(raw_ostream &OS) const override { |
577 | OS << " if (is" << getLowerName() << "Expr)\n" ; |
578 | OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>(" |
579 | << getUpperName() << ");\n" ; |
580 | OS << " else\n" ; |
581 | OS << " " << getLowerName() |
582 | << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName() |
583 | << ");\n" ; |
584 | } |
585 | |
586 | void writeCtorInitializers(raw_ostream &OS) const override { |
587 | OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)" ; |
588 | } |
589 | |
590 | void writeCtorDefaultInitializers(raw_ostream &OS) const override { |
591 | OS << "is" << getLowerName() << "Expr(false)" ; |
592 | } |
593 | |
594 | void writeCtorParameters(raw_ostream &OS) const override { |
595 | OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName(); |
596 | } |
597 | |
598 | void writeImplicitCtorArgs(raw_ostream &OS) const override { |
599 | OS << "Is" << getUpperName() << "Expr, " << getUpperName(); |
600 | } |
601 | |
602 | void writeDeclarations(raw_ostream &OS) const override { |
603 | OS << "bool is" << getLowerName() << "Expr;\n" ; |
604 | OS << "union {\n" ; |
605 | OS << "Expr *" << getLowerName() << "Expr;\n" ; |
606 | OS << "TypeSourceInfo *" << getLowerName() << "Type;\n" ; |
607 | OS << "};\n" ; |
608 | OS << "std::optional<unsigned> " << getLowerName() << "Cache;\n" ; |
609 | } |
610 | |
611 | void writePCHReadArgs(raw_ostream &OS) const override { |
612 | OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr" ; |
613 | } |
614 | |
615 | void writePCHReadDecls(raw_ostream &OS) const override { |
616 | OS << " bool is" << getLowerName() << "Expr = Record.readInt();\n" ; |
617 | OS << " void *" << getLowerName() << "Ptr;\n" ; |
618 | OS << " if (is" << getLowerName() << "Expr)\n" ; |
619 | OS << " " << getLowerName() << "Ptr = Record.readExpr();\n" ; |
620 | OS << " else\n" ; |
621 | OS << " " << getLowerName() |
622 | << "Ptr = Record.readTypeSourceInfo();\n" ; |
623 | } |
624 | |
625 | void writePCHWrite(raw_ostream &OS) const override { |
626 | OS << " Record.push_back(SA->is" << getUpperName() << "Expr());\n" ; |
627 | OS << " if (SA->is" << getUpperName() << "Expr())\n" ; |
628 | OS << " Record.AddStmt(SA->get" << getUpperName() << "Expr());\n" ; |
629 | OS << " else\n" ; |
630 | OS << " Record.AddTypeSourceInfo(SA->get" << getUpperName() |
631 | << "Type());\n" ; |
632 | } |
633 | |
634 | std::string getIsOmitted() const override { |
635 | return "!((is" + getLowerName().str() + "Expr && " + |
636 | getLowerName().str() + "Expr) || (!is" + getLowerName().str() + |
637 | "Expr && " + getLowerName().str() + "Type))" ; |
638 | } |
639 | |
640 | void writeValue(raw_ostream &OS) const override { |
641 | OS << "\";\n" ; |
642 | OS << " if (is" << getLowerName() << "Expr && " << getLowerName() |
643 | << "Expr)" ; |
644 | OS << " " << getLowerName() |
645 | << "Expr->printPretty(OS, nullptr, Policy);\n" ; |
646 | OS << " if (!is" << getLowerName() << "Expr && " << getLowerName() |
647 | << "Type)" ; |
648 | OS << " " << getLowerName() |
649 | << "Type->getType().print(OS, Policy);\n" ; |
650 | OS << " OS << \"" ; |
651 | } |
652 | |
653 | void writeDump(raw_ostream &OS) const override { |
654 | OS << " if (!SA->is" << getUpperName() << "Expr())\n" ; |
655 | OS << " dumpType(SA->get" << getUpperName() |
656 | << "Type()->getType());\n" ; |
657 | } |
658 | |
659 | void writeDumpChildren(raw_ostream &OS) const override { |
660 | OS << " if (SA->is" << getUpperName() << "Expr())\n" ; |
661 | OS << " Visit(SA->get" << getUpperName() << "Expr());\n" ; |
662 | } |
663 | |
664 | void writeHasChildren(raw_ostream &OS) const override { |
665 | OS << "SA->is" << getUpperName() << "Expr()" ; |
666 | } |
667 | }; |
668 | |
669 | class VariadicArgument : public Argument { |
670 | std::string Type, ArgName, ArgSizeName, RangeName; |
671 | |
672 | protected: |
673 | // Assumed to receive a parameter: raw_ostream OS. |
674 | virtual void writeValueImpl(raw_ostream &OS) const { |
675 | OS << " OS << Val;\n" ; |
676 | } |
677 | // Assumed to receive a parameter: raw_ostream OS. |
678 | virtual void writeDumpImpl(raw_ostream &OS) const { |
679 | OS << " OS << \" \" << Val;\n" ; |
680 | } |
681 | |
682 | public: |
683 | VariadicArgument(const Record &Arg, StringRef Attr, std::string T) |
684 | : Argument(Arg, Attr), Type(std::move(T)), |
685 | ArgName(getLowerName().str() + "_" ), ArgSizeName(ArgName + "Size" ), |
686 | RangeName(std::string(getLowerName())) {} |
687 | |
688 | VariadicArgument(StringRef Arg, StringRef Attr, std::string T) |
689 | : Argument(Arg, Attr), Type(std::move(T)), |
690 | ArgName(getLowerName().str() + "_" ), ArgSizeName(ArgName + "Size" ), |
691 | RangeName(std::string(getLowerName())) {} |
692 | |
693 | const std::string &getType() const { return Type; } |
694 | const std::string &getArgName() const { return ArgName; } |
695 | const std::string &getArgSizeName() const { return ArgSizeName; } |
696 | bool isVariadic() const override { return true; } |
697 | |
698 | void writeAccessors(raw_ostream &OS) const override { |
699 | std::string IteratorType = getLowerName().str() + "_iterator" ; |
700 | std::string BeginFn = getLowerName().str() + "_begin()" ; |
701 | std::string EndFn = getLowerName().str() + "_end()" ; |
702 | |
703 | OS << " typedef " << Type << "* " << IteratorType << ";\n" ; |
704 | OS << " " << IteratorType << " " << BeginFn << " const {" |
705 | << " return " << ArgName << "; }\n" ; |
706 | OS << " " << IteratorType << " " << EndFn << " const {" |
707 | << " return " << ArgName << " + " << ArgSizeName << "; }\n" ; |
708 | OS << " unsigned " << getLowerName() << "_size() const {" |
709 | << " return " << ArgSizeName << "; }\n" ; |
710 | OS << " llvm::iterator_range<" << IteratorType << "> " << RangeName |
711 | << "() const { return llvm::make_range(" << BeginFn << ", " << EndFn |
712 | << "); }\n" ; |
713 | } |
714 | |
715 | void writeSetter(raw_ostream &OS) const { |
716 | OS << " void set" << getUpperName() << "(ASTContext &Ctx, " ; |
717 | writeCtorParameters(OS); |
718 | OS << ") {\n" ; |
719 | OS << " " << ArgSizeName << " = " << getUpperName() << "Size;\n" ; |
720 | OS << " " << ArgName << " = new (Ctx, 16) " << getType() << "[" |
721 | << ArgSizeName << "];\n" ; |
722 | OS << " " ; |
723 | writeCtorBody(OS); |
724 | OS << " }\n" ; |
725 | } |
726 | |
727 | void writeCloneArgs(raw_ostream &OS) const override { |
728 | OS << ArgName << ", " << ArgSizeName; |
729 | } |
730 | |
731 | void writeTemplateInstantiationArgs(raw_ostream &OS) const override { |
732 | // This isn't elegant, but we have to go through public methods... |
733 | OS << "A->" << getLowerName() << "_begin(), " |
734 | << "A->" << getLowerName() << "_size()" ; |
735 | } |
736 | |
737 | void writeASTVisitorTraversal(raw_ostream &OS) const override { |
738 | // FIXME: Traverse the elements. |
739 | } |
740 | |
741 | void writeCtorBody(raw_ostream &OS) const override { |
742 | OS << " std::copy(" << getUpperName() << ", " << getUpperName() << " + " |
743 | << ArgSizeName << ", " << ArgName << ");\n" ; |
744 | } |
745 | |
746 | void writeCtorInitializers(raw_ostream &OS) const override { |
747 | OS << ArgSizeName << "(" << getUpperName() << "Size), " |
748 | << ArgName << "(new (Ctx, 16) " << getType() << "[" |
749 | << ArgSizeName << "])" ; |
750 | } |
751 | |
752 | void writeCtorDefaultInitializers(raw_ostream &OS) const override { |
753 | OS << ArgSizeName << "(0), " << ArgName << "(nullptr)" ; |
754 | } |
755 | |
756 | void writeCtorParameters(raw_ostream &OS) const override { |
757 | OS << getType() << " *" << getUpperName() << ", unsigned " |
758 | << getUpperName() << "Size" ; |
759 | } |
760 | |
761 | void writeImplicitCtorArgs(raw_ostream &OS) const override { |
762 | OS << getUpperName() << ", " << getUpperName() << "Size" ; |
763 | } |
764 | |
765 | void writeDeclarations(raw_ostream &OS) const override { |
766 | OS << " unsigned " << ArgSizeName << ";\n" ; |
767 | OS << " " << getType() << " *" << ArgName << ";" ; |
768 | } |
769 | |
770 | void writePCHReadDecls(raw_ostream &OS) const override { |
771 | OS << " unsigned " << getLowerName() << "Size = Record.readInt();\n" ; |
772 | OS << " SmallVector<" << getType() << ", 4> " |
773 | << getLowerName() << ";\n" ; |
774 | OS << " " << getLowerName() << ".reserve(" << getLowerName() |
775 | << "Size);\n" ; |
776 | |
777 | // If we can't store the values in the current type (if it's something |
778 | // like StringRef), store them in a different type and convert the |
779 | // container afterwards. |
780 | std::string StorageType = std::string(getStorageType(type: getType())); |
781 | std::string StorageName = std::string(getLowerName()); |
782 | if (StorageType != getType()) { |
783 | StorageName += "Storage" ; |
784 | OS << " SmallVector<" << StorageType << ", 4> " |
785 | << StorageName << ";\n" ; |
786 | OS << " " << StorageName << ".reserve(" << getLowerName() |
787 | << "Size);\n" ; |
788 | } |
789 | |
790 | OS << " for (unsigned i = 0; i != " << getLowerName() << "Size; ++i)\n" ; |
791 | std::string read = ReadPCHRecord(type: Type); |
792 | OS << " " << StorageName << ".push_back(" << read << ");\n" ; |
793 | |
794 | if (StorageType != getType()) { |
795 | OS << " for (unsigned i = 0; i != " << getLowerName() << "Size; ++i)\n" ; |
796 | OS << " " << getLowerName() << ".push_back(" |
797 | << StorageName << "[i]);\n" ; |
798 | } |
799 | } |
800 | |
801 | void writePCHReadArgs(raw_ostream &OS) const override { |
802 | OS << getLowerName() << ".data(), " << getLowerName() << "Size" ; |
803 | } |
804 | |
805 | void writePCHWrite(raw_ostream &OS) const override { |
806 | OS << " Record.push_back(SA->" << getLowerName() << "_size());\n" ; |
807 | OS << " for (auto &Val : SA->" << RangeName << "())\n" ; |
808 | OS << " " << WritePCHRecord(type: Type, name: "Val" ); |
809 | } |
810 | |
811 | void writeValue(raw_ostream &OS) const override { |
812 | OS << "\";\n" ; |
813 | OS << " for (const auto &Val : " << RangeName << "()) {\n" |
814 | << " DelimitAttributeArgument(OS, IsFirstArgument);\n" ; |
815 | writeValueImpl(OS); |
816 | OS << " }\n" ; |
817 | OS << " OS << \"" ; |
818 | } |
819 | |
820 | void writeDump(raw_ostream &OS) const override { |
821 | OS << " for (const auto &Val : SA->" << RangeName << "())\n" ; |
822 | writeDumpImpl(OS); |
823 | } |
824 | }; |
825 | |
826 | class VariadicOMPInteropInfoArgument : public VariadicArgument { |
827 | public: |
828 | VariadicOMPInteropInfoArgument(const Record &Arg, StringRef Attr) |
829 | : VariadicArgument(Arg, Attr, "OMPInteropInfo" ) {} |
830 | |
831 | void writeDump(raw_ostream &OS) const override { |
832 | OS << " for (" << getAttrName() << "Attr::" << getLowerName() |
833 | << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->" |
834 | << getLowerName() << "_end(); I != E; ++I) {\n" ; |
835 | OS << " if (I->IsTarget && I->IsTargetSync)\n" ; |
836 | OS << " OS << \" Target_TargetSync\";\n" ; |
837 | OS << " else if (I->IsTarget)\n" ; |
838 | OS << " OS << \" Target\";\n" ; |
839 | OS << " else\n" ; |
840 | OS << " OS << \" TargetSync\";\n" ; |
841 | OS << " }\n" ; |
842 | } |
843 | |
844 | void writePCHReadDecls(raw_ostream &OS) const override { |
845 | OS << " unsigned " << getLowerName() << "Size = Record.readInt();\n" ; |
846 | OS << " SmallVector<OMPInteropInfo, 4> " << getLowerName() << ";\n" ; |
847 | OS << " " << getLowerName() << ".reserve(" << getLowerName() |
848 | << "Size);\n" ; |
849 | OS << " for (unsigned I = 0, E = " << getLowerName() << "Size; " ; |
850 | OS << "I != E; ++I) {\n" ; |
851 | OS << " bool IsTarget = Record.readBool();\n" ; |
852 | OS << " bool IsTargetSync = Record.readBool();\n" ; |
853 | OS << " " << getLowerName() |
854 | << ".emplace_back(IsTarget, IsTargetSync);\n" ; |
855 | OS << " }\n" ; |
856 | } |
857 | |
858 | void writePCHWrite(raw_ostream &OS) const override { |
859 | OS << " Record.push_back(SA->" << getLowerName() << "_size());\n" ; |
860 | OS << " for (" << getAttrName() << "Attr::" << getLowerName() |
861 | << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->" |
862 | << getLowerName() << "_end(); I != E; ++I) {\n" ; |
863 | OS << " Record.writeBool(I->IsTarget);\n" ; |
864 | OS << " Record.writeBool(I->IsTargetSync);\n" ; |
865 | OS << " }\n" ; |
866 | } |
867 | }; |
868 | |
869 | class VariadicParamIdxArgument : public VariadicArgument { |
870 | public: |
871 | VariadicParamIdxArgument(const Record &Arg, StringRef Attr) |
872 | : VariadicArgument(Arg, Attr, "ParamIdx" ) {} |
873 | |
874 | public: |
875 | void writeValueImpl(raw_ostream &OS) const override { |
876 | OS << " OS << Val.getSourceIndex();\n" ; |
877 | } |
878 | |
879 | void writeDumpImpl(raw_ostream &OS) const override { |
880 | OS << " OS << \" \" << Val.getSourceIndex();\n" ; |
881 | } |
882 | }; |
883 | |
884 | struct VariadicParamOrParamIdxArgument : public VariadicArgument { |
885 | VariadicParamOrParamIdxArgument(const Record &Arg, StringRef Attr) |
886 | : VariadicArgument(Arg, Attr, "int" ) {} |
887 | }; |
888 | |
889 | // Unique the enums, but maintain the original declaration ordering. |
890 | std::vector<StringRef> |
891 | uniqueEnumsInOrder(const std::vector<StringRef> &enums) { |
892 | std::vector<StringRef> uniques; |
893 | SmallDenseSet<StringRef, 8> unique_set; |
894 | for (const auto &i : enums) { |
895 | if (unique_set.insert(V: i).second) |
896 | uniques.push_back(x: i); |
897 | } |
898 | return uniques; |
899 | } |
900 | |
901 | class EnumArgument : public Argument { |
902 | std::string fullType; |
903 | StringRef shortType; |
904 | std::vector<StringRef> values, enums, uniques; |
905 | bool isExternal; |
906 | bool isCovered; |
907 | |
908 | public: |
909 | EnumArgument(const Record &Arg, StringRef Attr) |
910 | : Argument(Arg, Attr), values(Arg.getValueAsListOfStrings(FieldName: "Values" )), |
911 | enums(Arg.getValueAsListOfStrings(FieldName: "Enums" )), |
912 | uniques(uniqueEnumsInOrder(enums)), |
913 | isExternal(Arg.getValueAsBit(FieldName: "IsExternalType" )), |
914 | isCovered(Arg.getValueAsBit(FieldName: "IsCovered" )) { |
915 | StringRef Type = Arg.getValueAsString(FieldName: "Type" ); |
916 | shortType = isExternal ? Type.rsplit(Separator: "::" ).second : Type; |
917 | // If shortType didn't contain :: at all rsplit will give us an empty |
918 | // string. |
919 | if (shortType.empty()) |
920 | shortType = Type; |
921 | fullType = isExternal ? Type : (getAttrName() + "Attr::" + Type).str(); |
922 | |
923 | // FIXME: Emit a proper error |
924 | assert(!uniques.empty()); |
925 | } |
926 | |
927 | bool isEnumArg() const override { return true; } |
928 | |
929 | void writeAccessors(raw_ostream &OS) const override { |
930 | OS << " " << fullType << " get" << getUpperName() << "() const {\n" ; |
931 | OS << " return " << getLowerName() << ";\n" ; |
932 | OS << " }" ; |
933 | } |
934 | |
935 | void writeCloneArgs(raw_ostream &OS) const override { |
936 | OS << getLowerName(); |
937 | } |
938 | |
939 | void writeTemplateInstantiationArgs(raw_ostream &OS) const override { |
940 | OS << "A->get" << getUpperName() << "()" ; |
941 | } |
942 | void writeCtorInitializers(raw_ostream &OS) const override { |
943 | OS << getLowerName() << "(" << getUpperName() << ")" ; |
944 | } |
945 | void writeCtorDefaultInitializers(raw_ostream &OS) const override { |
946 | OS << getLowerName() << "(" << fullType << "(0))" ; |
947 | } |
948 | void writeCtorParameters(raw_ostream &OS) const override { |
949 | OS << fullType << " " << getUpperName(); |
950 | } |
951 | void writeDeclarations(raw_ostream &OS) const override { |
952 | if (!isExternal) { |
953 | auto i = uniques.cbegin(), e = uniques.cend(); |
954 | // The last one needs to not have a comma. |
955 | --e; |
956 | |
957 | OS << "public:\n" ; |
958 | OS << " enum " << shortType << " {\n" ; |
959 | for (; i != e; ++i) |
960 | OS << " " << *i << ",\n" ; |
961 | OS << " " << *e << "\n" ; |
962 | OS << " };\n" ; |
963 | } |
964 | |
965 | OS << "private:\n" ; |
966 | OS << " " << fullType << " " << getLowerName() << ";" ; |
967 | } |
968 | |
969 | void writePCHReadDecls(raw_ostream &OS) const override { |
970 | OS << " " << fullType << " " << getLowerName() << "(static_cast<" |
971 | << fullType << ">(Record.readInt()));\n" ; |
972 | } |
973 | |
974 | void writePCHReadArgs(raw_ostream &OS) const override { |
975 | OS << getLowerName(); |
976 | } |
977 | |
978 | void writePCHWrite(raw_ostream &OS) const override { |
979 | OS << "Record.push_back(static_cast<uint64_t>(SA->get" << getUpperName() |
980 | << "()));\n" ; |
981 | } |
982 | |
983 | void writeValue(raw_ostream &OS) const override { |
984 | // FIXME: this isn't 100% correct -- some enum arguments require printing |
985 | // as a string literal, while others require printing as an identifier. |
986 | // Tablegen currently does not distinguish between the two forms. |
987 | OS << "\\\"\" << " << getAttrName() << "Attr::Convert" << shortType |
988 | << "ToStr(get" << getUpperName() << "()) << \"\\\"" ; |
989 | } |
990 | |
991 | void writeDump(raw_ostream &OS) const override { |
992 | OS << " switch(SA->get" << getUpperName() << "()) {\n" ; |
993 | for (const auto &I : uniques) { |
994 | OS << " case " << fullType << "::" << I << ":\n" ; |
995 | OS << " OS << \" " << I << "\";\n" ; |
996 | OS << " break;\n" ; |
997 | } |
998 | if (!isCovered) { |
999 | OS << " default:\n" ; |
1000 | OS << " llvm_unreachable(\"Invalid attribute value\");\n" ; |
1001 | } |
1002 | OS << " }\n" ; |
1003 | } |
1004 | |
1005 | void writeConversion(raw_ostream &OS, bool ) const { |
1006 | if (Header) { |
1007 | OS << " static bool ConvertStrTo" << shortType << "(StringRef Val, " |
1008 | << fullType << " &Out);\n" ; |
1009 | OS << " static const char *Convert" << shortType << "ToStr(" |
1010 | << fullType << " Val);\n" ; |
1011 | return; |
1012 | } |
1013 | |
1014 | OS << "bool " << getAttrName() << "Attr::ConvertStrTo" << shortType |
1015 | << "(StringRef Val, " << fullType << " &Out) {\n" ; |
1016 | OS << " std::optional<" << fullType << "> " |
1017 | << "R = llvm::StringSwitch<std::optional<" << fullType << ">>(Val)\n" ; |
1018 | for (size_t I = 0; I < enums.size(); ++I) { |
1019 | OS << " .Case(\"" << values[I] << "\", " ; |
1020 | OS << fullType << "::" << enums[I] << ")\n" ; |
1021 | } |
1022 | OS << " .Default(std::optional<" << fullType << ">());\n" ; |
1023 | OS << " if (R) {\n" ; |
1024 | OS << " Out = *R;\n return true;\n }\n" ; |
1025 | OS << " return false;\n" ; |
1026 | OS << "}\n\n" ; |
1027 | |
1028 | // Mapping from enumeration values back to enumeration strings isn't |
1029 | // trivial because some enumeration values have multiple named |
1030 | // enumerators, such as type_visibility(internal) and |
1031 | // type_visibility(hidden) both mapping to TypeVisibilityAttr::Hidden. |
1032 | OS << "const char *" << getAttrName() << "Attr::Convert" << shortType |
1033 | << "ToStr(" << fullType << " Val) {\n" |
1034 | << " switch(Val) {\n" ; |
1035 | SmallDenseSet<StringRef, 8> Uniques; |
1036 | for (size_t I = 0; I < enums.size(); ++I) { |
1037 | if (Uniques.insert(V: enums[I]).second) |
1038 | OS << " case " << fullType << "::" << enums[I] << ": return \"" |
1039 | << values[I] << "\";\n" ; |
1040 | } |
1041 | if (!isCovered) { |
1042 | OS << " default: llvm_unreachable(\"Invalid attribute value\");\n" ; |
1043 | } |
1044 | OS << " }\n" |
1045 | << " llvm_unreachable(\"No enumerator with that value\");\n" |
1046 | << "}\n" ; |
1047 | } |
1048 | }; |
1049 | |
1050 | class VariadicEnumArgument: public VariadicArgument { |
1051 | std::string fullType; |
1052 | StringRef shortType; |
1053 | std::vector<StringRef> values, enums, uniques; |
1054 | bool isExternal; |
1055 | bool isCovered; |
1056 | |
1057 | protected: |
1058 | void writeValueImpl(raw_ostream &OS) const override { |
1059 | // FIXME: this isn't 100% correct -- some enum arguments require printing |
1060 | // as a string literal, while others require printing as an identifier. |
1061 | // Tablegen currently does not distinguish between the two forms. |
1062 | OS << " OS << \"\\\"\" << " << getAttrName() << "Attr::Convert" |
1063 | << shortType << "ToStr(Val)" |
1064 | << "<< \"\\\"\";\n" ; |
1065 | } |
1066 | |
1067 | public: |
1068 | VariadicEnumArgument(const Record &Arg, StringRef Attr) |
1069 | : VariadicArgument(Arg, Attr, |
1070 | std::string(Arg.getValueAsString(FieldName: "Type" ))), |
1071 | values(Arg.getValueAsListOfStrings(FieldName: "Values" )), |
1072 | enums(Arg.getValueAsListOfStrings(FieldName: "Enums" )), |
1073 | uniques(uniqueEnumsInOrder(enums)), |
1074 | isExternal(Arg.getValueAsBit(FieldName: "IsExternalType" )), |
1075 | isCovered(Arg.getValueAsBit(FieldName: "IsCovered" )) { |
1076 | StringRef Type = Arg.getValueAsString(FieldName: "Type" ); |
1077 | shortType = isExternal ? Type.rsplit(Separator: "::" ).second : Type; |
1078 | // If shortType didn't contain :: at all rsplit will give us an empty |
1079 | // string. |
1080 | if (shortType.empty()) |
1081 | shortType = Type; |
1082 | fullType = isExternal ? Type : (getAttrName() + "Attr::" + Type).str(); |
1083 | |
1084 | // FIXME: Emit a proper error |
1085 | assert(!uniques.empty()); |
1086 | } |
1087 | |
1088 | bool isVariadicEnumArg() const override { return true; } |
1089 | |
1090 | void writeDeclarations(raw_ostream &OS) const override { |
1091 | if (!isExternal) { |
1092 | auto i = uniques.cbegin(), e = uniques.cend(); |
1093 | // The last one needs to not have a comma. |
1094 | --e; |
1095 | |
1096 | OS << "public:\n" ; |
1097 | OS << " enum " << shortType << " {\n" ; |
1098 | for (; i != e; ++i) |
1099 | OS << " " << *i << ",\n" ; |
1100 | OS << " " << *e << "\n" ; |
1101 | OS << " };\n" ; |
1102 | } |
1103 | OS << "private:\n" ; |
1104 | |
1105 | VariadicArgument::writeDeclarations(OS); |
1106 | } |
1107 | |
1108 | void writeDump(raw_ostream &OS) const override { |
1109 | OS << " for (" << getAttrName() << "Attr::" << getLowerName() |
1110 | << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->" |
1111 | << getLowerName() << "_end(); I != E; ++I) {\n" ; |
1112 | OS << " switch(*I) {\n" ; |
1113 | for (const auto &UI : uniques) { |
1114 | OS << " case " << fullType << "::" << UI << ":\n" ; |
1115 | OS << " OS << \" " << UI << "\";\n" ; |
1116 | OS << " break;\n" ; |
1117 | } |
1118 | if (!isCovered) { |
1119 | OS << " default:\n" ; |
1120 | OS << " llvm_unreachable(\"Invalid attribute value\");\n" ; |
1121 | } |
1122 | OS << " }\n" ; |
1123 | OS << " }\n" ; |
1124 | } |
1125 | |
1126 | void writePCHReadDecls(raw_ostream &OS) const override { |
1127 | OS << " unsigned " << getLowerName() << "Size = Record.readInt();\n" ; |
1128 | OS << " SmallVector<" << fullType << ", 4> " << getLowerName() |
1129 | << ";\n" ; |
1130 | OS << " " << getLowerName() << ".reserve(" << getLowerName() |
1131 | << "Size);\n" ; |
1132 | OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n" ; |
1133 | OS << " " << getLowerName() << ".push_back(" |
1134 | << "static_cast<" << fullType << ">(Record.readInt()));\n" ; |
1135 | } |
1136 | |
1137 | void writePCHWrite(raw_ostream &OS) const override { |
1138 | OS << " Record.push_back(SA->" << getLowerName() << "_size());\n" ; |
1139 | OS << " for (" << getAttrName() << "Attr::" << getLowerName() |
1140 | << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->" |
1141 | << getLowerName() << "_end(); i != e; ++i)\n" ; |
1142 | OS << " " << WritePCHRecord(type: fullType, name: "(*i)" ); |
1143 | } |
1144 | |
1145 | void writeConversion(raw_ostream &OS, bool ) const { |
1146 | if (Header) { |
1147 | OS << " static bool ConvertStrTo" << shortType << "(StringRef Val, " |
1148 | << fullType << " &Out);\n" ; |
1149 | OS << " static const char *Convert" << shortType << "ToStr(" |
1150 | << fullType << " Val);\n" ; |
1151 | return; |
1152 | } |
1153 | |
1154 | OS << "bool " << getAttrName() << "Attr::ConvertStrTo" << shortType |
1155 | << "(StringRef Val, " ; |
1156 | OS << fullType << " &Out) {\n" ; |
1157 | OS << " std::optional<" << fullType |
1158 | << "> R = llvm::StringSwitch<std::optional<" ; |
1159 | OS << fullType << ">>(Val)\n" ; |
1160 | for (size_t I = 0; I < enums.size(); ++I) { |
1161 | OS << " .Case(\"" << values[I] << "\", " ; |
1162 | OS << fullType << "::" << enums[I] << ")\n" ; |
1163 | } |
1164 | OS << " .Default(std::optional<" << fullType << ">());\n" ; |
1165 | OS << " if (R) {\n" ; |
1166 | OS << " Out = *R;\n return true;\n }\n" ; |
1167 | OS << " return false;\n" ; |
1168 | OS << "}\n\n" ; |
1169 | |
1170 | OS << "const char *" << getAttrName() << "Attr::Convert" << shortType |
1171 | << "ToStr(" << fullType << " Val) {\n" |
1172 | << " switch(Val) {\n" ; |
1173 | SmallDenseSet<StringRef, 8> Uniques; |
1174 | for (size_t I = 0; I < enums.size(); ++I) { |
1175 | if (Uniques.insert(V: enums[I]).second) |
1176 | OS << " case " << fullType << "::" << enums[I] << ": return \"" |
1177 | << values[I] << "\";\n" ; |
1178 | } |
1179 | if (!isCovered) { |
1180 | OS << " default: llvm_unreachable(\"Invalid attribute value\");\n" ; |
1181 | } |
1182 | OS << " }\n" |
1183 | << " llvm_unreachable(\"No enumerator with that value\");\n" |
1184 | << "}\n" ; |
1185 | } |
1186 | }; |
1187 | |
1188 | class VersionArgument : public Argument { |
1189 | public: |
1190 | VersionArgument(const Record &Arg, StringRef Attr) |
1191 | : Argument(Arg, Attr) |
1192 | {} |
1193 | |
1194 | void writeAccessors(raw_ostream &OS) const override { |
1195 | OS << " VersionTuple get" << getUpperName() << "() const {\n" ; |
1196 | OS << " return " << getLowerName() << ";\n" ; |
1197 | OS << " }\n" ; |
1198 | OS << " void set" << getUpperName() |
1199 | << "(ASTContext &C, VersionTuple V) {\n" ; |
1200 | OS << " " << getLowerName() << " = V;\n" ; |
1201 | OS << " }" ; |
1202 | } |
1203 | |
1204 | void writeCloneArgs(raw_ostream &OS) const override { |
1205 | OS << "get" << getUpperName() << "()" ; |
1206 | } |
1207 | |
1208 | void writeTemplateInstantiationArgs(raw_ostream &OS) const override { |
1209 | OS << "A->get" << getUpperName() << "()" ; |
1210 | } |
1211 | |
1212 | void writeCtorInitializers(raw_ostream &OS) const override { |
1213 | OS << getLowerName() << "(" << getUpperName() << ")" ; |
1214 | } |
1215 | |
1216 | void writeCtorDefaultInitializers(raw_ostream &OS) const override { |
1217 | OS << getLowerName() << "()" ; |
1218 | } |
1219 | |
1220 | void writeCtorParameters(raw_ostream &OS) const override { |
1221 | OS << "VersionTuple " << getUpperName(); |
1222 | } |
1223 | |
1224 | void writeDeclarations(raw_ostream &OS) const override { |
1225 | OS << "VersionTuple " << getLowerName() << ";\n" ; |
1226 | } |
1227 | |
1228 | void writePCHReadDecls(raw_ostream &OS) const override { |
1229 | OS << " VersionTuple " << getLowerName() |
1230 | << "= Record.readVersionTuple();\n" ; |
1231 | } |
1232 | |
1233 | void writePCHReadArgs(raw_ostream &OS) const override { |
1234 | OS << getLowerName(); |
1235 | } |
1236 | |
1237 | void writePCHWrite(raw_ostream &OS) const override { |
1238 | OS << " Record.AddVersionTuple(SA->get" << getUpperName() << "());\n" ; |
1239 | } |
1240 | |
1241 | void writeValue(raw_ostream &OS) const override { |
1242 | OS << getLowerName() << "=\" << get" << getUpperName() << "() << \"" ; |
1243 | } |
1244 | |
1245 | void writeDump(raw_ostream &OS) const override { |
1246 | OS << " OS << \" \" << SA->get" << getUpperName() << "();\n" ; |
1247 | } |
1248 | }; |
1249 | |
1250 | class ExprArgument : public SimpleArgument { |
1251 | public: |
1252 | ExprArgument(const Record &Arg, StringRef Attr) |
1253 | : SimpleArgument(Arg, Attr, "Expr *" ) |
1254 | {} |
1255 | |
1256 | void writeASTVisitorTraversal(raw_ostream &OS) const override { |
1257 | OS << " if (!" |
1258 | << "getDerived().TraverseStmt(A->get" << getUpperName() << "()))\n" ; |
1259 | OS << " return false;\n" ; |
1260 | } |
1261 | |
1262 | void writeTemplateInstantiationArgs(raw_ostream &OS) const override { |
1263 | OS << "tempInst" << getUpperName(); |
1264 | } |
1265 | |
1266 | void writeTemplateInstantiation(raw_ostream &OS) const override { |
1267 | OS << " " << getType() << " tempInst" << getUpperName() << ";\n" ; |
1268 | OS << " {\n" ; |
1269 | OS << " EnterExpressionEvaluationContext " |
1270 | << "Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);\n" ; |
1271 | OS << " ExprResult " << "Result = S.SubstExpr(" |
1272 | << "A->get" << getUpperName() << "(), TemplateArgs);\n" ; |
1273 | OS << " if (Result.isInvalid())\n" ; |
1274 | OS << " return nullptr;\n" ; |
1275 | OS << " tempInst" << getUpperName() << " = Result.get();\n" ; |
1276 | OS << " }\n" ; |
1277 | } |
1278 | |
1279 | void writeValue(raw_ostream &OS) const override { |
1280 | OS << "\";\n" ; |
1281 | OS << " get" << getUpperName() |
1282 | << "()->printPretty(OS, nullptr, Policy);\n" ; |
1283 | OS << " OS << \"" ; |
1284 | } |
1285 | |
1286 | void writeDump(raw_ostream &OS) const override {} |
1287 | |
1288 | void writeDumpChildren(raw_ostream &OS) const override { |
1289 | OS << " Visit(SA->get" << getUpperName() << "());\n" ; |
1290 | } |
1291 | |
1292 | void writeHasChildren(raw_ostream &OS) const override { OS << "true" ; } |
1293 | }; |
1294 | |
1295 | class VariadicExprArgument : public VariadicArgument { |
1296 | public: |
1297 | VariadicExprArgument(const Record &Arg, StringRef Attr) |
1298 | : VariadicArgument(Arg, Attr, "Expr *" ) |
1299 | {} |
1300 | |
1301 | VariadicExprArgument(StringRef ArgName, StringRef Attr) |
1302 | : VariadicArgument(ArgName, Attr, "Expr *" ) {} |
1303 | |
1304 | void writeASTVisitorTraversal(raw_ostream &OS) const override { |
1305 | OS << " {\n" ; |
1306 | OS << " " << getType() << " *I = A->" << getLowerName() |
1307 | << "_begin();\n" ; |
1308 | OS << " " << getType() << " *E = A->" << getLowerName() |
1309 | << "_end();\n" ; |
1310 | OS << " for (; I != E; ++I) {\n" ; |
1311 | OS << " if (!getDerived().TraverseStmt(*I))\n" ; |
1312 | OS << " return false;\n" ; |
1313 | OS << " }\n" ; |
1314 | OS << " }\n" ; |
1315 | } |
1316 | |
1317 | void writeTemplateInstantiationArgs(raw_ostream &OS) const override { |
1318 | OS << "tempInst" << getUpperName() << ", " |
1319 | << "A->" << getLowerName() << "_size()" ; |
1320 | } |
1321 | |
1322 | void writeTemplateInstantiation(raw_ostream &OS) const override { |
1323 | OS << " auto *tempInst" << getUpperName() |
1324 | << " = new (C, 16) " << getType() |
1325 | << "[A->" << getLowerName() << "_size()];\n" ; |
1326 | OS << " {\n" ; |
1327 | OS << " EnterExpressionEvaluationContext " |
1328 | << "Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);\n" ; |
1329 | OS << " " << getType() << " *TI = tempInst" << getUpperName() |
1330 | << ";\n" ; |
1331 | OS << " " << getType() << " *I = A->" << getLowerName() |
1332 | << "_begin();\n" ; |
1333 | OS << " " << getType() << " *E = A->" << getLowerName() |
1334 | << "_end();\n" ; |
1335 | OS << " for (; I != E; ++I, ++TI) {\n" ; |
1336 | OS << " ExprResult Result = S.SubstExpr(*I, TemplateArgs);\n" ; |
1337 | OS << " if (Result.isInvalid())\n" ; |
1338 | OS << " return nullptr;\n" ; |
1339 | OS << " *TI = Result.get();\n" ; |
1340 | OS << " }\n" ; |
1341 | OS << " }\n" ; |
1342 | } |
1343 | |
1344 | void writeDump(raw_ostream &OS) const override {} |
1345 | |
1346 | void writeDumpChildren(raw_ostream &OS) const override { |
1347 | OS << " for (" << getAttrName() << "Attr::" << getLowerName() |
1348 | << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->" |
1349 | << getLowerName() << "_end(); I != E; ++I)\n" ; |
1350 | OS << " Visit(*I);\n" ; |
1351 | } |
1352 | |
1353 | void writeHasChildren(raw_ostream &OS) const override { |
1354 | OS << "SA->" << getLowerName() << "_begin() != " |
1355 | << "SA->" << getLowerName() << "_end()" ; |
1356 | } |
1357 | }; |
1358 | |
1359 | class VariadicIdentifierArgument : public VariadicArgument { |
1360 | public: |
1361 | VariadicIdentifierArgument(const Record &Arg, StringRef Attr) |
1362 | : VariadicArgument(Arg, Attr, "IdentifierInfo *" ) |
1363 | {} |
1364 | }; |
1365 | |
1366 | class VariadicStringArgument : public VariadicArgument { |
1367 | public: |
1368 | VariadicStringArgument(const Record &Arg, StringRef Attr) |
1369 | : VariadicArgument(Arg, Attr, "StringRef" ) |
1370 | {} |
1371 | |
1372 | void writeCtorBody(raw_ostream &OS) const override { |
1373 | OS << " for (size_t I = 0, E = " << getArgSizeName() << "; I != E;\n" |
1374 | " ++I) {\n" |
1375 | " StringRef Ref = " << getUpperName() << "[I];\n" |
1376 | " if (!Ref.empty()) {\n" |
1377 | " char *Mem = new (Ctx, 1) char[Ref.size()];\n" |
1378 | " std::memcpy(Mem, Ref.data(), Ref.size());\n" |
1379 | " " << getArgName() << "[I] = StringRef(Mem, Ref.size());\n" |
1380 | " }\n" |
1381 | " }\n" ; |
1382 | } |
1383 | |
1384 | void writeValueImpl(raw_ostream &OS) const override { |
1385 | OS << " OS << \"\\\"\" << Val << \"\\\"\";\n" ; |
1386 | } |
1387 | }; |
1388 | |
1389 | class TypeArgument : public SimpleArgument { |
1390 | public: |
1391 | TypeArgument(const Record &Arg, StringRef Attr) |
1392 | : SimpleArgument(Arg, Attr, "TypeSourceInfo *" ) |
1393 | {} |
1394 | |
1395 | void writeAccessors(raw_ostream &OS) const override { |
1396 | OS << " QualType get" << getUpperName() << "() const {\n" ; |
1397 | OS << " return " << getLowerName() << "->getType();\n" ; |
1398 | OS << " }" ; |
1399 | OS << " " << getType() << " get" << getUpperName() << "Loc() const {\n" ; |
1400 | OS << " return " << getLowerName() << ";\n" ; |
1401 | OS << " }" ; |
1402 | } |
1403 | |
1404 | void writeASTVisitorTraversal(raw_ostream &OS) const override { |
1405 | OS << " if (auto *TSI = A->get" << getUpperName() << "Loc())\n" ; |
1406 | OS << " if (!getDerived().TraverseTypeLoc(TSI->getTypeLoc()))\n" ; |
1407 | OS << " return false;\n" ; |
1408 | } |
1409 | |
1410 | void writeTemplateInstantiation(raw_ostream &OS) const override { |
1411 | OS << " " << getType() << " tempInst" << getUpperName() << " =\n" ; |
1412 | OS << " S.SubstType(A->get" << getUpperName() << "Loc(), " |
1413 | << "TemplateArgs, A->getLoc(), A->getAttrName());\n" ; |
1414 | OS << " if (!tempInst" << getUpperName() << ")\n" ; |
1415 | OS << " return nullptr;\n" ; |
1416 | } |
1417 | |
1418 | void writeTemplateInstantiationArgs(raw_ostream &OS) const override { |
1419 | OS << "tempInst" << getUpperName(); |
1420 | } |
1421 | |
1422 | void writePCHWrite(raw_ostream &OS) const override { |
1423 | OS << " " |
1424 | << WritePCHRecord(type: getType(), |
1425 | name: "SA->get" + std::string(getUpperName()) + "Loc()" ); |
1426 | } |
1427 | }; |
1428 | |
1429 | class WrappedAttr : public SimpleArgument { |
1430 | public: |
1431 | WrappedAttr(const Record &Arg, StringRef Attr) |
1432 | : SimpleArgument(Arg, Attr, "Attr *" ) {} |
1433 | |
1434 | void writePCHReadDecls(raw_ostream &OS) const override { |
1435 | OS << " Attr *" << getLowerName() << " = Record.readAttr();" ; |
1436 | } |
1437 | |
1438 | void writePCHWrite(raw_ostream &OS) const override { |
1439 | OS << " AddAttr(SA->get" << getUpperName() << "());" ; |
1440 | } |
1441 | |
1442 | void writeDump(raw_ostream &OS) const override {} |
1443 | |
1444 | void writeDumpChildren(raw_ostream &OS) const override { |
1445 | OS << " Visit(SA->get" << getUpperName() << "());\n" ; |
1446 | } |
1447 | |
1448 | void writeHasChildren(raw_ostream &OS) const override { OS << "true" ; } |
1449 | }; |
1450 | |
1451 | } // end anonymous namespace |
1452 | |
1453 | static std::unique_ptr<Argument> |
1454 | createArgument(const Record &Arg, StringRef Attr, |
1455 | const Record *Search = nullptr) { |
1456 | if (!Search) |
1457 | Search = &Arg; |
1458 | |
1459 | std::unique_ptr<Argument> Ptr; |
1460 | llvm::StringRef ArgName = Search->getName(); |
1461 | |
1462 | if (ArgName == "AlignedArgument" ) |
1463 | Ptr = std::make_unique<AlignedArgument>(args: Arg, args&: Attr); |
1464 | else if (ArgName == "EnumArgument" ) |
1465 | Ptr = std::make_unique<EnumArgument>(args: Arg, args&: Attr); |
1466 | else if (ArgName == "ExprArgument" ) |
1467 | Ptr = std::make_unique<ExprArgument>(args: Arg, args&: Attr); |
1468 | else if (ArgName == "DeclArgument" ) |
1469 | Ptr = std::make_unique<SimpleArgument>( |
1470 | args: Arg, args&: Attr, args: (Arg.getValueAsDef(FieldName: "Kind" )->getName() + "Decl *" ).str()); |
1471 | else if (ArgName == "IdentifierArgument" ) |
1472 | Ptr = std::make_unique<SimpleArgument>(args: Arg, args&: Attr, args: "IdentifierInfo *" ); |
1473 | else if (ArgName == "DefaultBoolArgument" ) |
1474 | Ptr = std::make_unique<DefaultSimpleArgument>( |
1475 | args: Arg, args&: Attr, args: "bool" , args: Arg.getValueAsBit(FieldName: "Default" )); |
1476 | else if (ArgName == "BoolArgument" ) |
1477 | Ptr = std::make_unique<SimpleArgument>(args: Arg, args&: Attr, args: "bool" ); |
1478 | else if (ArgName == "DefaultIntArgument" ) |
1479 | Ptr = std::make_unique<DefaultSimpleArgument>( |
1480 | args: Arg, args&: Attr, args: "int" , args: Arg.getValueAsInt(FieldName: "Default" )); |
1481 | else if (ArgName == "IntArgument" ) |
1482 | Ptr = std::make_unique<SimpleArgument>(args: Arg, args&: Attr, args: "int" ); |
1483 | else if (ArgName == "StringArgument" ) |
1484 | Ptr = std::make_unique<StringArgument>(args: Arg, args&: Attr); |
1485 | else if (ArgName == "TypeArgument" ) |
1486 | Ptr = std::make_unique<TypeArgument>(args: Arg, args&: Attr); |
1487 | else if (ArgName == "UnsignedArgument" ) |
1488 | Ptr = std::make_unique<SimpleArgument>(args: Arg, args&: Attr, args: "unsigned" ); |
1489 | else if (ArgName == "VariadicUnsignedArgument" ) |
1490 | Ptr = std::make_unique<VariadicArgument>(args: Arg, args&: Attr, args: "unsigned" ); |
1491 | else if (ArgName == "VariadicStringArgument" ) |
1492 | Ptr = std::make_unique<VariadicStringArgument>(args: Arg, args&: Attr); |
1493 | else if (ArgName == "VariadicEnumArgument" ) |
1494 | Ptr = std::make_unique<VariadicEnumArgument>(args: Arg, args&: Attr); |
1495 | else if (ArgName == "VariadicExprArgument" ) |
1496 | Ptr = std::make_unique<VariadicExprArgument>(args: Arg, args&: Attr); |
1497 | else if (ArgName == "VariadicParamIdxArgument" ) |
1498 | Ptr = std::make_unique<VariadicParamIdxArgument>(args: Arg, args&: Attr); |
1499 | else if (ArgName == "VariadicParamOrParamIdxArgument" ) |
1500 | Ptr = std::make_unique<VariadicParamOrParamIdxArgument>(args: Arg, args&: Attr); |
1501 | else if (ArgName == "ParamIdxArgument" ) |
1502 | Ptr = std::make_unique<SimpleArgument>(args: Arg, args&: Attr, args: "ParamIdx" ); |
1503 | else if (ArgName == "VariadicIdentifierArgument" ) |
1504 | Ptr = std::make_unique<VariadicIdentifierArgument>(args: Arg, args&: Attr); |
1505 | else if (ArgName == "VersionArgument" ) |
1506 | Ptr = std::make_unique<VersionArgument>(args: Arg, args&: Attr); |
1507 | else if (ArgName == "WrappedAttr" ) |
1508 | Ptr = std::make_unique<WrappedAttr>(args: Arg, args&: Attr); |
1509 | else if (ArgName == "OMPTraitInfoArgument" ) |
1510 | Ptr = std::make_unique<SimpleArgument>(args: Arg, args&: Attr, args: "OMPTraitInfo *" ); |
1511 | else if (ArgName == "VariadicOMPInteropInfoArgument" ) |
1512 | Ptr = std::make_unique<VariadicOMPInteropInfoArgument>(args: Arg, args&: Attr); |
1513 | |
1514 | if (!Ptr) { |
1515 | // Search in reverse order so that the most-derived type is handled first. |
1516 | ArrayRef<std::pair<Record*, SMRange>> Bases = Search->getSuperClasses(); |
1517 | for (const auto &Base : llvm::reverse(C&: Bases)) { |
1518 | if ((Ptr = createArgument(Arg, Attr, Search: Base.first))) |
1519 | break; |
1520 | } |
1521 | } |
1522 | |
1523 | if (Ptr && Arg.getValueAsBit(FieldName: "Optional" )) |
1524 | Ptr->setOptional(true); |
1525 | |
1526 | if (Ptr && Arg.getValueAsBit(FieldName: "Fake" )) |
1527 | Ptr->setFake(true); |
1528 | |
1529 | return Ptr; |
1530 | } |
1531 | |
1532 | static void writeAvailabilityValue(raw_ostream &OS) { |
1533 | OS << "\" << getPlatform()->getName();\n" |
1534 | << " if (getStrict()) OS << \", strict\";\n" |
1535 | << " if (!getIntroduced().empty()) OS << \", introduced=\" << getIntroduced();\n" |
1536 | << " if (!getDeprecated().empty()) OS << \", deprecated=\" << getDeprecated();\n" |
1537 | << " if (!getObsoleted().empty()) OS << \", obsoleted=\" << getObsoleted();\n" |
1538 | << " if (getUnavailable()) OS << \", unavailable\";\n" |
1539 | << " OS << \"" ; |
1540 | } |
1541 | |
1542 | static void writeDeprecatedAttrValue(raw_ostream &OS, std::string &Variety) { |
1543 | OS << "\\\"\" << getMessage() << \"\\\"\";\n" ; |
1544 | // Only GNU deprecated has an optional fixit argument at the second position. |
1545 | if (Variety == "GNU" ) |
1546 | OS << " if (!getReplacement().empty()) OS << \", \\\"\"" |
1547 | " << getReplacement() << \"\\\"\";\n" ; |
1548 | OS << " OS << \"" ; |
1549 | } |
1550 | |
1551 | static void writeGetSpellingFunction(const Record &R, raw_ostream &OS) { |
1552 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr: R); |
1553 | |
1554 | OS << "const char *" << R.getName() << "Attr::getSpelling() const {\n" ; |
1555 | if (Spellings.empty()) { |
1556 | OS << " return \"(No spelling)\";\n}\n\n" ; |
1557 | return; |
1558 | } |
1559 | |
1560 | OS << " switch (getAttributeSpellingListIndex()) {\n" |
1561 | " default:\n" |
1562 | " llvm_unreachable(\"Unknown attribute spelling!\");\n" |
1563 | " return \"(No spelling)\";\n" ; |
1564 | |
1565 | for (unsigned I = 0; I < Spellings.size(); ++I) |
1566 | OS << " case " << I << ":\n" |
1567 | " return \"" << Spellings[I].name() << "\";\n" ; |
1568 | // End of the switch statement. |
1569 | OS << " }\n" ; |
1570 | // End of the getSpelling function. |
1571 | OS << "}\n\n" ; |
1572 | } |
1573 | |
1574 | static void |
1575 | writePrettyPrintFunction(const Record &R, |
1576 | const std::vector<std::unique_ptr<Argument>> &Args, |
1577 | raw_ostream &OS) { |
1578 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr: R); |
1579 | |
1580 | OS << "void " << R.getName() << "Attr::printPretty(" |
1581 | << "raw_ostream &OS, const PrintingPolicy &Policy) const {\n" ; |
1582 | |
1583 | if (Spellings.empty()) { |
1584 | OS << "}\n\n" ; |
1585 | return; |
1586 | } |
1587 | |
1588 | OS << " bool IsFirstArgument = true; (void)IsFirstArgument;\n" |
1589 | << " unsigned TrailingOmittedArgs = 0; (void)TrailingOmittedArgs;\n" |
1590 | << " switch (getAttributeSpellingListIndex()) {\n" |
1591 | << " default:\n" |
1592 | << " llvm_unreachable(\"Unknown attribute spelling!\");\n" |
1593 | << " break;\n" ; |
1594 | |
1595 | for (unsigned I = 0; I < Spellings.size(); ++ I) { |
1596 | llvm::SmallString<16> Prefix; |
1597 | llvm::SmallString<8> Suffix; |
1598 | // The actual spelling of the name and namespace (if applicable) |
1599 | // of an attribute without considering prefix and suffix. |
1600 | llvm::SmallString<64> Spelling; |
1601 | std::string Name = Spellings[I].name(); |
1602 | std::string Variety = Spellings[I].variety(); |
1603 | |
1604 | if (Variety == "GNU" ) { |
1605 | Prefix = "__attribute__((" ; |
1606 | Suffix = "))" ; |
1607 | } else if (Variety == "CXX11" || Variety == "C23" ) { |
1608 | Prefix = "[[" ; |
1609 | Suffix = "]]" ; |
1610 | std::string Namespace = Spellings[I].nameSpace(); |
1611 | if (!Namespace.empty()) { |
1612 | Spelling += Namespace; |
1613 | Spelling += "::" ; |
1614 | } |
1615 | } else if (Variety == "Declspec" ) { |
1616 | Prefix = "__declspec(" ; |
1617 | Suffix = ")" ; |
1618 | } else if (Variety == "Microsoft" ) { |
1619 | Prefix = "[" ; |
1620 | Suffix = "]" ; |
1621 | } else if (Variety == "Keyword" ) { |
1622 | Prefix = "" ; |
1623 | Suffix = "" ; |
1624 | } else if (Variety == "Pragma" ) { |
1625 | Prefix = "#pragma " ; |
1626 | Suffix = "\n" ; |
1627 | std::string Namespace = Spellings[I].nameSpace(); |
1628 | if (!Namespace.empty()) { |
1629 | Spelling += Namespace; |
1630 | Spelling += " " ; |
1631 | } |
1632 | } else if (Variety == "HLSLAnnotation" ) { |
1633 | Prefix = ":" ; |
1634 | Suffix = "" ; |
1635 | } else { |
1636 | llvm_unreachable("Unknown attribute syntax variety!" ); |
1637 | } |
1638 | |
1639 | Spelling += Name; |
1640 | |
1641 | OS << " case " << I << " : {\n" |
1642 | << " OS << \"" << Prefix << Spelling << "\";\n" ; |
1643 | |
1644 | if (Variety == "Pragma" ) { |
1645 | OS << " printPrettyPragma(OS, Policy);\n" ; |
1646 | OS << " OS << \"\\n\";" ; |
1647 | OS << " break;\n" ; |
1648 | OS << " }\n" ; |
1649 | continue; |
1650 | } |
1651 | |
1652 | if (Spelling == "availability" ) { |
1653 | OS << " OS << \"(" ; |
1654 | writeAvailabilityValue(OS); |
1655 | OS << ")\";\n" ; |
1656 | } else if (Spelling == "deprecated" || Spelling == "gnu::deprecated" ) { |
1657 | OS << " OS << \"(" ; |
1658 | writeDeprecatedAttrValue(OS, Variety); |
1659 | OS << ")\";\n" ; |
1660 | } else { |
1661 | // To avoid printing parentheses around an empty argument list or |
1662 | // printing spurious commas at the end of an argument list, we need to |
1663 | // determine where the last provided non-fake argument is. |
1664 | bool FoundNonOptArg = false; |
1665 | for (const auto &arg : llvm::reverse(C: Args)) { |
1666 | if (arg->isFake()) |
1667 | continue; |
1668 | if (FoundNonOptArg) |
1669 | continue; |
1670 | // FIXME: arg->getIsOmitted() == "false" means we haven't implemented |
1671 | // any way to detect whether the argument was omitted. |
1672 | if (!arg->isOptional() || arg->getIsOmitted() == "false" ) { |
1673 | FoundNonOptArg = true; |
1674 | continue; |
1675 | } |
1676 | OS << " if (" << arg->getIsOmitted() << ")\n" |
1677 | << " ++TrailingOmittedArgs;\n" ; |
1678 | } |
1679 | unsigned ArgIndex = 0; |
1680 | for (const auto &arg : Args) { |
1681 | if (arg->isFake()) |
1682 | continue; |
1683 | std::string IsOmitted = arg->getIsOmitted(); |
1684 | if (arg->isOptional() && IsOmitted != "false" ) |
1685 | OS << " if (!(" << IsOmitted << ")) {\n" ; |
1686 | // Variadic arguments print their own leading comma. |
1687 | if (!arg->isVariadic()) |
1688 | OS << " DelimitAttributeArgument(OS, IsFirstArgument);\n" ; |
1689 | OS << " OS << \"" ; |
1690 | arg->writeValue(OS); |
1691 | OS << "\";\n" ; |
1692 | if (arg->isOptional() && IsOmitted != "false" ) |
1693 | OS << " }\n" ; |
1694 | ++ArgIndex; |
1695 | } |
1696 | if (ArgIndex != 0) |
1697 | OS << " if (!IsFirstArgument)\n" |
1698 | << " OS << \")\";\n" ; |
1699 | } |
1700 | OS << " OS << \"" << Suffix << "\";\n" |
1701 | << " break;\n" |
1702 | << " }\n" ; |
1703 | } |
1704 | |
1705 | // End of the switch statement. |
1706 | OS << "}\n" ; |
1707 | // End of the print function. |
1708 | OS << "}\n\n" ; |
1709 | } |
1710 | |
1711 | /// Return the index of a spelling in a spelling list. |
1712 | static unsigned |
1713 | getSpellingListIndex(const std::vector<FlattenedSpelling> &SpellingList, |
1714 | const FlattenedSpelling &Spelling) { |
1715 | assert(!SpellingList.empty() && "Spelling list is empty!" ); |
1716 | |
1717 | for (unsigned Index = 0; Index < SpellingList.size(); ++Index) { |
1718 | const FlattenedSpelling &S = SpellingList[Index]; |
1719 | if (S.variety() != Spelling.variety()) |
1720 | continue; |
1721 | if (S.nameSpace() != Spelling.nameSpace()) |
1722 | continue; |
1723 | if (S.name() != Spelling.name()) |
1724 | continue; |
1725 | |
1726 | return Index; |
1727 | } |
1728 | |
1729 | llvm_unreachable("Unknown spelling!" ); |
1730 | } |
1731 | |
1732 | static void writeAttrAccessorDefinition(const Record &R, raw_ostream &OS) { |
1733 | std::vector<Record*> Accessors = R.getValueAsListOfDefs(FieldName: "Accessors" ); |
1734 | if (Accessors.empty()) |
1735 | return; |
1736 | |
1737 | const std::vector<FlattenedSpelling> SpellingList = GetFlattenedSpellings(Attr: R); |
1738 | assert(!SpellingList.empty() && |
1739 | "Attribute with empty spelling list can't have accessors!" ); |
1740 | for (const auto *Accessor : Accessors) { |
1741 | const StringRef Name = Accessor->getValueAsString(FieldName: "Name" ); |
1742 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr: *Accessor); |
1743 | |
1744 | OS << " bool " << Name |
1745 | << "() const { return getAttributeSpellingListIndex() == " ; |
1746 | for (unsigned Index = 0; Index < Spellings.size(); ++Index) { |
1747 | OS << getSpellingListIndex(SpellingList, Spelling: Spellings[Index]); |
1748 | if (Index != Spellings.size() - 1) |
1749 | OS << " ||\n getAttributeSpellingListIndex() == " ; |
1750 | else |
1751 | OS << "; }\n" ; |
1752 | } |
1753 | } |
1754 | } |
1755 | |
1756 | static bool |
1757 | SpellingNamesAreCommon(const std::vector<FlattenedSpelling>& Spellings) { |
1758 | assert(!Spellings.empty() && "An empty list of spellings was provided" ); |
1759 | std::string FirstName = |
1760 | std::string(NormalizeNameForSpellingComparison(Name: Spellings.front().name())); |
1761 | for (const auto &Spelling : llvm::drop_begin(RangeOrContainer: Spellings)) { |
1762 | std::string Name = |
1763 | std::string(NormalizeNameForSpellingComparison(Name: Spelling.name())); |
1764 | if (Name != FirstName) |
1765 | return false; |
1766 | } |
1767 | return true; |
1768 | } |
1769 | |
1770 | typedef std::map<unsigned, std::string> SemanticSpellingMap; |
1771 | static std::string |
1772 | CreateSemanticSpellings(const std::vector<FlattenedSpelling> &Spellings, |
1773 | SemanticSpellingMap &Map) { |
1774 | // The enumerants are automatically generated based on the variety, |
1775 | // namespace (if present) and name for each attribute spelling. However, |
1776 | // care is taken to avoid trampling on the reserved namespace due to |
1777 | // underscores. |
1778 | std::string Ret(" enum Spelling {\n" ); |
1779 | std::set<std::string> Uniques; |
1780 | unsigned Idx = 0; |
1781 | |
1782 | // If we have a need to have this many spellings we likely need to add an |
1783 | // extra bit to the SpellingIndex in AttributeCommonInfo, then increase the |
1784 | // value of SpellingNotCalculated there and here. |
1785 | assert(Spellings.size() < 15 && |
1786 | "Too many spellings, would step on SpellingNotCalculated in " |
1787 | "AttributeCommonInfo" ); |
1788 | for (auto I = Spellings.begin(), E = Spellings.end(); I != E; ++I, ++Idx) { |
1789 | const FlattenedSpelling &S = *I; |
1790 | const std::string &Variety = S.variety(); |
1791 | const std::string &Spelling = S.name(); |
1792 | const std::string &Namespace = S.nameSpace(); |
1793 | std::string EnumName; |
1794 | |
1795 | EnumName += (Variety + "_" ); |
1796 | if (!Namespace.empty()) |
1797 | EnumName += (NormalizeNameForSpellingComparison(Name: Namespace).str() + |
1798 | "_" ); |
1799 | EnumName += NormalizeNameForSpellingComparison(Name: Spelling); |
1800 | |
1801 | // Even if the name is not unique, this spelling index corresponds to a |
1802 | // particular enumerant name that we've calculated. |
1803 | Map[Idx] = EnumName; |
1804 | |
1805 | // Since we have been stripping underscores to avoid trampling on the |
1806 | // reserved namespace, we may have inadvertently created duplicate |
1807 | // enumerant names. These duplicates are not considered part of the |
1808 | // semantic spelling, and can be elided. |
1809 | if (Uniques.find(x: EnumName) != Uniques.end()) |
1810 | continue; |
1811 | |
1812 | Uniques.insert(x: EnumName); |
1813 | if (I != Spellings.begin()) |
1814 | Ret += ",\n" ; |
1815 | // Duplicate spellings are not considered part of the semantic spelling |
1816 | // enumeration, but the spelling index and semantic spelling values are |
1817 | // meant to be equivalent, so we must specify a concrete value for each |
1818 | // enumerator. |
1819 | Ret += " " + EnumName + " = " + llvm::utostr(X: Idx); |
1820 | } |
1821 | Ret += ",\n SpellingNotCalculated = 15\n" ; |
1822 | Ret += "\n };\n\n" ; |
1823 | return Ret; |
1824 | } |
1825 | |
1826 | void WriteSemanticSpellingSwitch(const std::string &VarName, |
1827 | const SemanticSpellingMap &Map, |
1828 | raw_ostream &OS) { |
1829 | OS << " switch (" << VarName << ") {\n default: " |
1830 | << "llvm_unreachable(\"Unknown spelling list index\");\n" ; |
1831 | for (const auto &I : Map) |
1832 | OS << " case " << I.first << ": return " << I.second << ";\n" ; |
1833 | OS << " }\n" ; |
1834 | } |
1835 | |
1836 | // Note: these values need to match the values used by LateAttrParseKind in |
1837 | // `Attr.td` |
1838 | enum class LateAttrParseKind { Never = 0, Standard = 1, ExperimentalExt = 2 }; |
1839 | |
1840 | static LateAttrParseKind getLateAttrParseKind(const Record *Attr) { |
1841 | // This function basically does |
1842 | // `Attr->getValueAsDef("LateParsed")->getValueAsInt("Kind")` but does a bunch |
1843 | // of sanity checking to ensure that `LateAttrParseMode` in `Attr.td` is in |
1844 | // sync with the `LateAttrParseKind` enum in this source file. |
1845 | |
1846 | static constexpr StringRef LateParsedStr = "LateParsed" ; |
1847 | static constexpr StringRef LateAttrParseKindStr = "LateAttrParseKind" ; |
1848 | static constexpr StringRef KindFieldStr = "Kind" ; |
1849 | |
1850 | auto *LAPK = Attr->getValueAsDef(FieldName: LateParsedStr); |
1851 | |
1852 | // Typecheck the `LateParsed` field. |
1853 | SmallVector<Record *, 1> SuperClasses; |
1854 | LAPK->getDirectSuperClasses(Classes&: SuperClasses); |
1855 | if (SuperClasses.size() != 1) |
1856 | PrintFatalError(Rec: Attr, Msg: "Field `" + llvm::Twine(LateParsedStr) + |
1857 | "`should only have one super class" ); |
1858 | |
1859 | if (SuperClasses[0]->getName() != LateAttrParseKindStr) |
1860 | PrintFatalError(Rec: Attr, Msg: "Field `" + llvm::Twine(LateParsedStr) + |
1861 | "`should only have type `" + |
1862 | llvm::Twine(LateAttrParseKindStr) + |
1863 | "` but found type `" + |
1864 | SuperClasses[0]->getName() + "`" ); |
1865 | |
1866 | // Get Kind and verify the enum name matches the name in `Attr.td`. |
1867 | unsigned Kind = LAPK->getValueAsInt(FieldName: KindFieldStr); |
1868 | switch (LateAttrParseKind(Kind)) { |
1869 | #define CASE(X) \ |
1870 | case LateAttrParseKind::X: \ |
1871 | if (LAPK->getName().compare("LateAttrParse" #X) != 0) { \ |
1872 | PrintFatalError(Attr, \ |
1873 | "Field `" + llvm::Twine(LateParsedStr) + "` set to `" + \ |
1874 | LAPK->getName() + \ |
1875 | "` but this converts to `LateAttrParseKind::" + \ |
1876 | llvm::Twine(#X) + "`"); \ |
1877 | } \ |
1878 | return LateAttrParseKind::X; |
1879 | |
1880 | CASE(Never) |
1881 | CASE(Standard) |
1882 | CASE(ExperimentalExt) |
1883 | #undef CASE |
1884 | } |
1885 | |
1886 | // The Kind value is completely invalid |
1887 | auto KindValueStr = llvm::utostr(X: Kind); |
1888 | PrintFatalError(Rec: Attr, Msg: "Field `" + llvm::Twine(LateParsedStr) + "` set to `" + |
1889 | LAPK->getName() + "` has unexpected `" + |
1890 | llvm::Twine(KindFieldStr) + "` value of " + |
1891 | KindValueStr); |
1892 | } |
1893 | |
1894 | // Emits the LateParsed property for attributes. |
1895 | static void emitClangAttrLateParsedListImpl(RecordKeeper &Records, |
1896 | raw_ostream &OS, |
1897 | LateAttrParseKind LateParseMode) { |
1898 | std::vector<Record *> Attrs = Records.getAllDerivedDefinitions(ClassName: "Attr" ); |
1899 | |
1900 | for (const auto *Attr : Attrs) { |
1901 | if (LateAttrParseKind LateParsed = getLateAttrParseKind(Attr); |
1902 | LateParsed != LateParseMode) |
1903 | continue; |
1904 | |
1905 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr: *Attr); |
1906 | |
1907 | // FIXME: Handle non-GNU attributes |
1908 | for (const auto &I : Spellings) { |
1909 | if (I.variety() != "GNU" ) |
1910 | continue; |
1911 | OS << ".Case(\"" << I.name() << "\", 1)\n" ; |
1912 | } |
1913 | } |
1914 | } |
1915 | |
1916 | static void emitClangAttrLateParsedList(RecordKeeper &Records, |
1917 | raw_ostream &OS) { |
1918 | OS << "#if defined(CLANG_ATTR_LATE_PARSED_LIST)\n" ; |
1919 | emitClangAttrLateParsedListImpl(Records, OS, LateParseMode: LateAttrParseKind::Standard); |
1920 | OS << "#endif // CLANG_ATTR_LATE_PARSED_LIST\n\n" ; |
1921 | } |
1922 | |
1923 | static void emitClangAttrLateParsedExperimentalList(RecordKeeper &Records, |
1924 | raw_ostream &OS) { |
1925 | OS << "#if defined(CLANG_ATTR_LATE_PARSED_EXPERIMENTAL_EXT_LIST)\n" ; |
1926 | emitClangAttrLateParsedListImpl(Records, OS, |
1927 | LateParseMode: LateAttrParseKind::ExperimentalExt); |
1928 | OS << "#endif // CLANG_ATTR_LATE_PARSED_EXPERIMENTAL_EXT_LIST\n\n" ; |
1929 | } |
1930 | |
1931 | static bool hasGNUorCXX11Spelling(const Record &Attribute) { |
1932 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr: Attribute); |
1933 | for (const auto &I : Spellings) { |
1934 | if (I.variety() == "GNU" || I.variety() == "CXX11" ) |
1935 | return true; |
1936 | } |
1937 | return false; |
1938 | } |
1939 | |
1940 | namespace { |
1941 | |
1942 | struct AttributeSubjectMatchRule { |
1943 | const Record *MetaSubject; |
1944 | const Record *Constraint; |
1945 | |
1946 | AttributeSubjectMatchRule(const Record *MetaSubject, const Record *Constraint) |
1947 | : MetaSubject(MetaSubject), Constraint(Constraint) { |
1948 | assert(MetaSubject && "Missing subject" ); |
1949 | } |
1950 | |
1951 | bool isSubRule() const { return Constraint != nullptr; } |
1952 | |
1953 | std::vector<Record *> getSubjects() const { |
1954 | return (Constraint ? Constraint : MetaSubject) |
1955 | ->getValueAsListOfDefs(FieldName: "Subjects" ); |
1956 | } |
1957 | |
1958 | std::vector<Record *> getLangOpts() const { |
1959 | if (Constraint) { |
1960 | // Lookup the options in the sub-rule first, in case the sub-rule |
1961 | // overrides the rules options. |
1962 | std::vector<Record *> Opts = Constraint->getValueAsListOfDefs(FieldName: "LangOpts" ); |
1963 | if (!Opts.empty()) |
1964 | return Opts; |
1965 | } |
1966 | return MetaSubject->getValueAsListOfDefs(FieldName: "LangOpts" ); |
1967 | } |
1968 | |
1969 | // Abstract rules are used only for sub-rules |
1970 | bool isAbstractRule() const { return getSubjects().empty(); } |
1971 | |
1972 | StringRef getName() const { |
1973 | return (Constraint ? Constraint : MetaSubject)->getValueAsString(FieldName: "Name" ); |
1974 | } |
1975 | |
1976 | bool isNegatedSubRule() const { |
1977 | assert(isSubRule() && "Not a sub-rule" ); |
1978 | return Constraint->getValueAsBit(FieldName: "Negated" ); |
1979 | } |
1980 | |
1981 | std::string getSpelling() const { |
1982 | std::string Result = std::string(MetaSubject->getValueAsString(FieldName: "Name" )); |
1983 | if (isSubRule()) { |
1984 | Result += '('; |
1985 | if (isNegatedSubRule()) |
1986 | Result += "unless(" ; |
1987 | Result += getName(); |
1988 | if (isNegatedSubRule()) |
1989 | Result += ')'; |
1990 | Result += ')'; |
1991 | } |
1992 | return Result; |
1993 | } |
1994 | |
1995 | std::string getEnumValueName() const { |
1996 | SmallString<128> Result; |
1997 | Result += "SubjectMatchRule_" ; |
1998 | Result += MetaSubject->getValueAsString(FieldName: "Name" ); |
1999 | if (isSubRule()) { |
2000 | Result += "_" ; |
2001 | if (isNegatedSubRule()) |
2002 | Result += "not_" ; |
2003 | Result += Constraint->getValueAsString(FieldName: "Name" ); |
2004 | } |
2005 | if (isAbstractRule()) |
2006 | Result += "_abstract" ; |
2007 | return std::string(Result); |
2008 | } |
2009 | |
2010 | std::string getEnumValue() const { return "attr::" + getEnumValueName(); } |
2011 | |
2012 | static const char *EnumName; |
2013 | }; |
2014 | |
2015 | const char *AttributeSubjectMatchRule::EnumName = "attr::SubjectMatchRule" ; |
2016 | |
2017 | struct PragmaClangAttributeSupport { |
2018 | std::vector<AttributeSubjectMatchRule> Rules; |
2019 | |
2020 | class RuleOrAggregateRuleSet { |
2021 | std::vector<AttributeSubjectMatchRule> Rules; |
2022 | bool IsRule; |
2023 | RuleOrAggregateRuleSet(ArrayRef<AttributeSubjectMatchRule> Rules, |
2024 | bool IsRule) |
2025 | : Rules(Rules), IsRule(IsRule) {} |
2026 | |
2027 | public: |
2028 | bool isRule() const { return IsRule; } |
2029 | |
2030 | const AttributeSubjectMatchRule &getRule() const { |
2031 | assert(IsRule && "not a rule!" ); |
2032 | return Rules[0]; |
2033 | } |
2034 | |
2035 | ArrayRef<AttributeSubjectMatchRule> getAggregateRuleSet() const { |
2036 | return Rules; |
2037 | } |
2038 | |
2039 | static RuleOrAggregateRuleSet |
2040 | getRule(const AttributeSubjectMatchRule &Rule) { |
2041 | return RuleOrAggregateRuleSet(Rule, /*IsRule=*/true); |
2042 | } |
2043 | static RuleOrAggregateRuleSet |
2044 | getAggregateRuleSet(ArrayRef<AttributeSubjectMatchRule> Rules) { |
2045 | return RuleOrAggregateRuleSet(Rules, /*IsRule=*/false); |
2046 | } |
2047 | }; |
2048 | llvm::DenseMap<const Record *, RuleOrAggregateRuleSet> SubjectsToRules; |
2049 | |
2050 | PragmaClangAttributeSupport(RecordKeeper &Records); |
2051 | |
2052 | bool isAttributedSupported(const Record &Attribute); |
2053 | |
2054 | void emitMatchRuleList(raw_ostream &OS); |
2055 | |
2056 | void generateStrictConformsTo(const Record &Attr, raw_ostream &OS); |
2057 | |
2058 | void generateParsingHelpers(raw_ostream &OS); |
2059 | }; |
2060 | |
2061 | } // end anonymous namespace |
2062 | |
2063 | static bool isSupportedPragmaClangAttributeSubject(const Record &Subject) { |
2064 | // FIXME: #pragma clang attribute does not currently support statement |
2065 | // attributes, so test whether the subject is one that appertains to a |
2066 | // declaration node. However, it may be reasonable for support for statement |
2067 | // attributes to be added. |
2068 | if (Subject.isSubClassOf(Name: "DeclNode" ) || Subject.isSubClassOf(Name: "DeclBase" ) || |
2069 | Subject.getName() == "DeclBase" ) |
2070 | return true; |
2071 | |
2072 | if (Subject.isSubClassOf(Name: "SubsetSubject" )) |
2073 | return isSupportedPragmaClangAttributeSubject( |
2074 | Subject: *Subject.getValueAsDef(FieldName: "Base" )); |
2075 | |
2076 | return false; |
2077 | } |
2078 | |
2079 | static bool doesDeclDeriveFrom(const Record *D, const Record *Base) { |
2080 | const Record *CurrentBase = D->getValueAsOptionalDef(BaseFieldName); |
2081 | if (!CurrentBase) |
2082 | return false; |
2083 | if (CurrentBase == Base) |
2084 | return true; |
2085 | return doesDeclDeriveFrom(D: CurrentBase, Base); |
2086 | } |
2087 | |
2088 | PragmaClangAttributeSupport::PragmaClangAttributeSupport( |
2089 | RecordKeeper &Records) { |
2090 | std::vector<Record *> MetaSubjects = |
2091 | Records.getAllDerivedDefinitions(ClassName: "AttrSubjectMatcherRule" ); |
2092 | auto MapFromSubjectsToRules = [this](const Record *SubjectContainer, |
2093 | const Record *MetaSubject, |
2094 | const Record *Constraint) { |
2095 | Rules.emplace_back(args&: MetaSubject, args&: Constraint); |
2096 | std::vector<Record *> ApplicableSubjects = |
2097 | SubjectContainer->getValueAsListOfDefs(FieldName: "Subjects" ); |
2098 | for (const auto *Subject : ApplicableSubjects) { |
2099 | bool Inserted = |
2100 | SubjectsToRules |
2101 | .try_emplace(Key: Subject, Args: RuleOrAggregateRuleSet::getRule( |
2102 | Rule: AttributeSubjectMatchRule(MetaSubject, |
2103 | Constraint))) |
2104 | .second; |
2105 | if (!Inserted) { |
2106 | PrintFatalError(Msg: "Attribute subject match rules should not represent" |
2107 | "same attribute subjects." ); |
2108 | } |
2109 | } |
2110 | }; |
2111 | for (const auto *MetaSubject : MetaSubjects) { |
2112 | MapFromSubjectsToRules(MetaSubject, MetaSubject, /*Constraints=*/nullptr); |
2113 | std::vector<Record *> Constraints = |
2114 | MetaSubject->getValueAsListOfDefs(FieldName: "Constraints" ); |
2115 | for (const auto *Constraint : Constraints) |
2116 | MapFromSubjectsToRules(Constraint, MetaSubject, Constraint); |
2117 | } |
2118 | |
2119 | std::vector<Record *> Aggregates = |
2120 | Records.getAllDerivedDefinitions(ClassName: "AttrSubjectMatcherAggregateRule" ); |
2121 | std::vector<Record *> DeclNodes = |
2122 | Records.getAllDerivedDefinitions(DeclNodeClassName); |
2123 | for (const auto *Aggregate : Aggregates) { |
2124 | Record *SubjectDecl = Aggregate->getValueAsDef(FieldName: "Subject" ); |
2125 | |
2126 | // Gather sub-classes of the aggregate subject that act as attribute |
2127 | // subject rules. |
2128 | std::vector<AttributeSubjectMatchRule> Rules; |
2129 | for (const auto *D : DeclNodes) { |
2130 | if (doesDeclDeriveFrom(D, Base: SubjectDecl)) { |
2131 | auto It = SubjectsToRules.find(Val: D); |
2132 | if (It == SubjectsToRules.end()) |
2133 | continue; |
2134 | if (!It->second.isRule() || It->second.getRule().isSubRule()) |
2135 | continue; // Assume that the rule will be included as well. |
2136 | Rules.push_back(x: It->second.getRule()); |
2137 | } |
2138 | } |
2139 | |
2140 | bool Inserted = |
2141 | SubjectsToRules |
2142 | .try_emplace(Key: SubjectDecl, |
2143 | Args: RuleOrAggregateRuleSet::getAggregateRuleSet(Rules)) |
2144 | .second; |
2145 | if (!Inserted) { |
2146 | PrintFatalError(Msg: "Attribute subject match rules should not represent" |
2147 | "same attribute subjects." ); |
2148 | } |
2149 | } |
2150 | } |
2151 | |
2152 | static PragmaClangAttributeSupport & |
2153 | getPragmaAttributeSupport(RecordKeeper &Records) { |
2154 | static PragmaClangAttributeSupport Instance(Records); |
2155 | return Instance; |
2156 | } |
2157 | |
2158 | void PragmaClangAttributeSupport::emitMatchRuleList(raw_ostream &OS) { |
2159 | OS << "#ifndef ATTR_MATCH_SUB_RULE\n" ; |
2160 | OS << "#define ATTR_MATCH_SUB_RULE(Value, Spelling, IsAbstract, Parent, " |
2161 | "IsNegated) " |
2162 | << "ATTR_MATCH_RULE(Value, Spelling, IsAbstract)\n" ; |
2163 | OS << "#endif\n" ; |
2164 | for (const auto &Rule : Rules) { |
2165 | OS << (Rule.isSubRule() ? "ATTR_MATCH_SUB_RULE" : "ATTR_MATCH_RULE" ) << '('; |
2166 | OS << Rule.getEnumValueName() << ", \"" << Rule.getSpelling() << "\", " |
2167 | << Rule.isAbstractRule(); |
2168 | if (Rule.isSubRule()) |
2169 | OS << ", " |
2170 | << AttributeSubjectMatchRule(Rule.MetaSubject, nullptr).getEnumValue() |
2171 | << ", " << Rule.isNegatedSubRule(); |
2172 | OS << ")\n" ; |
2173 | } |
2174 | OS << "#undef ATTR_MATCH_SUB_RULE\n" ; |
2175 | } |
2176 | |
2177 | bool PragmaClangAttributeSupport::isAttributedSupported( |
2178 | const Record &Attribute) { |
2179 | // If the attribute explicitly specified whether to support #pragma clang |
2180 | // attribute, use that setting. |
2181 | bool Unset; |
2182 | bool SpecifiedResult = |
2183 | Attribute.getValueAsBitOrUnset(FieldName: "PragmaAttributeSupport" , Unset); |
2184 | if (!Unset) |
2185 | return SpecifiedResult; |
2186 | |
2187 | // Opt-out rules: |
2188 | |
2189 | // An attribute requires delayed parsing (LateParsed is on). |
2190 | switch (getLateAttrParseKind(Attr: &Attribute)) { |
2191 | case LateAttrParseKind::Never: |
2192 | break; |
2193 | case LateAttrParseKind::Standard: |
2194 | return false; |
2195 | case LateAttrParseKind::ExperimentalExt: |
2196 | // This is only late parsed in certain parsing contexts when |
2197 | // `LangOpts.ExperimentalLateParseAttributes` is true. Information about the |
2198 | // parsing context and `LangOpts` is not available in this method so just |
2199 | // opt this attribute out. |
2200 | return false; |
2201 | } |
2202 | |
2203 | // An attribute has no GNU/CXX11 spelling |
2204 | if (!hasGNUorCXX11Spelling(Attribute)) |
2205 | return false; |
2206 | // An attribute subject list has a subject that isn't covered by one of the |
2207 | // subject match rules or has no subjects at all. |
2208 | if (Attribute.isValueUnset(FieldName: "Subjects" )) |
2209 | return false; |
2210 | const Record *SubjectObj = Attribute.getValueAsDef(FieldName: "Subjects" ); |
2211 | std::vector<Record *> Subjects = SubjectObj->getValueAsListOfDefs(FieldName: "Subjects" ); |
2212 | bool HasAtLeastOneValidSubject = false; |
2213 | for (const auto *Subject : Subjects) { |
2214 | if (!isSupportedPragmaClangAttributeSubject(Subject: *Subject)) |
2215 | continue; |
2216 | if (!SubjectsToRules.contains(Val: Subject)) |
2217 | return false; |
2218 | HasAtLeastOneValidSubject = true; |
2219 | } |
2220 | return HasAtLeastOneValidSubject; |
2221 | } |
2222 | |
2223 | static std::string GenerateTestExpression(ArrayRef<Record *> LangOpts) { |
2224 | std::string Test; |
2225 | |
2226 | for (auto *E : LangOpts) { |
2227 | if (!Test.empty()) |
2228 | Test += " || " ; |
2229 | |
2230 | const StringRef Code = E->getValueAsString(FieldName: "CustomCode" ); |
2231 | if (!Code.empty()) { |
2232 | Test += "(" ; |
2233 | Test += Code; |
2234 | Test += ")" ; |
2235 | if (!E->getValueAsString(FieldName: "Name" ).empty()) { |
2236 | PrintWarning( |
2237 | WarningLoc: E->getLoc(), |
2238 | Msg: "non-empty 'Name' field ignored because 'CustomCode' was supplied" ); |
2239 | } |
2240 | } else { |
2241 | Test += "LangOpts." ; |
2242 | Test += E->getValueAsString(FieldName: "Name" ); |
2243 | } |
2244 | } |
2245 | |
2246 | if (Test.empty()) |
2247 | return "true" ; |
2248 | |
2249 | return Test; |
2250 | } |
2251 | |
2252 | void |
2253 | PragmaClangAttributeSupport::generateStrictConformsTo(const Record &Attr, |
2254 | raw_ostream &OS) { |
2255 | if (!isAttributedSupported(Attribute: Attr) || Attr.isValueUnset(FieldName: "Subjects" )) |
2256 | return; |
2257 | // Generate a function that constructs a set of matching rules that describe |
2258 | // to which declarations the attribute should apply to. |
2259 | OS << "void getPragmaAttributeMatchRules(" |
2260 | << "llvm::SmallVectorImpl<std::pair<" |
2261 | << AttributeSubjectMatchRule::EnumName |
2262 | << ", bool>> &MatchRules, const LangOptions &LangOpts) const override {\n" ; |
2263 | const Record *SubjectObj = Attr.getValueAsDef(FieldName: "Subjects" ); |
2264 | std::vector<Record *> Subjects = SubjectObj->getValueAsListOfDefs(FieldName: "Subjects" ); |
2265 | for (const auto *Subject : Subjects) { |
2266 | if (!isSupportedPragmaClangAttributeSubject(Subject: *Subject)) |
2267 | continue; |
2268 | auto It = SubjectsToRules.find(Val: Subject); |
2269 | assert(It != SubjectsToRules.end() && |
2270 | "This attribute is unsupported by #pragma clang attribute" ); |
2271 | for (const auto &Rule : It->getSecond().getAggregateRuleSet()) { |
2272 | // The rule might be language specific, so only subtract it from the given |
2273 | // rules if the specific language options are specified. |
2274 | std::vector<Record *> LangOpts = Rule.getLangOpts(); |
2275 | OS << " MatchRules.push_back(std::make_pair(" << Rule.getEnumValue() |
2276 | << ", /*IsSupported=*/" << GenerateTestExpression(LangOpts) |
2277 | << "));\n" ; |
2278 | } |
2279 | } |
2280 | OS << "}\n\n" ; |
2281 | } |
2282 | |
2283 | void PragmaClangAttributeSupport::generateParsingHelpers(raw_ostream &OS) { |
2284 | // Generate routines that check the names of sub-rules. |
2285 | OS << "std::optional<attr::SubjectMatchRule> " |
2286 | "defaultIsAttributeSubjectMatchSubRuleFor(StringRef, bool) {\n" ; |
2287 | OS << " return std::nullopt;\n" ; |
2288 | OS << "}\n\n" ; |
2289 | |
2290 | llvm::MapVector<const Record *, std::vector<AttributeSubjectMatchRule>> |
2291 | SubMatchRules; |
2292 | for (const auto &Rule : Rules) { |
2293 | if (!Rule.isSubRule()) |
2294 | continue; |
2295 | SubMatchRules[Rule.MetaSubject].push_back(x: Rule); |
2296 | } |
2297 | |
2298 | for (const auto &SubMatchRule : SubMatchRules) { |
2299 | OS << "std::optional<attr::SubjectMatchRule> " |
2300 | "isAttributeSubjectMatchSubRuleFor_" |
2301 | << SubMatchRule.first->getValueAsString(FieldName: "Name" ) |
2302 | << "(StringRef Name, bool IsUnless) {\n" ; |
2303 | OS << " if (IsUnless)\n" ; |
2304 | OS << " return " |
2305 | "llvm::StringSwitch<std::optional<attr::SubjectMatchRule>>(Name).\n" ; |
2306 | for (const auto &Rule : SubMatchRule.second) { |
2307 | if (Rule.isNegatedSubRule()) |
2308 | OS << " Case(\"" << Rule.getName() << "\", " << Rule.getEnumValue() |
2309 | << ").\n" ; |
2310 | } |
2311 | OS << " Default(std::nullopt);\n" ; |
2312 | OS << " return " |
2313 | "llvm::StringSwitch<std::optional<attr::SubjectMatchRule>>(Name).\n" ; |
2314 | for (const auto &Rule : SubMatchRule.second) { |
2315 | if (!Rule.isNegatedSubRule()) |
2316 | OS << " Case(\"" << Rule.getName() << "\", " << Rule.getEnumValue() |
2317 | << ").\n" ; |
2318 | } |
2319 | OS << " Default(std::nullopt);\n" ; |
2320 | OS << "}\n\n" ; |
2321 | } |
2322 | |
2323 | // Generate the function that checks for the top-level rules. |
2324 | OS << "std::pair<std::optional<attr::SubjectMatchRule>, " |
2325 | "std::optional<attr::SubjectMatchRule> (*)(StringRef, " |
2326 | "bool)> isAttributeSubjectMatchRule(StringRef Name) {\n" ; |
2327 | OS << " return " |
2328 | "llvm::StringSwitch<std::pair<std::optional<attr::SubjectMatchRule>, " |
2329 | "std::optional<attr::SubjectMatchRule> (*) (StringRef, " |
2330 | "bool)>>(Name).\n" ; |
2331 | for (const auto &Rule : Rules) { |
2332 | if (Rule.isSubRule()) |
2333 | continue; |
2334 | std::string SubRuleFunction; |
2335 | if (SubMatchRules.count(Key: Rule.MetaSubject)) |
2336 | SubRuleFunction = |
2337 | ("isAttributeSubjectMatchSubRuleFor_" + Rule.getName()).str(); |
2338 | else |
2339 | SubRuleFunction = "defaultIsAttributeSubjectMatchSubRuleFor" ; |
2340 | OS << " Case(\"" << Rule.getName() << "\", std::make_pair(" |
2341 | << Rule.getEnumValue() << ", " << SubRuleFunction << ")).\n" ; |
2342 | } |
2343 | OS << " Default(std::make_pair(std::nullopt, " |
2344 | "defaultIsAttributeSubjectMatchSubRuleFor));\n" ; |
2345 | OS << "}\n\n" ; |
2346 | |
2347 | // Generate the function that checks for the submatch rules. |
2348 | OS << "const char *validAttributeSubjectMatchSubRules(" |
2349 | << AttributeSubjectMatchRule::EnumName << " Rule) {\n" ; |
2350 | OS << " switch (Rule) {\n" ; |
2351 | for (const auto &SubMatchRule : SubMatchRules) { |
2352 | OS << " case " |
2353 | << AttributeSubjectMatchRule(SubMatchRule.first, nullptr).getEnumValue() |
2354 | << ":\n" ; |
2355 | OS << " return \"'" ; |
2356 | bool IsFirst = true; |
2357 | for (const auto &Rule : SubMatchRule.second) { |
2358 | if (!IsFirst) |
2359 | OS << ", '" ; |
2360 | IsFirst = false; |
2361 | if (Rule.isNegatedSubRule()) |
2362 | OS << "unless(" ; |
2363 | OS << Rule.getName(); |
2364 | if (Rule.isNegatedSubRule()) |
2365 | OS << ')'; |
2366 | OS << "'" ; |
2367 | } |
2368 | OS << "\";\n" ; |
2369 | } |
2370 | OS << " default: return nullptr;\n" ; |
2371 | OS << " }\n" ; |
2372 | OS << "}\n\n" ; |
2373 | } |
2374 | |
2375 | template <typename Fn> |
2376 | static void forEachUniqueSpelling(const Record &Attr, Fn &&F) { |
2377 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr); |
2378 | SmallDenseSet<StringRef, 8> Seen; |
2379 | for (const FlattenedSpelling &S : Spellings) { |
2380 | if (Seen.insert(V: S.name()).second) |
2381 | F(S); |
2382 | } |
2383 | } |
2384 | |
2385 | static bool isTypeArgument(const Record *Arg) { |
2386 | return !Arg->getSuperClasses().empty() && |
2387 | Arg->getSuperClasses().back().first->getName() == "TypeArgument" ; |
2388 | } |
2389 | |
2390 | /// Emits the first-argument-is-type property for attributes. |
2391 | static void emitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) { |
2392 | OS << "#if defined(CLANG_ATTR_TYPE_ARG_LIST)\n" ; |
2393 | std::vector<Record *> Attrs = Records.getAllDerivedDefinitions(ClassName: "Attr" ); |
2394 | |
2395 | for (const auto *Attr : Attrs) { |
2396 | // Determine whether the first argument is a type. |
2397 | std::vector<Record *> Args = Attr->getValueAsListOfDefs(FieldName: "Args" ); |
2398 | if (Args.empty()) |
2399 | continue; |
2400 | |
2401 | if (!isTypeArgument(Arg: Args[0])) |
2402 | continue; |
2403 | |
2404 | // All these spellings take a single type argument. |
2405 | forEachUniqueSpelling(Attr: *Attr, F: [&](const FlattenedSpelling &S) { |
2406 | OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n" ; |
2407 | }); |
2408 | } |
2409 | OS << "#endif // CLANG_ATTR_TYPE_ARG_LIST\n\n" ; |
2410 | } |
2411 | |
2412 | /// Emits the parse-arguments-in-unevaluated-context property for |
2413 | /// attributes. |
2414 | static void emitClangAttrArgContextList(RecordKeeper &Records, raw_ostream &OS) { |
2415 | OS << "#if defined(CLANG_ATTR_ARG_CONTEXT_LIST)\n" ; |
2416 | ParsedAttrMap Attrs = getParsedAttrList(Records); |
2417 | for (const auto &I : Attrs) { |
2418 | const Record &Attr = *I.second; |
2419 | |
2420 | if (!Attr.getValueAsBit(FieldName: "ParseArgumentsAsUnevaluated" )) |
2421 | continue; |
2422 | |
2423 | // All these spellings take are parsed unevaluated. |
2424 | forEachUniqueSpelling(Attr, F: [&](const FlattenedSpelling &S) { |
2425 | OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n" ; |
2426 | }); |
2427 | } |
2428 | OS << "#endif // CLANG_ATTR_ARG_CONTEXT_LIST\n\n" ; |
2429 | } |
2430 | |
2431 | static bool isIdentifierArgument(const Record *Arg) { |
2432 | return !Arg->getSuperClasses().empty() && |
2433 | llvm::StringSwitch<bool>(Arg->getSuperClasses().back().first->getName()) |
2434 | .Case(S: "IdentifierArgument" , Value: true) |
2435 | .Case(S: "EnumArgument" , Value: true) |
2436 | .Case(S: "VariadicEnumArgument" , Value: true) |
2437 | .Default(Value: false); |
2438 | } |
2439 | |
2440 | static bool isVariadicIdentifierArgument(const Record *Arg) { |
2441 | return !Arg->getSuperClasses().empty() && |
2442 | llvm::StringSwitch<bool>( |
2443 | Arg->getSuperClasses().back().first->getName()) |
2444 | .Case(S: "VariadicIdentifierArgument" , Value: true) |
2445 | .Case(S: "VariadicParamOrParamIdxArgument" , Value: true) |
2446 | .Default(Value: false); |
2447 | } |
2448 | |
2449 | static bool isVariadicExprArgument(const Record *Arg) { |
2450 | return !Arg->getSuperClasses().empty() && |
2451 | llvm::StringSwitch<bool>( |
2452 | Arg->getSuperClasses().back().first->getName()) |
2453 | .Case(S: "VariadicExprArgument" , Value: true) |
2454 | .Default(Value: false); |
2455 | } |
2456 | |
2457 | static bool isStringLiteralArgument(const Record *Arg) { |
2458 | if (Arg->getSuperClasses().empty()) |
2459 | return false; |
2460 | StringRef ArgKind = Arg->getSuperClasses().back().first->getName(); |
2461 | if (ArgKind == "EnumArgument" ) |
2462 | return Arg->getValueAsBit(FieldName: "IsString" ); |
2463 | return ArgKind == "StringArgument" ; |
2464 | } |
2465 | |
2466 | static bool isVariadicStringLiteralArgument(const Record *Arg) { |
2467 | if (Arg->getSuperClasses().empty()) |
2468 | return false; |
2469 | StringRef ArgKind = Arg->getSuperClasses().back().first->getName(); |
2470 | if (ArgKind == "VariadicEnumArgument" ) |
2471 | return Arg->getValueAsBit(FieldName: "IsString" ); |
2472 | return ArgKind == "VariadicStringArgument" ; |
2473 | } |
2474 | |
2475 | static void emitClangAttrVariadicIdentifierArgList(RecordKeeper &Records, |
2476 | raw_ostream &OS) { |
2477 | OS << "#if defined(CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST)\n" ; |
2478 | std::vector<Record *> Attrs = Records.getAllDerivedDefinitions(ClassName: "Attr" ); |
2479 | for (const auto *A : Attrs) { |
2480 | // Determine whether the first argument is a variadic identifier. |
2481 | std::vector<Record *> Args = A->getValueAsListOfDefs(FieldName: "Args" ); |
2482 | if (Args.empty() || !isVariadicIdentifierArgument(Arg: Args[0])) |
2483 | continue; |
2484 | |
2485 | // All these spellings take an identifier argument. |
2486 | forEachUniqueSpelling(Attr: *A, F: [&](const FlattenedSpelling &S) { |
2487 | OS << ".Case(\"" << S.name() << "\", " |
2488 | << "true" |
2489 | << ")\n" ; |
2490 | }); |
2491 | } |
2492 | OS << "#endif // CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST\n\n" ; |
2493 | } |
2494 | |
2495 | static bool GenerateTargetSpecificAttrChecks(const Record *R, |
2496 | std::vector<StringRef> &Arches, |
2497 | std::string &Test, |
2498 | std::string *FnName); |
2499 | |
2500 | // Emits the list of arguments that should be parsed as unevaluated string |
2501 | // literals for each attribute. |
2502 | static void emitClangAttrUnevaluatedStringLiteralList(RecordKeeper &Records, |
2503 | raw_ostream &OS) { |
2504 | OS << "#if defined(CLANG_ATTR_STRING_LITERAL_ARG_LIST)\n" ; |
2505 | |
2506 | auto MakeMask = [](ArrayRef<Record *> Args) { |
2507 | uint32_t Bits = 0; |
2508 | assert(Args.size() <= 32 && "unsupported number of arguments in attribute" ); |
2509 | for (uint32_t N = 0; N < Args.size(); ++N) { |
2510 | Bits |= (isStringLiteralArgument(Arg: Args[N]) << N); |
2511 | // If we have a variadic string argument, set all the remaining bits to 1 |
2512 | if (isVariadicStringLiteralArgument(Arg: Args[N])) { |
2513 | Bits |= maskTrailingZeros<decltype(Bits)>(N); |
2514 | break; |
2515 | } |
2516 | } |
2517 | return Bits; |
2518 | }; |
2519 | |
2520 | auto AddMaskWithTargetCheck = [](const Record *Attr, uint32_t Mask, |
2521 | std::string &MaskStr) { |
2522 | const Record *T = Attr->getValueAsDef(FieldName: "Target" ); |
2523 | std::vector<StringRef> Arches = T->getValueAsListOfStrings(FieldName: "Arches" ); |
2524 | std::string Test; |
2525 | GenerateTargetSpecificAttrChecks(R: T, Arches, Test, FnName: nullptr); |
2526 | MaskStr.append(str: Test + " ? " + std::to_string(val: Mask) + " : " ); |
2527 | }; |
2528 | |
2529 | ParsedAttrMap Dupes; |
2530 | ParsedAttrMap Attrs = getParsedAttrList(Records, Dupes: &Dupes, /*SemaOnly=*/false); |
2531 | for (const auto &[AttrName, Attr] : Attrs) { |
2532 | std::string MaskStr; |
2533 | if (Attr->isSubClassOf(Name: "TargetSpecificAttr" ) && |
2534 | !Attr->isValueUnset(FieldName: "ParseKind" )) { |
2535 | if (uint32_t Mask = MakeMask(Attr->getValueAsListOfDefs(FieldName: "Args" ))) |
2536 | AddMaskWithTargetCheck(Attr, Mask, MaskStr); |
2537 | StringRef ParseKind = Attr->getValueAsString(FieldName: "ParseKind" ); |
2538 | for (const auto &[DupeParseKind, DupAttr] : Dupes) { |
2539 | if (DupeParseKind != ParseKind) |
2540 | continue; |
2541 | if (uint32_t Mask = MakeMask(DupAttr->getValueAsListOfDefs(FieldName: "Args" ))) |
2542 | AddMaskWithTargetCheck(DupAttr, Mask, MaskStr); |
2543 | } |
2544 | if (!MaskStr.empty()) |
2545 | MaskStr.append(s: "0" ); |
2546 | } else { |
2547 | if (uint32_t Mask = MakeMask(Attr->getValueAsListOfDefs(FieldName: "Args" ))) |
2548 | MaskStr = std::to_string(val: Mask); |
2549 | } |
2550 | |
2551 | if (MaskStr.empty()) |
2552 | continue; |
2553 | |
2554 | // All these spellings have at least one string literal has argument. |
2555 | forEachUniqueSpelling(Attr: *Attr, F: [&](const FlattenedSpelling &S) { |
2556 | OS << ".Case(\"" << S.name() << "\", " << MaskStr << ")\n" ; |
2557 | }); |
2558 | } |
2559 | OS << "#endif // CLANG_ATTR_STRING_LITERAL_ARG_LIST\n\n" ; |
2560 | } |
2561 | |
2562 | // Emits the first-argument-is-identifier property for attributes. |
2563 | static void emitClangAttrIdentifierArgList(RecordKeeper &Records, raw_ostream &OS) { |
2564 | OS << "#if defined(CLANG_ATTR_IDENTIFIER_ARG_LIST)\n" ; |
2565 | std::vector<Record*> Attrs = Records.getAllDerivedDefinitions(ClassName: "Attr" ); |
2566 | |
2567 | for (const auto *Attr : Attrs) { |
2568 | // Determine whether the first argument is an identifier. |
2569 | std::vector<Record *> Args = Attr->getValueAsListOfDefs(FieldName: "Args" ); |
2570 | if (Args.empty() || !isIdentifierArgument(Arg: Args[0])) |
2571 | continue; |
2572 | |
2573 | // All these spellings take an identifier argument. |
2574 | forEachUniqueSpelling(Attr: *Attr, F: [&](const FlattenedSpelling &S) { |
2575 | OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n" ; |
2576 | }); |
2577 | } |
2578 | OS << "#endif // CLANG_ATTR_IDENTIFIER_ARG_LIST\n\n" ; |
2579 | } |
2580 | |
2581 | // Emits the indexed-argument-is-identifier property for attributes. |
2582 | static void emitClangAttrStrictIdentifierArgAtIndexList(RecordKeeper &Records, |
2583 | raw_ostream &OS) { |
2584 | OS << "#if defined(CLANG_ATTR_STRICT_IDENTIFIER_ARG_AT_INDEX_LIST)\n" ; |
2585 | std::vector<Record *> Attrs = Records.getAllDerivedDefinitions(ClassName: "Attr" ); |
2586 | |
2587 | for (const auto *Attr : Attrs) { |
2588 | if (!Attr->getValueAsBit(FieldName: "StrictEnumParameters" )) |
2589 | continue; |
2590 | // Determine whether the first argument is an identifier. |
2591 | std::vector<Record *> Args = Attr->getValueAsListOfDefs(FieldName: "Args" ); |
2592 | uint64_t enumAtIndex = 0; |
2593 | for (size_t i = 0; i < Args.size(); i++) { |
2594 | enumAtIndex |= ((uint64_t)isIdentifierArgument(Arg: Args[0])) << i; |
2595 | } |
2596 | if (!enumAtIndex) |
2597 | continue; |
2598 | |
2599 | // All these spellings take an identifier argument. |
2600 | forEachUniqueSpelling(Attr: *Attr, F: [&](const FlattenedSpelling &S) { |
2601 | OS << ".Case(\"" << S.name() << "\", " << enumAtIndex << "ull)\n" ; |
2602 | }); |
2603 | } |
2604 | OS << "#endif // CLANG_ATTR_STRICT_IDENTIFIER_ARG_AT_INDEX_LIST\n\n" ; |
2605 | } |
2606 | |
2607 | static bool keywordThisIsaIdentifierInArgument(const Record *Arg) { |
2608 | return !Arg->getSuperClasses().empty() && |
2609 | llvm::StringSwitch<bool>( |
2610 | Arg->getSuperClasses().back().first->getName()) |
2611 | .Case(S: "VariadicParamOrParamIdxArgument" , Value: true) |
2612 | .Default(Value: false); |
2613 | } |
2614 | |
2615 | static void emitClangAttrThisIsaIdentifierArgList(RecordKeeper &Records, |
2616 | raw_ostream &OS) { |
2617 | OS << "#if defined(CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST)\n" ; |
2618 | std::vector<Record *> Attrs = Records.getAllDerivedDefinitions(ClassName: "Attr" ); |
2619 | for (const auto *A : Attrs) { |
2620 | // Determine whether the first argument is a variadic identifier. |
2621 | std::vector<Record *> Args = A->getValueAsListOfDefs(FieldName: "Args" ); |
2622 | if (Args.empty() || !keywordThisIsaIdentifierInArgument(Arg: Args[0])) |
2623 | continue; |
2624 | |
2625 | // All these spellings take an identifier argument. |
2626 | forEachUniqueSpelling(Attr: *A, F: [&](const FlattenedSpelling &S) { |
2627 | OS << ".Case(\"" << S.name() << "\", " |
2628 | << "true" |
2629 | << ")\n" ; |
2630 | }); |
2631 | } |
2632 | OS << "#endif // CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST\n\n" ; |
2633 | } |
2634 | |
2635 | static void emitClangAttrAcceptsExprPack(RecordKeeper &Records, |
2636 | raw_ostream &OS) { |
2637 | OS << "#if defined(CLANG_ATTR_ACCEPTS_EXPR_PACK)\n" ; |
2638 | ParsedAttrMap Attrs = getParsedAttrList(Records); |
2639 | for (const auto &I : Attrs) { |
2640 | const Record &Attr = *I.second; |
2641 | |
2642 | if (!Attr.getValueAsBit(FieldName: "AcceptsExprPack" )) |
2643 | continue; |
2644 | |
2645 | forEachUniqueSpelling(Attr, F: [&](const FlattenedSpelling &S) { |
2646 | OS << ".Case(\"" << S.name() << "\", true)\n" ; |
2647 | }); |
2648 | } |
2649 | OS << "#endif // CLANG_ATTR_ACCEPTS_EXPR_PACK\n\n" ; |
2650 | } |
2651 | |
2652 | static bool isRegularKeywordAttribute(const FlattenedSpelling &S) { |
2653 | return (S.variety() == "Keyword" && |
2654 | !S.getSpellingRecord().getValueAsBit(FieldName: "HasOwnParseRules" )); |
2655 | } |
2656 | |
2657 | static void emitFormInitializer(raw_ostream &OS, |
2658 | const FlattenedSpelling &Spelling, |
2659 | StringRef SpellingIndex) { |
2660 | bool IsAlignas = |
2661 | (Spelling.variety() == "Keyword" && Spelling.name() == "alignas" ); |
2662 | OS << "{AttributeCommonInfo::AS_" << Spelling.variety() << ", " |
2663 | << SpellingIndex << ", " << (IsAlignas ? "true" : "false" ) |
2664 | << " /*IsAlignas*/, " |
2665 | << (isRegularKeywordAttribute(S: Spelling) ? "true" : "false" ) |
2666 | << " /*IsRegularKeywordAttribute*/}" ; |
2667 | } |
2668 | |
2669 | static void emitAttributes(RecordKeeper &Records, raw_ostream &OS, |
2670 | bool ) { |
2671 | std::vector<Record*> Attrs = Records.getAllDerivedDefinitions(ClassName: "Attr" ); |
2672 | ParsedAttrMap AttrMap = getParsedAttrList(Records); |
2673 | |
2674 | // Helper to print the starting character of an attribute argument. If there |
2675 | // hasn't been an argument yet, it prints an opening parenthese; otherwise it |
2676 | // prints a comma. |
2677 | OS << "static inline void DelimitAttributeArgument(" |
2678 | << "raw_ostream& OS, bool& IsFirst) {\n" |
2679 | << " if (IsFirst) {\n" |
2680 | << " IsFirst = false;\n" |
2681 | << " OS << \"(\";\n" |
2682 | << " } else\n" |
2683 | << " OS << \", \";\n" |
2684 | << "}\n" ; |
2685 | |
2686 | for (const auto *Attr : Attrs) { |
2687 | const Record &R = *Attr; |
2688 | |
2689 | // FIXME: Currently, documentation is generated as-needed due to the fact |
2690 | // that there is no way to allow a generated project "reach into" the docs |
2691 | // directory (for instance, it may be an out-of-tree build). However, we want |
2692 | // to ensure that every attribute has a Documentation field, and produce an |
2693 | // error if it has been neglected. Otherwise, the on-demand generation which |
2694 | // happens server-side will fail. This code is ensuring that functionality, |
2695 | // even though this Emitter doesn't technically need the documentation. |
2696 | // When attribute documentation can be generated as part of the build |
2697 | // itself, this code can be removed. |
2698 | (void)R.getValueAsListOfDefs(FieldName: "Documentation" ); |
2699 | |
2700 | if (!R.getValueAsBit(FieldName: "ASTNode" )) |
2701 | continue; |
2702 | |
2703 | ArrayRef<std::pair<Record *, SMRange>> Supers = R.getSuperClasses(); |
2704 | assert(!Supers.empty() && "Forgot to specify a superclass for the attr" ); |
2705 | std::string SuperName; |
2706 | bool Inheritable = false; |
2707 | for (const auto &Super : llvm::reverse(C&: Supers)) { |
2708 | const Record *R = Super.first; |
2709 | if (R->getName() != "TargetSpecificAttr" && |
2710 | R->getName() != "DeclOrTypeAttr" && SuperName.empty()) |
2711 | SuperName = std::string(R->getName()); |
2712 | if (R->getName() == "InheritableAttr" ) |
2713 | Inheritable = true; |
2714 | } |
2715 | |
2716 | if (Header) |
2717 | OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n" ; |
2718 | else |
2719 | OS << "\n// " << R.getName() << "Attr implementation\n\n" ; |
2720 | |
2721 | std::vector<Record*> ArgRecords = R.getValueAsListOfDefs(FieldName: "Args" ); |
2722 | std::vector<std::unique_ptr<Argument>> Args; |
2723 | Args.reserve(n: ArgRecords.size()); |
2724 | |
2725 | bool AttrAcceptsExprPack = Attr->getValueAsBit(FieldName: "AcceptsExprPack" ); |
2726 | if (AttrAcceptsExprPack) { |
2727 | for (size_t I = 0; I < ArgRecords.size(); ++I) { |
2728 | const Record *ArgR = ArgRecords[I]; |
2729 | if (isIdentifierArgument(Arg: ArgR) || isVariadicIdentifierArgument(Arg: ArgR) || |
2730 | isTypeArgument(Arg: ArgR)) |
2731 | PrintFatalError(ErrorLoc: Attr->getLoc(), |
2732 | Msg: "Attributes accepting packs cannot also " |
2733 | "have identifier or type arguments." ); |
2734 | // When trying to determine if value-dependent expressions can populate |
2735 | // the attribute without prior instantiation, the decision is made based |
2736 | // on the assumption that only the last argument is ever variadic. |
2737 | if (I < (ArgRecords.size() - 1) && isVariadicExprArgument(Arg: ArgR)) |
2738 | PrintFatalError(ErrorLoc: Attr->getLoc(), |
2739 | Msg: "Attributes accepting packs can only have the last " |
2740 | "argument be variadic." ); |
2741 | } |
2742 | } |
2743 | |
2744 | bool HasOptArg = false; |
2745 | bool HasFakeArg = false; |
2746 | for (const auto *ArgRecord : ArgRecords) { |
2747 | Args.emplace_back(args: createArgument(Arg: *ArgRecord, Attr: R.getName())); |
2748 | if (Header) { |
2749 | Args.back()->writeDeclarations(OS); |
2750 | OS << "\n\n" ; |
2751 | } |
2752 | |
2753 | // For these purposes, fake takes priority over optional. |
2754 | if (Args.back()->isFake()) { |
2755 | HasFakeArg = true; |
2756 | } else if (Args.back()->isOptional()) { |
2757 | HasOptArg = true; |
2758 | } |
2759 | } |
2760 | |
2761 | std::unique_ptr<VariadicExprArgument> DelayedArgs = nullptr; |
2762 | if (AttrAcceptsExprPack) { |
2763 | DelayedArgs = |
2764 | std::make_unique<VariadicExprArgument>(args: "DelayedArgs" , args: R.getName()); |
2765 | if (Header) { |
2766 | DelayedArgs->writeDeclarations(OS); |
2767 | OS << "\n\n" ; |
2768 | } |
2769 | } |
2770 | |
2771 | if (Header) |
2772 | OS << "public:\n" ; |
2773 | |
2774 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr: R); |
2775 | |
2776 | // If there are zero or one spellings, all spelling-related functionality |
2777 | // can be elided. If all of the spellings share the same name, the spelling |
2778 | // functionality can also be elided. |
2779 | bool ElideSpelling = (Spellings.size() <= 1) || |
2780 | SpellingNamesAreCommon(Spellings); |
2781 | |
2782 | // This maps spelling index values to semantic Spelling enumerants. |
2783 | SemanticSpellingMap SemanticToSyntacticMap; |
2784 | |
2785 | std::string SpellingEnum; |
2786 | if (Spellings.size() > 1) |
2787 | SpellingEnum = CreateSemanticSpellings(Spellings, Map&: SemanticToSyntacticMap); |
2788 | if (Header) |
2789 | OS << SpellingEnum; |
2790 | |
2791 | const auto &ParsedAttrSpellingItr = llvm::find_if( |
2792 | Range&: AttrMap, P: [R](const std::pair<std::string, const Record *> &P) { |
2793 | return &R == P.second; |
2794 | }); |
2795 | |
2796 | // Emit CreateImplicit factory methods. |
2797 | auto emitCreate = [&](bool Implicit, bool DelayedArgsOnly, bool emitFake) { |
2798 | if (Header) |
2799 | OS << " static " ; |
2800 | OS << R.getName() << "Attr *" ; |
2801 | if (!Header) |
2802 | OS << R.getName() << "Attr::" ; |
2803 | OS << "Create" ; |
2804 | if (Implicit) |
2805 | OS << "Implicit" ; |
2806 | if (DelayedArgsOnly) |
2807 | OS << "WithDelayedArgs" ; |
2808 | OS << "(" ; |
2809 | OS << "ASTContext &Ctx" ; |
2810 | if (!DelayedArgsOnly) { |
2811 | for (auto const &ai : Args) { |
2812 | if (ai->isFake() && !emitFake) |
2813 | continue; |
2814 | OS << ", " ; |
2815 | ai->writeCtorParameters(OS); |
2816 | } |
2817 | } else { |
2818 | OS << ", " ; |
2819 | DelayedArgs->writeCtorParameters(OS); |
2820 | } |
2821 | OS << ", const AttributeCommonInfo &CommonInfo" ; |
2822 | OS << ")" ; |
2823 | if (Header) { |
2824 | OS << ";\n" ; |
2825 | return; |
2826 | } |
2827 | |
2828 | OS << " {\n" ; |
2829 | OS << " auto *A = new (Ctx) " << R.getName(); |
2830 | OS << "Attr(Ctx, CommonInfo" ; |
2831 | |
2832 | if (!DelayedArgsOnly) { |
2833 | for (auto const &ai : Args) { |
2834 | if (ai->isFake() && !emitFake) |
2835 | continue; |
2836 | OS << ", " ; |
2837 | ai->writeImplicitCtorArgs(OS); |
2838 | } |
2839 | } |
2840 | OS << ");\n" ; |
2841 | if (Implicit) { |
2842 | OS << " A->setImplicit(true);\n" ; |
2843 | } |
2844 | if (Implicit || ElideSpelling) { |
2845 | OS << " if (!A->isAttributeSpellingListCalculated() && " |
2846 | "!A->getAttrName())\n" ; |
2847 | OS << " A->setAttributeSpellingListIndex(0);\n" ; |
2848 | } |
2849 | if (DelayedArgsOnly) { |
2850 | OS << " A->setDelayedArgs(Ctx, " ; |
2851 | DelayedArgs->writeImplicitCtorArgs(OS); |
2852 | OS << ");\n" ; |
2853 | } |
2854 | OS << " return A;\n}\n\n" ; |
2855 | }; |
2856 | |
2857 | auto emitCreateNoCI = [&](bool Implicit, bool DelayedArgsOnly, |
2858 | bool emitFake) { |
2859 | if (Header) |
2860 | OS << " static " ; |
2861 | OS << R.getName() << "Attr *" ; |
2862 | if (!Header) |
2863 | OS << R.getName() << "Attr::" ; |
2864 | OS << "Create" ; |
2865 | if (Implicit) |
2866 | OS << "Implicit" ; |
2867 | if (DelayedArgsOnly) |
2868 | OS << "WithDelayedArgs" ; |
2869 | OS << "(" ; |
2870 | OS << "ASTContext &Ctx" ; |
2871 | if (!DelayedArgsOnly) { |
2872 | for (auto const &ai : Args) { |
2873 | if (ai->isFake() && !emitFake) |
2874 | continue; |
2875 | OS << ", " ; |
2876 | ai->writeCtorParameters(OS); |
2877 | } |
2878 | } else { |
2879 | OS << ", " ; |
2880 | DelayedArgs->writeCtorParameters(OS); |
2881 | } |
2882 | OS << ", SourceRange Range" ; |
2883 | if (Header) |
2884 | OS << " = {}" ; |
2885 | if (Spellings.size() > 1) { |
2886 | OS << ", Spelling S" ; |
2887 | if (Header) |
2888 | OS << " = " << SemanticToSyntacticMap[0]; |
2889 | } |
2890 | OS << ")" ; |
2891 | if (Header) { |
2892 | OS << ";\n" ; |
2893 | return; |
2894 | } |
2895 | |
2896 | OS << " {\n" ; |
2897 | OS << " AttributeCommonInfo I(Range, " ; |
2898 | |
2899 | if (ParsedAttrSpellingItr != std::end(cont&: AttrMap)) |
2900 | OS << "AT_" << ParsedAttrSpellingItr->first; |
2901 | else |
2902 | OS << "NoSemaHandlerAttribute" ; |
2903 | |
2904 | if (Spellings.size() == 0) { |
2905 | OS << ", AttributeCommonInfo::Form::Implicit()" ; |
2906 | } else if (Spellings.size() == 1) { |
2907 | OS << ", " ; |
2908 | emitFormInitializer(OS, Spelling: Spellings[0], SpellingIndex: "0" ); |
2909 | } else { |
2910 | OS << ", [&]() {\n" ; |
2911 | OS << " switch (S) {\n" ; |
2912 | std::set<std::string> Uniques; |
2913 | unsigned Idx = 0; |
2914 | for (auto I = Spellings.begin(), E = Spellings.end(); I != E; |
2915 | ++I, ++Idx) { |
2916 | const FlattenedSpelling &S = *I; |
2917 | const auto &Name = SemanticToSyntacticMap[Idx]; |
2918 | if (Uniques.insert(x: Name).second) { |
2919 | OS << " case " << Name << ":\n" ; |
2920 | OS << " return AttributeCommonInfo::Form" ; |
2921 | emitFormInitializer(OS, Spelling: S, SpellingIndex: Name); |
2922 | OS << ";\n" ; |
2923 | } |
2924 | } |
2925 | OS << " default:\n" ; |
2926 | OS << " llvm_unreachable(\"Unknown attribute spelling!\");\n" |
2927 | << " return AttributeCommonInfo::Form" ; |
2928 | emitFormInitializer(OS, Spelling: Spellings[0], SpellingIndex: "0" ); |
2929 | OS << ";\n" |
2930 | << " }\n" |
2931 | << " }()" ; |
2932 | } |
2933 | |
2934 | OS << ");\n" ; |
2935 | OS << " return Create" ; |
2936 | if (Implicit) |
2937 | OS << "Implicit" ; |
2938 | if (DelayedArgsOnly) |
2939 | OS << "WithDelayedArgs" ; |
2940 | OS << "(Ctx" ; |
2941 | if (!DelayedArgsOnly) { |
2942 | for (auto const &ai : Args) { |
2943 | if (ai->isFake() && !emitFake) |
2944 | continue; |
2945 | OS << ", " ; |
2946 | ai->writeImplicitCtorArgs(OS); |
2947 | } |
2948 | } else { |
2949 | OS << ", " ; |
2950 | DelayedArgs->writeImplicitCtorArgs(OS); |
2951 | } |
2952 | OS << ", I);\n" ; |
2953 | OS << "}\n\n" ; |
2954 | }; |
2955 | |
2956 | auto emitCreates = [&](bool DelayedArgsOnly, bool emitFake) { |
2957 | emitCreate(true, DelayedArgsOnly, emitFake); |
2958 | emitCreate(false, DelayedArgsOnly, emitFake); |
2959 | emitCreateNoCI(true, DelayedArgsOnly, emitFake); |
2960 | emitCreateNoCI(false, DelayedArgsOnly, emitFake); |
2961 | }; |
2962 | |
2963 | if (Header) |
2964 | OS << " // Factory methods\n" ; |
2965 | |
2966 | // Emit a CreateImplicit that takes all the arguments. |
2967 | emitCreates(false, true); |
2968 | |
2969 | // Emit a CreateImplicit that takes all the non-fake arguments. |
2970 | if (HasFakeArg) |
2971 | emitCreates(false, false); |
2972 | |
2973 | // Emit a CreateWithDelayedArgs that takes only the dependent argument |
2974 | // expressions. |
2975 | if (DelayedArgs) |
2976 | emitCreates(true, false); |
2977 | |
2978 | // Emit constructors. |
2979 | auto emitCtor = [&](bool emitOpt, bool emitFake, bool emitNoArgs) { |
2980 | auto shouldEmitArg = [=](const std::unique_ptr<Argument> &arg) { |
2981 | if (emitNoArgs) |
2982 | return false; |
2983 | if (arg->isFake()) |
2984 | return emitFake; |
2985 | if (arg->isOptional()) |
2986 | return emitOpt; |
2987 | return true; |
2988 | }; |
2989 | if (Header) |
2990 | OS << " " ; |
2991 | else |
2992 | OS << R.getName() << "Attr::" ; |
2993 | OS << R.getName() |
2994 | << "Attr(ASTContext &Ctx, const AttributeCommonInfo &CommonInfo" ; |
2995 | OS << '\n'; |
2996 | for (auto const &ai : Args) { |
2997 | if (!shouldEmitArg(ai)) |
2998 | continue; |
2999 | OS << " , " ; |
3000 | ai->writeCtorParameters(OS); |
3001 | OS << "\n" ; |
3002 | } |
3003 | |
3004 | OS << " )" ; |
3005 | if (Header) { |
3006 | OS << ";\n" ; |
3007 | return; |
3008 | } |
3009 | OS << "\n : " << SuperName << "(Ctx, CommonInfo, " ; |
3010 | OS << "attr::" << R.getName() << ", " ; |
3011 | |
3012 | // Handle different late parsing modes. |
3013 | OS << "/*IsLateParsed=*/" ; |
3014 | switch (getLateAttrParseKind(Attr: &R)) { |
3015 | case LateAttrParseKind::Never: |
3016 | OS << "false" ; |
3017 | break; |
3018 | case LateAttrParseKind::ExperimentalExt: |
3019 | // Currently no clients need to know the distinction between `Standard` |
3020 | // and `ExperimentalExt` so treat `ExperimentalExt` just like |
3021 | // `Standard` for now. |
3022 | case LateAttrParseKind::Standard: |
3023 | // Note: This is misleading. `IsLateParsed` doesn't mean the |
3024 | // attribute was actually late parsed. Instead it means the attribute in |
3025 | // `Attr.td` is marked as being late parsed. Maybe it should be called |
3026 | // `IsLateParseable`? |
3027 | OS << "true" ; |
3028 | break; |
3029 | } |
3030 | |
3031 | if (Inheritable) { |
3032 | OS << ", " |
3033 | << (R.getValueAsBit(FieldName: "InheritEvenIfAlreadyPresent" ) ? "true" |
3034 | : "false" ); |
3035 | } |
3036 | OS << ")\n" ; |
3037 | |
3038 | for (auto const &ai : Args) { |
3039 | OS << " , " ; |
3040 | if (!shouldEmitArg(ai)) { |
3041 | ai->writeCtorDefaultInitializers(OS); |
3042 | } else { |
3043 | ai->writeCtorInitializers(OS); |
3044 | } |
3045 | OS << "\n" ; |
3046 | } |
3047 | if (DelayedArgs) { |
3048 | OS << " , " ; |
3049 | DelayedArgs->writeCtorDefaultInitializers(OS); |
3050 | OS << "\n" ; |
3051 | } |
3052 | |
3053 | OS << " {\n" ; |
3054 | |
3055 | for (auto const &ai : Args) { |
3056 | if (!shouldEmitArg(ai)) |
3057 | continue; |
3058 | ai->writeCtorBody(OS); |
3059 | } |
3060 | OS << "}\n\n" ; |
3061 | }; |
3062 | |
3063 | if (Header) |
3064 | OS << "\n // Constructors\n" ; |
3065 | |
3066 | // Emit a constructor that includes all the arguments. |
3067 | // This is necessary for cloning. |
3068 | emitCtor(true, true, false); |
3069 | |
3070 | // Emit a constructor that takes all the non-fake arguments. |
3071 | if (HasFakeArg) |
3072 | emitCtor(true, false, false); |
3073 | |
3074 | // Emit a constructor that takes all the non-fake, non-optional arguments. |
3075 | if (HasOptArg) |
3076 | emitCtor(false, false, false); |
3077 | |
3078 | // Emit constructors that takes no arguments if none already exists. |
3079 | // This is used for delaying arguments. |
3080 | bool HasRequiredArgs = |
3081 | llvm::count_if(Range&: Args, P: [=](const std::unique_ptr<Argument> &arg) { |
3082 | return !arg->isFake() && !arg->isOptional(); |
3083 | }); |
3084 | if (DelayedArgs && HasRequiredArgs) |
3085 | emitCtor(false, false, true); |
3086 | |
3087 | if (Header) { |
3088 | OS << '\n'; |
3089 | OS << " " << R.getName() << "Attr *clone(ASTContext &C) const;\n" ; |
3090 | OS << " void printPretty(raw_ostream &OS,\n" |
3091 | << " const PrintingPolicy &Policy) const;\n" ; |
3092 | OS << " const char *getSpelling() const;\n" ; |
3093 | } |
3094 | |
3095 | if (!ElideSpelling) { |
3096 | assert(!SemanticToSyntacticMap.empty() && "Empty semantic mapping list" ); |
3097 | if (Header) |
3098 | OS << " Spelling getSemanticSpelling() const;\n" ; |
3099 | else { |
3100 | OS << R.getName() << "Attr::Spelling " << R.getName() |
3101 | << "Attr::getSemanticSpelling() const {\n" ; |
3102 | WriteSemanticSpellingSwitch(VarName: "getAttributeSpellingListIndex()" , |
3103 | Map: SemanticToSyntacticMap, OS); |
3104 | OS << "}\n" ; |
3105 | } |
3106 | } |
3107 | |
3108 | if (Header) |
3109 | writeAttrAccessorDefinition(R, OS); |
3110 | |
3111 | for (auto const &ai : Args) { |
3112 | if (Header) { |
3113 | ai->writeAccessors(OS); |
3114 | } else { |
3115 | ai->writeAccessorDefinitions(OS); |
3116 | } |
3117 | OS << "\n\n" ; |
3118 | |
3119 | // Don't write conversion routines for fake arguments. |
3120 | if (ai->isFake()) continue; |
3121 | |
3122 | if (ai->isEnumArg()) |
3123 | static_cast<const EnumArgument *>(ai.get())->writeConversion(OS, |
3124 | Header); |
3125 | else if (ai->isVariadicEnumArg()) |
3126 | static_cast<const VariadicEnumArgument *>(ai.get())->writeConversion( |
3127 | OS, Header); |
3128 | } |
3129 | |
3130 | if (Header) { |
3131 | if (DelayedArgs) { |
3132 | DelayedArgs->writeAccessors(OS); |
3133 | DelayedArgs->writeSetter(OS); |
3134 | } |
3135 | |
3136 | OS << R.getValueAsString(FieldName: "AdditionalMembers" ); |
3137 | OS << "\n\n" ; |
3138 | |
3139 | OS << " static bool classof(const Attr *A) { return A->getKind() == " |
3140 | << "attr::" << R.getName() << "; }\n" ; |
3141 | |
3142 | OS << "};\n\n" ; |
3143 | } else { |
3144 | if (DelayedArgs) |
3145 | DelayedArgs->writeAccessorDefinitions(OS); |
3146 | |
3147 | OS << R.getName() << "Attr *" << R.getName() |
3148 | << "Attr::clone(ASTContext &C) const {\n" ; |
3149 | OS << " auto *A = new (C) " << R.getName() << "Attr(C, *this" ; |
3150 | for (auto const &ai : Args) { |
3151 | OS << ", " ; |
3152 | ai->writeCloneArgs(OS); |
3153 | } |
3154 | OS << ");\n" ; |
3155 | OS << " A->Inherited = Inherited;\n" ; |
3156 | OS << " A->IsPackExpansion = IsPackExpansion;\n" ; |
3157 | OS << " A->setImplicit(Implicit);\n" ; |
3158 | if (DelayedArgs) { |
3159 | OS << " A->setDelayedArgs(C, " ; |
3160 | DelayedArgs->writeCloneArgs(OS); |
3161 | OS << ");\n" ; |
3162 | } |
3163 | OS << " return A;\n}\n\n" ; |
3164 | |
3165 | writePrettyPrintFunction(R, Args, OS); |
3166 | writeGetSpellingFunction(R, OS); |
3167 | } |
3168 | } |
3169 | } |
3170 | // Emits the class definitions for attributes. |
3171 | void clang::EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) { |
3172 | emitSourceFileHeader(Desc: "Attribute classes' definitions" , OS, Record: Records); |
3173 | |
3174 | OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n" ; |
3175 | OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n" ; |
3176 | |
3177 | emitAttributes(Records, OS, Header: true); |
3178 | |
3179 | OS << "#endif // LLVM_CLANG_ATTR_CLASSES_INC\n" ; |
3180 | } |
3181 | |
3182 | // Emits the class method definitions for attributes. |
3183 | void clang::EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) { |
3184 | emitSourceFileHeader(Desc: "Attribute classes' member function definitions" , OS, |
3185 | Record: Records); |
3186 | |
3187 | emitAttributes(Records, OS, Header: false); |
3188 | |
3189 | std::vector<Record *> Attrs = Records.getAllDerivedDefinitions(ClassName: "Attr" ); |
3190 | |
3191 | // Instead of relying on virtual dispatch we just create a huge dispatch |
3192 | // switch. This is both smaller and faster than virtual functions. |
3193 | auto EmitFunc = [&](const char *Method) { |
3194 | OS << " switch (getKind()) {\n" ; |
3195 | for (const auto *Attr : Attrs) { |
3196 | const Record &R = *Attr; |
3197 | if (!R.getValueAsBit(FieldName: "ASTNode" )) |
3198 | continue; |
3199 | |
3200 | OS << " case attr::" << R.getName() << ":\n" ; |
3201 | OS << " return cast<" << R.getName() << "Attr>(this)->" << Method |
3202 | << ";\n" ; |
3203 | } |
3204 | OS << " }\n" ; |
3205 | OS << " llvm_unreachable(\"Unexpected attribute kind!\");\n" ; |
3206 | OS << "}\n\n" ; |
3207 | }; |
3208 | |
3209 | OS << "const char *Attr::getSpelling() const {\n" ; |
3210 | EmitFunc("getSpelling()" ); |
3211 | |
3212 | OS << "Attr *Attr::clone(ASTContext &C) const {\n" ; |
3213 | EmitFunc("clone(C)" ); |
3214 | |
3215 | OS << "void Attr::printPretty(raw_ostream &OS, " |
3216 | "const PrintingPolicy &Policy) const {\n" ; |
3217 | EmitFunc("printPretty(OS, Policy)" ); |
3218 | } |
3219 | |
3220 | static void emitAttrList(raw_ostream &OS, StringRef Class, |
3221 | const std::vector<Record*> &AttrList) { |
3222 | for (auto Cur : AttrList) { |
3223 | OS << Class << "(" << Cur->getName() << ")\n" ; |
3224 | } |
3225 | } |
3226 | |
3227 | // Determines if an attribute has a Pragma spelling. |
3228 | static bool AttrHasPragmaSpelling(const Record *R) { |
3229 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr: *R); |
3230 | return llvm::any_of(Range&: Spellings, P: [](const FlattenedSpelling &S) { |
3231 | return S.variety() == "Pragma" ; |
3232 | }); |
3233 | } |
3234 | |
3235 | namespace { |
3236 | |
3237 | struct AttrClassDescriptor { |
3238 | const char * const MacroName; |
3239 | const char * const TableGenName; |
3240 | }; |
3241 | |
3242 | } // end anonymous namespace |
3243 | |
3244 | static const AttrClassDescriptor AttrClassDescriptors[] = { |
3245 | { .MacroName: "ATTR" , .TableGenName: "Attr" }, |
3246 | { .MacroName: "TYPE_ATTR" , .TableGenName: "TypeAttr" }, |
3247 | { .MacroName: "STMT_ATTR" , .TableGenName: "StmtAttr" }, |
3248 | { .MacroName: "DECL_OR_STMT_ATTR" , .TableGenName: "DeclOrStmtAttr" }, |
3249 | { .MacroName: "INHERITABLE_ATTR" , .TableGenName: "InheritableAttr" }, |
3250 | { .MacroName: "DECL_OR_TYPE_ATTR" , .TableGenName: "DeclOrTypeAttr" }, |
3251 | { .MacroName: "INHERITABLE_PARAM_ATTR" , .TableGenName: "InheritableParamAttr" }, |
3252 | { .MacroName: "PARAMETER_ABI_ATTR" , .TableGenName: "ParameterABIAttr" }, |
3253 | { .MacroName: "HLSL_ANNOTATION_ATTR" , .TableGenName: "HLSLAnnotationAttr" } |
3254 | }; |
3255 | |
3256 | static void emitDefaultDefine(raw_ostream &OS, StringRef name, |
3257 | const char *superName) { |
3258 | OS << "#ifndef " << name << "\n" ; |
3259 | OS << "#define " << name << "(NAME) " ; |
3260 | if (superName) OS << superName << "(NAME)" ; |
3261 | OS << "\n#endif\n\n" ; |
3262 | } |
3263 | |
3264 | namespace { |
3265 | |
3266 | /// A class of attributes. |
3267 | struct AttrClass { |
3268 | const AttrClassDescriptor &Descriptor; |
3269 | Record *TheRecord; |
3270 | AttrClass *SuperClass = nullptr; |
3271 | std::vector<AttrClass*> SubClasses; |
3272 | std::vector<Record*> Attrs; |
3273 | |
3274 | AttrClass(const AttrClassDescriptor &Descriptor, Record *R) |
3275 | : Descriptor(Descriptor), TheRecord(R) {} |
3276 | |
3277 | void emitDefaultDefines(raw_ostream &OS) const { |
3278 | // Default the macro unless this is a root class (i.e. Attr). |
3279 | if (SuperClass) { |
3280 | emitDefaultDefine(OS, name: Descriptor.MacroName, |
3281 | superName: SuperClass->Descriptor.MacroName); |
3282 | } |
3283 | } |
3284 | |
3285 | void emitUndefs(raw_ostream &OS) const { |
3286 | OS << "#undef " << Descriptor.MacroName << "\n" ; |
3287 | } |
3288 | |
3289 | void emitAttrList(raw_ostream &OS) const { |
3290 | for (auto SubClass : SubClasses) { |
3291 | SubClass->emitAttrList(OS); |
3292 | } |
3293 | |
3294 | ::emitAttrList(OS, Class: Descriptor.MacroName, AttrList: Attrs); |
3295 | } |
3296 | |
3297 | void classifyAttrOnRoot(Record *Attr) { |
3298 | bool result = classifyAttr(Attr); |
3299 | assert(result && "failed to classify on root" ); (void) result; |
3300 | } |
3301 | |
3302 | void emitAttrRange(raw_ostream &OS) const { |
3303 | OS << "ATTR_RANGE(" << Descriptor.TableGenName |
3304 | << ", " << getFirstAttr()->getName() |
3305 | << ", " << getLastAttr()->getName() << ")\n" ; |
3306 | } |
3307 | |
3308 | private: |
3309 | bool classifyAttr(Record *Attr) { |
3310 | // Check all the subclasses. |
3311 | for (auto SubClass : SubClasses) { |
3312 | if (SubClass->classifyAttr(Attr)) |
3313 | return true; |
3314 | } |
3315 | |
3316 | // It's not more specific than this class, but it might still belong here. |
3317 | if (Attr->isSubClassOf(R: TheRecord)) { |
3318 | Attrs.push_back(x: Attr); |
3319 | return true; |
3320 | } |
3321 | |
3322 | return false; |
3323 | } |
3324 | |
3325 | Record *getFirstAttr() const { |
3326 | if (!SubClasses.empty()) |
3327 | return SubClasses.front()->getFirstAttr(); |
3328 | return Attrs.front(); |
3329 | } |
3330 | |
3331 | Record *getLastAttr() const { |
3332 | if (!Attrs.empty()) |
3333 | return Attrs.back(); |
3334 | return SubClasses.back()->getLastAttr(); |
3335 | } |
3336 | }; |
3337 | |
3338 | /// The entire hierarchy of attribute classes. |
3339 | class AttrClassHierarchy { |
3340 | std::vector<std::unique_ptr<AttrClass>> Classes; |
3341 | |
3342 | public: |
3343 | AttrClassHierarchy(RecordKeeper &Records) { |
3344 | // Find records for all the classes. |
3345 | for (auto &Descriptor : AttrClassDescriptors) { |
3346 | Record *ClassRecord = Records.getClass(Name: Descriptor.TableGenName); |
3347 | AttrClass *Class = new AttrClass(Descriptor, ClassRecord); |
3348 | Classes.emplace_back(args&: Class); |
3349 | } |
3350 | |
3351 | // Link up the hierarchy. |
3352 | for (auto &Class : Classes) { |
3353 | if (AttrClass *SuperClass = findSuperClass(R: Class->TheRecord)) { |
3354 | Class->SuperClass = SuperClass; |
3355 | SuperClass->SubClasses.push_back(x: Class.get()); |
3356 | } |
3357 | } |
3358 | |
3359 | #ifndef NDEBUG |
3360 | for (auto i = Classes.begin(), e = Classes.end(); i != e; ++i) { |
3361 | assert((i == Classes.begin()) == ((*i)->SuperClass == nullptr) && |
3362 | "only the first class should be a root class!" ); |
3363 | } |
3364 | #endif |
3365 | } |
3366 | |
3367 | void emitDefaultDefines(raw_ostream &OS) const { |
3368 | for (auto &Class : Classes) { |
3369 | Class->emitDefaultDefines(OS); |
3370 | } |
3371 | } |
3372 | |
3373 | void emitUndefs(raw_ostream &OS) const { |
3374 | for (auto &Class : Classes) { |
3375 | Class->emitUndefs(OS); |
3376 | } |
3377 | } |
3378 | |
3379 | void emitAttrLists(raw_ostream &OS) const { |
3380 | // Just start from the root class. |
3381 | Classes[0]->emitAttrList(OS); |
3382 | } |
3383 | |
3384 | void emitAttrRanges(raw_ostream &OS) const { |
3385 | for (auto &Class : Classes) |
3386 | Class->emitAttrRange(OS); |
3387 | } |
3388 | |
3389 | void classifyAttr(Record *Attr) { |
3390 | // Add the attribute to the root class. |
3391 | Classes[0]->classifyAttrOnRoot(Attr); |
3392 | } |
3393 | |
3394 | private: |
3395 | AttrClass *findClassByRecord(Record *R) const { |
3396 | for (auto &Class : Classes) { |
3397 | if (Class->TheRecord == R) |
3398 | return Class.get(); |
3399 | } |
3400 | return nullptr; |
3401 | } |
3402 | |
3403 | AttrClass *findSuperClass(Record *R) const { |
3404 | // TableGen flattens the superclass list, so we just need to walk it |
3405 | // in reverse. |
3406 | auto SuperClasses = R->getSuperClasses(); |
3407 | for (signed i = 0, e = SuperClasses.size(); i != e; ++i) { |
3408 | auto SuperClass = findClassByRecord(R: SuperClasses[e - i - 1].first); |
3409 | if (SuperClass) return SuperClass; |
3410 | } |
3411 | return nullptr; |
3412 | } |
3413 | }; |
3414 | |
3415 | } // end anonymous namespace |
3416 | |
3417 | namespace clang { |
3418 | |
3419 | // Emits the enumeration list for attributes. |
3420 | void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) { |
3421 | emitSourceFileHeader(Desc: "List of all attributes that Clang recognizes" , OS, |
3422 | Record: Records); |
3423 | |
3424 | AttrClassHierarchy Hierarchy(Records); |
3425 | |
3426 | // Add defaulting macro definitions. |
3427 | Hierarchy.emitDefaultDefines(OS); |
3428 | emitDefaultDefine(OS, name: "PRAGMA_SPELLING_ATTR" , superName: nullptr); |
3429 | |
3430 | std::vector<Record *> Attrs = Records.getAllDerivedDefinitions(ClassName: "Attr" ); |
3431 | std::vector<Record *> PragmaAttrs; |
3432 | for (auto *Attr : Attrs) { |
3433 | if (!Attr->getValueAsBit(FieldName: "ASTNode" )) |
3434 | continue; |
3435 | |
3436 | // Add the attribute to the ad-hoc groups. |
3437 | if (AttrHasPragmaSpelling(R: Attr)) |
3438 | PragmaAttrs.push_back(x: Attr); |
3439 | |
3440 | // Place it in the hierarchy. |
3441 | Hierarchy.classifyAttr(Attr); |
3442 | } |
3443 | |
3444 | // Emit the main attribute list. |
3445 | Hierarchy.emitAttrLists(OS); |
3446 | |
3447 | // Emit the ad hoc groups. |
3448 | emitAttrList(OS, Class: "PRAGMA_SPELLING_ATTR" , AttrList: PragmaAttrs); |
3449 | |
3450 | // Emit the attribute ranges. |
3451 | OS << "#ifdef ATTR_RANGE\n" ; |
3452 | Hierarchy.emitAttrRanges(OS); |
3453 | OS << "#undef ATTR_RANGE\n" ; |
3454 | OS << "#endif\n" ; |
3455 | |
3456 | Hierarchy.emitUndefs(OS); |
3457 | OS << "#undef PRAGMA_SPELLING_ATTR\n" ; |
3458 | } |
3459 | |
3460 | // Emits the enumeration list for attributes. |
3461 | void EmitClangAttrSubjectMatchRuleList(RecordKeeper &Records, raw_ostream &OS) { |
3462 | emitSourceFileHeader( |
3463 | Desc: "List of all attribute subject matching rules that Clang recognizes" , OS, |
3464 | Record: Records); |
3465 | PragmaClangAttributeSupport &PragmaAttributeSupport = |
3466 | getPragmaAttributeSupport(Records); |
3467 | emitDefaultDefine(OS, name: "ATTR_MATCH_RULE" , superName: nullptr); |
3468 | PragmaAttributeSupport.emitMatchRuleList(OS); |
3469 | OS << "#undef ATTR_MATCH_RULE\n" ; |
3470 | } |
3471 | |
3472 | // Emits the code to read an attribute from a precompiled header. |
3473 | void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) { |
3474 | emitSourceFileHeader(Desc: "Attribute deserialization code" , OS, Record: Records); |
3475 | |
3476 | Record *InhClass = Records.getClass(Name: "InheritableAttr" ); |
3477 | std::vector<Record*> Attrs = Records.getAllDerivedDefinitions(ClassName: "Attr" ), |
3478 | ArgRecords; |
3479 | std::vector<std::unique_ptr<Argument>> Args; |
3480 | std::unique_ptr<VariadicExprArgument> DelayedArgs; |
3481 | |
3482 | OS << " switch (Kind) {\n" ; |
3483 | for (const auto *Attr : Attrs) { |
3484 | const Record &R = *Attr; |
3485 | if (!R.getValueAsBit(FieldName: "ASTNode" )) |
3486 | continue; |
3487 | |
3488 | OS << " case attr::" << R.getName() << ": {\n" ; |
3489 | if (R.isSubClassOf(R: InhClass)) |
3490 | OS << " bool isInherited = Record.readInt();\n" ; |
3491 | OS << " bool isImplicit = Record.readInt();\n" ; |
3492 | OS << " bool isPackExpansion = Record.readInt();\n" ; |
3493 | DelayedArgs = nullptr; |
3494 | if (Attr->getValueAsBit(FieldName: "AcceptsExprPack" )) { |
3495 | DelayedArgs = |
3496 | std::make_unique<VariadicExprArgument>(args: "DelayedArgs" , args: R.getName()); |
3497 | DelayedArgs->writePCHReadDecls(OS); |
3498 | } |
3499 | ArgRecords = R.getValueAsListOfDefs(FieldName: "Args" ); |
3500 | Args.clear(); |
3501 | for (const auto *Arg : ArgRecords) { |
3502 | Args.emplace_back(args: createArgument(Arg: *Arg, Attr: R.getName())); |
3503 | Args.back()->writePCHReadDecls(OS); |
3504 | } |
3505 | OS << " New = new (Context) " << R.getName() << "Attr(Context, Info" ; |
3506 | for (auto const &ri : Args) { |
3507 | OS << ", " ; |
3508 | ri->writePCHReadArgs(OS); |
3509 | } |
3510 | OS << ");\n" ; |
3511 | if (R.isSubClassOf(R: InhClass)) |
3512 | OS << " cast<InheritableAttr>(New)->setInherited(isInherited);\n" ; |
3513 | OS << " New->setImplicit(isImplicit);\n" ; |
3514 | OS << " New->setPackExpansion(isPackExpansion);\n" ; |
3515 | if (DelayedArgs) { |
3516 | OS << " cast<" << R.getName() |
3517 | << "Attr>(New)->setDelayedArgs(Context, " ; |
3518 | DelayedArgs->writePCHReadArgs(OS); |
3519 | OS << ");\n" ; |
3520 | } |
3521 | OS << " break;\n" ; |
3522 | OS << " }\n" ; |
3523 | } |
3524 | OS << " }\n" ; |
3525 | } |
3526 | |
3527 | // Emits the code to write an attribute to a precompiled header. |
3528 | void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) { |
3529 | emitSourceFileHeader(Desc: "Attribute serialization code" , OS, Record: Records); |
3530 | |
3531 | Record *InhClass = Records.getClass(Name: "InheritableAttr" ); |
3532 | std::vector<Record*> Attrs = Records.getAllDerivedDefinitions(ClassName: "Attr" ), Args; |
3533 | |
3534 | OS << " switch (A->getKind()) {\n" ; |
3535 | for (const auto *Attr : Attrs) { |
3536 | const Record &R = *Attr; |
3537 | if (!R.getValueAsBit(FieldName: "ASTNode" )) |
3538 | continue; |
3539 | OS << " case attr::" << R.getName() << ": {\n" ; |
3540 | Args = R.getValueAsListOfDefs(FieldName: "Args" ); |
3541 | if (R.isSubClassOf(R: InhClass) || !Args.empty()) |
3542 | OS << " const auto *SA = cast<" << R.getName() |
3543 | << "Attr>(A);\n" ; |
3544 | if (R.isSubClassOf(R: InhClass)) |
3545 | OS << " Record.push_back(SA->isInherited());\n" ; |
3546 | OS << " Record.push_back(A->isImplicit());\n" ; |
3547 | OS << " Record.push_back(A->isPackExpansion());\n" ; |
3548 | if (Attr->getValueAsBit(FieldName: "AcceptsExprPack" )) |
3549 | VariadicExprArgument("DelayedArgs" , R.getName()).writePCHWrite(OS); |
3550 | |
3551 | for (const auto *Arg : Args) |
3552 | createArgument(Arg: *Arg, Attr: R.getName())->writePCHWrite(OS); |
3553 | OS << " break;\n" ; |
3554 | OS << " }\n" ; |
3555 | } |
3556 | OS << " }\n" ; |
3557 | } |
3558 | |
3559 | } // namespace clang |
3560 | |
3561 | // Helper function for GenerateTargetSpecificAttrChecks that alters the 'Test' |
3562 | // parameter with only a single check type, if applicable. |
3563 | static bool GenerateTargetSpecificAttrCheck(const Record *R, std::string &Test, |
3564 | std::string *FnName, |
3565 | StringRef ListName, |
3566 | StringRef CheckAgainst, |
3567 | StringRef Scope) { |
3568 | if (!R->isValueUnset(FieldName: ListName)) { |
3569 | Test += " && (" ; |
3570 | std::vector<StringRef> Items = R->getValueAsListOfStrings(FieldName: ListName); |
3571 | for (auto I = Items.begin(), E = Items.end(); I != E; ++I) { |
3572 | StringRef Part = *I; |
3573 | Test += CheckAgainst; |
3574 | Test += " == " ; |
3575 | Test += Scope; |
3576 | Test += Part; |
3577 | if (I + 1 != E) |
3578 | Test += " || " ; |
3579 | if (FnName) |
3580 | *FnName += Part; |
3581 | } |
3582 | Test += ")" ; |
3583 | return true; |
3584 | } |
3585 | return false; |
3586 | } |
3587 | |
3588 | // Generate a conditional expression to check if the current target satisfies |
3589 | // the conditions for a TargetSpecificAttr record, and append the code for |
3590 | // those checks to the Test string. If the FnName string pointer is non-null, |
3591 | // append a unique suffix to distinguish this set of target checks from other |
3592 | // TargetSpecificAttr records. |
3593 | static bool GenerateTargetSpecificAttrChecks(const Record *R, |
3594 | std::vector<StringRef> &Arches, |
3595 | std::string &Test, |
3596 | std::string *FnName) { |
3597 | bool AnyTargetChecks = false; |
3598 | |
3599 | // It is assumed that there will be an llvm::Triple object |
3600 | // named "T" and a TargetInfo object named "Target" within |
3601 | // scope that can be used to determine whether the attribute exists in |
3602 | // a given target. |
3603 | Test += "true" ; |
3604 | // If one or more architectures is specified, check those. Arches are handled |
3605 | // differently because GenerateTargetRequirements needs to combine the list |
3606 | // with ParseKind. |
3607 | if (!Arches.empty()) { |
3608 | AnyTargetChecks = true; |
3609 | Test += " && (" ; |
3610 | for (auto I = Arches.begin(), E = Arches.end(); I != E; ++I) { |
3611 | StringRef Part = *I; |
3612 | Test += "T.getArch() == llvm::Triple::" ; |
3613 | Test += Part; |
3614 | if (I + 1 != E) |
3615 | Test += " || " ; |
3616 | if (FnName) |
3617 | *FnName += Part; |
3618 | } |
3619 | Test += ")" ; |
3620 | } |
3621 | |
3622 | // If the attribute is specific to particular OSes, check those. |
3623 | AnyTargetChecks |= GenerateTargetSpecificAttrCheck( |
3624 | R, Test, FnName, ListName: "OSes" , CheckAgainst: "T.getOS()" , Scope: "llvm::Triple::" ); |
3625 | |
3626 | // If one or more object formats is specified, check those. |
3627 | AnyTargetChecks |= |
3628 | GenerateTargetSpecificAttrCheck(R, Test, FnName, ListName: "ObjectFormats" , |
3629 | CheckAgainst: "T.getObjectFormat()" , Scope: "llvm::Triple::" ); |
3630 | |
3631 | // If custom code is specified, emit it. |
3632 | StringRef Code = R->getValueAsString(FieldName: "CustomCode" ); |
3633 | if (!Code.empty()) { |
3634 | AnyTargetChecks = true; |
3635 | Test += " && (" ; |
3636 | Test += Code; |
3637 | Test += ")" ; |
3638 | } |
3639 | |
3640 | return AnyTargetChecks; |
3641 | } |
3642 | |
3643 | static void GenerateHasAttrSpellingStringSwitch( |
3644 | const std::vector<std::pair<const Record *, FlattenedSpelling>> &Attrs, |
3645 | raw_ostream &OS, const std::string &Variety, |
3646 | const std::string &Scope = "" ) { |
3647 | for (const auto &[Attr, Spelling] : Attrs) { |
3648 | // C++11-style attributes have specific version information associated with |
3649 | // them. If the attribute has no scope, the version information must not |
3650 | // have the default value (1), as that's incorrect. Instead, the unscoped |
3651 | // attribute version information should be taken from the SD-6 standing |
3652 | // document, which can be found at: |
3653 | // https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations |
3654 | // |
3655 | // C23-style attributes have the same kind of version information |
3656 | // associated with them. The unscoped attribute version information should |
3657 | // be taken from the specification of the attribute in the C Standard. |
3658 | // |
3659 | // Clang-specific attributes have the same kind of version information |
3660 | // associated with them. This version is typically the default value (1). |
3661 | // These version values are clang-specific and should typically be |
3662 | // incremented once the attribute changes its syntax and/or semantics in a |
3663 | // a way that is impactful to the end user. |
3664 | int Version = 1; |
3665 | |
3666 | assert(Spelling.variety() == Variety); |
3667 | std::string Name = "" ; |
3668 | if (Spelling.nameSpace().empty() || Scope == Spelling.nameSpace()) { |
3669 | Name = Spelling.name(); |
3670 | Version = static_cast<int>( |
3671 | Spelling.getSpellingRecord().getValueAsInt(FieldName: "Version" )); |
3672 | // Verify that explicitly specified CXX11 and C23 spellings (i.e. |
3673 | // not inferred from Clang/GCC spellings) have a version that's |
3674 | // different from the default (1). |
3675 | bool RequiresValidVersion = |
3676 | (Variety == "CXX11" || Variety == "C23" ) && |
3677 | Spelling.getSpellingRecord().getValueAsString(FieldName: "Variety" ) == Variety; |
3678 | if (RequiresValidVersion && Scope.empty() && Version == 1) |
3679 | PrintError(ErrorLoc: Spelling.getSpellingRecord().getLoc(), |
3680 | Msg: "Standard attributes must have " |
3681 | "valid version information." ); |
3682 | } |
3683 | |
3684 | std::string Test; |
3685 | if (Attr->isSubClassOf(Name: "TargetSpecificAttr" )) { |
3686 | const Record *R = Attr->getValueAsDef(FieldName: "Target" ); |
3687 | std::vector<StringRef> Arches = R->getValueAsListOfStrings(FieldName: "Arches" ); |
3688 | GenerateTargetSpecificAttrChecks(R, Arches, Test, FnName: nullptr); |
3689 | } else if (!Attr->getValueAsListOfDefs(FieldName: "TargetSpecificSpellings" ).empty()) { |
3690 | // Add target checks if this spelling is target-specific. |
3691 | const std::vector<Record *> TargetSpellings = |
3692 | Attr->getValueAsListOfDefs(FieldName: "TargetSpecificSpellings" ); |
3693 | for (const auto &TargetSpelling : TargetSpellings) { |
3694 | // Find spelling that matches current scope and name. |
3695 | for (const auto &Spelling : GetFlattenedSpellings(Attr: *TargetSpelling)) { |
3696 | if (Scope == Spelling.nameSpace() && Name == Spelling.name()) { |
3697 | const Record *Target = TargetSpelling->getValueAsDef(FieldName: "Target" ); |
3698 | std::vector<StringRef> Arches = |
3699 | Target->getValueAsListOfStrings(FieldName: "Arches" ); |
3700 | GenerateTargetSpecificAttrChecks(R: Target, Arches, Test, |
3701 | /*FnName=*/nullptr); |
3702 | break; |
3703 | } |
3704 | } |
3705 | } |
3706 | } |
3707 | |
3708 | std::string TestStr = !Test.empty() |
3709 | ? Test + " ? " + llvm::itostr(X: Version) + " : 0" |
3710 | : llvm::itostr(X: Version); |
3711 | if (Scope.empty() || Scope == Spelling.nameSpace()) |
3712 | OS << " .Case(\"" << Spelling.name() << "\", " << TestStr << ")\n" ; |
3713 | } |
3714 | OS << " .Default(0);\n" ; |
3715 | } |
3716 | |
3717 | namespace clang { |
3718 | |
3719 | // Emits list of regular keyword attributes with info about their arguments. |
3720 | void EmitClangRegularKeywordAttributeInfo(RecordKeeper &Records, |
3721 | raw_ostream &OS) { |
3722 | emitSourceFileHeader( |
3723 | Desc: "A list of regular keyword attributes generated from the attribute" |
3724 | " definitions" , |
3725 | OS); |
3726 | // Assume for now that the same token is not used in multiple regular |
3727 | // keyword attributes. |
3728 | for (auto *R : Records.getAllDerivedDefinitions(ClassName: "Attr" )) |
3729 | for (const auto &S : GetFlattenedSpellings(Attr: *R)) { |
3730 | if (!isRegularKeywordAttribute(S)) |
3731 | continue; |
3732 | std::vector<Record *> Args = R->getValueAsListOfDefs(FieldName: "Args" ); |
3733 | bool HasArgs = llvm::any_of( |
3734 | Range&: Args, P: [](const Record *Arg) { return !Arg->getValueAsBit(FieldName: "Fake" ); }); |
3735 | |
3736 | OS << "KEYWORD_ATTRIBUTE(" |
3737 | << S.getSpellingRecord().getValueAsString(FieldName: "Name" ) << ", " |
3738 | << (HasArgs ? "true" : "false" ) << ", )\n" ; |
3739 | } |
3740 | OS << "#undef KEYWORD_ATTRIBUTE\n" ; |
3741 | } |
3742 | |
3743 | // Emits the list of spellings for attributes. |
3744 | void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) { |
3745 | emitSourceFileHeader(Desc: "Code to implement the __has_attribute logic" , OS, |
3746 | Record: Records); |
3747 | |
3748 | // Separate all of the attributes out into four group: generic, C++11, GNU, |
3749 | // and declspecs. Then generate a big switch statement for each of them. |
3750 | std::vector<Record *> Attrs = Records.getAllDerivedDefinitions(ClassName: "Attr" ); |
3751 | std::vector<std::pair<const Record *, FlattenedSpelling>> Declspec, Microsoft, |
3752 | GNU, Pragma, HLSLAnnotation; |
3753 | std::map<std::string, |
3754 | std::vector<std::pair<const Record *, FlattenedSpelling>>> |
3755 | CXX, C23; |
3756 | |
3757 | // Walk over the list of all attributes, and split them out based on the |
3758 | // spelling variety. |
3759 | for (auto *R : Attrs) { |
3760 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr: *R); |
3761 | for (const auto &SI : Spellings) { |
3762 | const std::string &Variety = SI.variety(); |
3763 | if (Variety == "GNU" ) |
3764 | GNU.emplace_back(args&: R, args: SI); |
3765 | else if (Variety == "Declspec" ) |
3766 | Declspec.emplace_back(args&: R, args: SI); |
3767 | else if (Variety == "Microsoft" ) |
3768 | Microsoft.emplace_back(args&: R, args: SI); |
3769 | else if (Variety == "CXX11" ) |
3770 | CXX[SI.nameSpace()].emplace_back(args&: R, args: SI); |
3771 | else if (Variety == "C23" ) |
3772 | C23[SI.nameSpace()].emplace_back(args&: R, args: SI); |
3773 | else if (Variety == "Pragma" ) |
3774 | Pragma.emplace_back(args&: R, args: SI); |
3775 | else if (Variety == "HLSLAnnotation" ) |
3776 | HLSLAnnotation.emplace_back(args&: R, args: SI); |
3777 | } |
3778 | } |
3779 | |
3780 | OS << "const llvm::Triple &T = Target.getTriple();\n" ; |
3781 | OS << "switch (Syntax) {\n" ; |
3782 | OS << "case AttributeCommonInfo::Syntax::AS_GNU:\n" ; |
3783 | OS << " return llvm::StringSwitch<int>(Name)\n" ; |
3784 | GenerateHasAttrSpellingStringSwitch(Attrs: GNU, OS, Variety: "GNU" ); |
3785 | OS << "case AttributeCommonInfo::Syntax::AS_Declspec:\n" ; |
3786 | OS << " return llvm::StringSwitch<int>(Name)\n" ; |
3787 | GenerateHasAttrSpellingStringSwitch(Attrs: Declspec, OS, Variety: "Declspec" ); |
3788 | OS << "case AttributeCommonInfo::Syntax::AS_Microsoft:\n" ; |
3789 | OS << " return llvm::StringSwitch<int>(Name)\n" ; |
3790 | GenerateHasAttrSpellingStringSwitch(Attrs: Microsoft, OS, Variety: "Microsoft" ); |
3791 | OS << "case AttributeCommonInfo::Syntax::AS_Pragma:\n" ; |
3792 | OS << " return llvm::StringSwitch<int>(Name)\n" ; |
3793 | GenerateHasAttrSpellingStringSwitch(Attrs: Pragma, OS, Variety: "Pragma" ); |
3794 | OS << "case AttributeCommonInfo::Syntax::AS_HLSLAnnotation:\n" ; |
3795 | OS << " return llvm::StringSwitch<int>(Name)\n" ; |
3796 | GenerateHasAttrSpellingStringSwitch(Attrs: HLSLAnnotation, OS, Variety: "HLSLAnnotation" ); |
3797 | auto fn = [&OS](const char *Spelling, |
3798 | const std::map< |
3799 | std::string, |
3800 | std::vector<std::pair<const Record *, FlattenedSpelling>>> |
3801 | &List) { |
3802 | OS << "case AttributeCommonInfo::Syntax::AS_" << Spelling << ": {\n" ; |
3803 | // C++11-style attributes are further split out based on the Scope. |
3804 | for (auto I = List.cbegin(), E = List.cend(); I != E; ++I) { |
3805 | if (I != List.cbegin()) |
3806 | OS << " else " ; |
3807 | if (I->first.empty()) |
3808 | OS << "if (ScopeName == \"\") {\n" ; |
3809 | else |
3810 | OS << "if (ScopeName == \"" << I->first << "\") {\n" ; |
3811 | OS << " return llvm::StringSwitch<int>(Name)\n" ; |
3812 | GenerateHasAttrSpellingStringSwitch(Attrs: I->second, OS, Variety: Spelling, Scope: I->first); |
3813 | OS << "}" ; |
3814 | } |
3815 | OS << "\n} break;\n" ; |
3816 | }; |
3817 | fn("CXX11" , CXX); |
3818 | fn("C23" , C23); |
3819 | OS << "case AttributeCommonInfo::Syntax::AS_Keyword:\n" ; |
3820 | OS << "case AttributeCommonInfo::Syntax::AS_ContextSensitiveKeyword:\n" ; |
3821 | OS << " llvm_unreachable(\"hasAttribute not supported for keyword\");\n" ; |
3822 | OS << " return 0;\n" ; |
3823 | OS << "case AttributeCommonInfo::Syntax::AS_Implicit:\n" ; |
3824 | OS << " llvm_unreachable (\"hasAttribute not supported for " |
3825 | "AS_Implicit\");\n" ; |
3826 | OS << " return 0;\n" ; |
3827 | |
3828 | OS << "}\n" ; |
3829 | } |
3830 | |
3831 | void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) { |
3832 | emitSourceFileHeader(Desc: "Code to translate different attribute spellings into " |
3833 | "internal identifiers" , |
3834 | OS, Record: Records); |
3835 | |
3836 | OS << " switch (getParsedKind()) {\n" ; |
3837 | OS << " case IgnoredAttribute:\n" ; |
3838 | OS << " case UnknownAttribute:\n" ; |
3839 | OS << " case NoSemaHandlerAttribute:\n" ; |
3840 | OS << " llvm_unreachable(\"Ignored/unknown shouldn't get here\");\n" ; |
3841 | |
3842 | ParsedAttrMap Attrs = getParsedAttrList(Records); |
3843 | for (const auto &I : Attrs) { |
3844 | const Record &R = *I.second; |
3845 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr: R); |
3846 | OS << " case AT_" << I.first << ": {\n" ; |
3847 | for (unsigned I = 0; I < Spellings.size(); ++ I) { |
3848 | OS << " if (Name == \"" << Spellings[I].name() << "\" && " |
3849 | << "getSyntax() == AttributeCommonInfo::AS_" << Spellings[I].variety() |
3850 | << " && Scope == \"" << Spellings[I].nameSpace() << "\")\n" |
3851 | << " return " << I << ";\n" ; |
3852 | } |
3853 | |
3854 | OS << " break;\n" ; |
3855 | OS << " }\n" ; |
3856 | } |
3857 | |
3858 | OS << " }\n" ; |
3859 | OS << " return 0;\n" ; |
3860 | } |
3861 | |
3862 | // Emits code used by RecursiveASTVisitor to visit attributes |
3863 | void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS) { |
3864 | emitSourceFileHeader(Desc: "Used by RecursiveASTVisitor to visit attributes." , OS, |
3865 | Record: Records); |
3866 | |
3867 | std::vector<Record*> Attrs = Records.getAllDerivedDefinitions(ClassName: "Attr" ); |
3868 | |
3869 | // Write method declarations for Traverse* methods. |
3870 | // We emit this here because we only generate methods for attributes that |
3871 | // are declared as ASTNodes. |
3872 | OS << "#ifdef ATTR_VISITOR_DECLS_ONLY\n\n" ; |
3873 | for (const auto *Attr : Attrs) { |
3874 | const Record &R = *Attr; |
3875 | if (!R.getValueAsBit(FieldName: "ASTNode" )) |
3876 | continue; |
3877 | OS << " bool Traverse" |
3878 | << R.getName() << "Attr(" << R.getName() << "Attr *A);\n" ; |
3879 | OS << " bool Visit" |
3880 | << R.getName() << "Attr(" << R.getName() << "Attr *A) {\n" |
3881 | << " return true; \n" |
3882 | << " }\n" ; |
3883 | } |
3884 | OS << "\n#else // ATTR_VISITOR_DECLS_ONLY\n\n" ; |
3885 | |
3886 | // Write individual Traverse* methods for each attribute class. |
3887 | for (const auto *Attr : Attrs) { |
3888 | const Record &R = *Attr; |
3889 | if (!R.getValueAsBit(FieldName: "ASTNode" )) |
3890 | continue; |
3891 | |
3892 | OS << "template <typename Derived>\n" |
3893 | << "bool VISITORCLASS<Derived>::Traverse" |
3894 | << R.getName() << "Attr(" << R.getName() << "Attr *A) {\n" |
3895 | << " if (!getDerived().VisitAttr(A))\n" |
3896 | << " return false;\n" |
3897 | << " if (!getDerived().Visit" << R.getName() << "Attr(A))\n" |
3898 | << " return false;\n" ; |
3899 | |
3900 | std::vector<Record*> ArgRecords = R.getValueAsListOfDefs(FieldName: "Args" ); |
3901 | for (const auto *Arg : ArgRecords) |
3902 | createArgument(Arg: *Arg, Attr: R.getName())->writeASTVisitorTraversal(OS); |
3903 | |
3904 | if (Attr->getValueAsBit(FieldName: "AcceptsExprPack" )) |
3905 | VariadicExprArgument("DelayedArgs" , R.getName()) |
3906 | .writeASTVisitorTraversal(OS); |
3907 | |
3908 | OS << " return true;\n" ; |
3909 | OS << "}\n\n" ; |
3910 | } |
3911 | |
3912 | // Write generic Traverse routine |
3913 | OS << "template <typename Derived>\n" |
3914 | << "bool VISITORCLASS<Derived>::TraverseAttr(Attr *A) {\n" |
3915 | << " if (!A)\n" |
3916 | << " return true;\n" |
3917 | << "\n" |
3918 | << " switch (A->getKind()) {\n" ; |
3919 | |
3920 | for (const auto *Attr : Attrs) { |
3921 | const Record &R = *Attr; |
3922 | if (!R.getValueAsBit(FieldName: "ASTNode" )) |
3923 | continue; |
3924 | |
3925 | OS << " case attr::" << R.getName() << ":\n" |
3926 | << " return getDerived().Traverse" << R.getName() << "Attr(" |
3927 | << "cast<" << R.getName() << "Attr>(A));\n" ; |
3928 | } |
3929 | OS << " }\n" ; // end switch |
3930 | OS << " llvm_unreachable(\"bad attribute kind\");\n" ; |
3931 | OS << "}\n" ; // end function |
3932 | OS << "#endif // ATTR_VISITOR_DECLS_ONLY\n" ; |
3933 | } |
3934 | |
3935 | void EmitClangAttrTemplateInstantiateHelper(const std::vector<Record *> &Attrs, |
3936 | raw_ostream &OS, |
3937 | bool AppliesToDecl) { |
3938 | |
3939 | OS << " switch (At->getKind()) {\n" ; |
3940 | for (const auto *Attr : Attrs) { |
3941 | const Record &R = *Attr; |
3942 | if (!R.getValueAsBit(FieldName: "ASTNode" )) |
3943 | continue; |
3944 | OS << " case attr::" << R.getName() << ": {\n" ; |
3945 | bool ShouldClone = R.getValueAsBit(FieldName: "Clone" ) && |
3946 | (!AppliesToDecl || |
3947 | R.getValueAsBit(FieldName: "MeaningfulToClassTemplateDefinition" )); |
3948 | |
3949 | if (!ShouldClone) { |
3950 | OS << " return nullptr;\n" ; |
3951 | OS << " }\n" ; |
3952 | continue; |
3953 | } |
3954 | |
3955 | OS << " const auto *A = cast<" |
3956 | << R.getName() << "Attr>(At);\n" ; |
3957 | bool TDependent = R.getValueAsBit(FieldName: "TemplateDependent" ); |
3958 | |
3959 | if (!TDependent) { |
3960 | OS << " return A->clone(C);\n" ; |
3961 | OS << " }\n" ; |
3962 | continue; |
3963 | } |
3964 | |
3965 | std::vector<Record*> ArgRecords = R.getValueAsListOfDefs(FieldName: "Args" ); |
3966 | std::vector<std::unique_ptr<Argument>> Args; |
3967 | Args.reserve(n: ArgRecords.size()); |
3968 | |
3969 | for (const auto *ArgRecord : ArgRecords) |
3970 | Args.emplace_back(args: createArgument(Arg: *ArgRecord, Attr: R.getName())); |
3971 | |
3972 | for (auto const &ai : Args) |
3973 | ai->writeTemplateInstantiation(OS); |
3974 | |
3975 | OS << " return new (C) " << R.getName() << "Attr(C, *A" ; |
3976 | for (auto const &ai : Args) { |
3977 | OS << ", " ; |
3978 | ai->writeTemplateInstantiationArgs(OS); |
3979 | } |
3980 | OS << ");\n" |
3981 | << " }\n" ; |
3982 | } |
3983 | OS << " } // end switch\n" |
3984 | << " llvm_unreachable(\"Unknown attribute!\");\n" |
3985 | << " return nullptr;\n" ; |
3986 | } |
3987 | |
3988 | // Emits code to instantiate dependent attributes on templates. |
3989 | void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) { |
3990 | emitSourceFileHeader(Desc: "Template instantiation code for attributes" , OS, |
3991 | Record: Records); |
3992 | |
3993 | std::vector<Record*> Attrs = Records.getAllDerivedDefinitions(ClassName: "Attr" ); |
3994 | |
3995 | OS << "namespace clang {\n" |
3996 | << "namespace sema {\n\n" |
3997 | << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, " |
3998 | << "Sema &S,\n" |
3999 | << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n" ; |
4000 | EmitClangAttrTemplateInstantiateHelper(Attrs, OS, /*AppliesToDecl*/false); |
4001 | OS << "}\n\n" |
4002 | << "Attr *instantiateTemplateAttributeForDecl(const Attr *At,\n" |
4003 | << " ASTContext &C, Sema &S,\n" |
4004 | << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n" ; |
4005 | EmitClangAttrTemplateInstantiateHelper(Attrs, OS, /*AppliesToDecl*/true); |
4006 | OS << "}\n\n" |
4007 | << "} // end namespace sema\n" |
4008 | << "} // end namespace clang\n" ; |
4009 | } |
4010 | |
4011 | // Emits the list of parsed attributes. |
4012 | void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) { |
4013 | emitSourceFileHeader(Desc: "List of all attributes that Clang recognizes" , OS, |
4014 | Record: Records); |
4015 | |
4016 | OS << "#ifndef PARSED_ATTR\n" ; |
4017 | OS << "#define PARSED_ATTR(NAME) NAME\n" ; |
4018 | OS << "#endif\n\n" ; |
4019 | |
4020 | ParsedAttrMap Names = getParsedAttrList(Records); |
4021 | for (const auto &I : Names) { |
4022 | OS << "PARSED_ATTR(" << I.first << ")\n" ; |
4023 | } |
4024 | } |
4025 | |
4026 | static bool isArgVariadic(const Record &R, StringRef AttrName) { |
4027 | return createArgument(Arg: R, Attr: AttrName)->isVariadic(); |
4028 | } |
4029 | |
4030 | static void emitArgInfo(const Record &R, raw_ostream &OS) { |
4031 | // This function will count the number of arguments specified for the |
4032 | // attribute and emit the number of required arguments followed by the |
4033 | // number of optional arguments. |
4034 | std::vector<Record *> Args = R.getValueAsListOfDefs(FieldName: "Args" ); |
4035 | unsigned ArgCount = 0, OptCount = 0, ArgMemberCount = 0; |
4036 | bool HasVariadic = false; |
4037 | for (const auto *Arg : Args) { |
4038 | // If the arg is fake, it's the user's job to supply it: general parsing |
4039 | // logic shouldn't need to know anything about it. |
4040 | if (Arg->getValueAsBit(FieldName: "Fake" )) |
4041 | continue; |
4042 | Arg->getValueAsBit(FieldName: "Optional" ) ? ++OptCount : ++ArgCount; |
4043 | ++ArgMemberCount; |
4044 | if (!HasVariadic && isArgVariadic(R: *Arg, AttrName: R.getName())) |
4045 | HasVariadic = true; |
4046 | } |
4047 | |
4048 | // If there is a variadic argument, we will set the optional argument count |
4049 | // to its largest value. Since it's currently a 4-bit number, we set it to 15. |
4050 | OS << " /*NumArgs=*/" << ArgCount << ",\n" ; |
4051 | OS << " /*OptArgs=*/" << (HasVariadic ? 15 : OptCount) << ",\n" ; |
4052 | OS << " /*NumArgMembers=*/" << ArgMemberCount << ",\n" ; |
4053 | } |
4054 | |
4055 | static std::string GetDiagnosticSpelling(const Record &R) { |
4056 | std::string Ret = std::string(R.getValueAsString(FieldName: "DiagSpelling" )); |
4057 | if (!Ret.empty()) |
4058 | return Ret; |
4059 | |
4060 | // If we couldn't find the DiagSpelling in this object, we can check to see |
4061 | // if the object is one that has a base, and if it is, loop up to the Base |
4062 | // member recursively. |
4063 | if (auto Base = R.getValueAsOptionalDef(BaseFieldName)) |
4064 | return GetDiagnosticSpelling(R: *Base); |
4065 | |
4066 | return "" ; |
4067 | } |
4068 | |
4069 | static std::string CalculateDiagnostic(const Record &S) { |
4070 | // If the SubjectList object has a custom diagnostic associated with it, |
4071 | // return that directly. |
4072 | const StringRef CustomDiag = S.getValueAsString(FieldName: "CustomDiag" ); |
4073 | if (!CustomDiag.empty()) |
4074 | return ("\"" + Twine(CustomDiag) + "\"" ).str(); |
4075 | |
4076 | std::vector<std::string> DiagList; |
4077 | std::vector<Record *> Subjects = S.getValueAsListOfDefs(FieldName: "Subjects" ); |
4078 | for (const auto *Subject : Subjects) { |
4079 | const Record &R = *Subject; |
4080 | // Get the diagnostic text from the Decl or Stmt node given. |
4081 | std::string V = GetDiagnosticSpelling(R); |
4082 | if (V.empty()) { |
4083 | PrintError(ErrorLoc: R.getLoc(), |
4084 | Msg: "Could not determine diagnostic spelling for the node: " + |
4085 | R.getName() + "; please add one to DeclNodes.td" ); |
4086 | } else { |
4087 | // The node may contain a list of elements itself, so split the elements |
4088 | // by a comma, and trim any whitespace. |
4089 | SmallVector<StringRef, 2> Frags; |
4090 | llvm::SplitString(Source: V, OutFragments&: Frags, Delimiters: "," ); |
4091 | for (auto Str : Frags) { |
4092 | DiagList.push_back(x: std::string(Str.trim())); |
4093 | } |
4094 | } |
4095 | } |
4096 | |
4097 | if (DiagList.empty()) { |
4098 | PrintFatalError(ErrorLoc: S.getLoc(), |
4099 | Msg: "Could not deduce diagnostic argument for Attr subjects" ); |
4100 | return "" ; |
4101 | } |
4102 | |
4103 | // FIXME: this is not particularly good for localization purposes and ideally |
4104 | // should be part of the diagnostics engine itself with some sort of list |
4105 | // specifier. |
4106 | |
4107 | // A single member of the list can be returned directly. |
4108 | if (DiagList.size() == 1) |
4109 | return '"' + DiagList.front() + '"'; |
4110 | |
4111 | if (DiagList.size() == 2) |
4112 | return '"' + DiagList[0] + " and " + DiagList[1] + '"'; |
4113 | |
4114 | // If there are more than two in the list, we serialize the first N - 1 |
4115 | // elements with a comma. This leaves the string in the state: foo, bar, |
4116 | // baz (but misses quux). We can then add ", and " for the last element |
4117 | // manually. |
4118 | std::string Diag = llvm::join(Begin: DiagList.begin(), End: DiagList.end() - 1, Separator: ", " ); |
4119 | return '"' + Diag + ", and " + *(DiagList.end() - 1) + '"'; |
4120 | } |
4121 | |
4122 | static std::string GetSubjectWithSuffix(const Record *R) { |
4123 | const std::string &B = std::string(R->getName()); |
4124 | if (B == "DeclBase" ) |
4125 | return "Decl" ; |
4126 | return B + "Decl" ; |
4127 | } |
4128 | |
4129 | static std::string functionNameForCustomAppertainsTo(const Record &Subject) { |
4130 | return "is" + Subject.getName().str(); |
4131 | } |
4132 | |
4133 | static void GenerateCustomAppertainsTo(const Record &Subject, raw_ostream &OS) { |
4134 | std::string FnName = functionNameForCustomAppertainsTo(Subject); |
4135 | |
4136 | // If this code has already been generated, we don't need to do anything. |
4137 | static std::set<std::string> CustomSubjectSet; |
4138 | auto I = CustomSubjectSet.find(x: FnName); |
4139 | if (I != CustomSubjectSet.end()) |
4140 | return; |
4141 | |
4142 | // This only works with non-root Decls. |
4143 | Record *Base = Subject.getValueAsDef(BaseFieldName); |
4144 | |
4145 | // Not currently support custom subjects within custom subjects. |
4146 | if (Base->isSubClassOf(Name: "SubsetSubject" )) { |
4147 | PrintFatalError(ErrorLoc: Subject.getLoc(), |
4148 | Msg: "SubsetSubjects within SubsetSubjects is not supported" ); |
4149 | return; |
4150 | } |
4151 | |
4152 | OS << "static bool " << FnName << "(const Decl *D) {\n" ; |
4153 | OS << " if (const auto *S = dyn_cast<" ; |
4154 | OS << GetSubjectWithSuffix(R: Base); |
4155 | OS << ">(D))\n" ; |
4156 | OS << " return " << Subject.getValueAsString(FieldName: "CheckCode" ) << ";\n" ; |
4157 | OS << " return false;\n" ; |
4158 | OS << "}\n\n" ; |
4159 | |
4160 | CustomSubjectSet.insert(x: FnName); |
4161 | } |
4162 | |
4163 | static void GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) { |
4164 | // If the attribute does not contain a Subjects definition, then use the |
4165 | // default appertainsTo logic. |
4166 | if (Attr.isValueUnset(FieldName: "Subjects" )) |
4167 | return; |
4168 | |
4169 | const Record *SubjectObj = Attr.getValueAsDef(FieldName: "Subjects" ); |
4170 | std::vector<Record *> Subjects = SubjectObj->getValueAsListOfDefs(FieldName: "Subjects" ); |
4171 | |
4172 | // If the list of subjects is empty, it is assumed that the attribute |
4173 | // appertains to everything. |
4174 | if (Subjects.empty()) |
4175 | return; |
4176 | |
4177 | bool Warn = SubjectObj->getValueAsDef(FieldName: "Diag" )->getValueAsBit(FieldName: "Warn" ); |
4178 | |
4179 | // Split the subjects into declaration subjects and statement subjects. |
4180 | // FIXME: subset subjects are added to the declaration list until there are |
4181 | // enough statement attributes with custom subject needs to warrant |
4182 | // the implementation effort. |
4183 | std::vector<Record *> DeclSubjects, StmtSubjects; |
4184 | llvm::copy_if( |
4185 | Range&: Subjects, Out: std::back_inserter(x&: DeclSubjects), P: [](const Record *R) { |
4186 | return R->isSubClassOf(Name: "SubsetSubject" ) || !R->isSubClassOf(Name: "StmtNode" ); |
4187 | }); |
4188 | llvm::copy_if(Range&: Subjects, Out: std::back_inserter(x&: StmtSubjects), |
4189 | P: [](const Record *R) { return R->isSubClassOf(Name: "StmtNode" ); }); |
4190 | |
4191 | // We should have sorted all of the subjects into two lists. |
4192 | // FIXME: this assertion will be wrong if we ever add type attribute subjects. |
4193 | assert(DeclSubjects.size() + StmtSubjects.size() == Subjects.size()); |
4194 | |
4195 | if (DeclSubjects.empty()) { |
4196 | // If there are no decl subjects but there are stmt subjects, diagnose |
4197 | // trying to apply a statement attribute to a declaration. |
4198 | if (!StmtSubjects.empty()) { |
4199 | OS << "bool diagAppertainsToDecl(Sema &S, const ParsedAttr &AL, " ; |
4200 | OS << "const Decl *D) const override {\n" ; |
4201 | OS << " S.Diag(AL.getLoc(), diag::err_attribute_invalid_on_decl)\n" ; |
4202 | OS << " << AL << AL.isRegularKeywordAttribute() << " |
4203 | "D->getLocation();\n" ; |
4204 | OS << " return false;\n" ; |
4205 | OS << "}\n\n" ; |
4206 | } |
4207 | } else { |
4208 | // Otherwise, generate an appertainsTo check specific to this attribute |
4209 | // which checks all of the given subjects against the Decl passed in. |
4210 | OS << "bool diagAppertainsToDecl(Sema &S, " ; |
4211 | OS << "const ParsedAttr &Attr, const Decl *D) const override {\n" ; |
4212 | OS << " if (" ; |
4213 | for (auto I = DeclSubjects.begin(), E = DeclSubjects.end(); I != E; ++I) { |
4214 | // If the subject has custom code associated with it, use the generated |
4215 | // function for it. The function cannot be inlined into this check (yet) |
4216 | // because it requires the subject to be of a specific type, and were that |
4217 | // information inlined here, it would not support an attribute with |
4218 | // multiple custom subjects. |
4219 | if ((*I)->isSubClassOf(Name: "SubsetSubject" )) |
4220 | OS << "!" << functionNameForCustomAppertainsTo(Subject: **I) << "(D)" ; |
4221 | else |
4222 | OS << "!isa<" << GetSubjectWithSuffix(R: *I) << ">(D)" ; |
4223 | |
4224 | if (I + 1 != E) |
4225 | OS << " && " ; |
4226 | } |
4227 | OS << ") {\n" ; |
4228 | OS << " S.Diag(Attr.getLoc(), diag::" ; |
4229 | OS << (Warn ? "warn_attribute_wrong_decl_type_str" |
4230 | : "err_attribute_wrong_decl_type_str" ); |
4231 | OS << ")\n" ; |
4232 | OS << " << Attr << Attr.isRegularKeywordAttribute() << " ; |
4233 | OS << CalculateDiagnostic(S: *SubjectObj) << ";\n" ; |
4234 | OS << " return false;\n" ; |
4235 | OS << " }\n" ; |
4236 | OS << " return true;\n" ; |
4237 | OS << "}\n\n" ; |
4238 | } |
4239 | |
4240 | if (StmtSubjects.empty()) { |
4241 | // If there are no stmt subjects but there are decl subjects, diagnose |
4242 | // trying to apply a declaration attribute to a statement. |
4243 | if (!DeclSubjects.empty()) { |
4244 | OS << "bool diagAppertainsToStmt(Sema &S, const ParsedAttr &AL, " ; |
4245 | OS << "const Stmt *St) const override {\n" ; |
4246 | OS << " S.Diag(AL.getLoc(), diag::err_decl_attribute_invalid_on_stmt)\n" ; |
4247 | OS << " << AL << AL.isRegularKeywordAttribute() << " |
4248 | "St->getBeginLoc();\n" ; |
4249 | OS << " return false;\n" ; |
4250 | OS << "}\n\n" ; |
4251 | } |
4252 | } else { |
4253 | // Now, do the same for statements. |
4254 | OS << "bool diagAppertainsToStmt(Sema &S, " ; |
4255 | OS << "const ParsedAttr &Attr, const Stmt *St) const override {\n" ; |
4256 | OS << " if (" ; |
4257 | for (auto I = StmtSubjects.begin(), E = StmtSubjects.end(); I != E; ++I) { |
4258 | OS << "!isa<" << (*I)->getName() << ">(St)" ; |
4259 | if (I + 1 != E) |
4260 | OS << " && " ; |
4261 | } |
4262 | OS << ") {\n" ; |
4263 | OS << " S.Diag(Attr.getLoc(), diag::" ; |
4264 | OS << (Warn ? "warn_attribute_wrong_decl_type_str" |
4265 | : "err_attribute_wrong_decl_type_str" ); |
4266 | OS << ")\n" ; |
4267 | OS << " << Attr << Attr.isRegularKeywordAttribute() << " ; |
4268 | OS << CalculateDiagnostic(S: *SubjectObj) << ";\n" ; |
4269 | OS << " return false;\n" ; |
4270 | OS << " }\n" ; |
4271 | OS << " return true;\n" ; |
4272 | OS << "}\n\n" ; |
4273 | } |
4274 | } |
4275 | |
4276 | // Generates the mutual exclusion checks. The checks for parsed attributes are |
4277 | // written into OS and the checks for merging declaration attributes are |
4278 | // written into MergeOS. |
4279 | static void GenerateMutualExclusionsChecks(const Record &Attr, |
4280 | const RecordKeeper &Records, |
4281 | raw_ostream &OS, |
4282 | raw_ostream &MergeDeclOS, |
4283 | raw_ostream &MergeStmtOS) { |
4284 | // Find all of the definitions that inherit from MutualExclusions and include |
4285 | // the given attribute in the list of exclusions to generate the |
4286 | // diagMutualExclusion() check. |
4287 | std::vector<Record *> ExclusionsList = |
4288 | Records.getAllDerivedDefinitions(ClassName: "MutualExclusions" ); |
4289 | |
4290 | // We don't do any of this magic for type attributes yet. |
4291 | if (Attr.isSubClassOf(Name: "TypeAttr" )) |
4292 | return; |
4293 | |
4294 | // This means the attribute is either a statement attribute, a decl |
4295 | // attribute, or both; find out which. |
4296 | bool CurAttrIsStmtAttr = |
4297 | Attr.isSubClassOf(Name: "StmtAttr" ) || Attr.isSubClassOf(Name: "DeclOrStmtAttr" ); |
4298 | bool CurAttrIsDeclAttr = |
4299 | !CurAttrIsStmtAttr || Attr.isSubClassOf(Name: "DeclOrStmtAttr" ); |
4300 | |
4301 | std::vector<std::string> DeclAttrs, StmtAttrs; |
4302 | |
4303 | for (const Record *Exclusion : ExclusionsList) { |
4304 | std::vector<Record *> MutuallyExclusiveAttrs = |
4305 | Exclusion->getValueAsListOfDefs(FieldName: "Exclusions" ); |
4306 | auto IsCurAttr = [Attr](const Record *R) { |
4307 | return R->getName() == Attr.getName(); |
4308 | }; |
4309 | if (llvm::any_of(Range&: MutuallyExclusiveAttrs, P: IsCurAttr)) { |
4310 | // This list of exclusions includes the attribute we're looking for, so |
4311 | // add the exclusive attributes to the proper list for checking. |
4312 | for (const Record *AttrToExclude : MutuallyExclusiveAttrs) { |
4313 | if (IsCurAttr(AttrToExclude)) |
4314 | continue; |
4315 | |
4316 | if (CurAttrIsStmtAttr) |
4317 | StmtAttrs.push_back(x: (AttrToExclude->getName() + "Attr" ).str()); |
4318 | if (CurAttrIsDeclAttr) |
4319 | DeclAttrs.push_back(x: (AttrToExclude->getName() + "Attr" ).str()); |
4320 | } |
4321 | } |
4322 | } |
4323 | |
4324 | // If there are any decl or stmt attributes, silence -Woverloaded-virtual |
4325 | // warnings for them both. |
4326 | if (!DeclAttrs.empty() || !StmtAttrs.empty()) |
4327 | OS << " using ParsedAttrInfo::diagMutualExclusion;\n\n" ; |
4328 | |
4329 | // If we discovered any decl or stmt attributes to test for, generate the |
4330 | // predicates for them now. |
4331 | if (!DeclAttrs.empty()) { |
4332 | // Generate the ParsedAttrInfo subclass logic for declarations. |
4333 | OS << " bool diagMutualExclusion(Sema &S, const ParsedAttr &AL, " |
4334 | << "const Decl *D) const override {\n" ; |
4335 | for (const std::string &A : DeclAttrs) { |
4336 | OS << " if (const auto *A = D->getAttr<" << A << ">()) {\n" ; |
4337 | OS << " S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)" |
4338 | << " << AL << A << (AL.isRegularKeywordAttribute() ||" |
4339 | << " A->isRegularKeywordAttribute());\n" ; |
4340 | OS << " S.Diag(A->getLocation(), diag::note_conflicting_attribute);" ; |
4341 | OS << " \nreturn false;\n" ; |
4342 | OS << " }\n" ; |
4343 | } |
4344 | OS << " return true;\n" ; |
4345 | OS << " }\n\n" ; |
4346 | |
4347 | // Also generate the declaration attribute merging logic if the current |
4348 | // attribute is one that can be inheritted on a declaration. It is assumed |
4349 | // this code will be executed in the context of a function with parameters: |
4350 | // Sema &S, Decl *D, Attr *A and that returns a bool (false on diagnostic, |
4351 | // true on success). |
4352 | if (Attr.isSubClassOf(Name: "InheritableAttr" )) { |
4353 | MergeDeclOS << " if (const auto *Second = dyn_cast<" |
4354 | << (Attr.getName() + "Attr" ).str() << ">(A)) {\n" ; |
4355 | for (const std::string &A : DeclAttrs) { |
4356 | MergeDeclOS << " if (const auto *First = D->getAttr<" << A |
4357 | << ">()) {\n" ; |
4358 | MergeDeclOS << " S.Diag(First->getLocation(), " |
4359 | << "diag::err_attributes_are_not_compatible) << First << " |
4360 | << "Second << (First->isRegularKeywordAttribute() || " |
4361 | << "Second->isRegularKeywordAttribute());\n" ; |
4362 | MergeDeclOS << " S.Diag(Second->getLocation(), " |
4363 | << "diag::note_conflicting_attribute);\n" ; |
4364 | MergeDeclOS << " return false;\n" ; |
4365 | MergeDeclOS << " }\n" ; |
4366 | } |
4367 | MergeDeclOS << " return true;\n" ; |
4368 | MergeDeclOS << " }\n" ; |
4369 | } |
4370 | } |
4371 | |
4372 | // Statement attributes are a bit different from declarations. With |
4373 | // declarations, each attribute is added to the declaration as it is |
4374 | // processed, and so you can look on the Decl * itself to see if there is a |
4375 | // conflicting attribute. Statement attributes are processed as a group |
4376 | // because AttributedStmt needs to tail-allocate all of the attribute nodes |
4377 | // at once. This means we cannot check whether the statement already contains |
4378 | // an attribute to check for the conflict. Instead, we need to check whether |
4379 | // the given list of semantic attributes contain any conflicts. It is assumed |
4380 | // this code will be executed in the context of a function with parameters: |
4381 | // Sema &S, const SmallVectorImpl<const Attr *> &C. The code will be within a |
4382 | // loop which loops over the container C with a loop variable named A to |
4383 | // represent the current attribute to check for conflicts. |
4384 | // |
4385 | // FIXME: it would be nice not to walk over the list of potential attributes |
4386 | // to apply to the statement more than once, but statements typically don't |
4387 | // have long lists of attributes on them, so re-walking the list should not |
4388 | // be an expensive operation. |
4389 | if (!StmtAttrs.empty()) { |
4390 | MergeStmtOS << " if (const auto *Second = dyn_cast<" |
4391 | << (Attr.getName() + "Attr" ).str() << ">(A)) {\n" ; |
4392 | MergeStmtOS << " auto Iter = llvm::find_if(C, [](const Attr *Check) " |
4393 | << "{ return isa<" ; |
4394 | interleave( |
4395 | c: StmtAttrs, each_fn: [&](const std::string &Name) { MergeStmtOS << Name; }, |
4396 | between_fn: [&] { MergeStmtOS << ", " ; }); |
4397 | MergeStmtOS << ">(Check); });\n" ; |
4398 | MergeStmtOS << " if (Iter != C.end()) {\n" ; |
4399 | MergeStmtOS << " S.Diag((*Iter)->getLocation(), " |
4400 | << "diag::err_attributes_are_not_compatible) << *Iter << " |
4401 | << "Second << ((*Iter)->isRegularKeywordAttribute() || " |
4402 | << "Second->isRegularKeywordAttribute());\n" ; |
4403 | MergeStmtOS << " S.Diag(Second->getLocation(), " |
4404 | << "diag::note_conflicting_attribute);\n" ; |
4405 | MergeStmtOS << " return false;\n" ; |
4406 | MergeStmtOS << " }\n" ; |
4407 | MergeStmtOS << " }\n" ; |
4408 | } |
4409 | } |
4410 | |
4411 | static void |
4412 | emitAttributeMatchRules(PragmaClangAttributeSupport &PragmaAttributeSupport, |
4413 | raw_ostream &OS) { |
4414 | OS << "static bool checkAttributeMatchRuleAppliesTo(const Decl *D, " |
4415 | << AttributeSubjectMatchRule::EnumName << " rule) {\n" ; |
4416 | OS << " switch (rule) {\n" ; |
4417 | for (const auto &Rule : PragmaAttributeSupport.Rules) { |
4418 | if (Rule.isAbstractRule()) { |
4419 | OS << " case " << Rule.getEnumValue() << ":\n" ; |
4420 | OS << " assert(false && \"Abstract matcher rule isn't allowed\");\n" ; |
4421 | OS << " return false;\n" ; |
4422 | continue; |
4423 | } |
4424 | std::vector<Record *> Subjects = Rule.getSubjects(); |
4425 | assert(!Subjects.empty() && "Missing subjects" ); |
4426 | OS << " case " << Rule.getEnumValue() << ":\n" ; |
4427 | OS << " return " ; |
4428 | for (auto I = Subjects.begin(), E = Subjects.end(); I != E; ++I) { |
4429 | // If the subject has custom code associated with it, use the function |
4430 | // that was generated for GenerateAppertainsTo to check if the declaration |
4431 | // is valid. |
4432 | if ((*I)->isSubClassOf(Name: "SubsetSubject" )) |
4433 | OS << functionNameForCustomAppertainsTo(Subject: **I) << "(D)" ; |
4434 | else |
4435 | OS << "isa<" << GetSubjectWithSuffix(R: *I) << ">(D)" ; |
4436 | |
4437 | if (I + 1 != E) |
4438 | OS << " || " ; |
4439 | } |
4440 | OS << ";\n" ; |
4441 | } |
4442 | OS << " }\n" ; |
4443 | OS << " llvm_unreachable(\"Invalid match rule\");\nreturn false;\n" ; |
4444 | OS << "}\n\n" ; |
4445 | } |
4446 | |
4447 | static void GenerateLangOptRequirements(const Record &R, |
4448 | raw_ostream &OS) { |
4449 | // If the attribute has an empty or unset list of language requirements, |
4450 | // use the default handler. |
4451 | std::vector<Record *> LangOpts = R.getValueAsListOfDefs(FieldName: "LangOpts" ); |
4452 | if (LangOpts.empty()) |
4453 | return; |
4454 | |
4455 | OS << "bool acceptsLangOpts(const LangOptions &LangOpts) const override {\n" ; |
4456 | OS << " return " << GenerateTestExpression(LangOpts) << ";\n" ; |
4457 | OS << "}\n\n" ; |
4458 | } |
4459 | |
4460 | static void GenerateTargetRequirements(const Record &Attr, |
4461 | const ParsedAttrMap &Dupes, |
4462 | raw_ostream &OS) { |
4463 | // If the attribute is not a target specific attribute, use the default |
4464 | // target handler. |
4465 | if (!Attr.isSubClassOf(Name: "TargetSpecificAttr" )) |
4466 | return; |
4467 | |
4468 | // Get the list of architectures to be tested for. |
4469 | const Record *R = Attr.getValueAsDef(FieldName: "Target" ); |
4470 | std::vector<StringRef> Arches = R->getValueAsListOfStrings(FieldName: "Arches" ); |
4471 | |
4472 | // If there are other attributes which share the same parsed attribute kind, |
4473 | // such as target-specific attributes with a shared spelling, collapse the |
4474 | // duplicate architectures. This is required because a shared target-specific |
4475 | // attribute has only one ParsedAttr::Kind enumeration value, but it |
4476 | // applies to multiple target architectures. In order for the attribute to be |
4477 | // considered valid, all of its architectures need to be included. |
4478 | if (!Attr.isValueUnset(FieldName: "ParseKind" )) { |
4479 | const StringRef APK = Attr.getValueAsString(FieldName: "ParseKind" ); |
4480 | for (const auto &I : Dupes) { |
4481 | if (I.first == APK) { |
4482 | std::vector<StringRef> DA = |
4483 | I.second->getValueAsDef(FieldName: "Target" )->getValueAsListOfStrings( |
4484 | FieldName: "Arches" ); |
4485 | Arches.insert(position: Arches.end(), first: DA.begin(), last: DA.end()); |
4486 | } |
4487 | } |
4488 | } |
4489 | |
4490 | std::string FnName = "isTarget" ; |
4491 | std::string Test; |
4492 | bool UsesT = GenerateTargetSpecificAttrChecks(R, Arches, Test, FnName: &FnName); |
4493 | |
4494 | OS << "bool existsInTarget(const TargetInfo &Target) const override {\n" ; |
4495 | if (UsesT) |
4496 | OS << " const llvm::Triple &T = Target.getTriple(); (void)T;\n" ; |
4497 | OS << " return " << Test << ";\n" ; |
4498 | OS << "}\n\n" ; |
4499 | } |
4500 | |
4501 | static void |
4502 | GenerateSpellingTargetRequirements(const Record &Attr, |
4503 | const std::vector<Record *> &TargetSpellings, |
4504 | raw_ostream &OS) { |
4505 | // If there are no target specific spellings, use the default target handler. |
4506 | if (TargetSpellings.empty()) |
4507 | return; |
4508 | |
4509 | std::string Test; |
4510 | bool UsesT = false; |
4511 | const std::vector<FlattenedSpelling> SpellingList = |
4512 | GetFlattenedSpellings(Attr); |
4513 | for (unsigned TargetIndex = 0; TargetIndex < TargetSpellings.size(); |
4514 | ++TargetIndex) { |
4515 | const auto &TargetSpelling = TargetSpellings[TargetIndex]; |
4516 | std::vector<FlattenedSpelling> Spellings = |
4517 | GetFlattenedSpellings(Attr: *TargetSpelling); |
4518 | |
4519 | Test += "((SpellingListIndex == " ; |
4520 | for (unsigned Index = 0; Index < Spellings.size(); ++Index) { |
4521 | Test += |
4522 | llvm::itostr(X: getSpellingListIndex(SpellingList, Spelling: Spellings[Index])); |
4523 | if (Index != Spellings.size() - 1) |
4524 | Test += " ||\n SpellingListIndex == " ; |
4525 | else |
4526 | Test += ") && " ; |
4527 | } |
4528 | |
4529 | const Record *Target = TargetSpelling->getValueAsDef(FieldName: "Target" ); |
4530 | std::vector<StringRef> Arches = Target->getValueAsListOfStrings(FieldName: "Arches" ); |
4531 | std::string FnName = "isTargetSpelling" ; |
4532 | UsesT |= GenerateTargetSpecificAttrChecks(R: Target, Arches, Test, FnName: &FnName); |
4533 | Test += ")" ; |
4534 | if (TargetIndex != TargetSpellings.size() - 1) |
4535 | Test += " || " ; |
4536 | } |
4537 | |
4538 | OS << "bool spellingExistsInTarget(const TargetInfo &Target,\n" ; |
4539 | OS << " const unsigned SpellingListIndex) const " |
4540 | "override {\n" ; |
4541 | if (UsesT) |
4542 | OS << " const llvm::Triple &T = Target.getTriple(); (void)T;\n" ; |
4543 | OS << " return " << Test << ";\n" , OS << "}\n\n" ; |
4544 | } |
4545 | |
4546 | static void GenerateSpellingIndexToSemanticSpelling(const Record &Attr, |
4547 | raw_ostream &OS) { |
4548 | // If the attribute does not have a semantic form, we can bail out early. |
4549 | if (!Attr.getValueAsBit(FieldName: "ASTNode" )) |
4550 | return; |
4551 | |
4552 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr); |
4553 | |
4554 | // If there are zero or one spellings, or all of the spellings share the same |
4555 | // name, we can also bail out early. |
4556 | if (Spellings.size() <= 1 || SpellingNamesAreCommon(Spellings)) |
4557 | return; |
4558 | |
4559 | // Generate the enumeration we will use for the mapping. |
4560 | SemanticSpellingMap SemanticToSyntacticMap; |
4561 | std::string Enum = CreateSemanticSpellings(Spellings, Map&: SemanticToSyntacticMap); |
4562 | std::string Name = Attr.getName().str() + "AttrSpellingMap" ; |
4563 | |
4564 | OS << "unsigned spellingIndexToSemanticSpelling(" ; |
4565 | OS << "const ParsedAttr &Attr) const override {\n" ; |
4566 | OS << Enum; |
4567 | OS << " unsigned Idx = Attr.getAttributeSpellingListIndex();\n" ; |
4568 | WriteSemanticSpellingSwitch(VarName: "Idx" , Map: SemanticToSyntacticMap, OS); |
4569 | OS << "}\n\n" ; |
4570 | } |
4571 | |
4572 | static void GenerateHandleDeclAttribute(const Record &Attr, raw_ostream &OS) { |
4573 | // Only generate if Attr can be handled simply. |
4574 | if (!Attr.getValueAsBit(FieldName: "SimpleHandler" )) |
4575 | return; |
4576 | |
4577 | // Generate a function which just converts from ParsedAttr to the Attr type. |
4578 | OS << "AttrHandling handleDeclAttribute(Sema &S, Decl *D," ; |
4579 | OS << "const ParsedAttr &Attr) const override {\n" ; |
4580 | OS << " D->addAttr(::new (S.Context) " << Attr.getName(); |
4581 | OS << "Attr(S.Context, Attr));\n" ; |
4582 | OS << " return AttributeApplied;\n" ; |
4583 | OS << "}\n\n" ; |
4584 | } |
4585 | |
4586 | static bool isParamExpr(const Record *Arg) { |
4587 | return !Arg->getSuperClasses().empty() && |
4588 | llvm::StringSwitch<bool>( |
4589 | Arg->getSuperClasses().back().first->getName()) |
4590 | .Case(S: "ExprArgument" , Value: true) |
4591 | .Case(S: "VariadicExprArgument" , Value: true) |
4592 | .Default(Value: false); |
4593 | } |
4594 | |
4595 | void GenerateIsParamExpr(const Record &Attr, raw_ostream &OS) { |
4596 | OS << "bool isParamExpr(size_t N) const override {\n" ; |
4597 | OS << " return " ; |
4598 | auto Args = Attr.getValueAsListOfDefs(FieldName: "Args" ); |
4599 | for (size_t I = 0; I < Args.size(); ++I) |
4600 | if (isParamExpr(Arg: Args[I])) |
4601 | OS << "(N == " << I << ") || " ; |
4602 | OS << "false;\n" ; |
4603 | OS << "}\n\n" ; |
4604 | } |
4605 | |
4606 | void GenerateHandleAttrWithDelayedArgs(RecordKeeper &Records, raw_ostream &OS) { |
4607 | OS << "static void handleAttrWithDelayedArgs(Sema &S, Decl *D, " ; |
4608 | OS << "const ParsedAttr &Attr) {\n" ; |
4609 | OS << " SmallVector<Expr *, 4> ArgExprs;\n" ; |
4610 | OS << " ArgExprs.reserve(Attr.getNumArgs());\n" ; |
4611 | OS << " for (unsigned I = 0; I < Attr.getNumArgs(); ++I) {\n" ; |
4612 | OS << " assert(!Attr.isArgIdent(I));\n" ; |
4613 | OS << " ArgExprs.push_back(Attr.getArgAsExpr(I));\n" ; |
4614 | OS << " }\n" ; |
4615 | OS << " clang::Attr *CreatedAttr = nullptr;\n" ; |
4616 | OS << " switch (Attr.getKind()) {\n" ; |
4617 | OS << " default:\n" ; |
4618 | OS << " llvm_unreachable(\"Attribute cannot hold delayed arguments.\");\n" ; |
4619 | ParsedAttrMap Attrs = getParsedAttrList(Records); |
4620 | for (const auto &I : Attrs) { |
4621 | const Record &R = *I.second; |
4622 | if (!R.getValueAsBit(FieldName: "AcceptsExprPack" )) |
4623 | continue; |
4624 | OS << " case ParsedAttr::AT_" << I.first << ": {\n" ; |
4625 | OS << " CreatedAttr = " << R.getName() << "Attr::CreateWithDelayedArgs" ; |
4626 | OS << "(S.Context, ArgExprs.data(), ArgExprs.size(), Attr);\n" ; |
4627 | OS << " break;\n" ; |
4628 | OS << " }\n" ; |
4629 | } |
4630 | OS << " }\n" ; |
4631 | OS << " D->addAttr(CreatedAttr);\n" ; |
4632 | OS << "}\n\n" ; |
4633 | } |
4634 | |
4635 | static bool IsKnownToGCC(const Record &Attr) { |
4636 | // Look at the spellings for this subject; if there are any spellings which |
4637 | // claim to be known to GCC, the attribute is known to GCC. |
4638 | return llvm::any_of( |
4639 | Range: GetFlattenedSpellings(Attr), |
4640 | P: [](const FlattenedSpelling &S) { return S.knownToGCC(); }); |
4641 | } |
4642 | |
4643 | /// Emits the parsed attribute helpers |
4644 | void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) { |
4645 | emitSourceFileHeader(Desc: "Parsed attribute helpers" , OS, Record: Records); |
4646 | |
4647 | OS << "#if !defined(WANT_DECL_MERGE_LOGIC) && " |
4648 | << "!defined(WANT_STMT_MERGE_LOGIC)\n" ; |
4649 | PragmaClangAttributeSupport &PragmaAttributeSupport = |
4650 | getPragmaAttributeSupport(Records); |
4651 | |
4652 | // Get the list of parsed attributes, and accept the optional list of |
4653 | // duplicates due to the ParseKind. |
4654 | ParsedAttrMap Dupes; |
4655 | ParsedAttrMap Attrs = getParsedAttrList(Records, Dupes: &Dupes); |
4656 | |
4657 | // Generate all of the custom appertainsTo functions that the attributes |
4658 | // will be using. |
4659 | for (const auto &I : Attrs) { |
4660 | const Record &Attr = *I.second; |
4661 | if (Attr.isValueUnset(FieldName: "Subjects" )) |
4662 | continue; |
4663 | const Record *SubjectObj = Attr.getValueAsDef(FieldName: "Subjects" ); |
4664 | for (auto Subject : SubjectObj->getValueAsListOfDefs(FieldName: "Subjects" )) |
4665 | if (Subject->isSubClassOf(Name: "SubsetSubject" )) |
4666 | GenerateCustomAppertainsTo(Subject: *Subject, OS); |
4667 | } |
4668 | |
4669 | // This stream is used to collect all of the declaration attribute merging |
4670 | // logic for performing mutual exclusion checks. This gets emitted at the |
4671 | // end of the file in a helper function of its own. |
4672 | std::string DeclMergeChecks, StmtMergeChecks; |
4673 | raw_string_ostream MergeDeclOS(DeclMergeChecks), MergeStmtOS(StmtMergeChecks); |
4674 | |
4675 | // Generate a ParsedAttrInfo struct for each of the attributes. |
4676 | for (auto I = Attrs.begin(), E = Attrs.end(); I != E; ++I) { |
4677 | // TODO: If the attribute's kind appears in the list of duplicates, that is |
4678 | // because it is a target-specific attribute that appears multiple times. |
4679 | // It would be beneficial to test whether the duplicates are "similar |
4680 | // enough" to each other to not cause problems. For instance, check that |
4681 | // the spellings are identical, and custom parsing rules match, etc. |
4682 | |
4683 | // We need to generate struct instances based off ParsedAttrInfo from |
4684 | // ParsedAttr.cpp. |
4685 | const std::string &AttrName = I->first; |
4686 | const Record &Attr = *I->second; |
4687 | auto Spellings = GetFlattenedSpellings(Attr); |
4688 | if (!Spellings.empty()) { |
4689 | OS << "static constexpr ParsedAttrInfo::Spelling " << I->first |
4690 | << "Spellings[] = {\n" ; |
4691 | for (const auto &S : Spellings) { |
4692 | const std::string &RawSpelling = S.name(); |
4693 | std::string Spelling; |
4694 | if (!S.nameSpace().empty()) |
4695 | Spelling += S.nameSpace() + "::" ; |
4696 | if (S.variety() == "GNU" ) |
4697 | Spelling += NormalizeGNUAttrSpelling(AttrSpelling: RawSpelling); |
4698 | else |
4699 | Spelling += RawSpelling; |
4700 | OS << " {AttributeCommonInfo::AS_" << S.variety(); |
4701 | OS << ", \"" << Spelling << "\"},\n" ; |
4702 | } |
4703 | OS << "};\n" ; |
4704 | } |
4705 | |
4706 | std::vector<std::string> ArgNames; |
4707 | for (const auto &Arg : Attr.getValueAsListOfDefs(FieldName: "Args" )) { |
4708 | bool UnusedUnset; |
4709 | if (Arg->getValueAsBitOrUnset(FieldName: "Fake" , Unset&: UnusedUnset)) |
4710 | continue; |
4711 | ArgNames.push_back(x: Arg->getValueAsString(FieldName: "Name" ).str()); |
4712 | for (const auto &Class : Arg->getSuperClasses()) { |
4713 | if (Class.first->getName().starts_with(Prefix: "Variadic" )) { |
4714 | ArgNames.back().append(s: "..." ); |
4715 | break; |
4716 | } |
4717 | } |
4718 | } |
4719 | if (!ArgNames.empty()) { |
4720 | OS << "static constexpr const char *" << I->first << "ArgNames[] = {\n" ; |
4721 | for (const auto &N : ArgNames) |
4722 | OS << '"' << N << "\"," ; |
4723 | OS << "};\n" ; |
4724 | } |
4725 | |
4726 | OS << "struct ParsedAttrInfo" << I->first |
4727 | << " final : public ParsedAttrInfo {\n" ; |
4728 | OS << " constexpr ParsedAttrInfo" << I->first << "() : ParsedAttrInfo(\n" ; |
4729 | OS << " /*AttrKind=*/ParsedAttr::AT_" << AttrName << ",\n" ; |
4730 | emitArgInfo(R: Attr, OS); |
4731 | OS << " /*HasCustomParsing=*/" ; |
4732 | OS << Attr.getValueAsBit(FieldName: "HasCustomParsing" ) << ",\n" ; |
4733 | OS << " /*AcceptsExprPack=*/" ; |
4734 | OS << Attr.getValueAsBit(FieldName: "AcceptsExprPack" ) << ",\n" ; |
4735 | OS << " /*IsTargetSpecific=*/" ; |
4736 | OS << Attr.isSubClassOf(Name: "TargetSpecificAttr" ) << ",\n" ; |
4737 | OS << " /*IsType=*/" ; |
4738 | OS << (Attr.isSubClassOf(Name: "TypeAttr" ) || Attr.isSubClassOf(Name: "DeclOrTypeAttr" )) |
4739 | << ",\n" ; |
4740 | OS << " /*IsStmt=*/" ; |
4741 | OS << (Attr.isSubClassOf(Name: "StmtAttr" ) || Attr.isSubClassOf(Name: "DeclOrStmtAttr" )) |
4742 | << ",\n" ; |
4743 | OS << " /*IsKnownToGCC=*/" ; |
4744 | OS << IsKnownToGCC(Attr) << ",\n" ; |
4745 | OS << " /*IsSupportedByPragmaAttribute=*/" ; |
4746 | OS << PragmaAttributeSupport.isAttributedSupported(Attribute: *I->second) << ",\n" ; |
4747 | if (!Spellings.empty()) |
4748 | OS << " /*Spellings=*/" << I->first << "Spellings,\n" ; |
4749 | else |
4750 | OS << " /*Spellings=*/{},\n" ; |
4751 | if (!ArgNames.empty()) |
4752 | OS << " /*ArgNames=*/" << I->first << "ArgNames" ; |
4753 | else |
4754 | OS << " /*ArgNames=*/{}" ; |
4755 | OS << ") {}\n" ; |
4756 | GenerateAppertainsTo(Attr, OS); |
4757 | GenerateMutualExclusionsChecks(Attr, Records, OS, MergeDeclOS, MergeStmtOS); |
4758 | GenerateLangOptRequirements(R: Attr, OS); |
4759 | GenerateTargetRequirements(Attr, Dupes, OS); |
4760 | GenerateSpellingTargetRequirements( |
4761 | Attr, TargetSpellings: Attr.getValueAsListOfDefs(FieldName: "TargetSpecificSpellings" ), OS); |
4762 | GenerateSpellingIndexToSemanticSpelling(Attr, OS); |
4763 | PragmaAttributeSupport.generateStrictConformsTo(Attr: *I->second, OS); |
4764 | GenerateHandleDeclAttribute(Attr, OS); |
4765 | GenerateIsParamExpr(Attr, OS); |
4766 | OS << "static const ParsedAttrInfo" << I->first << " Instance;\n" ; |
4767 | OS << "};\n" ; |
4768 | OS << "const ParsedAttrInfo" << I->first << " ParsedAttrInfo" << I->first |
4769 | << "::Instance;\n" ; |
4770 | } |
4771 | |
4772 | OS << "static const ParsedAttrInfo *AttrInfoMap[] = {\n" ; |
4773 | for (auto I = Attrs.begin(), E = Attrs.end(); I != E; ++I) { |
4774 | OS << "&ParsedAttrInfo" << I->first << "::Instance,\n" ; |
4775 | } |
4776 | OS << "};\n\n" ; |
4777 | |
4778 | // Generate function for handling attributes with delayed arguments |
4779 | GenerateHandleAttrWithDelayedArgs(Records, OS); |
4780 | |
4781 | // Generate the attribute match rules. |
4782 | emitAttributeMatchRules(PragmaAttributeSupport, OS); |
4783 | |
4784 | OS << "#elif defined(WANT_DECL_MERGE_LOGIC)\n\n" ; |
4785 | |
4786 | // Write out the declaration merging check logic. |
4787 | OS << "static bool DiagnoseMutualExclusions(Sema &S, const NamedDecl *D, " |
4788 | << "const Attr *A) {\n" ; |
4789 | OS << DeclMergeChecks; |
4790 | OS << " return true;\n" ; |
4791 | OS << "}\n\n" ; |
4792 | |
4793 | OS << "#elif defined(WANT_STMT_MERGE_LOGIC)\n\n" ; |
4794 | |
4795 | // Write out the statement merging check logic. |
4796 | OS << "static bool DiagnoseMutualExclusions(Sema &S, " |
4797 | << "const SmallVectorImpl<const Attr *> &C) {\n" ; |
4798 | OS << " for (const Attr *A : C) {\n" ; |
4799 | OS << StmtMergeChecks; |
4800 | OS << " }\n" ; |
4801 | OS << " return true;\n" ; |
4802 | OS << "}\n\n" ; |
4803 | |
4804 | OS << "#endif\n" ; |
4805 | } |
4806 | |
4807 | // Emits the kind list of parsed attributes |
4808 | void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) { |
4809 | emitSourceFileHeader(Desc: "Attribute name matcher" , OS, Record: Records); |
4810 | |
4811 | std::vector<Record *> Attrs = Records.getAllDerivedDefinitions(ClassName: "Attr" ); |
4812 | std::vector<StringMatcher::StringPair> GNU, Declspec, Microsoft, CXX11, |
4813 | Keywords, Pragma, C23, HLSLAnnotation; |
4814 | std::set<std::string> Seen; |
4815 | for (const auto *A : Attrs) { |
4816 | const Record &Attr = *A; |
4817 | |
4818 | bool SemaHandler = Attr.getValueAsBit(FieldName: "SemaHandler" ); |
4819 | bool Ignored = Attr.getValueAsBit(FieldName: "Ignored" ); |
4820 | if (SemaHandler || Ignored) { |
4821 | // Attribute spellings can be shared between target-specific attributes, |
4822 | // and can be shared between syntaxes for the same attribute. For |
4823 | // instance, an attribute can be spelled GNU<"interrupt"> for an ARM- |
4824 | // specific attribute, or MSP430-specific attribute. Additionally, an |
4825 | // attribute can be spelled GNU<"dllexport"> and Declspec<"dllexport"> |
4826 | // for the same semantic attribute. Ultimately, we need to map each of |
4827 | // these to a single AttributeCommonInfo::Kind value, but the |
4828 | // StringMatcher class cannot handle duplicate match strings. So we |
4829 | // generate a list of string to match based on the syntax, and emit |
4830 | // multiple string matchers depending on the syntax used. |
4831 | std::string AttrName; |
4832 | if (Attr.isSubClassOf(Name: "TargetSpecificAttr" ) && |
4833 | !Attr.isValueUnset(FieldName: "ParseKind" )) { |
4834 | AttrName = std::string(Attr.getValueAsString(FieldName: "ParseKind" )); |
4835 | if (!Seen.insert(x: AttrName).second) |
4836 | continue; |
4837 | } else |
4838 | AttrName = NormalizeAttrName(AttrName: StringRef(Attr.getName())).str(); |
4839 | |
4840 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr); |
4841 | for (const auto &S : Spellings) { |
4842 | const std::string &RawSpelling = S.name(); |
4843 | std::vector<StringMatcher::StringPair> *Matches = nullptr; |
4844 | std::string Spelling; |
4845 | const std::string &Variety = S.variety(); |
4846 | if (Variety == "CXX11" ) { |
4847 | Matches = &CXX11; |
4848 | if (!S.nameSpace().empty()) |
4849 | Spelling += S.nameSpace() + "::" ; |
4850 | } else if (Variety == "C23" ) { |
4851 | Matches = &C23; |
4852 | if (!S.nameSpace().empty()) |
4853 | Spelling += S.nameSpace() + "::" ; |
4854 | } else if (Variety == "GNU" ) |
4855 | Matches = &GNU; |
4856 | else if (Variety == "Declspec" ) |
4857 | Matches = &Declspec; |
4858 | else if (Variety == "Microsoft" ) |
4859 | Matches = &Microsoft; |
4860 | else if (Variety == "Keyword" ) |
4861 | Matches = &Keywords; |
4862 | else if (Variety == "Pragma" ) |
4863 | Matches = &Pragma; |
4864 | else if (Variety == "HLSLAnnotation" ) |
4865 | Matches = &HLSLAnnotation; |
4866 | |
4867 | assert(Matches && "Unsupported spelling variety found" ); |
4868 | |
4869 | if (Variety == "GNU" ) |
4870 | Spelling += NormalizeGNUAttrSpelling(AttrSpelling: RawSpelling); |
4871 | else |
4872 | Spelling += RawSpelling; |
4873 | |
4874 | if (SemaHandler) |
4875 | Matches->push_back(x: StringMatcher::StringPair( |
4876 | Spelling, "return AttributeCommonInfo::AT_" + AttrName + ";" )); |
4877 | else |
4878 | Matches->push_back(x: StringMatcher::StringPair( |
4879 | Spelling, "return AttributeCommonInfo::IgnoredAttribute;" )); |
4880 | } |
4881 | } |
4882 | } |
4883 | |
4884 | OS << "static AttributeCommonInfo::Kind getAttrKind(StringRef Name, " ; |
4885 | OS << "AttributeCommonInfo::Syntax Syntax) {\n" ; |
4886 | OS << " if (AttributeCommonInfo::AS_GNU == Syntax) {\n" ; |
4887 | StringMatcher("Name" , GNU, OS).Emit(); |
4888 | OS << " } else if (AttributeCommonInfo::AS_Declspec == Syntax) {\n" ; |
4889 | StringMatcher("Name" , Declspec, OS).Emit(); |
4890 | OS << " } else if (AttributeCommonInfo::AS_Microsoft == Syntax) {\n" ; |
4891 | StringMatcher("Name" , Microsoft, OS).Emit(); |
4892 | OS << " } else if (AttributeCommonInfo::AS_CXX11 == Syntax) {\n" ; |
4893 | StringMatcher("Name" , CXX11, OS).Emit(); |
4894 | OS << " } else if (AttributeCommonInfo::AS_C23 == Syntax) {\n" ; |
4895 | StringMatcher("Name" , C23, OS).Emit(); |
4896 | OS << " } else if (AttributeCommonInfo::AS_Keyword == Syntax || " ; |
4897 | OS << "AttributeCommonInfo::AS_ContextSensitiveKeyword == Syntax) {\n" ; |
4898 | StringMatcher("Name" , Keywords, OS).Emit(); |
4899 | OS << " } else if (AttributeCommonInfo::AS_Pragma == Syntax) {\n" ; |
4900 | StringMatcher("Name" , Pragma, OS).Emit(); |
4901 | OS << " } else if (AttributeCommonInfo::AS_HLSLAnnotation == Syntax) {\n" ; |
4902 | StringMatcher("Name" , HLSLAnnotation, OS).Emit(); |
4903 | OS << " }\n" ; |
4904 | OS << " return AttributeCommonInfo::UnknownAttribute;\n" |
4905 | << "}\n" ; |
4906 | } |
4907 | |
4908 | // Emits the code to dump an attribute. |
4909 | void EmitClangAttrTextNodeDump(RecordKeeper &Records, raw_ostream &OS) { |
4910 | emitSourceFileHeader(Desc: "Attribute text node dumper" , OS, Record: Records); |
4911 | |
4912 | std::vector<Record*> Attrs = Records.getAllDerivedDefinitions(ClassName: "Attr" ), Args; |
4913 | for (const auto *Attr : Attrs) { |
4914 | const Record &R = *Attr; |
4915 | if (!R.getValueAsBit(FieldName: "ASTNode" )) |
4916 | continue; |
4917 | |
4918 | // If the attribute has a semantically-meaningful name (which is determined |
4919 | // by whether there is a Spelling enumeration for it), then write out the |
4920 | // spelling used for the attribute. |
4921 | |
4922 | std::string FunctionContent; |
4923 | llvm::raw_string_ostream SS(FunctionContent); |
4924 | |
4925 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr: R); |
4926 | if (Spellings.size() > 1 && !SpellingNamesAreCommon(Spellings)) |
4927 | SS << " OS << \" \" << A->getSpelling();\n" ; |
4928 | |
4929 | Args = R.getValueAsListOfDefs(FieldName: "Args" ); |
4930 | for (const auto *Arg : Args) |
4931 | createArgument(Arg: *Arg, Attr: R.getName())->writeDump(OS&: SS); |
4932 | |
4933 | if (Attr->getValueAsBit(FieldName: "AcceptsExprPack" )) |
4934 | VariadicExprArgument("DelayedArgs" , R.getName()).writeDump(OS); |
4935 | |
4936 | if (SS.tell()) { |
4937 | OS << " void Visit" << R.getName() << "Attr(const " << R.getName() |
4938 | << "Attr *A) {\n" ; |
4939 | if (!Args.empty()) |
4940 | OS << " const auto *SA = cast<" << R.getName() |
4941 | << "Attr>(A); (void)SA;\n" ; |
4942 | OS << FunctionContent; |
4943 | OS << " }\n" ; |
4944 | } |
4945 | } |
4946 | } |
4947 | |
4948 | void EmitClangAttrNodeTraverse(RecordKeeper &Records, raw_ostream &OS) { |
4949 | emitSourceFileHeader(Desc: "Attribute text node traverser" , OS, Record: Records); |
4950 | |
4951 | std::vector<Record *> Attrs = Records.getAllDerivedDefinitions(ClassName: "Attr" ), Args; |
4952 | for (const auto *Attr : Attrs) { |
4953 | const Record &R = *Attr; |
4954 | if (!R.getValueAsBit(FieldName: "ASTNode" )) |
4955 | continue; |
4956 | |
4957 | std::string FunctionContent; |
4958 | llvm::raw_string_ostream SS(FunctionContent); |
4959 | |
4960 | Args = R.getValueAsListOfDefs(FieldName: "Args" ); |
4961 | for (const auto *Arg : Args) |
4962 | createArgument(Arg: *Arg, Attr: R.getName())->writeDumpChildren(OS&: SS); |
4963 | if (Attr->getValueAsBit(FieldName: "AcceptsExprPack" )) |
4964 | VariadicExprArgument("DelayedArgs" , R.getName()).writeDumpChildren(OS&: SS); |
4965 | if (SS.tell()) { |
4966 | OS << " void Visit" << R.getName() << "Attr(const " << R.getName() |
4967 | << "Attr *A) {\n" ; |
4968 | if (!Args.empty()) |
4969 | OS << " const auto *SA = cast<" << R.getName() |
4970 | << "Attr>(A); (void)SA;\n" ; |
4971 | OS << FunctionContent; |
4972 | OS << " }\n" ; |
4973 | } |
4974 | } |
4975 | } |
4976 | |
4977 | void EmitClangAttrParserStringSwitches(RecordKeeper &Records, raw_ostream &OS) { |
4978 | emitSourceFileHeader(Desc: "Parser-related llvm::StringSwitch cases" , OS, Record: Records); |
4979 | emitClangAttrArgContextList(Records, OS); |
4980 | emitClangAttrIdentifierArgList(Records, OS); |
4981 | emitClangAttrUnevaluatedStringLiteralList(Records, OS); |
4982 | emitClangAttrVariadicIdentifierArgList(Records, OS); |
4983 | emitClangAttrThisIsaIdentifierArgList(Records, OS); |
4984 | emitClangAttrAcceptsExprPack(Records, OS); |
4985 | emitClangAttrTypeArgList(Records, OS); |
4986 | emitClangAttrLateParsedList(Records, OS); |
4987 | emitClangAttrLateParsedExperimentalList(Records, OS); |
4988 | emitClangAttrStrictIdentifierArgAtIndexList(Records, OS); |
4989 | } |
4990 | |
4991 | void EmitClangAttrSubjectMatchRulesParserStringSwitches(RecordKeeper &Records, |
4992 | raw_ostream &OS) { |
4993 | getPragmaAttributeSupport(Records).generateParsingHelpers(OS); |
4994 | } |
4995 | |
4996 | void EmitClangAttrDocTable(RecordKeeper &Records, raw_ostream &OS) { |
4997 | emitSourceFileHeader(Desc: "Clang attribute documentation" , OS, Record: Records); |
4998 | |
4999 | std::vector<Record *> Attrs = Records.getAllDerivedDefinitions(ClassName: "Attr" ); |
5000 | for (const auto *A : Attrs) { |
5001 | if (!A->getValueAsBit(FieldName: "ASTNode" )) |
5002 | continue; |
5003 | std::vector<Record *> Docs = A->getValueAsListOfDefs(FieldName: "Documentation" ); |
5004 | assert(!Docs.empty()); |
5005 | // Only look at the first documentation if there are several. |
5006 | // (Currently there's only one such attr, revisit if this becomes common). |
5007 | StringRef Text = |
5008 | Docs.front()->getValueAsOptionalString(FieldName: "Content" ).value_or(u: "" ); |
5009 | OS << "\nstatic const char AttrDoc_" << A->getName() << "[] = " |
5010 | << "R\"reST(" << Text.trim() << ")reST\";\n" ; |
5011 | } |
5012 | } |
5013 | |
5014 | enum class SpellingKind : size_t { |
5015 | GNU, |
5016 | CXX11, |
5017 | C23, |
5018 | Declspec, |
5019 | Microsoft, |
5020 | Keyword, |
5021 | Pragma, |
5022 | HLSLAnnotation, |
5023 | NumSpellingKinds |
5024 | }; |
5025 | static const size_t NumSpellingKinds = (size_t)SpellingKind::NumSpellingKinds; |
5026 | |
5027 | class SpellingList { |
5028 | std::vector<std::string> Spellings[NumSpellingKinds]; |
5029 | |
5030 | public: |
5031 | ArrayRef<std::string> operator[](SpellingKind K) const { |
5032 | return Spellings[(size_t)K]; |
5033 | } |
5034 | |
5035 | void add(const Record &Attr, FlattenedSpelling Spelling) { |
5036 | SpellingKind Kind = |
5037 | StringSwitch<SpellingKind>(Spelling.variety()) |
5038 | .Case(S: "GNU" , Value: SpellingKind::GNU) |
5039 | .Case(S: "CXX11" , Value: SpellingKind::CXX11) |
5040 | .Case(S: "C23" , Value: SpellingKind::C23) |
5041 | .Case(S: "Declspec" , Value: SpellingKind::Declspec) |
5042 | .Case(S: "Microsoft" , Value: SpellingKind::Microsoft) |
5043 | .Case(S: "Keyword" , Value: SpellingKind::Keyword) |
5044 | .Case(S: "Pragma" , Value: SpellingKind::Pragma) |
5045 | .Case(S: "HLSLAnnotation" , Value: SpellingKind::HLSLAnnotation); |
5046 | std::string Name; |
5047 | if (!Spelling.nameSpace().empty()) { |
5048 | switch (Kind) { |
5049 | case SpellingKind::CXX11: |
5050 | case SpellingKind::C23: |
5051 | Name = Spelling.nameSpace() + "::" ; |
5052 | break; |
5053 | case SpellingKind::Pragma: |
5054 | Name = Spelling.nameSpace() + " " ; |
5055 | break; |
5056 | default: |
5057 | PrintFatalError(ErrorLoc: Attr.getLoc(), Msg: "Unexpected namespace in spelling" ); |
5058 | } |
5059 | } |
5060 | Name += Spelling.name(); |
5061 | |
5062 | Spellings[(size_t)Kind].push_back(x: Name); |
5063 | } |
5064 | }; |
5065 | |
5066 | class DocumentationData { |
5067 | public: |
5068 | const Record *Documentation; |
5069 | const Record *Attribute; |
5070 | std::string Heading; |
5071 | SpellingList SupportedSpellings; |
5072 | |
5073 | DocumentationData(const Record &Documentation, const Record &Attribute, |
5074 | std::pair<std::string, SpellingList> HeadingAndSpellings) |
5075 | : Documentation(&Documentation), Attribute(&Attribute), |
5076 | Heading(std::move(HeadingAndSpellings.first)), |
5077 | SupportedSpellings(std::move(HeadingAndSpellings.second)) {} |
5078 | }; |
5079 | |
5080 | static void (const Record *DocCategory, |
5081 | raw_ostream &OS) { |
5082 | const StringRef Name = DocCategory->getValueAsString(FieldName: "Name" ); |
5083 | OS << Name << "\n" << std::string(Name.size(), '=') << "\n" ; |
5084 | |
5085 | // If there is content, print that as well. |
5086 | const StringRef ContentStr = DocCategory->getValueAsString(FieldName: "Content" ); |
5087 | // Trim leading and trailing newlines and spaces. |
5088 | OS << ContentStr.trim(); |
5089 | |
5090 | OS << "\n\n" ; |
5091 | } |
5092 | |
5093 | static std::pair<std::string, SpellingList> |
5094 | GetAttributeHeadingAndSpellings(const Record &Documentation, |
5095 | const Record &Attribute, |
5096 | StringRef Cat) { |
5097 | // FIXME: there is no way to have a per-spelling category for the attribute |
5098 | // documentation. This may not be a limiting factor since the spellings |
5099 | // should generally be consistently applied across the category. |
5100 | |
5101 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr: Attribute); |
5102 | if (Spellings.empty()) |
5103 | PrintFatalError(ErrorLoc: Attribute.getLoc(), |
5104 | Msg: "Attribute has no supported spellings; cannot be " |
5105 | "documented" ); |
5106 | |
5107 | // Determine the heading to be used for this attribute. |
5108 | std::string Heading = std::string(Documentation.getValueAsString(FieldName: "Heading" )); |
5109 | if (Heading.empty()) { |
5110 | // If there's only one spelling, we can simply use that. |
5111 | if (Spellings.size() == 1) |
5112 | Heading = Spellings.begin()->name(); |
5113 | else { |
5114 | std::set<std::string> Uniques; |
5115 | for (auto I = Spellings.begin(), E = Spellings.end(); |
5116 | I != E; ++I) { |
5117 | std::string Spelling = |
5118 | std::string(NormalizeNameForSpellingComparison(Name: I->name())); |
5119 | Uniques.insert(x: Spelling); |
5120 | } |
5121 | // If the semantic map has only one spelling, that is sufficient for our |
5122 | // needs. |
5123 | if (Uniques.size() == 1) |
5124 | Heading = *Uniques.begin(); |
5125 | // If it's in the undocumented category, just construct a header by |
5126 | // concatenating all the spellings. Might not be great, but better than |
5127 | // nothing. |
5128 | else if (Cat == "Undocumented" ) |
5129 | Heading = llvm::join(Begin: Uniques.begin(), End: Uniques.end(), Separator: ", " ); |
5130 | } |
5131 | } |
5132 | |
5133 | // If the heading is still empty, it is an error. |
5134 | if (Heading.empty()) |
5135 | PrintFatalError(ErrorLoc: Attribute.getLoc(), |
5136 | Msg: "This attribute requires a heading to be specified" ); |
5137 | |
5138 | SpellingList SupportedSpellings; |
5139 | for (const auto &I : Spellings) |
5140 | SupportedSpellings.add(Attr: Attribute, Spelling: I); |
5141 | |
5142 | return std::make_pair(x: std::move(Heading), y: std::move(SupportedSpellings)); |
5143 | } |
5144 | |
5145 | static void WriteDocumentation(RecordKeeper &Records, |
5146 | const DocumentationData &Doc, raw_ostream &OS) { |
5147 | OS << Doc.Heading << "\n" << std::string(Doc.Heading.length(), '-') << "\n" ; |
5148 | |
5149 | // List what spelling syntaxes the attribute supports. |
5150 | // Note: "#pragma clang attribute" is handled outside the spelling kinds loop |
5151 | // so it must be last. |
5152 | OS << ".. csv-table:: Supported Syntaxes\n" ; |
5153 | OS << " :header: \"GNU\", \"C++11\", \"C23\", \"``__declspec``\"," ; |
5154 | OS << " \"Keyword\", \"``#pragma``\", \"HLSL Annotation\", \"``#pragma " |
5155 | "clang " ; |
5156 | OS << "attribute``\"\n\n \"" ; |
5157 | for (size_t Kind = 0; Kind != NumSpellingKinds; ++Kind) { |
5158 | SpellingKind K = (SpellingKind)Kind; |
5159 | // TODO: List Microsoft (IDL-style attribute) spellings once we fully |
5160 | // support them. |
5161 | if (K == SpellingKind::Microsoft) |
5162 | continue; |
5163 | |
5164 | bool PrintedAny = false; |
5165 | for (StringRef Spelling : Doc.SupportedSpellings[K]) { |
5166 | if (PrintedAny) |
5167 | OS << " |br| " ; |
5168 | OS << "``" << Spelling << "``" ; |
5169 | PrintedAny = true; |
5170 | } |
5171 | |
5172 | OS << "\",\"" ; |
5173 | } |
5174 | |
5175 | if (getPragmaAttributeSupport(Records).isAttributedSupported( |
5176 | Attribute: *Doc.Attribute)) |
5177 | OS << "Yes" ; |
5178 | OS << "\"\n\n" ; |
5179 | |
5180 | // If the attribute is deprecated, print a message about it, and possibly |
5181 | // provide a replacement attribute. |
5182 | if (!Doc.Documentation->isValueUnset(FieldName: "Deprecated" )) { |
5183 | OS << "This attribute has been deprecated, and may be removed in a future " |
5184 | << "version of Clang." ; |
5185 | const Record &Deprecated = *Doc.Documentation->getValueAsDef(FieldName: "Deprecated" ); |
5186 | const StringRef Replacement = Deprecated.getValueAsString(FieldName: "Replacement" ); |
5187 | if (!Replacement.empty()) |
5188 | OS << " This attribute has been superseded by ``" << Replacement |
5189 | << "``." ; |
5190 | OS << "\n\n" ; |
5191 | } |
5192 | |
5193 | const StringRef ContentStr = Doc.Documentation->getValueAsString(FieldName: "Content" ); |
5194 | // Trim leading and trailing newlines and spaces. |
5195 | OS << ContentStr.trim(); |
5196 | |
5197 | OS << "\n\n\n" ; |
5198 | } |
5199 | |
5200 | void EmitClangAttrDocs(RecordKeeper &Records, raw_ostream &OS) { |
5201 | // Get the documentation introduction paragraph. |
5202 | const Record *Documentation = Records.getDef(Name: "GlobalDocumentation" ); |
5203 | if (!Documentation) { |
5204 | PrintFatalError(Msg: "The Documentation top-level definition is missing, " |
5205 | "no documentation will be generated." ); |
5206 | return; |
5207 | } |
5208 | |
5209 | OS << Documentation->getValueAsString(FieldName: "Intro" ) << "\n" ; |
5210 | |
5211 | // Gather the Documentation lists from each of the attributes, based on the |
5212 | // category provided. |
5213 | std::vector<Record *> Attrs = Records.getAllDerivedDefinitions(ClassName: "Attr" ); |
5214 | struct CategoryLess { |
5215 | bool operator()(const Record *L, const Record *R) const { |
5216 | return L->getValueAsString(FieldName: "Name" ) < R->getValueAsString(FieldName: "Name" ); |
5217 | } |
5218 | }; |
5219 | std::map<const Record *, std::vector<DocumentationData>, CategoryLess> |
5220 | SplitDocs; |
5221 | for (const auto *A : Attrs) { |
5222 | const Record &Attr = *A; |
5223 | std::vector<Record *> Docs = Attr.getValueAsListOfDefs(FieldName: "Documentation" ); |
5224 | for (const auto *D : Docs) { |
5225 | const Record &Doc = *D; |
5226 | const Record *Category = Doc.getValueAsDef(FieldName: "Category" ); |
5227 | // If the category is "InternalOnly", then there cannot be any other |
5228 | // documentation categories (otherwise, the attribute would be |
5229 | // emitted into the docs). |
5230 | const StringRef Cat = Category->getValueAsString(FieldName: "Name" ); |
5231 | bool InternalOnly = Cat == "InternalOnly" ; |
5232 | if (InternalOnly && Docs.size() > 1) |
5233 | PrintFatalError(ErrorLoc: Doc.getLoc(), |
5234 | Msg: "Attribute is \"InternalOnly\", but has multiple " |
5235 | "documentation categories" ); |
5236 | |
5237 | if (!InternalOnly) |
5238 | SplitDocs[Category].push_back(x: DocumentationData( |
5239 | Doc, Attr, GetAttributeHeadingAndSpellings(Documentation: Doc, Attribute: Attr, Cat))); |
5240 | } |
5241 | } |
5242 | |
5243 | // Having split the attributes out based on what documentation goes where, |
5244 | // we can begin to generate sections of documentation. |
5245 | for (auto &I : SplitDocs) { |
5246 | WriteCategoryHeader(DocCategory: I.first, OS); |
5247 | |
5248 | llvm::sort(C&: I.second, |
5249 | Comp: [](const DocumentationData &D1, const DocumentationData &D2) { |
5250 | return D1.Heading < D2.Heading; |
5251 | }); |
5252 | |
5253 | // Walk over each of the attributes in the category and write out their |
5254 | // documentation. |
5255 | for (const auto &Doc : I.second) |
5256 | WriteDocumentation(Records, Doc, OS); |
5257 | } |
5258 | } |
5259 | |
5260 | void EmitTestPragmaAttributeSupportedAttributes(RecordKeeper &Records, |
5261 | raw_ostream &OS) { |
5262 | PragmaClangAttributeSupport Support = getPragmaAttributeSupport(Records); |
5263 | ParsedAttrMap Attrs = getParsedAttrList(Records); |
5264 | OS << "#pragma clang attribute supports the following attributes:\n" ; |
5265 | for (const auto &I : Attrs) { |
5266 | if (!Support.isAttributedSupported(Attribute: *I.second)) |
5267 | continue; |
5268 | OS << I.first; |
5269 | if (I.second->isValueUnset(FieldName: "Subjects" )) { |
5270 | OS << " ()\n" ; |
5271 | continue; |
5272 | } |
5273 | const Record *SubjectObj = I.second->getValueAsDef(FieldName: "Subjects" ); |
5274 | std::vector<Record *> Subjects = |
5275 | SubjectObj->getValueAsListOfDefs(FieldName: "Subjects" ); |
5276 | OS << " (" ; |
5277 | bool PrintComma = false; |
5278 | for (const auto &Subject : llvm::enumerate(First&: Subjects)) { |
5279 | if (!isSupportedPragmaClangAttributeSubject(Subject: *Subject.value())) |
5280 | continue; |
5281 | if (PrintComma) |
5282 | OS << ", " ; |
5283 | PrintComma = true; |
5284 | PragmaClangAttributeSupport::RuleOrAggregateRuleSet &RuleSet = |
5285 | Support.SubjectsToRules.find(Val: Subject.value())->getSecond(); |
5286 | if (RuleSet.isRule()) { |
5287 | OS << RuleSet.getRule().getEnumValueName(); |
5288 | continue; |
5289 | } |
5290 | OS << "(" ; |
5291 | for (const auto &Rule : llvm::enumerate(First: RuleSet.getAggregateRuleSet())) { |
5292 | if (Rule.index()) |
5293 | OS << ", " ; |
5294 | OS << Rule.value().getEnumValueName(); |
5295 | } |
5296 | OS << ")" ; |
5297 | } |
5298 | OS << ")\n" ; |
5299 | } |
5300 | OS << "End of supported attributes.\n" ; |
5301 | } |
5302 | |
5303 | } // end namespace clang |
5304 | |