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