clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ClangAttrEmitter.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/gnu/usr.bin/clang/clang-tblgen/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/gnu/usr.bin/clang/clang-tblgen/../../../llvm/llvm/include -I /usr/src/gnu/usr.bin/clang/clang-tblgen/../include -I /usr/src/gnu/usr.bin/clang/clang-tblgen/obj -I /usr/src/gnu/usr.bin/clang/clang-tblgen/obj/../include -D NDEBUG -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D LLVM_PREFIX="/usr" -internal-isystem /usr/include/c++/v1 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/usr/src/gnu/usr.bin/clang/clang-tblgen/obj -ferror-limit 19 -fvisibility-inlines-hidden -fwrapv -stack-protector 2 -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c++ /usr/src/gnu/usr.bin/clang/clang-tblgen/../../../llvm/clang/utils/TableGen/ClangAttrEmitter.cpp
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
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/STLExtras.h" |
20 | #include "llvm/ADT/SmallString.h" |
21 | #include "llvm/ADT/StringExtras.h" |
22 | #include "llvm/ADT/StringRef.h" |
23 | #include "llvm/ADT/StringSet.h" |
24 | #include "llvm/ADT/StringSwitch.h" |
25 | #include "llvm/ADT/iterator_range.h" |
26 | #include "llvm/Support/ErrorHandling.h" |
27 | #include "llvm/Support/raw_ostream.h" |
28 | #include "llvm/TableGen/Error.h" |
29 | #include "llvm/TableGen/Record.h" |
30 | #include "llvm/TableGen/StringMatcher.h" |
31 | #include "llvm/TableGen/TableGenBackend.h" |
32 | #include <algorithm> |
33 | #include <cassert> |
34 | #include <cctype> |
35 | #include <cstddef> |
36 | #include <cstdint> |
37 | #include <map> |
38 | #include <memory> |
39 | #include <set> |
40 | #include <sstream> |
41 | #include <string> |
42 | #include <utility> |
43 | #include <vector> |
44 | |
45 | using namespace llvm; |
46 | |
47 | namespace { |
48 | |
49 | class FlattenedSpelling { |
50 | std::string V, N, NS; |
51 | bool K = false; |
52 | |
53 | public: |
54 | FlattenedSpelling(const std::string &Variety, const std::string &Name, |
55 | const std::string &Namespace, bool KnownToGCC) : |
56 | V(Variety), N(Name), NS(Namespace), K(KnownToGCC) {} |
57 | explicit FlattenedSpelling(const Record &Spelling) |
58 | : V(std::string(Spelling.getValueAsString("Variety"))), |
59 | N(std::string(Spelling.getValueAsString("Name"))) { |
60 | assert(V != "GCC" && V != "Clang" && |
61 | "Given a GCC spelling, which means this hasn't been flattened!"); |
62 | if (V == "CXX11" || V == "C2x" || V == "Pragma") |
63 | NS = std::string(Spelling.getValueAsString("Namespace")); |
64 | } |
65 | |
66 | const std::string &variety() const { return V; } |
67 | const std::string &name() const { return N; } |
68 | const std::string &nameSpace() const { return NS; } |
69 | bool knownToGCC() const { return K; } |
70 | }; |
71 | |
72 | } |
73 | |
74 | static std::vector<FlattenedSpelling> |
75 | GetFlattenedSpellings(const Record &Attr) { |
76 | std::vector<Record *> Spellings = Attr.getValueAsListOfDefs("Spellings"); |
77 | std::vector<FlattenedSpelling> Ret; |
78 | |
79 | for (const auto &Spelling : Spellings) { |
80 | StringRef Variety = Spelling->getValueAsString("Variety"); |
81 | StringRef Name = Spelling->getValueAsString("Name"); |
82 | if (Variety == "GCC") { |
83 | Ret.emplace_back("GNU", std::string(Name), "", true); |
84 | Ret.emplace_back("CXX11", std::string(Name), "gnu", true); |
85 | if (Spelling->getValueAsBit("AllowInC")) |
86 | Ret.emplace_back("C2x", std::string(Name), "gnu", true); |
87 | } else if (Variety == "Clang") { |
88 | Ret.emplace_back("GNU", std::string(Name), "", false); |
89 | Ret.emplace_back("CXX11", std::string(Name), "clang", false); |
90 | if (Spelling->getValueAsBit("AllowInC")) |
91 | Ret.emplace_back("C2x", std::string(Name), "clang", false); |
92 | } else |
93 | Ret.push_back(FlattenedSpelling(*Spelling)); |
94 | } |
95 | |
96 | return Ret; |
97 | } |
98 | |
99 | static std::string ReadPCHRecord(StringRef type) { |
100 | return StringSwitch<std::string>(type) |
101 | .EndsWith("Decl *", "Record.GetLocalDeclAs<" + |
102 | std::string(type.data(), 0, type.size() - 1) + |
103 | ">(Record.readInt())") |
104 | .Case("TypeSourceInfo *", "Record.readTypeSourceInfo()") |
105 | .Case("Expr *", "Record.readExpr()") |
106 | .Case("IdentifierInfo *", "Record.readIdentifier()") |
107 | .Case("StringRef", "Record.readString()") |
108 | .Case("ParamIdx", "ParamIdx::deserialize(Record.readInt())") |
109 | .Case("OMPTraitInfo *", "Record.readOMPTraitInfo()") |
110 | .Default("Record.readInt()"); |
111 | } |
112 | |
113 | |
114 | static StringRef getStorageType(StringRef type) { |
115 | return StringSwitch<StringRef>(type) |
116 | .Case("StringRef", "std::string") |
117 | .Default(type); |
118 | } |
119 | |
120 | |
121 | static std::string WritePCHRecord(StringRef type, StringRef name) { |
122 | return "Record." + |
123 | StringSwitch<std::string>(type) |
124 | .EndsWith("Decl *", "AddDeclRef(" + std::string(name) + ");\n") |
125 | .Case("TypeSourceInfo *", |
126 | "AddTypeSourceInfo(" + std::string(name) + ");\n") |
127 | .Case("Expr *", "AddStmt(" + std::string(name) + ");\n") |
128 | .Case("IdentifierInfo *", |
129 | "AddIdentifierRef(" + std::string(name) + ");\n") |
130 | .Case("StringRef", "AddString(" + std::string(name) + ");\n") |
131 | .Case("ParamIdx", |
132 | "push_back(" + std::string(name) + ".serialize());\n") |
133 | .Case("OMPTraitInfo *", |
134 | "writeOMPTraitInfo(" + std::string(name) + ");\n") |
135 | .Default("push_back(" + std::string(name) + ");\n"); |
136 | } |
137 | |
138 | |
139 | |
140 | |
141 | static StringRef NormalizeAttrName(StringRef AttrName) { |
142 | AttrName.consume_front("__"); |
143 | AttrName.consume_back("__"); |
144 | return AttrName; |
145 | } |
146 | |
147 | |
148 | |
149 | |
150 | static StringRef NormalizeNameForSpellingComparison(StringRef Name) { |
151 | return Name.trim("_"); |
152 | } |
153 | |
154 | |
155 | |
156 | static StringRef NormalizeGNUAttrSpelling(StringRef AttrSpelling) { |
157 | if (AttrSpelling.startswith("__") && AttrSpelling.endswith("__")) { |
158 | AttrSpelling = AttrSpelling.substr(2, AttrSpelling.size() - 4); |
159 | } |
160 | |
161 | return AttrSpelling; |
162 | } |
163 | |
164 | typedef std::vector<std::pair<std::string, const Record *>> ParsedAttrMap; |
165 | |
166 | static ParsedAttrMap getParsedAttrList(const RecordKeeper &Records, |
167 | ParsedAttrMap *Dupes = nullptr) { |
168 | std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"); |
169 | std::set<std::string> Seen; |
170 | ParsedAttrMap R; |
171 | for (const auto *Attr : Attrs) { |
172 | if (Attr->getValueAsBit("SemaHandler")) { |
173 | std::string AN; |
174 | if (Attr->isSubClassOf("TargetSpecificAttr") && |
175 | !Attr->isValueUnset("ParseKind")) { |
176 | AN = std::string(Attr->getValueAsString("ParseKind")); |
177 | |
178 | |
179 | |
180 | if (Seen.find(AN) != Seen.end()) { |
181 | if (Dupes) |
182 | Dupes->push_back(std::make_pair(AN, Attr)); |
183 | continue; |
184 | } |
185 | Seen.insert(AN); |
186 | } else |
187 | AN = NormalizeAttrName(Attr->getName()).str(); |
188 | |
189 | R.push_back(std::make_pair(AN, Attr)); |
190 | } |
191 | } |
192 | return R; |
193 | } |
194 | |
195 | namespace { |
196 | |
197 | class Argument { |
198 | std::string lowerName, upperName; |
199 | StringRef attrName; |
200 | bool isOpt; |
201 | bool Fake; |
202 | |
203 | public: |
204 | Argument(const Record &Arg, StringRef Attr) |
205 | : lowerName(std::string(Arg.getValueAsString("Name"))), |
206 | upperName(lowerName), attrName(Attr), isOpt(false), Fake(false) { |
207 | if (!lowerName.empty()) { |
208 | lowerName[0] = std::tolower(lowerName[0]); |
209 | upperName[0] = std::toupper(upperName[0]); |
210 | } |
211 | |
212 | |
213 | |
214 | if (lowerName == "interface") |
215 | lowerName = "interface_"; |
216 | } |
217 | virtual ~Argument() = default; |
218 | |
219 | StringRef getLowerName() const { return lowerName; } |
220 | StringRef getUpperName() const { return upperName; } |
221 | StringRef getAttrName() const { return attrName; } |
222 | |
223 | bool isOptional() const { return isOpt; } |
224 | void setOptional(bool set) { isOpt = set; } |
225 | |
226 | bool isFake() const { return Fake; } |
227 | void setFake(bool fake) { Fake = fake; } |
228 | |
229 | |
230 | virtual void writeAccessors(raw_ostream &OS) const = 0; |
231 | virtual void writeAccessorDefinitions(raw_ostream &OS) const {} |
232 | virtual void writeASTVisitorTraversal(raw_ostream &OS) const {} |
233 | virtual void writeCloneArgs(raw_ostream &OS) const = 0; |
234 | virtual void writeTemplateInstantiationArgs(raw_ostream &OS) const = 0; |
235 | virtual void writeTemplateInstantiation(raw_ostream &OS) const {} |
236 | virtual void writeCtorBody(raw_ostream &OS) const {} |
237 | virtual void writeCtorInitializers(raw_ostream &OS) const = 0; |
238 | virtual void writeCtorDefaultInitializers(raw_ostream &OS) const = 0; |
239 | virtual void writeCtorParameters(raw_ostream &OS) const = 0; |
240 | virtual void writeDeclarations(raw_ostream &OS) const = 0; |
241 | virtual void writePCHReadArgs(raw_ostream &OS) const = 0; |
242 | virtual void writePCHReadDecls(raw_ostream &OS) const = 0; |
243 | virtual void writePCHWrite(raw_ostream &OS) const = 0; |
244 | virtual std::string getIsOmitted() const { return "false"; } |
245 | virtual void writeValue(raw_ostream &OS) const = 0; |
246 | virtual void writeDump(raw_ostream &OS) const = 0; |
247 | virtual void writeDumpChildren(raw_ostream &OS) const {} |
248 | virtual void writeHasChildren(raw_ostream &OS) const { OS << "false"; } |
249 | |
250 | virtual bool isEnumArg() const { return false; } |
251 | virtual bool isVariadicEnumArg() const { return false; } |
252 | virtual bool isVariadic() const { return false; } |
253 | |
254 | virtual void writeImplicitCtorArgs(raw_ostream &OS) const { |
255 | OS << getUpperName(); |
256 | } |
257 | }; |
258 | |
259 | class SimpleArgument : public Argument { |
260 | std::string type; |
261 | |
262 | public: |
263 | SimpleArgument(const Record &Arg, StringRef Attr, std::string T) |
264 | : Argument(Arg, Attr), type(std::move(T)) {} |
265 | |
266 | std::string getType() const { return type; } |
267 | |
268 | void writeAccessors(raw_ostream &OS) const override { |
269 | OS << " " << type << " get" << getUpperName() << "() const {\n"; |
270 | OS << " return " << getLowerName() << ";\n"; |
271 | OS << " }"; |
272 | } |
273 | |
274 | void writeCloneArgs(raw_ostream &OS) const override { |
275 | OS << getLowerName(); |
276 | } |
277 | |
278 | void writeTemplateInstantiationArgs(raw_ostream &OS) const override { |
279 | OS << "A->get" << getUpperName() << "()"; |
280 | } |
281 | |
282 | void writeCtorInitializers(raw_ostream &OS) const override { |
283 | OS << getLowerName() << "(" << getUpperName() << ")"; |
284 | } |
285 | |
286 | void writeCtorDefaultInitializers(raw_ostream &OS) const override { |
287 | OS << getLowerName() << "()"; |
288 | } |
289 | |
290 | void writeCtorParameters(raw_ostream &OS) const override { |
291 | OS << type << " " << getUpperName(); |
292 | } |
293 | |
294 | void writeDeclarations(raw_ostream &OS) const override { |
295 | OS << type << " " << getLowerName() << ";"; |
296 | } |
297 | |
298 | void writePCHReadDecls(raw_ostream &OS) const override { |
299 | std::string read = ReadPCHRecord(type); |
300 | OS << " " << type << " " << getLowerName() << " = " << read << ";\n"; |
301 | } |
302 | |
303 | void writePCHReadArgs(raw_ostream &OS) const override { |
304 | OS << getLowerName(); |
305 | } |
306 | |
307 | void writePCHWrite(raw_ostream &OS) const override { |
308 | OS << " " |
309 | << WritePCHRecord(type, |
310 | "SA->get" + std::string(getUpperName()) + "()"); |
311 | } |
312 | |
313 | std::string getIsOmitted() const override { |
314 | if (type == "IdentifierInfo *") |
315 | return "!get" + getUpperName().str() + "()"; |
316 | if (type == "TypeSourceInfo *") |
317 | return "!get" + getUpperName().str() + "Loc()"; |
318 | if (type == "ParamIdx") |
319 | return "!get" + getUpperName().str() + "().isValid()"; |
320 | return "false"; |
321 | } |
322 | |
323 | void writeValue(raw_ostream &OS) const override { |
324 | if (type == "FunctionDecl *") |
325 | OS << "\" << get" << getUpperName() |
326 | << "()->getNameInfo().getAsString() << \""; |
327 | else if (type == "IdentifierInfo *") |
328 | |
329 | |
330 | OS << "\" << (get" << getUpperName() << "() ? get" << getUpperName() |
331 | << "()->getName() : \"\") << \""; |
332 | else if (type == "VarDecl *") |
333 | OS << "\" << get" << getUpperName() << "()->getName() << \""; |
334 | else if (type == "TypeSourceInfo *") |
335 | OS << "\" << get" << getUpperName() << "().getAsString() << \""; |
336 | else if (type == "ParamIdx") |
337 | OS << "\" << get" << getUpperName() << "().getSourceIndex() << \""; |
338 | else |
339 | OS << "\" << get" << getUpperName() << "() << \""; |
340 | } |
341 | |
342 | void writeDump(raw_ostream &OS) const override { |
343 | if (StringRef(type).endswith("Decl *")) { |
344 | OS << " OS << \" \";\n"; |
345 | OS << " dumpBareDeclRef(SA->get" << getUpperName() << "());\n"; |
346 | } else if (type == "IdentifierInfo *") { |
347 | |
348 | |
349 | OS << " if (SA->get" << getUpperName() << "())\n" |
350 | << " OS << \" \" << SA->get" << getUpperName() |
351 | << "()->getName();\n"; |
352 | } else if (type == "TypeSourceInfo *") { |
353 | if (isOptional()) |
354 | OS << " if (SA->get" << getUpperName() << "Loc())"; |
355 | OS << " OS << \" \" << SA->get" << getUpperName() |
356 | << "().getAsString();\n"; |
357 | } else if (type == "bool") { |
358 | OS << " if (SA->get" << getUpperName() << "()) OS << \" " |
359 | << getUpperName() << "\";\n"; |
360 | } else if (type == "int" || type == "unsigned") { |
361 | OS << " OS << \" \" << SA->get" << getUpperName() << "();\n"; |
362 | } else if (type == "ParamIdx") { |
363 | if (isOptional()) |
364 | OS << " if (SA->get" << getUpperName() << "().isValid())\n "; |
365 | OS << " OS << \" \" << SA->get" << getUpperName() |
366 | << "().getSourceIndex();\n"; |
367 | } else if (type == "OMPTraitInfo *") { |
368 | OS << " OS << \" \" << SA->get" << getUpperName() << "();\n"; |
369 | } else { |
370 | llvm_unreachable("Unknown SimpleArgument type!"); |
371 | } |
372 | } |
373 | }; |
374 | |
375 | class DefaultSimpleArgument : public SimpleArgument { |
376 | int64_t Default; |
377 | |
378 | public: |
379 | DefaultSimpleArgument(const Record &Arg, StringRef Attr, |
380 | std::string T, int64_t Default) |
381 | : SimpleArgument(Arg, Attr, T), Default(Default) {} |
382 | |
383 | void writeAccessors(raw_ostream &OS) const override { |
384 | SimpleArgument::writeAccessors(OS); |
385 | |
386 | OS << "\n\n static const " << getType() << " Default" << getUpperName() |
387 | << " = "; |
388 | if (getType() == "bool") |
389 | OS << (Default != 0 ? "true" : "false"); |
390 | else |
391 | OS << Default; |
392 | OS << ";"; |
393 | } |
394 | }; |
395 | |
396 | class StringArgument : public Argument { |
397 | public: |
398 | StringArgument(const Record &Arg, StringRef Attr) |
399 | : Argument(Arg, Attr) |
400 | {} |
401 | |
402 | void writeAccessors(raw_ostream &OS) const override { |
403 | OS << " llvm::StringRef get" << getUpperName() << "() const {\n"; |
404 | OS << " return llvm::StringRef(" << getLowerName() << ", " |
405 | << getLowerName() << "Length);\n"; |
406 | OS << " }\n"; |
407 | OS << " unsigned get" << getUpperName() << "Length() const {\n"; |
408 | OS << " return " << getLowerName() << "Length;\n"; |
409 | OS << " }\n"; |
410 | OS << " void set" << getUpperName() |
411 | << "(ASTContext &C, llvm::StringRef S) {\n"; |
412 | OS << " " << getLowerName() << "Length = S.size();\n"; |
413 | OS << " this->" << getLowerName() << " = new (C, 1) char [" |
414 | << getLowerName() << "Length];\n"; |
415 | OS << " if (!S.empty())\n"; |
416 | OS << " std::memcpy(this->" << getLowerName() << ", S.data(), " |
417 | << getLowerName() << "Length);\n"; |
418 | OS << " }"; |
419 | } |
420 | |
421 | void writeCloneArgs(raw_ostream &OS) const override { |
422 | OS << "get" << getUpperName() << "()"; |
423 | } |
424 | |
425 | void writeTemplateInstantiationArgs(raw_ostream &OS) const override { |
426 | OS << "A->get" << getUpperName() << "()"; |
427 | } |
428 | |
429 | void writeCtorBody(raw_ostream &OS) const override { |
430 | OS << " if (!" << getUpperName() << ".empty())\n"; |
431 | OS << " std::memcpy(" << getLowerName() << ", " << getUpperName() |
432 | << ".data(), " << getLowerName() << "Length);\n"; |
433 | } |
434 | |
435 | void writeCtorInitializers(raw_ostream &OS) const override { |
436 | OS << getLowerName() << "Length(" << getUpperName() << ".size())," |
437 | << getLowerName() << "(new (Ctx, 1) char[" << getLowerName() |
438 | << "Length])"; |
439 | } |
440 | |
441 | void writeCtorDefaultInitializers(raw_ostream &OS) const override { |
442 | OS << getLowerName() << "Length(0)," << getLowerName() << "(nullptr)"; |
443 | } |
444 | |
445 | void writeCtorParameters(raw_ostream &OS) const override { |
446 | OS << "llvm::StringRef " << getUpperName(); |
447 | } |
448 | |
449 | void writeDeclarations(raw_ostream &OS) const override { |
450 | OS << "unsigned " << getLowerName() << "Length;\n"; |
451 | OS << "char *" << getLowerName() << ";"; |
452 | } |
453 | |
454 | void writePCHReadDecls(raw_ostream &OS) const override { |
455 | OS << " std::string " << getLowerName() |
456 | << "= Record.readString();\n"; |
457 | } |
458 | |
459 | void writePCHReadArgs(raw_ostream &OS) const override { |
460 | OS << getLowerName(); |
461 | } |
462 | |
463 | void writePCHWrite(raw_ostream &OS) const override { |
464 | OS << " Record.AddString(SA->get" << getUpperName() << "());\n"; |
465 | } |
466 | |
467 | void writeValue(raw_ostream &OS) const override { |
468 | OS << "\\\"\" << get" << getUpperName() << "() << \"\\\""; |
469 | } |
470 | |
471 | void writeDump(raw_ostream &OS) const override { |
472 | OS << " OS << \" \\\"\" << SA->get" << getUpperName() |
473 | << "() << \"\\\"\";\n"; |
474 | } |
475 | }; |
476 | |
477 | class AlignedArgument : public Argument { |
478 | public: |
479 | AlignedArgument(const Record &Arg, StringRef Attr) |
480 | : Argument(Arg, Attr) |
481 | {} |
482 | |
483 | void writeAccessors(raw_ostream &OS) const override { |
484 | OS << " bool is" << getUpperName() << "Dependent() const;\n"; |
485 | OS << " bool is" << getUpperName() << "ErrorDependent() const;\n"; |
486 | |
487 | OS << " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n"; |
488 | |
489 | OS << " bool is" << getUpperName() << "Expr() const {\n"; |
490 | OS << " return is" << getLowerName() << "Expr;\n"; |
491 | OS << " }\n"; |
492 | |
493 | OS << " Expr *get" << getUpperName() << "Expr() const {\n"; |
494 | OS << " assert(is" << getLowerName() << "Expr);\n"; |
495 | OS << " return " << getLowerName() << "Expr;\n"; |
496 | OS << " }\n"; |
497 | |
498 | OS << " TypeSourceInfo *get" << getUpperName() << "Type() const {\n"; |
499 | OS << " assert(!is" << getLowerName() << "Expr);\n"; |
500 | OS << " return " << getLowerName() << "Type;\n"; |
501 | OS << " }"; |
502 | } |
503 | |
504 | void writeAccessorDefinitions(raw_ostream &OS) const override { |
505 | OS << "bool " << getAttrName() << "Attr::is" << getUpperName() |
506 | << "Dependent() const {\n"; |
507 | OS << " if (is" << getLowerName() << "Expr)\n"; |
508 | OS << " return " << getLowerName() << "Expr && (" << getLowerName() |
509 | << "Expr->isValueDependent() || " << getLowerName() |
510 | << "Expr->isTypeDependent());\n"; |
511 | OS << " else\n"; |
512 | OS << " return " << getLowerName() |
513 | << "Type->getType()->isDependentType();\n"; |
514 | OS << "}\n"; |
515 | |
516 | OS << "bool " << getAttrName() << "Attr::is" << getUpperName() |
517 | << "ErrorDependent() const {\n"; |
518 | OS << " if (is" << getLowerName() << "Expr)\n"; |
519 | OS << " return " << getLowerName() << "Expr && " << getLowerName() |
520 | << "Expr->containsErrors();\n"; |
521 | OS << " return " << getLowerName() |
522 | << "Type->getType()->containsErrors();\n"; |
523 | OS << "}\n"; |
524 | |
525 | |
526 | |
527 | |
528 | OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName() |
529 | << "(ASTContext &Ctx) const {\n"; |
530 | OS << " assert(!is" << getUpperName() << "Dependent());\n"; |
531 | OS << " if (is" << getLowerName() << "Expr)\n"; |
532 | OS << " return " << getLowerName() << "Expr ? " << getLowerName() |
533 | << "Expr->EvaluateKnownConstInt(Ctx).getZExtValue()" |
534 | << " * Ctx.getCharWidth() : " |
535 | << "Ctx.getTargetDefaultAlignForAttributeAligned();\n"; |
536 | OS << " else\n"; |
537 | OS << " return 0; // FIXME\n"; |
538 | OS << "}\n"; |
539 | } |
540 | |
541 | void writeASTVisitorTraversal(raw_ostream &OS) const override { |
542 | StringRef Name = getUpperName(); |
543 | OS << " if (A->is" << Name << "Expr()) {\n" |
544 | << " if (!getDerived().TraverseStmt(A->get" << Name << "Expr()))\n" |
545 | << " return false;\n" |
546 | << " } else if (auto *TSI = A->get" << Name << "Type()) {\n" |
547 | << " if (!getDerived().TraverseTypeLoc(TSI->getTypeLoc()))\n" |
548 | << " return false;\n" |
549 | << " }\n"; |
550 | } |
551 | |
552 | void writeCloneArgs(raw_ostream &OS) const override { |
553 | OS << "is" << getLowerName() << "Expr, is" << getLowerName() |
554 | << "Expr ? static_cast<void*>(" << getLowerName() |
555 | << "Expr) : " << getLowerName() |
556 | << "Type"; |
557 | } |
558 | |
559 | void writeTemplateInstantiationArgs(raw_ostream &OS) const override { |
560 | |
561 | |
562 | } |
563 | |
564 | void writeCtorBody(raw_ostream &OS) const override { |
565 | OS << " if (is" << getLowerName() << "Expr)\n"; |
566 | OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>(" |
567 | << getUpperName() << ");\n"; |
568 | OS << " else\n"; |
569 | OS << " " << getLowerName() |
570 | << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName() |
571 | << ");\n"; |
572 | } |
573 | |
574 | void writeCtorInitializers(raw_ostream &OS) const override { |
575 | OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)"; |
576 | } |
577 | |
578 | void writeCtorDefaultInitializers(raw_ostream &OS) const override { |
579 | OS << "is" << getLowerName() << "Expr(false)"; |
580 | } |
581 | |
582 | void writeCtorParameters(raw_ostream &OS) const override { |
583 | OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName(); |
584 | } |
585 | |
586 | void writeImplicitCtorArgs(raw_ostream &OS) const override { |
587 | OS << "Is" << getUpperName() << "Expr, " << getUpperName(); |
588 | } |
589 | |
590 | void writeDeclarations(raw_ostream &OS) const override { |
591 | OS << "bool is" << getLowerName() << "Expr;\n"; |
592 | OS << "union {\n"; |
593 | OS << "Expr *" << getLowerName() << "Expr;\n"; |
594 | OS << "TypeSourceInfo *" << getLowerName() << "Type;\n"; |
595 | OS << "};"; |
596 | } |
597 | |
598 | void writePCHReadArgs(raw_ostream &OS) const override { |
599 | OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr"; |
600 | } |
601 | |
602 | void writePCHReadDecls(raw_ostream &OS) const override { |
603 | OS << " bool is" << getLowerName() << "Expr = Record.readInt();\n"; |
604 | OS << " void *" << getLowerName() << "Ptr;\n"; |
605 | OS << " if (is" << getLowerName() << "Expr)\n"; |
606 | OS << " " << getLowerName() << "Ptr = Record.readExpr();\n"; |
607 | OS << " else\n"; |
608 | OS << " " << getLowerName() |
609 | << "Ptr = Record.readTypeSourceInfo();\n"; |
610 | } |
611 | |
612 | void writePCHWrite(raw_ostream &OS) const override { |
613 | OS << " Record.push_back(SA->is" << getUpperName() << "Expr());\n"; |
614 | OS << " if (SA->is" << getUpperName() << "Expr())\n"; |
615 | OS << " Record.AddStmt(SA->get" << getUpperName() << "Expr());\n"; |
616 | OS << " else\n"; |
617 | OS << " Record.AddTypeSourceInfo(SA->get" << getUpperName() |
618 | << "Type());\n"; |
619 | } |
620 | |
621 | std::string getIsOmitted() const override { |
622 | return "!is" + getLowerName().str() + "Expr || !" + getLowerName().str() |
623 | + "Expr"; |
624 | } |
625 | |
626 | void writeValue(raw_ostream &OS) const override { |
627 | OS << "\";\n"; |
628 | OS << " " << getLowerName() |
629 | << "Expr->printPretty(OS, nullptr, Policy);\n"; |
630 | OS << " OS << \""; |
631 | } |
632 | |
633 | void writeDump(raw_ostream &OS) const override { |
634 | OS << " if (!SA->is" << getUpperName() << "Expr())\n"; |
635 | OS << " dumpType(SA->get" << getUpperName() |
636 | << "Type()->getType());\n"; |
637 | } |
638 | |
639 | void writeDumpChildren(raw_ostream &OS) const override { |
640 | OS << " if (SA->is" << getUpperName() << "Expr())\n"; |
641 | OS << " Visit(SA->get" << getUpperName() << "Expr());\n"; |
642 | } |
643 | |
644 | void writeHasChildren(raw_ostream &OS) const override { |
645 | OS << "SA->is" << getUpperName() << "Expr()"; |
646 | } |
647 | }; |
648 | |
649 | class VariadicArgument : public Argument { |
650 | std::string Type, ArgName, ArgSizeName, RangeName; |
651 | |
652 | protected: |
653 | |
654 | virtual void writeValueImpl(raw_ostream &OS) const { |
655 | OS << " OS << Val;\n"; |
656 | } |
657 | |
658 | virtual void writeDumpImpl(raw_ostream &OS) const { |
659 | OS << " OS << \" \" << Val;\n"; |
660 | } |
661 | |
662 | public: |
663 | VariadicArgument(const Record &Arg, StringRef Attr, std::string T) |
664 | : Argument(Arg, Attr), Type(std::move(T)), |
665 | ArgName(getLowerName().str() + "_"), ArgSizeName(ArgName + "Size"), |
666 | RangeName(std::string(getLowerName())) {} |
667 | |
668 | const std::string &getType() const { return Type; } |
669 | const std::string &getArgName() const { return ArgName; } |
670 | const std::string &getArgSizeName() const { return ArgSizeName; } |
671 | bool isVariadic() const override { return true; } |
672 | |
673 | void writeAccessors(raw_ostream &OS) const override { |
674 | std::string IteratorType = getLowerName().str() + "_iterator"; |
675 | std::string BeginFn = getLowerName().str() + "_begin()"; |
676 | std::string EndFn = getLowerName().str() + "_end()"; |
677 | |
678 | OS << " typedef " << Type << "* " << IteratorType << ";\n"; |
679 | OS << " " << IteratorType << " " << BeginFn << " const {" |
680 | << " return " << ArgName << "; }\n"; |
681 | OS << " " << IteratorType << " " << EndFn << " const {" |
682 | << " return " << ArgName << " + " << ArgSizeName << "; }\n"; |
683 | OS << " unsigned " << getLowerName() << "_size() const {" |
684 | << " return " << ArgSizeName << "; }\n"; |
685 | OS << " llvm::iterator_range<" << IteratorType << "> " << RangeName |
686 | << "() const { return llvm::make_range(" << BeginFn << ", " << EndFn |
687 | << "); }\n"; |
688 | } |
689 | |
690 | void writeCloneArgs(raw_ostream &OS) const override { |
691 | OS << ArgName << ", " << ArgSizeName; |
692 | } |
693 | |
694 | void writeTemplateInstantiationArgs(raw_ostream &OS) const override { |
695 | |
696 | OS << "A->" << getLowerName() << "_begin(), " |
697 | << "A->" << getLowerName() << "_size()"; |
698 | } |
699 | |
700 | void writeASTVisitorTraversal(raw_ostream &OS) const override { |
701 | |
702 | } |
703 | |
704 | void writeCtorBody(raw_ostream &OS) const override { |
705 | OS << " std::copy(" << getUpperName() << ", " << getUpperName() << " + " |
706 | << ArgSizeName << ", " << ArgName << ");\n"; |
707 | } |
708 | |
709 | void writeCtorInitializers(raw_ostream &OS) const override { |
710 | OS << ArgSizeName << "(" << getUpperName() << "Size), " |
711 | << ArgName << "(new (Ctx, 16) " << getType() << "[" |
712 | << ArgSizeName << "])"; |
713 | } |
714 | |
715 | void writeCtorDefaultInitializers(raw_ostream &OS) const override { |
716 | OS << ArgSizeName << "(0), " << ArgName << "(nullptr)"; |
717 | } |
718 | |
719 | void writeCtorParameters(raw_ostream &OS) const override { |
720 | OS << getType() << " *" << getUpperName() << ", unsigned " |
721 | << getUpperName() << "Size"; |
722 | } |
723 | |
724 | void writeImplicitCtorArgs(raw_ostream &OS) const override { |
725 | OS << getUpperName() << ", " << getUpperName() << "Size"; |
726 | } |
727 | |
728 | void writeDeclarations(raw_ostream &OS) const override { |
729 | OS << " unsigned " << ArgSizeName << ";\n"; |
730 | OS << " " << getType() << " *" << ArgName << ";"; |
731 | } |
732 | |
733 | void writePCHReadDecls(raw_ostream &OS) const override { |
734 | OS << " unsigned " << getLowerName() << "Size = Record.readInt();\n"; |
735 | OS << " SmallVector<" << getType() << ", 4> " |
736 | << getLowerName() << ";\n"; |
737 | OS << " " << getLowerName() << ".reserve(" << getLowerName() |
738 | << "Size);\n"; |
739 | |
740 | |
741 | |
742 | |
743 | std::string StorageType = std::string(getStorageType(getType())); |
744 | std::string StorageName = std::string(getLowerName()); |
745 | if (StorageType != getType()) { |
746 | StorageName += "Storage"; |
747 | OS << " SmallVector<" << StorageType << ", 4> " |
748 | << StorageName << ";\n"; |
749 | OS << " " << StorageName << ".reserve(" << getLowerName() |
750 | << "Size);\n"; |
751 | } |
752 | |
753 | OS << " for (unsigned i = 0; i != " << getLowerName() << "Size; ++i)\n"; |
754 | std::string read = ReadPCHRecord(Type); |
755 | OS << " " << StorageName << ".push_back(" << read << ");\n"; |
756 | |
757 | if (StorageType != getType()) { |
758 | OS << " for (unsigned i = 0; i != " << getLowerName() << "Size; ++i)\n"; |
759 | OS << " " << getLowerName() << ".push_back(" |
760 | << StorageName << "[i]);\n"; |
761 | } |
762 | } |
763 | |
764 | void writePCHReadArgs(raw_ostream &OS) const override { |
765 | OS << getLowerName() << ".data(), " << getLowerName() << "Size"; |
766 | } |
767 | |
768 | void writePCHWrite(raw_ostream &OS) const override { |
769 | OS << " Record.push_back(SA->" << getLowerName() << "_size());\n"; |
770 | OS << " for (auto &Val : SA->" << RangeName << "())\n"; |
771 | OS << " " << WritePCHRecord(Type, "Val"); |
772 | } |
773 | |
774 | void writeValue(raw_ostream &OS) const override { |
775 | OS << "\";\n"; |
776 | OS << " for (const auto &Val : " << RangeName << "()) {\n" |
777 | << " DelimitAttributeArgument(OS, IsFirstArgument);\n"; |
778 | writeValueImpl(OS); |
779 | OS << " }\n"; |
780 | OS << " OS << \""; |
781 | } |
782 | |
783 | void writeDump(raw_ostream &OS) const override { |
784 | OS << " for (const auto &Val : SA->" << RangeName << "())\n"; |
785 | writeDumpImpl(OS); |
786 | } |
787 | }; |
788 | |
789 | class VariadicParamIdxArgument : public VariadicArgument { |
790 | public: |
791 | VariadicParamIdxArgument(const Record &Arg, StringRef Attr) |
792 | : VariadicArgument(Arg, Attr, "ParamIdx") {} |
793 | |
794 | public: |
795 | void writeValueImpl(raw_ostream &OS) const override { |
796 | OS << " OS << Val.getSourceIndex();\n"; |
797 | } |
798 | |
799 | void writeDumpImpl(raw_ostream &OS) const override { |
800 | OS << " OS << \" \" << Val.getSourceIndex();\n"; |
801 | } |
802 | }; |
803 | |
804 | struct VariadicParamOrParamIdxArgument : public VariadicArgument { |
805 | VariadicParamOrParamIdxArgument(const Record &Arg, StringRef Attr) |
806 | : VariadicArgument(Arg, Attr, "int") {} |
807 | }; |
808 | |
809 | |
810 | std::vector<StringRef> |
811 | uniqueEnumsInOrder(const std::vector<StringRef> &enums) { |
812 | std::vector<StringRef> uniques; |
813 | SmallDenseSet<StringRef, 8> unique_set; |
814 | for (const auto &i : enums) { |
815 | if (unique_set.insert(i).second) |
816 | uniques.push_back(i); |
817 | } |
818 | return uniques; |
819 | } |
820 | |
821 | class EnumArgument : public Argument { |
822 | std::string type; |
823 | std::vector<StringRef> values, enums, uniques; |
824 | |
825 | public: |
826 | EnumArgument(const Record &Arg, StringRef Attr) |
827 | : Argument(Arg, Attr), type(std::string(Arg.getValueAsString("Type"))), |
828 | values(Arg.getValueAsListOfStrings("Values")), |
829 | enums(Arg.getValueAsListOfStrings("Enums")), |
830 | uniques(uniqueEnumsInOrder(enums)) { |
831 | |
832 | assert(!uniques.empty()); |
833 | } |
834 | |
835 | bool isEnumArg() const override { return true; } |
836 | |
837 | void writeAccessors(raw_ostream &OS) const override { |
838 | OS << " " << type << " get" << getUpperName() << "() const {\n"; |
839 | OS << " return " << getLowerName() << ";\n"; |
840 | OS << " }"; |
841 | } |
842 | |
843 | void writeCloneArgs(raw_ostream &OS) const override { |
844 | OS << getLowerName(); |
845 | } |
846 | |
847 | void writeTemplateInstantiationArgs(raw_ostream &OS) const override { |
848 | OS << "A->get" << getUpperName() << "()"; |
849 | } |
850 | void writeCtorInitializers(raw_ostream &OS) const override { |
851 | OS << getLowerName() << "(" << getUpperName() << ")"; |
852 | } |
853 | void writeCtorDefaultInitializers(raw_ostream &OS) const override { |
854 | OS << getLowerName() << "(" << type << "(0))"; |
855 | } |
856 | void writeCtorParameters(raw_ostream &OS) const override { |
857 | OS << type << " " << getUpperName(); |
858 | } |
859 | void writeDeclarations(raw_ostream &OS) const override { |
860 | auto i = uniques.cbegin(), e = uniques.cend(); |
861 | |
862 | --e; |
863 | |
864 | OS << "public:\n"; |
865 | OS << " enum " << type << " {\n"; |
866 | for (; i != e; ++i) |
867 | OS << " " << *i << ",\n"; |
868 | OS << " " << *e << "\n"; |
869 | OS << " };\n"; |
870 | OS << "private:\n"; |
871 | OS << " " << type << " " << getLowerName() << ";"; |
872 | } |
873 | |
874 | void writePCHReadDecls(raw_ostream &OS) const override { |
875 | OS << " " << getAttrName() << "Attr::" << type << " " << getLowerName() |
876 | << "(static_cast<" << getAttrName() << "Attr::" << type |
877 | << ">(Record.readInt()));\n"; |
878 | } |
879 | |
880 | void writePCHReadArgs(raw_ostream &OS) const override { |
881 | OS << getLowerName(); |
882 | } |
883 | |
884 | void writePCHWrite(raw_ostream &OS) const override { |
885 | OS << "Record.push_back(SA->get" << getUpperName() << "());\n"; |
886 | } |
887 | |
888 | void writeValue(raw_ostream &OS) const override { |
889 | |
890 | |
891 | |
892 | OS << "\\\"\" << " << getAttrName() << "Attr::Convert" << type << "ToStr(get" |
893 | << getUpperName() << "()) << \"\\\""; |
894 | } |
895 | |
896 | void writeDump(raw_ostream &OS) const override { |
897 | OS << " switch(SA->get" << getUpperName() << "()) {\n"; |
898 | for (const auto &I : uniques) { |
899 | OS << " case " << getAttrName() << "Attr::" << I << ":\n"; |
900 | OS << " OS << \" " << I << "\";\n"; |
901 | OS << " break;\n"; |
902 | } |
903 | OS << " }\n"; |
904 | } |
905 | |
906 | void writeConversion(raw_ostream &OS, bool Header) const { |
907 | if (Header) { |
908 | OS << " static bool ConvertStrTo" << type << "(StringRef Val, " << type |
909 | << " &Out);\n"; |
910 | OS << " static const char *Convert" << type << "ToStr(" << type |
911 | << " Val);\n"; |
912 | return; |
913 | } |
914 | |
915 | OS << "bool " << getAttrName() << "Attr::ConvertStrTo" << type |
916 | << "(StringRef Val, " << type << " &Out) {\n"; |
917 | OS << " Optional<" << type << "> R = llvm::StringSwitch<Optional<"; |
918 | OS << type << ">>(Val)\n"; |
919 | for (size_t I = 0; I < enums.size(); ++I) { |
920 | OS << " .Case(\"" << values[I] << "\", "; |
921 | OS << getAttrName() << "Attr::" << enums[I] << ")\n"; |
922 | } |
923 | OS << " .Default(Optional<" << type << ">());\n"; |
924 | OS << " if (R) {\n"; |
925 | OS << " Out = *R;\n return true;\n }\n"; |
926 | OS << " return false;\n"; |
927 | OS << "}\n\n"; |
928 | |
929 | |
930 | |
931 | |
932 | |
933 | OS << "const char *" << getAttrName() << "Attr::Convert" << type |
934 | << "ToStr(" << type << " Val) {\n" |
935 | << " switch(Val) {\n"; |
936 | SmallDenseSet<StringRef, 8> Uniques; |
937 | for (size_t I = 0; I < enums.size(); ++I) { |
938 | if (Uniques.insert(enums[I]).second) |
939 | OS << " case " << getAttrName() << "Attr::" << enums[I] |
940 | << ": return \"" << values[I] << "\";\n"; |
941 | } |
942 | OS << " }\n" |
943 | << " llvm_unreachable(\"No enumerator with that value\");\n" |
944 | << "}\n"; |
945 | } |
946 | }; |
947 | |
948 | class VariadicEnumArgument: public VariadicArgument { |
949 | std::string type, QualifiedTypeName; |
950 | std::vector<StringRef> values, enums, uniques; |
951 | |
952 | protected: |
953 | void writeValueImpl(raw_ostream &OS) const override { |
954 | |
955 | |
956 | |
957 | OS << " OS << \"\\\"\" << " << getAttrName() << "Attr::Convert" << type |
958 | << "ToStr(Val)" << "<< \"\\\"\";\n"; |
959 | } |
960 | |
961 | public: |
962 | VariadicEnumArgument(const Record &Arg, StringRef Attr) |
963 | : VariadicArgument(Arg, Attr, |
964 | std::string(Arg.getValueAsString("Type"))), |
965 | type(std::string(Arg.getValueAsString("Type"))), |
966 | values(Arg.getValueAsListOfStrings("Values")), |
967 | enums(Arg.getValueAsListOfStrings("Enums")), |
968 | uniques(uniqueEnumsInOrder(enums)) { |
969 | QualifiedTypeName = getAttrName().str() + "Attr::" + type; |
970 | |
971 | |
972 | assert(!uniques.empty()); |
973 | } |
974 | |
975 | bool isVariadicEnumArg() const override { return true; } |
976 | |
977 | void writeDeclarations(raw_ostream &OS) const override { |
978 | auto i = uniques.cbegin(), e = uniques.cend(); |
979 | |
980 | --e; |
981 | |
982 | OS << "public:\n"; |
983 | OS << " enum " << type << " {\n"; |
984 | for (; i != e; ++i) |
985 | OS << " " << *i << ",\n"; |
986 | OS << " " << *e << "\n"; |
987 | OS << " };\n"; |
988 | OS << "private:\n"; |
989 | |
990 | VariadicArgument::writeDeclarations(OS); |
991 | } |
992 | |
993 | void writeDump(raw_ostream &OS) const override { |
994 | OS << " for (" << getAttrName() << "Attr::" << getLowerName() |
995 | << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->" |
996 | << getLowerName() << "_end(); I != E; ++I) {\n"; |
997 | OS << " switch(*I) {\n"; |
998 | for (const auto &UI : uniques) { |
999 | OS << " case " << getAttrName() << "Attr::" << UI << ":\n"; |
1000 | OS << " OS << \" " << UI << "\";\n"; |
1001 | OS << " break;\n"; |
1002 | } |
1003 | OS << " }\n"; |
1004 | OS << " }\n"; |
1005 | } |
1006 | |
1007 | void writePCHReadDecls(raw_ostream &OS) const override { |
1008 | OS << " unsigned " << getLowerName() << "Size = Record.readInt();\n"; |
1009 | OS << " SmallVector<" << QualifiedTypeName << ", 4> " << getLowerName() |
1010 | << ";\n"; |
1011 | OS << " " << getLowerName() << ".reserve(" << getLowerName() |
1012 | << "Size);\n"; |
1013 | OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n"; |
1014 | OS << " " << getLowerName() << ".push_back(" << "static_cast<" |
1015 | << QualifiedTypeName << ">(Record.readInt()));\n"; |
1016 | } |
1017 | |
1018 | void writePCHWrite(raw_ostream &OS) const override { |
1019 | OS << " Record.push_back(SA->" << getLowerName() << "_size());\n"; |
1020 | OS << " for (" << getAttrName() << "Attr::" << getLowerName() |
1021 | << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->" |
1022 | << getLowerName() << "_end(); i != e; ++i)\n"; |
1023 | OS << " " << WritePCHRecord(QualifiedTypeName, "(*i)"); |
1024 | } |
1025 | |
1026 | void writeConversion(raw_ostream &OS, bool Header) const { |
1027 | if (Header) { |
1028 | OS << " static bool ConvertStrTo" << type << "(StringRef Val, " << type |
1029 | << " &Out);\n"; |
1030 | OS << " static const char *Convert" << type << "ToStr(" << type |
1031 | << " Val);\n"; |
1032 | return; |
1033 | } |
1034 | |
1035 | OS << "bool " << getAttrName() << "Attr::ConvertStrTo" << type |
1036 | << "(StringRef Val, "; |
1037 | OS << type << " &Out) {\n"; |
1038 | OS << " Optional<" << type << "> R = llvm::StringSwitch<Optional<"; |
1039 | OS << type << ">>(Val)\n"; |
1040 | for (size_t I = 0; I < enums.size(); ++I) { |
1041 | OS << " .Case(\"" << values[I] << "\", "; |
1042 | OS << getAttrName() << "Attr::" << enums[I] << ")\n"; |
1043 | } |
1044 | OS << " .Default(Optional<" << type << ">());\n"; |
1045 | OS << " if (R) {\n"; |
1046 | OS << " Out = *R;\n return true;\n }\n"; |
1047 | OS << " return false;\n"; |
1048 | OS << "}\n\n"; |
1049 | |
1050 | OS << "const char *" << getAttrName() << "Attr::Convert" << type |
1051 | << "ToStr(" << type << " Val) {\n" |
1052 | << " switch(Val) {\n"; |
1053 | SmallDenseSet<StringRef, 8> Uniques; |
1054 | for (size_t I = 0; I < enums.size(); ++I) { |
1055 | if (Uniques.insert(enums[I]).second) |
1056 | OS << " case " << getAttrName() << "Attr::" << enums[I] |
1057 | << ": return \"" << values[I] << "\";\n"; |
1058 | } |
1059 | OS << " }\n" |
1060 | << " llvm_unreachable(\"No enumerator with that value\");\n" |
1061 | << "}\n"; |
1062 | } |
1063 | }; |
1064 | |
1065 | class VersionArgument : public Argument { |
1066 | public: |
1067 | VersionArgument(const Record &Arg, StringRef Attr) |
1068 | : Argument(Arg, Attr) |
1069 | {} |
1070 | |
1071 | void writeAccessors(raw_ostream &OS) const override { |
1072 | OS << " VersionTuple get" << getUpperName() << "() const {\n"; |
1073 | OS << " return " << getLowerName() << ";\n"; |
1074 | OS << " }\n"; |
1075 | OS << " void set" << getUpperName() |
1076 | << "(ASTContext &C, VersionTuple V) {\n"; |
1077 | OS << " " << getLowerName() << " = V;\n"; |
1078 | OS << " }"; |
1079 | } |
1080 | |
1081 | void writeCloneArgs(raw_ostream &OS) const override { |
1082 | OS << "get" << getUpperName() << "()"; |
1083 | } |
1084 | |
1085 | void writeTemplateInstantiationArgs(raw_ostream &OS) const override { |
1086 | OS << "A->get" << getUpperName() << "()"; |
1087 | } |
1088 | |
1089 | void writeCtorInitializers(raw_ostream &OS) const override { |
1090 | OS << getLowerName() << "(" << getUpperName() << ")"; |
1091 | } |
1092 | |
1093 | void writeCtorDefaultInitializers(raw_ostream &OS) const override { |
1094 | OS << getLowerName() << "()"; |
1095 | } |
1096 | |
1097 | void writeCtorParameters(raw_ostream &OS) const override { |
1098 | OS << "VersionTuple " << getUpperName(); |
1099 | } |
1100 | |
1101 | void writeDeclarations(raw_ostream &OS) const override { |
1102 | OS << "VersionTuple " << getLowerName() << ";\n"; |
1103 | } |
1104 | |
1105 | void writePCHReadDecls(raw_ostream &OS) const override { |
1106 | OS << " VersionTuple " << getLowerName() |
1107 | << "= Record.readVersionTuple();\n"; |
1108 | } |
1109 | |
1110 | void writePCHReadArgs(raw_ostream &OS) const override { |
1111 | OS << getLowerName(); |
1112 | } |
1113 | |
1114 | void writePCHWrite(raw_ostream &OS) const override { |
1115 | OS << " Record.AddVersionTuple(SA->get" << getUpperName() << "());\n"; |
1116 | } |
1117 | |
1118 | void writeValue(raw_ostream &OS) const override { |
1119 | OS << getLowerName() << "=\" << get" << getUpperName() << "() << \""; |
1120 | } |
1121 | |
1122 | void writeDump(raw_ostream &OS) const override { |
1123 | OS << " OS << \" \" << SA->get" << getUpperName() << "();\n"; |
1124 | } |
1125 | }; |
1126 | |
1127 | class ExprArgument : public SimpleArgument { |
1128 | public: |
1129 | ExprArgument(const Record &Arg, StringRef Attr) |
1130 | : SimpleArgument(Arg, Attr, "Expr *") |
1131 | {} |
1132 | |
1133 | void writeASTVisitorTraversal(raw_ostream &OS) const override { |
1134 | OS << " if (!" |
1135 | << "getDerived().TraverseStmt(A->get" << getUpperName() << "()))\n"; |
1136 | OS << " return false;\n"; |
1137 | } |
1138 | |
1139 | void writeTemplateInstantiationArgs(raw_ostream &OS) const override { |
1140 | OS << "tempInst" << getUpperName(); |
1141 | } |
1142 | |
1143 | void writeTemplateInstantiation(raw_ostream &OS) const override { |
1144 | OS << " " << getType() << " tempInst" << getUpperName() << ";\n"; |
1145 | OS << " {\n"; |
1146 | OS << " EnterExpressionEvaluationContext " |
1147 | << "Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);\n"; |
1148 | OS << " ExprResult " << "Result = S.SubstExpr(" |
1149 | << "A->get" << getUpperName() << "(), TemplateArgs);\n"; |
1150 | OS << " if (Result.isInvalid())\n"; |
1151 | OS << " return nullptr;\n"; |
1152 | OS << " tempInst" << getUpperName() << " = Result.get();\n"; |
1153 | OS << " }\n"; |
1154 | } |
1155 | |
1156 | void writeDump(raw_ostream &OS) const override {} |
1157 | |
1158 | void writeDumpChildren(raw_ostream &OS) const override { |
1159 | OS << " Visit(SA->get" << getUpperName() << "());\n"; |
1160 | } |
1161 | |
1162 | void writeHasChildren(raw_ostream &OS) const override { OS << "true"; } |
1163 | }; |
1164 | |
1165 | class VariadicExprArgument : public VariadicArgument { |
1166 | public: |
1167 | VariadicExprArgument(const Record &Arg, StringRef Attr) |
1168 | : VariadicArgument(Arg, Attr, "Expr *") |
1169 | {} |
1170 | |
1171 | void writeASTVisitorTraversal(raw_ostream &OS) const override { |
1172 | OS << " {\n"; |
1173 | OS << " " << getType() << " *I = A->" << getLowerName() |
1174 | << "_begin();\n"; |
1175 | OS << " " << getType() << " *E = A->" << getLowerName() |
1176 | << "_end();\n"; |
1177 | OS << " for (; I != E; ++I) {\n"; |
1178 | OS << " if (!getDerived().TraverseStmt(*I))\n"; |
1179 | OS << " return false;\n"; |
1180 | OS << " }\n"; |
1181 | OS << " }\n"; |
1182 | } |
1183 | |
1184 | void writeTemplateInstantiationArgs(raw_ostream &OS) const override { |
1185 | OS << "tempInst" << getUpperName() << ", " |
1186 | << "A->" << getLowerName() << "_size()"; |
1187 | } |
1188 | |
1189 | void writeTemplateInstantiation(raw_ostream &OS) const override { |
1190 | OS << " auto *tempInst" << getUpperName() |
1191 | << " = new (C, 16) " << getType() |
1192 | << "[A->" << getLowerName() << "_size()];\n"; |
1193 | OS << " {\n"; |
1194 | OS << " EnterExpressionEvaluationContext " |
1195 | << "Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);\n"; |
1196 | OS << " " << getType() << " *TI = tempInst" << getUpperName() |
1197 | << ";\n"; |
1198 | OS << " " << getType() << " *I = A->" << getLowerName() |
1199 | << "_begin();\n"; |
1200 | OS << " " << getType() << " *E = A->" << getLowerName() |
1201 | << "_end();\n"; |
1202 | OS << " for (; I != E; ++I, ++TI) {\n"; |
1203 | OS << " ExprResult Result = S.SubstExpr(*I, TemplateArgs);\n"; |
1204 | OS << " if (Result.isInvalid())\n"; |
1205 | OS << " return nullptr;\n"; |
1206 | OS << " *TI = Result.get();\n"; |
1207 | OS << " }\n"; |
1208 | OS << " }\n"; |
1209 | } |
1210 | |
1211 | void writeDump(raw_ostream &OS) const override {} |
1212 | |
1213 | void writeDumpChildren(raw_ostream &OS) const override { |
1214 | OS << " for (" << getAttrName() << "Attr::" << getLowerName() |
1215 | << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->" |
1216 | << getLowerName() << "_end(); I != E; ++I)\n"; |
1217 | OS << " Visit(*I);\n"; |
1218 | } |
1219 | |
1220 | void writeHasChildren(raw_ostream &OS) const override { |
1221 | OS << "SA->" << getLowerName() << "_begin() != " |
1222 | << "SA->" << getLowerName() << "_end()"; |
1223 | } |
1224 | }; |
1225 | |
1226 | class VariadicIdentifierArgument : public VariadicArgument { |
1227 | public: |
1228 | VariadicIdentifierArgument(const Record &Arg, StringRef Attr) |
1229 | : VariadicArgument(Arg, Attr, "IdentifierInfo *") |
1230 | {} |
1231 | }; |
1232 | |
1233 | class VariadicStringArgument : public VariadicArgument { |
1234 | public: |
1235 | VariadicStringArgument(const Record &Arg, StringRef Attr) |
1236 | : VariadicArgument(Arg, Attr, "StringRef") |
1237 | {} |
1238 | |
1239 | void writeCtorBody(raw_ostream &OS) const override { |
1240 | OS << " for (size_t I = 0, E = " << getArgSizeName() << "; I != E;\n" |
1241 | " ++I) {\n" |
1242 | " StringRef Ref = " << getUpperName() << "[I];\n" |
1243 | " if (!Ref.empty()) {\n" |
1244 | " char *Mem = new (Ctx, 1) char[Ref.size()];\n" |
1245 | " std::memcpy(Mem, Ref.data(), Ref.size());\n" |
1246 | " " << getArgName() << "[I] = StringRef(Mem, Ref.size());\n" |
1247 | " }\n" |
1248 | " }\n"; |
1249 | } |
1250 | |
1251 | void writeValueImpl(raw_ostream &OS) const override { |
1252 | OS << " OS << \"\\\"\" << Val << \"\\\"\";\n"; |
1253 | } |
1254 | }; |
1255 | |
1256 | class TypeArgument : public SimpleArgument { |
1257 | public: |
1258 | TypeArgument(const Record &Arg, StringRef Attr) |
1259 | : SimpleArgument(Arg, Attr, "TypeSourceInfo *") |
1260 | {} |
1261 | |
1262 | void writeAccessors(raw_ostream &OS) const override { |
1263 | OS << " QualType get" << getUpperName() << "() const {\n"; |
1264 | OS << " return " << getLowerName() << "->getType();\n"; |
1265 | OS << " }"; |
1266 | OS << " " << getType() << " get" << getUpperName() << "Loc() const {\n"; |
1267 | OS << " return " << getLowerName() << ";\n"; |
1268 | OS << " }"; |
1269 | } |
1270 | |
1271 | void writeASTVisitorTraversal(raw_ostream &OS) const override { |
1272 | OS << " if (auto *TSI = A->get" << getUpperName() << "Loc())\n"; |
1273 | OS << " if (!getDerived().TraverseTypeLoc(TSI->getTypeLoc()))\n"; |
1274 | OS << " return false;\n"; |
1275 | } |
1276 | |
1277 | void writeTemplateInstantiation(raw_ostream &OS) const override { |
1278 | OS << " " << getType() << " tempInst" << getUpperName() << " =\n"; |
1279 | OS << " S.SubstType(A->get" << getUpperName() << "Loc(), " |
1280 | << "TemplateArgs, A->getLoc(), A->getAttrName());\n"; |
1281 | OS << " if (!tempInst" << getUpperName() << ")\n"; |
1282 | OS << " return nullptr;\n"; |
1283 | } |
1284 | |
1285 | void writeTemplateInstantiationArgs(raw_ostream &OS) const override { |
1286 | OS << "tempInst" << getUpperName(); |
1287 | } |
1288 | |
1289 | void writePCHWrite(raw_ostream &OS) const override { |
1290 | OS << " " |
1291 | << WritePCHRecord(getType(), |
1292 | "SA->get" + std::string(getUpperName()) + "Loc()"); |
1293 | } |
1294 | }; |
1295 | |
1296 | } |
1297 | |
1298 | static std::unique_ptr<Argument> |
1299 | createArgument(const Record &Arg, StringRef Attr, |
1300 | const Record *Search = nullptr) { |
1301 | if (!Search) |
1302 | Search = &Arg; |
1303 | |
1304 | std::unique_ptr<Argument> Ptr; |
1305 | llvm::StringRef ArgName = Search->getName(); |
1306 | |
1307 | if (ArgName == "AlignedArgument") |
1308 | Ptr = std::make_unique<AlignedArgument>(Arg, Attr); |
1309 | else if (ArgName == "EnumArgument") |
1310 | Ptr = std::make_unique<EnumArgument>(Arg, Attr); |
1311 | else if (ArgName == "ExprArgument") |
1312 | Ptr = std::make_unique<ExprArgument>(Arg, Attr); |
1313 | else if (ArgName == "DeclArgument") |
1314 | Ptr = std::make_unique<SimpleArgument>( |
1315 | Arg, Attr, (Arg.getValueAsDef("Kind")->getName() + "Decl *").str()); |
1316 | else if (ArgName == "IdentifierArgument") |
1317 | Ptr = std::make_unique<SimpleArgument>(Arg, Attr, "IdentifierInfo *"); |
1318 | else if (ArgName == "DefaultBoolArgument") |
1319 | Ptr = std::make_unique<DefaultSimpleArgument>( |
1320 | Arg, Attr, "bool", Arg.getValueAsBit("Default")); |
1321 | else if (ArgName == "BoolArgument") |
1322 | Ptr = std::make_unique<SimpleArgument>(Arg, Attr, "bool"); |
1323 | else if (ArgName == "DefaultIntArgument") |
1324 | Ptr = std::make_unique<DefaultSimpleArgument>( |
1325 | Arg, Attr, "int", Arg.getValueAsInt("Default")); |
1326 | else if (ArgName == "IntArgument") |
1327 | Ptr = std::make_unique<SimpleArgument>(Arg, Attr, "int"); |
1328 | else if (ArgName == "StringArgument") |
1329 | Ptr = std::make_unique<StringArgument>(Arg, Attr); |
1330 | else if (ArgName == "TypeArgument") |
1331 | Ptr = std::make_unique<TypeArgument>(Arg, Attr); |
1332 | else if (ArgName == "UnsignedArgument") |
1333 | Ptr = std::make_unique<SimpleArgument>(Arg, Attr, "unsigned"); |
1334 | else if (ArgName == "VariadicUnsignedArgument") |
1335 | Ptr = std::make_unique<VariadicArgument>(Arg, Attr, "unsigned"); |
1336 | else if (ArgName == "VariadicStringArgument") |
1337 | Ptr = std::make_unique<VariadicStringArgument>(Arg, Attr); |
1338 | else if (ArgName == "VariadicEnumArgument") |
1339 | Ptr = std::make_unique<VariadicEnumArgument>(Arg, Attr); |
1340 | else if (ArgName == "VariadicExprArgument") |
1341 | Ptr = std::make_unique<VariadicExprArgument>(Arg, Attr); |
1342 | else if (ArgName == "VariadicParamIdxArgument") |
1343 | Ptr = std::make_unique<VariadicParamIdxArgument>(Arg, Attr); |
1344 | else if (ArgName == "VariadicParamOrParamIdxArgument") |
1345 | Ptr = std::make_unique<VariadicParamOrParamIdxArgument>(Arg, Attr); |
1346 | else if (ArgName == "ParamIdxArgument") |
1347 | Ptr = std::make_unique<SimpleArgument>(Arg, Attr, "ParamIdx"); |
1348 | else if (ArgName == "VariadicIdentifierArgument") |
1349 | Ptr = std::make_unique<VariadicIdentifierArgument>(Arg, Attr); |
1350 | else if (ArgName == "VersionArgument") |
1351 | Ptr = std::make_unique<VersionArgument>(Arg, Attr); |
1352 | else if (ArgName == "OMPTraitInfoArgument") |
1353 | Ptr = std::make_unique<SimpleArgument>(Arg, Attr, "OMPTraitInfo *"); |
1354 | |
1355 | if (!Ptr) { |
1356 | |
1357 | ArrayRef<std::pair<Record*, SMRange>> Bases = Search->getSuperClasses(); |
1358 | for (const auto &Base : llvm::reverse(Bases)) { |
1359 | if ((Ptr = createArgument(Arg, Attr, Base.first))) |
1360 | break; |
1361 | } |
1362 | } |
1363 | |
1364 | if (Ptr && Arg.getValueAsBit("Optional")) |
1365 | Ptr->setOptional(true); |
1366 | |
1367 | if (Ptr && Arg.getValueAsBit("Fake")) |
1368 | Ptr->setFake(true); |
1369 | |
1370 | return Ptr; |
1371 | } |
1372 | |
1373 | static void writeAvailabilityValue(raw_ostream &OS) { |
1374 | OS << "\" << getPlatform()->getName();\n" |
1375 | << " if (getStrict()) OS << \", strict\";\n" |
1376 | << " if (!getIntroduced().empty()) OS << \", introduced=\" << getIntroduced();\n" |
1377 | << " if (!getDeprecated().empty()) OS << \", deprecated=\" << getDeprecated();\n" |
1378 | << " if (!getObsoleted().empty()) OS << \", obsoleted=\" << getObsoleted();\n" |
1379 | << " if (getUnavailable()) OS << \", unavailable\";\n" |
1380 | << " OS << \""; |
1381 | } |
1382 | |
1383 | static void writeDeprecatedAttrValue(raw_ostream &OS, std::string &Variety) { |
1384 | OS << "\\\"\" << getMessage() << \"\\\"\";\n"; |
1385 | |
1386 | if (Variety == "GNU") |
1387 | OS << " if (!getReplacement().empty()) OS << \", \\\"\"" |
1388 | " << getReplacement() << \"\\\"\";\n"; |
1389 | OS << " OS << \""; |
1390 | } |
1391 | |
1392 | static void writeGetSpellingFunction(const Record &R, raw_ostream &OS) { |
1393 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R); |
1394 | |
1395 | OS << "const char *" << R.getName() << "Attr::getSpelling() const {\n"; |
1396 | if (Spellings.empty()) { |
1397 | OS << " return \"(No spelling)\";\n}\n\n"; |
1398 | return; |
1399 | } |
1400 | |
1401 | OS << " switch (getAttributeSpellingListIndex()) {\n" |
1402 | " default:\n" |
1403 | " llvm_unreachable(\"Unknown attribute spelling!\");\n" |
1404 | " return \"(No spelling)\";\n"; |
1405 | |
1406 | for (unsigned I = 0; I < Spellings.size(); ++I) |
1407 | OS << " case " << I << ":\n" |
1408 | " return \"" << Spellings[I].name() << "\";\n"; |
1409 | |
1410 | OS << " }\n"; |
1411 | |
1412 | OS << "}\n\n"; |
1413 | } |
1414 | |
1415 | static void |
1416 | writePrettyPrintFunction(const Record &R, |
1417 | const std::vector<std::unique_ptr<Argument>> &Args, |
1418 | raw_ostream &OS) { |
1419 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R); |
1420 | |
1421 | OS << "void " << R.getName() << "Attr::printPretty(" |
1422 | << "raw_ostream &OS, const PrintingPolicy &Policy) const {\n"; |
1423 | |
1424 | if (Spellings.empty()) { |
1425 | OS << "}\n\n"; |
1426 | return; |
1427 | } |
1428 | |
1429 | OS << " bool IsFirstArgument = true; (void)IsFirstArgument;\n" |
1430 | << " unsigned TrailingOmittedArgs = 0; (void)TrailingOmittedArgs;\n" |
1431 | << " switch (getAttributeSpellingListIndex()) {\n" |
1432 | << " default:\n" |
1433 | << " llvm_unreachable(\"Unknown attribute spelling!\");\n" |
1434 | << " break;\n"; |
1435 | |
1436 | for (unsigned I = 0; I < Spellings.size(); ++ I) { |
1437 | llvm::SmallString<16> Prefix; |
1438 | llvm::SmallString<8> Suffix; |
1439 | |
1440 | |
1441 | llvm::SmallString<64> Spelling; |
1442 | std::string Name = Spellings[I].name(); |
1443 | std::string Variety = Spellings[I].variety(); |
1444 | |
1445 | if (Variety == "GNU") { |
1446 | Prefix = " __attribute__(("; |
1447 | Suffix = "))"; |
1448 | } else if (Variety == "CXX11" || Variety == "C2x") { |
1449 | Prefix = " [["; |
1450 | Suffix = "]]"; |
1451 | std::string Namespace = Spellings[I].nameSpace(); |
1452 | if (!Namespace.empty()) { |
1453 | Spelling += Namespace; |
1454 | Spelling += "::"; |
1455 | } |
1456 | } else if (Variety == "Declspec") { |
1457 | Prefix = " __declspec("; |
1458 | Suffix = ")"; |
1459 | } else if (Variety == "Microsoft") { |
1460 | Prefix = "["; |
1461 | Suffix = "]"; |
1462 | } else if (Variety == "Keyword") { |
1463 | Prefix = " "; |
1464 | Suffix = ""; |
1465 | } else if (Variety == "Pragma") { |
1466 | Prefix = "#pragma "; |
1467 | Suffix = "\n"; |
1468 | std::string Namespace = Spellings[I].nameSpace(); |
1469 | if (!Namespace.empty()) { |
1470 | Spelling += Namespace; |
1471 | Spelling += " "; |
1472 | } |
1473 | } else { |
1474 | llvm_unreachable("Unknown attribute syntax variety!"); |
1475 | } |
1476 | |
1477 | Spelling += Name; |
1478 | |
1479 | OS << " case " << I << " : {\n" |
1480 | << " OS << \"" << Prefix << Spelling << "\";\n"; |
1481 | |
1482 | if (Variety == "Pragma") { |
1483 | OS << " printPrettyPragma(OS, Policy);\n"; |
1484 | OS << " OS << \"\\n\";"; |
1485 | OS << " break;\n"; |
1486 | OS << " }\n"; |
1487 | continue; |
1488 | } |
1489 | |
1490 | if (Spelling == "availability") { |
1491 | OS << " OS << \"("; |
1492 | writeAvailabilityValue(OS); |
1493 | OS << ")\";\n"; |
1494 | } else if (Spelling == "deprecated" || Spelling == "gnu::deprecated") { |
1495 | OS << " OS << \"("; |
1496 | writeDeprecatedAttrValue(OS, Variety); |
1497 | OS << ")\";\n"; |
1498 | } else { |
1499 | |
1500 | |
1501 | |
1502 | unsigned NonFakeArgs = 0; |
1503 | bool FoundNonOptArg = false; |
1504 | for (const auto &arg : llvm::reverse(Args)) { |
1505 | if (arg->isFake()) |
1506 | continue; |
1507 | ++NonFakeArgs; |
1508 | if (FoundNonOptArg) |
1509 | continue; |
1510 | |
1511 | |
1512 | if (!arg->isOptional() || arg->getIsOmitted() == "false") { |
1513 | FoundNonOptArg = true; |
1514 | continue; |
1515 | } |
1516 | OS << " if (" << arg->getIsOmitted() << ")\n" |
1517 | << " ++TrailingOmittedArgs;\n"; |
1518 | } |
1519 | unsigned ArgIndex = 0; |
1520 | for (const auto &arg : Args) { |
1521 | if (arg->isFake()) |
1522 | continue; |
1523 | std::string IsOmitted = arg->getIsOmitted(); |
1524 | if (arg->isOptional() && IsOmitted != "false") |
1525 | OS << " if (!(" << IsOmitted << ")) {\n"; |
1526 | |
1527 | if (!arg->isVariadic()) |
1528 | OS << " DelimitAttributeArgument(OS, IsFirstArgument);\n"; |
1529 | OS << " OS << \""; |
1530 | arg->writeValue(OS); |
1531 | OS << "\";\n"; |
1532 | if (arg->isOptional() && IsOmitted != "false") |
1533 | OS << " }\n"; |
1534 | ++ArgIndex; |
1535 | } |
1536 | if (ArgIndex != 0) |
1537 | OS << " if (!IsFirstArgument)\n" |
1538 | << " OS << \")\";\n"; |
1539 | } |
1540 | OS << " OS << \"" << Suffix << "\";\n" |
1541 | << " break;\n" |
1542 | << " }\n"; |
1543 | } |
1544 | |
1545 | |
1546 | OS << "}\n"; |
1547 | |
1548 | OS << "}\n\n"; |
1549 | } |
1550 | |
1551 | |
1552 | static unsigned |
1553 | getSpellingListIndex(const std::vector<FlattenedSpelling> &SpellingList, |
1554 | const FlattenedSpelling &Spelling) { |
1555 | assert(!SpellingList.empty() && "Spelling list is empty!"); |
1556 | |
1557 | for (unsigned Index = 0; Index < SpellingList.size(); ++Index) { |
1558 | const FlattenedSpelling &S = SpellingList[Index]; |
1559 | if (S.variety() != Spelling.variety()) |
1560 | continue; |
1561 | if (S.nameSpace() != Spelling.nameSpace()) |
1562 | continue; |
1563 | if (S.name() != Spelling.name()) |
1564 | continue; |
1565 | |
1566 | return Index; |
1567 | } |
1568 | |
1569 | llvm_unreachable("Unknown spelling!"); |
1570 | } |
1571 | |
1572 | static void writeAttrAccessorDefinition(const Record &R, raw_ostream &OS) { |
1573 | std::vector<Record*> Accessors = R.getValueAsListOfDefs("Accessors"); |
1574 | if (Accessors.empty()) |
1575 | return; |
1576 | |
1577 | const std::vector<FlattenedSpelling> SpellingList = GetFlattenedSpellings(R); |
1578 | assert(!SpellingList.empty() && |
1579 | "Attribute with empty spelling list can't have accessors!"); |
1580 | for (const auto *Accessor : Accessors) { |
1581 | const StringRef Name = Accessor->getValueAsString("Name"); |
1582 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Accessor); |
1583 | |
1584 | OS << " bool " << Name |
1585 | << "() const { return getAttributeSpellingListIndex() == "; |
1586 | for (unsigned Index = 0; Index < Spellings.size(); ++Index) { |
1587 | OS << getSpellingListIndex(SpellingList, Spellings[Index]); |
1588 | if (Index != Spellings.size() - 1) |
1589 | OS << " ||\n getAttributeSpellingListIndex() == "; |
1590 | else |
1591 | OS << "; }\n"; |
1592 | } |
1593 | } |
1594 | } |
1595 | |
1596 | static bool |
1597 | SpellingNamesAreCommon(const std::vector<FlattenedSpelling>& Spellings) { |
1598 | assert(!Spellings.empty() && "An empty list of spellings was provided"); |
1599 | std::string FirstName = |
1600 | std::string(NormalizeNameForSpellingComparison(Spellings.front().name())); |
1601 | for (const auto &Spelling : |
1602 | llvm::make_range(std::next(Spellings.begin()), Spellings.end())) { |
1603 | std::string Name = |
1604 | std::string(NormalizeNameForSpellingComparison(Spelling.name())); |
1605 | if (Name != FirstName) |
1606 | return false; |
1607 | } |
1608 | return true; |
1609 | } |
1610 | |
1611 | typedef std::map<unsigned, std::string> SemanticSpellingMap; |
1612 | static std::string |
1613 | CreateSemanticSpellings(const std::vector<FlattenedSpelling> &Spellings, |
1614 | SemanticSpellingMap &Map) { |
1615 | |
1616 | |
1617 | |
1618 | |
1619 | std::string Ret(" enum Spelling {\n"); |
1620 | std::set<std::string> Uniques; |
1621 | unsigned Idx = 0; |
1622 | |
1623 | |
1624 | |
1625 | |
1626 | assert(Spellings.size() < 15 && |
1627 | "Too many spellings, would step on SpellingNotCalculated in " |
1628 | "AttributeCommonInfo"); |
1629 | for (auto I = Spellings.begin(), E = Spellings.end(); I != E; ++I, ++Idx) { |
1630 | const FlattenedSpelling &S = *I; |
1631 | const std::string &Variety = S.variety(); |
1632 | const std::string &Spelling = S.name(); |
1633 | const std::string &Namespace = S.nameSpace(); |
1634 | std::string EnumName; |
1635 | |
1636 | EnumName += (Variety + "_"); |
1637 | if (!Namespace.empty()) |
1638 | EnumName += (NormalizeNameForSpellingComparison(Namespace).str() + |
1639 | "_"); |
1640 | EnumName += NormalizeNameForSpellingComparison(Spelling); |
1641 | |
1642 | |
1643 | |
1644 | Map[Idx] = EnumName; |
1645 | |
1646 | |
1647 | |
1648 | |
1649 | |
1650 | if (Uniques.find(EnumName) != Uniques.end()) |
1651 | continue; |
1652 | |
1653 | Uniques.insert(EnumName); |
1654 | if (I != Spellings.begin()) |
1655 | Ret += ",\n"; |
1656 | |
1657 | |
1658 | |
1659 | |
1660 | Ret += " " + EnumName + " = " + llvm::utostr(Idx); |
1661 | } |
1662 | Ret += ",\n SpellingNotCalculated = 15\n"; |
1663 | Ret += "\n };\n\n"; |
1664 | return Ret; |
1665 | } |
1666 | |
1667 | void WriteSemanticSpellingSwitch(const std::string &VarName, |
1668 | const SemanticSpellingMap &Map, |
1669 | raw_ostream &OS) { |
1670 | OS << " switch (" << VarName << ") {\n default: " |
1671 | << "llvm_unreachable(\"Unknown spelling list index\");\n"; |
1672 | for (const auto &I : Map) |
1673 | OS << " case " << I.first << ": return " << I.second << ";\n"; |
1674 | OS << " }\n"; |
1675 | } |
1676 | |
1677 | |
1678 | static void emitClangAttrLateParsedList(RecordKeeper &Records, raw_ostream &OS) { |
1679 | OS << "#if defined(CLANG_ATTR_LATE_PARSED_LIST)\n"; |
1680 | std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); |
1681 | |
1682 | for (const auto *Attr : Attrs) { |
1683 | bool LateParsed = Attr->getValueAsBit("LateParsed"); |
1684 | |
1685 | if (LateParsed) { |
1686 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr); |
1687 | |
1688 | |
1689 | for (const auto &I : Spellings) { |
1690 | if (I.variety() != "GNU") |
1691 | continue; |
1692 | OS << ".Case(\"" << I.name() << "\", " << LateParsed << ")\n"; |
1693 | } |
1694 | } |
1695 | } |
1696 | OS << "#endif // CLANG_ATTR_LATE_PARSED_LIST\n\n"; |
1697 | } |
1698 | |
1699 | static bool hasGNUorCXX11Spelling(const Record &Attribute) { |
1700 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attribute); |
1701 | for (const auto &I : Spellings) { |
1702 | if (I.variety() == "GNU" || I.variety() == "CXX11") |
1703 | return true; |
1704 | } |
1705 | return false; |
1706 | } |
1707 | |
1708 | namespace { |
1709 | |
1710 | struct AttributeSubjectMatchRule { |
1711 | const Record *MetaSubject; |
1712 | const Record *Constraint; |
1713 | |
1714 | AttributeSubjectMatchRule(const Record *MetaSubject, const Record *Constraint) |
1715 | : MetaSubject(MetaSubject), Constraint(Constraint) { |
1716 | assert(MetaSubject && "Missing subject"); |
1717 | } |
1718 | |
1719 | bool isSubRule() const { return Constraint != nullptr; } |
1720 | |
1721 | std::vector<Record *> getSubjects() const { |
1722 | return (Constraint ? Constraint : MetaSubject) |
1723 | ->getValueAsListOfDefs("Subjects"); |
1724 | } |
1725 | |
1726 | std::vector<Record *> getLangOpts() const { |
1727 | if (Constraint) { |
1728 | |
1729 | |
1730 | std::vector<Record *> Opts = Constraint->getValueAsListOfDefs("LangOpts"); |
1731 | if (!Opts.empty()) |
1732 | return Opts; |
1733 | } |
1734 | return MetaSubject->getValueAsListOfDefs("LangOpts"); |
1735 | } |
1736 | |
1737 | |
1738 | bool isAbstractRule() const { return getSubjects().empty(); } |
1739 | |
1740 | StringRef getName() const { |
1741 | return (Constraint ? Constraint : MetaSubject)->getValueAsString("Name"); |
1742 | } |
1743 | |
1744 | bool isNegatedSubRule() const { |
1745 | assert(isSubRule() && "Not a sub-rule"); |
1746 | return Constraint->getValueAsBit("Negated"); |
1747 | } |
1748 | |
1749 | std::string getSpelling() const { |
1750 | std::string Result = std::string(MetaSubject->getValueAsString("Name")); |
1751 | if (isSubRule()) { |
1752 | Result += '('; |
1753 | if (isNegatedSubRule()) |
1754 | Result += "unless("; |
1755 | Result += getName(); |
1756 | if (isNegatedSubRule()) |
1757 | Result += ')'; |
1758 | Result += ')'; |
1759 | } |
1760 | return Result; |
1761 | } |
1762 | |
1763 | std::string getEnumValueName() const { |
1764 | SmallString<128> Result; |
1765 | Result += "SubjectMatchRule_"; |
1766 | Result += MetaSubject->getValueAsString("Name"); |
1767 | if (isSubRule()) { |
1768 | Result += "_"; |
1769 | if (isNegatedSubRule()) |
1770 | Result += "not_"; |
1771 | Result += Constraint->getValueAsString("Name"); |
1772 | } |
1773 | if (isAbstractRule()) |
1774 | Result += "_abstract"; |
1775 | return std::string(Result.str()); |
1776 | } |
1777 | |
1778 | std::string getEnumValue() const { return "attr::" + getEnumValueName(); } |
1779 | |
1780 | static const char *EnumName; |
1781 | }; |
1782 | |
1783 | const char *AttributeSubjectMatchRule::EnumName = "attr::SubjectMatchRule"; |
1784 | |
1785 | struct PragmaClangAttributeSupport { |
1786 | std::vector<AttributeSubjectMatchRule> Rules; |
1787 | |
1788 | class RuleOrAggregateRuleSet { |
1789 | std::vector<AttributeSubjectMatchRule> Rules; |
1790 | bool IsRule; |
1791 | RuleOrAggregateRuleSet(ArrayRef<AttributeSubjectMatchRule> Rules, |
1792 | bool IsRule) |
1793 | : Rules(Rules), IsRule(IsRule) {} |
1794 | |
1795 | public: |
1796 | bool isRule() const { return IsRule; } |
1797 | |
1798 | const AttributeSubjectMatchRule &getRule() const { |
1799 | assert(IsRule && "not a rule!"); |
1800 | return Rules[0]; |
1801 | } |
1802 | |
1803 | ArrayRef<AttributeSubjectMatchRule> getAggregateRuleSet() const { |
1804 | return Rules; |
1805 | } |
1806 | |
1807 | static RuleOrAggregateRuleSet |
1808 | getRule(const AttributeSubjectMatchRule &Rule) { |
1809 | return RuleOrAggregateRuleSet(Rule, true); |
1810 | } |
1811 | static RuleOrAggregateRuleSet |
1812 | getAggregateRuleSet(ArrayRef<AttributeSubjectMatchRule> Rules) { |
1813 | return RuleOrAggregateRuleSet(Rules, false); |
1814 | } |
1815 | }; |
1816 | llvm::DenseMap<const Record *, RuleOrAggregateRuleSet> SubjectsToRules; |
1817 | |
1818 | PragmaClangAttributeSupport(RecordKeeper &Records); |
1819 | |
1820 | bool isAttributedSupported(const Record &Attribute); |
1821 | |
1822 | void emitMatchRuleList(raw_ostream &OS); |
1823 | |
1824 | void generateStrictConformsTo(const Record &Attr, raw_ostream &OS); |
1825 | |
1826 | void generateParsingHelpers(raw_ostream &OS); |
1827 | }; |
1828 | |
1829 | } |
1830 | |
1831 | static bool isSupportedPragmaClangAttributeSubject(const Record &Subject) { |
1832 | |
1833 | |
1834 | |
1835 | |
1836 | if (Subject.isSubClassOf("DeclNode") || Subject.isSubClassOf("DeclBase") || |
1837 | Subject.getName() == "DeclBase") |
1838 | return true; |
1839 | |
1840 | if (Subject.isSubClassOf("SubsetSubject")) |
1841 | return isSupportedPragmaClangAttributeSubject( |
1842 | *Subject.getValueAsDef("Base")); |
1843 | |
1844 | return false; |
1845 | } |
1846 | |
1847 | static bool doesDeclDeriveFrom(const Record *D, const Record *Base) { |
1848 | const Record *CurrentBase = D->getValueAsOptionalDef(BaseFieldName); |
1849 | if (!CurrentBase) |
1850 | return false; |
1851 | if (CurrentBase == Base) |
1852 | return true; |
1853 | return doesDeclDeriveFrom(CurrentBase, Base); |
1854 | } |
1855 | |
1856 | PragmaClangAttributeSupport::PragmaClangAttributeSupport( |
1857 | RecordKeeper &Records) { |
1858 | std::vector<Record *> MetaSubjects = |
1859 | Records.getAllDerivedDefinitions("AttrSubjectMatcherRule"); |
1860 | auto MapFromSubjectsToRules = [this](const Record *SubjectContainer, |
1861 | const Record *MetaSubject, |
1862 | const Record *Constraint) { |
1863 | Rules.emplace_back(MetaSubject, Constraint); |
1864 | std::vector<Record *> ApplicableSubjects = |
1865 | SubjectContainer->getValueAsListOfDefs("Subjects"); |
1866 | for (const auto *Subject : ApplicableSubjects) { |
1867 | bool Inserted = |
1868 | SubjectsToRules |
1869 | .try_emplace(Subject, RuleOrAggregateRuleSet::getRule( |
1870 | AttributeSubjectMatchRule(MetaSubject, |
1871 | Constraint))) |
1872 | .second; |
1873 | if (!Inserted) { |
1874 | PrintFatalError("Attribute subject match rules should not represent" |
1875 | "same attribute subjects."); |
1876 | } |
1877 | } |
1878 | }; |
1879 | for (const auto *MetaSubject : MetaSubjects) { |
1880 | MapFromSubjectsToRules(MetaSubject, MetaSubject, nullptr); |
1881 | std::vector<Record *> Constraints = |
1882 | MetaSubject->getValueAsListOfDefs("Constraints"); |
1883 | for (const auto *Constraint : Constraints) |
1884 | MapFromSubjectsToRules(Constraint, MetaSubject, Constraint); |
1885 | } |
1886 | |
1887 | std::vector<Record *> Aggregates = |
1888 | Records.getAllDerivedDefinitions("AttrSubjectMatcherAggregateRule"); |
1889 | std::vector<Record *> DeclNodes = |
1890 | Records.getAllDerivedDefinitions(DeclNodeClassName); |
1891 | for (const auto *Aggregate : Aggregates) { |
1892 | Record *SubjectDecl = Aggregate->getValueAsDef("Subject"); |
1893 | |
1894 | |
1895 | |
1896 | std::vector<AttributeSubjectMatchRule> Rules; |
1897 | for (const auto *D : DeclNodes) { |
1898 | if (doesDeclDeriveFrom(D, SubjectDecl)) { |
1899 | auto It = SubjectsToRules.find(D); |
1900 | if (It == SubjectsToRules.end()) |
1901 | continue; |
1902 | if (!It->second.isRule() || It->second.getRule().isSubRule()) |
1903 | continue; |
1904 | Rules.push_back(It->second.getRule()); |
1905 | } |
1906 | } |
1907 | |
1908 | bool Inserted = |
1909 | SubjectsToRules |
1910 | .try_emplace(SubjectDecl, |
1911 | RuleOrAggregateRuleSet::getAggregateRuleSet(Rules)) |
1912 | .second; |
1913 | if (!Inserted) { |
1914 | PrintFatalError("Attribute subject match rules should not represent" |
1915 | "same attribute subjects."); |
1916 | } |
1917 | } |
1918 | } |
1919 | |
1920 | static PragmaClangAttributeSupport & |
1921 | getPragmaAttributeSupport(RecordKeeper &Records) { |
1922 | static PragmaClangAttributeSupport Instance(Records); |
1923 | return Instance; |
1924 | } |
1925 | |
1926 | void PragmaClangAttributeSupport::emitMatchRuleList(raw_ostream &OS) { |
1927 | OS << "#ifndef ATTR_MATCH_SUB_RULE\n"; |
1928 | OS << "#define ATTR_MATCH_SUB_RULE(Value, Spelling, IsAbstract, Parent, " |
1929 | "IsNegated) " |
1930 | << "ATTR_MATCH_RULE(Value, Spelling, IsAbstract)\n"; |
1931 | OS << "#endif\n"; |
1932 | for (const auto &Rule : Rules) { |
1933 | OS << (Rule.isSubRule() ? "ATTR_MATCH_SUB_RULE" : "ATTR_MATCH_RULE") << '('; |
1934 | OS << Rule.getEnumValueName() << ", \"" << Rule.getSpelling() << "\", " |
1935 | << Rule.isAbstractRule(); |
1936 | if (Rule.isSubRule()) |
1937 | OS << ", " |
1938 | << AttributeSubjectMatchRule(Rule.MetaSubject, nullptr).getEnumValue() |
1939 | << ", " << Rule.isNegatedSubRule(); |
1940 | OS << ")\n"; |
1941 | } |
1942 | OS << "#undef ATTR_MATCH_SUB_RULE\n"; |
1943 | } |
1944 | |
1945 | bool PragmaClangAttributeSupport::isAttributedSupported( |
1946 | const Record &Attribute) { |
1947 | |
1948 | |
1949 | bool Unset; |
1950 | bool SpecifiedResult = |
1951 | Attribute.getValueAsBitOrUnset("PragmaAttributeSupport", Unset); |
1952 | if (!Unset) |
1953 | return SpecifiedResult; |
1954 | |
1955 | |
1956 | |
1957 | if (Attribute.getValueAsBit("LateParsed")) |
1958 | return false; |
1959 | |
1960 | if (!hasGNUorCXX11Spelling(Attribute)) |
1961 | return false; |
1962 | |
1963 | |
1964 | if (Attribute.isValueUnset("Subjects")) |
1965 | return false; |
1966 | const Record *SubjectObj = Attribute.getValueAsDef("Subjects"); |
1967 | std::vector<Record *> Subjects = SubjectObj->getValueAsListOfDefs("Subjects"); |
1968 | bool HasAtLeastOneValidSubject = false; |
1969 | for (const auto *Subject : Subjects) { |
1970 | if (!isSupportedPragmaClangAttributeSubject(*Subject)) |
1971 | continue; |
1972 | if (SubjectsToRules.find(Subject) == SubjectsToRules.end()) |
1973 | return false; |
1974 | HasAtLeastOneValidSubject = true; |
1975 | } |
1976 | return HasAtLeastOneValidSubject; |
1977 | } |
1978 | |
1979 | static std::string GenerateTestExpression(ArrayRef<Record *> LangOpts) { |
1980 | std::string Test; |
1981 | |
1982 | for (auto *E : LangOpts) { |
1983 | if (!Test.empty()) |
1984 | Test += " || "; |
1985 | |
1986 | const StringRef Code = E->getValueAsString("CustomCode"); |
1987 | if (!Code.empty()) { |
1988 | Test += "("; |
1989 | Test += Code; |
1990 | Test += ")"; |
1991 | if (!E->getValueAsString("Name").empty()) { |
1992 | PrintWarning( |
1993 | E->getLoc(), |
1994 | "non-empty 'Name' field ignored because 'CustomCode' was supplied"); |
1995 | } |
1996 | } else { |
1997 | Test += "LangOpts."; |
1998 | Test += E->getValueAsString("Name"); |
1999 | } |
2000 | } |
2001 | |
2002 | if (Test.empty()) |
2003 | return "true"; |
2004 | |
2005 | return Test; |
2006 | } |
2007 | |
2008 | void |
2009 | PragmaClangAttributeSupport::generateStrictConformsTo(const Record &Attr, |
2010 | raw_ostream &OS) { |
2011 | if (!isAttributedSupported(Attr) || Attr.isValueUnset("Subjects")) |
2012 | return; |
2013 | |
2014 | |
2015 | OS << "void getPragmaAttributeMatchRules(" |
2016 | << "llvm::SmallVectorImpl<std::pair<" |
2017 | << AttributeSubjectMatchRule::EnumName |
2018 | << ", bool>> &MatchRules, const LangOptions &LangOpts) const override {\n"; |
2019 | const Record *SubjectObj = Attr.getValueAsDef("Subjects"); |
2020 | std::vector<Record *> Subjects = SubjectObj->getValueAsListOfDefs("Subjects"); |
2021 | for (const auto *Subject : Subjects) { |
2022 | if (!isSupportedPragmaClangAttributeSubject(*Subject)) |
2023 | continue; |
2024 | auto It = SubjectsToRules.find(Subject); |
2025 | assert(It != SubjectsToRules.end() && |
2026 | "This attribute is unsupported by #pragma clang attribute"); |
2027 | for (const auto &Rule : It->getSecond().getAggregateRuleSet()) { |
2028 | |
2029 | |
2030 | std::vector<Record *> LangOpts = Rule.getLangOpts(); |
2031 | OS << " MatchRules.push_back(std::make_pair(" << Rule.getEnumValue() |
2032 | << ", /*IsSupported=*/" << GenerateTestExpression(LangOpts) |
2033 | << "));\n"; |
2034 | } |
2035 | } |
2036 | OS << "}\n\n"; |
2037 | } |
2038 | |
2039 | void PragmaClangAttributeSupport::generateParsingHelpers(raw_ostream &OS) { |
2040 | |
2041 | OS << "Optional<attr::SubjectMatchRule> " |
2042 | "defaultIsAttributeSubjectMatchSubRuleFor(StringRef, bool) {\n"; |
2043 | OS << " return None;\n"; |
2044 | OS << "}\n\n"; |
2045 | |
2046 | std::map<const Record *, std::vector<AttributeSubjectMatchRule>> |
2047 | SubMatchRules; |
2048 | for (const auto &Rule : Rules) { |
2049 | if (!Rule.isSubRule()) |
2050 | continue; |
2051 | SubMatchRules[Rule.MetaSubject].push_back(Rule); |
2052 | } |
2053 | |
2054 | for (const auto &SubMatchRule : SubMatchRules) { |
2055 | OS << "Optional<attr::SubjectMatchRule> isAttributeSubjectMatchSubRuleFor_" |
2056 | << SubMatchRule.first->getValueAsString("Name") |
2057 | << "(StringRef Name, bool IsUnless) {\n"; |
2058 | OS << " if (IsUnless)\n"; |
2059 | OS << " return " |
2060 | "llvm::StringSwitch<Optional<attr::SubjectMatchRule>>(Name).\n"; |
2061 | for (const auto &Rule : SubMatchRule.second) { |
2062 | if (Rule.isNegatedSubRule()) |
2063 | OS << " Case(\"" << Rule.getName() << "\", " << Rule.getEnumValue() |
2064 | << ").\n"; |
2065 | } |
2066 | OS << " Default(None);\n"; |
2067 | OS << " return " |
2068 | "llvm::StringSwitch<Optional<attr::SubjectMatchRule>>(Name).\n"; |
2069 | for (const auto &Rule : SubMatchRule.second) { |
2070 | if (!Rule.isNegatedSubRule()) |
2071 | OS << " Case(\"" << Rule.getName() << "\", " << Rule.getEnumValue() |
2072 | << ").\n"; |
2073 | } |
2074 | OS << " Default(None);\n"; |
2075 | OS << "}\n\n"; |
2076 | } |
2077 | |
2078 | |
2079 | OS << "std::pair<Optional<attr::SubjectMatchRule>, " |
2080 | "Optional<attr::SubjectMatchRule> (*)(StringRef, " |
2081 | "bool)> isAttributeSubjectMatchRule(StringRef Name) {\n"; |
2082 | OS << " return " |
2083 | "llvm::StringSwitch<std::pair<Optional<attr::SubjectMatchRule>, " |
2084 | "Optional<attr::SubjectMatchRule> (*) (StringRef, " |
2085 | "bool)>>(Name).\n"; |
2086 | for (const auto &Rule : Rules) { |
2087 | if (Rule.isSubRule()) |
2088 | continue; |
2089 | std::string SubRuleFunction; |
2090 | if (SubMatchRules.count(Rule.MetaSubject)) |
2091 | SubRuleFunction = |
2092 | ("isAttributeSubjectMatchSubRuleFor_" + Rule.getName()).str(); |
2093 | else |
2094 | SubRuleFunction = "defaultIsAttributeSubjectMatchSubRuleFor"; |
2095 | OS << " Case(\"" << Rule.getName() << "\", std::make_pair(" |
2096 | << Rule.getEnumValue() << ", " << SubRuleFunction << ")).\n"; |
2097 | } |
2098 | OS << " Default(std::make_pair(None, " |
2099 | "defaultIsAttributeSubjectMatchSubRuleFor));\n"; |
2100 | OS << "}\n\n"; |
2101 | |
2102 | |
2103 | OS << "const char *validAttributeSubjectMatchSubRules(" |
2104 | << AttributeSubjectMatchRule::EnumName << " Rule) {\n"; |
2105 | OS << " switch (Rule) {\n"; |
2106 | for (const auto &SubMatchRule : SubMatchRules) { |
2107 | OS << " case " |
2108 | << AttributeSubjectMatchRule(SubMatchRule.first, nullptr).getEnumValue() |
2109 | << ":\n"; |
2110 | OS << " return \"'"; |
2111 | bool IsFirst = true; |
2112 | for (const auto &Rule : SubMatchRule.second) { |
2113 | if (!IsFirst) |
2114 | OS << ", '"; |
2115 | IsFirst = false; |
2116 | if (Rule.isNegatedSubRule()) |
2117 | OS << "unless("; |
2118 | OS << Rule.getName(); |
2119 | if (Rule.isNegatedSubRule()) |
2120 | OS << ')'; |
2121 | OS << "'"; |
2122 | } |
2123 | OS << "\";\n"; |
2124 | } |
2125 | OS << " default: return nullptr;\n"; |
2126 | OS << " }\n"; |
2127 | OS << "}\n\n"; |
2128 | } |
2129 | |
2130 | template <typename Fn> |
2131 | static void forEachUniqueSpelling(const Record &Attr, Fn &&F) { |
2132 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr); |
2133 | SmallDenseSet<StringRef, 8> Seen; |
2134 | for (const FlattenedSpelling &S : Spellings) { |
2135 | if (Seen.insert(S.name()).second) |
2136 | F(S); |
2137 | } |
2138 | } |
2139 | |
2140 | |
2141 | static void emitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) { |
2142 | OS << "#if defined(CLANG_ATTR_TYPE_ARG_LIST)\n"; |
2143 | std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"); |
2144 | |
2145 | for (const auto *Attr : Attrs) { |
2146 | |
2147 | std::vector<Record *> Args = Attr->getValueAsListOfDefs("Args"); |
2148 | if (Args.empty()) |
2149 | continue; |
2150 | |
2151 | if (Args[0]->getSuperClasses().back().first->getName() != "TypeArgument") |
2152 | continue; |
2153 | |
2154 | |
2155 | forEachUniqueSpelling(*Attr, [&](const FlattenedSpelling &S) { |
2156 | OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n"; |
2157 | }); |
2158 | } |
2159 | OS << "#endif // CLANG_ATTR_TYPE_ARG_LIST\n\n"; |
2160 | } |
2161 | |
2162 | |
2163 | |
2164 | static void emitClangAttrArgContextList(RecordKeeper &Records, raw_ostream &OS) { |
2165 | OS << "#if defined(CLANG_ATTR_ARG_CONTEXT_LIST)\n"; |
2166 | ParsedAttrMap Attrs = getParsedAttrList(Records); |
2167 | for (const auto &I : Attrs) { |
2168 | const Record &Attr = *I.second; |
2169 | |
2170 | if (!Attr.getValueAsBit("ParseArgumentsAsUnevaluated")) |
2171 | continue; |
2172 | |
2173 | |
2174 | forEachUniqueSpelling(Attr, [&](const FlattenedSpelling &S) { |
2175 | OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n"; |
2176 | }); |
2177 | } |
2178 | OS << "#endif // CLANG_ATTR_ARG_CONTEXT_LIST\n\n"; |
2179 | } |
2180 | |
2181 | static bool isIdentifierArgument(Record *Arg) { |
2182 | return !Arg->getSuperClasses().empty() && |
2183 | llvm::StringSwitch<bool>(Arg->getSuperClasses().back().first->getName()) |
2184 | .Case("IdentifierArgument", true) |
2185 | .Case("EnumArgument", true) |
2186 | .Case("VariadicEnumArgument", true) |
2187 | .Default(false); |
2188 | } |
2189 | |
2190 | static bool isVariadicIdentifierArgument(Record *Arg) { |
2191 | return !Arg->getSuperClasses().empty() && |
2192 | llvm::StringSwitch<bool>( |
2193 | Arg->getSuperClasses().back().first->getName()) |
2194 | .Case("VariadicIdentifierArgument", true) |
2195 | .Case("VariadicParamOrParamIdxArgument", true) |
2196 | .Default(false); |
2197 | } |
2198 | |
2199 | static void emitClangAttrVariadicIdentifierArgList(RecordKeeper &Records, |
2200 | raw_ostream &OS) { |
2201 | OS << "#if defined(CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST)\n"; |
2202 | std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"); |
2203 | for (const auto *A : Attrs) { |
2204 | |
2205 | std::vector<Record *> Args = A->getValueAsListOfDefs("Args"); |
2206 | if (Args.empty() || !isVariadicIdentifierArgument(Args[0])) |
2207 | continue; |
2208 | |
2209 | |
2210 | forEachUniqueSpelling(*A, [&](const FlattenedSpelling &S) { |
2211 | OS << ".Case(\"" << S.name() << "\", " |
2212 | << "true" |
2213 | << ")\n"; |
2214 | }); |
2215 | } |
2216 | OS << "#endif // CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST\n\n"; |
2217 | } |
2218 | |
2219 | |
2220 | static void emitClangAttrIdentifierArgList(RecordKeeper &Records, raw_ostream &OS) { |
2221 | OS << "#if defined(CLANG_ATTR_IDENTIFIER_ARG_LIST)\n"; |
2222 | std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); |
2223 | |
2224 | for (const auto *Attr : Attrs) { |
2225 | |
2226 | std::vector<Record *> Args = Attr->getValueAsListOfDefs("Args"); |
2227 | if (Args.empty() || !isIdentifierArgument(Args[0])) |
2228 | continue; |
2229 | |
2230 | |
2231 | forEachUniqueSpelling(*Attr, [&](const FlattenedSpelling &S) { |
2232 | OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n"; |
2233 | }); |
2234 | } |
2235 | OS << "#endif // CLANG_ATTR_IDENTIFIER_ARG_LIST\n\n"; |
2236 | } |
2237 | |
2238 | static bool keywordThisIsaIdentifierInArgument(const Record *Arg) { |
2239 | return !Arg->getSuperClasses().empty() && |
2240 | llvm::StringSwitch<bool>( |
2241 | Arg->getSuperClasses().back().first->getName()) |
2242 | .Case("VariadicParamOrParamIdxArgument", true) |
2243 | .Default(false); |
2244 | } |
2245 | |
2246 | static void emitClangAttrThisIsaIdentifierArgList(RecordKeeper &Records, |
2247 | raw_ostream &OS) { |
2248 | OS << "#if defined(CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST)\n"; |
2249 | std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"); |
2250 | for (const auto *A : Attrs) { |
2251 | |
2252 | std::vector<Record *> Args = A->getValueAsListOfDefs("Args"); |
2253 | if (Args.empty() || !keywordThisIsaIdentifierInArgument(Args[0])) |
2254 | continue; |
2255 | |
2256 | |
2257 | forEachUniqueSpelling(*A, [&](const FlattenedSpelling &S) { |
2258 | OS << ".Case(\"" << S.name() << "\", " |
2259 | << "true" |
2260 | << ")\n"; |
2261 | }); |
2262 | } |
2263 | OS << "#endif // CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST\n\n"; |
2264 | } |
2265 | |
2266 | static void emitAttributes(RecordKeeper &Records, raw_ostream &OS, |
2267 | bool Header) { |
2268 | std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); |
2269 | ParsedAttrMap AttrMap = getParsedAttrList(Records); |
2270 | |
2271 | |
2272 | |
2273 | |
2274 | OS << "static inline void DelimitAttributeArgument(" |
2275 | << "raw_ostream& OS, bool& IsFirst) {\n" |
2276 | << " if (IsFirst) {\n" |
2277 | << " IsFirst = false;\n" |
2278 | << " OS << \"(\";\n" |
2279 | << " } else\n" |
2280 | << " OS << \", \";\n" |
2281 | << "}\n"; |
2282 | |
2283 | for (const auto *Attr : Attrs) { |
2284 | const Record &R = *Attr; |
2285 | |
2286 | |
2287 | |
2288 | |
2289 | |
2290 | |
2291 | |
2292 | |
2293 | |
2294 | |
2295 | (void)R.getValueAsListOfDefs("Documentation"); |
2296 | |
2297 | if (!R.getValueAsBit("ASTNode")) |
2298 | continue; |
2299 | |
2300 | ArrayRef<std::pair<Record *, SMRange>> Supers = R.getSuperClasses(); |
2301 | assert(!Supers.empty() && "Forgot to specify a superclass for the attr"); |
2302 | std::string SuperName; |
2303 | bool Inheritable = false; |
2304 | for (const auto &Super : llvm::reverse(Supers)) { |
2305 | const Record *R = Super.first; |
2306 | if (R->getName() != "TargetSpecificAttr" && |
2307 | R->getName() != "DeclOrTypeAttr" && SuperName.empty()) |
2308 | SuperName = std::string(R->getName()); |
2309 | if (R->getName() == "InheritableAttr") |
2310 | Inheritable = true; |
2311 | } |
2312 | |
2313 | if (Header) |
2314 | OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n"; |
2315 | else |
2316 | OS << "\n// " << R.getName() << "Attr implementation\n\n"; |
2317 | |
2318 | std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args"); |
2319 | std::vector<std::unique_ptr<Argument>> Args; |
2320 | Args.reserve(ArgRecords.size()); |
2321 | |
2322 | bool HasOptArg = false; |
2323 | bool HasFakeArg = false; |
2324 | for (const auto *ArgRecord : ArgRecords) { |
2325 | Args.emplace_back(createArgument(*ArgRecord, R.getName())); |
2326 | if (Header) { |
2327 | Args.back()->writeDeclarations(OS); |
2328 | OS << "\n\n"; |
2329 | } |
2330 | |
2331 | |
2332 | if (Args.back()->isFake()) { |
2333 | HasFakeArg = true; |
2334 | } else if (Args.back()->isOptional()) { |
2335 | HasOptArg = true; |
2336 | } |
2337 | } |
2338 | |
2339 | if (Header) |
2340 | OS << "public:\n"; |
2341 | |
2342 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R); |
2343 | |
2344 | |
2345 | |
2346 | |
2347 | bool ElideSpelling = (Spellings.size() <= 1) || |
2348 | SpellingNamesAreCommon(Spellings); |
2349 | |
2350 | |
2351 | SemanticSpellingMap SemanticToSyntacticMap; |
2352 | |
2353 | std::string SpellingEnum; |
2354 | if (Spellings.size() > 1) |
2355 | SpellingEnum = CreateSemanticSpellings(Spellings, SemanticToSyntacticMap); |
2356 | if (Header) |
2357 | OS << SpellingEnum; |
2358 | |
2359 | const auto &ParsedAttrSpellingItr = llvm::find_if( |
2360 | AttrMap, [R](const std::pair<std::string, const Record *> &P) { |
2361 | return &R == P.second; |
2362 | }); |
2363 | |
2364 | |
2365 | auto emitCreate = [&](bool Implicit, bool emitFake) { |
2366 | if (Header) |
2367 | OS << " static "; |
2368 | OS << R.getName() << "Attr *"; |
2369 | if (!Header) |
2370 | OS << R.getName() << "Attr::"; |
2371 | OS << "Create"; |
2372 | if (Implicit) |
2373 | OS << "Implicit"; |
2374 | OS << "("; |
2375 | OS << "ASTContext &Ctx"; |
2376 | for (auto const &ai : Args) { |
2377 | if (ai->isFake() && !emitFake) continue; |
2378 | OS << ", "; |
2379 | ai->writeCtorParameters(OS); |
2380 | } |
2381 | OS << ", const AttributeCommonInfo &CommonInfo"; |
2382 | if (Header && Implicit) |
2383 | OS << " = {SourceRange{}}"; |
2384 | OS << ")"; |
2385 | if (Header) { |
2386 | OS << ";\n"; |
2387 | return; |
2388 | } |
2389 | |
2390 | OS << " {\n"; |
2391 | OS << " auto *A = new (Ctx) " << R.getName(); |
2392 | OS << "Attr(Ctx, CommonInfo"; |
2393 | for (auto const &ai : Args) { |
2394 | if (ai->isFake() && !emitFake) continue; |
2395 | OS << ", "; |
2396 | ai->writeImplicitCtorArgs(OS); |
2397 | } |
2398 | OS << ");\n"; |
2399 | if (Implicit) { |
2400 | OS << " A->setImplicit(true);\n"; |
2401 | } |
2402 | if (Implicit || ElideSpelling) { |
2403 | OS << " if (!A->isAttributeSpellingListCalculated() && " |
2404 | "!A->getAttrName())\n"; |
2405 | OS << " A->setAttributeSpellingListIndex(0);\n"; |
2406 | } |
2407 | OS << " return A;\n}\n\n"; |
2408 | }; |
2409 | |
2410 | auto emitCreateNoCI = [&](bool Implicit, bool emitFake) { |
2411 | if (Header) |
2412 | OS << " static "; |
2413 | OS << R.getName() << "Attr *"; |
2414 | if (!Header) |
2415 | OS << R.getName() << "Attr::"; |
2416 | OS << "Create"; |
2417 | if (Implicit) |
2418 | OS << "Implicit"; |
2419 | OS << "("; |
2420 | OS << "ASTContext &Ctx"; |
2421 | for (auto const &ai : Args) { |
2422 | if (ai->isFake() && !emitFake) continue; |
2423 | OS << ", "; |
2424 | ai->writeCtorParameters(OS); |
2425 | } |
2426 | OS << ", SourceRange Range, AttributeCommonInfo::Syntax Syntax"; |
2427 | if (!ElideSpelling) { |
2428 | OS << ", " << R.getName() << "Attr::Spelling S"; |
2429 | if (Header) |
2430 | OS << " = static_cast<Spelling>(SpellingNotCalculated)"; |
2431 | } |
2432 | OS << ")"; |
2433 | if (Header) { |
2434 | OS << ";\n"; |
2435 | return; |
2436 | } |
2437 | |
2438 | OS << " {\n"; |
2439 | OS << " AttributeCommonInfo I(Range, "; |
2440 | |
2441 | if (ParsedAttrSpellingItr != std::end(AttrMap)) |
2442 | OS << "AT_" << ParsedAttrSpellingItr->first; |
2443 | else |
2444 | OS << "NoSemaHandlerAttribute"; |
2445 | |
2446 | OS << ", Syntax"; |
2447 | if (!ElideSpelling) |
2448 | OS << ", S"; |
2449 | OS << ");\n"; |
2450 | OS << " return Create"; |
2451 | if (Implicit) |
2452 | OS << "Implicit"; |
2453 | OS << "(Ctx"; |
2454 | for (auto const &ai : Args) { |
2455 | if (ai->isFake() && !emitFake) continue; |
2456 | OS << ", "; |
2457 | ai->writeImplicitCtorArgs(OS); |
2458 | } |
2459 | OS << ", I);\n"; |
2460 | OS << "}\n\n"; |
2461 | }; |
2462 | |
2463 | auto emitCreates = [&](bool emitFake) { |
2464 | emitCreate(true, emitFake); |
2465 | emitCreate(false, emitFake); |
2466 | emitCreateNoCI(true, emitFake); |
2467 | emitCreateNoCI(false, emitFake); |
2468 | }; |
2469 | |
2470 | if (Header) |
2471 | OS << " // Factory methods\n"; |
2472 | |
2473 | |
2474 | emitCreates(true); |
2475 | |
2476 | |
2477 | if (HasFakeArg) |
2478 | emitCreates(false); |
2479 | |
2480 | |
2481 | auto emitCtor = [&](bool emitOpt, bool emitFake) { |
2482 | auto shouldEmitArg = [=](const std::unique_ptr<Argument> &arg) { |
2483 | if (arg->isFake()) return emitFake; |
2484 | if (arg->isOptional()) return emitOpt; |
2485 | return true; |
2486 | }; |
2487 | if (Header) |
2488 | OS << " "; |
2489 | else |
2490 | OS << R.getName() << "Attr::"; |
2491 | OS << R.getName() |
2492 | << "Attr(ASTContext &Ctx, const AttributeCommonInfo &CommonInfo"; |
2493 | OS << '\n'; |
2494 | for (auto const &ai : Args) { |
2495 | if (!shouldEmitArg(ai)) continue; |
2496 | OS << " , "; |
2497 | ai->writeCtorParameters(OS); |
2498 | OS << "\n"; |
2499 | } |
2500 | |
2501 | OS << " )"; |
2502 | if (Header) { |
2503 | OS << ";\n"; |
2504 | return; |
2505 | } |
2506 | OS << "\n : " << SuperName << "(Ctx, CommonInfo, "; |
2507 | OS << "attr::" << R.getName() << ", " |
2508 | << (R.getValueAsBit("LateParsed") ? "true" : "false"); |
2509 | if (Inheritable) { |
2510 | OS << ", " |
2511 | << (R.getValueAsBit("InheritEvenIfAlreadyPresent") ? "true" |
2512 | : "false"); |
2513 | } |
2514 | OS << ")\n"; |
2515 | |
2516 | for (auto const &ai : Args) { |
2517 | OS << " , "; |
2518 | if (!shouldEmitArg(ai)) { |
2519 | ai->writeCtorDefaultInitializers(OS); |
2520 | } else { |
2521 | ai->writeCtorInitializers(OS); |
2522 | } |
2523 | OS << "\n"; |
2524 | } |
2525 | |
2526 | OS << " {\n"; |
2527 | |
2528 | for (auto const &ai : Args) { |
2529 | if (!shouldEmitArg(ai)) continue; |
2530 | ai->writeCtorBody(OS); |
2531 | } |
2532 | OS << "}\n\n"; |
2533 | }; |
2534 | |
2535 | if (Header) |
2536 | OS << "\n // Constructors\n"; |
2537 | |
2538 | |
2539 | |
2540 | emitCtor(true, true); |
2541 | |
2542 | |
2543 | if (HasFakeArg) |
2544 | emitCtor(true, false); |
2545 | |
2546 | |
2547 | if (HasOptArg) |
2548 | emitCtor(false, false); |
2549 | |
2550 | if (Header) { |
2551 | OS << '\n'; |
2552 | OS << " " << R.getName() << "Attr *clone(ASTContext &C) const;\n"; |
2553 | OS << " void printPretty(raw_ostream &OS,\n" |
2554 | << " const PrintingPolicy &Policy) const;\n"; |
2555 | OS << " const char *getSpelling() const;\n"; |
2556 | } |
2557 | |
2558 | if (!ElideSpelling) { |
2559 | assert(!SemanticToSyntacticMap.empty() && "Empty semantic mapping list"); |
2560 | if (Header) |
2561 | OS << " Spelling getSemanticSpelling() const;\n"; |
2562 | else { |
2563 | OS << R.getName() << "Attr::Spelling " << R.getName() |
2564 | << "Attr::getSemanticSpelling() const {\n"; |
2565 | WriteSemanticSpellingSwitch("getAttributeSpellingListIndex()", |
2566 | SemanticToSyntacticMap, OS); |
2567 | OS << "}\n"; |
2568 | } |
2569 | } |
2570 | |
2571 | if (Header) |
2572 | writeAttrAccessorDefinition(R, OS); |
2573 | |
2574 | for (auto const &ai : Args) { |
2575 | if (Header) { |
2576 | ai->writeAccessors(OS); |
2577 | } else { |
2578 | ai->writeAccessorDefinitions(OS); |
2579 | } |
2580 | OS << "\n\n"; |
2581 | |
2582 | |
2583 | if (ai->isFake()) continue; |
2584 | |
2585 | if (ai->isEnumArg()) |
2586 | static_cast<const EnumArgument *>(ai.get())->writeConversion(OS, |
2587 | Header); |
2588 | else if (ai->isVariadicEnumArg()) |
2589 | static_cast<const VariadicEnumArgument *>(ai.get())->writeConversion( |
2590 | OS, Header); |
2591 | } |
2592 | |
2593 | if (Header) { |
2594 | OS << R.getValueAsString("AdditionalMembers"); |
2595 | OS << "\n\n"; |
2596 | |
2597 | OS << " static bool classof(const Attr *A) { return A->getKind() == " |
2598 | << "attr::" << R.getName() << "; }\n"; |
2599 | |
2600 | OS << "};\n\n"; |
2601 | } else { |
2602 | OS << R.getName() << "Attr *" << R.getName() |
2603 | << "Attr::clone(ASTContext &C) const {\n"; |
2604 | OS << " auto *A = new (C) " << R.getName() << "Attr(C, *this"; |
2605 | for (auto const &ai : Args) { |
2606 | OS << ", "; |
2607 | ai->writeCloneArgs(OS); |
2608 | } |
2609 | OS << ");\n"; |
2610 | OS << " A->Inherited = Inherited;\n"; |
2611 | OS << " A->IsPackExpansion = IsPackExpansion;\n"; |
2612 | OS << " A->setImplicit(Implicit);\n"; |
2613 | OS << " return A;\n}\n\n"; |
2614 | |
2615 | writePrettyPrintFunction(R, Args, OS); |
2616 | writeGetSpellingFunction(R, OS); |
2617 | } |
2618 | } |
2619 | } |
2620 | |
2621 | void clang::EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) { |
2622 | emitSourceFileHeader("Attribute classes' definitions", OS); |
2623 | |
2624 | OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n"; |
2625 | OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n"; |
2626 | |
2627 | emitAttributes(Records, OS, true); |
2628 | |
2629 | OS << "#endif // LLVM_CLANG_ATTR_CLASSES_INC\n"; |
2630 | } |
2631 | |
2632 | |
2633 | void clang::EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) { |
2634 | emitSourceFileHeader("Attribute classes' member function definitions", OS); |
2635 | |
2636 | emitAttributes(Records, OS, false); |
2637 | |
2638 | std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"); |
2639 | |
2640 | |
2641 | |
2642 | auto EmitFunc = [&](const char *Method) { |
2643 | OS << " switch (getKind()) {\n"; |
2644 | for (const auto *Attr : Attrs) { |
2645 | const Record &R = *Attr; |
2646 | if (!R.getValueAsBit("ASTNode")) |
2647 | continue; |
2648 | |
2649 | OS << " case attr::" << R.getName() << ":\n"; |
2650 | OS << " return cast<" << R.getName() << "Attr>(this)->" << Method |
2651 | << ";\n"; |
2652 | } |
2653 | OS << " }\n"; |
2654 | OS << " llvm_unreachable(\"Unexpected attribute kind!\");\n"; |
2655 | OS << "}\n\n"; |
2656 | }; |
2657 | |
2658 | OS << "const char *Attr::getSpelling() const {\n"; |
2659 | EmitFunc("getSpelling()"); |
2660 | |
2661 | OS << "Attr *Attr::clone(ASTContext &C) const {\n"; |
2662 | EmitFunc("clone(C)"); |
2663 | |
2664 | OS << "void Attr::printPretty(raw_ostream &OS, " |
2665 | "const PrintingPolicy &Policy) const {\n"; |
2666 | EmitFunc("printPretty(OS, Policy)"); |
2667 | } |
2668 | |
2669 | static void emitAttrList(raw_ostream &OS, StringRef Class, |
2670 | const std::vector<Record*> &AttrList) { |
2671 | for (auto Cur : AttrList) { |
2672 | OS << Class << "(" << Cur->getName() << ")\n"; |
2673 | } |
2674 | } |
2675 | |
2676 | |
2677 | static bool AttrHasPragmaSpelling(const Record *R) { |
2678 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*R); |
2679 | return llvm::find_if(Spellings, [](const FlattenedSpelling &S) { |
2680 | return S.variety() == "Pragma"; |
2681 | }) != Spellings.end(); |
2682 | } |
2683 | |
2684 | namespace { |
2685 | |
2686 | struct AttrClassDescriptor { |
2687 | const char * const MacroName; |
2688 | const char * const TableGenName; |
2689 | }; |
2690 | |
2691 | } |
2692 | |
2693 | static const AttrClassDescriptor AttrClassDescriptors[] = { |
2694 | { "ATTR", "Attr" }, |
2695 | { "TYPE_ATTR", "TypeAttr" }, |
2696 | { "STMT_ATTR", "StmtAttr" }, |
2697 | { "DECL_OR_STMT_ATTR", "DeclOrStmtAttr" }, |
2698 | { "INHERITABLE_ATTR", "InheritableAttr" }, |
2699 | { "DECL_OR_TYPE_ATTR", "DeclOrTypeAttr" }, |
2700 | { "INHERITABLE_PARAM_ATTR", "InheritableParamAttr" }, |
2701 | { "PARAMETER_ABI_ATTR", "ParameterABIAttr" } |
2702 | }; |
2703 | |
2704 | static void emitDefaultDefine(raw_ostream &OS, StringRef name, |
2705 | const char *superName) { |
2706 | OS << "#ifndef " << name << "\n"; |
2707 | OS << "#define " << name << "(NAME) "; |
2708 | if (superName) OS << superName << "(NAME)"; |
2709 | OS << "\n#endif\n\n"; |
2710 | } |
2711 | |
2712 | namespace { |
2713 | |
2714 | |
2715 | struct AttrClass { |
2716 | const AttrClassDescriptor &Descriptor; |
2717 | Record *TheRecord; |
2718 | AttrClass *SuperClass = nullptr; |
2719 | std::vector<AttrClass*> SubClasses; |
2720 | std::vector<Record*> Attrs; |
2721 | |
2722 | AttrClass(const AttrClassDescriptor &Descriptor, Record *R) |
2723 | : Descriptor(Descriptor), TheRecord(R) {} |
2724 | |
2725 | void emitDefaultDefines(raw_ostream &OS) const { |
2726 | |
2727 | if (SuperClass) { |
2728 | emitDefaultDefine(OS, Descriptor.MacroName, |
2729 | SuperClass->Descriptor.MacroName); |
2730 | } |
2731 | } |
2732 | |
2733 | void emitUndefs(raw_ostream &OS) const { |
2734 | OS << "#undef " << Descriptor.MacroName << "\n"; |
2735 | } |
2736 | |
2737 | void emitAttrList(raw_ostream &OS) const { |
2738 | for (auto SubClass : SubClasses) { |
2739 | SubClass->emitAttrList(OS); |
2740 | } |
2741 | |
2742 | ::emitAttrList(OS, Descriptor.MacroName, Attrs); |
2743 | } |
2744 | |
2745 | void classifyAttrOnRoot(Record *Attr) { |
2746 | bool result = classifyAttr(Attr); |
2747 | assert(result && "failed to classify on root"); (void) result; |
2748 | } |
2749 | |
2750 | void emitAttrRange(raw_ostream &OS) const { |
2751 | OS << "ATTR_RANGE(" << Descriptor.TableGenName |
2752 | << ", " << getFirstAttr()->getName() |
2753 | << ", " << getLastAttr()->getName() << ")\n"; |
2754 | } |
2755 | |
2756 | private: |
2757 | bool classifyAttr(Record *Attr) { |
2758 | |
2759 | for (auto SubClass : SubClasses) { |
2760 | if (SubClass->classifyAttr(Attr)) |
2761 | return true; |
2762 | } |
2763 | |
2764 | |
2765 | if (Attr->isSubClassOf(TheRecord)) { |
2766 | Attrs.push_back(Attr); |
2767 | return true; |
2768 | } |
2769 | |
2770 | return false; |
2771 | } |
2772 | |
2773 | Record *getFirstAttr() const { |
2774 | if (!SubClasses.empty()) |
2775 | return SubClasses.front()->getFirstAttr(); |
2776 | return Attrs.front(); |
2777 | } |
2778 | |
2779 | Record *getLastAttr() const { |
2780 | if (!Attrs.empty()) |
2781 | return Attrs.back(); |
2782 | return SubClasses.back()->getLastAttr(); |
2783 | } |
2784 | }; |
2785 | |
2786 | |
2787 | class AttrClassHierarchy { |
2788 | std::vector<std::unique_ptr<AttrClass>> Classes; |
2789 | |
2790 | public: |
2791 | AttrClassHierarchy(RecordKeeper &Records) { |
2792 | |
2793 | for (auto &Descriptor : AttrClassDescriptors) { |
2794 | Record *ClassRecord = Records.getClass(Descriptor.TableGenName); |
2795 | AttrClass *Class = new AttrClass(Descriptor, ClassRecord); |
2796 | Classes.emplace_back(Class); |
2797 | } |
2798 | |
2799 | |
2800 | for (auto &Class : Classes) { |
2801 | if (AttrClass *SuperClass = findSuperClass(Class->TheRecord)) { |
2802 | Class->SuperClass = SuperClass; |
2803 | SuperClass->SubClasses.push_back(Class.get()); |
2804 | } |
2805 | } |
2806 | |
2807 | #ifndef NDEBUG |
2808 | for (auto i = Classes.begin(), e = Classes.end(); i != e; ++i) { |
2809 | assert((i == Classes.begin()) == ((*i)->SuperClass == nullptr) && |
2810 | "only the first class should be a root class!"); |
2811 | } |
2812 | #endif |
2813 | } |
2814 | |
2815 | void emitDefaultDefines(raw_ostream &OS) const { |
2816 | for (auto &Class : Classes) { |
2817 | Class->emitDefaultDefines(OS); |
2818 | } |
2819 | } |
2820 | |
2821 | void emitUndefs(raw_ostream &OS) const { |
2822 | for (auto &Class : Classes) { |
2823 | Class->emitUndefs(OS); |
2824 | } |
2825 | } |
2826 | |
2827 | void emitAttrLists(raw_ostream &OS) const { |
2828 | |
2829 | Classes[0]->emitAttrList(OS); |
2830 | } |
2831 | |
2832 | void emitAttrRanges(raw_ostream &OS) const { |
2833 | for (auto &Class : Classes) |
2834 | Class->emitAttrRange(OS); |
2835 | } |
2836 | |
2837 | void classifyAttr(Record *Attr) { |
2838 | |
2839 | Classes[0]->classifyAttrOnRoot(Attr); |
2840 | } |
2841 | |
2842 | private: |
2843 | AttrClass *findClassByRecord(Record *R) const { |
2844 | for (auto &Class : Classes) { |
2845 | if (Class->TheRecord == R) |
2846 | return Class.get(); |
2847 | } |
2848 | return nullptr; |
2849 | } |
2850 | |
2851 | AttrClass *findSuperClass(Record *R) const { |
2852 | |
2853 | |
2854 | auto SuperClasses = R->getSuperClasses(); |
2855 | for (signed i = 0, e = SuperClasses.size(); i != e; ++i) { |
2856 | auto SuperClass = findClassByRecord(SuperClasses[e - i - 1].first); |
2857 | if (SuperClass) return SuperClass; |
2858 | } |
2859 | return nullptr; |
2860 | } |
2861 | }; |
2862 | |
2863 | } |
2864 | |
2865 | namespace clang { |
2866 | |
2867 | |
2868 | void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) { |
2869 | emitSourceFileHeader("List of all attributes that Clang recognizes", OS); |
2870 | |
2871 | AttrClassHierarchy Hierarchy(Records); |
2872 | |
2873 | |
2874 | Hierarchy.emitDefaultDefines(OS); |
2875 | emitDefaultDefine(OS, "PRAGMA_SPELLING_ATTR", nullptr); |
2876 | |
2877 | std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"); |
2878 | std::vector<Record *> PragmaAttrs; |
2879 | for (auto *Attr : Attrs) { |
2880 | if (!Attr->getValueAsBit("ASTNode")) |
2881 | continue; |
2882 | |
2883 | |
2884 | if (AttrHasPragmaSpelling(Attr)) |
2885 | PragmaAttrs.push_back(Attr); |
2886 | |
2887 | |
2888 | Hierarchy.classifyAttr(Attr); |
2889 | } |
2890 | |
2891 | |
2892 | Hierarchy.emitAttrLists(OS); |
2893 | |
2894 | |
2895 | emitAttrList(OS, "PRAGMA_SPELLING_ATTR", PragmaAttrs); |
2896 | |
2897 | |
2898 | OS << "#ifdef ATTR_RANGE\n"; |
2899 | Hierarchy.emitAttrRanges(OS); |
2900 | OS << "#undef ATTR_RANGE\n"; |
2901 | OS << "#endif\n"; |
2902 | |
2903 | Hierarchy.emitUndefs(OS); |
2904 | OS << "#undef PRAGMA_SPELLING_ATTR\n"; |
2905 | } |
2906 | |
2907 | |
2908 | void EmitClangAttrSubjectMatchRuleList(RecordKeeper &Records, raw_ostream &OS) { |
2909 | emitSourceFileHeader( |
2910 | "List of all attribute subject matching rules that Clang recognizes", OS); |
2911 | PragmaClangAttributeSupport &PragmaAttributeSupport = |
2912 | getPragmaAttributeSupport(Records); |
2913 | emitDefaultDefine(OS, "ATTR_MATCH_RULE", nullptr); |
2914 | PragmaAttributeSupport.emitMatchRuleList(OS); |
2915 | OS << "#undef ATTR_MATCH_RULE\n"; |
2916 | } |
2917 | |
2918 | |
2919 | void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) { |
2920 | emitSourceFileHeader("Attribute deserialization code", OS); |
2921 | |
2922 | Record *InhClass = Records.getClass("InheritableAttr"); |
2923 | std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), |
2924 | ArgRecords; |
2925 | std::vector<std::unique_ptr<Argument>> Args; |
2926 | |
2927 | OS << " switch (Kind) {\n"; |
2928 | for (const auto *Attr : Attrs) { |
2929 | const Record &R = *Attr; |
2930 | if (!R.getValueAsBit("ASTNode")) |
2931 | continue; |
2932 | |
2933 | OS << " case attr::" << R.getName() << ": {\n"; |
2934 | if (R.isSubClassOf(InhClass)) |
2935 | OS << " bool isInherited = Record.readInt();\n"; |
2936 | OS << " bool isImplicit = Record.readInt();\n"; |
2937 | OS << " bool isPackExpansion = Record.readInt();\n"; |
2938 | ArgRecords = R.getValueAsListOfDefs("Args"); |
2939 | Args.clear(); |
2940 | for (const auto *Arg : ArgRecords) { |
2941 | Args.emplace_back(createArgument(*Arg, R.getName())); |
2942 | Args.back()->writePCHReadDecls(OS); |
2943 | } |
2944 | OS << " New = new (Context) " << R.getName() << "Attr(Context, Info"; |
2945 | for (auto const &ri : Args) { |
2946 | OS << ", "; |
2947 | ri->writePCHReadArgs(OS); |
2948 | } |
2949 | OS << ");\n"; |
2950 | if (R.isSubClassOf(InhClass)) |
2951 | OS << " cast<InheritableAttr>(New)->setInherited(isInherited);\n"; |
2952 | OS << " New->setImplicit(isImplicit);\n"; |
2953 | OS << " New->setPackExpansion(isPackExpansion);\n"; |
2954 | OS << " break;\n"; |
2955 | OS << " }\n"; |
2956 | } |
2957 | OS << " }\n"; |
2958 | } |
2959 | |
2960 | |
2961 | void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) { |
2962 | emitSourceFileHeader("Attribute serialization code", OS); |
2963 | |
2964 | Record *InhClass = Records.getClass("InheritableAttr"); |
2965 | std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args; |
2966 | |
2967 | OS << " switch (A->getKind()) {\n"; |
2968 | for (const auto *Attr : Attrs) { |
2969 | const Record &R = *Attr; |
2970 | if (!R.getValueAsBit("ASTNode")) |
2971 | continue; |
2972 | OS << " case attr::" << R.getName() << ": {\n"; |
2973 | Args = R.getValueAsListOfDefs("Args"); |
2974 | if (R.isSubClassOf(InhClass) || !Args.empty()) |
2975 | OS << " const auto *SA = cast<" << R.getName() |
2976 | << "Attr>(A);\n"; |
2977 | if (R.isSubClassOf(InhClass)) |
2978 | OS << " Record.push_back(SA->isInherited());\n"; |
2979 | OS << " Record.push_back(A->isImplicit());\n"; |
2980 | OS << " Record.push_back(A->isPackExpansion());\n"; |
2981 | |
2982 | for (const auto *Arg : Args) |
2983 | createArgument(*Arg, R.getName())->writePCHWrite(OS); |
2984 | OS << " break;\n"; |
2985 | OS << " }\n"; |
2986 | } |
2987 | OS << " }\n"; |
2988 | } |
2989 | |
2990 | |
2991 | |
2992 | static bool GenerateTargetSpecificAttrCheck(const Record *R, std::string &Test, |
2993 | std::string *FnName, |
2994 | StringRef ListName, |
2995 | StringRef CheckAgainst, |
2996 | StringRef Scope) { |
2997 | if (!R->isValueUnset(ListName)) { |
2998 | Test += " && ("; |
2999 | std::vector<StringRef> Items = R->getValueAsListOfStrings(ListName); |
3000 | for (auto I = Items.begin(), E = Items.end(); I != E; ++I) { |
3001 | StringRef Part = *I; |
3002 | Test += CheckAgainst; |
3003 | Test += " == "; |
3004 | Test += Scope; |
3005 | Test += Part; |
3006 | if (I + 1 != E) |
3007 | Test += " || "; |
3008 | if (FnName) |
3009 | *FnName += Part; |
3010 | } |
3011 | Test += ")"; |
3012 | return true; |
3013 | } |
3014 | return false; |
3015 | } |
3016 | |
3017 | |
3018 | |
3019 | |
3020 | |
3021 | |
3022 | static bool GenerateTargetSpecificAttrChecks(const Record *R, |
3023 | std::vector<StringRef> &Arches, |
3024 | std::string &Test, |
3025 | std::string *FnName) { |
3026 | bool AnyTargetChecks = false; |
3027 | |
3028 | |
3029 | |
3030 | |
3031 | |
3032 | Test += "true"; |
3033 | |
3034 | |
3035 | |
3036 | if (!Arches.empty()) { |
3037 | AnyTargetChecks = true; |
3038 | Test += " && ("; |
3039 | for (auto I = Arches.begin(), E = Arches.end(); I != E; ++I) { |
3040 | StringRef Part = *I; |
3041 | Test += "T.getArch() == llvm::Triple::"; |
3042 | Test += Part; |
3043 | if (I + 1 != E) |
3044 | Test += " || "; |
3045 | if (FnName) |
3046 | *FnName += Part; |
3047 | } |
3048 | Test += ")"; |
3049 | } |
3050 | |
3051 | |
3052 | AnyTargetChecks |= GenerateTargetSpecificAttrCheck( |
3053 | R, Test, FnName, "OSes", "T.getOS()", "llvm::Triple::"); |
3054 | |
3055 | |
3056 | AnyTargetChecks |= |
3057 | GenerateTargetSpecificAttrCheck(R, Test, FnName, "ObjectFormats", |
3058 | "T.getObjectFormat()", "llvm::Triple::"); |
3059 | |
3060 | |
3061 | StringRef Code = R->getValueAsString("CustomCode"); |
3062 | if (!Code.empty()) { |
3063 | AnyTargetChecks = true; |
3064 | Test += " && ("; |
3065 | Test += Code; |
3066 | Test += ")"; |
3067 | } |
3068 | |
3069 | return AnyTargetChecks; |
3070 | } |
3071 | |
3072 | static void GenerateHasAttrSpellingStringSwitch( |
3073 | const std::vector<Record *> &Attrs, raw_ostream &OS, |
3074 | const std::string &Variety = "", const std::string &Scope = "") { |
3075 | for (const auto *Attr : Attrs) { |
3076 | |
3077 | |
3078 | |
3079 | |
3080 | |
3081 | |
3082 | |
3083 | |
3084 | |
3085 | |
3086 | int Version = 1; |
3087 | |
3088 | if (Variety == "CXX11" || Variety == "C2x") { |
3089 | std::vector<Record *> Spellings = Attr->getValueAsListOfDefs("Spellings"); |
3090 | for (const auto &Spelling : Spellings) { |
3091 | if (Spelling->getValueAsString("Variety") == Variety) { |
3092 | Version = static_cast<int>(Spelling->getValueAsInt("Version")); |
3093 | if (Scope.empty() && Version == 1) |
3094 | PrintError(Spelling->getLoc(), "Standard attributes must have " |
3095 | "valid version information."); |
3096 | break; |
3097 | } |
3098 | } |
3099 | } |
3100 | |
3101 | std::string Test; |
3102 | if (Attr->isSubClassOf("TargetSpecificAttr")) { |
3103 | const Record *R = Attr->getValueAsDef("Target"); |
3104 | std::vector<StringRef> Arches = R->getValueAsListOfStrings("Arches"); |
3105 | GenerateTargetSpecificAttrChecks(R, Arches, Test, nullptr); |
3106 | |
3107 | |
3108 | if (Variety == "CXX11") |
3109 | Test += " && LangOpts.CPlusPlus11"; |
3110 | else if (Variety == "C2x") |
3111 | Test += " && LangOpts.DoubleSquareBracketAttributes"; |
3112 | } else if (Variety == "CXX11") |
3113 | |
3114 | |
3115 | Test = "LangOpts.CPlusPlus11"; |
3116 | else if (Variety == "C2x") |
3117 | Test = "LangOpts.DoubleSquareBracketAttributes"; |
3118 | |
3119 | std::string TestStr = |
3120 | !Test.empty() ? Test + " ? " + llvm::itostr(Version) + " : 0" : "1"; |
3121 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr); |
3122 | for (const auto &S : Spellings) |
3123 | if (Variety.empty() || (Variety == S.variety() && |
3124 | (Scope.empty() || Scope == S.nameSpace()))) |
3125 | OS << " .Case(\"" << S.name() << "\", " << TestStr << ")\n"; |
3126 | } |
3127 | OS << " .Default(0);\n"; |
3128 | } |
3129 | |
3130 | |
3131 | void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) { |
3132 | emitSourceFileHeader("Code to implement the __has_attribute logic", OS); |
3133 | |
3134 | |
3135 | |
3136 | std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"); |
3137 | std::vector<Record *> Declspec, Microsoft, GNU, Pragma; |
3138 | std::map<std::string, std::vector<Record *>> CXX, C2x; |
3139 | |
3140 | |
3141 | |
3142 | for (auto *R : Attrs) { |
3143 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*R); |
3144 | for (const auto &SI : Spellings) { |
3145 | const std::string &Variety = SI.variety(); |
3146 | if (Variety == "GNU") |
3147 | GNU.push_back(R); |
3148 | else if (Variety == "Declspec") |
3149 | Declspec.push_back(R); |
3150 | else if (Variety == "Microsoft") |
3151 | Microsoft.push_back(R); |
3152 | else if (Variety == "CXX11") |
3153 | CXX[SI.nameSpace()].push_back(R); |
3154 | else if (Variety == "C2x") |
3155 | C2x[SI.nameSpace()].push_back(R); |
3156 | else if (Variety == "Pragma") |
3157 | Pragma.push_back(R); |
3158 | } |
3159 | } |
3160 | |
3161 | OS << "const llvm::Triple &T = Target.getTriple();\n"; |
3162 | OS << "switch (Syntax) {\n"; |
3163 | OS << "case AttrSyntax::GNU:\n"; |
3164 | OS << " return llvm::StringSwitch<int>(Name)\n"; |
3165 | GenerateHasAttrSpellingStringSwitch(GNU, OS, "GNU"); |
3166 | OS << "case AttrSyntax::Declspec:\n"; |
3167 | OS << " return llvm::StringSwitch<int>(Name)\n"; |
3168 | GenerateHasAttrSpellingStringSwitch(Declspec, OS, "Declspec"); |
3169 | OS << "case AttrSyntax::Microsoft:\n"; |
3170 | OS << " return llvm::StringSwitch<int>(Name)\n"; |
3171 | GenerateHasAttrSpellingStringSwitch(Microsoft, OS, "Microsoft"); |
3172 | OS << "case AttrSyntax::Pragma:\n"; |
3173 | OS << " return llvm::StringSwitch<int>(Name)\n"; |
3174 | GenerateHasAttrSpellingStringSwitch(Pragma, OS, "Pragma"); |
3175 | auto fn = [&OS](const char *Spelling, const char *Variety, |
3176 | const std::map<std::string, std::vector<Record *>> &List) { |
3177 | OS << "case AttrSyntax::" << Variety << ": {\n"; |
3178 | |
3179 | for (auto I = List.cbegin(), E = List.cend(); I != E; ++I) { |
3180 | if (I != List.cbegin()) |
3181 | OS << " else "; |
3182 | if (I->first.empty()) |
3183 | OS << "if (ScopeName == \"\") {\n"; |
3184 | else |
3185 | OS << "if (ScopeName == \"" << I->first << "\") {\n"; |
3186 | OS << " return llvm::StringSwitch<int>(Name)\n"; |
3187 | GenerateHasAttrSpellingStringSwitch(I->second, OS, Spelling, I->first); |
3188 | OS << "}"; |
3189 | } |
3190 | OS << "\n} break;\n"; |
3191 | }; |
3192 | fn("CXX11", "CXX", CXX); |
3193 | fn("C2x", "C", C2x); |
3194 | OS << "}\n"; |
3195 | } |
3196 | |
3197 | void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) { |
3198 | emitSourceFileHeader("Code to translate different attribute spellings " |
3199 | "into internal identifiers", OS); |
3200 | |
3201 | OS << " switch (getParsedKind()) {\n"; |
3202 | OS << " case IgnoredAttribute:\n"; |
3203 | OS << " case UnknownAttribute:\n"; |
3204 | OS << " case NoSemaHandlerAttribute:\n"; |
3205 | OS << " llvm_unreachable(\"Ignored/unknown shouldn't get here\");\n"; |
3206 | |
3207 | ParsedAttrMap Attrs = getParsedAttrList(Records); |
3208 | for (const auto &I : Attrs) { |
3209 | const Record &R = *I.second; |
3210 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R); |
3211 | OS << " case AT_" << I.first << ": {\n"; |
3212 | for (unsigned I = 0; I < Spellings.size(); ++ I) { |
3213 | OS << " if (Name == \"" << Spellings[I].name() << "\" && " |
3214 | << "getSyntax() == AttributeCommonInfo::AS_" << Spellings[I].variety() |
3215 | << " && Scope == \"" << Spellings[I].nameSpace() << "\")\n" |
3216 | << " return " << I << ";\n"; |
3217 | } |
3218 | |
3219 | OS << " break;\n"; |
3220 | OS << " }\n"; |
3221 | } |
3222 | |
3223 | OS << " }\n"; |
3224 | OS << " return 0;\n"; |
3225 | } |
3226 | |
3227 | |
3228 | void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS) { |
3229 | emitSourceFileHeader("Used by RecursiveASTVisitor to visit attributes.", OS); |
3230 | |
3231 | std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); |
3232 | |
3233 | |
3234 | |
3235 | |
3236 | OS << "#ifdef ATTR_VISITOR_DECLS_ONLY\n\n"; |
3237 | for (const auto *Attr : Attrs) { |
3238 | const Record &R = *Attr; |
3239 | if (!R.getValueAsBit("ASTNode")) |
3240 | continue; |
3241 | OS << " bool Traverse" |
3242 | << R.getName() << "Attr(" << R.getName() << "Attr *A);\n"; |
3243 | OS << " bool Visit" |
3244 | << R.getName() << "Attr(" << R.getName() << "Attr *A) {\n" |
3245 | << " return true; \n" |
3246 | << " }\n"; |
3247 | } |
3248 | OS << "\n#else // ATTR_VISITOR_DECLS_ONLY\n\n"; |
3249 | |
3250 | |
3251 | for (const auto *Attr : Attrs) { |
3252 | const Record &R = *Attr; |
3253 | if (!R.getValueAsBit("ASTNode")) |
3254 | continue; |
3255 | |
3256 | OS << "template <typename Derived>\n" |
3257 | << "bool VISITORCLASS<Derived>::Traverse" |
3258 | << R.getName() << "Attr(" << R.getName() << "Attr *A) {\n" |
3259 | << " if (!getDerived().VisitAttr(A))\n" |
3260 | << " return false;\n" |
3261 | << " if (!getDerived().Visit" << R.getName() << "Attr(A))\n" |
3262 | << " return false;\n"; |
3263 | |
3264 | std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args"); |
3265 | for (const auto *Arg : ArgRecords) |
3266 | createArgument(*Arg, R.getName())->writeASTVisitorTraversal(OS); |
3267 | |
3268 | OS << " return true;\n"; |
3269 | OS << "}\n\n"; |
3270 | } |
3271 | |
3272 | |
3273 | OS << "template <typename Derived>\n" |
3274 | << "bool VISITORCLASS<Derived>::TraverseAttr(Attr *A) {\n" |
3275 | << " if (!A)\n" |
3276 | << " return true;\n" |
3277 | << "\n" |
3278 | << " switch (A->getKind()) {\n"; |
3279 | |
3280 | for (const auto *Attr : Attrs) { |
3281 | const Record &R = *Attr; |
3282 | if (!R.getValueAsBit("ASTNode")) |
3283 | continue; |
3284 | |
3285 | OS << " case attr::" << R.getName() << ":\n" |
3286 | << " return getDerived().Traverse" << R.getName() << "Attr(" |
3287 | << "cast<" << R.getName() << "Attr>(A));\n"; |
3288 | } |
3289 | OS << " }\n"; |
3290 | OS << " llvm_unreachable(\"bad attribute kind\");\n"; |
3291 | OS << "}\n"; |
3292 | OS << "#endif // ATTR_VISITOR_DECLS_ONLY\n"; |
3293 | } |
3294 | |
3295 | void EmitClangAttrTemplateInstantiateHelper(const std::vector<Record *> &Attrs, |
3296 | raw_ostream &OS, |
3297 | bool AppliesToDecl) { |
3298 | |
3299 | OS << " switch (At->getKind()) {\n"; |
3300 | for (const auto *Attr : Attrs) { |
3301 | const Record &R = *Attr; |
3302 | if (!R.getValueAsBit("ASTNode")) |
3303 | continue; |
3304 | OS << " case attr::" << R.getName() << ": {\n"; |
3305 | bool ShouldClone = R.getValueAsBit("Clone") && |
3306 | (!AppliesToDecl || |
3307 | R.getValueAsBit("MeaningfulToClassTemplateDefinition")); |
3308 | |
3309 | if (!ShouldClone) { |
3310 | OS << " return nullptr;\n"; |
3311 | OS << " }\n"; |
3312 | continue; |
3313 | } |
3314 | |
3315 | OS << " const auto *A = cast<" |
3316 | << R.getName() << "Attr>(At);\n"; |
3317 | bool TDependent = R.getValueAsBit("TemplateDependent"); |
3318 | |
3319 | if (!TDependent) { |
3320 | OS << " return A->clone(C);\n"; |
3321 | OS << " }\n"; |
3322 | continue; |
3323 | } |
3324 | |
3325 | std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args"); |
3326 | std::vector<std::unique_ptr<Argument>> Args; |
3327 | Args.reserve(ArgRecords.size()); |
3328 | |
3329 | for (const auto *ArgRecord : ArgRecords) |
3330 | Args.emplace_back(createArgument(*ArgRecord, R.getName())); |
3331 | |
3332 | for (auto const &ai : Args) |
3333 | ai->writeTemplateInstantiation(OS); |
3334 | |
3335 | OS << " return new (C) " << R.getName() << "Attr(C, *A"; |
3336 | for (auto const &ai : Args) { |
3337 | OS << ", "; |
3338 | ai->writeTemplateInstantiationArgs(OS); |
3339 | } |
3340 | OS << ");\n" |
3341 | << " }\n"; |
3342 | } |
3343 | OS << " } // end switch\n" |
3344 | << " llvm_unreachable(\"Unknown attribute!\");\n" |
3345 | << " return nullptr;\n"; |
3346 | } |
3347 | |
3348 | |
3349 | void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) { |
3350 | emitSourceFileHeader("Template instantiation code for attributes", OS); |
3351 | |
3352 | std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); |
3353 | |
3354 | OS << "namespace clang {\n" |
3355 | << "namespace sema {\n\n" |
3356 | << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, " |
3357 | << "Sema &S,\n" |
3358 | << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n"; |
3359 | EmitClangAttrTemplateInstantiateHelper(Attrs, OS, false); |
3360 | OS << "}\n\n" |
3361 | << "Attr *instantiateTemplateAttributeForDecl(const Attr *At,\n" |
3362 | << " ASTContext &C, Sema &S,\n" |
3363 | << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n"; |
3364 | EmitClangAttrTemplateInstantiateHelper(Attrs, OS, true); |
3365 | OS << "}\n\n" |
3366 | << "} // end namespace sema\n" |
3367 | << "} // end namespace clang\n"; |
3368 | } |
3369 | |
3370 | |
3371 | void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) { |
3372 | emitSourceFileHeader("List of all attributes that Clang recognizes", OS); |
3373 | |
3374 | OS << "#ifndef PARSED_ATTR\n"; |
3375 | OS << "#define PARSED_ATTR(NAME) NAME\n"; |
3376 | OS << "#endif\n\n"; |
3377 | |
3378 | ParsedAttrMap Names = getParsedAttrList(Records); |
3379 | for (const auto &I : Names) { |
3380 | OS << "PARSED_ATTR(" << I.first << ")\n"; |
3381 | } |
3382 | } |
3383 | |
3384 | static bool isArgVariadic(const Record &R, StringRef AttrName) { |
3385 | return createArgument(R, AttrName)->isVariadic(); |
3386 | } |
3387 | |
3388 | static void emitArgInfo(const Record &R, raw_ostream &OS) { |
3389 | |
3390 | |
3391 | |
3392 | std::vector<Record *> Args = R.getValueAsListOfDefs("Args"); |
3393 | unsigned ArgCount = 0, OptCount = 0; |
3394 | bool HasVariadic = false; |
3395 | for (const auto *Arg : Args) { |
3396 | |
3397 | |
3398 | if (Arg->getValueAsBit("Fake")) |
3399 | continue; |
3400 | Arg->getValueAsBit("Optional") ? ++OptCount : ++ArgCount; |
3401 | if (!HasVariadic && isArgVariadic(*Arg, R.getName())) |
3402 | HasVariadic = true; |
3403 | } |
3404 | |
3405 | |
3406 | |
3407 | OS << " NumArgs = " << ArgCount << ";\n"; |
3408 | OS << " OptArgs = " << (HasVariadic ? 15 : OptCount) << ";\n"; |
3409 | } |
3410 | |
3411 | static std::string GetDiagnosticSpelling(const Record &R) { |
3412 | std::string Ret = std::string(R.getValueAsString("DiagSpelling")); |
3413 | if (!Ret.empty()) |
3414 | return Ret; |
3415 | |
3416 | |
3417 | |
3418 | |
3419 | if (auto Base = R.getValueAsOptionalDef(BaseFieldName)) |
3420 | return GetDiagnosticSpelling(*Base); |
3421 | |
3422 | return ""; |
3423 | } |
3424 | |
3425 | static std::string CalculateDiagnostic(const Record &S) { |
3426 | |
3427 | |
3428 | const StringRef CustomDiag = S.getValueAsString("CustomDiag"); |
3429 | if (!CustomDiag.empty()) |
3430 | return ("\"" + Twine(CustomDiag) + "\"").str(); |
3431 | |
3432 | std::vector<std::string> DiagList; |
3433 | std::vector<Record *> Subjects = S.getValueAsListOfDefs("Subjects"); |
3434 | for (const auto *Subject : Subjects) { |
3435 | const Record &R = *Subject; |
3436 | |
3437 | std::string V = GetDiagnosticSpelling(R); |
3438 | if (V.empty()) { |
3439 | PrintError(R.getLoc(), |
3440 | "Could not determine diagnostic spelling for the node: " + |
3441 | R.getName() + "; please add one to DeclNodes.td"); |
3442 | } else { |
3443 | |
3444 | |
3445 | SmallVector<StringRef, 2> Frags; |
3446 | llvm::SplitString(V, Frags, ","); |
3447 | for (auto Str : Frags) { |
3448 | DiagList.push_back(std::string(Str.trim())); |
3449 | } |
3450 | } |
3451 | } |
3452 | |
3453 | if (DiagList.empty()) { |
3454 | PrintFatalError(S.getLoc(), |
3455 | "Could not deduce diagnostic argument for Attr subjects"); |
3456 | return ""; |
3457 | } |
3458 | |
3459 | |
3460 | |
3461 | |
3462 | |
3463 | |
3464 | if (DiagList.size() == 1) |
3465 | return '"' + DiagList.front() + '"'; |
3466 | |
3467 | if (DiagList.size() == 2) |
3468 | return '"' + DiagList[0] + " and " + DiagList[1] + '"'; |
3469 | |
3470 | |
3471 | |
3472 | |
3473 | |
3474 | std::string Diag = llvm::join(DiagList.begin(), DiagList.end() - 1, ", "); |
3475 | return '"' + Diag + ", and " + *(DiagList.end() - 1) + '"'; |
3476 | } |
3477 | |
3478 | static std::string GetSubjectWithSuffix(const Record *R) { |
3479 | const std::string &B = std::string(R->getName()); |
3480 | if (B == "DeclBase") |
3481 | return "Decl"; |
3482 | return B + "Decl"; |
3483 | } |
3484 | |
3485 | static std::string functionNameForCustomAppertainsTo(const Record &Subject) { |
3486 | return "is" + Subject.getName().str(); |
3487 | } |
3488 | |
3489 | static void GenerateCustomAppertainsTo(const Record &Subject, raw_ostream &OS) { |
3490 | std::string FnName = functionNameForCustomAppertainsTo(Subject); |
3491 | |
3492 | |
3493 | static std::set<std::string> CustomSubjectSet; |
3494 | auto I = CustomSubjectSet.find(FnName); |
3495 | if (I != CustomSubjectSet.end()) |
3496 | return; |
3497 | |
3498 | |
3499 | Record *Base = Subject.getValueAsDef(BaseFieldName); |
3500 | |
3501 | |
3502 | if (Base->isSubClassOf("SubsetSubject")) { |
3503 | PrintFatalError(Subject.getLoc(), |
3504 | "SubsetSubjects within SubsetSubjects is not supported"); |
3505 | return; |
3506 | } |
3507 | |
3508 | OS << "static bool " << FnName << "(const Decl *D) {\n"; |
3509 | OS << " if (const auto *S = dyn_cast<"; |
3510 | OS << GetSubjectWithSuffix(Base); |
3511 | OS << ">(D))\n"; |
3512 | OS << " return " << Subject.getValueAsString("CheckCode") << ";\n"; |
3513 | OS << " return false;\n"; |
3514 | OS << "}\n\n"; |
3515 | |
3516 | CustomSubjectSet.insert(FnName); |
3517 | } |
3518 | |
3519 | static void GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) { |
3520 | |
3521 | |
3522 | if (Attr.isValueUnset("Subjects")) |
3523 | return; |
3524 | |
3525 | const Record *SubjectObj = Attr.getValueAsDef("Subjects"); |
3526 | std::vector<Record *> Subjects = SubjectObj->getValueAsListOfDefs("Subjects"); |
3527 | |
3528 | |
3529 | |
3530 | if (Subjects.empty()) |
3531 | return; |
3532 | |
3533 | bool Warn = SubjectObj->getValueAsDef("Diag")->getValueAsBit("Warn"); |
3534 | |
3535 | |
3536 | |
3537 | |
3538 | |
3539 | std::vector<Record *> DeclSubjects, StmtSubjects; |
3540 | llvm::copy_if( |
3541 | Subjects, std::back_inserter(DeclSubjects), [](const Record *R) { |
3542 | return R->isSubClassOf("SubsetSubject") || !R->isSubClassOf("StmtNode"); |
3543 | }); |
3544 | llvm::copy_if(Subjects, std::back_inserter(StmtSubjects), |
3545 | [](const Record *R) { return R->isSubClassOf("StmtNode"); }); |
3546 | |
3547 | |
3548 | |
3549 | assert(DeclSubjects.size() + StmtSubjects.size() == Subjects.size()); |
3550 | |
3551 | if (DeclSubjects.empty()) { |
3552 | |
3553 | |
3554 | if (!StmtSubjects.empty()) { |
3555 | OS << "bool diagAppertainsToDecl(Sema &S, const ParsedAttr &AL, "; |
3556 | OS << "const Decl *D) const override {\n"; |
3557 | OS << " S.Diag(AL.getLoc(), diag::err_stmt_attribute_invalid_on_decl)\n"; |
3558 | OS << " << AL << D->getLocation();\n"; |
3559 | OS << " return false;\n"; |
3560 | OS << "}\n\n"; |
3561 | } |
3562 | } else { |
3563 | |
3564 | |
3565 | OS << "bool diagAppertainsToDecl(Sema &S, "; |
3566 | OS << "const ParsedAttr &Attr, const Decl *D) const override {\n"; |
3567 | OS << " if ("; |
3568 | for (auto I = DeclSubjects.begin(), E = DeclSubjects.end(); I != E; ++I) { |
3569 | |
3570 | |
3571 | |
3572 | |
3573 | |
3574 | if ((*I)->isSubClassOf("SubsetSubject")) |
3575 | OS << "!" << functionNameForCustomAppertainsTo(**I) << "(D)"; |
3576 | else |
3577 | OS << "!isa<" << GetSubjectWithSuffix(*I) << ">(D)"; |
3578 | |
3579 | if (I + 1 != E) |
3580 | OS << " && "; |
3581 | } |
3582 | OS << ") {\n"; |
3583 | OS << " S.Diag(Attr.getLoc(), diag::"; |
3584 | OS << (Warn ? "warn_attribute_wrong_decl_type_str" |
3585 | : "err_attribute_wrong_decl_type_str"); |
3586 | OS << ")\n"; |
3587 | OS << " << Attr << "; |
3588 | OS << CalculateDiagnostic(*SubjectObj) << ";\n"; |
3589 | OS << " return false;\n"; |
3590 | OS << " }\n"; |
3591 | OS << " return true;\n"; |
3592 | OS << "}\n\n"; |
3593 | } |
3594 | |
3595 | if (StmtSubjects.empty()) { |
3596 | |
3597 | |
3598 | if (!DeclSubjects.empty()) { |
3599 | OS << "bool diagAppertainsToStmt(Sema &S, const ParsedAttr &AL, "; |
3600 | OS << "const Stmt *St) const override {\n"; |
3601 | OS << " S.Diag(AL.getLoc(), diag::err_decl_attribute_invalid_on_stmt)\n"; |
3602 | OS << " << AL << St->getBeginLoc();\n"; |
3603 | OS << " return false;\n"; |
3604 | OS << "}\n\n"; |
3605 | } |
3606 | } else { |
3607 | |
3608 | OS << "bool diagAppertainsToStmt(Sema &S, "; |
3609 | OS << "const ParsedAttr &Attr, const Stmt *St) const override {\n"; |
3610 | OS << " if ("; |
3611 | for (auto I = StmtSubjects.begin(), E = StmtSubjects.end(); I != E; ++I) { |
3612 | OS << "!isa<" << (*I)->getName() << ">(St)"; |
3613 | if (I + 1 != E) |
3614 | OS << " && "; |
3615 | } |
3616 | OS << ") {\n"; |
3617 | OS << " S.Diag(Attr.getLoc(), diag::"; |
3618 | OS << (Warn ? "warn_attribute_wrong_decl_type_str" |
3619 | : "err_attribute_wrong_decl_type_str"); |
3620 | OS << ")\n"; |
3621 | OS << " << Attr << "; |
3622 | OS << CalculateDiagnostic(*SubjectObj) << ";\n"; |
3623 | OS << " return false;\n"; |
3624 | OS << " }\n"; |
3625 | OS << " return true;\n"; |
3626 | OS << "}\n\n"; |
3627 | } |
3628 | } |
3629 | |
3630 | |
3631 | |
3632 | |
3633 | static void GenerateMutualExclusionsChecks(const Record &Attr, |
3634 | const RecordKeeper &Records, |
3635 | raw_ostream &OS, |
3636 | raw_ostream &MergeDeclOS, |
3637 | raw_ostream &MergeStmtOS) { |
3638 | |
3639 | |
3640 | |
3641 | std::vector<Record *> ExclusionsList = |
3642 | Records.getAllDerivedDefinitions("MutualExclusions"); |
3643 | |
3644 | |
3645 | if (Attr.isSubClassOf("TypeAttr")) |
3646 | return; |
3647 | |
3648 | |
3649 | |
3650 | bool CurAttrIsStmtAttr = |
3651 | Attr.isSubClassOf("StmtAttr") || Attr.isSubClassOf("DeclOrStmtAttr"); |
3652 | bool CurAttrIsDeclAttr = |
3653 | !CurAttrIsStmtAttr || Attr.isSubClassOf("DeclOrStmtAttr"); |
3654 | |
3655 | std::vector<std::string> DeclAttrs, StmtAttrs; |
3656 | |
3657 | for (const Record *Exclusion : ExclusionsList) { |
3658 | std::vector<Record *> MutuallyExclusiveAttrs = |
3659 | Exclusion->getValueAsListOfDefs("Exclusions"); |
3660 | auto IsCurAttr = [Attr](const Record *R) { |
3661 | return R->getName() == Attr.getName(); |
3662 | }; |
3663 | if (llvm::any_of(MutuallyExclusiveAttrs, IsCurAttr)) { |
3664 | |
3665 | |
3666 | for (const Record *AttrToExclude : MutuallyExclusiveAttrs) { |
3667 | if (IsCurAttr(AttrToExclude)) |
3668 | continue; |
3669 | |
3670 | if (CurAttrIsStmtAttr) |
3671 | StmtAttrs.push_back((AttrToExclude->getName() + "Attr").str()); |
3672 | if (CurAttrIsDeclAttr) |
3673 | DeclAttrs.push_back((AttrToExclude->getName() + "Attr").str()); |
3674 | } |
3675 | } |
3676 | } |
3677 | |
3678 | |
3679 | |
3680 | if (!DeclAttrs.empty() || !StmtAttrs.empty()) |
3681 | OS << " using ParsedAttrInfo::diagMutualExclusion;\n\n"; |
3682 | |
3683 | |
3684 | |
3685 | if (!DeclAttrs.empty()) { |
3686 | |
3687 | OS << " bool diagMutualExclusion(Sema &S, const ParsedAttr &AL, " |
3688 | << "const Decl *D) const override {\n"; |
3689 | for (const std::string &A : DeclAttrs) { |
3690 | OS << " if (const auto *A = D->getAttr<" << A << ">()) {\n"; |
3691 | OS << " S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)" |
3692 | << " << AL << A;\n"; |
3693 | OS << " S.Diag(A->getLocation(), diag::note_conflicting_attribute);"; |
3694 | OS << " \nreturn false;\n"; |
3695 | OS << " }\n"; |
3696 | } |
3697 | OS << " return true;\n"; |
3698 | OS << " }\n\n"; |
3699 | |
3700 | |
3701 | |
3702 | |
3703 | |
3704 | |
3705 | if (Attr.isSubClassOf("InheritableAttr")) { |
3706 | MergeDeclOS << " if (const auto *Second = dyn_cast<" |
3707 | << (Attr.getName() + "Attr").str() << ">(A)) {\n"; |
3708 | for (const std::string &A : DeclAttrs) { |
3709 | MergeDeclOS << " if (const auto *First = D->getAttr<" << A |
3710 | << ">()) {\n"; |
3711 | MergeDeclOS << " S.Diag(First->getLocation(), " |
3712 | << "diag::err_attributes_are_not_compatible) << First << " |
3713 | << "Second;\n"; |
3714 | MergeDeclOS << " S.Diag(Second->getLocation(), " |
3715 | << "diag::note_conflicting_attribute);\n"; |
3716 | MergeDeclOS << " return false;\n"; |
3717 | MergeDeclOS << " }\n"; |
3718 | } |
3719 | MergeDeclOS << " return true;\n"; |
3720 | MergeDeclOS << " }\n"; |
3721 | } |
3722 | } |
3723 | |
3724 | |
3725 | |
3726 | |
3727 | |
3728 | |
3729 | |
3730 | |
3731 | |
3732 | |
3733 | |
3734 | |
3735 | |
3736 | |
3737 | |
3738 | |
3739 | |
3740 | |
3741 | if (!StmtAttrs.empty()) { |
3742 | MergeStmtOS << " if (const auto *Second = dyn_cast<" |
3743 | << (Attr.getName() + "Attr").str() << ">(A)) {\n"; |
3744 | MergeStmtOS << " auto Iter = llvm::find_if(C, [](const Attr *Check) " |
3745 | << "{ return isa<"; |
3746 | interleave( |
3747 | StmtAttrs, [&](const std::string &Name) { MergeStmtOS << Name; }, |
3748 | [&] { MergeStmtOS << ", "; }); |
3749 | MergeStmtOS << ">(Check); });\n"; |
3750 | MergeStmtOS << " if (Iter != C.end()) {\n"; |
3751 | MergeStmtOS << " S.Diag((*Iter)->getLocation(), " |
3752 | << "diag::err_attributes_are_not_compatible) << *Iter << " |
3753 | << "Second;\n"; |
3754 | MergeStmtOS << " S.Diag(Second->getLocation(), " |
3755 | << "diag::note_conflicting_attribute);\n"; |
3756 | MergeStmtOS << " return false;\n"; |
3757 | MergeStmtOS << " }\n"; |
3758 | MergeStmtOS << " }\n"; |
3759 | } |
3760 | } |
3761 | |
3762 | static void |
3763 | emitAttributeMatchRules(PragmaClangAttributeSupport &PragmaAttributeSupport, |
3764 | raw_ostream &OS) { |
3765 | OS << "static bool checkAttributeMatchRuleAppliesTo(const Decl *D, " |
3766 | << AttributeSubjectMatchRule::EnumName << " rule) {\n"; |
3767 | OS << " switch (rule) {\n"; |
3768 | for (const auto &Rule : PragmaAttributeSupport.Rules) { |
3769 | if (Rule.isAbstractRule()) { |
3770 | OS << " case " << Rule.getEnumValue() << ":\n"; |
3771 | OS << " assert(false && \"Abstract matcher rule isn't allowed\");\n"; |
3772 | OS << " return false;\n"; |
3773 | continue; |
3774 | } |
3775 | std::vector<Record *> Subjects = Rule.getSubjects(); |
3776 | assert(!Subjects.empty() && "Missing subjects"); |
3777 | OS << " case " << Rule.getEnumValue() << ":\n"; |
3778 | OS << " return "; |
3779 | for (auto I = Subjects.begin(), E = Subjects.end(); I != E; ++I) { |
3780 | |
3781 | |
3782 | |
3783 | if ((*I)->isSubClassOf("SubsetSubject")) |
3784 | OS << functionNameForCustomAppertainsTo(**I) << "(D)"; |
3785 | else |
3786 | OS << "isa<" << GetSubjectWithSuffix(*I) << ">(D)"; |
3787 | |
3788 | if (I + 1 != E) |
3789 | OS << " || "; |
3790 | } |
3791 | OS << ";\n"; |
3792 | } |
3793 | OS << " }\n"; |
3794 | OS << " llvm_unreachable(\"Invalid match rule\");\nreturn false;\n"; |
3795 | OS << "}\n\n"; |
3796 | } |
3797 | |
3798 | static void GenerateLangOptRequirements(const Record &R, |
3799 | raw_ostream &OS) { |
3800 | |
3801 | |
3802 | std::vector<Record *> LangOpts = R.getValueAsListOfDefs("LangOpts"); |
3803 | if (LangOpts.empty()) |
3804 | return; |
3805 | |
3806 | OS << "bool diagLangOpts(Sema &S, const ParsedAttr &Attr) "; |
3807 | OS << "const override {\n"; |
3808 | OS << " auto &LangOpts = S.LangOpts;\n"; |
3809 | OS << " if (" << GenerateTestExpression(LangOpts) << ")\n"; |
3810 | OS << " return true;\n\n"; |
3811 | OS << " S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) "; |
3812 | OS << "<< Attr;\n"; |
3813 | OS << " return false;\n"; |
3814 | OS << "}\n\n"; |
3815 | } |
3816 | |
3817 | static void GenerateTargetRequirements(const Record &Attr, |
3818 | const ParsedAttrMap &Dupes, |
3819 | raw_ostream &OS) { |
3820 | |
3821 | |
3822 | if (!Attr.isSubClassOf("TargetSpecificAttr")) |
3823 | return; |
3824 | |
3825 | |
3826 | const Record *R = Attr.getValueAsDef("Target"); |
3827 | std::vector<StringRef> Arches = R->getValueAsListOfStrings("Arches"); |
3828 | |
3829 | |
3830 | |
3831 | |
3832 | |
3833 | |
3834 | |
3835 | if (!Attr.isValueUnset("ParseKind")) { |
3836 | const StringRef APK = Attr.getValueAsString("ParseKind"); |
3837 | for (const auto &I : Dupes) { |
3838 | if (I.first == APK) { |
3839 | std::vector<StringRef> DA = |
3840 | I.second->getValueAsDef("Target")->getValueAsListOfStrings( |
3841 | "Arches"); |
3842 | Arches.insert(Arches.end(), DA.begin(), DA.end()); |
3843 | } |
3844 | } |
3845 | } |
3846 | |
3847 | std::string FnName = "isTarget"; |
3848 | std::string Test; |
3849 | bool UsesT = GenerateTargetSpecificAttrChecks(R, Arches, Test, &FnName); |
3850 | |
3851 | OS << "bool existsInTarget(const TargetInfo &Target) const override {\n"; |
3852 | if (UsesT) |
3853 | OS << " const llvm::Triple &T = Target.getTriple(); (void)T;\n"; |
3854 | OS << " return " << Test << ";\n"; |
3855 | OS << "}\n\n"; |
3856 | } |
3857 | |
3858 | static void GenerateSpellingIndexToSemanticSpelling(const Record &Attr, |
3859 | raw_ostream &OS) { |
3860 | |
3861 | if (!Attr.getValueAsBit("ASTNode")) |
3862 | return; |
3863 | |
3864 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr); |
3865 | |
3866 | |
3867 | |
3868 | if (Spellings.size() <= 1 || SpellingNamesAreCommon(Spellings)) |
3869 | return; |
3870 | |
3871 | |
3872 | SemanticSpellingMap SemanticToSyntacticMap; |
3873 | std::string Enum = CreateSemanticSpellings(Spellings, SemanticToSyntacticMap); |
3874 | std::string Name = Attr.getName().str() + "AttrSpellingMap"; |
3875 | |
3876 | OS << "unsigned spellingIndexToSemanticSpelling("; |
3877 | OS << "const ParsedAttr &Attr) const override {\n"; |
3878 | OS << Enum; |
3879 | OS << " unsigned Idx = Attr.getAttributeSpellingListIndex();\n"; |
3880 | WriteSemanticSpellingSwitch("Idx", SemanticToSyntacticMap, OS); |
3881 | OS << "}\n\n"; |
3882 | } |
3883 | |
3884 | static void GenerateHandleDeclAttribute(const Record &Attr, raw_ostream &OS) { |
3885 | |
3886 | if (!Attr.getValueAsBit("SimpleHandler")) |
3887 | return; |
3888 | |
3889 | |
3890 | OS << "AttrHandling handleDeclAttribute(Sema &S, Decl *D,"; |
3891 | OS << "const ParsedAttr &Attr) const override {\n"; |
3892 | OS << " D->addAttr(::new (S.Context) " << Attr.getName(); |
3893 | OS << "Attr(S.Context, Attr));\n"; |
3894 | OS << " return AttributeApplied;\n"; |
3895 | OS << "}\n\n"; |
3896 | } |
3897 | |
3898 | static bool IsKnownToGCC(const Record &Attr) { |
3899 | |
3900 | |
3901 | return llvm::any_of( |
3902 | GetFlattenedSpellings(Attr), |
3903 | [](const FlattenedSpelling &S) { return S.knownToGCC(); }); |
3904 | } |
3905 | |
3906 | |
3907 | void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) { |
3908 | emitSourceFileHeader("Parsed attribute helpers", OS); |
3909 | |
3910 | OS << "#if !defined(WANT_DECL_MERGE_LOGIC) && " |
3911 | << "!defined(WANT_STMT_MERGE_LOGIC)\n"; |
3912 | PragmaClangAttributeSupport &PragmaAttributeSupport = |
3913 | getPragmaAttributeSupport(Records); |
3914 | |
3915 | |
3916 | |
3917 | ParsedAttrMap Dupes; |
3918 | ParsedAttrMap Attrs = getParsedAttrList(Records, &Dupes); |
3919 | |
3920 | |
3921 | |
3922 | for (auto I : Attrs) { |
3923 | const Record &Attr = *I.second; |
3924 | if (Attr.isValueUnset("Subjects")) |
3925 | continue; |
3926 | const Record *SubjectObj = Attr.getValueAsDef("Subjects"); |
3927 | for (auto Subject : SubjectObj->getValueAsListOfDefs("Subjects")) |
3928 | if (Subject->isSubClassOf("SubsetSubject")) |
3929 | GenerateCustomAppertainsTo(*Subject, OS); |
3930 | } |
3931 | |
3932 | |
3933 | |
3934 | |
3935 | std::string DeclMergeChecks, StmtMergeChecks; |
3936 | raw_string_ostream MergeDeclOS(DeclMergeChecks), MergeStmtOS(StmtMergeChecks); |
3937 | |
3938 | |
3939 | for (auto I = Attrs.begin(), E = Attrs.end(); I != E; ++I) { |
3940 | |
3941 | |
3942 | |
3943 | |
3944 | |
3945 | |
3946 | |
3947 | |
3948 | const std::string &AttrName = I->first; |
3949 | const Record &Attr = *I->second; |
3950 | auto Spellings = GetFlattenedSpellings(Attr); |
3951 | if (!Spellings.empty()) { |
3952 | OS << "static constexpr ParsedAttrInfo::Spelling " << I->first |
3953 | << "Spellings[] = {\n"; |
3954 | for (const auto &S : Spellings) { |
3955 | const std::string &RawSpelling = S.name(); |
3956 | std::string Spelling; |
3957 | if (!S.nameSpace().empty()) |
3958 | Spelling += S.nameSpace() + "::"; |
3959 | if (S.variety() == "GNU") |
3960 | Spelling += NormalizeGNUAttrSpelling(RawSpelling); |
3961 | else |
3962 | Spelling += RawSpelling; |
3963 | OS << " {AttributeCommonInfo::AS_" << S.variety(); |
3964 | OS << ", \"" << Spelling << "\"},\n"; |
3965 | } |
3966 | OS << "};\n"; |
3967 | } |
3968 | OS << "struct ParsedAttrInfo" << I->first |
3969 | << " final : public ParsedAttrInfo {\n"; |
3970 | OS << " ParsedAttrInfo" << I->first << "() {\n"; |
3971 | OS << " AttrKind = ParsedAttr::AT_" << AttrName << ";\n"; |
3972 | emitArgInfo(Attr, OS); |
3973 | OS << " HasCustomParsing = "; |
3974 | OS << Attr.getValueAsBit("HasCustomParsing") << ";\n"; |
3975 | OS << " IsTargetSpecific = "; |
3976 | OS << Attr.isSubClassOf("TargetSpecificAttr") << ";\n"; |
3977 | OS << " IsType = "; |
3978 | OS << (Attr.isSubClassOf("TypeAttr") || |
3979 | Attr.isSubClassOf("DeclOrTypeAttr")) << ";\n"; |
3980 | OS << " IsStmt = "; |
3981 | OS << (Attr.isSubClassOf("StmtAttr") || Attr.isSubClassOf("DeclOrStmtAttr")) |
3982 | << ";\n"; |
3983 | OS << " IsKnownToGCC = "; |
3984 | OS << IsKnownToGCC(Attr) << ";\n"; |
3985 | OS << " IsSupportedByPragmaAttribute = "; |
3986 | OS << PragmaAttributeSupport.isAttributedSupported(*I->second) << ";\n"; |
3987 | if (!Spellings.empty()) |
3988 | OS << " Spellings = " << I->first << "Spellings;\n"; |
3989 | OS << " }\n"; |
3990 | GenerateAppertainsTo(Attr, OS); |
3991 | GenerateMutualExclusionsChecks(Attr, Records, OS, MergeDeclOS, MergeStmtOS); |
3992 | GenerateLangOptRequirements(Attr, OS); |
3993 | GenerateTargetRequirements(Attr, Dupes, OS); |
3994 | GenerateSpellingIndexToSemanticSpelling(Attr, OS); |
3995 | PragmaAttributeSupport.generateStrictConformsTo(*I->second, OS); |
3996 | GenerateHandleDeclAttribute(Attr, OS); |
3997 | OS << "static const ParsedAttrInfo" << I->first << " Instance;\n"; |
3998 | OS << "};\n"; |
3999 | OS << "const ParsedAttrInfo" << I->first << " ParsedAttrInfo" << I->first |
4000 | << "::Instance;\n"; |
4001 | } |
4002 | |
4003 | OS << "static const ParsedAttrInfo *AttrInfoMap[] = {\n"; |
4004 | for (auto I = Attrs.begin(), E = Attrs.end(); I != E; ++I) { |
4005 | OS << "&ParsedAttrInfo" << I->first << "::Instance,\n"; |
4006 | } |
4007 | OS << "};\n\n"; |
4008 | |
4009 | |
4010 | emitAttributeMatchRules(PragmaAttributeSupport, OS); |
4011 | |
4012 | OS << "#elif defined(WANT_DECL_MERGE_LOGIC)\n\n"; |
4013 | |
4014 | |
4015 | OS << "static bool DiagnoseMutualExclusions(Sema &S, const NamedDecl *D, " |
4016 | << "const Attr *A) {\n"; |
4017 | OS << MergeDeclOS.str(); |
4018 | OS << " return true;\n"; |
4019 | OS << "}\n\n"; |
4020 | |
4021 | OS << "#elif defined(WANT_STMT_MERGE_LOGIC)\n\n"; |
4022 | |
4023 | |
4024 | OS << "static bool DiagnoseMutualExclusions(Sema &S, " |
4025 | << "const SmallVectorImpl<const Attr *> &C) {\n"; |
4026 | OS << " for (const Attr *A : C) {\n"; |
4027 | OS << MergeStmtOS.str(); |
4028 | OS << " }\n"; |
4029 | OS << " return true;\n"; |
4030 | OS << "}\n\n"; |
4031 | |
4032 | OS << "#endif\n"; |
4033 | } |
4034 | |
4035 | |
4036 | void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) { |
4037 | emitSourceFileHeader("Attribute name matcher", OS); |
4038 | |
4039 | std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"); |
4040 | std::vector<StringMatcher::StringPair> GNU, Declspec, Microsoft, CXX11, |
4041 | Keywords, Pragma, C2x; |
4042 | std::set<std::string> Seen; |
4043 | for (const auto *A : Attrs) { |
4044 | const Record &Attr = *A; |
4045 | |
4046 | bool SemaHandler = Attr.getValueAsBit("SemaHandler"); |
4047 | bool Ignored = Attr.getValueAsBit("Ignored"); |
4048 | if (SemaHandler || Ignored) { |
| 1 | Assuming 'SemaHandler' is false | |
|
| 2 | | Assuming 'Ignored' is true | |
|
| |
4049 | |
4050 | |
4051 | |
4052 | |
4053 | |
4054 | |
4055 | |
4056 | |
4057 | |
4058 | |
4059 | std::string AttrName; |
4060 | if (Attr.isSubClassOf("TargetSpecificAttr") && |
| |
4061 | !Attr.isValueUnset("ParseKind")) { |
4062 | AttrName = std::string(Attr.getValueAsString("ParseKind")); |
4063 | if (Seen.find(AttrName) != Seen.end()) |
4064 | continue; |
4065 | Seen.insert(AttrName); |
4066 | } else |
4067 | AttrName = NormalizeAttrName(StringRef(Attr.getName())).str(); |
4068 | |
4069 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr); |
4070 | for (const auto &S : Spellings) { |
4071 | const std::string &RawSpelling = S.name(); |
4072 | std::vector<StringMatcher::StringPair> *Matches = nullptr; |
| 5 | | 'Matches' initialized to a null pointer value | |
|
4073 | std::string Spelling; |
4074 | const std::string &Variety = S.variety(); |
4075 | if (Variety == "CXX11") { |
| |
4076 | Matches = &CXX11; |
4077 | if (!S.nameSpace().empty()) |
4078 | Spelling += S.nameSpace() + "::"; |
4079 | } else if (Variety == "C2x") { |
| |
4080 | Matches = &C2x; |
4081 | if (!S.nameSpace().empty()) |
4082 | Spelling += S.nameSpace() + "::"; |
4083 | } else if (Variety == "GNU") |
| |
4084 | Matches = &GNU; |
4085 | else if (Variety == "Declspec") |
| |
4086 | Matches = &Declspec; |
4087 | else if (Variety == "Microsoft") |
| |
4088 | Matches = &Microsoft; |
4089 | else if (Variety == "Keyword") |
| |
4090 | Matches = &Keywords; |
4091 | else if (Variety == "Pragma") |
| |
4092 | Matches = &Pragma; |
4093 | |
4094 | assert(Matches && "Unsupported spelling variety found"); |
4095 | |
4096 | if (Variety == "GNU") |
| |
4097 | Spelling += NormalizeGNUAttrSpelling(RawSpelling); |
4098 | else |
4099 | Spelling += RawSpelling; |
4100 | |
4101 | if (SemaHandler) |
| |
4102 | Matches->push_back(StringMatcher::StringPair( |
4103 | Spelling, "return AttributeCommonInfo::AT_" + AttrName + ";")); |
4104 | else |
4105 | Matches->push_back(StringMatcher::StringPair( |
| 15 | | Called C++ object pointer is null |
|
4106 | Spelling, "return AttributeCommonInfo::IgnoredAttribute;")); |
4107 | } |
4108 | } |
4109 | } |
4110 | |
4111 | OS << "static AttributeCommonInfo::Kind getAttrKind(StringRef Name, "; |
4112 | OS << "AttributeCommonInfo::Syntax Syntax) {\n"; |
4113 | OS << " if (AttributeCommonInfo::AS_GNU == Syntax) {\n"; |
4114 | StringMatcher("Name", GNU, OS).Emit(); |
4115 | OS << " } else if (AttributeCommonInfo::AS_Declspec == Syntax) {\n"; |
4116 | StringMatcher("Name", Declspec, OS).Emit(); |
4117 | OS << " } else if (AttributeCommonInfo::AS_Microsoft == Syntax) {\n"; |
4118 | StringMatcher("Name", Microsoft, OS).Emit(); |
4119 | OS << " } else if (AttributeCommonInfo::AS_CXX11 == Syntax) {\n"; |
4120 | StringMatcher("Name", CXX11, OS).Emit(); |
4121 | OS << " } else if (AttributeCommonInfo::AS_C2x == Syntax) {\n"; |
4122 | StringMatcher("Name", C2x, OS).Emit(); |
4123 | OS << " } else if (AttributeCommonInfo::AS_Keyword == Syntax || "; |
4124 | OS << "AttributeCommonInfo::AS_ContextSensitiveKeyword == Syntax) {\n"; |
4125 | StringMatcher("Name", Keywords, OS).Emit(); |
4126 | OS << " } else if (AttributeCommonInfo::AS_Pragma == Syntax) {\n"; |
4127 | StringMatcher("Name", Pragma, OS).Emit(); |
4128 | OS << " }\n"; |
4129 | OS << " return AttributeCommonInfo::UnknownAttribute;\n" |
4130 | << "}\n"; |
4131 | } |
4132 | |
4133 | |
4134 | void EmitClangAttrTextNodeDump(RecordKeeper &Records, raw_ostream &OS) { |
4135 | emitSourceFileHeader("Attribute text node dumper", OS); |
4136 | |
4137 | std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args; |
4138 | for (const auto *Attr : Attrs) { |
4139 | const Record &R = *Attr; |
4140 | if (!R.getValueAsBit("ASTNode")) |
4141 | continue; |
4142 | |
4143 | |
4144 | |
4145 | |
4146 | |
4147 | std::string FunctionContent; |
4148 | llvm::raw_string_ostream SS(FunctionContent); |
4149 | |
4150 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R); |
4151 | if (Spellings.size() > 1 && !SpellingNamesAreCommon(Spellings)) |
4152 | SS << " OS << \" \" << A->getSpelling();\n"; |
4153 | |
4154 | Args = R.getValueAsListOfDefs("Args"); |
4155 | for (const auto *Arg : Args) |
4156 | createArgument(*Arg, R.getName())->writeDump(SS); |
4157 | |
4158 | if (SS.tell()) { |
4159 | OS << " void Visit" << R.getName() << "Attr(const " << R.getName() |
4160 | << "Attr *A) {\n"; |
4161 | if (!Args.empty()) |
4162 | OS << " const auto *SA = cast<" << R.getName() |
4163 | << "Attr>(A); (void)SA;\n"; |
4164 | OS << SS.str(); |
4165 | OS << " }\n"; |
4166 | } |
4167 | } |
4168 | } |
4169 | |
4170 | void EmitClangAttrNodeTraverse(RecordKeeper &Records, raw_ostream &OS) { |
4171 | emitSourceFileHeader("Attribute text node traverser", OS); |
4172 | |
4173 | std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"), Args; |
4174 | for (const auto *Attr : Attrs) { |
4175 | const Record &R = *Attr; |
4176 | if (!R.getValueAsBit("ASTNode")) |
4177 | continue; |
4178 | |
4179 | std::string FunctionContent; |
4180 | llvm::raw_string_ostream SS(FunctionContent); |
4181 | |
4182 | Args = R.getValueAsListOfDefs("Args"); |
4183 | for (const auto *Arg : Args) |
4184 | createArgument(*Arg, R.getName())->writeDumpChildren(SS); |
4185 | if (SS.tell()) { |
4186 | OS << " void Visit" << R.getName() << "Attr(const " << R.getName() |
4187 | << "Attr *A) {\n"; |
4188 | if (!Args.empty()) |
4189 | OS << " const auto *SA = cast<" << R.getName() |
4190 | << "Attr>(A); (void)SA;\n"; |
4191 | OS << SS.str(); |
4192 | OS << " }\n"; |
4193 | } |
4194 | } |
4195 | } |
4196 | |
4197 | void EmitClangAttrParserStringSwitches(RecordKeeper &Records, |
4198 | raw_ostream &OS) { |
4199 | emitSourceFileHeader("Parser-related llvm::StringSwitch cases", OS); |
4200 | emitClangAttrArgContextList(Records, OS); |
4201 | emitClangAttrIdentifierArgList(Records, OS); |
4202 | emitClangAttrVariadicIdentifierArgList(Records, OS); |
4203 | emitClangAttrThisIsaIdentifierArgList(Records, OS); |
4204 | emitClangAttrTypeArgList(Records, OS); |
4205 | emitClangAttrLateParsedList(Records, OS); |
4206 | } |
4207 | |
4208 | void EmitClangAttrSubjectMatchRulesParserStringSwitches(RecordKeeper &Records, |
4209 | raw_ostream &OS) { |
4210 | getPragmaAttributeSupport(Records).generateParsingHelpers(OS); |
4211 | } |
4212 | |
4213 | enum class SpellingKind { |
4214 | GNU, |
4215 | CXX11, |
4216 | C2x, |
4217 | Declspec, |
4218 | Microsoft, |
4219 | Keyword, |
4220 | Pragma, |
4221 | }; |
4222 | static const size_t NumSpellingKinds = (size_t)SpellingKind::Pragma + 1; |
4223 | |
4224 | class SpellingList { |
4225 | std::vector<std::string> Spellings[NumSpellingKinds]; |
4226 | |
4227 | public: |
4228 | ArrayRef<std::string> operator[](SpellingKind K) const { |
4229 | return Spellings[(size_t)K]; |
4230 | } |
4231 | |
4232 | void add(const Record &Attr, FlattenedSpelling Spelling) { |
4233 | SpellingKind Kind = StringSwitch<SpellingKind>(Spelling.variety()) |
4234 | .Case("GNU", SpellingKind::GNU) |
4235 | .Case("CXX11", SpellingKind::CXX11) |
4236 | .Case("C2x", SpellingKind::C2x) |
4237 | .Case("Declspec", SpellingKind::Declspec) |
4238 | .Case("Microsoft", SpellingKind::Microsoft) |
4239 | .Case("Keyword", SpellingKind::Keyword) |
4240 | .Case("Pragma", SpellingKind::Pragma); |
4241 | std::string Name; |
4242 | if (!Spelling.nameSpace().empty()) { |
4243 | switch (Kind) { |
4244 | case SpellingKind::CXX11: |
4245 | case SpellingKind::C2x: |
4246 | Name = Spelling.nameSpace() + "::"; |
4247 | break; |
4248 | case SpellingKind::Pragma: |
4249 | Name = Spelling.nameSpace() + " "; |
4250 | break; |
4251 | default: |
4252 | PrintFatalError(Attr.getLoc(), "Unexpected namespace in spelling"); |
4253 | } |
4254 | } |
4255 | Name += Spelling.name(); |
4256 | |
4257 | Spellings[(size_t)Kind].push_back(Name); |
4258 | } |
4259 | }; |
4260 | |
4261 | class DocumentationData { |
4262 | public: |
4263 | const Record *Documentation; |
4264 | const Record *Attribute; |
4265 | std::string Heading; |
4266 | SpellingList SupportedSpellings; |
4267 | |
4268 | DocumentationData(const Record &Documentation, const Record &Attribute, |
4269 | std::pair<std::string, SpellingList> HeadingAndSpellings) |
4270 | : Documentation(&Documentation), Attribute(&Attribute), |
4271 | Heading(std::move(HeadingAndSpellings.first)), |
4272 | SupportedSpellings(std::move(HeadingAndSpellings.second)) {} |
4273 | }; |
4274 | |
4275 | static void WriteCategoryHeader(const Record *DocCategory, |
4276 | raw_ostream &OS) { |
4277 | const StringRef Name = DocCategory->getValueAsString("Name"); |
4278 | OS << Name << "\n" << std::string(Name.size(), '=') << "\n"; |
4279 | |
4280 | |
4281 | const StringRef ContentStr = DocCategory->getValueAsString("Content"); |
4282 | |
4283 | OS << ContentStr.trim(); |
4284 | |
4285 | OS << "\n\n"; |
4286 | } |
4287 | |
4288 | static std::pair<std::string, SpellingList> |
4289 | GetAttributeHeadingAndSpellings(const Record &Documentation, |
4290 | const Record &Attribute) { |
4291 | |
4292 | |
4293 | |
4294 | |
4295 | std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attribute); |
4296 | if (Spellings.empty()) |
4297 | PrintFatalError(Attribute.getLoc(), |
4298 | "Attribute has no supported spellings; cannot be " |
4299 | "documented"); |
4300 | |
4301 | |
4302 | std::string Heading = std::string(Documentation.getValueAsString("Heading")); |
4303 | if (Heading.empty()) { |
4304 | |
4305 | if (Spellings.size() == 1) |
4306 | Heading = Spellings.begin()->name(); |
4307 | else { |
4308 | std::set<std::string> Uniques; |
4309 | for (auto I = Spellings.begin(), E = Spellings.end(); |
4310 | I != E && Uniques.size() <= 1; ++I) { |
4311 | std::string Spelling = |
4312 | std::string(NormalizeNameForSpellingComparison(I->name())); |
4313 | Uniques.insert(Spelling); |
4314 | } |
4315 | |
4316 | |
4317 | if (Uniques.size() == 1) |
4318 | Heading = *Uniques.begin(); |
4319 | } |
4320 | } |
4321 | |
4322 | |
4323 | if (Heading.empty()) |
4324 | PrintFatalError(Attribute.getLoc(), |
4325 | "This attribute requires a heading to be specified"); |
4326 | |
4327 | SpellingList SupportedSpellings; |
4328 | for (const auto &I : Spellings) |
4329 | SupportedSpellings.add(Attribute, I); |
4330 | |
4331 | return std::make_pair(std::move(Heading), std::move(SupportedSpellings)); |
4332 | } |
4333 | |
4334 | static void WriteDocumentation(RecordKeeper &Records, |
4335 | const DocumentationData &Doc, raw_ostream &OS) { |
4336 | OS << Doc.Heading << "\n" << std::string(Doc.Heading.length(), '-') << "\n"; |
4337 | |
4338 | |
4339 | OS << ".. csv-table:: Supported Syntaxes\n"; |
4340 | OS << " :header: \"GNU\", \"C++11\", \"C2x\", \"``__declspec``\","; |
4341 | OS << " \"Keyword\", \"``#pragma``\", \"``#pragma clang attribute``\"\n\n"; |
4342 | OS << " \""; |
4343 | for (size_t Kind = 0; Kind != NumSpellingKinds; ++Kind) { |
4344 | SpellingKind K = (SpellingKind)Kind; |
4345 | |
4346 | |
4347 | if (K == SpellingKind::Microsoft) |
4348 | continue; |
4349 | |
4350 | bool PrintedAny = false; |
4351 | for (StringRef Spelling : Doc.SupportedSpellings[K]) { |
4352 | if (PrintedAny) |
4353 | OS << " |br| "; |
4354 | OS << "``" << Spelling << "``"; |
4355 | PrintedAny = true; |
4356 | } |
4357 | |
4358 | OS << "\",\""; |
4359 | } |
4360 | |
4361 | if (getPragmaAttributeSupport(Records).isAttributedSupported( |
4362 | *Doc.Attribute)) |
4363 | OS << "Yes"; |
4364 | OS << "\"\n\n"; |
4365 | |
4366 | |
4367 | |
4368 | if (!Doc.Documentation->isValueUnset("Deprecated")) { |
4369 | OS << "This attribute has been deprecated, and may be removed in a future " |
4370 | << "version of Clang."; |
4371 | const Record &Deprecated = *Doc.Documentation->getValueAsDef("Deprecated"); |
4372 | const StringRef Replacement = Deprecated.getValueAsString("Replacement"); |
4373 | if (!Replacement.empty()) |
4374 | OS << " This attribute has been superseded by ``" << Replacement |
4375 | << "``."; |
4376 | OS << "\n\n"; |
4377 | } |
4378 | |
4379 | const StringRef ContentStr = Doc.Documentation->getValueAsString("Content"); |
4380 | |
4381 | OS << ContentStr.trim(); |
4382 | |
4383 | OS << "\n\n\n"; |
4384 | } |
4385 | |
4386 | void EmitClangAttrDocs(RecordKeeper &Records, raw_ostream &OS) { |
4387 | |
4388 | const Record *Documentation = Records.getDef("GlobalDocumentation"); |
4389 | if (!Documentation) { |
4390 | PrintFatalError("The Documentation top-level definition is missing, " |
4391 | "no documentation will be generated."); |
4392 | return; |
4393 | } |
4394 | |
4395 | OS << Documentation->getValueAsString("Intro") << "\n"; |
4396 | |
4397 | |
4398 | |
4399 | std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"); |
4400 | std::map<const Record *, std::vector<DocumentationData>> SplitDocs; |
4401 | for (const auto *A : Attrs) { |
4402 | const Record &Attr = *A; |
4403 | std::vector<Record *> Docs = Attr.getValueAsListOfDefs("Documentation"); |
4404 | for (const auto *D : Docs) { |
4405 | const Record &Doc = *D; |
4406 | const Record *Category = Doc.getValueAsDef("Category"); |
4407 | |
4408 | |
4409 | |
4410 | const StringRef Cat = Category->getValueAsString("Name"); |
4411 | bool Undocumented = Cat == "Undocumented"; |
4412 | if (Undocumented && Docs.size() > 1) |
4413 | PrintFatalError(Doc.getLoc(), |
4414 | "Attribute is \"Undocumented\", but has multiple " |
4415 | "documentation categories"); |
4416 | |
4417 | if (!Undocumented) |
4418 | SplitDocs[Category].push_back(DocumentationData( |
4419 | Doc, Attr, GetAttributeHeadingAndSpellings(Doc, Attr))); |
4420 | } |
4421 | } |
4422 | |
4423 | |
4424 | |
4425 | for (auto &I : SplitDocs) { |
4426 | WriteCategoryHeader(I.first, OS); |
4427 | |
4428 | llvm::sort(I.second, |
4429 | [](const DocumentationData &D1, const DocumentationData &D2) { |
4430 | return D1.Heading < D2.Heading; |
4431 | }); |
4432 | |
4433 | |
4434 | |
4435 | for (const auto &Doc : I.second) |
4436 | WriteDocumentation(Records, Doc, OS); |
4437 | } |
4438 | } |
4439 | |
4440 | void EmitTestPragmaAttributeSupportedAttributes(RecordKeeper &Records, |
4441 | raw_ostream &OS) { |
4442 | PragmaClangAttributeSupport Support = getPragmaAttributeSupport(Records); |
4443 | ParsedAttrMap Attrs = getParsedAttrList(Records); |
4444 | OS << "#pragma clang attribute supports the following attributes:\n"; |
4445 | for (const auto &I : Attrs) { |
4446 | if (!Support.isAttributedSupported(*I.second)) |
4447 | continue; |
4448 | OS << I.first; |
4449 | if (I.second->isValueUnset("Subjects")) { |
4450 | OS << " ()\n"; |
4451 | continue; |
4452 | } |
4453 | const Record *SubjectObj = I.second->getValueAsDef("Subjects"); |
4454 | std::vector<Record *> Subjects = |
4455 | SubjectObj->getValueAsListOfDefs("Subjects"); |
4456 | OS << " ("; |
4457 | bool PrintComma = false; |
4458 | for (const auto &Subject : llvm::enumerate(Subjects)) { |
4459 | if (!isSupportedPragmaClangAttributeSubject(*Subject.value())) |
4460 | continue; |
4461 | if (PrintComma) |
4462 | OS << ", "; |
4463 | PrintComma = true; |
4464 | PragmaClangAttributeSupport::RuleOrAggregateRuleSet &RuleSet = |
4465 | Support.SubjectsToRules.find(Subject.value())->getSecond(); |
4466 | if (RuleSet.isRule()) { |
4467 | OS << RuleSet.getRule().getEnumValueName(); |
4468 | continue; |
4469 | } |
4470 | OS << "("; |
4471 | for (const auto &Rule : llvm::enumerate(RuleSet.getAggregateRuleSet())) { |
4472 | if (Rule.index()) |
4473 | OS << ", "; |
4474 | OS << Rule.value().getEnumValueName(); |
4475 | } |
4476 | OS << ")"; |
4477 | } |
4478 | OS << ")\n"; |
4479 | } |
4480 | OS << "End of supported attributes.\n"; |
4481 | } |
4482 | |
4483 | } |