brintos

brintos / llvm-project-archived public Read only

0
0
Text · 201.0 KiB · bee9a01 Raw
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