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