xref: /freebsd-src/contrib/llvm-project/clang/utils/TableGen/ClangAttrEmitter.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- ClangAttrEmitter.cpp - Generate Clang attribute handling =-*- C++ -*--=//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // These tablegen backends emit Clang attribute processing code
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
13a7dea167SDimitry Andric #include "TableGenBackends.h"
14480093f4SDimitry Andric #include "ASTTableGen.h"
15a7dea167SDimitry Andric 
160b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
170b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
180b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h"
19349cc55cSDimitry Andric #include "llvm/ADT/MapVector.h"
200b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
210b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
220b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
230b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
240b57cec5SDimitry Andric #include "llvm/ADT/StringSet.h"
250b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
260b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h"
270b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
280b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
290b57cec5SDimitry Andric #include "llvm/TableGen/Error.h"
300b57cec5SDimitry Andric #include "llvm/TableGen/Record.h"
310b57cec5SDimitry Andric #include "llvm/TableGen/StringMatcher.h"
320b57cec5SDimitry Andric #include "llvm/TableGen/TableGenBackend.h"
330b57cec5SDimitry Andric #include <algorithm>
340b57cec5SDimitry Andric #include <cassert>
350b57cec5SDimitry Andric #include <cctype>
360b57cec5SDimitry Andric #include <cstddef>
370b57cec5SDimitry Andric #include <cstdint>
380b57cec5SDimitry Andric #include <map>
390b57cec5SDimitry Andric #include <memory>
40bdd1243dSDimitry Andric #include <optional>
410b57cec5SDimitry Andric #include <set>
420b57cec5SDimitry Andric #include <sstream>
430b57cec5SDimitry Andric #include <string>
440b57cec5SDimitry Andric #include <utility>
450b57cec5SDimitry Andric #include <vector>
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric using namespace llvm;
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric namespace {
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric class FlattenedSpelling {
520b57cec5SDimitry Andric   std::string V, N, NS;
535ffd83dbSDimitry Andric   bool K = false;
5406c3fb27SDimitry Andric   const Record &OriginalSpelling;
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric public:
570b57cec5SDimitry Andric   FlattenedSpelling(const std::string &Variety, const std::string &Name,
5806c3fb27SDimitry Andric                     const std::string &Namespace, bool KnownToGCC,
5906c3fb27SDimitry Andric                     const Record &OriginalSpelling)
6006c3fb27SDimitry Andric       : V(Variety), N(Name), NS(Namespace), K(KnownToGCC),
6106c3fb27SDimitry Andric         OriginalSpelling(OriginalSpelling) {}
625ffd83dbSDimitry Andric   explicit FlattenedSpelling(const Record &Spelling)
635ffd83dbSDimitry Andric       : V(std::string(Spelling.getValueAsString("Variety"))),
6406c3fb27SDimitry Andric         N(std::string(Spelling.getValueAsString("Name"))),
6506c3fb27SDimitry Andric         OriginalSpelling(Spelling) {
660b57cec5SDimitry Andric     assert(V != "GCC" && V != "Clang" &&
670b57cec5SDimitry Andric            "Given a GCC spelling, which means this hasn't been flattened!");
685f757f3fSDimitry Andric     if (V == "CXX11" || V == "C23" || V == "Pragma")
695ffd83dbSDimitry Andric       NS = std::string(Spelling.getValueAsString("Namespace"));
700b57cec5SDimitry Andric   }
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric   const std::string &variety() const { return V; }
730b57cec5SDimitry Andric   const std::string &name() const { return N; }
740b57cec5SDimitry Andric   const std::string &nameSpace() const { return NS; }
750b57cec5SDimitry Andric   bool knownToGCC() const { return K; }
7606c3fb27SDimitry Andric   const Record &getSpellingRecord() const { return OriginalSpelling; }
770b57cec5SDimitry Andric };
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric } // end anonymous namespace
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric static std::vector<FlattenedSpelling>
820b57cec5SDimitry Andric GetFlattenedSpellings(const Record &Attr) {
830b57cec5SDimitry Andric   std::vector<Record *> Spellings = Attr.getValueAsListOfDefs("Spellings");
840b57cec5SDimitry Andric   std::vector<FlattenedSpelling> Ret;
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   for (const auto &Spelling : Spellings) {
870b57cec5SDimitry Andric     StringRef Variety = Spelling->getValueAsString("Variety");
880b57cec5SDimitry Andric     StringRef Name = Spelling->getValueAsString("Name");
890b57cec5SDimitry Andric     if (Variety == "GCC") {
9006c3fb27SDimitry Andric       Ret.emplace_back("GNU", std::string(Name), "", true, *Spelling);
9106c3fb27SDimitry Andric       Ret.emplace_back("CXX11", std::string(Name), "gnu", true, *Spelling);
920b57cec5SDimitry Andric       if (Spelling->getValueAsBit("AllowInC"))
935f757f3fSDimitry Andric         Ret.emplace_back("C23", std::string(Name), "gnu", true, *Spelling);
945ffd83dbSDimitry Andric     } else if (Variety == "Clang") {
9506c3fb27SDimitry Andric       Ret.emplace_back("GNU", std::string(Name), "", false, *Spelling);
9606c3fb27SDimitry Andric       Ret.emplace_back("CXX11", std::string(Name), "clang", false, *Spelling);
975ffd83dbSDimitry Andric       if (Spelling->getValueAsBit("AllowInC"))
985f757f3fSDimitry Andric         Ret.emplace_back("C23", std::string(Name), "clang", false, *Spelling);
990b57cec5SDimitry Andric     } else
1000b57cec5SDimitry Andric       Ret.push_back(FlattenedSpelling(*Spelling));
1010b57cec5SDimitry Andric   }
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric   return Ret;
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric static std::string ReadPCHRecord(StringRef type) {
1070b57cec5SDimitry Andric   return StringSwitch<std::string>(type)
108*0fca6ea1SDimitry Andric       .EndsWith("Decl *", "Record.readDeclAs<" +
1095ffd83dbSDimitry Andric                               std::string(type.data(), 0, type.size() - 1) +
110*0fca6ea1SDimitry Andric                               ">()")
111480093f4SDimitry Andric       .Case("TypeSourceInfo *", "Record.readTypeSourceInfo()")
1120b57cec5SDimitry Andric       .Case("Expr *", "Record.readExpr()")
113480093f4SDimitry Andric       .Case("IdentifierInfo *", "Record.readIdentifier()")
1140b57cec5SDimitry Andric       .Case("StringRef", "Record.readString()")
1150b57cec5SDimitry Andric       .Case("ParamIdx", "ParamIdx::deserialize(Record.readInt())")
1165ffd83dbSDimitry Andric       .Case("OMPTraitInfo *", "Record.readOMPTraitInfo()")
1170b57cec5SDimitry Andric       .Default("Record.readInt()");
1180b57cec5SDimitry Andric }
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric // Get a type that is suitable for storing an object of the specified type.
1210b57cec5SDimitry Andric static StringRef getStorageType(StringRef type) {
1220b57cec5SDimitry Andric   return StringSwitch<StringRef>(type)
1230b57cec5SDimitry Andric     .Case("StringRef", "std::string")
1240b57cec5SDimitry Andric     .Default(type);
1250b57cec5SDimitry Andric }
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric // Assumes that the way to get the value is SA->getname()
1280b57cec5SDimitry Andric static std::string WritePCHRecord(StringRef type, StringRef name) {
1295ffd83dbSDimitry Andric   return "Record." +
1305ffd83dbSDimitry Andric          StringSwitch<std::string>(type)
1310b57cec5SDimitry Andric              .EndsWith("Decl *", "AddDeclRef(" + std::string(name) + ");\n")
1325ffd83dbSDimitry Andric              .Case("TypeSourceInfo *",
1335ffd83dbSDimitry Andric                    "AddTypeSourceInfo(" + std::string(name) + ");\n")
1340b57cec5SDimitry Andric              .Case("Expr *", "AddStmt(" + std::string(name) + ");\n")
1355ffd83dbSDimitry Andric              .Case("IdentifierInfo *",
1365ffd83dbSDimitry Andric                    "AddIdentifierRef(" + std::string(name) + ");\n")
1370b57cec5SDimitry Andric              .Case("StringRef", "AddString(" + std::string(name) + ");\n")
1385ffd83dbSDimitry Andric              .Case("ParamIdx",
1395ffd83dbSDimitry Andric                    "push_back(" + std::string(name) + ".serialize());\n")
1405ffd83dbSDimitry Andric              .Case("OMPTraitInfo *",
1415ffd83dbSDimitry Andric                    "writeOMPTraitInfo(" + std::string(name) + ");\n")
1420b57cec5SDimitry Andric              .Default("push_back(" + std::string(name) + ");\n");
1430b57cec5SDimitry Andric }
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric // Normalize attribute name by removing leading and trailing
1460b57cec5SDimitry Andric // underscores. For example, __foo, foo__, __foo__ would
1470b57cec5SDimitry Andric // become foo.
1480b57cec5SDimitry Andric static StringRef NormalizeAttrName(StringRef AttrName) {
1490b57cec5SDimitry Andric   AttrName.consume_front("__");
1500b57cec5SDimitry Andric   AttrName.consume_back("__");
1510b57cec5SDimitry Andric   return AttrName;
1520b57cec5SDimitry Andric }
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric // Normalize the name by removing any and all leading and trailing underscores.
1550b57cec5SDimitry Andric // This is different from NormalizeAttrName in that it also handles names like
1560b57cec5SDimitry Andric // _pascal and __pascal.
1570b57cec5SDimitry Andric static StringRef NormalizeNameForSpellingComparison(StringRef Name) {
1580b57cec5SDimitry Andric   return Name.trim("_");
1590b57cec5SDimitry Andric }
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric // Normalize the spelling of a GNU attribute (i.e. "x" in "__attribute__((x))"),
1620b57cec5SDimitry Andric // removing "__" if it appears at the beginning and end of the attribute's name.
1630b57cec5SDimitry Andric static StringRef NormalizeGNUAttrSpelling(StringRef AttrSpelling) {
1645f757f3fSDimitry Andric   if (AttrSpelling.starts_with("__") && AttrSpelling.ends_with("__")) {
1650b57cec5SDimitry Andric     AttrSpelling = AttrSpelling.substr(2, AttrSpelling.size() - 4);
1660b57cec5SDimitry Andric   }
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   return AttrSpelling;
1690b57cec5SDimitry Andric }
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric typedef std::vector<std::pair<std::string, const Record *>> ParsedAttrMap;
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric static ParsedAttrMap getParsedAttrList(const RecordKeeper &Records,
174*0fca6ea1SDimitry Andric                                        ParsedAttrMap *Dupes = nullptr,
175*0fca6ea1SDimitry Andric                                        bool SemaOnly = true) {
1760b57cec5SDimitry Andric   std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
1770b57cec5SDimitry Andric   std::set<std::string> Seen;
1780b57cec5SDimitry Andric   ParsedAttrMap R;
1790b57cec5SDimitry Andric   for (const auto *Attr : Attrs) {
180*0fca6ea1SDimitry Andric     if (!SemaOnly || Attr->getValueAsBit("SemaHandler")) {
1810b57cec5SDimitry Andric       std::string AN;
1820b57cec5SDimitry Andric       if (Attr->isSubClassOf("TargetSpecificAttr") &&
1830b57cec5SDimitry Andric           !Attr->isValueUnset("ParseKind")) {
1845ffd83dbSDimitry Andric         AN = std::string(Attr->getValueAsString("ParseKind"));
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric         // If this attribute has already been handled, it does not need to be
1870b57cec5SDimitry Andric         // handled again.
1880b57cec5SDimitry Andric         if (Seen.find(AN) != Seen.end()) {
1890b57cec5SDimitry Andric           if (Dupes)
1900b57cec5SDimitry Andric             Dupes->push_back(std::make_pair(AN, Attr));
1910b57cec5SDimitry Andric           continue;
1920b57cec5SDimitry Andric         }
1930b57cec5SDimitry Andric         Seen.insert(AN);
1940b57cec5SDimitry Andric       } else
1950b57cec5SDimitry Andric         AN = NormalizeAttrName(Attr->getName()).str();
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric       R.push_back(std::make_pair(AN, Attr));
1980b57cec5SDimitry Andric     }
1990b57cec5SDimitry Andric   }
2000b57cec5SDimitry Andric   return R;
2010b57cec5SDimitry Andric }
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric namespace {
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric   class Argument {
2060b57cec5SDimitry Andric     std::string lowerName, upperName;
2070b57cec5SDimitry Andric     StringRef attrName;
2080b57cec5SDimitry Andric     bool isOpt;
2090b57cec5SDimitry Andric     bool Fake;
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric   public:
21281ad6265SDimitry Andric     Argument(StringRef Arg, StringRef Attr)
21381ad6265SDimitry Andric         : lowerName(std::string(Arg)), upperName(lowerName), attrName(Attr),
21481ad6265SDimitry Andric           isOpt(false), Fake(false) {
2150b57cec5SDimitry Andric       if (!lowerName.empty()) {
2160b57cec5SDimitry Andric         lowerName[0] = std::tolower(lowerName[0]);
2170b57cec5SDimitry Andric         upperName[0] = std::toupper(upperName[0]);
2180b57cec5SDimitry Andric       }
2190b57cec5SDimitry Andric       // Work around MinGW's macro definition of 'interface' to 'struct'. We
2200b57cec5SDimitry Andric       // have an attribute argument called 'Interface', so only the lower case
2210b57cec5SDimitry Andric       // name conflicts with the macro definition.
2220b57cec5SDimitry Andric       if (lowerName == "interface")
2230b57cec5SDimitry Andric         lowerName = "interface_";
2240b57cec5SDimitry Andric     }
22581ad6265SDimitry Andric     Argument(const Record &Arg, StringRef Attr)
22681ad6265SDimitry Andric         : Argument(Arg.getValueAsString("Name"), Attr) {}
2270b57cec5SDimitry Andric     virtual ~Argument() = default;
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric     StringRef getLowerName() const { return lowerName; }
2300b57cec5SDimitry Andric     StringRef getUpperName() const { return upperName; }
2310b57cec5SDimitry Andric     StringRef getAttrName() const { return attrName; }
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric     bool isOptional() const { return isOpt; }
2340b57cec5SDimitry Andric     void setOptional(bool set) { isOpt = set; }
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric     bool isFake() const { return Fake; }
2370b57cec5SDimitry Andric     void setFake(bool fake) { Fake = fake; }
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric     // These functions print the argument contents formatted in different ways.
2400b57cec5SDimitry Andric     virtual void writeAccessors(raw_ostream &OS) const = 0;
2410b57cec5SDimitry Andric     virtual void writeAccessorDefinitions(raw_ostream &OS) const {}
2420b57cec5SDimitry Andric     virtual void writeASTVisitorTraversal(raw_ostream &OS) const {}
2430b57cec5SDimitry Andric     virtual void writeCloneArgs(raw_ostream &OS) const = 0;
2440b57cec5SDimitry Andric     virtual void writeTemplateInstantiationArgs(raw_ostream &OS) const = 0;
2450b57cec5SDimitry Andric     virtual void writeTemplateInstantiation(raw_ostream &OS) const {}
2460b57cec5SDimitry Andric     virtual void writeCtorBody(raw_ostream &OS) const {}
2470b57cec5SDimitry Andric     virtual void writeCtorInitializers(raw_ostream &OS) const = 0;
2480b57cec5SDimitry Andric     virtual void writeCtorDefaultInitializers(raw_ostream &OS) const = 0;
2490b57cec5SDimitry Andric     virtual void writeCtorParameters(raw_ostream &OS) const = 0;
2500b57cec5SDimitry Andric     virtual void writeDeclarations(raw_ostream &OS) const = 0;
2510b57cec5SDimitry Andric     virtual void writePCHReadArgs(raw_ostream &OS) const = 0;
2520b57cec5SDimitry Andric     virtual void writePCHReadDecls(raw_ostream &OS) const = 0;
2530b57cec5SDimitry Andric     virtual void writePCHWrite(raw_ostream &OS) const = 0;
2540b57cec5SDimitry Andric     virtual std::string getIsOmitted() const { return "false"; }
2550b57cec5SDimitry Andric     virtual void writeValue(raw_ostream &OS) const = 0;
2560b57cec5SDimitry Andric     virtual void writeDump(raw_ostream &OS) const = 0;
2570b57cec5SDimitry Andric     virtual void writeDumpChildren(raw_ostream &OS) const {}
2580b57cec5SDimitry Andric     virtual void writeHasChildren(raw_ostream &OS) const { OS << "false"; }
2590b57cec5SDimitry Andric 
2600b57cec5SDimitry Andric     virtual bool isEnumArg() const { return false; }
2610b57cec5SDimitry Andric     virtual bool isVariadicEnumArg() const { return false; }
2620b57cec5SDimitry Andric     virtual bool isVariadic() const { return false; }
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric     virtual void writeImplicitCtorArgs(raw_ostream &OS) const {
2650b57cec5SDimitry Andric       OS << getUpperName();
2660b57cec5SDimitry Andric     }
2670b57cec5SDimitry Andric   };
2680b57cec5SDimitry Andric 
2690b57cec5SDimitry Andric   class SimpleArgument : public Argument {
2700b57cec5SDimitry Andric     std::string type;
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric   public:
2730b57cec5SDimitry Andric     SimpleArgument(const Record &Arg, StringRef Attr, std::string T)
2740b57cec5SDimitry Andric         : Argument(Arg, Attr), type(std::move(T)) {}
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric     std::string getType() const { return type; }
2770b57cec5SDimitry Andric 
2780b57cec5SDimitry Andric     void writeAccessors(raw_ostream &OS) const override {
2790b57cec5SDimitry Andric       OS << "  " << type << " get" << getUpperName() << "() const {\n";
2800b57cec5SDimitry Andric       OS << "    return " << getLowerName() << ";\n";
2810b57cec5SDimitry Andric       OS << "  }";
2820b57cec5SDimitry Andric     }
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric     void writeCloneArgs(raw_ostream &OS) const override {
2850b57cec5SDimitry Andric       OS << getLowerName();
2860b57cec5SDimitry Andric     }
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric     void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
2890b57cec5SDimitry Andric       OS << "A->get" << getUpperName() << "()";
2900b57cec5SDimitry Andric     }
2910b57cec5SDimitry Andric 
2920b57cec5SDimitry Andric     void writeCtorInitializers(raw_ostream &OS) const override {
2930b57cec5SDimitry Andric       OS << getLowerName() << "(" << getUpperName() << ")";
2940b57cec5SDimitry Andric     }
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric     void writeCtorDefaultInitializers(raw_ostream &OS) const override {
2970b57cec5SDimitry Andric       OS << getLowerName() << "()";
2980b57cec5SDimitry Andric     }
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric     void writeCtorParameters(raw_ostream &OS) const override {
3010b57cec5SDimitry Andric       OS << type << " " << getUpperName();
3020b57cec5SDimitry Andric     }
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric     void writeDeclarations(raw_ostream &OS) const override {
3050b57cec5SDimitry Andric       OS << type << " " << getLowerName() << ";";
3060b57cec5SDimitry Andric     }
3070b57cec5SDimitry Andric 
3080b57cec5SDimitry Andric     void writePCHReadDecls(raw_ostream &OS) const override {
3090b57cec5SDimitry Andric       std::string read = ReadPCHRecord(type);
3100b57cec5SDimitry Andric       OS << "    " << type << " " << getLowerName() << " = " << read << ";\n";
3110b57cec5SDimitry Andric     }
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric     void writePCHReadArgs(raw_ostream &OS) const override {
3140b57cec5SDimitry Andric       OS << getLowerName();
3150b57cec5SDimitry Andric     }
3160b57cec5SDimitry Andric 
3170b57cec5SDimitry Andric     void writePCHWrite(raw_ostream &OS) const override {
3185ffd83dbSDimitry Andric       OS << "    "
3195ffd83dbSDimitry Andric          << WritePCHRecord(type,
3205ffd83dbSDimitry Andric                            "SA->get" + std::string(getUpperName()) + "()");
3210b57cec5SDimitry Andric     }
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric     std::string getIsOmitted() const override {
3245f757f3fSDimitry Andric       auto IsOneOf = [](StringRef subject, auto... list) {
3255f757f3fSDimitry Andric         return ((subject == list) || ...);
3265f757f3fSDimitry Andric       };
3275f757f3fSDimitry Andric 
3285f757f3fSDimitry Andric       if (IsOneOf(type, "IdentifierInfo *", "Expr *"))
3290b57cec5SDimitry Andric         return "!get" + getUpperName().str() + "()";
3305f757f3fSDimitry Andric       if (IsOneOf(type, "TypeSourceInfo *"))
331a7dea167SDimitry Andric         return "!get" + getUpperName().str() + "Loc()";
3325f757f3fSDimitry Andric       if (IsOneOf(type, "ParamIdx"))
3330b57cec5SDimitry Andric         return "!get" + getUpperName().str() + "().isValid()";
3345f757f3fSDimitry Andric 
3355f757f3fSDimitry Andric       assert(IsOneOf(type, "unsigned", "int", "bool", "FunctionDecl *",
3365f757f3fSDimitry Andric                      "VarDecl *"));
3370b57cec5SDimitry Andric       return "false";
3380b57cec5SDimitry Andric     }
3390b57cec5SDimitry Andric 
3400b57cec5SDimitry Andric     void writeValue(raw_ostream &OS) const override {
3410b57cec5SDimitry Andric       if (type == "FunctionDecl *")
3420b57cec5SDimitry Andric         OS << "\" << get" << getUpperName()
3430b57cec5SDimitry Andric            << "()->getNameInfo().getAsString() << \"";
3440b57cec5SDimitry Andric       else if (type == "IdentifierInfo *")
3450b57cec5SDimitry Andric         // Some non-optional (comma required) identifier arguments can be the
3460b57cec5SDimitry Andric         // empty string but are then recorded as a nullptr.
3470b57cec5SDimitry Andric         OS << "\" << (get" << getUpperName() << "() ? get" << getUpperName()
3480b57cec5SDimitry Andric            << "()->getName() : \"\") << \"";
349e8d8bef9SDimitry Andric       else if (type == "VarDecl *")
350e8d8bef9SDimitry Andric         OS << "\" << get" << getUpperName() << "()->getName() << \"";
3510b57cec5SDimitry Andric       else if (type == "TypeSourceInfo *")
3520b57cec5SDimitry Andric         OS << "\" << get" << getUpperName() << "().getAsString() << \"";
3530b57cec5SDimitry Andric       else if (type == "ParamIdx")
3540b57cec5SDimitry Andric         OS << "\" << get" << getUpperName() << "().getSourceIndex() << \"";
3550b57cec5SDimitry Andric       else
3560b57cec5SDimitry Andric         OS << "\" << get" << getUpperName() << "() << \"";
3570b57cec5SDimitry Andric     }
3580b57cec5SDimitry Andric 
3590b57cec5SDimitry Andric     void writeDump(raw_ostream &OS) const override {
3605f757f3fSDimitry Andric       if (StringRef(type).ends_with("Decl *")) {
3610b57cec5SDimitry Andric         OS << "    OS << \" \";\n";
3620b57cec5SDimitry Andric         OS << "    dumpBareDeclRef(SA->get" << getUpperName() << "());\n";
3630b57cec5SDimitry Andric       } else if (type == "IdentifierInfo *") {
3640b57cec5SDimitry Andric         // Some non-optional (comma required) identifier arguments can be the
3650b57cec5SDimitry Andric         // empty string but are then recorded as a nullptr.
3660b57cec5SDimitry Andric         OS << "    if (SA->get" << getUpperName() << "())\n"
3670b57cec5SDimitry Andric            << "      OS << \" \" << SA->get" << getUpperName()
3680b57cec5SDimitry Andric            << "()->getName();\n";
3690b57cec5SDimitry Andric       } else if (type == "TypeSourceInfo *") {
370a7dea167SDimitry Andric         if (isOptional())
371a7dea167SDimitry Andric           OS << "    if (SA->get" << getUpperName() << "Loc())";
3720b57cec5SDimitry Andric         OS << "    OS << \" \" << SA->get" << getUpperName()
3730b57cec5SDimitry Andric            << "().getAsString();\n";
3740b57cec5SDimitry Andric       } else if (type == "bool") {
3750b57cec5SDimitry Andric         OS << "    if (SA->get" << getUpperName() << "()) OS << \" "
3760b57cec5SDimitry Andric            << getUpperName() << "\";\n";
3770b57cec5SDimitry Andric       } else if (type == "int" || type == "unsigned") {
3780b57cec5SDimitry Andric         OS << "    OS << \" \" << SA->get" << getUpperName() << "();\n";
3790b57cec5SDimitry Andric       } else if (type == "ParamIdx") {
3800b57cec5SDimitry Andric         if (isOptional())
3810b57cec5SDimitry Andric           OS << "    if (SA->get" << getUpperName() << "().isValid())\n  ";
3820b57cec5SDimitry Andric         OS << "    OS << \" \" << SA->get" << getUpperName()
3830b57cec5SDimitry Andric            << "().getSourceIndex();\n";
3845ffd83dbSDimitry Andric       } else if (type == "OMPTraitInfo *") {
3855ffd83dbSDimitry Andric         OS << "    OS << \" \" << SA->get" << getUpperName() << "();\n";
3860b57cec5SDimitry Andric       } else {
3870b57cec5SDimitry Andric         llvm_unreachable("Unknown SimpleArgument type!");
3880b57cec5SDimitry Andric       }
3890b57cec5SDimitry Andric     }
3900b57cec5SDimitry Andric   };
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric   class DefaultSimpleArgument : public SimpleArgument {
3930b57cec5SDimitry Andric     int64_t Default;
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric   public:
3960b57cec5SDimitry Andric     DefaultSimpleArgument(const Record &Arg, StringRef Attr,
3970b57cec5SDimitry Andric                           std::string T, int64_t Default)
3980b57cec5SDimitry Andric       : SimpleArgument(Arg, Attr, T), Default(Default) {}
3990b57cec5SDimitry Andric 
4000b57cec5SDimitry Andric     void writeAccessors(raw_ostream &OS) const override {
4010b57cec5SDimitry Andric       SimpleArgument::writeAccessors(OS);
4020b57cec5SDimitry Andric 
4030b57cec5SDimitry Andric       OS << "\n\n  static const " << getType() << " Default" << getUpperName()
4040b57cec5SDimitry Andric          << " = ";
4050b57cec5SDimitry Andric       if (getType() == "bool")
4060b57cec5SDimitry Andric         OS << (Default != 0 ? "true" : "false");
4070b57cec5SDimitry Andric       else
4080b57cec5SDimitry Andric         OS << Default;
4090b57cec5SDimitry Andric       OS << ";";
4100b57cec5SDimitry Andric     }
4110b57cec5SDimitry Andric   };
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric   class StringArgument : public Argument {
4140b57cec5SDimitry Andric   public:
4150b57cec5SDimitry Andric     StringArgument(const Record &Arg, StringRef Attr)
4160b57cec5SDimitry Andric       : Argument(Arg, Attr)
4170b57cec5SDimitry Andric     {}
4180b57cec5SDimitry Andric 
4190b57cec5SDimitry Andric     void writeAccessors(raw_ostream &OS) const override {
4200b57cec5SDimitry Andric       OS << "  llvm::StringRef get" << getUpperName() << "() const {\n";
4210b57cec5SDimitry Andric       OS << "    return llvm::StringRef(" << getLowerName() << ", "
4220b57cec5SDimitry Andric          << getLowerName() << "Length);\n";
4230b57cec5SDimitry Andric       OS << "  }\n";
4240b57cec5SDimitry Andric       OS << "  unsigned get" << getUpperName() << "Length() const {\n";
4250b57cec5SDimitry Andric       OS << "    return " << getLowerName() << "Length;\n";
4260b57cec5SDimitry Andric       OS << "  }\n";
4270b57cec5SDimitry Andric       OS << "  void set" << getUpperName()
4280b57cec5SDimitry Andric          << "(ASTContext &C, llvm::StringRef S) {\n";
4290b57cec5SDimitry Andric       OS << "    " << getLowerName() << "Length = S.size();\n";
4300b57cec5SDimitry Andric       OS << "    this->" << getLowerName() << " = new (C, 1) char ["
4310b57cec5SDimitry Andric          << getLowerName() << "Length];\n";
4320b57cec5SDimitry Andric       OS << "    if (!S.empty())\n";
4330b57cec5SDimitry Andric       OS << "      std::memcpy(this->" << getLowerName() << ", S.data(), "
4340b57cec5SDimitry Andric          << getLowerName() << "Length);\n";
4350b57cec5SDimitry Andric       OS << "  }";
4360b57cec5SDimitry Andric     }
4370b57cec5SDimitry Andric 
4380b57cec5SDimitry Andric     void writeCloneArgs(raw_ostream &OS) const override {
4390b57cec5SDimitry Andric       OS << "get" << getUpperName() << "()";
4400b57cec5SDimitry Andric     }
4410b57cec5SDimitry Andric 
4420b57cec5SDimitry Andric     void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
4430b57cec5SDimitry Andric       OS << "A->get" << getUpperName() << "()";
4440b57cec5SDimitry Andric     }
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric     void writeCtorBody(raw_ostream &OS) const override {
4470b57cec5SDimitry Andric       OS << "    if (!" << getUpperName() << ".empty())\n";
4480b57cec5SDimitry Andric       OS << "      std::memcpy(" << getLowerName() << ", " << getUpperName()
4490b57cec5SDimitry Andric          << ".data(), " << getLowerName() << "Length);\n";
4500b57cec5SDimitry Andric     }
4510b57cec5SDimitry Andric 
4520b57cec5SDimitry Andric     void writeCtorInitializers(raw_ostream &OS) const override {
4530b57cec5SDimitry Andric       OS << getLowerName() << "Length(" << getUpperName() << ".size()),"
4540b57cec5SDimitry Andric          << getLowerName() << "(new (Ctx, 1) char[" << getLowerName()
4550b57cec5SDimitry Andric          << "Length])";
4560b57cec5SDimitry Andric     }
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric     void writeCtorDefaultInitializers(raw_ostream &OS) const override {
4590b57cec5SDimitry Andric       OS << getLowerName() << "Length(0)," << getLowerName() << "(nullptr)";
4600b57cec5SDimitry Andric     }
4610b57cec5SDimitry Andric 
4620b57cec5SDimitry Andric     void writeCtorParameters(raw_ostream &OS) const override {
4630b57cec5SDimitry Andric       OS << "llvm::StringRef " << getUpperName();
4640b57cec5SDimitry Andric     }
4650b57cec5SDimitry Andric 
4660b57cec5SDimitry Andric     void writeDeclarations(raw_ostream &OS) const override {
4670b57cec5SDimitry Andric       OS << "unsigned " << getLowerName() << "Length;\n";
4680b57cec5SDimitry Andric       OS << "char *" << getLowerName() << ";";
4690b57cec5SDimitry Andric     }
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric     void writePCHReadDecls(raw_ostream &OS) const override {
4720b57cec5SDimitry Andric       OS << "    std::string " << getLowerName()
4730b57cec5SDimitry Andric          << "= Record.readString();\n";
4740b57cec5SDimitry Andric     }
4750b57cec5SDimitry Andric 
4760b57cec5SDimitry Andric     void writePCHReadArgs(raw_ostream &OS) const override {
4770b57cec5SDimitry Andric       OS << getLowerName();
4780b57cec5SDimitry Andric     }
4790b57cec5SDimitry Andric 
4800b57cec5SDimitry Andric     void writePCHWrite(raw_ostream &OS) const override {
4810b57cec5SDimitry Andric       OS << "    Record.AddString(SA->get" << getUpperName() << "());\n";
4820b57cec5SDimitry Andric     }
4830b57cec5SDimitry Andric 
4840b57cec5SDimitry Andric     void writeValue(raw_ostream &OS) const override {
4850b57cec5SDimitry Andric       OS << "\\\"\" << get" << getUpperName() << "() << \"\\\"";
4860b57cec5SDimitry Andric     }
4870b57cec5SDimitry Andric 
4880b57cec5SDimitry Andric     void writeDump(raw_ostream &OS) const override {
4890b57cec5SDimitry Andric       OS << "    OS << \" \\\"\" << SA->get" << getUpperName()
4900b57cec5SDimitry Andric          << "() << \"\\\"\";\n";
4910b57cec5SDimitry Andric     }
4920b57cec5SDimitry Andric   };
4930b57cec5SDimitry Andric 
4940b57cec5SDimitry Andric   class AlignedArgument : public Argument {
4950b57cec5SDimitry Andric   public:
4960b57cec5SDimitry Andric     AlignedArgument(const Record &Arg, StringRef Attr)
4970b57cec5SDimitry Andric       : Argument(Arg, Attr)
4980b57cec5SDimitry Andric     {}
4990b57cec5SDimitry Andric 
5000b57cec5SDimitry Andric     void writeAccessors(raw_ostream &OS) const override {
5010b57cec5SDimitry Andric       OS << "  bool is" << getUpperName() << "Dependent() const;\n";
5025ffd83dbSDimitry Andric       OS << "  bool is" << getUpperName() << "ErrorDependent() const;\n";
5030b57cec5SDimitry Andric 
5040b57cec5SDimitry Andric       OS << "  unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n";
5050b57cec5SDimitry Andric 
5060b57cec5SDimitry Andric       OS << "  bool is" << getUpperName() << "Expr() const {\n";
5070b57cec5SDimitry Andric       OS << "    return is" << getLowerName() << "Expr;\n";
5080b57cec5SDimitry Andric       OS << "  }\n";
5090b57cec5SDimitry Andric 
5100b57cec5SDimitry Andric       OS << "  Expr *get" << getUpperName() << "Expr() const {\n";
5110b57cec5SDimitry Andric       OS << "    assert(is" << getLowerName() << "Expr);\n";
5120b57cec5SDimitry Andric       OS << "    return " << getLowerName() << "Expr;\n";
5130b57cec5SDimitry Andric       OS << "  }\n";
5140b57cec5SDimitry Andric 
5150b57cec5SDimitry Andric       OS << "  TypeSourceInfo *get" << getUpperName() << "Type() const {\n";
5160b57cec5SDimitry Andric       OS << "    assert(!is" << getLowerName() << "Expr);\n";
5170b57cec5SDimitry Andric       OS << "    return " << getLowerName() << "Type;\n";
5180b57cec5SDimitry Andric       OS << "  }";
51906c3fb27SDimitry Andric 
52006c3fb27SDimitry Andric       OS << "  std::optional<unsigned> getCached" << getUpperName()
52106c3fb27SDimitry Andric          << "Value() const {\n";
52206c3fb27SDimitry Andric       OS << "    return " << getLowerName() << "Cache;\n";
52306c3fb27SDimitry Andric       OS << "  }";
52406c3fb27SDimitry Andric 
52506c3fb27SDimitry Andric       OS << "  void setCached" << getUpperName()
52606c3fb27SDimitry Andric          << "Value(unsigned AlignVal) {\n";
52706c3fb27SDimitry Andric       OS << "    " << getLowerName() << "Cache = AlignVal;\n";
52806c3fb27SDimitry Andric       OS << "  }";
5290b57cec5SDimitry Andric     }
5300b57cec5SDimitry Andric 
5310b57cec5SDimitry Andric     void writeAccessorDefinitions(raw_ostream &OS) const override {
5320b57cec5SDimitry Andric       OS << "bool " << getAttrName() << "Attr::is" << getUpperName()
5330b57cec5SDimitry Andric          << "Dependent() const {\n";
5340b57cec5SDimitry Andric       OS << "  if (is" << getLowerName() << "Expr)\n";
5350b57cec5SDimitry Andric       OS << "    return " << getLowerName() << "Expr && (" << getLowerName()
5360b57cec5SDimitry Andric          << "Expr->isValueDependent() || " << getLowerName()
5370b57cec5SDimitry Andric          << "Expr->isTypeDependent());\n";
5380b57cec5SDimitry Andric       OS << "  else\n";
5390b57cec5SDimitry Andric       OS << "    return " << getLowerName()
5400b57cec5SDimitry Andric          << "Type->getType()->isDependentType();\n";
5410b57cec5SDimitry Andric       OS << "}\n";
5420b57cec5SDimitry Andric 
5435ffd83dbSDimitry Andric       OS << "bool " << getAttrName() << "Attr::is" << getUpperName()
5445ffd83dbSDimitry Andric          << "ErrorDependent() const {\n";
5455ffd83dbSDimitry Andric       OS << "  if (is" << getLowerName() << "Expr)\n";
5465ffd83dbSDimitry Andric       OS << "    return " << getLowerName() << "Expr && " << getLowerName()
5475ffd83dbSDimitry Andric          << "Expr->containsErrors();\n";
5485ffd83dbSDimitry Andric       OS << "  return " << getLowerName()
5495ffd83dbSDimitry Andric          << "Type->getType()->containsErrors();\n";
5505ffd83dbSDimitry Andric       OS << "}\n";
5510b57cec5SDimitry Andric     }
5520b57cec5SDimitry Andric 
5530b57cec5SDimitry Andric     void writeASTVisitorTraversal(raw_ostream &OS) const override {
5540b57cec5SDimitry Andric       StringRef Name = getUpperName();
5550b57cec5SDimitry Andric       OS << "  if (A->is" << Name << "Expr()) {\n"
5560b57cec5SDimitry Andric          << "    if (!getDerived().TraverseStmt(A->get" << Name << "Expr()))\n"
5570b57cec5SDimitry Andric          << "      return false;\n"
5580b57cec5SDimitry Andric          << "  } else if (auto *TSI = A->get" << Name << "Type()) {\n"
5590b57cec5SDimitry Andric          << "    if (!getDerived().TraverseTypeLoc(TSI->getTypeLoc()))\n"
5600b57cec5SDimitry Andric          << "      return false;\n"
5610b57cec5SDimitry Andric          << "  }\n";
5620b57cec5SDimitry Andric     }
5630b57cec5SDimitry Andric 
5640b57cec5SDimitry Andric     void writeCloneArgs(raw_ostream &OS) const override {
5650b57cec5SDimitry Andric       OS << "is" << getLowerName() << "Expr, is" << getLowerName()
5660b57cec5SDimitry Andric          << "Expr ? static_cast<void*>(" << getLowerName()
5670b57cec5SDimitry Andric          << "Expr) : " << getLowerName()
5680b57cec5SDimitry Andric          << "Type";
5690b57cec5SDimitry Andric     }
5700b57cec5SDimitry Andric 
5710b57cec5SDimitry Andric     void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
5720b57cec5SDimitry Andric       // FIXME: move the definition in Sema::InstantiateAttrs to here.
5730b57cec5SDimitry Andric       // In the meantime, aligned attributes are cloned.
5740b57cec5SDimitry Andric     }
5750b57cec5SDimitry Andric 
5760b57cec5SDimitry Andric     void writeCtorBody(raw_ostream &OS) const override {
5770b57cec5SDimitry Andric       OS << "    if (is" << getLowerName() << "Expr)\n";
5780b57cec5SDimitry Andric       OS << "       " << getLowerName() << "Expr = reinterpret_cast<Expr *>("
5790b57cec5SDimitry Andric          << getUpperName() << ");\n";
5800b57cec5SDimitry Andric       OS << "    else\n";
5810b57cec5SDimitry Andric       OS << "       " << getLowerName()
5820b57cec5SDimitry Andric          << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName()
5830b57cec5SDimitry Andric          << ");\n";
5840b57cec5SDimitry Andric     }
5850b57cec5SDimitry Andric 
5860b57cec5SDimitry Andric     void writeCtorInitializers(raw_ostream &OS) const override {
5870b57cec5SDimitry Andric       OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)";
5880b57cec5SDimitry Andric     }
5890b57cec5SDimitry Andric 
5900b57cec5SDimitry Andric     void writeCtorDefaultInitializers(raw_ostream &OS) const override {
5910b57cec5SDimitry Andric       OS << "is" << getLowerName() << "Expr(false)";
5920b57cec5SDimitry Andric     }
5930b57cec5SDimitry Andric 
5940b57cec5SDimitry Andric     void writeCtorParameters(raw_ostream &OS) const override {
5950b57cec5SDimitry Andric       OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName();
5960b57cec5SDimitry Andric     }
5970b57cec5SDimitry Andric 
5980b57cec5SDimitry Andric     void writeImplicitCtorArgs(raw_ostream &OS) const override {
5990b57cec5SDimitry Andric       OS << "Is" << getUpperName() << "Expr, " << getUpperName();
6000b57cec5SDimitry Andric     }
6010b57cec5SDimitry Andric 
6020b57cec5SDimitry Andric     void writeDeclarations(raw_ostream &OS) const override {
6030b57cec5SDimitry Andric       OS << "bool is" << getLowerName() << "Expr;\n";
6040b57cec5SDimitry Andric       OS << "union {\n";
6050b57cec5SDimitry Andric       OS << "Expr *" << getLowerName() << "Expr;\n";
6060b57cec5SDimitry Andric       OS << "TypeSourceInfo *" << getLowerName() << "Type;\n";
60706c3fb27SDimitry Andric       OS << "};\n";
60806c3fb27SDimitry Andric       OS << "std::optional<unsigned> " << getLowerName() << "Cache;\n";
6090b57cec5SDimitry Andric     }
6100b57cec5SDimitry Andric 
6110b57cec5SDimitry Andric     void writePCHReadArgs(raw_ostream &OS) const override {
6120b57cec5SDimitry Andric       OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr";
6130b57cec5SDimitry Andric     }
6140b57cec5SDimitry Andric 
6150b57cec5SDimitry Andric     void writePCHReadDecls(raw_ostream &OS) const override {
6160b57cec5SDimitry Andric       OS << "    bool is" << getLowerName() << "Expr = Record.readInt();\n";
6170b57cec5SDimitry Andric       OS << "    void *" << getLowerName() << "Ptr;\n";
6180b57cec5SDimitry Andric       OS << "    if (is" << getLowerName() << "Expr)\n";
6190b57cec5SDimitry Andric       OS << "      " << getLowerName() << "Ptr = Record.readExpr();\n";
6200b57cec5SDimitry Andric       OS << "    else\n";
6210b57cec5SDimitry Andric       OS << "      " << getLowerName()
622480093f4SDimitry Andric          << "Ptr = Record.readTypeSourceInfo();\n";
6230b57cec5SDimitry Andric     }
6240b57cec5SDimitry Andric 
6250b57cec5SDimitry Andric     void writePCHWrite(raw_ostream &OS) const override {
6260b57cec5SDimitry Andric       OS << "    Record.push_back(SA->is" << getUpperName() << "Expr());\n";
6270b57cec5SDimitry Andric       OS << "    if (SA->is" << getUpperName() << "Expr())\n";
6280b57cec5SDimitry Andric       OS << "      Record.AddStmt(SA->get" << getUpperName() << "Expr());\n";
6290b57cec5SDimitry Andric       OS << "    else\n";
6300b57cec5SDimitry Andric       OS << "      Record.AddTypeSourceInfo(SA->get" << getUpperName()
6310b57cec5SDimitry Andric          << "Type());\n";
6320b57cec5SDimitry Andric     }
6330b57cec5SDimitry Andric 
6340b57cec5SDimitry Andric     std::string getIsOmitted() const override {
63506c3fb27SDimitry Andric       return "!((is" + getLowerName().str() + "Expr && " +
63606c3fb27SDimitry Andric              getLowerName().str() + "Expr) || (!is" + getLowerName().str() +
63706c3fb27SDimitry Andric              "Expr && " + getLowerName().str() + "Type))";
6380b57cec5SDimitry Andric     }
6390b57cec5SDimitry Andric 
6400b57cec5SDimitry Andric     void writeValue(raw_ostream &OS) const override {
6410b57cec5SDimitry Andric       OS << "\";\n";
64206c3fb27SDimitry Andric       OS << "    if (is" << getLowerName() << "Expr && " << getLowerName()
64306c3fb27SDimitry Andric          << "Expr)";
6440b57cec5SDimitry Andric       OS << "      " << getLowerName()
6450b57cec5SDimitry Andric          << "Expr->printPretty(OS, nullptr, Policy);\n";
64606c3fb27SDimitry Andric       OS << "    if (!is" << getLowerName() << "Expr && " << getLowerName()
64706c3fb27SDimitry Andric          << "Type)";
64806c3fb27SDimitry Andric       OS << "      " << getLowerName()
64906c3fb27SDimitry Andric          << "Type->getType().print(OS, Policy);\n";
6500b57cec5SDimitry Andric       OS << "    OS << \"";
6510b57cec5SDimitry Andric     }
6520b57cec5SDimitry Andric 
6530b57cec5SDimitry Andric     void writeDump(raw_ostream &OS) const override {
6540b57cec5SDimitry Andric       OS << "    if (!SA->is" << getUpperName() << "Expr())\n";
6550b57cec5SDimitry Andric       OS << "      dumpType(SA->get" << getUpperName()
6560b57cec5SDimitry Andric          << "Type()->getType());\n";
6570b57cec5SDimitry Andric     }
6580b57cec5SDimitry Andric 
6590b57cec5SDimitry Andric     void writeDumpChildren(raw_ostream &OS) const override {
6600b57cec5SDimitry Andric       OS << "    if (SA->is" << getUpperName() << "Expr())\n";
6610b57cec5SDimitry Andric       OS << "      Visit(SA->get" << getUpperName() << "Expr());\n";
6620b57cec5SDimitry Andric     }
6630b57cec5SDimitry Andric 
6640b57cec5SDimitry Andric     void writeHasChildren(raw_ostream &OS) const override {
6650b57cec5SDimitry Andric       OS << "SA->is" << getUpperName() << "Expr()";
6660b57cec5SDimitry Andric     }
6670b57cec5SDimitry Andric   };
6680b57cec5SDimitry Andric 
6690b57cec5SDimitry Andric   class VariadicArgument : public Argument {
6700b57cec5SDimitry Andric     std::string Type, ArgName, ArgSizeName, RangeName;
6710b57cec5SDimitry Andric 
6720b57cec5SDimitry Andric   protected:
6730b57cec5SDimitry Andric     // Assumed to receive a parameter: raw_ostream OS.
6740b57cec5SDimitry Andric     virtual void writeValueImpl(raw_ostream &OS) const {
6750b57cec5SDimitry Andric       OS << "    OS << Val;\n";
6760b57cec5SDimitry Andric     }
6770b57cec5SDimitry Andric     // Assumed to receive a parameter: raw_ostream OS.
6780b57cec5SDimitry Andric     virtual void writeDumpImpl(raw_ostream &OS) const {
6790b57cec5SDimitry Andric       OS << "      OS << \" \" << Val;\n";
6800b57cec5SDimitry Andric     }
6810b57cec5SDimitry Andric 
6820b57cec5SDimitry Andric   public:
6830b57cec5SDimitry Andric     VariadicArgument(const Record &Arg, StringRef Attr, std::string T)
6840b57cec5SDimitry Andric         : Argument(Arg, Attr), Type(std::move(T)),
6850b57cec5SDimitry Andric           ArgName(getLowerName().str() + "_"), ArgSizeName(ArgName + "Size"),
6865ffd83dbSDimitry Andric           RangeName(std::string(getLowerName())) {}
6870b57cec5SDimitry Andric 
68881ad6265SDimitry Andric     VariadicArgument(StringRef Arg, StringRef Attr, std::string T)
68981ad6265SDimitry Andric         : Argument(Arg, Attr), Type(std::move(T)),
69081ad6265SDimitry Andric           ArgName(getLowerName().str() + "_"), ArgSizeName(ArgName + "Size"),
69181ad6265SDimitry Andric           RangeName(std::string(getLowerName())) {}
69281ad6265SDimitry Andric 
6930b57cec5SDimitry Andric     const std::string &getType() const { return Type; }
6940b57cec5SDimitry Andric     const std::string &getArgName() const { return ArgName; }
6950b57cec5SDimitry Andric     const std::string &getArgSizeName() const { return ArgSizeName; }
6960b57cec5SDimitry Andric     bool isVariadic() const override { return true; }
6970b57cec5SDimitry Andric 
6980b57cec5SDimitry Andric     void writeAccessors(raw_ostream &OS) const override {
6990b57cec5SDimitry Andric       std::string IteratorType = getLowerName().str() + "_iterator";
7000b57cec5SDimitry Andric       std::string BeginFn = getLowerName().str() + "_begin()";
7010b57cec5SDimitry Andric       std::string EndFn = getLowerName().str() + "_end()";
7020b57cec5SDimitry Andric 
7030b57cec5SDimitry Andric       OS << "  typedef " << Type << "* " << IteratorType << ";\n";
7040b57cec5SDimitry Andric       OS << "  " << IteratorType << " " << BeginFn << " const {"
7050b57cec5SDimitry Andric          << " return " << ArgName << "; }\n";
7060b57cec5SDimitry Andric       OS << "  " << IteratorType << " " << EndFn << " const {"
7070b57cec5SDimitry Andric          << " return " << ArgName << " + " << ArgSizeName << "; }\n";
7080b57cec5SDimitry Andric       OS << "  unsigned " << getLowerName() << "_size() const {"
7090b57cec5SDimitry Andric          << " return " << ArgSizeName << "; }\n";
7100b57cec5SDimitry Andric       OS << "  llvm::iterator_range<" << IteratorType << "> " << RangeName
7110b57cec5SDimitry Andric          << "() const { return llvm::make_range(" << BeginFn << ", " << EndFn
7120b57cec5SDimitry Andric          << "); }\n";
7130b57cec5SDimitry Andric     }
7140b57cec5SDimitry Andric 
71581ad6265SDimitry Andric     void writeSetter(raw_ostream &OS) const {
71681ad6265SDimitry Andric       OS << "  void set" << getUpperName() << "(ASTContext &Ctx, ";
71781ad6265SDimitry Andric       writeCtorParameters(OS);
71881ad6265SDimitry Andric       OS << ") {\n";
71981ad6265SDimitry Andric       OS << "    " << ArgSizeName << " = " << getUpperName() << "Size;\n";
72081ad6265SDimitry Andric       OS << "    " << ArgName << " = new (Ctx, 16) " << getType() << "["
72181ad6265SDimitry Andric          << ArgSizeName << "];\n";
72281ad6265SDimitry Andric       OS << "  ";
72381ad6265SDimitry Andric       writeCtorBody(OS);
72481ad6265SDimitry Andric       OS << "  }\n";
72581ad6265SDimitry Andric     }
72681ad6265SDimitry Andric 
7270b57cec5SDimitry Andric     void writeCloneArgs(raw_ostream &OS) const override {
7280b57cec5SDimitry Andric       OS << ArgName << ", " << ArgSizeName;
7290b57cec5SDimitry Andric     }
7300b57cec5SDimitry Andric 
7310b57cec5SDimitry Andric     void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
7320b57cec5SDimitry Andric       // This isn't elegant, but we have to go through public methods...
7330b57cec5SDimitry Andric       OS << "A->" << getLowerName() << "_begin(), "
7340b57cec5SDimitry Andric          << "A->" << getLowerName() << "_size()";
7350b57cec5SDimitry Andric     }
7360b57cec5SDimitry Andric 
7370b57cec5SDimitry Andric     void writeASTVisitorTraversal(raw_ostream &OS) const override {
7380b57cec5SDimitry Andric       // FIXME: Traverse the elements.
7390b57cec5SDimitry Andric     }
7400b57cec5SDimitry Andric 
7410b57cec5SDimitry Andric     void writeCtorBody(raw_ostream &OS) const override {
7425ffd83dbSDimitry Andric       OS << "  std::copy(" << getUpperName() << ", " << getUpperName() << " + "
7435ffd83dbSDimitry Andric          << ArgSizeName << ", " << ArgName << ");\n";
7440b57cec5SDimitry Andric     }
7450b57cec5SDimitry Andric 
7460b57cec5SDimitry Andric     void writeCtorInitializers(raw_ostream &OS) const override {
7470b57cec5SDimitry Andric       OS << ArgSizeName << "(" << getUpperName() << "Size), "
7480b57cec5SDimitry Andric          << ArgName << "(new (Ctx, 16) " << getType() << "["
7490b57cec5SDimitry Andric          << ArgSizeName << "])";
7500b57cec5SDimitry Andric     }
7510b57cec5SDimitry Andric 
7520b57cec5SDimitry Andric     void writeCtorDefaultInitializers(raw_ostream &OS) const override {
7530b57cec5SDimitry Andric       OS << ArgSizeName << "(0), " << ArgName << "(nullptr)";
7540b57cec5SDimitry Andric     }
7550b57cec5SDimitry Andric 
7560b57cec5SDimitry Andric     void writeCtorParameters(raw_ostream &OS) const override {
7570b57cec5SDimitry Andric       OS << getType() << " *" << getUpperName() << ", unsigned "
7580b57cec5SDimitry Andric          << getUpperName() << "Size";
7590b57cec5SDimitry Andric     }
7600b57cec5SDimitry Andric 
7610b57cec5SDimitry Andric     void writeImplicitCtorArgs(raw_ostream &OS) const override {
7620b57cec5SDimitry Andric       OS << getUpperName() << ", " << getUpperName() << "Size";
7630b57cec5SDimitry Andric     }
7640b57cec5SDimitry Andric 
7650b57cec5SDimitry Andric     void writeDeclarations(raw_ostream &OS) const override {
7660b57cec5SDimitry Andric       OS << "  unsigned " << ArgSizeName << ";\n";
7670b57cec5SDimitry Andric       OS << "  " << getType() << " *" << ArgName << ";";
7680b57cec5SDimitry Andric     }
7690b57cec5SDimitry Andric 
7700b57cec5SDimitry Andric     void writePCHReadDecls(raw_ostream &OS) const override {
7710b57cec5SDimitry Andric       OS << "    unsigned " << getLowerName() << "Size = Record.readInt();\n";
7720b57cec5SDimitry Andric       OS << "    SmallVector<" << getType() << ", 4> "
7730b57cec5SDimitry Andric          << getLowerName() << ";\n";
7740b57cec5SDimitry Andric       OS << "    " << getLowerName() << ".reserve(" << getLowerName()
7750b57cec5SDimitry Andric          << "Size);\n";
7760b57cec5SDimitry Andric 
7770b57cec5SDimitry Andric       // If we can't store the values in the current type (if it's something
7780b57cec5SDimitry Andric       // like StringRef), store them in a different type and convert the
7790b57cec5SDimitry Andric       // container afterwards.
7805ffd83dbSDimitry Andric       std::string StorageType = std::string(getStorageType(getType()));
7815ffd83dbSDimitry Andric       std::string StorageName = std::string(getLowerName());
7820b57cec5SDimitry Andric       if (StorageType != getType()) {
7830b57cec5SDimitry Andric         StorageName += "Storage";
7840b57cec5SDimitry Andric         OS << "    SmallVector<" << StorageType << ", 4> "
7850b57cec5SDimitry Andric            << StorageName << ";\n";
7860b57cec5SDimitry Andric         OS << "    " << StorageName << ".reserve(" << getLowerName()
7870b57cec5SDimitry Andric            << "Size);\n";
7880b57cec5SDimitry Andric       }
7890b57cec5SDimitry Andric 
7900b57cec5SDimitry Andric       OS << "    for (unsigned i = 0; i != " << getLowerName() << "Size; ++i)\n";
7910b57cec5SDimitry Andric       std::string read = ReadPCHRecord(Type);
7920b57cec5SDimitry Andric       OS << "      " << StorageName << ".push_back(" << read << ");\n";
7930b57cec5SDimitry Andric 
7940b57cec5SDimitry Andric       if (StorageType != getType()) {
7950b57cec5SDimitry Andric         OS << "    for (unsigned i = 0; i != " << getLowerName() << "Size; ++i)\n";
7960b57cec5SDimitry Andric         OS << "      " << getLowerName() << ".push_back("
7970b57cec5SDimitry Andric            << StorageName << "[i]);\n";
7980b57cec5SDimitry Andric       }
7990b57cec5SDimitry Andric     }
8000b57cec5SDimitry Andric 
8010b57cec5SDimitry Andric     void writePCHReadArgs(raw_ostream &OS) const override {
8020b57cec5SDimitry Andric       OS << getLowerName() << ".data(), " << getLowerName() << "Size";
8030b57cec5SDimitry Andric     }
8040b57cec5SDimitry Andric 
8050b57cec5SDimitry Andric     void writePCHWrite(raw_ostream &OS) const override {
8060b57cec5SDimitry Andric       OS << "    Record.push_back(SA->" << getLowerName() << "_size());\n";
8070b57cec5SDimitry Andric       OS << "    for (auto &Val : SA->" << RangeName << "())\n";
8080b57cec5SDimitry Andric       OS << "      " << WritePCHRecord(Type, "Val");
8090b57cec5SDimitry Andric     }
8100b57cec5SDimitry Andric 
8110b57cec5SDimitry Andric     void writeValue(raw_ostream &OS) const override {
8120b57cec5SDimitry Andric       OS << "\";\n";
813fe6060f1SDimitry Andric       OS << "  for (const auto &Val : " << RangeName << "()) {\n"
814fe6060f1SDimitry Andric          << "    DelimitAttributeArgument(OS, IsFirstArgument);\n";
8150b57cec5SDimitry Andric       writeValueImpl(OS);
8160b57cec5SDimitry Andric       OS << "  }\n";
8170b57cec5SDimitry Andric       OS << "  OS << \"";
8180b57cec5SDimitry Andric     }
8190b57cec5SDimitry Andric 
8200b57cec5SDimitry Andric     void writeDump(raw_ostream &OS) const override {
8210b57cec5SDimitry Andric       OS << "    for (const auto &Val : SA->" << RangeName << "())\n";
8220b57cec5SDimitry Andric       writeDumpImpl(OS);
8230b57cec5SDimitry Andric     }
8240b57cec5SDimitry Andric   };
8250b57cec5SDimitry Andric 
826bdd1243dSDimitry Andric   class VariadicOMPInteropInfoArgument : public VariadicArgument {
827bdd1243dSDimitry Andric   public:
828bdd1243dSDimitry Andric     VariadicOMPInteropInfoArgument(const Record &Arg, StringRef Attr)
829bdd1243dSDimitry Andric         : VariadicArgument(Arg, Attr, "OMPInteropInfo") {}
830bdd1243dSDimitry Andric 
831bdd1243dSDimitry Andric     void writeDump(raw_ostream &OS) const override {
832bdd1243dSDimitry Andric       OS << "    for (" << getAttrName() << "Attr::" << getLowerName()
833bdd1243dSDimitry Andric          << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
834bdd1243dSDimitry Andric          << getLowerName() << "_end(); I != E; ++I) {\n";
835bdd1243dSDimitry Andric       OS << "      if (I->IsTarget && I->IsTargetSync)\n";
836bdd1243dSDimitry Andric       OS << "        OS << \" Target_TargetSync\";\n";
837bdd1243dSDimitry Andric       OS << "      else if (I->IsTarget)\n";
838bdd1243dSDimitry Andric       OS << "        OS << \" Target\";\n";
839bdd1243dSDimitry Andric       OS << "      else\n";
840bdd1243dSDimitry Andric       OS << "        OS << \" TargetSync\";\n";
841bdd1243dSDimitry Andric       OS << "    }\n";
842bdd1243dSDimitry Andric     }
843bdd1243dSDimitry Andric 
844bdd1243dSDimitry Andric     void writePCHReadDecls(raw_ostream &OS) const override {
845bdd1243dSDimitry Andric       OS << "    unsigned " << getLowerName() << "Size = Record.readInt();\n";
846bdd1243dSDimitry Andric       OS << "    SmallVector<OMPInteropInfo, 4> " << getLowerName() << ";\n";
847bdd1243dSDimitry Andric       OS << "    " << getLowerName() << ".reserve(" << getLowerName()
848bdd1243dSDimitry Andric          << "Size);\n";
849bdd1243dSDimitry Andric       OS << "    for (unsigned I = 0, E = " << getLowerName() << "Size; ";
850bdd1243dSDimitry Andric       OS << "I != E; ++I) {\n";
851bdd1243dSDimitry Andric       OS << "      bool IsTarget = Record.readBool();\n";
852bdd1243dSDimitry Andric       OS << "      bool IsTargetSync = Record.readBool();\n";
853bdd1243dSDimitry Andric       OS << "      " << getLowerName()
854bdd1243dSDimitry Andric          << ".emplace_back(IsTarget, IsTargetSync);\n";
855bdd1243dSDimitry Andric       OS << "    }\n";
856bdd1243dSDimitry Andric     }
857bdd1243dSDimitry Andric 
858bdd1243dSDimitry Andric     void writePCHWrite(raw_ostream &OS) const override {
859bdd1243dSDimitry Andric       OS << "    Record.push_back(SA->" << getLowerName() << "_size());\n";
860bdd1243dSDimitry Andric       OS << "    for (" << getAttrName() << "Attr::" << getLowerName()
861bdd1243dSDimitry Andric          << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
862bdd1243dSDimitry Andric          << getLowerName() << "_end(); I != E; ++I) {\n";
863bdd1243dSDimitry Andric       OS << "      Record.writeBool(I->IsTarget);\n";
864bdd1243dSDimitry Andric       OS << "      Record.writeBool(I->IsTargetSync);\n";
865bdd1243dSDimitry Andric       OS << "    }\n";
866bdd1243dSDimitry Andric     }
867bdd1243dSDimitry Andric   };
868bdd1243dSDimitry Andric 
8690b57cec5SDimitry Andric   class VariadicParamIdxArgument : public VariadicArgument {
8700b57cec5SDimitry Andric   public:
8710b57cec5SDimitry Andric     VariadicParamIdxArgument(const Record &Arg, StringRef Attr)
8720b57cec5SDimitry Andric         : VariadicArgument(Arg, Attr, "ParamIdx") {}
8730b57cec5SDimitry Andric 
8740b57cec5SDimitry Andric   public:
8750b57cec5SDimitry Andric     void writeValueImpl(raw_ostream &OS) const override {
8760b57cec5SDimitry Andric       OS << "    OS << Val.getSourceIndex();\n";
8770b57cec5SDimitry Andric     }
8780b57cec5SDimitry Andric 
8790b57cec5SDimitry Andric     void writeDumpImpl(raw_ostream &OS) const override {
8800b57cec5SDimitry Andric       OS << "      OS << \" \" << Val.getSourceIndex();\n";
8810b57cec5SDimitry Andric     }
8820b57cec5SDimitry Andric   };
8830b57cec5SDimitry Andric 
8840b57cec5SDimitry Andric   struct VariadicParamOrParamIdxArgument : public VariadicArgument {
8850b57cec5SDimitry Andric     VariadicParamOrParamIdxArgument(const Record &Arg, StringRef Attr)
8860b57cec5SDimitry Andric         : VariadicArgument(Arg, Attr, "int") {}
8870b57cec5SDimitry Andric   };
8880b57cec5SDimitry Andric 
8890b57cec5SDimitry Andric   // Unique the enums, but maintain the original declaration ordering.
8900b57cec5SDimitry Andric   std::vector<StringRef>
8910b57cec5SDimitry Andric   uniqueEnumsInOrder(const std::vector<StringRef> &enums) {
8920b57cec5SDimitry Andric     std::vector<StringRef> uniques;
8930b57cec5SDimitry Andric     SmallDenseSet<StringRef, 8> unique_set;
8940b57cec5SDimitry Andric     for (const auto &i : enums) {
8950b57cec5SDimitry Andric       if (unique_set.insert(i).second)
8960b57cec5SDimitry Andric         uniques.push_back(i);
8970b57cec5SDimitry Andric     }
8980b57cec5SDimitry Andric     return uniques;
8990b57cec5SDimitry Andric   }
9000b57cec5SDimitry Andric 
9010b57cec5SDimitry Andric   class EnumArgument : public Argument {
9025f757f3fSDimitry Andric     std::string fullType;
9035f757f3fSDimitry Andric     StringRef shortType;
9040b57cec5SDimitry Andric     std::vector<StringRef> values, enums, uniques;
9055f757f3fSDimitry Andric     bool isExternal;
906*0fca6ea1SDimitry Andric     bool isCovered;
9070b57cec5SDimitry Andric 
9080b57cec5SDimitry Andric   public:
9090b57cec5SDimitry Andric     EnumArgument(const Record &Arg, StringRef Attr)
9105f757f3fSDimitry Andric         : Argument(Arg, Attr), values(Arg.getValueAsListOfStrings("Values")),
9110b57cec5SDimitry Andric           enums(Arg.getValueAsListOfStrings("Enums")),
9125f757f3fSDimitry Andric           uniques(uniqueEnumsInOrder(enums)),
913*0fca6ea1SDimitry Andric           isExternal(Arg.getValueAsBit("IsExternalType")),
914*0fca6ea1SDimitry Andric           isCovered(Arg.getValueAsBit("IsCovered")) {
9155f757f3fSDimitry Andric       StringRef Type = Arg.getValueAsString("Type");
9165f757f3fSDimitry Andric       shortType = isExternal ? Type.rsplit("::").second : Type;
9175f757f3fSDimitry Andric       // If shortType didn't contain :: at all rsplit will give us an empty
9185f757f3fSDimitry Andric       // string.
9195f757f3fSDimitry Andric       if (shortType.empty())
9205f757f3fSDimitry Andric         shortType = Type;
9215f757f3fSDimitry Andric       fullType = isExternal ? Type : (getAttrName() + "Attr::" + Type).str();
9225f757f3fSDimitry Andric 
9230b57cec5SDimitry Andric       // FIXME: Emit a proper error
9240b57cec5SDimitry Andric       assert(!uniques.empty());
9250b57cec5SDimitry Andric     }
9260b57cec5SDimitry Andric 
9270b57cec5SDimitry Andric     bool isEnumArg() const override { return true; }
9280b57cec5SDimitry Andric 
9290b57cec5SDimitry Andric     void writeAccessors(raw_ostream &OS) const override {
9305f757f3fSDimitry Andric       OS << "  " << fullType << " get" << getUpperName() << "() const {\n";
9310b57cec5SDimitry Andric       OS << "    return " << getLowerName() << ";\n";
9320b57cec5SDimitry Andric       OS << "  }";
9330b57cec5SDimitry Andric     }
9340b57cec5SDimitry Andric 
9350b57cec5SDimitry Andric     void writeCloneArgs(raw_ostream &OS) const override {
9360b57cec5SDimitry Andric       OS << getLowerName();
9370b57cec5SDimitry Andric     }
9380b57cec5SDimitry Andric 
9390b57cec5SDimitry Andric     void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
9400b57cec5SDimitry Andric       OS << "A->get" << getUpperName() << "()";
9410b57cec5SDimitry Andric     }
9420b57cec5SDimitry Andric     void writeCtorInitializers(raw_ostream &OS) const override {
9430b57cec5SDimitry Andric       OS << getLowerName() << "(" << getUpperName() << ")";
9440b57cec5SDimitry Andric     }
9450b57cec5SDimitry Andric     void writeCtorDefaultInitializers(raw_ostream &OS) const override {
9465f757f3fSDimitry Andric       OS << getLowerName() << "(" << fullType << "(0))";
9470b57cec5SDimitry Andric     }
9480b57cec5SDimitry Andric     void writeCtorParameters(raw_ostream &OS) const override {
9495f757f3fSDimitry Andric       OS << fullType << " " << getUpperName();
9500b57cec5SDimitry Andric     }
9510b57cec5SDimitry Andric     void writeDeclarations(raw_ostream &OS) const override {
9525f757f3fSDimitry Andric       if (!isExternal) {
9530b57cec5SDimitry Andric         auto i = uniques.cbegin(), e = uniques.cend();
9540b57cec5SDimitry Andric         // The last one needs to not have a comma.
9550b57cec5SDimitry Andric         --e;
9560b57cec5SDimitry Andric 
9570b57cec5SDimitry Andric         OS << "public:\n";
9585f757f3fSDimitry Andric         OS << "  enum " << shortType << " {\n";
9590b57cec5SDimitry Andric         for (; i != e; ++i)
9600b57cec5SDimitry Andric           OS << "    " << *i << ",\n";
9610b57cec5SDimitry Andric         OS << "    " << *e << "\n";
9620b57cec5SDimitry Andric         OS << "  };\n";
9635f757f3fSDimitry Andric       }
9645f757f3fSDimitry Andric 
9650b57cec5SDimitry Andric       OS << "private:\n";
9665f757f3fSDimitry Andric       OS << "  " << fullType << " " << getLowerName() << ";";
9670b57cec5SDimitry Andric     }
9680b57cec5SDimitry Andric 
9690b57cec5SDimitry Andric     void writePCHReadDecls(raw_ostream &OS) const override {
9705f757f3fSDimitry Andric       OS << "    " << fullType << " " << getLowerName() << "(static_cast<"
9715f757f3fSDimitry Andric          << fullType << ">(Record.readInt()));\n";
9720b57cec5SDimitry Andric     }
9730b57cec5SDimitry Andric 
9740b57cec5SDimitry Andric     void writePCHReadArgs(raw_ostream &OS) const override {
9750b57cec5SDimitry Andric       OS << getLowerName();
9760b57cec5SDimitry Andric     }
9770b57cec5SDimitry Andric 
9780b57cec5SDimitry Andric     void writePCHWrite(raw_ostream &OS) const override {
9795f757f3fSDimitry Andric       OS << "Record.push_back(static_cast<uint64_t>(SA->get" << getUpperName()
9805f757f3fSDimitry Andric          << "()));\n";
9810b57cec5SDimitry Andric     }
9820b57cec5SDimitry Andric 
9830b57cec5SDimitry Andric     void writeValue(raw_ostream &OS) const override {
9840b57cec5SDimitry Andric       // FIXME: this isn't 100% correct -- some enum arguments require printing
9850b57cec5SDimitry Andric       // as a string literal, while others require printing as an identifier.
9860b57cec5SDimitry Andric       // Tablegen currently does not distinguish between the two forms.
9875f757f3fSDimitry Andric       OS << "\\\"\" << " << getAttrName() << "Attr::Convert" << shortType
9885f757f3fSDimitry Andric          << "ToStr(get" << getUpperName() << "()) << \"\\\"";
9890b57cec5SDimitry Andric     }
9900b57cec5SDimitry Andric 
9910b57cec5SDimitry Andric     void writeDump(raw_ostream &OS) const override {
9920b57cec5SDimitry Andric       OS << "    switch(SA->get" << getUpperName() << "()) {\n";
9930b57cec5SDimitry Andric       for (const auto &I : uniques) {
9945f757f3fSDimitry Andric         OS << "    case " << fullType << "::" << I << ":\n";
9950b57cec5SDimitry Andric         OS << "      OS << \" " << I << "\";\n";
9960b57cec5SDimitry Andric         OS << "      break;\n";
9970b57cec5SDimitry Andric       }
998*0fca6ea1SDimitry Andric       if (!isCovered) {
9995f757f3fSDimitry Andric         OS << "    default:\n";
10005f757f3fSDimitry Andric         OS << "      llvm_unreachable(\"Invalid attribute value\");\n";
10015f757f3fSDimitry Andric       }
10020b57cec5SDimitry Andric       OS << "    }\n";
10030b57cec5SDimitry Andric     }
10040b57cec5SDimitry Andric 
10055ffd83dbSDimitry Andric     void writeConversion(raw_ostream &OS, bool Header) const {
10065ffd83dbSDimitry Andric       if (Header) {
10075f757f3fSDimitry Andric         OS << "  static bool ConvertStrTo" << shortType << "(StringRef Val, "
10085f757f3fSDimitry Andric            << fullType << " &Out);\n";
10095f757f3fSDimitry Andric         OS << "  static const char *Convert" << shortType << "ToStr("
10105f757f3fSDimitry Andric            << fullType << " Val);\n";
10115ffd83dbSDimitry Andric         return;
10125ffd83dbSDimitry Andric       }
10135ffd83dbSDimitry Andric 
10145f757f3fSDimitry Andric       OS << "bool " << getAttrName() << "Attr::ConvertStrTo" << shortType
10155f757f3fSDimitry Andric          << "(StringRef Val, " << fullType << " &Out) {\n";
10165f757f3fSDimitry Andric       OS << "  std::optional<" << fullType << "> "
10175f757f3fSDimitry Andric          << "R = llvm::StringSwitch<std::optional<" << fullType << ">>(Val)\n";
10180b57cec5SDimitry Andric       for (size_t I = 0; I < enums.size(); ++I) {
10190b57cec5SDimitry Andric         OS << "    .Case(\"" << values[I] << "\", ";
10205f757f3fSDimitry Andric         OS << fullType << "::" << enums[I] << ")\n";
10210b57cec5SDimitry Andric       }
10225f757f3fSDimitry Andric       OS << "    .Default(std::optional<" << fullType << ">());\n";
10230b57cec5SDimitry Andric       OS << "  if (R) {\n";
10240b57cec5SDimitry Andric       OS << "    Out = *R;\n      return true;\n    }\n";
10250b57cec5SDimitry Andric       OS << "  return false;\n";
10260b57cec5SDimitry Andric       OS << "}\n\n";
10270b57cec5SDimitry Andric 
10280b57cec5SDimitry Andric       // Mapping from enumeration values back to enumeration strings isn't
10290b57cec5SDimitry Andric       // trivial because some enumeration values have multiple named
10300b57cec5SDimitry Andric       // enumerators, such as type_visibility(internal) and
10310b57cec5SDimitry Andric       // type_visibility(hidden) both mapping to TypeVisibilityAttr::Hidden.
10325f757f3fSDimitry Andric       OS << "const char *" << getAttrName() << "Attr::Convert" << shortType
10335f757f3fSDimitry Andric          << "ToStr(" << fullType << " Val) {\n"
10340b57cec5SDimitry Andric          << "  switch(Val) {\n";
10350b57cec5SDimitry Andric       SmallDenseSet<StringRef, 8> Uniques;
10360b57cec5SDimitry Andric       for (size_t I = 0; I < enums.size(); ++I) {
10370b57cec5SDimitry Andric         if (Uniques.insert(enums[I]).second)
10385f757f3fSDimitry Andric           OS << "  case " << fullType << "::" << enums[I] << ": return \""
10395f757f3fSDimitry Andric              << values[I] << "\";\n";
10405f757f3fSDimitry Andric       }
1041*0fca6ea1SDimitry Andric       if (!isCovered) {
10425f757f3fSDimitry Andric         OS << "  default: llvm_unreachable(\"Invalid attribute value\");\n";
10430b57cec5SDimitry Andric       }
10440b57cec5SDimitry Andric       OS << "  }\n"
10450b57cec5SDimitry Andric          << "  llvm_unreachable(\"No enumerator with that value\");\n"
10460b57cec5SDimitry Andric          << "}\n";
10470b57cec5SDimitry Andric     }
10480b57cec5SDimitry Andric   };
10490b57cec5SDimitry Andric 
10500b57cec5SDimitry Andric   class VariadicEnumArgument: public VariadicArgument {
10515f757f3fSDimitry Andric     std::string fullType;
10525f757f3fSDimitry Andric     StringRef shortType;
10530b57cec5SDimitry Andric     std::vector<StringRef> values, enums, uniques;
10545f757f3fSDimitry Andric     bool isExternal;
1055*0fca6ea1SDimitry Andric     bool isCovered;
10560b57cec5SDimitry Andric 
10570b57cec5SDimitry Andric   protected:
10580b57cec5SDimitry Andric     void writeValueImpl(raw_ostream &OS) const override {
10590b57cec5SDimitry Andric       // FIXME: this isn't 100% correct -- some enum arguments require printing
10600b57cec5SDimitry Andric       // as a string literal, while others require printing as an identifier.
10610b57cec5SDimitry Andric       // Tablegen currently does not distinguish between the two forms.
10625f757f3fSDimitry Andric       OS << "    OS << \"\\\"\" << " << getAttrName() << "Attr::Convert"
10635f757f3fSDimitry Andric          << shortType << "ToStr(Val)"
10645f757f3fSDimitry Andric          << "<< \"\\\"\";\n";
10650b57cec5SDimitry Andric     }
10660b57cec5SDimitry Andric 
10670b57cec5SDimitry Andric   public:
10680b57cec5SDimitry Andric     VariadicEnumArgument(const Record &Arg, StringRef Attr)
10695ffd83dbSDimitry Andric         : VariadicArgument(Arg, Attr,
10705ffd83dbSDimitry Andric                            std::string(Arg.getValueAsString("Type"))),
10710b57cec5SDimitry Andric           values(Arg.getValueAsListOfStrings("Values")),
10720b57cec5SDimitry Andric           enums(Arg.getValueAsListOfStrings("Enums")),
10735f757f3fSDimitry Andric           uniques(uniqueEnumsInOrder(enums)),
1074*0fca6ea1SDimitry Andric           isExternal(Arg.getValueAsBit("IsExternalType")),
1075*0fca6ea1SDimitry Andric           isCovered(Arg.getValueAsBit("IsCovered")) {
10765f757f3fSDimitry Andric       StringRef Type = Arg.getValueAsString("Type");
10775f757f3fSDimitry Andric       shortType = isExternal ? Type.rsplit("::").second : Type;
10785f757f3fSDimitry Andric       // If shortType didn't contain :: at all rsplit will give us an empty
10795f757f3fSDimitry Andric       // string.
10805f757f3fSDimitry Andric       if (shortType.empty())
10815f757f3fSDimitry Andric         shortType = Type;
10825f757f3fSDimitry Andric       fullType = isExternal ? Type : (getAttrName() + "Attr::" + Type).str();
10830b57cec5SDimitry Andric 
10840b57cec5SDimitry Andric       // FIXME: Emit a proper error
10850b57cec5SDimitry Andric       assert(!uniques.empty());
10860b57cec5SDimitry Andric     }
10870b57cec5SDimitry Andric 
10880b57cec5SDimitry Andric     bool isVariadicEnumArg() const override { return true; }
10890b57cec5SDimitry Andric 
10900b57cec5SDimitry Andric     void writeDeclarations(raw_ostream &OS) const override {
10915f757f3fSDimitry Andric       if (!isExternal) {
10920b57cec5SDimitry Andric         auto i = uniques.cbegin(), e = uniques.cend();
10930b57cec5SDimitry Andric         // The last one needs to not have a comma.
10940b57cec5SDimitry Andric         --e;
10950b57cec5SDimitry Andric 
10960b57cec5SDimitry Andric         OS << "public:\n";
10975f757f3fSDimitry Andric         OS << "  enum " << shortType << " {\n";
10980b57cec5SDimitry Andric         for (; i != e; ++i)
10990b57cec5SDimitry Andric           OS << "    " << *i << ",\n";
11000b57cec5SDimitry Andric         OS << "    " << *e << "\n";
11010b57cec5SDimitry Andric         OS << "  };\n";
11025f757f3fSDimitry Andric       }
11030b57cec5SDimitry Andric       OS << "private:\n";
11040b57cec5SDimitry Andric 
11050b57cec5SDimitry Andric       VariadicArgument::writeDeclarations(OS);
11060b57cec5SDimitry Andric     }
11070b57cec5SDimitry Andric 
11080b57cec5SDimitry Andric     void writeDump(raw_ostream &OS) const override {
11090b57cec5SDimitry Andric       OS << "    for (" << getAttrName() << "Attr::" << getLowerName()
11100b57cec5SDimitry Andric          << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
11110b57cec5SDimitry Andric          << getLowerName() << "_end(); I != E; ++I) {\n";
11120b57cec5SDimitry Andric       OS << "      switch(*I) {\n";
11130b57cec5SDimitry Andric       for (const auto &UI : uniques) {
11145f757f3fSDimitry Andric         OS << "    case " << fullType << "::" << UI << ":\n";
11150b57cec5SDimitry Andric         OS << "      OS << \" " << UI << "\";\n";
11160b57cec5SDimitry Andric         OS << "      break;\n";
11170b57cec5SDimitry Andric       }
1118*0fca6ea1SDimitry Andric       if (!isCovered) {
1119*0fca6ea1SDimitry Andric         OS << "    default:\n";
1120*0fca6ea1SDimitry Andric         OS << "      llvm_unreachable(\"Invalid attribute value\");\n";
1121*0fca6ea1SDimitry Andric       }
11220b57cec5SDimitry Andric       OS << "      }\n";
11230b57cec5SDimitry Andric       OS << "    }\n";
11240b57cec5SDimitry Andric     }
11250b57cec5SDimitry Andric 
11260b57cec5SDimitry Andric     void writePCHReadDecls(raw_ostream &OS) const override {
11270b57cec5SDimitry Andric       OS << "    unsigned " << getLowerName() << "Size = Record.readInt();\n";
11285f757f3fSDimitry Andric       OS << "    SmallVector<" << fullType << ", 4> " << getLowerName()
11290b57cec5SDimitry Andric          << ";\n";
11300b57cec5SDimitry Andric       OS << "    " << getLowerName() << ".reserve(" << getLowerName()
11310b57cec5SDimitry Andric          << "Size);\n";
11320b57cec5SDimitry Andric       OS << "    for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
11335f757f3fSDimitry Andric       OS << "      " << getLowerName() << ".push_back("
11345f757f3fSDimitry Andric          << "static_cast<" << fullType << ">(Record.readInt()));\n";
11350b57cec5SDimitry Andric     }
11360b57cec5SDimitry Andric 
11370b57cec5SDimitry Andric     void writePCHWrite(raw_ostream &OS) const override {
11380b57cec5SDimitry Andric       OS << "    Record.push_back(SA->" << getLowerName() << "_size());\n";
11390b57cec5SDimitry Andric       OS << "    for (" << getAttrName() << "Attr::" << getLowerName()
11400b57cec5SDimitry Andric          << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
11410b57cec5SDimitry Andric          << getLowerName() << "_end(); i != e; ++i)\n";
11425f757f3fSDimitry Andric       OS << "      " << WritePCHRecord(fullType, "(*i)");
11430b57cec5SDimitry Andric     }
11440b57cec5SDimitry Andric 
11455ffd83dbSDimitry Andric     void writeConversion(raw_ostream &OS, bool Header) const {
11465ffd83dbSDimitry Andric       if (Header) {
11475f757f3fSDimitry Andric         OS << "  static bool ConvertStrTo" << shortType << "(StringRef Val, "
11485f757f3fSDimitry Andric            << fullType << " &Out);\n";
11495f757f3fSDimitry Andric         OS << "  static const char *Convert" << shortType << "ToStr("
11505f757f3fSDimitry Andric            << fullType << " Val);\n";
11515ffd83dbSDimitry Andric         return;
11525ffd83dbSDimitry Andric       }
11535ffd83dbSDimitry Andric 
11545f757f3fSDimitry Andric       OS << "bool " << getAttrName() << "Attr::ConvertStrTo" << shortType
11555ffd83dbSDimitry Andric          << "(StringRef Val, ";
11565f757f3fSDimitry Andric       OS << fullType << " &Out) {\n";
11575f757f3fSDimitry Andric       OS << "  std::optional<" << fullType
1158bdd1243dSDimitry Andric          << "> R = llvm::StringSwitch<std::optional<";
11595f757f3fSDimitry Andric       OS << fullType << ">>(Val)\n";
11600b57cec5SDimitry Andric       for (size_t I = 0; I < enums.size(); ++I) {
11610b57cec5SDimitry Andric         OS << "    .Case(\"" << values[I] << "\", ";
11625f757f3fSDimitry Andric         OS << fullType << "::" << enums[I] << ")\n";
11630b57cec5SDimitry Andric       }
11645f757f3fSDimitry Andric       OS << "    .Default(std::optional<" << fullType << ">());\n";
11650b57cec5SDimitry Andric       OS << "  if (R) {\n";
11660b57cec5SDimitry Andric       OS << "    Out = *R;\n      return true;\n    }\n";
11670b57cec5SDimitry Andric       OS << "  return false;\n";
11680b57cec5SDimitry Andric       OS << "}\n\n";
11690b57cec5SDimitry Andric 
11705f757f3fSDimitry Andric       OS << "const char *" << getAttrName() << "Attr::Convert" << shortType
11715f757f3fSDimitry Andric          << "ToStr(" << fullType << " Val) {\n"
11720b57cec5SDimitry Andric          << "  switch(Val) {\n";
11730b57cec5SDimitry Andric       SmallDenseSet<StringRef, 8> Uniques;
11740b57cec5SDimitry Andric       for (size_t I = 0; I < enums.size(); ++I) {
11750b57cec5SDimitry Andric         if (Uniques.insert(enums[I]).second)
11765f757f3fSDimitry Andric           OS << "  case " << fullType << "::" << enums[I] << ": return \""
11775f757f3fSDimitry Andric              << values[I] << "\";\n";
11780b57cec5SDimitry Andric       }
1179*0fca6ea1SDimitry Andric       if (!isCovered) {
1180*0fca6ea1SDimitry Andric         OS << "  default: llvm_unreachable(\"Invalid attribute value\");\n";
1181*0fca6ea1SDimitry Andric       }
11820b57cec5SDimitry Andric       OS << "  }\n"
11830b57cec5SDimitry Andric          << "  llvm_unreachable(\"No enumerator with that value\");\n"
11840b57cec5SDimitry Andric          << "}\n";
11850b57cec5SDimitry Andric     }
11860b57cec5SDimitry Andric   };
11870b57cec5SDimitry Andric 
11880b57cec5SDimitry Andric   class VersionArgument : public Argument {
11890b57cec5SDimitry Andric   public:
11900b57cec5SDimitry Andric     VersionArgument(const Record &Arg, StringRef Attr)
11910b57cec5SDimitry Andric       : Argument(Arg, Attr)
11920b57cec5SDimitry Andric     {}
11930b57cec5SDimitry Andric 
11940b57cec5SDimitry Andric     void writeAccessors(raw_ostream &OS) const override {
11950b57cec5SDimitry Andric       OS << "  VersionTuple get" << getUpperName() << "() const {\n";
11960b57cec5SDimitry Andric       OS << "    return " << getLowerName() << ";\n";
11970b57cec5SDimitry Andric       OS << "  }\n";
11980b57cec5SDimitry Andric       OS << "  void set" << getUpperName()
11990b57cec5SDimitry Andric          << "(ASTContext &C, VersionTuple V) {\n";
12000b57cec5SDimitry Andric       OS << "    " << getLowerName() << " = V;\n";
12010b57cec5SDimitry Andric       OS << "  }";
12020b57cec5SDimitry Andric     }
12030b57cec5SDimitry Andric 
12040b57cec5SDimitry Andric     void writeCloneArgs(raw_ostream &OS) const override {
12050b57cec5SDimitry Andric       OS << "get" << getUpperName() << "()";
12060b57cec5SDimitry Andric     }
12070b57cec5SDimitry Andric 
12080b57cec5SDimitry Andric     void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
12090b57cec5SDimitry Andric       OS << "A->get" << getUpperName() << "()";
12100b57cec5SDimitry Andric     }
12110b57cec5SDimitry Andric 
12120b57cec5SDimitry Andric     void writeCtorInitializers(raw_ostream &OS) const override {
12130b57cec5SDimitry Andric       OS << getLowerName() << "(" << getUpperName() << ")";
12140b57cec5SDimitry Andric     }
12150b57cec5SDimitry Andric 
12160b57cec5SDimitry Andric     void writeCtorDefaultInitializers(raw_ostream &OS) const override {
12170b57cec5SDimitry Andric       OS << getLowerName() << "()";
12180b57cec5SDimitry Andric     }
12190b57cec5SDimitry Andric 
12200b57cec5SDimitry Andric     void writeCtorParameters(raw_ostream &OS) const override {
12210b57cec5SDimitry Andric       OS << "VersionTuple " << getUpperName();
12220b57cec5SDimitry Andric     }
12230b57cec5SDimitry Andric 
12240b57cec5SDimitry Andric     void writeDeclarations(raw_ostream &OS) const override {
12250b57cec5SDimitry Andric       OS << "VersionTuple " << getLowerName() << ";\n";
12260b57cec5SDimitry Andric     }
12270b57cec5SDimitry Andric 
12280b57cec5SDimitry Andric     void writePCHReadDecls(raw_ostream &OS) const override {
12290b57cec5SDimitry Andric       OS << "    VersionTuple " << getLowerName()
12300b57cec5SDimitry Andric          << "= Record.readVersionTuple();\n";
12310b57cec5SDimitry Andric     }
12320b57cec5SDimitry Andric 
12330b57cec5SDimitry Andric     void writePCHReadArgs(raw_ostream &OS) const override {
12340b57cec5SDimitry Andric       OS << getLowerName();
12350b57cec5SDimitry Andric     }
12360b57cec5SDimitry Andric 
12370b57cec5SDimitry Andric     void writePCHWrite(raw_ostream &OS) const override {
12380b57cec5SDimitry Andric       OS << "    Record.AddVersionTuple(SA->get" << getUpperName() << "());\n";
12390b57cec5SDimitry Andric     }
12400b57cec5SDimitry Andric 
12410b57cec5SDimitry Andric     void writeValue(raw_ostream &OS) const override {
12420b57cec5SDimitry Andric       OS << getLowerName() << "=\" << get" << getUpperName() << "() << \"";
12430b57cec5SDimitry Andric     }
12440b57cec5SDimitry Andric 
12450b57cec5SDimitry Andric     void writeDump(raw_ostream &OS) const override {
12460b57cec5SDimitry Andric       OS << "    OS << \" \" << SA->get" << getUpperName() << "();\n";
12470b57cec5SDimitry Andric     }
12480b57cec5SDimitry Andric   };
12490b57cec5SDimitry Andric 
12500b57cec5SDimitry Andric   class ExprArgument : public SimpleArgument {
12510b57cec5SDimitry Andric   public:
12520b57cec5SDimitry Andric     ExprArgument(const Record &Arg, StringRef Attr)
12530b57cec5SDimitry Andric       : SimpleArgument(Arg, Attr, "Expr *")
12540b57cec5SDimitry Andric     {}
12550b57cec5SDimitry Andric 
12560b57cec5SDimitry Andric     void writeASTVisitorTraversal(raw_ostream &OS) const override {
12570b57cec5SDimitry Andric       OS << "  if (!"
12580b57cec5SDimitry Andric          << "getDerived().TraverseStmt(A->get" << getUpperName() << "()))\n";
12590b57cec5SDimitry Andric       OS << "    return false;\n";
12600b57cec5SDimitry Andric     }
12610b57cec5SDimitry Andric 
12620b57cec5SDimitry Andric     void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
12630b57cec5SDimitry Andric       OS << "tempInst" << getUpperName();
12640b57cec5SDimitry Andric     }
12650b57cec5SDimitry Andric 
12660b57cec5SDimitry Andric     void writeTemplateInstantiation(raw_ostream &OS) const override {
12670b57cec5SDimitry Andric       OS << "      " << getType() << " tempInst" << getUpperName() << ";\n";
12680b57cec5SDimitry Andric       OS << "      {\n";
12690b57cec5SDimitry Andric       OS << "        EnterExpressionEvaluationContext "
12700b57cec5SDimitry Andric          << "Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);\n";
12710b57cec5SDimitry Andric       OS << "        ExprResult " << "Result = S.SubstExpr("
12720b57cec5SDimitry Andric          << "A->get" << getUpperName() << "(), TemplateArgs);\n";
1273e8d8bef9SDimitry Andric       OS << "        if (Result.isInvalid())\n";
1274e8d8bef9SDimitry Andric       OS << "          return nullptr;\n";
1275e8d8bef9SDimitry Andric       OS << "        tempInst" << getUpperName() << " = Result.get();\n";
12760b57cec5SDimitry Andric       OS << "      }\n";
12770b57cec5SDimitry Andric     }
12780b57cec5SDimitry Andric 
1279bdd1243dSDimitry Andric     void writeValue(raw_ostream &OS) const override {
1280bdd1243dSDimitry Andric       OS << "\";\n";
1281bdd1243dSDimitry Andric       OS << "    get" << getUpperName()
1282bdd1243dSDimitry Andric          << "()->printPretty(OS, nullptr, Policy);\n";
1283bdd1243dSDimitry Andric       OS << "    OS << \"";
1284bdd1243dSDimitry Andric     }
1285bdd1243dSDimitry Andric 
12860b57cec5SDimitry Andric     void writeDump(raw_ostream &OS) const override {}
12870b57cec5SDimitry Andric 
12880b57cec5SDimitry Andric     void writeDumpChildren(raw_ostream &OS) const override {
12890b57cec5SDimitry Andric       OS << "    Visit(SA->get" << getUpperName() << "());\n";
12900b57cec5SDimitry Andric     }
12910b57cec5SDimitry Andric 
12920b57cec5SDimitry Andric     void writeHasChildren(raw_ostream &OS) const override { OS << "true"; }
12930b57cec5SDimitry Andric   };
12940b57cec5SDimitry Andric 
12950b57cec5SDimitry Andric   class VariadicExprArgument : public VariadicArgument {
12960b57cec5SDimitry Andric   public:
12970b57cec5SDimitry Andric     VariadicExprArgument(const Record &Arg, StringRef Attr)
12980b57cec5SDimitry Andric       : VariadicArgument(Arg, Attr, "Expr *")
12990b57cec5SDimitry Andric     {}
13000b57cec5SDimitry Andric 
130181ad6265SDimitry Andric     VariadicExprArgument(StringRef ArgName, StringRef Attr)
130281ad6265SDimitry Andric         : VariadicArgument(ArgName, Attr, "Expr *") {}
130381ad6265SDimitry Andric 
13040b57cec5SDimitry Andric     void writeASTVisitorTraversal(raw_ostream &OS) const override {
13050b57cec5SDimitry Andric       OS << "  {\n";
13060b57cec5SDimitry Andric       OS << "    " << getType() << " *I = A->" << getLowerName()
13070b57cec5SDimitry Andric          << "_begin();\n";
13080b57cec5SDimitry Andric       OS << "    " << getType() << " *E = A->" << getLowerName()
13090b57cec5SDimitry Andric          << "_end();\n";
13100b57cec5SDimitry Andric       OS << "    for (; I != E; ++I) {\n";
13110b57cec5SDimitry Andric       OS << "      if (!getDerived().TraverseStmt(*I))\n";
13120b57cec5SDimitry Andric       OS << "        return false;\n";
13130b57cec5SDimitry Andric       OS << "    }\n";
13140b57cec5SDimitry Andric       OS << "  }\n";
13150b57cec5SDimitry Andric     }
13160b57cec5SDimitry Andric 
13170b57cec5SDimitry Andric     void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
13180b57cec5SDimitry Andric       OS << "tempInst" << getUpperName() << ", "
13190b57cec5SDimitry Andric          << "A->" << getLowerName() << "_size()";
13200b57cec5SDimitry Andric     }
13210b57cec5SDimitry Andric 
13220b57cec5SDimitry Andric     void writeTemplateInstantiation(raw_ostream &OS) const override {
13230b57cec5SDimitry Andric       OS << "      auto *tempInst" << getUpperName()
13240b57cec5SDimitry Andric          << " = new (C, 16) " << getType()
13250b57cec5SDimitry Andric          << "[A->" << getLowerName() << "_size()];\n";
13260b57cec5SDimitry Andric       OS << "      {\n";
13270b57cec5SDimitry Andric       OS << "        EnterExpressionEvaluationContext "
13280b57cec5SDimitry Andric          << "Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);\n";
13290b57cec5SDimitry Andric       OS << "        " << getType() << " *TI = tempInst" << getUpperName()
13300b57cec5SDimitry Andric          << ";\n";
13310b57cec5SDimitry Andric       OS << "        " << getType() << " *I = A->" << getLowerName()
13320b57cec5SDimitry Andric          << "_begin();\n";
13330b57cec5SDimitry Andric       OS << "        " << getType() << " *E = A->" << getLowerName()
13340b57cec5SDimitry Andric          << "_end();\n";
13350b57cec5SDimitry Andric       OS << "        for (; I != E; ++I, ++TI) {\n";
13360b57cec5SDimitry Andric       OS << "          ExprResult Result = S.SubstExpr(*I, TemplateArgs);\n";
1337e8d8bef9SDimitry Andric       OS << "          if (Result.isInvalid())\n";
1338e8d8bef9SDimitry Andric       OS << "            return nullptr;\n";
1339e8d8bef9SDimitry Andric       OS << "          *TI = Result.get();\n";
13400b57cec5SDimitry Andric       OS << "        }\n";
13410b57cec5SDimitry Andric       OS << "      }\n";
13420b57cec5SDimitry Andric     }
13430b57cec5SDimitry Andric 
13440b57cec5SDimitry Andric     void writeDump(raw_ostream &OS) const override {}
13450b57cec5SDimitry Andric 
13460b57cec5SDimitry Andric     void writeDumpChildren(raw_ostream &OS) const override {
13470b57cec5SDimitry Andric       OS << "    for (" << getAttrName() << "Attr::" << getLowerName()
13480b57cec5SDimitry Andric          << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
13490b57cec5SDimitry Andric          << getLowerName() << "_end(); I != E; ++I)\n";
13500b57cec5SDimitry Andric       OS << "      Visit(*I);\n";
13510b57cec5SDimitry Andric     }
13520b57cec5SDimitry Andric 
13530b57cec5SDimitry Andric     void writeHasChildren(raw_ostream &OS) const override {
13540b57cec5SDimitry Andric       OS << "SA->" << getLowerName() << "_begin() != "
13550b57cec5SDimitry Andric          << "SA->" << getLowerName() << "_end()";
13560b57cec5SDimitry Andric     }
13570b57cec5SDimitry Andric   };
13580b57cec5SDimitry Andric 
13590b57cec5SDimitry Andric   class VariadicIdentifierArgument : public VariadicArgument {
13600b57cec5SDimitry Andric   public:
13610b57cec5SDimitry Andric     VariadicIdentifierArgument(const Record &Arg, StringRef Attr)
13620b57cec5SDimitry Andric       : VariadicArgument(Arg, Attr, "IdentifierInfo *")
13630b57cec5SDimitry Andric     {}
13640b57cec5SDimitry Andric   };
13650b57cec5SDimitry Andric 
13660b57cec5SDimitry Andric   class VariadicStringArgument : public VariadicArgument {
13670b57cec5SDimitry Andric   public:
13680b57cec5SDimitry Andric     VariadicStringArgument(const Record &Arg, StringRef Attr)
13690b57cec5SDimitry Andric       : VariadicArgument(Arg, Attr, "StringRef")
13700b57cec5SDimitry Andric     {}
13710b57cec5SDimitry Andric 
13720b57cec5SDimitry Andric     void writeCtorBody(raw_ostream &OS) const override {
13730b57cec5SDimitry Andric       OS << "  for (size_t I = 0, E = " << getArgSizeName() << "; I != E;\n"
13740b57cec5SDimitry Andric             "       ++I) {\n"
13750b57cec5SDimitry Andric             "    StringRef Ref = " << getUpperName() << "[I];\n"
13760b57cec5SDimitry Andric             "    if (!Ref.empty()) {\n"
13770b57cec5SDimitry Andric             "      char *Mem = new (Ctx, 1) char[Ref.size()];\n"
13780b57cec5SDimitry Andric             "      std::memcpy(Mem, Ref.data(), Ref.size());\n"
13790b57cec5SDimitry Andric             "      " << getArgName() << "[I] = StringRef(Mem, Ref.size());\n"
13800b57cec5SDimitry Andric             "    }\n"
13810b57cec5SDimitry Andric             "  }\n";
13820b57cec5SDimitry Andric     }
13830b57cec5SDimitry Andric 
13840b57cec5SDimitry Andric     void writeValueImpl(raw_ostream &OS) const override {
13850b57cec5SDimitry Andric       OS << "    OS << \"\\\"\" << Val << \"\\\"\";\n";
13860b57cec5SDimitry Andric     }
13870b57cec5SDimitry Andric   };
13880b57cec5SDimitry Andric 
13890b57cec5SDimitry Andric   class TypeArgument : public SimpleArgument {
13900b57cec5SDimitry Andric   public:
13910b57cec5SDimitry Andric     TypeArgument(const Record &Arg, StringRef Attr)
13920b57cec5SDimitry Andric       : SimpleArgument(Arg, Attr, "TypeSourceInfo *")
13930b57cec5SDimitry Andric     {}
13940b57cec5SDimitry Andric 
13950b57cec5SDimitry Andric     void writeAccessors(raw_ostream &OS) const override {
13960b57cec5SDimitry Andric       OS << "  QualType get" << getUpperName() << "() const {\n";
13970b57cec5SDimitry Andric       OS << "    return " << getLowerName() << "->getType();\n";
13980b57cec5SDimitry Andric       OS << "  }";
13990b57cec5SDimitry Andric       OS << "  " << getType() << " get" << getUpperName() << "Loc() const {\n";
14000b57cec5SDimitry Andric       OS << "    return " << getLowerName() << ";\n";
14010b57cec5SDimitry Andric       OS << "  }";
14020b57cec5SDimitry Andric     }
14030b57cec5SDimitry Andric 
14040b57cec5SDimitry Andric     void writeASTVisitorTraversal(raw_ostream &OS) const override {
14050b57cec5SDimitry Andric       OS << "  if (auto *TSI = A->get" << getUpperName() << "Loc())\n";
14060b57cec5SDimitry Andric       OS << "    if (!getDerived().TraverseTypeLoc(TSI->getTypeLoc()))\n";
14070b57cec5SDimitry Andric       OS << "      return false;\n";
14080b57cec5SDimitry Andric     }
14090b57cec5SDimitry Andric 
1410e8d8bef9SDimitry Andric     void writeTemplateInstantiation(raw_ostream &OS) const override {
1411e8d8bef9SDimitry Andric       OS << "      " << getType() << " tempInst" << getUpperName() << " =\n";
1412e8d8bef9SDimitry Andric       OS << "        S.SubstType(A->get" << getUpperName() << "Loc(), "
1413e8d8bef9SDimitry Andric          << "TemplateArgs, A->getLoc(), A->getAttrName());\n";
1414e8d8bef9SDimitry Andric       OS << "      if (!tempInst" << getUpperName() << ")\n";
1415e8d8bef9SDimitry Andric       OS << "        return nullptr;\n";
1416e8d8bef9SDimitry Andric     }
1417e8d8bef9SDimitry Andric 
14180b57cec5SDimitry Andric     void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
1419e8d8bef9SDimitry Andric       OS << "tempInst" << getUpperName();
14200b57cec5SDimitry Andric     }
14210b57cec5SDimitry Andric 
14220b57cec5SDimitry Andric     void writePCHWrite(raw_ostream &OS) const override {
14235ffd83dbSDimitry Andric       OS << "    "
14245ffd83dbSDimitry Andric          << WritePCHRecord(getType(),
14255ffd83dbSDimitry Andric                            "SA->get" + std::string(getUpperName()) + "Loc()");
14260b57cec5SDimitry Andric     }
14270b57cec5SDimitry Andric   };
14280b57cec5SDimitry Andric 
14297a6dacacSDimitry Andric   class WrappedAttr : public SimpleArgument {
14307a6dacacSDimitry Andric   public:
14317a6dacacSDimitry Andric     WrappedAttr(const Record &Arg, StringRef Attr)
14327a6dacacSDimitry Andric         : SimpleArgument(Arg, Attr, "Attr *") {}
14337a6dacacSDimitry Andric 
14347a6dacacSDimitry Andric     void writePCHReadDecls(raw_ostream &OS) const override {
14357a6dacacSDimitry Andric       OS << "    Attr *" << getLowerName() << " = Record.readAttr();";
14367a6dacacSDimitry Andric     }
14377a6dacacSDimitry Andric 
14387a6dacacSDimitry Andric     void writePCHWrite(raw_ostream &OS) const override {
14397a6dacacSDimitry Andric       OS << "    AddAttr(SA->get" << getUpperName() << "());";
14407a6dacacSDimitry Andric     }
14417a6dacacSDimitry Andric 
14427a6dacacSDimitry Andric     void writeDump(raw_ostream &OS) const override {}
14437a6dacacSDimitry Andric 
14447a6dacacSDimitry Andric     void writeDumpChildren(raw_ostream &OS) const override {
14457a6dacacSDimitry Andric       OS << "    Visit(SA->get" << getUpperName() << "());\n";
14467a6dacacSDimitry Andric     }
14477a6dacacSDimitry Andric 
14487a6dacacSDimitry Andric     void writeHasChildren(raw_ostream &OS) const override { OS << "true"; }
14497a6dacacSDimitry Andric   };
14507a6dacacSDimitry Andric 
14510b57cec5SDimitry Andric   } // end anonymous namespace
14520b57cec5SDimitry Andric 
14530b57cec5SDimitry Andric static std::unique_ptr<Argument>
14540b57cec5SDimitry Andric createArgument(const Record &Arg, StringRef Attr,
14550b57cec5SDimitry Andric                const Record *Search = nullptr) {
14560b57cec5SDimitry Andric   if (!Search)
14570b57cec5SDimitry Andric     Search = &Arg;
14580b57cec5SDimitry Andric 
14590b57cec5SDimitry Andric   std::unique_ptr<Argument> Ptr;
14600b57cec5SDimitry Andric   llvm::StringRef ArgName = Search->getName();
14610b57cec5SDimitry Andric 
14620b57cec5SDimitry Andric   if (ArgName == "AlignedArgument")
1463a7dea167SDimitry Andric     Ptr = std::make_unique<AlignedArgument>(Arg, Attr);
14640b57cec5SDimitry Andric   else if (ArgName == "EnumArgument")
1465a7dea167SDimitry Andric     Ptr = std::make_unique<EnumArgument>(Arg, Attr);
14660b57cec5SDimitry Andric   else if (ArgName == "ExprArgument")
1467a7dea167SDimitry Andric     Ptr = std::make_unique<ExprArgument>(Arg, Attr);
14685ffd83dbSDimitry Andric   else if (ArgName == "DeclArgument")
14695ffd83dbSDimitry Andric     Ptr = std::make_unique<SimpleArgument>(
14705ffd83dbSDimitry Andric         Arg, Attr, (Arg.getValueAsDef("Kind")->getName() + "Decl *").str());
14710b57cec5SDimitry Andric   else if (ArgName == "IdentifierArgument")
1472a7dea167SDimitry Andric     Ptr = std::make_unique<SimpleArgument>(Arg, Attr, "IdentifierInfo *");
14730b57cec5SDimitry Andric   else if (ArgName == "DefaultBoolArgument")
1474a7dea167SDimitry Andric     Ptr = std::make_unique<DefaultSimpleArgument>(
14750b57cec5SDimitry Andric         Arg, Attr, "bool", Arg.getValueAsBit("Default"));
14760b57cec5SDimitry Andric   else if (ArgName == "BoolArgument")
1477a7dea167SDimitry Andric     Ptr = std::make_unique<SimpleArgument>(Arg, Attr, "bool");
14780b57cec5SDimitry Andric   else if (ArgName == "DefaultIntArgument")
1479a7dea167SDimitry Andric     Ptr = std::make_unique<DefaultSimpleArgument>(
14800b57cec5SDimitry Andric         Arg, Attr, "int", Arg.getValueAsInt("Default"));
14810b57cec5SDimitry Andric   else if (ArgName == "IntArgument")
1482a7dea167SDimitry Andric     Ptr = std::make_unique<SimpleArgument>(Arg, Attr, "int");
14830b57cec5SDimitry Andric   else if (ArgName == "StringArgument")
1484a7dea167SDimitry Andric     Ptr = std::make_unique<StringArgument>(Arg, Attr);
14850b57cec5SDimitry Andric   else if (ArgName == "TypeArgument")
1486a7dea167SDimitry Andric     Ptr = std::make_unique<TypeArgument>(Arg, Attr);
14870b57cec5SDimitry Andric   else if (ArgName == "UnsignedArgument")
1488a7dea167SDimitry Andric     Ptr = std::make_unique<SimpleArgument>(Arg, Attr, "unsigned");
14890b57cec5SDimitry Andric   else if (ArgName == "VariadicUnsignedArgument")
1490a7dea167SDimitry Andric     Ptr = std::make_unique<VariadicArgument>(Arg, Attr, "unsigned");
14910b57cec5SDimitry Andric   else if (ArgName == "VariadicStringArgument")
1492a7dea167SDimitry Andric     Ptr = std::make_unique<VariadicStringArgument>(Arg, Attr);
14930b57cec5SDimitry Andric   else if (ArgName == "VariadicEnumArgument")
1494a7dea167SDimitry Andric     Ptr = std::make_unique<VariadicEnumArgument>(Arg, Attr);
14950b57cec5SDimitry Andric   else if (ArgName == "VariadicExprArgument")
1496a7dea167SDimitry Andric     Ptr = std::make_unique<VariadicExprArgument>(Arg, Attr);
14970b57cec5SDimitry Andric   else if (ArgName == "VariadicParamIdxArgument")
1498a7dea167SDimitry Andric     Ptr = std::make_unique<VariadicParamIdxArgument>(Arg, Attr);
14990b57cec5SDimitry Andric   else if (ArgName == "VariadicParamOrParamIdxArgument")
1500a7dea167SDimitry Andric     Ptr = std::make_unique<VariadicParamOrParamIdxArgument>(Arg, Attr);
15010b57cec5SDimitry Andric   else if (ArgName == "ParamIdxArgument")
1502a7dea167SDimitry Andric     Ptr = std::make_unique<SimpleArgument>(Arg, Attr, "ParamIdx");
15030b57cec5SDimitry Andric   else if (ArgName == "VariadicIdentifierArgument")
1504a7dea167SDimitry Andric     Ptr = std::make_unique<VariadicIdentifierArgument>(Arg, Attr);
15050b57cec5SDimitry Andric   else if (ArgName == "VersionArgument")
1506a7dea167SDimitry Andric     Ptr = std::make_unique<VersionArgument>(Arg, Attr);
15077a6dacacSDimitry Andric   else if (ArgName == "WrappedAttr")
15087a6dacacSDimitry Andric     Ptr = std::make_unique<WrappedAttr>(Arg, Attr);
15095ffd83dbSDimitry Andric   else if (ArgName == "OMPTraitInfoArgument")
15105ffd83dbSDimitry Andric     Ptr = std::make_unique<SimpleArgument>(Arg, Attr, "OMPTraitInfo *");
1511bdd1243dSDimitry Andric   else if (ArgName == "VariadicOMPInteropInfoArgument")
1512bdd1243dSDimitry Andric     Ptr = std::make_unique<VariadicOMPInteropInfoArgument>(Arg, Attr);
15130b57cec5SDimitry Andric 
15140b57cec5SDimitry Andric   if (!Ptr) {
15150b57cec5SDimitry Andric     // Search in reverse order so that the most-derived type is handled first.
15160b57cec5SDimitry Andric     ArrayRef<std::pair<Record*, SMRange>> Bases = Search->getSuperClasses();
15170b57cec5SDimitry Andric     for (const auto &Base : llvm::reverse(Bases)) {
15180b57cec5SDimitry Andric       if ((Ptr = createArgument(Arg, Attr, Base.first)))
15190b57cec5SDimitry Andric         break;
15200b57cec5SDimitry Andric     }
15210b57cec5SDimitry Andric   }
15220b57cec5SDimitry Andric 
15230b57cec5SDimitry Andric   if (Ptr && Arg.getValueAsBit("Optional"))
15240b57cec5SDimitry Andric     Ptr->setOptional(true);
15250b57cec5SDimitry Andric 
15260b57cec5SDimitry Andric   if (Ptr && Arg.getValueAsBit("Fake"))
15270b57cec5SDimitry Andric     Ptr->setFake(true);
15280b57cec5SDimitry Andric 
15290b57cec5SDimitry Andric   return Ptr;
15300b57cec5SDimitry Andric }
15310b57cec5SDimitry Andric 
15320b57cec5SDimitry Andric static void writeAvailabilityValue(raw_ostream &OS) {
15330b57cec5SDimitry Andric   OS << "\" << getPlatform()->getName();\n"
15340b57cec5SDimitry Andric      << "  if (getStrict()) OS << \", strict\";\n"
15350b57cec5SDimitry Andric      << "  if (!getIntroduced().empty()) OS << \", introduced=\" << getIntroduced();\n"
15360b57cec5SDimitry Andric      << "  if (!getDeprecated().empty()) OS << \", deprecated=\" << getDeprecated();\n"
15370b57cec5SDimitry Andric      << "  if (!getObsoleted().empty()) OS << \", obsoleted=\" << getObsoleted();\n"
15380b57cec5SDimitry Andric      << "  if (getUnavailable()) OS << \", unavailable\";\n"
15390b57cec5SDimitry Andric      << "  OS << \"";
15400b57cec5SDimitry Andric }
15410b57cec5SDimitry Andric 
15420b57cec5SDimitry Andric static void writeDeprecatedAttrValue(raw_ostream &OS, std::string &Variety) {
15430b57cec5SDimitry Andric   OS << "\\\"\" << getMessage() << \"\\\"\";\n";
15440b57cec5SDimitry Andric   // Only GNU deprecated has an optional fixit argument at the second position.
15450b57cec5SDimitry Andric   if (Variety == "GNU")
15460b57cec5SDimitry Andric      OS << "    if (!getReplacement().empty()) OS << \", \\\"\""
15470b57cec5SDimitry Andric            " << getReplacement() << \"\\\"\";\n";
15480b57cec5SDimitry Andric   OS << "    OS << \"";
15490b57cec5SDimitry Andric }
15500b57cec5SDimitry Andric 
15515ffd83dbSDimitry Andric static void writeGetSpellingFunction(const Record &R, raw_ostream &OS) {
15520b57cec5SDimitry Andric   std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
15530b57cec5SDimitry Andric 
15540b57cec5SDimitry Andric   OS << "const char *" << R.getName() << "Attr::getSpelling() const {\n";
15550b57cec5SDimitry Andric   if (Spellings.empty()) {
15560b57cec5SDimitry Andric     OS << "  return \"(No spelling)\";\n}\n\n";
15570b57cec5SDimitry Andric     return;
15580b57cec5SDimitry Andric   }
15590b57cec5SDimitry Andric 
1560a7dea167SDimitry Andric   OS << "  switch (getAttributeSpellingListIndex()) {\n"
15610b57cec5SDimitry Andric         "  default:\n"
15620b57cec5SDimitry Andric         "    llvm_unreachable(\"Unknown attribute spelling!\");\n"
15630b57cec5SDimitry Andric         "    return \"(No spelling)\";\n";
15640b57cec5SDimitry Andric 
15650b57cec5SDimitry Andric   for (unsigned I = 0; I < Spellings.size(); ++I)
15660b57cec5SDimitry Andric     OS << "  case " << I << ":\n"
15670b57cec5SDimitry Andric           "    return \"" << Spellings[I].name() << "\";\n";
15680b57cec5SDimitry Andric   // End of the switch statement.
15690b57cec5SDimitry Andric   OS << "  }\n";
15700b57cec5SDimitry Andric   // End of the getSpelling function.
15710b57cec5SDimitry Andric   OS << "}\n\n";
15720b57cec5SDimitry Andric }
15730b57cec5SDimitry Andric 
15740b57cec5SDimitry Andric static void
15755ffd83dbSDimitry Andric writePrettyPrintFunction(const Record &R,
15760b57cec5SDimitry Andric                          const std::vector<std::unique_ptr<Argument>> &Args,
15770b57cec5SDimitry Andric                          raw_ostream &OS) {
15780b57cec5SDimitry Andric   std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
15790b57cec5SDimitry Andric 
15800b57cec5SDimitry Andric   OS << "void " << R.getName() << "Attr::printPretty("
15810b57cec5SDimitry Andric     << "raw_ostream &OS, const PrintingPolicy &Policy) const {\n";
15820b57cec5SDimitry Andric 
15830b57cec5SDimitry Andric   if (Spellings.empty()) {
15840b57cec5SDimitry Andric     OS << "}\n\n";
15850b57cec5SDimitry Andric     return;
15860b57cec5SDimitry Andric   }
15870b57cec5SDimitry Andric 
1588fe6060f1SDimitry Andric   OS << "  bool IsFirstArgument = true; (void)IsFirstArgument;\n"
1589fe6060f1SDimitry Andric      << "  unsigned TrailingOmittedArgs = 0; (void)TrailingOmittedArgs;\n"
1590fe6060f1SDimitry Andric      << "  switch (getAttributeSpellingListIndex()) {\n"
1591fe6060f1SDimitry Andric      << "  default:\n"
1592fe6060f1SDimitry Andric      << "    llvm_unreachable(\"Unknown attribute spelling!\");\n"
1593fe6060f1SDimitry Andric      << "    break;\n";
15940b57cec5SDimitry Andric 
15950b57cec5SDimitry Andric   for (unsigned I = 0; I < Spellings.size(); ++ I) {
15960b57cec5SDimitry Andric     llvm::SmallString<16> Prefix;
15970b57cec5SDimitry Andric     llvm::SmallString<8> Suffix;
15980b57cec5SDimitry Andric     // The actual spelling of the name and namespace (if applicable)
15990b57cec5SDimitry Andric     // of an attribute without considering prefix and suffix.
16000b57cec5SDimitry Andric     llvm::SmallString<64> Spelling;
16010b57cec5SDimitry Andric     std::string Name = Spellings[I].name();
16020b57cec5SDimitry Andric     std::string Variety = Spellings[I].variety();
16030b57cec5SDimitry Andric 
16040b57cec5SDimitry Andric     if (Variety == "GNU") {
16050b57cec5SDimitry Andric       Prefix = "__attribute__((";
16060b57cec5SDimitry Andric       Suffix = "))";
16075f757f3fSDimitry Andric     } else if (Variety == "CXX11" || Variety == "C23") {
16080b57cec5SDimitry Andric       Prefix = "[[";
16090b57cec5SDimitry Andric       Suffix = "]]";
16100b57cec5SDimitry Andric       std::string Namespace = Spellings[I].nameSpace();
16110b57cec5SDimitry Andric       if (!Namespace.empty()) {
16120b57cec5SDimitry Andric         Spelling += Namespace;
16130b57cec5SDimitry Andric         Spelling += "::";
16140b57cec5SDimitry Andric       }
16150b57cec5SDimitry Andric     } else if (Variety == "Declspec") {
16160b57cec5SDimitry Andric       Prefix = "__declspec(";
16170b57cec5SDimitry Andric       Suffix = ")";
16180b57cec5SDimitry Andric     } else if (Variety == "Microsoft") {
16190b57cec5SDimitry Andric       Prefix = "[";
16200b57cec5SDimitry Andric       Suffix = "]";
16210b57cec5SDimitry Andric     } else if (Variety == "Keyword") {
16220b57cec5SDimitry Andric       Prefix = "";
16230b57cec5SDimitry Andric       Suffix = "";
16240b57cec5SDimitry Andric     } else if (Variety == "Pragma") {
16250b57cec5SDimitry Andric       Prefix = "#pragma ";
16260b57cec5SDimitry Andric       Suffix = "\n";
16270b57cec5SDimitry Andric       std::string Namespace = Spellings[I].nameSpace();
16280b57cec5SDimitry Andric       if (!Namespace.empty()) {
16290b57cec5SDimitry Andric         Spelling += Namespace;
16300b57cec5SDimitry Andric         Spelling += " ";
16310b57cec5SDimitry Andric       }
1632*0fca6ea1SDimitry Andric     } else if (Variety == "HLSLAnnotation") {
163381ad6265SDimitry Andric       Prefix = ":";
163481ad6265SDimitry Andric       Suffix = "";
16350b57cec5SDimitry Andric     } else {
16360b57cec5SDimitry Andric       llvm_unreachable("Unknown attribute syntax variety!");
16370b57cec5SDimitry Andric     }
16380b57cec5SDimitry Andric 
16390b57cec5SDimitry Andric     Spelling += Name;
16400b57cec5SDimitry Andric 
1641fe6060f1SDimitry Andric     OS << "  case " << I << " : {\n"
1642fe6060f1SDimitry Andric        << "    OS << \"" << Prefix << Spelling << "\";\n";
16430b57cec5SDimitry Andric 
16440b57cec5SDimitry Andric     if (Variety == "Pragma") {
16450b57cec5SDimitry Andric       OS << "    printPrettyPragma(OS, Policy);\n";
16460b57cec5SDimitry Andric       OS << "    OS << \"\\n\";";
16470b57cec5SDimitry Andric       OS << "    break;\n";
16480b57cec5SDimitry Andric       OS << "  }\n";
16490b57cec5SDimitry Andric       continue;
16500b57cec5SDimitry Andric     }
16510b57cec5SDimitry Andric 
16520b57cec5SDimitry Andric     if (Spelling == "availability") {
1653fe6060f1SDimitry Andric       OS << "    OS << \"(";
16540b57cec5SDimitry Andric       writeAvailabilityValue(OS);
1655fe6060f1SDimitry Andric       OS << ")\";\n";
16560b57cec5SDimitry Andric     } else if (Spelling == "deprecated" || Spelling == "gnu::deprecated") {
1657fe6060f1SDimitry Andric       OS << "    OS << \"(";
16580b57cec5SDimitry Andric       writeDeprecatedAttrValue(OS, Variety);
1659fe6060f1SDimitry Andric       OS << ")\";\n";
16600b57cec5SDimitry Andric     } else {
16610b57cec5SDimitry Andric       // To avoid printing parentheses around an empty argument list or
16620b57cec5SDimitry Andric       // printing spurious commas at the end of an argument list, we need to
16630b57cec5SDimitry Andric       // determine where the last provided non-fake argument is.
16640b57cec5SDimitry Andric       bool FoundNonOptArg = false;
16650b57cec5SDimitry Andric       for (const auto &arg : llvm::reverse(Args)) {
16660b57cec5SDimitry Andric         if (arg->isFake())
16670b57cec5SDimitry Andric           continue;
16680b57cec5SDimitry Andric         if (FoundNonOptArg)
16690b57cec5SDimitry Andric           continue;
16700b57cec5SDimitry Andric         // FIXME: arg->getIsOmitted() == "false" means we haven't implemented
16710b57cec5SDimitry Andric         // any way to detect whether the argument was omitted.
16720b57cec5SDimitry Andric         if (!arg->isOptional() || arg->getIsOmitted() == "false") {
16730b57cec5SDimitry Andric           FoundNonOptArg = true;
16740b57cec5SDimitry Andric           continue;
16750b57cec5SDimitry Andric         }
16760b57cec5SDimitry Andric         OS << "    if (" << arg->getIsOmitted() << ")\n"
16770b57cec5SDimitry Andric            << "      ++TrailingOmittedArgs;\n";
16780b57cec5SDimitry Andric       }
16790b57cec5SDimitry Andric       unsigned ArgIndex = 0;
16800b57cec5SDimitry Andric       for (const auto &arg : Args) {
16810b57cec5SDimitry Andric         if (arg->isFake())
16820b57cec5SDimitry Andric           continue;
16830b57cec5SDimitry Andric         std::string IsOmitted = arg->getIsOmitted();
16840b57cec5SDimitry Andric         if (arg->isOptional() && IsOmitted != "false")
1685fe6060f1SDimitry Andric           OS << "    if (!(" << IsOmitted << ")) {\n";
1686fe6060f1SDimitry Andric         // Variadic arguments print their own leading comma.
1687fe6060f1SDimitry Andric         if (!arg->isVariadic())
1688fe6060f1SDimitry Andric           OS << "    DelimitAttributeArgument(OS, IsFirstArgument);\n";
1689fe6060f1SDimitry Andric         OS << "    OS << \"";
16900b57cec5SDimitry Andric         arg->writeValue(OS);
1691fe6060f1SDimitry Andric         OS << "\";\n";
16920b57cec5SDimitry Andric         if (arg->isOptional() && IsOmitted != "false")
1693fe6060f1SDimitry Andric           OS << "    }\n";
16940b57cec5SDimitry Andric         ++ArgIndex;
16950b57cec5SDimitry Andric       }
1696fe6060f1SDimitry Andric       if (ArgIndex != 0)
1697fe6060f1SDimitry Andric         OS << "    if (!IsFirstArgument)\n"
1698fe6060f1SDimitry Andric            << "      OS << \")\";\n";
16990b57cec5SDimitry Andric     }
1700fe6060f1SDimitry Andric     OS << "    OS << \"" << Suffix << "\";\n"
1701fe6060f1SDimitry Andric        << "    break;\n"
1702fe6060f1SDimitry Andric        << "  }\n";
17030b57cec5SDimitry Andric   }
17040b57cec5SDimitry Andric 
17050b57cec5SDimitry Andric   // End of the switch statement.
17060b57cec5SDimitry Andric   OS << "}\n";
17070b57cec5SDimitry Andric   // End of the print function.
17080b57cec5SDimitry Andric   OS << "}\n\n";
17090b57cec5SDimitry Andric }
17100b57cec5SDimitry Andric 
17110b57cec5SDimitry Andric /// Return the index of a spelling in a spelling list.
17120b57cec5SDimitry Andric static unsigned
17130b57cec5SDimitry Andric getSpellingListIndex(const std::vector<FlattenedSpelling> &SpellingList,
17140b57cec5SDimitry Andric                      const FlattenedSpelling &Spelling) {
17150b57cec5SDimitry Andric   assert(!SpellingList.empty() && "Spelling list is empty!");
17160b57cec5SDimitry Andric 
17170b57cec5SDimitry Andric   for (unsigned Index = 0; Index < SpellingList.size(); ++Index) {
17180b57cec5SDimitry Andric     const FlattenedSpelling &S = SpellingList[Index];
17190b57cec5SDimitry Andric     if (S.variety() != Spelling.variety())
17200b57cec5SDimitry Andric       continue;
17210b57cec5SDimitry Andric     if (S.nameSpace() != Spelling.nameSpace())
17220b57cec5SDimitry Andric       continue;
17230b57cec5SDimitry Andric     if (S.name() != Spelling.name())
17240b57cec5SDimitry Andric       continue;
17250b57cec5SDimitry Andric 
17260b57cec5SDimitry Andric     return Index;
17270b57cec5SDimitry Andric   }
17280b57cec5SDimitry Andric 
17290b57cec5SDimitry Andric   llvm_unreachable("Unknown spelling!");
17300b57cec5SDimitry Andric }
17310b57cec5SDimitry Andric 
17320b57cec5SDimitry Andric static void writeAttrAccessorDefinition(const Record &R, raw_ostream &OS) {
17330b57cec5SDimitry Andric   std::vector<Record*> Accessors = R.getValueAsListOfDefs("Accessors");
17340b57cec5SDimitry Andric   if (Accessors.empty())
17350b57cec5SDimitry Andric     return;
17360b57cec5SDimitry Andric 
17370b57cec5SDimitry Andric   const std::vector<FlattenedSpelling> SpellingList = GetFlattenedSpellings(R);
17380b57cec5SDimitry Andric   assert(!SpellingList.empty() &&
17390b57cec5SDimitry Andric          "Attribute with empty spelling list can't have accessors!");
17400b57cec5SDimitry Andric   for (const auto *Accessor : Accessors) {
17410b57cec5SDimitry Andric     const StringRef Name = Accessor->getValueAsString("Name");
17420b57cec5SDimitry Andric     std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Accessor);
17430b57cec5SDimitry Andric 
1744a7dea167SDimitry Andric     OS << "  bool " << Name
1745a7dea167SDimitry Andric        << "() const { return getAttributeSpellingListIndex() == ";
17460b57cec5SDimitry Andric     for (unsigned Index = 0; Index < Spellings.size(); ++Index) {
17470b57cec5SDimitry Andric       OS << getSpellingListIndex(SpellingList, Spellings[Index]);
17480b57cec5SDimitry Andric       if (Index != Spellings.size() - 1)
1749a7dea167SDimitry Andric         OS << " ||\n    getAttributeSpellingListIndex() == ";
17500b57cec5SDimitry Andric       else
17510b57cec5SDimitry Andric         OS << "; }\n";
17520b57cec5SDimitry Andric     }
17530b57cec5SDimitry Andric   }
17540b57cec5SDimitry Andric }
17550b57cec5SDimitry Andric 
17560b57cec5SDimitry Andric static bool
17570b57cec5SDimitry Andric SpellingNamesAreCommon(const std::vector<FlattenedSpelling>& Spellings) {
17580b57cec5SDimitry Andric   assert(!Spellings.empty() && "An empty list of spellings was provided");
17595ffd83dbSDimitry Andric   std::string FirstName =
17605ffd83dbSDimitry Andric       std::string(NormalizeNameForSpellingComparison(Spellings.front().name()));
17617a6dacacSDimitry Andric   for (const auto &Spelling : llvm::drop_begin(Spellings)) {
17625ffd83dbSDimitry Andric     std::string Name =
17635ffd83dbSDimitry Andric         std::string(NormalizeNameForSpellingComparison(Spelling.name()));
17640b57cec5SDimitry Andric     if (Name != FirstName)
17650b57cec5SDimitry Andric       return false;
17660b57cec5SDimitry Andric   }
17670b57cec5SDimitry Andric   return true;
17680b57cec5SDimitry Andric }
17690b57cec5SDimitry Andric 
17700b57cec5SDimitry Andric typedef std::map<unsigned, std::string> SemanticSpellingMap;
17710b57cec5SDimitry Andric static std::string
17720b57cec5SDimitry Andric CreateSemanticSpellings(const std::vector<FlattenedSpelling> &Spellings,
17730b57cec5SDimitry Andric                         SemanticSpellingMap &Map) {
17740b57cec5SDimitry Andric   // The enumerants are automatically generated based on the variety,
17750b57cec5SDimitry Andric   // namespace (if present) and name for each attribute spelling. However,
17760b57cec5SDimitry Andric   // care is taken to avoid trampling on the reserved namespace due to
17770b57cec5SDimitry Andric   // underscores.
17780b57cec5SDimitry Andric   std::string Ret("  enum Spelling {\n");
17790b57cec5SDimitry Andric   std::set<std::string> Uniques;
17800b57cec5SDimitry Andric   unsigned Idx = 0;
1781a7dea167SDimitry Andric 
1782a7dea167SDimitry Andric   // If we have a need to have this many spellings we likely need to add an
1783a7dea167SDimitry Andric   // extra bit to the SpellingIndex in AttributeCommonInfo, then increase the
1784a7dea167SDimitry Andric   // value of SpellingNotCalculated there and here.
1785a7dea167SDimitry Andric   assert(Spellings.size() < 15 &&
1786a7dea167SDimitry Andric          "Too many spellings, would step on SpellingNotCalculated in "
1787a7dea167SDimitry Andric          "AttributeCommonInfo");
17880b57cec5SDimitry Andric   for (auto I = Spellings.begin(), E = Spellings.end(); I != E; ++I, ++Idx) {
17890b57cec5SDimitry Andric     const FlattenedSpelling &S = *I;
17900b57cec5SDimitry Andric     const std::string &Variety = S.variety();
17910b57cec5SDimitry Andric     const std::string &Spelling = S.name();
17920b57cec5SDimitry Andric     const std::string &Namespace = S.nameSpace();
17930b57cec5SDimitry Andric     std::string EnumName;
17940b57cec5SDimitry Andric 
17950b57cec5SDimitry Andric     EnumName += (Variety + "_");
17960b57cec5SDimitry Andric     if (!Namespace.empty())
17970b57cec5SDimitry Andric       EnumName += (NormalizeNameForSpellingComparison(Namespace).str() +
17980b57cec5SDimitry Andric       "_");
17990b57cec5SDimitry Andric     EnumName += NormalizeNameForSpellingComparison(Spelling);
18000b57cec5SDimitry Andric 
18010b57cec5SDimitry Andric     // Even if the name is not unique, this spelling index corresponds to a
18020b57cec5SDimitry Andric     // particular enumerant name that we've calculated.
18030b57cec5SDimitry Andric     Map[Idx] = EnumName;
18040b57cec5SDimitry Andric 
18050b57cec5SDimitry Andric     // Since we have been stripping underscores to avoid trampling on the
18060b57cec5SDimitry Andric     // reserved namespace, we may have inadvertently created duplicate
18070b57cec5SDimitry Andric     // enumerant names. These duplicates are not considered part of the
18080b57cec5SDimitry Andric     // semantic spelling, and can be elided.
18090b57cec5SDimitry Andric     if (Uniques.find(EnumName) != Uniques.end())
18100b57cec5SDimitry Andric       continue;
18110b57cec5SDimitry Andric 
18120b57cec5SDimitry Andric     Uniques.insert(EnumName);
18130b57cec5SDimitry Andric     if (I != Spellings.begin())
18140b57cec5SDimitry Andric       Ret += ",\n";
18150b57cec5SDimitry Andric     // Duplicate spellings are not considered part of the semantic spelling
18160b57cec5SDimitry Andric     // enumeration, but the spelling index and semantic spelling values are
18170b57cec5SDimitry Andric     // meant to be equivalent, so we must specify a concrete value for each
18180b57cec5SDimitry Andric     // enumerator.
18190b57cec5SDimitry Andric     Ret += "    " + EnumName + " = " + llvm::utostr(Idx);
18200b57cec5SDimitry Andric   }
1821a7dea167SDimitry Andric   Ret += ",\n  SpellingNotCalculated = 15\n";
18220b57cec5SDimitry Andric   Ret += "\n  };\n\n";
18230b57cec5SDimitry Andric   return Ret;
18240b57cec5SDimitry Andric }
18250b57cec5SDimitry Andric 
18260b57cec5SDimitry Andric void WriteSemanticSpellingSwitch(const std::string &VarName,
18270b57cec5SDimitry Andric                                  const SemanticSpellingMap &Map,
18280b57cec5SDimitry Andric                                  raw_ostream &OS) {
18290b57cec5SDimitry Andric   OS << "  switch (" << VarName << ") {\n    default: "
18300b57cec5SDimitry Andric     << "llvm_unreachable(\"Unknown spelling list index\");\n";
18310b57cec5SDimitry Andric   for (const auto &I : Map)
18320b57cec5SDimitry Andric     OS << "    case " << I.first << ": return " << I.second << ";\n";
18330b57cec5SDimitry Andric   OS << "  }\n";
18340b57cec5SDimitry Andric }
18350b57cec5SDimitry Andric 
1836*0fca6ea1SDimitry Andric // Note: these values need to match the values used by LateAttrParseKind in
1837*0fca6ea1SDimitry Andric // `Attr.td`
1838*0fca6ea1SDimitry Andric enum class LateAttrParseKind { Never = 0, Standard = 1, ExperimentalExt = 2 };
1839*0fca6ea1SDimitry Andric 
1840*0fca6ea1SDimitry Andric static LateAttrParseKind getLateAttrParseKind(const Record *Attr) {
1841*0fca6ea1SDimitry Andric   // This function basically does
1842*0fca6ea1SDimitry Andric   // `Attr->getValueAsDef("LateParsed")->getValueAsInt("Kind")` but does a bunch
1843*0fca6ea1SDimitry Andric   // of sanity checking to ensure that `LateAttrParseMode` in `Attr.td` is in
1844*0fca6ea1SDimitry Andric   // sync with the `LateAttrParseKind` enum in this source file.
1845*0fca6ea1SDimitry Andric 
1846*0fca6ea1SDimitry Andric   static constexpr StringRef LateParsedStr = "LateParsed";
1847*0fca6ea1SDimitry Andric   static constexpr StringRef LateAttrParseKindStr = "LateAttrParseKind";
1848*0fca6ea1SDimitry Andric   static constexpr StringRef KindFieldStr = "Kind";
1849*0fca6ea1SDimitry Andric 
1850*0fca6ea1SDimitry Andric   auto *LAPK = Attr->getValueAsDef(LateParsedStr);
1851*0fca6ea1SDimitry Andric 
1852*0fca6ea1SDimitry Andric   // Typecheck the `LateParsed` field.
1853*0fca6ea1SDimitry Andric   SmallVector<Record *, 1> SuperClasses;
1854*0fca6ea1SDimitry Andric   LAPK->getDirectSuperClasses(SuperClasses);
1855*0fca6ea1SDimitry Andric   if (SuperClasses.size() != 1)
1856*0fca6ea1SDimitry Andric     PrintFatalError(Attr, "Field `" + llvm::Twine(LateParsedStr) +
1857*0fca6ea1SDimitry Andric                               "`should only have one super class");
1858*0fca6ea1SDimitry Andric 
1859*0fca6ea1SDimitry Andric   if (SuperClasses[0]->getName() != LateAttrParseKindStr)
1860*0fca6ea1SDimitry Andric     PrintFatalError(Attr, "Field `" + llvm::Twine(LateParsedStr) +
1861*0fca6ea1SDimitry Andric                               "`should only have type `" +
1862*0fca6ea1SDimitry Andric                               llvm::Twine(LateAttrParseKindStr) +
1863*0fca6ea1SDimitry Andric                               "` but found type `" +
1864*0fca6ea1SDimitry Andric                               SuperClasses[0]->getName() + "`");
1865*0fca6ea1SDimitry Andric 
1866*0fca6ea1SDimitry Andric   // Get Kind and verify the enum name matches the name in `Attr.td`.
1867*0fca6ea1SDimitry Andric   unsigned Kind = LAPK->getValueAsInt(KindFieldStr);
1868*0fca6ea1SDimitry Andric   switch (LateAttrParseKind(Kind)) {
1869*0fca6ea1SDimitry Andric #define CASE(X)                                                                \
1870*0fca6ea1SDimitry Andric   case LateAttrParseKind::X:                                                   \
1871*0fca6ea1SDimitry Andric     if (LAPK->getName().compare("LateAttrParse" #X) != 0) {                    \
1872*0fca6ea1SDimitry Andric       PrintFatalError(Attr,                                                    \
1873*0fca6ea1SDimitry Andric                       "Field `" + llvm::Twine(LateParsedStr) + "` set to `" +  \
1874*0fca6ea1SDimitry Andric                           LAPK->getName() +                                    \
1875*0fca6ea1SDimitry Andric                           "` but this converts to `LateAttrParseKind::" +      \
1876*0fca6ea1SDimitry Andric                           llvm::Twine(#X) + "`");                              \
1877*0fca6ea1SDimitry Andric     }                                                                          \
1878*0fca6ea1SDimitry Andric     return LateAttrParseKind::X;
1879*0fca6ea1SDimitry Andric 
1880*0fca6ea1SDimitry Andric     CASE(Never)
1881*0fca6ea1SDimitry Andric     CASE(Standard)
1882*0fca6ea1SDimitry Andric     CASE(ExperimentalExt)
1883*0fca6ea1SDimitry Andric #undef CASE
1884*0fca6ea1SDimitry Andric   }
1885*0fca6ea1SDimitry Andric 
1886*0fca6ea1SDimitry Andric   // The Kind value is completely invalid
1887*0fca6ea1SDimitry Andric   auto KindValueStr = llvm::utostr(Kind);
1888*0fca6ea1SDimitry Andric   PrintFatalError(Attr, "Field `" + llvm::Twine(LateParsedStr) + "` set to `" +
1889*0fca6ea1SDimitry Andric                             LAPK->getName() + "` has unexpected `" +
1890*0fca6ea1SDimitry Andric                             llvm::Twine(KindFieldStr) + "` value of " +
1891*0fca6ea1SDimitry Andric                             KindValueStr);
1892*0fca6ea1SDimitry Andric }
1893*0fca6ea1SDimitry Andric 
18940b57cec5SDimitry Andric // Emits the LateParsed property for attributes.
1895*0fca6ea1SDimitry Andric static void emitClangAttrLateParsedListImpl(RecordKeeper &Records,
1896*0fca6ea1SDimitry Andric                                             raw_ostream &OS,
1897*0fca6ea1SDimitry Andric                                             LateAttrParseKind LateParseMode) {
18980b57cec5SDimitry Andric   std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
18990b57cec5SDimitry Andric 
19000b57cec5SDimitry Andric   for (const auto *Attr : Attrs) {
1901*0fca6ea1SDimitry Andric     if (LateAttrParseKind LateParsed = getLateAttrParseKind(Attr);
1902*0fca6ea1SDimitry Andric         LateParsed != LateParseMode)
1903*0fca6ea1SDimitry Andric       continue;
19040b57cec5SDimitry Andric 
19050b57cec5SDimitry Andric     std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr);
19060b57cec5SDimitry Andric 
19070b57cec5SDimitry Andric     // FIXME: Handle non-GNU attributes
19080b57cec5SDimitry Andric     for (const auto &I : Spellings) {
19090b57cec5SDimitry Andric       if (I.variety() != "GNU")
19100b57cec5SDimitry Andric         continue;
1911*0fca6ea1SDimitry Andric       OS << ".Case(\"" << I.name() << "\", 1)\n";
19120b57cec5SDimitry Andric     }
19130b57cec5SDimitry Andric   }
19140b57cec5SDimitry Andric }
1915*0fca6ea1SDimitry Andric 
1916*0fca6ea1SDimitry Andric static void emitClangAttrLateParsedList(RecordKeeper &Records,
1917*0fca6ea1SDimitry Andric                                         raw_ostream &OS) {
1918*0fca6ea1SDimitry Andric   OS << "#if defined(CLANG_ATTR_LATE_PARSED_LIST)\n";
1919*0fca6ea1SDimitry Andric   emitClangAttrLateParsedListImpl(Records, OS, LateAttrParseKind::Standard);
19200b57cec5SDimitry Andric   OS << "#endif // CLANG_ATTR_LATE_PARSED_LIST\n\n";
19210b57cec5SDimitry Andric }
19220b57cec5SDimitry Andric 
1923*0fca6ea1SDimitry Andric static void emitClangAttrLateParsedExperimentalList(RecordKeeper &Records,
1924*0fca6ea1SDimitry Andric                                                     raw_ostream &OS) {
1925*0fca6ea1SDimitry Andric   OS << "#if defined(CLANG_ATTR_LATE_PARSED_EXPERIMENTAL_EXT_LIST)\n";
1926*0fca6ea1SDimitry Andric   emitClangAttrLateParsedListImpl(Records, OS,
1927*0fca6ea1SDimitry Andric                                   LateAttrParseKind::ExperimentalExt);
1928*0fca6ea1SDimitry Andric   OS << "#endif // CLANG_ATTR_LATE_PARSED_EXPERIMENTAL_EXT_LIST\n\n";
1929*0fca6ea1SDimitry Andric }
1930*0fca6ea1SDimitry Andric 
19310b57cec5SDimitry Andric static bool hasGNUorCXX11Spelling(const Record &Attribute) {
19320b57cec5SDimitry Andric   std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attribute);
19330b57cec5SDimitry Andric   for (const auto &I : Spellings) {
19340b57cec5SDimitry Andric     if (I.variety() == "GNU" || I.variety() == "CXX11")
19350b57cec5SDimitry Andric       return true;
19360b57cec5SDimitry Andric   }
19370b57cec5SDimitry Andric   return false;
19380b57cec5SDimitry Andric }
19390b57cec5SDimitry Andric 
19400b57cec5SDimitry Andric namespace {
19410b57cec5SDimitry Andric 
19420b57cec5SDimitry Andric struct AttributeSubjectMatchRule {
19430b57cec5SDimitry Andric   const Record *MetaSubject;
19440b57cec5SDimitry Andric   const Record *Constraint;
19450b57cec5SDimitry Andric 
19460b57cec5SDimitry Andric   AttributeSubjectMatchRule(const Record *MetaSubject, const Record *Constraint)
19470b57cec5SDimitry Andric       : MetaSubject(MetaSubject), Constraint(Constraint) {
19480b57cec5SDimitry Andric     assert(MetaSubject && "Missing subject");
19490b57cec5SDimitry Andric   }
19500b57cec5SDimitry Andric 
19510b57cec5SDimitry Andric   bool isSubRule() const { return Constraint != nullptr; }
19520b57cec5SDimitry Andric 
19530b57cec5SDimitry Andric   std::vector<Record *> getSubjects() const {
19540b57cec5SDimitry Andric     return (Constraint ? Constraint : MetaSubject)
19550b57cec5SDimitry Andric         ->getValueAsListOfDefs("Subjects");
19560b57cec5SDimitry Andric   }
19570b57cec5SDimitry Andric 
19580b57cec5SDimitry Andric   std::vector<Record *> getLangOpts() const {
19590b57cec5SDimitry Andric     if (Constraint) {
19600b57cec5SDimitry Andric       // Lookup the options in the sub-rule first, in case the sub-rule
19610b57cec5SDimitry Andric       // overrides the rules options.
19620b57cec5SDimitry Andric       std::vector<Record *> Opts = Constraint->getValueAsListOfDefs("LangOpts");
19630b57cec5SDimitry Andric       if (!Opts.empty())
19640b57cec5SDimitry Andric         return Opts;
19650b57cec5SDimitry Andric     }
19660b57cec5SDimitry Andric     return MetaSubject->getValueAsListOfDefs("LangOpts");
19670b57cec5SDimitry Andric   }
19680b57cec5SDimitry Andric 
19690b57cec5SDimitry Andric   // Abstract rules are used only for sub-rules
19700b57cec5SDimitry Andric   bool isAbstractRule() const { return getSubjects().empty(); }
19710b57cec5SDimitry Andric 
19720b57cec5SDimitry Andric   StringRef getName() const {
19730b57cec5SDimitry Andric     return (Constraint ? Constraint : MetaSubject)->getValueAsString("Name");
19740b57cec5SDimitry Andric   }
19750b57cec5SDimitry Andric 
19760b57cec5SDimitry Andric   bool isNegatedSubRule() const {
19770b57cec5SDimitry Andric     assert(isSubRule() && "Not a sub-rule");
19780b57cec5SDimitry Andric     return Constraint->getValueAsBit("Negated");
19790b57cec5SDimitry Andric   }
19800b57cec5SDimitry Andric 
19810b57cec5SDimitry Andric   std::string getSpelling() const {
19825ffd83dbSDimitry Andric     std::string Result = std::string(MetaSubject->getValueAsString("Name"));
19830b57cec5SDimitry Andric     if (isSubRule()) {
19840b57cec5SDimitry Andric       Result += '(';
19850b57cec5SDimitry Andric       if (isNegatedSubRule())
19860b57cec5SDimitry Andric         Result += "unless(";
19870b57cec5SDimitry Andric       Result += getName();
19880b57cec5SDimitry Andric       if (isNegatedSubRule())
19890b57cec5SDimitry Andric         Result += ')';
19900b57cec5SDimitry Andric       Result += ')';
19910b57cec5SDimitry Andric     }
19920b57cec5SDimitry Andric     return Result;
19930b57cec5SDimitry Andric   }
19940b57cec5SDimitry Andric 
19950b57cec5SDimitry Andric   std::string getEnumValueName() const {
19960b57cec5SDimitry Andric     SmallString<128> Result;
19970b57cec5SDimitry Andric     Result += "SubjectMatchRule_";
19980b57cec5SDimitry Andric     Result += MetaSubject->getValueAsString("Name");
19990b57cec5SDimitry Andric     if (isSubRule()) {
20000b57cec5SDimitry Andric       Result += "_";
20010b57cec5SDimitry Andric       if (isNegatedSubRule())
20020b57cec5SDimitry Andric         Result += "not_";
20030b57cec5SDimitry Andric       Result += Constraint->getValueAsString("Name");
20040b57cec5SDimitry Andric     }
20050b57cec5SDimitry Andric     if (isAbstractRule())
20060b57cec5SDimitry Andric       Result += "_abstract";
20077a6dacacSDimitry Andric     return std::string(Result);
20080b57cec5SDimitry Andric   }
20090b57cec5SDimitry Andric 
20100b57cec5SDimitry Andric   std::string getEnumValue() const { return "attr::" + getEnumValueName(); }
20110b57cec5SDimitry Andric 
20120b57cec5SDimitry Andric   static const char *EnumName;
20130b57cec5SDimitry Andric };
20140b57cec5SDimitry Andric 
20150b57cec5SDimitry Andric const char *AttributeSubjectMatchRule::EnumName = "attr::SubjectMatchRule";
20160b57cec5SDimitry Andric 
20170b57cec5SDimitry Andric struct PragmaClangAttributeSupport {
20180b57cec5SDimitry Andric   std::vector<AttributeSubjectMatchRule> Rules;
20190b57cec5SDimitry Andric 
20200b57cec5SDimitry Andric   class RuleOrAggregateRuleSet {
20210b57cec5SDimitry Andric     std::vector<AttributeSubjectMatchRule> Rules;
20220b57cec5SDimitry Andric     bool IsRule;
20230b57cec5SDimitry Andric     RuleOrAggregateRuleSet(ArrayRef<AttributeSubjectMatchRule> Rules,
20240b57cec5SDimitry Andric                            bool IsRule)
20250b57cec5SDimitry Andric         : Rules(Rules), IsRule(IsRule) {}
20260b57cec5SDimitry Andric 
20270b57cec5SDimitry Andric   public:
20280b57cec5SDimitry Andric     bool isRule() const { return IsRule; }
20290b57cec5SDimitry Andric 
20300b57cec5SDimitry Andric     const AttributeSubjectMatchRule &getRule() const {
20310b57cec5SDimitry Andric       assert(IsRule && "not a rule!");
20320b57cec5SDimitry Andric       return Rules[0];
20330b57cec5SDimitry Andric     }
20340b57cec5SDimitry Andric 
20350b57cec5SDimitry Andric     ArrayRef<AttributeSubjectMatchRule> getAggregateRuleSet() const {
20360b57cec5SDimitry Andric       return Rules;
20370b57cec5SDimitry Andric     }
20380b57cec5SDimitry Andric 
20390b57cec5SDimitry Andric     static RuleOrAggregateRuleSet
20400b57cec5SDimitry Andric     getRule(const AttributeSubjectMatchRule &Rule) {
20410b57cec5SDimitry Andric       return RuleOrAggregateRuleSet(Rule, /*IsRule=*/true);
20420b57cec5SDimitry Andric     }
20430b57cec5SDimitry Andric     static RuleOrAggregateRuleSet
20440b57cec5SDimitry Andric     getAggregateRuleSet(ArrayRef<AttributeSubjectMatchRule> Rules) {
20450b57cec5SDimitry Andric       return RuleOrAggregateRuleSet(Rules, /*IsRule=*/false);
20460b57cec5SDimitry Andric     }
20470b57cec5SDimitry Andric   };
20480b57cec5SDimitry Andric   llvm::DenseMap<const Record *, RuleOrAggregateRuleSet> SubjectsToRules;
20490b57cec5SDimitry Andric 
20500b57cec5SDimitry Andric   PragmaClangAttributeSupport(RecordKeeper &Records);
20510b57cec5SDimitry Andric 
20520b57cec5SDimitry Andric   bool isAttributedSupported(const Record &Attribute);
20530b57cec5SDimitry Andric 
20540b57cec5SDimitry Andric   void emitMatchRuleList(raw_ostream &OS);
20550b57cec5SDimitry Andric 
20565ffd83dbSDimitry Andric   void generateStrictConformsTo(const Record &Attr, raw_ostream &OS);
20570b57cec5SDimitry Andric 
20580b57cec5SDimitry Andric   void generateParsingHelpers(raw_ostream &OS);
20590b57cec5SDimitry Andric };
20600b57cec5SDimitry Andric 
20610b57cec5SDimitry Andric } // end anonymous namespace
20620b57cec5SDimitry Andric 
2063fe6060f1SDimitry Andric static bool isSupportedPragmaClangAttributeSubject(const Record &Subject) {
2064fe6060f1SDimitry Andric   // FIXME: #pragma clang attribute does not currently support statement
2065fe6060f1SDimitry Andric   // attributes, so test whether the subject is one that appertains to a
2066fe6060f1SDimitry Andric   // declaration node. However, it may be reasonable for support for statement
2067fe6060f1SDimitry Andric   // attributes to be added.
2068fe6060f1SDimitry Andric   if (Subject.isSubClassOf("DeclNode") || Subject.isSubClassOf("DeclBase") ||
2069fe6060f1SDimitry Andric       Subject.getName() == "DeclBase")
2070fe6060f1SDimitry Andric     return true;
2071fe6060f1SDimitry Andric 
2072fe6060f1SDimitry Andric   if (Subject.isSubClassOf("SubsetSubject"))
2073fe6060f1SDimitry Andric     return isSupportedPragmaClangAttributeSubject(
2074fe6060f1SDimitry Andric         *Subject.getValueAsDef("Base"));
2075fe6060f1SDimitry Andric 
2076fe6060f1SDimitry Andric   return false;
2077fe6060f1SDimitry Andric }
2078fe6060f1SDimitry Andric 
20790b57cec5SDimitry Andric static bool doesDeclDeriveFrom(const Record *D, const Record *Base) {
2080480093f4SDimitry Andric   const Record *CurrentBase = D->getValueAsOptionalDef(BaseFieldName);
20810b57cec5SDimitry Andric   if (!CurrentBase)
20820b57cec5SDimitry Andric     return false;
20830b57cec5SDimitry Andric   if (CurrentBase == Base)
20840b57cec5SDimitry Andric     return true;
20850b57cec5SDimitry Andric   return doesDeclDeriveFrom(CurrentBase, Base);
20860b57cec5SDimitry Andric }
20870b57cec5SDimitry Andric 
20880b57cec5SDimitry Andric PragmaClangAttributeSupport::PragmaClangAttributeSupport(
20890b57cec5SDimitry Andric     RecordKeeper &Records) {
20900b57cec5SDimitry Andric   std::vector<Record *> MetaSubjects =
20910b57cec5SDimitry Andric       Records.getAllDerivedDefinitions("AttrSubjectMatcherRule");
20920b57cec5SDimitry Andric   auto MapFromSubjectsToRules = [this](const Record *SubjectContainer,
20930b57cec5SDimitry Andric                                        const Record *MetaSubject,
20940b57cec5SDimitry Andric                                        const Record *Constraint) {
20950b57cec5SDimitry Andric     Rules.emplace_back(MetaSubject, Constraint);
20960b57cec5SDimitry Andric     std::vector<Record *> ApplicableSubjects =
20970b57cec5SDimitry Andric         SubjectContainer->getValueAsListOfDefs("Subjects");
20980b57cec5SDimitry Andric     for (const auto *Subject : ApplicableSubjects) {
20990b57cec5SDimitry Andric       bool Inserted =
21000b57cec5SDimitry Andric           SubjectsToRules
21010b57cec5SDimitry Andric               .try_emplace(Subject, RuleOrAggregateRuleSet::getRule(
21020b57cec5SDimitry Andric                                         AttributeSubjectMatchRule(MetaSubject,
21030b57cec5SDimitry Andric                                                                   Constraint)))
21040b57cec5SDimitry Andric               .second;
21050b57cec5SDimitry Andric       if (!Inserted) {
21060b57cec5SDimitry Andric         PrintFatalError("Attribute subject match rules should not represent"
21070b57cec5SDimitry Andric                         "same attribute subjects.");
21080b57cec5SDimitry Andric       }
21090b57cec5SDimitry Andric     }
21100b57cec5SDimitry Andric   };
21110b57cec5SDimitry Andric   for (const auto *MetaSubject : MetaSubjects) {
21120b57cec5SDimitry Andric     MapFromSubjectsToRules(MetaSubject, MetaSubject, /*Constraints=*/nullptr);
21130b57cec5SDimitry Andric     std::vector<Record *> Constraints =
21140b57cec5SDimitry Andric         MetaSubject->getValueAsListOfDefs("Constraints");
21150b57cec5SDimitry Andric     for (const auto *Constraint : Constraints)
21160b57cec5SDimitry Andric       MapFromSubjectsToRules(Constraint, MetaSubject, Constraint);
21170b57cec5SDimitry Andric   }
21180b57cec5SDimitry Andric 
21190b57cec5SDimitry Andric   std::vector<Record *> Aggregates =
21200b57cec5SDimitry Andric       Records.getAllDerivedDefinitions("AttrSubjectMatcherAggregateRule");
2121480093f4SDimitry Andric   std::vector<Record *> DeclNodes =
2122480093f4SDimitry Andric     Records.getAllDerivedDefinitions(DeclNodeClassName);
21230b57cec5SDimitry Andric   for (const auto *Aggregate : Aggregates) {
21240b57cec5SDimitry Andric     Record *SubjectDecl = Aggregate->getValueAsDef("Subject");
21250b57cec5SDimitry Andric 
21260b57cec5SDimitry Andric     // Gather sub-classes of the aggregate subject that act as attribute
21270b57cec5SDimitry Andric     // subject rules.
21280b57cec5SDimitry Andric     std::vector<AttributeSubjectMatchRule> Rules;
21290b57cec5SDimitry Andric     for (const auto *D : DeclNodes) {
21300b57cec5SDimitry Andric       if (doesDeclDeriveFrom(D, SubjectDecl)) {
21310b57cec5SDimitry Andric         auto It = SubjectsToRules.find(D);
21320b57cec5SDimitry Andric         if (It == SubjectsToRules.end())
21330b57cec5SDimitry Andric           continue;
21340b57cec5SDimitry Andric         if (!It->second.isRule() || It->second.getRule().isSubRule())
21350b57cec5SDimitry Andric           continue; // Assume that the rule will be included as well.
21360b57cec5SDimitry Andric         Rules.push_back(It->second.getRule());
21370b57cec5SDimitry Andric       }
21380b57cec5SDimitry Andric     }
21390b57cec5SDimitry Andric 
21400b57cec5SDimitry Andric     bool Inserted =
21410b57cec5SDimitry Andric         SubjectsToRules
21420b57cec5SDimitry Andric             .try_emplace(SubjectDecl,
21430b57cec5SDimitry Andric                          RuleOrAggregateRuleSet::getAggregateRuleSet(Rules))
21440b57cec5SDimitry Andric             .second;
21450b57cec5SDimitry Andric     if (!Inserted) {
21460b57cec5SDimitry Andric       PrintFatalError("Attribute subject match rules should not represent"
21470b57cec5SDimitry Andric                       "same attribute subjects.");
21480b57cec5SDimitry Andric     }
21490b57cec5SDimitry Andric   }
21500b57cec5SDimitry Andric }
21510b57cec5SDimitry Andric 
21520b57cec5SDimitry Andric static PragmaClangAttributeSupport &
21530b57cec5SDimitry Andric getPragmaAttributeSupport(RecordKeeper &Records) {
21540b57cec5SDimitry Andric   static PragmaClangAttributeSupport Instance(Records);
21550b57cec5SDimitry Andric   return Instance;
21560b57cec5SDimitry Andric }
21570b57cec5SDimitry Andric 
21580b57cec5SDimitry Andric void PragmaClangAttributeSupport::emitMatchRuleList(raw_ostream &OS) {
21590b57cec5SDimitry Andric   OS << "#ifndef ATTR_MATCH_SUB_RULE\n";
21600b57cec5SDimitry Andric   OS << "#define ATTR_MATCH_SUB_RULE(Value, Spelling, IsAbstract, Parent, "
21610b57cec5SDimitry Andric         "IsNegated) "
21620b57cec5SDimitry Andric      << "ATTR_MATCH_RULE(Value, Spelling, IsAbstract)\n";
21630b57cec5SDimitry Andric   OS << "#endif\n";
21640b57cec5SDimitry Andric   for (const auto &Rule : Rules) {
21650b57cec5SDimitry Andric     OS << (Rule.isSubRule() ? "ATTR_MATCH_SUB_RULE" : "ATTR_MATCH_RULE") << '(';
21660b57cec5SDimitry Andric     OS << Rule.getEnumValueName() << ", \"" << Rule.getSpelling() << "\", "
21670b57cec5SDimitry Andric        << Rule.isAbstractRule();
21680b57cec5SDimitry Andric     if (Rule.isSubRule())
21690b57cec5SDimitry Andric       OS << ", "
21700b57cec5SDimitry Andric          << AttributeSubjectMatchRule(Rule.MetaSubject, nullptr).getEnumValue()
21710b57cec5SDimitry Andric          << ", " << Rule.isNegatedSubRule();
21720b57cec5SDimitry Andric     OS << ")\n";
21730b57cec5SDimitry Andric   }
21740b57cec5SDimitry Andric   OS << "#undef ATTR_MATCH_SUB_RULE\n";
21750b57cec5SDimitry Andric }
21760b57cec5SDimitry Andric 
21770b57cec5SDimitry Andric bool PragmaClangAttributeSupport::isAttributedSupported(
21780b57cec5SDimitry Andric     const Record &Attribute) {
21790b57cec5SDimitry Andric   // If the attribute explicitly specified whether to support #pragma clang
21800b57cec5SDimitry Andric   // attribute, use that setting.
21810b57cec5SDimitry Andric   bool Unset;
21820b57cec5SDimitry Andric   bool SpecifiedResult =
21830b57cec5SDimitry Andric     Attribute.getValueAsBitOrUnset("PragmaAttributeSupport", Unset);
21840b57cec5SDimitry Andric   if (!Unset)
21850b57cec5SDimitry Andric     return SpecifiedResult;
21860b57cec5SDimitry Andric 
21870b57cec5SDimitry Andric   // Opt-out rules:
2188*0fca6ea1SDimitry Andric 
2189*0fca6ea1SDimitry Andric   // An attribute requires delayed parsing (LateParsed is on).
2190*0fca6ea1SDimitry Andric   switch (getLateAttrParseKind(&Attribute)) {
2191*0fca6ea1SDimitry Andric   case LateAttrParseKind::Never:
2192*0fca6ea1SDimitry Andric     break;
2193*0fca6ea1SDimitry Andric   case LateAttrParseKind::Standard:
21940b57cec5SDimitry Andric     return false;
2195*0fca6ea1SDimitry Andric   case LateAttrParseKind::ExperimentalExt:
2196*0fca6ea1SDimitry Andric     // This is only late parsed in certain parsing contexts when
2197*0fca6ea1SDimitry Andric     // `LangOpts.ExperimentalLateParseAttributes` is true. Information about the
2198*0fca6ea1SDimitry Andric     // parsing context and `LangOpts` is not available in this method so just
2199*0fca6ea1SDimitry Andric     // opt this attribute out.
2200*0fca6ea1SDimitry Andric     return false;
2201*0fca6ea1SDimitry Andric   }
2202*0fca6ea1SDimitry Andric 
22030b57cec5SDimitry Andric   // An attribute has no GNU/CXX11 spelling
22040b57cec5SDimitry Andric   if (!hasGNUorCXX11Spelling(Attribute))
22050b57cec5SDimitry Andric     return false;
22060b57cec5SDimitry Andric   // An attribute subject list has a subject that isn't covered by one of the
22070b57cec5SDimitry Andric   // subject match rules or has no subjects at all.
22080b57cec5SDimitry Andric   if (Attribute.isValueUnset("Subjects"))
22090b57cec5SDimitry Andric     return false;
22100b57cec5SDimitry Andric   const Record *SubjectObj = Attribute.getValueAsDef("Subjects");
22110b57cec5SDimitry Andric   std::vector<Record *> Subjects = SubjectObj->getValueAsListOfDefs("Subjects");
2212fe6060f1SDimitry Andric   bool HasAtLeastOneValidSubject = false;
22130b57cec5SDimitry Andric   for (const auto *Subject : Subjects) {
2214fe6060f1SDimitry Andric     if (!isSupportedPragmaClangAttributeSubject(*Subject))
2215fe6060f1SDimitry Andric       continue;
221606c3fb27SDimitry Andric     if (!SubjectsToRules.contains(Subject))
22170b57cec5SDimitry Andric       return false;
2218fe6060f1SDimitry Andric     HasAtLeastOneValidSubject = true;
22190b57cec5SDimitry Andric   }
2220fe6060f1SDimitry Andric   return HasAtLeastOneValidSubject;
22210b57cec5SDimitry Andric }
22220b57cec5SDimitry Andric 
22230b57cec5SDimitry Andric static std::string GenerateTestExpression(ArrayRef<Record *> LangOpts) {
22240b57cec5SDimitry Andric   std::string Test;
22250b57cec5SDimitry Andric 
22260b57cec5SDimitry Andric   for (auto *E : LangOpts) {
22270b57cec5SDimitry Andric     if (!Test.empty())
22280b57cec5SDimitry Andric       Test += " || ";
22290b57cec5SDimitry Andric 
22300b57cec5SDimitry Andric     const StringRef Code = E->getValueAsString("CustomCode");
22310b57cec5SDimitry Andric     if (!Code.empty()) {
22320b57cec5SDimitry Andric       Test += "(";
22330b57cec5SDimitry Andric       Test += Code;
22340b57cec5SDimitry Andric       Test += ")";
22355ffd83dbSDimitry Andric       if (!E->getValueAsString("Name").empty()) {
22365ffd83dbSDimitry Andric         PrintWarning(
22375ffd83dbSDimitry Andric             E->getLoc(),
22385ffd83dbSDimitry Andric             "non-empty 'Name' field ignored because 'CustomCode' was supplied");
22395ffd83dbSDimitry Andric       }
22400b57cec5SDimitry Andric     } else {
22410b57cec5SDimitry Andric       Test += "LangOpts.";
22420b57cec5SDimitry Andric       Test += E->getValueAsString("Name");
22430b57cec5SDimitry Andric     }
22440b57cec5SDimitry Andric   }
22450b57cec5SDimitry Andric 
22460b57cec5SDimitry Andric   if (Test.empty())
22470b57cec5SDimitry Andric     return "true";
22480b57cec5SDimitry Andric 
22490b57cec5SDimitry Andric   return Test;
22500b57cec5SDimitry Andric }
22510b57cec5SDimitry Andric 
22525ffd83dbSDimitry Andric void
22530b57cec5SDimitry Andric PragmaClangAttributeSupport::generateStrictConformsTo(const Record &Attr,
22540b57cec5SDimitry Andric                                                       raw_ostream &OS) {
22555ffd83dbSDimitry Andric   if (!isAttributedSupported(Attr) || Attr.isValueUnset("Subjects"))
22565ffd83dbSDimitry Andric     return;
22570b57cec5SDimitry Andric   // Generate a function that constructs a set of matching rules that describe
22580b57cec5SDimitry Andric   // to which declarations the attribute should apply to.
22595ffd83dbSDimitry Andric   OS << "void getPragmaAttributeMatchRules("
22605ffd83dbSDimitry Andric      << "llvm::SmallVectorImpl<std::pair<"
22610b57cec5SDimitry Andric      << AttributeSubjectMatchRule::EnumName
22625ffd83dbSDimitry Andric      << ", bool>> &MatchRules, const LangOptions &LangOpts) const override {\n";
22630b57cec5SDimitry Andric   const Record *SubjectObj = Attr.getValueAsDef("Subjects");
22640b57cec5SDimitry Andric   std::vector<Record *> Subjects = SubjectObj->getValueAsListOfDefs("Subjects");
22650b57cec5SDimitry Andric   for (const auto *Subject : Subjects) {
2266fe6060f1SDimitry Andric     if (!isSupportedPragmaClangAttributeSubject(*Subject))
2267fe6060f1SDimitry Andric       continue;
22680b57cec5SDimitry Andric     auto It = SubjectsToRules.find(Subject);
22690b57cec5SDimitry Andric     assert(It != SubjectsToRules.end() &&
22700b57cec5SDimitry Andric            "This attribute is unsupported by #pragma clang attribute");
22710b57cec5SDimitry Andric     for (const auto &Rule : It->getSecond().getAggregateRuleSet()) {
22720b57cec5SDimitry Andric       // The rule might be language specific, so only subtract it from the given
22730b57cec5SDimitry Andric       // rules if the specific language options are specified.
22740b57cec5SDimitry Andric       std::vector<Record *> LangOpts = Rule.getLangOpts();
22750b57cec5SDimitry Andric       OS << "  MatchRules.push_back(std::make_pair(" << Rule.getEnumValue()
22760b57cec5SDimitry Andric          << ", /*IsSupported=*/" << GenerateTestExpression(LangOpts)
22770b57cec5SDimitry Andric          << "));\n";
22780b57cec5SDimitry Andric     }
22790b57cec5SDimitry Andric   }
22800b57cec5SDimitry Andric   OS << "}\n\n";
22810b57cec5SDimitry Andric }
22820b57cec5SDimitry Andric 
22830b57cec5SDimitry Andric void PragmaClangAttributeSupport::generateParsingHelpers(raw_ostream &OS) {
22840b57cec5SDimitry Andric   // Generate routines that check the names of sub-rules.
2285bdd1243dSDimitry Andric   OS << "std::optional<attr::SubjectMatchRule> "
22860b57cec5SDimitry Andric         "defaultIsAttributeSubjectMatchSubRuleFor(StringRef, bool) {\n";
2287bdd1243dSDimitry Andric   OS << "  return std::nullopt;\n";
22880b57cec5SDimitry Andric   OS << "}\n\n";
22890b57cec5SDimitry Andric 
2290349cc55cSDimitry Andric   llvm::MapVector<const Record *, std::vector<AttributeSubjectMatchRule>>
22910b57cec5SDimitry Andric       SubMatchRules;
22920b57cec5SDimitry Andric   for (const auto &Rule : Rules) {
22930b57cec5SDimitry Andric     if (!Rule.isSubRule())
22940b57cec5SDimitry Andric       continue;
22950b57cec5SDimitry Andric     SubMatchRules[Rule.MetaSubject].push_back(Rule);
22960b57cec5SDimitry Andric   }
22970b57cec5SDimitry Andric 
22980b57cec5SDimitry Andric   for (const auto &SubMatchRule : SubMatchRules) {
2299bdd1243dSDimitry Andric     OS << "std::optional<attr::SubjectMatchRule> "
2300bdd1243dSDimitry Andric           "isAttributeSubjectMatchSubRuleFor_"
23010b57cec5SDimitry Andric        << SubMatchRule.first->getValueAsString("Name")
23020b57cec5SDimitry Andric        << "(StringRef Name, bool IsUnless) {\n";
23030b57cec5SDimitry Andric     OS << "  if (IsUnless)\n";
23040b57cec5SDimitry Andric     OS << "    return "
2305bdd1243dSDimitry Andric           "llvm::StringSwitch<std::optional<attr::SubjectMatchRule>>(Name).\n";
23060b57cec5SDimitry Andric     for (const auto &Rule : SubMatchRule.second) {
23070b57cec5SDimitry Andric       if (Rule.isNegatedSubRule())
23080b57cec5SDimitry Andric         OS << "    Case(\"" << Rule.getName() << "\", " << Rule.getEnumValue()
23090b57cec5SDimitry Andric            << ").\n";
23100b57cec5SDimitry Andric     }
2311bdd1243dSDimitry Andric     OS << "    Default(std::nullopt);\n";
23120b57cec5SDimitry Andric     OS << "  return "
2313bdd1243dSDimitry Andric           "llvm::StringSwitch<std::optional<attr::SubjectMatchRule>>(Name).\n";
23140b57cec5SDimitry Andric     for (const auto &Rule : SubMatchRule.second) {
23150b57cec5SDimitry Andric       if (!Rule.isNegatedSubRule())
23160b57cec5SDimitry Andric         OS << "  Case(\"" << Rule.getName() << "\", " << Rule.getEnumValue()
23170b57cec5SDimitry Andric            << ").\n";
23180b57cec5SDimitry Andric     }
2319bdd1243dSDimitry Andric     OS << "  Default(std::nullopt);\n";
23200b57cec5SDimitry Andric     OS << "}\n\n";
23210b57cec5SDimitry Andric   }
23220b57cec5SDimitry Andric 
23230b57cec5SDimitry Andric   // Generate the function that checks for the top-level rules.
2324bdd1243dSDimitry Andric   OS << "std::pair<std::optional<attr::SubjectMatchRule>, "
2325bdd1243dSDimitry Andric         "std::optional<attr::SubjectMatchRule> (*)(StringRef, "
23260b57cec5SDimitry Andric         "bool)> isAttributeSubjectMatchRule(StringRef Name) {\n";
23270b57cec5SDimitry Andric   OS << "  return "
2328bdd1243dSDimitry Andric         "llvm::StringSwitch<std::pair<std::optional<attr::SubjectMatchRule>, "
2329bdd1243dSDimitry Andric         "std::optional<attr::SubjectMatchRule> (*) (StringRef, "
23300b57cec5SDimitry Andric         "bool)>>(Name).\n";
23310b57cec5SDimitry Andric   for (const auto &Rule : Rules) {
23320b57cec5SDimitry Andric     if (Rule.isSubRule())
23330b57cec5SDimitry Andric       continue;
23340b57cec5SDimitry Andric     std::string SubRuleFunction;
23350b57cec5SDimitry Andric     if (SubMatchRules.count(Rule.MetaSubject))
23360b57cec5SDimitry Andric       SubRuleFunction =
23370b57cec5SDimitry Andric           ("isAttributeSubjectMatchSubRuleFor_" + Rule.getName()).str();
23380b57cec5SDimitry Andric     else
23390b57cec5SDimitry Andric       SubRuleFunction = "defaultIsAttributeSubjectMatchSubRuleFor";
23400b57cec5SDimitry Andric     OS << "  Case(\"" << Rule.getName() << "\", std::make_pair("
23410b57cec5SDimitry Andric        << Rule.getEnumValue() << ", " << SubRuleFunction << ")).\n";
23420b57cec5SDimitry Andric   }
2343bdd1243dSDimitry Andric   OS << "  Default(std::make_pair(std::nullopt, "
23440b57cec5SDimitry Andric         "defaultIsAttributeSubjectMatchSubRuleFor));\n";
23450b57cec5SDimitry Andric   OS << "}\n\n";
23460b57cec5SDimitry Andric 
23470b57cec5SDimitry Andric   // Generate the function that checks for the submatch rules.
23480b57cec5SDimitry Andric   OS << "const char *validAttributeSubjectMatchSubRules("
23490b57cec5SDimitry Andric      << AttributeSubjectMatchRule::EnumName << " Rule) {\n";
23500b57cec5SDimitry Andric   OS << "  switch (Rule) {\n";
23510b57cec5SDimitry Andric   for (const auto &SubMatchRule : SubMatchRules) {
23520b57cec5SDimitry Andric     OS << "  case "
23530b57cec5SDimitry Andric        << AttributeSubjectMatchRule(SubMatchRule.first, nullptr).getEnumValue()
23540b57cec5SDimitry Andric        << ":\n";
23550b57cec5SDimitry Andric     OS << "  return \"'";
23560b57cec5SDimitry Andric     bool IsFirst = true;
23570b57cec5SDimitry Andric     for (const auto &Rule : SubMatchRule.second) {
23580b57cec5SDimitry Andric       if (!IsFirst)
23590b57cec5SDimitry Andric         OS << ", '";
23600b57cec5SDimitry Andric       IsFirst = false;
23610b57cec5SDimitry Andric       if (Rule.isNegatedSubRule())
23620b57cec5SDimitry Andric         OS << "unless(";
23630b57cec5SDimitry Andric       OS << Rule.getName();
23640b57cec5SDimitry Andric       if (Rule.isNegatedSubRule())
23650b57cec5SDimitry Andric         OS << ')';
23660b57cec5SDimitry Andric       OS << "'";
23670b57cec5SDimitry Andric     }
23680b57cec5SDimitry Andric     OS << "\";\n";
23690b57cec5SDimitry Andric   }
23700b57cec5SDimitry Andric   OS << "  default: return nullptr;\n";
23710b57cec5SDimitry Andric   OS << "  }\n";
23720b57cec5SDimitry Andric   OS << "}\n\n";
23730b57cec5SDimitry Andric }
23740b57cec5SDimitry Andric 
23750b57cec5SDimitry Andric template <typename Fn>
23760b57cec5SDimitry Andric static void forEachUniqueSpelling(const Record &Attr, Fn &&F) {
23770b57cec5SDimitry Andric   std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
23780b57cec5SDimitry Andric   SmallDenseSet<StringRef, 8> Seen;
23790b57cec5SDimitry Andric   for (const FlattenedSpelling &S : Spellings) {
23800b57cec5SDimitry Andric     if (Seen.insert(S.name()).second)
23810b57cec5SDimitry Andric       F(S);
23820b57cec5SDimitry Andric   }
23830b57cec5SDimitry Andric }
23840b57cec5SDimitry Andric 
238581ad6265SDimitry Andric static bool isTypeArgument(const Record *Arg) {
238681ad6265SDimitry Andric   return !Arg->getSuperClasses().empty() &&
238781ad6265SDimitry Andric          Arg->getSuperClasses().back().first->getName() == "TypeArgument";
238881ad6265SDimitry Andric }
238981ad6265SDimitry Andric 
23900b57cec5SDimitry Andric /// Emits the first-argument-is-type property for attributes.
23910b57cec5SDimitry Andric static void emitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) {
23920b57cec5SDimitry Andric   OS << "#if defined(CLANG_ATTR_TYPE_ARG_LIST)\n";
23930b57cec5SDimitry Andric   std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
23940b57cec5SDimitry Andric 
23950b57cec5SDimitry Andric   for (const auto *Attr : Attrs) {
23960b57cec5SDimitry Andric     // Determine whether the first argument is a type.
23970b57cec5SDimitry Andric     std::vector<Record *> Args = Attr->getValueAsListOfDefs("Args");
23980b57cec5SDimitry Andric     if (Args.empty())
23990b57cec5SDimitry Andric       continue;
24000b57cec5SDimitry Andric 
240181ad6265SDimitry Andric     if (!isTypeArgument(Args[0]))
24020b57cec5SDimitry Andric       continue;
24030b57cec5SDimitry Andric 
24040b57cec5SDimitry Andric     // All these spellings take a single type argument.
24050b57cec5SDimitry Andric     forEachUniqueSpelling(*Attr, [&](const FlattenedSpelling &S) {
24060b57cec5SDimitry Andric       OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n";
24070b57cec5SDimitry Andric     });
24080b57cec5SDimitry Andric   }
24090b57cec5SDimitry Andric   OS << "#endif // CLANG_ATTR_TYPE_ARG_LIST\n\n";
24100b57cec5SDimitry Andric }
24110b57cec5SDimitry Andric 
24120b57cec5SDimitry Andric /// Emits the parse-arguments-in-unevaluated-context property for
24130b57cec5SDimitry Andric /// attributes.
24140b57cec5SDimitry Andric static void emitClangAttrArgContextList(RecordKeeper &Records, raw_ostream &OS) {
24150b57cec5SDimitry Andric   OS << "#if defined(CLANG_ATTR_ARG_CONTEXT_LIST)\n";
24160b57cec5SDimitry Andric   ParsedAttrMap Attrs = getParsedAttrList(Records);
24170b57cec5SDimitry Andric   for (const auto &I : Attrs) {
24180b57cec5SDimitry Andric     const Record &Attr = *I.second;
24190b57cec5SDimitry Andric 
24200b57cec5SDimitry Andric     if (!Attr.getValueAsBit("ParseArgumentsAsUnevaluated"))
24210b57cec5SDimitry Andric       continue;
24220b57cec5SDimitry Andric 
24230b57cec5SDimitry Andric     // All these spellings take are parsed unevaluated.
24240b57cec5SDimitry Andric     forEachUniqueSpelling(Attr, [&](const FlattenedSpelling &S) {
24250b57cec5SDimitry Andric       OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n";
24260b57cec5SDimitry Andric     });
24270b57cec5SDimitry Andric   }
24280b57cec5SDimitry Andric   OS << "#endif // CLANG_ATTR_ARG_CONTEXT_LIST\n\n";
24290b57cec5SDimitry Andric }
24300b57cec5SDimitry Andric 
243181ad6265SDimitry Andric static bool isIdentifierArgument(const Record *Arg) {
24320b57cec5SDimitry Andric   return !Arg->getSuperClasses().empty() &&
24330b57cec5SDimitry Andric     llvm::StringSwitch<bool>(Arg->getSuperClasses().back().first->getName())
24340b57cec5SDimitry Andric     .Case("IdentifierArgument", true)
24350b57cec5SDimitry Andric     .Case("EnumArgument", true)
24360b57cec5SDimitry Andric     .Case("VariadicEnumArgument", true)
24370b57cec5SDimitry Andric     .Default(false);
24380b57cec5SDimitry Andric }
24390b57cec5SDimitry Andric 
244081ad6265SDimitry Andric static bool isVariadicIdentifierArgument(const Record *Arg) {
24410b57cec5SDimitry Andric   return !Arg->getSuperClasses().empty() &&
24420b57cec5SDimitry Andric          llvm::StringSwitch<bool>(
24430b57cec5SDimitry Andric              Arg->getSuperClasses().back().first->getName())
24440b57cec5SDimitry Andric              .Case("VariadicIdentifierArgument", true)
24450b57cec5SDimitry Andric              .Case("VariadicParamOrParamIdxArgument", true)
24460b57cec5SDimitry Andric              .Default(false);
24470b57cec5SDimitry Andric }
24480b57cec5SDimitry Andric 
244981ad6265SDimitry Andric static bool isVariadicExprArgument(const Record *Arg) {
245081ad6265SDimitry Andric   return !Arg->getSuperClasses().empty() &&
245181ad6265SDimitry Andric          llvm::StringSwitch<bool>(
245281ad6265SDimitry Andric              Arg->getSuperClasses().back().first->getName())
245381ad6265SDimitry Andric              .Case("VariadicExprArgument", true)
245481ad6265SDimitry Andric              .Default(false);
245581ad6265SDimitry Andric }
245681ad6265SDimitry Andric 
24575f757f3fSDimitry Andric static bool isStringLiteralArgument(const Record *Arg) {
2458*0fca6ea1SDimitry Andric   if (Arg->getSuperClasses().empty())
2459*0fca6ea1SDimitry Andric     return false;
2460*0fca6ea1SDimitry Andric   StringRef ArgKind = Arg->getSuperClasses().back().first->getName();
2461*0fca6ea1SDimitry Andric   if (ArgKind == "EnumArgument")
2462*0fca6ea1SDimitry Andric     return Arg->getValueAsBit("IsString");
2463*0fca6ea1SDimitry Andric   return ArgKind == "StringArgument";
24645f757f3fSDimitry Andric }
24655f757f3fSDimitry Andric 
24665f757f3fSDimitry Andric static bool isVariadicStringLiteralArgument(const Record *Arg) {
2467*0fca6ea1SDimitry Andric   if (Arg->getSuperClasses().empty())
2468*0fca6ea1SDimitry Andric     return false;
2469*0fca6ea1SDimitry Andric   StringRef ArgKind = Arg->getSuperClasses().back().first->getName();
2470*0fca6ea1SDimitry Andric   if (ArgKind == "VariadicEnumArgument")
2471*0fca6ea1SDimitry Andric     return Arg->getValueAsBit("IsString");
2472*0fca6ea1SDimitry Andric   return ArgKind == "VariadicStringArgument";
24735f757f3fSDimitry Andric }
24745f757f3fSDimitry Andric 
24750b57cec5SDimitry Andric static void emitClangAttrVariadicIdentifierArgList(RecordKeeper &Records,
24760b57cec5SDimitry Andric                                                    raw_ostream &OS) {
24770b57cec5SDimitry Andric   OS << "#if defined(CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST)\n";
24780b57cec5SDimitry Andric   std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
24790b57cec5SDimitry Andric   for (const auto *A : Attrs) {
24800b57cec5SDimitry Andric     // Determine whether the first argument is a variadic identifier.
24810b57cec5SDimitry Andric     std::vector<Record *> Args = A->getValueAsListOfDefs("Args");
24820b57cec5SDimitry Andric     if (Args.empty() || !isVariadicIdentifierArgument(Args[0]))
24830b57cec5SDimitry Andric       continue;
24840b57cec5SDimitry Andric 
24850b57cec5SDimitry Andric     // All these spellings take an identifier argument.
24860b57cec5SDimitry Andric     forEachUniqueSpelling(*A, [&](const FlattenedSpelling &S) {
24870b57cec5SDimitry Andric       OS << ".Case(\"" << S.name() << "\", "
24880b57cec5SDimitry Andric          << "true"
24890b57cec5SDimitry Andric          << ")\n";
24900b57cec5SDimitry Andric     });
24910b57cec5SDimitry Andric   }
24920b57cec5SDimitry Andric   OS << "#endif // CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST\n\n";
24930b57cec5SDimitry Andric }
24940b57cec5SDimitry Andric 
2495*0fca6ea1SDimitry Andric static bool GenerateTargetSpecificAttrChecks(const Record *R,
2496*0fca6ea1SDimitry Andric                                              std::vector<StringRef> &Arches,
2497*0fca6ea1SDimitry Andric                                              std::string &Test,
2498*0fca6ea1SDimitry Andric                                              std::string *FnName);
2499*0fca6ea1SDimitry Andric 
25005f757f3fSDimitry Andric // Emits the list of arguments that should be parsed as unevaluated string
25015f757f3fSDimitry Andric // literals for each attribute.
25025f757f3fSDimitry Andric static void emitClangAttrUnevaluatedStringLiteralList(RecordKeeper &Records,
25035f757f3fSDimitry Andric                                                       raw_ostream &OS) {
25045f757f3fSDimitry Andric   OS << "#if defined(CLANG_ATTR_STRING_LITERAL_ARG_LIST)\n";
2505*0fca6ea1SDimitry Andric 
2506*0fca6ea1SDimitry Andric   auto MakeMask = [](ArrayRef<Record *> Args) {
25075f757f3fSDimitry Andric     uint32_t Bits = 0;
25085f757f3fSDimitry Andric     assert(Args.size() <= 32 && "unsupported number of arguments in attribute");
25095f757f3fSDimitry Andric     for (uint32_t N = 0; N < Args.size(); ++N) {
25105f757f3fSDimitry Andric       Bits |= (isStringLiteralArgument(Args[N]) << N);
25115f757f3fSDimitry Andric       // If we have a variadic string argument, set all the remaining bits to 1
25125f757f3fSDimitry Andric       if (isVariadicStringLiteralArgument(Args[N])) {
25135f757f3fSDimitry Andric         Bits |= maskTrailingZeros<decltype(Bits)>(N);
25145f757f3fSDimitry Andric         break;
25155f757f3fSDimitry Andric       }
25165f757f3fSDimitry Andric     }
2517*0fca6ea1SDimitry Andric     return Bits;
2518*0fca6ea1SDimitry Andric   };
2519*0fca6ea1SDimitry Andric 
2520*0fca6ea1SDimitry Andric   auto AddMaskWithTargetCheck = [](const Record *Attr, uint32_t Mask,
2521*0fca6ea1SDimitry Andric                                    std::string &MaskStr) {
2522*0fca6ea1SDimitry Andric     const Record *T = Attr->getValueAsDef("Target");
2523*0fca6ea1SDimitry Andric     std::vector<StringRef> Arches = T->getValueAsListOfStrings("Arches");
2524*0fca6ea1SDimitry Andric     std::string Test;
2525*0fca6ea1SDimitry Andric     GenerateTargetSpecificAttrChecks(T, Arches, Test, nullptr);
2526*0fca6ea1SDimitry Andric     MaskStr.append(Test + " ? " + std::to_string(Mask) + " : ");
2527*0fca6ea1SDimitry Andric   };
2528*0fca6ea1SDimitry Andric 
2529*0fca6ea1SDimitry Andric   ParsedAttrMap Dupes;
2530*0fca6ea1SDimitry Andric   ParsedAttrMap Attrs = getParsedAttrList(Records, &Dupes, /*SemaOnly=*/false);
2531*0fca6ea1SDimitry Andric   for (const auto &[AttrName, Attr] : Attrs) {
2532*0fca6ea1SDimitry Andric     std::string MaskStr;
2533*0fca6ea1SDimitry Andric     if (Attr->isSubClassOf("TargetSpecificAttr") &&
2534*0fca6ea1SDimitry Andric         !Attr->isValueUnset("ParseKind")) {
2535*0fca6ea1SDimitry Andric       if (uint32_t Mask = MakeMask(Attr->getValueAsListOfDefs("Args")))
2536*0fca6ea1SDimitry Andric         AddMaskWithTargetCheck(Attr, Mask, MaskStr);
2537*0fca6ea1SDimitry Andric       StringRef ParseKind = Attr->getValueAsString("ParseKind");
2538*0fca6ea1SDimitry Andric       for (const auto &[DupeParseKind, DupAttr] : Dupes) {
2539*0fca6ea1SDimitry Andric         if (DupeParseKind != ParseKind)
25405f757f3fSDimitry Andric           continue;
2541*0fca6ea1SDimitry Andric         if (uint32_t Mask = MakeMask(DupAttr->getValueAsListOfDefs("Args")))
2542*0fca6ea1SDimitry Andric           AddMaskWithTargetCheck(DupAttr, Mask, MaskStr);
2543*0fca6ea1SDimitry Andric       }
2544*0fca6ea1SDimitry Andric       if (!MaskStr.empty())
2545*0fca6ea1SDimitry Andric         MaskStr.append("0");
2546*0fca6ea1SDimitry Andric     } else {
2547*0fca6ea1SDimitry Andric       if (uint32_t Mask = MakeMask(Attr->getValueAsListOfDefs("Args")))
2548*0fca6ea1SDimitry Andric         MaskStr = std::to_string(Mask);
2549*0fca6ea1SDimitry Andric     }
2550*0fca6ea1SDimitry Andric 
2551*0fca6ea1SDimitry Andric     if (MaskStr.empty())
2552*0fca6ea1SDimitry Andric       continue;
2553*0fca6ea1SDimitry Andric 
25545f757f3fSDimitry Andric     // All these spellings have at least one string literal has argument.
25555f757f3fSDimitry Andric     forEachUniqueSpelling(*Attr, [&](const FlattenedSpelling &S) {
2556*0fca6ea1SDimitry Andric       OS << ".Case(\"" << S.name() << "\", " << MaskStr << ")\n";
25575f757f3fSDimitry Andric     });
25585f757f3fSDimitry Andric   }
25595f757f3fSDimitry Andric   OS << "#endif // CLANG_ATTR_STRING_LITERAL_ARG_LIST\n\n";
25605f757f3fSDimitry Andric }
25615f757f3fSDimitry Andric 
25620b57cec5SDimitry Andric // Emits the first-argument-is-identifier property for attributes.
25630b57cec5SDimitry Andric static void emitClangAttrIdentifierArgList(RecordKeeper &Records, raw_ostream &OS) {
25640b57cec5SDimitry Andric   OS << "#if defined(CLANG_ATTR_IDENTIFIER_ARG_LIST)\n";
25650b57cec5SDimitry Andric   std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
25660b57cec5SDimitry Andric 
25670b57cec5SDimitry Andric   for (const auto *Attr : Attrs) {
25680b57cec5SDimitry Andric     // Determine whether the first argument is an identifier.
25690b57cec5SDimitry Andric     std::vector<Record *> Args = Attr->getValueAsListOfDefs("Args");
25700b57cec5SDimitry Andric     if (Args.empty() || !isIdentifierArgument(Args[0]))
25710b57cec5SDimitry Andric       continue;
25720b57cec5SDimitry Andric 
25730b57cec5SDimitry Andric     // All these spellings take an identifier argument.
25740b57cec5SDimitry Andric     forEachUniqueSpelling(*Attr, [&](const FlattenedSpelling &S) {
25750b57cec5SDimitry Andric       OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n";
25760b57cec5SDimitry Andric     });
25770b57cec5SDimitry Andric   }
25780b57cec5SDimitry Andric   OS << "#endif // CLANG_ATTR_IDENTIFIER_ARG_LIST\n\n";
25790b57cec5SDimitry Andric }
25800b57cec5SDimitry Andric 
2581*0fca6ea1SDimitry Andric // Emits the indexed-argument-is-identifier property for attributes.
2582*0fca6ea1SDimitry Andric static void emitClangAttrStrictIdentifierArgAtIndexList(RecordKeeper &Records,
2583*0fca6ea1SDimitry Andric                                                         raw_ostream &OS) {
2584*0fca6ea1SDimitry Andric   OS << "#if defined(CLANG_ATTR_STRICT_IDENTIFIER_ARG_AT_INDEX_LIST)\n";
2585*0fca6ea1SDimitry Andric   std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
2586*0fca6ea1SDimitry Andric 
2587*0fca6ea1SDimitry Andric   for (const auto *Attr : Attrs) {
2588*0fca6ea1SDimitry Andric     if (!Attr->getValueAsBit("StrictEnumParameters"))
2589*0fca6ea1SDimitry Andric       continue;
2590*0fca6ea1SDimitry Andric     // Determine whether the first argument is an identifier.
2591*0fca6ea1SDimitry Andric     std::vector<Record *> Args = Attr->getValueAsListOfDefs("Args");
2592*0fca6ea1SDimitry Andric     uint64_t enumAtIndex = 0;
2593*0fca6ea1SDimitry Andric     for (size_t i = 0; i < Args.size(); i++) {
2594*0fca6ea1SDimitry Andric       enumAtIndex |= ((uint64_t)isIdentifierArgument(Args[0])) << i;
2595*0fca6ea1SDimitry Andric     }
2596*0fca6ea1SDimitry Andric     if (!enumAtIndex)
2597*0fca6ea1SDimitry Andric       continue;
2598*0fca6ea1SDimitry Andric 
2599*0fca6ea1SDimitry Andric     // All these spellings take an identifier argument.
2600*0fca6ea1SDimitry Andric     forEachUniqueSpelling(*Attr, [&](const FlattenedSpelling &S) {
2601*0fca6ea1SDimitry Andric       OS << ".Case(\"" << S.name() << "\", " << enumAtIndex << "ull)\n";
2602*0fca6ea1SDimitry Andric     });
2603*0fca6ea1SDimitry Andric   }
2604*0fca6ea1SDimitry Andric   OS << "#endif // CLANG_ATTR_STRICT_IDENTIFIER_ARG_AT_INDEX_LIST\n\n";
2605*0fca6ea1SDimitry Andric }
2606*0fca6ea1SDimitry Andric 
26070b57cec5SDimitry Andric static bool keywordThisIsaIdentifierInArgument(const Record *Arg) {
26080b57cec5SDimitry Andric   return !Arg->getSuperClasses().empty() &&
26090b57cec5SDimitry Andric          llvm::StringSwitch<bool>(
26100b57cec5SDimitry Andric              Arg->getSuperClasses().back().first->getName())
26110b57cec5SDimitry Andric              .Case("VariadicParamOrParamIdxArgument", true)
26120b57cec5SDimitry Andric              .Default(false);
26130b57cec5SDimitry Andric }
26140b57cec5SDimitry Andric 
26150b57cec5SDimitry Andric static void emitClangAttrThisIsaIdentifierArgList(RecordKeeper &Records,
26160b57cec5SDimitry Andric                                                   raw_ostream &OS) {
26170b57cec5SDimitry Andric   OS << "#if defined(CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST)\n";
26180b57cec5SDimitry Andric   std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
26190b57cec5SDimitry Andric   for (const auto *A : Attrs) {
26200b57cec5SDimitry Andric     // Determine whether the first argument is a variadic identifier.
26210b57cec5SDimitry Andric     std::vector<Record *> Args = A->getValueAsListOfDefs("Args");
26220b57cec5SDimitry Andric     if (Args.empty() || !keywordThisIsaIdentifierInArgument(Args[0]))
26230b57cec5SDimitry Andric       continue;
26240b57cec5SDimitry Andric 
26250b57cec5SDimitry Andric     // All these spellings take an identifier argument.
26260b57cec5SDimitry Andric     forEachUniqueSpelling(*A, [&](const FlattenedSpelling &S) {
26270b57cec5SDimitry Andric       OS << ".Case(\"" << S.name() << "\", "
26280b57cec5SDimitry Andric          << "true"
26290b57cec5SDimitry Andric          << ")\n";
26300b57cec5SDimitry Andric     });
26310b57cec5SDimitry Andric   }
26320b57cec5SDimitry Andric   OS << "#endif // CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST\n\n";
26330b57cec5SDimitry Andric }
26340b57cec5SDimitry Andric 
263581ad6265SDimitry Andric static void emitClangAttrAcceptsExprPack(RecordKeeper &Records,
263681ad6265SDimitry Andric                                          raw_ostream &OS) {
263781ad6265SDimitry Andric   OS << "#if defined(CLANG_ATTR_ACCEPTS_EXPR_PACK)\n";
263881ad6265SDimitry Andric   ParsedAttrMap Attrs = getParsedAttrList(Records);
263981ad6265SDimitry Andric   for (const auto &I : Attrs) {
264081ad6265SDimitry Andric     const Record &Attr = *I.second;
264181ad6265SDimitry Andric 
264281ad6265SDimitry Andric     if (!Attr.getValueAsBit("AcceptsExprPack"))
264381ad6265SDimitry Andric       continue;
264481ad6265SDimitry Andric 
264581ad6265SDimitry Andric     forEachUniqueSpelling(Attr, [&](const FlattenedSpelling &S) {
264681ad6265SDimitry Andric       OS << ".Case(\"" << S.name() << "\", true)\n";
264781ad6265SDimitry Andric     });
264881ad6265SDimitry Andric   }
264981ad6265SDimitry Andric   OS << "#endif // CLANG_ATTR_ACCEPTS_EXPR_PACK\n\n";
265081ad6265SDimitry Andric }
265181ad6265SDimitry Andric 
265206c3fb27SDimitry Andric static bool isRegularKeywordAttribute(const FlattenedSpelling &S) {
265306c3fb27SDimitry Andric   return (S.variety() == "Keyword" &&
265406c3fb27SDimitry Andric           !S.getSpellingRecord().getValueAsBit("HasOwnParseRules"));
265506c3fb27SDimitry Andric }
265606c3fb27SDimitry Andric 
265706c3fb27SDimitry Andric static void emitFormInitializer(raw_ostream &OS,
265806c3fb27SDimitry Andric                                 const FlattenedSpelling &Spelling,
265906c3fb27SDimitry Andric                                 StringRef SpellingIndex) {
266006c3fb27SDimitry Andric   bool IsAlignas =
266106c3fb27SDimitry Andric       (Spelling.variety() == "Keyword" && Spelling.name() == "alignas");
266206c3fb27SDimitry Andric   OS << "{AttributeCommonInfo::AS_" << Spelling.variety() << ", "
266306c3fb27SDimitry Andric      << SpellingIndex << ", " << (IsAlignas ? "true" : "false")
266406c3fb27SDimitry Andric      << " /*IsAlignas*/, "
266506c3fb27SDimitry Andric      << (isRegularKeywordAttribute(Spelling) ? "true" : "false")
266606c3fb27SDimitry Andric      << " /*IsRegularKeywordAttribute*/}";
266706c3fb27SDimitry Andric }
266806c3fb27SDimitry Andric 
26695ffd83dbSDimitry Andric static void emitAttributes(RecordKeeper &Records, raw_ostream &OS,
26705ffd83dbSDimitry Andric                            bool Header) {
26710b57cec5SDimitry Andric   std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
2672a7dea167SDimitry Andric   ParsedAttrMap AttrMap = getParsedAttrList(Records);
26730b57cec5SDimitry Andric 
2674fe6060f1SDimitry Andric   // Helper to print the starting character of an attribute argument. If there
2675fe6060f1SDimitry Andric   // hasn't been an argument yet, it prints an opening parenthese; otherwise it
2676fe6060f1SDimitry Andric   // prints a comma.
2677fe6060f1SDimitry Andric   OS << "static inline void DelimitAttributeArgument("
2678fe6060f1SDimitry Andric      << "raw_ostream& OS, bool& IsFirst) {\n"
2679fe6060f1SDimitry Andric      << "  if (IsFirst) {\n"
2680fe6060f1SDimitry Andric      << "    IsFirst = false;\n"
2681fe6060f1SDimitry Andric      << "    OS << \"(\";\n"
2682fe6060f1SDimitry Andric      << "  } else\n"
2683fe6060f1SDimitry Andric      << "    OS << \", \";\n"
2684fe6060f1SDimitry Andric      << "}\n";
2685fe6060f1SDimitry Andric 
26860b57cec5SDimitry Andric   for (const auto *Attr : Attrs) {
26870b57cec5SDimitry Andric     const Record &R = *Attr;
26880b57cec5SDimitry Andric 
26890b57cec5SDimitry Andric     // FIXME: Currently, documentation is generated as-needed due to the fact
26900b57cec5SDimitry Andric     // that there is no way to allow a generated project "reach into" the docs
26910b57cec5SDimitry Andric     // directory (for instance, it may be an out-of-tree build). However, we want
26920b57cec5SDimitry Andric     // to ensure that every attribute has a Documentation field, and produce an
26930b57cec5SDimitry Andric     // error if it has been neglected. Otherwise, the on-demand generation which
26940b57cec5SDimitry Andric     // happens server-side will fail. This code is ensuring that functionality,
26950b57cec5SDimitry Andric     // even though this Emitter doesn't technically need the documentation.
26960b57cec5SDimitry Andric     // When attribute documentation can be generated as part of the build
26970b57cec5SDimitry Andric     // itself, this code can be removed.
26980b57cec5SDimitry Andric     (void)R.getValueAsListOfDefs("Documentation");
26990b57cec5SDimitry Andric 
27000b57cec5SDimitry Andric     if (!R.getValueAsBit("ASTNode"))
27010b57cec5SDimitry Andric       continue;
27020b57cec5SDimitry Andric 
27030b57cec5SDimitry Andric     ArrayRef<std::pair<Record *, SMRange>> Supers = R.getSuperClasses();
27040b57cec5SDimitry Andric     assert(!Supers.empty() && "Forgot to specify a superclass for the attr");
27050b57cec5SDimitry Andric     std::string SuperName;
27060b57cec5SDimitry Andric     bool Inheritable = false;
27070b57cec5SDimitry Andric     for (const auto &Super : llvm::reverse(Supers)) {
27080b57cec5SDimitry Andric       const Record *R = Super.first;
27090b57cec5SDimitry Andric       if (R->getName() != "TargetSpecificAttr" &&
27100b57cec5SDimitry Andric           R->getName() != "DeclOrTypeAttr" && SuperName.empty())
27115ffd83dbSDimitry Andric         SuperName = std::string(R->getName());
27120b57cec5SDimitry Andric       if (R->getName() == "InheritableAttr")
27130b57cec5SDimitry Andric         Inheritable = true;
27140b57cec5SDimitry Andric     }
27150b57cec5SDimitry Andric 
27165ffd83dbSDimitry Andric     if (Header)
27170b57cec5SDimitry Andric       OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n";
27185ffd83dbSDimitry Andric     else
27195ffd83dbSDimitry Andric       OS << "\n// " << R.getName() << "Attr implementation\n\n";
27200b57cec5SDimitry Andric 
27210b57cec5SDimitry Andric     std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
27220b57cec5SDimitry Andric     std::vector<std::unique_ptr<Argument>> Args;
27230b57cec5SDimitry Andric     Args.reserve(ArgRecords.size());
27240b57cec5SDimitry Andric 
272581ad6265SDimitry Andric     bool AttrAcceptsExprPack = Attr->getValueAsBit("AcceptsExprPack");
272681ad6265SDimitry Andric     if (AttrAcceptsExprPack) {
272781ad6265SDimitry Andric       for (size_t I = 0; I < ArgRecords.size(); ++I) {
272881ad6265SDimitry Andric         const Record *ArgR = ArgRecords[I];
272981ad6265SDimitry Andric         if (isIdentifierArgument(ArgR) || isVariadicIdentifierArgument(ArgR) ||
273081ad6265SDimitry Andric             isTypeArgument(ArgR))
273181ad6265SDimitry Andric           PrintFatalError(Attr->getLoc(),
273281ad6265SDimitry Andric                           "Attributes accepting packs cannot also "
273381ad6265SDimitry Andric                           "have identifier or type arguments.");
273481ad6265SDimitry Andric         // When trying to determine if value-dependent expressions can populate
273581ad6265SDimitry Andric         // the attribute without prior instantiation, the decision is made based
273681ad6265SDimitry Andric         // on the assumption that only the last argument is ever variadic.
273781ad6265SDimitry Andric         if (I < (ArgRecords.size() - 1) && isVariadicExprArgument(ArgR))
273881ad6265SDimitry Andric           PrintFatalError(Attr->getLoc(),
273981ad6265SDimitry Andric                           "Attributes accepting packs can only have the last "
274081ad6265SDimitry Andric                           "argument be variadic.");
274181ad6265SDimitry Andric       }
274281ad6265SDimitry Andric     }
274381ad6265SDimitry Andric 
27440b57cec5SDimitry Andric     bool HasOptArg = false;
27450b57cec5SDimitry Andric     bool HasFakeArg = false;
27460b57cec5SDimitry Andric     for (const auto *ArgRecord : ArgRecords) {
27470b57cec5SDimitry Andric       Args.emplace_back(createArgument(*ArgRecord, R.getName()));
27485ffd83dbSDimitry Andric       if (Header) {
27490b57cec5SDimitry Andric         Args.back()->writeDeclarations(OS);
27500b57cec5SDimitry Andric         OS << "\n\n";
27515ffd83dbSDimitry Andric       }
27520b57cec5SDimitry Andric 
27530b57cec5SDimitry Andric       // For these purposes, fake takes priority over optional.
27540b57cec5SDimitry Andric       if (Args.back()->isFake()) {
27550b57cec5SDimitry Andric         HasFakeArg = true;
27560b57cec5SDimitry Andric       } else if (Args.back()->isOptional()) {
27570b57cec5SDimitry Andric         HasOptArg = true;
27580b57cec5SDimitry Andric       }
27590b57cec5SDimitry Andric     }
27600b57cec5SDimitry Andric 
276181ad6265SDimitry Andric     std::unique_ptr<VariadicExprArgument> DelayedArgs = nullptr;
276281ad6265SDimitry Andric     if (AttrAcceptsExprPack) {
276381ad6265SDimitry Andric       DelayedArgs =
276481ad6265SDimitry Andric           std::make_unique<VariadicExprArgument>("DelayedArgs", R.getName());
276581ad6265SDimitry Andric       if (Header) {
276681ad6265SDimitry Andric         DelayedArgs->writeDeclarations(OS);
276781ad6265SDimitry Andric         OS << "\n\n";
276881ad6265SDimitry Andric       }
276981ad6265SDimitry Andric     }
277081ad6265SDimitry Andric 
27715ffd83dbSDimitry Andric     if (Header)
27720b57cec5SDimitry Andric       OS << "public:\n";
27730b57cec5SDimitry Andric 
27740b57cec5SDimitry Andric     std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
27750b57cec5SDimitry Andric 
27760b57cec5SDimitry Andric     // If there are zero or one spellings, all spelling-related functionality
27770b57cec5SDimitry Andric     // can be elided. If all of the spellings share the same name, the spelling
27780b57cec5SDimitry Andric     // functionality can also be elided.
27790b57cec5SDimitry Andric     bool ElideSpelling = (Spellings.size() <= 1) ||
27800b57cec5SDimitry Andric                          SpellingNamesAreCommon(Spellings);
27810b57cec5SDimitry Andric 
27820b57cec5SDimitry Andric     // This maps spelling index values to semantic Spelling enumerants.
27830b57cec5SDimitry Andric     SemanticSpellingMap SemanticToSyntacticMap;
27840b57cec5SDimitry Andric 
27855ffd83dbSDimitry Andric     std::string SpellingEnum;
27865ffd83dbSDimitry Andric     if (Spellings.size() > 1)
27875ffd83dbSDimitry Andric       SpellingEnum = CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);
27885ffd83dbSDimitry Andric     if (Header)
27895ffd83dbSDimitry Andric       OS << SpellingEnum;
27900b57cec5SDimitry Andric 
2791a7dea167SDimitry Andric     const auto &ParsedAttrSpellingItr = llvm::find_if(
2792a7dea167SDimitry Andric         AttrMap, [R](const std::pair<std::string, const Record *> &P) {
2793a7dea167SDimitry Andric           return &R == P.second;
2794a7dea167SDimitry Andric         });
2795a7dea167SDimitry Andric 
27960b57cec5SDimitry Andric     // Emit CreateImplicit factory methods.
279781ad6265SDimitry Andric     auto emitCreate = [&](bool Implicit, bool DelayedArgsOnly, bool emitFake) {
27985ffd83dbSDimitry Andric       if (Header)
27995ffd83dbSDimitry Andric         OS << "  static ";
28005ffd83dbSDimitry Andric       OS << R.getName() << "Attr *";
28015ffd83dbSDimitry Andric       if (!Header)
28025ffd83dbSDimitry Andric         OS << R.getName() << "Attr::";
28035ffd83dbSDimitry Andric       OS << "Create";
2804a7dea167SDimitry Andric       if (Implicit)
2805a7dea167SDimitry Andric         OS << "Implicit";
280681ad6265SDimitry Andric       if (DelayedArgsOnly)
280781ad6265SDimitry Andric         OS << "WithDelayedArgs";
2808a7dea167SDimitry Andric       OS << "(";
28090b57cec5SDimitry Andric       OS << "ASTContext &Ctx";
281081ad6265SDimitry Andric       if (!DelayedArgsOnly) {
28110b57cec5SDimitry Andric         for (auto const &ai : Args) {
281281ad6265SDimitry Andric           if (ai->isFake() && !emitFake)
281381ad6265SDimitry Andric             continue;
28140b57cec5SDimitry Andric           OS << ", ";
28150b57cec5SDimitry Andric           ai->writeCtorParameters(OS);
28160b57cec5SDimitry Andric         }
281781ad6265SDimitry Andric       } else {
281881ad6265SDimitry Andric         OS << ", ";
281981ad6265SDimitry Andric         DelayedArgs->writeCtorParameters(OS);
282081ad6265SDimitry Andric       }
28215ffd83dbSDimitry Andric       OS << ", const AttributeCommonInfo &CommonInfo";
28225ffd83dbSDimitry Andric       OS << ")";
28235ffd83dbSDimitry Andric       if (Header) {
28245ffd83dbSDimitry Andric         OS << ";\n";
28255ffd83dbSDimitry Andric         return;
28265ffd83dbSDimitry Andric       }
28275ffd83dbSDimitry Andric 
28285ffd83dbSDimitry Andric       OS << " {\n";
28290b57cec5SDimitry Andric       OS << "  auto *A = new (Ctx) " << R.getName();
2830a7dea167SDimitry Andric       OS << "Attr(Ctx, CommonInfo";
283106c3fb27SDimitry Andric 
283281ad6265SDimitry Andric       if (!DelayedArgsOnly) {
28330b57cec5SDimitry Andric         for (auto const &ai : Args) {
283481ad6265SDimitry Andric           if (ai->isFake() && !emitFake)
283581ad6265SDimitry Andric             continue;
28360b57cec5SDimitry Andric           OS << ", ";
2837a7dea167SDimitry Andric           ai->writeImplicitCtorArgs(OS);
28380b57cec5SDimitry Andric         }
283981ad6265SDimitry Andric       }
2840a7dea167SDimitry Andric       OS << ");\n";
2841a7dea167SDimitry Andric       if (Implicit) {
28420b57cec5SDimitry Andric         OS << "  A->setImplicit(true);\n";
2843a7dea167SDimitry Andric       }
2844a7dea167SDimitry Andric       if (Implicit || ElideSpelling) {
2845a7dea167SDimitry Andric         OS << "  if (!A->isAttributeSpellingListCalculated() && "
2846a7dea167SDimitry Andric               "!A->getAttrName())\n";
2847a7dea167SDimitry Andric         OS << "    A->setAttributeSpellingListIndex(0);\n";
2848a7dea167SDimitry Andric       }
284981ad6265SDimitry Andric       if (DelayedArgsOnly) {
285081ad6265SDimitry Andric         OS << "  A->setDelayedArgs(Ctx, ";
285181ad6265SDimitry Andric         DelayedArgs->writeImplicitCtorArgs(OS);
285281ad6265SDimitry Andric         OS << ");\n";
285381ad6265SDimitry Andric       }
28540b57cec5SDimitry Andric       OS << "  return A;\n}\n\n";
28550b57cec5SDimitry Andric     };
28560b57cec5SDimitry Andric 
285781ad6265SDimitry Andric     auto emitCreateNoCI = [&](bool Implicit, bool DelayedArgsOnly,
285881ad6265SDimitry Andric                               bool emitFake) {
28595ffd83dbSDimitry Andric       if (Header)
28605ffd83dbSDimitry Andric         OS << "  static ";
28615ffd83dbSDimitry Andric       OS << R.getName() << "Attr *";
28625ffd83dbSDimitry Andric       if (!Header)
28635ffd83dbSDimitry Andric         OS << R.getName() << "Attr::";
28645ffd83dbSDimitry Andric       OS << "Create";
2865a7dea167SDimitry Andric       if (Implicit)
2866a7dea167SDimitry Andric         OS << "Implicit";
286781ad6265SDimitry Andric       if (DelayedArgsOnly)
286881ad6265SDimitry Andric         OS << "WithDelayedArgs";
2869a7dea167SDimitry Andric       OS << "(";
2870a7dea167SDimitry Andric       OS << "ASTContext &Ctx";
287181ad6265SDimitry Andric       if (!DelayedArgsOnly) {
2872a7dea167SDimitry Andric         for (auto const &ai : Args) {
287381ad6265SDimitry Andric           if (ai->isFake() && !emitFake)
287481ad6265SDimitry Andric             continue;
2875a7dea167SDimitry Andric           OS << ", ";
2876a7dea167SDimitry Andric           ai->writeCtorParameters(OS);
2877a7dea167SDimitry Andric         }
287881ad6265SDimitry Andric       } else {
287981ad6265SDimitry Andric         OS << ", ";
288081ad6265SDimitry Andric         DelayedArgs->writeCtorParameters(OS);
288181ad6265SDimitry Andric       }
288206c3fb27SDimitry Andric       OS << ", SourceRange Range";
28835ffd83dbSDimitry Andric       if (Header)
288406c3fb27SDimitry Andric         OS << " = {}";
288506c3fb27SDimitry Andric       if (Spellings.size() > 1) {
288606c3fb27SDimitry Andric         OS << ", Spelling S";
288706c3fb27SDimitry Andric         if (Header)
288806c3fb27SDimitry Andric           OS << " = " << SemanticToSyntacticMap[0];
28895ffd83dbSDimitry Andric       }
28905ffd83dbSDimitry Andric       OS << ")";
28915ffd83dbSDimitry Andric       if (Header) {
28925ffd83dbSDimitry Andric         OS << ";\n";
28935ffd83dbSDimitry Andric         return;
28945ffd83dbSDimitry Andric       }
28955ffd83dbSDimitry Andric 
28965ffd83dbSDimitry Andric       OS << " {\n";
2897a7dea167SDimitry Andric       OS << "  AttributeCommonInfo I(Range, ";
2898a7dea167SDimitry Andric 
2899a7dea167SDimitry Andric       if (ParsedAttrSpellingItr != std::end(AttrMap))
2900a7dea167SDimitry Andric         OS << "AT_" << ParsedAttrSpellingItr->first;
2901a7dea167SDimitry Andric       else
2902a7dea167SDimitry Andric         OS << "NoSemaHandlerAttribute";
2903a7dea167SDimitry Andric 
290406c3fb27SDimitry Andric       if (Spellings.size() == 0) {
290506c3fb27SDimitry Andric         OS << ", AttributeCommonInfo::Form::Implicit()";
290606c3fb27SDimitry Andric       } else if (Spellings.size() == 1) {
290706c3fb27SDimitry Andric         OS << ", ";
290806c3fb27SDimitry Andric         emitFormInitializer(OS, Spellings[0], "0");
290906c3fb27SDimitry Andric       } else {
2910bdb86d1aSDimitry Andric         OS << ", [&]() {\n";
2911bdb86d1aSDimitry Andric         OS << "    switch (S) {\n";
291206c3fb27SDimitry Andric         std::set<std::string> Uniques;
291306c3fb27SDimitry Andric         unsigned Idx = 0;
291406c3fb27SDimitry Andric         for (auto I = Spellings.begin(), E = Spellings.end(); I != E;
291506c3fb27SDimitry Andric              ++I, ++Idx) {
291606c3fb27SDimitry Andric           const FlattenedSpelling &S = *I;
291706c3fb27SDimitry Andric           const auto &Name = SemanticToSyntacticMap[Idx];
291806c3fb27SDimitry Andric           if (Uniques.insert(Name).second) {
2919bdb86d1aSDimitry Andric             OS << "    case " << Name << ":\n";
2920bdb86d1aSDimitry Andric             OS << "      return AttributeCommonInfo::Form";
292106c3fb27SDimitry Andric             emitFormInitializer(OS, S, Name);
2922bdb86d1aSDimitry Andric             OS << ";\n";
292306c3fb27SDimitry Andric           }
292406c3fb27SDimitry Andric         }
2925bdb86d1aSDimitry Andric         OS << "    default:\n";
2926bdb86d1aSDimitry Andric         OS << "      llvm_unreachable(\"Unknown attribute spelling!\");\n"
2927bdb86d1aSDimitry Andric            << "      return AttributeCommonInfo::Form";
292806c3fb27SDimitry Andric         emitFormInitializer(OS, Spellings[0], "0");
2929bdb86d1aSDimitry Andric         OS << ";\n"
2930bdb86d1aSDimitry Andric            << "    }\n"
2931bdb86d1aSDimitry Andric            << "  }()";
293206c3fb27SDimitry Andric       }
293306c3fb27SDimitry Andric 
2934a7dea167SDimitry Andric       OS << ");\n";
2935a7dea167SDimitry Andric       OS << "  return Create";
2936a7dea167SDimitry Andric       if (Implicit)
2937a7dea167SDimitry Andric         OS << "Implicit";
293881ad6265SDimitry Andric       if (DelayedArgsOnly)
293981ad6265SDimitry Andric         OS << "WithDelayedArgs";
2940a7dea167SDimitry Andric       OS << "(Ctx";
294181ad6265SDimitry Andric       if (!DelayedArgsOnly) {
2942a7dea167SDimitry Andric         for (auto const &ai : Args) {
294381ad6265SDimitry Andric           if (ai->isFake() && !emitFake)
294481ad6265SDimitry Andric             continue;
2945a7dea167SDimitry Andric           OS << ", ";
2946a7dea167SDimitry Andric           ai->writeImplicitCtorArgs(OS);
2947a7dea167SDimitry Andric         }
294881ad6265SDimitry Andric       } else {
294981ad6265SDimitry Andric         OS << ", ";
295081ad6265SDimitry Andric         DelayedArgs->writeImplicitCtorArgs(OS);
295181ad6265SDimitry Andric       }
2952a7dea167SDimitry Andric       OS << ", I);\n";
29535ffd83dbSDimitry Andric       OS << "}\n\n";
2954a7dea167SDimitry Andric     };
2955a7dea167SDimitry Andric 
295681ad6265SDimitry Andric     auto emitCreates = [&](bool DelayedArgsOnly, bool emitFake) {
295781ad6265SDimitry Andric       emitCreate(true, DelayedArgsOnly, emitFake);
295881ad6265SDimitry Andric       emitCreate(false, DelayedArgsOnly, emitFake);
295981ad6265SDimitry Andric       emitCreateNoCI(true, DelayedArgsOnly, emitFake);
296081ad6265SDimitry Andric       emitCreateNoCI(false, DelayedArgsOnly, emitFake);
2961a7dea167SDimitry Andric     };
2962a7dea167SDimitry Andric 
29635ffd83dbSDimitry Andric     if (Header)
29645ffd83dbSDimitry Andric       OS << "  // Factory methods\n";
29655ffd83dbSDimitry Andric 
29660b57cec5SDimitry Andric     // Emit a CreateImplicit that takes all the arguments.
296781ad6265SDimitry Andric     emitCreates(false, true);
29680b57cec5SDimitry Andric 
29690b57cec5SDimitry Andric     // Emit a CreateImplicit that takes all the non-fake arguments.
2970a7dea167SDimitry Andric     if (HasFakeArg)
297181ad6265SDimitry Andric       emitCreates(false, false);
297281ad6265SDimitry Andric 
297381ad6265SDimitry Andric     // Emit a CreateWithDelayedArgs that takes only the dependent argument
297481ad6265SDimitry Andric     // expressions.
297581ad6265SDimitry Andric     if (DelayedArgs)
297681ad6265SDimitry Andric       emitCreates(true, false);
29770b57cec5SDimitry Andric 
29780b57cec5SDimitry Andric     // Emit constructors.
297981ad6265SDimitry Andric     auto emitCtor = [&](bool emitOpt, bool emitFake, bool emitNoArgs) {
29800b57cec5SDimitry Andric       auto shouldEmitArg = [=](const std::unique_ptr<Argument> &arg) {
298181ad6265SDimitry Andric         if (emitNoArgs)
298281ad6265SDimitry Andric           return false;
298381ad6265SDimitry Andric         if (arg->isFake())
298481ad6265SDimitry Andric           return emitFake;
298581ad6265SDimitry Andric         if (arg->isOptional())
298681ad6265SDimitry Andric           return emitOpt;
29870b57cec5SDimitry Andric         return true;
29880b57cec5SDimitry Andric       };
29895ffd83dbSDimitry Andric       if (Header)
29905ffd83dbSDimitry Andric         OS << "  ";
29915ffd83dbSDimitry Andric       else
29925ffd83dbSDimitry Andric         OS << R.getName() << "Attr::";
29935ffd83dbSDimitry Andric       OS << R.getName()
2994a7dea167SDimitry Andric          << "Attr(ASTContext &Ctx, const AttributeCommonInfo &CommonInfo";
2995a7dea167SDimitry Andric       OS << '\n';
29960b57cec5SDimitry Andric       for (auto const &ai : Args) {
299781ad6265SDimitry Andric         if (!shouldEmitArg(ai))
299881ad6265SDimitry Andric           continue;
29990b57cec5SDimitry Andric         OS << "              , ";
30000b57cec5SDimitry Andric         ai->writeCtorParameters(OS);
30010b57cec5SDimitry Andric         OS << "\n";
30020b57cec5SDimitry Andric       }
30030b57cec5SDimitry Andric 
30045ffd83dbSDimitry Andric       OS << "             )";
30055ffd83dbSDimitry Andric       if (Header) {
30065ffd83dbSDimitry Andric         OS << ";\n";
30075ffd83dbSDimitry Andric         return;
30085ffd83dbSDimitry Andric       }
30095ffd83dbSDimitry Andric       OS << "\n  : " << SuperName << "(Ctx, CommonInfo, ";
3010*0fca6ea1SDimitry Andric       OS << "attr::" << R.getName() << ", ";
3011*0fca6ea1SDimitry Andric 
3012*0fca6ea1SDimitry Andric       // Handle different late parsing modes.
3013*0fca6ea1SDimitry Andric       OS << "/*IsLateParsed=*/";
3014*0fca6ea1SDimitry Andric       switch (getLateAttrParseKind(&R)) {
3015*0fca6ea1SDimitry Andric       case LateAttrParseKind::Never:
3016*0fca6ea1SDimitry Andric         OS << "false";
3017*0fca6ea1SDimitry Andric         break;
3018*0fca6ea1SDimitry Andric       case LateAttrParseKind::ExperimentalExt:
3019*0fca6ea1SDimitry Andric         // Currently no clients need to know the distinction between `Standard`
3020*0fca6ea1SDimitry Andric         // and `ExperimentalExt` so treat `ExperimentalExt` just like
3021*0fca6ea1SDimitry Andric         // `Standard` for now.
3022*0fca6ea1SDimitry Andric       case LateAttrParseKind::Standard:
3023*0fca6ea1SDimitry Andric         // Note: This is misleading. `IsLateParsed` doesn't mean the
3024*0fca6ea1SDimitry Andric         // attribute was actually late parsed. Instead it means the attribute in
3025*0fca6ea1SDimitry Andric         // `Attr.td` is marked as being late parsed. Maybe it should be called
3026*0fca6ea1SDimitry Andric         // `IsLateParseable`?
3027*0fca6ea1SDimitry Andric         OS << "true";
3028*0fca6ea1SDimitry Andric         break;
3029*0fca6ea1SDimitry Andric       }
3030*0fca6ea1SDimitry Andric 
30310b57cec5SDimitry Andric       if (Inheritable) {
30320b57cec5SDimitry Andric         OS << ", "
30330b57cec5SDimitry Andric            << (R.getValueAsBit("InheritEvenIfAlreadyPresent") ? "true"
30340b57cec5SDimitry Andric                                                               : "false");
30350b57cec5SDimitry Andric       }
30360b57cec5SDimitry Andric       OS << ")\n";
30370b57cec5SDimitry Andric 
30380b57cec5SDimitry Andric       for (auto const &ai : Args) {
30390b57cec5SDimitry Andric         OS << "              , ";
30400b57cec5SDimitry Andric         if (!shouldEmitArg(ai)) {
30410b57cec5SDimitry Andric           ai->writeCtorDefaultInitializers(OS);
30420b57cec5SDimitry Andric         } else {
30430b57cec5SDimitry Andric           ai->writeCtorInitializers(OS);
30440b57cec5SDimitry Andric         }
30450b57cec5SDimitry Andric         OS << "\n";
30460b57cec5SDimitry Andric       }
304781ad6265SDimitry Andric       if (DelayedArgs) {
304881ad6265SDimitry Andric         OS << "              , ";
304981ad6265SDimitry Andric         DelayedArgs->writeCtorDefaultInitializers(OS);
305081ad6265SDimitry Andric         OS << "\n";
305181ad6265SDimitry Andric       }
30520b57cec5SDimitry Andric 
30530b57cec5SDimitry Andric       OS << "  {\n";
30540b57cec5SDimitry Andric 
30550b57cec5SDimitry Andric       for (auto const &ai : Args) {
305681ad6265SDimitry Andric         if (!shouldEmitArg(ai))
305781ad6265SDimitry Andric           continue;
30580b57cec5SDimitry Andric         ai->writeCtorBody(OS);
30590b57cec5SDimitry Andric       }
30600b57cec5SDimitry Andric       OS << "}\n\n";
30610b57cec5SDimitry Andric     };
30620b57cec5SDimitry Andric 
30635ffd83dbSDimitry Andric     if (Header)
30645ffd83dbSDimitry Andric       OS << "\n  // Constructors\n";
30655ffd83dbSDimitry Andric 
30660b57cec5SDimitry Andric     // Emit a constructor that includes all the arguments.
30670b57cec5SDimitry Andric     // This is necessary for cloning.
306881ad6265SDimitry Andric     emitCtor(true, true, false);
30690b57cec5SDimitry Andric 
30700b57cec5SDimitry Andric     // Emit a constructor that takes all the non-fake arguments.
3071a7dea167SDimitry Andric     if (HasFakeArg)
307281ad6265SDimitry Andric       emitCtor(true, false, false);
30730b57cec5SDimitry Andric 
30740b57cec5SDimitry Andric     // Emit a constructor that takes all the non-fake, non-optional arguments.
3075a7dea167SDimitry Andric     if (HasOptArg)
307681ad6265SDimitry Andric       emitCtor(false, false, false);
307781ad6265SDimitry Andric 
307881ad6265SDimitry Andric     // Emit constructors that takes no arguments if none already exists.
307981ad6265SDimitry Andric     // This is used for delaying arguments.
3080bdd1243dSDimitry Andric     bool HasRequiredArgs =
3081bdd1243dSDimitry Andric         llvm::count_if(Args, [=](const std::unique_ptr<Argument> &arg) {
308281ad6265SDimitry Andric           return !arg->isFake() && !arg->isOptional();
308381ad6265SDimitry Andric         });
308481ad6265SDimitry Andric     if (DelayedArgs && HasRequiredArgs)
308581ad6265SDimitry Andric       emitCtor(false, false, true);
30860b57cec5SDimitry Andric 
30875ffd83dbSDimitry Andric     if (Header) {
30885ffd83dbSDimitry Andric       OS << '\n';
30890b57cec5SDimitry Andric       OS << "  " << R.getName() << "Attr *clone(ASTContext &C) const;\n";
30900b57cec5SDimitry Andric       OS << "  void printPretty(raw_ostream &OS,\n"
30910b57cec5SDimitry Andric          << "                   const PrintingPolicy &Policy) const;\n";
30920b57cec5SDimitry Andric       OS << "  const char *getSpelling() const;\n";
30935ffd83dbSDimitry Andric     }
30940b57cec5SDimitry Andric 
30950b57cec5SDimitry Andric     if (!ElideSpelling) {
30960b57cec5SDimitry Andric       assert(!SemanticToSyntacticMap.empty() && "Empty semantic mapping list");
30975ffd83dbSDimitry Andric       if (Header)
30985ffd83dbSDimitry Andric         OS << "  Spelling getSemanticSpelling() const;\n";
30995ffd83dbSDimitry Andric       else {
31005ffd83dbSDimitry Andric         OS << R.getName() << "Attr::Spelling " << R.getName()
31015ffd83dbSDimitry Andric            << "Attr::getSemanticSpelling() const {\n";
3102a7dea167SDimitry Andric         WriteSemanticSpellingSwitch("getAttributeSpellingListIndex()",
3103a7dea167SDimitry Andric                                     SemanticToSyntacticMap, OS);
31040b57cec5SDimitry Andric         OS << "}\n";
31050b57cec5SDimitry Andric       }
31065ffd83dbSDimitry Andric     }
31070b57cec5SDimitry Andric 
31085ffd83dbSDimitry Andric     if (Header)
31090b57cec5SDimitry Andric       writeAttrAccessorDefinition(R, OS);
31100b57cec5SDimitry Andric 
31110b57cec5SDimitry Andric     for (auto const &ai : Args) {
31125ffd83dbSDimitry Andric       if (Header) {
31130b57cec5SDimitry Andric         ai->writeAccessors(OS);
31145ffd83dbSDimitry Andric       } else {
31155ffd83dbSDimitry Andric         ai->writeAccessorDefinitions(OS);
31165ffd83dbSDimitry Andric       }
31170b57cec5SDimitry Andric       OS << "\n\n";
31180b57cec5SDimitry Andric 
31190b57cec5SDimitry Andric       // Don't write conversion routines for fake arguments.
31200b57cec5SDimitry Andric       if (ai->isFake()) continue;
31210b57cec5SDimitry Andric 
31220b57cec5SDimitry Andric       if (ai->isEnumArg())
31235ffd83dbSDimitry Andric         static_cast<const EnumArgument *>(ai.get())->writeConversion(OS,
31245ffd83dbSDimitry Andric                                                                      Header);
31250b57cec5SDimitry Andric       else if (ai->isVariadicEnumArg())
31265ffd83dbSDimitry Andric         static_cast<const VariadicEnumArgument *>(ai.get())->writeConversion(
31275ffd83dbSDimitry Andric             OS, Header);
31280b57cec5SDimitry Andric     }
31290b57cec5SDimitry Andric 
31305ffd83dbSDimitry Andric     if (Header) {
313181ad6265SDimitry Andric       if (DelayedArgs) {
313281ad6265SDimitry Andric         DelayedArgs->writeAccessors(OS);
313381ad6265SDimitry Andric         DelayedArgs->writeSetter(OS);
313481ad6265SDimitry Andric       }
313581ad6265SDimitry Andric 
31360b57cec5SDimitry Andric       OS << R.getValueAsString("AdditionalMembers");
31370b57cec5SDimitry Andric       OS << "\n\n";
31380b57cec5SDimitry Andric 
31390b57cec5SDimitry Andric       OS << "  static bool classof(const Attr *A) { return A->getKind() == "
31400b57cec5SDimitry Andric          << "attr::" << R.getName() << "; }\n";
31410b57cec5SDimitry Andric 
31420b57cec5SDimitry Andric       OS << "};\n\n";
31435ffd83dbSDimitry Andric     } else {
314481ad6265SDimitry Andric       if (DelayedArgs)
314581ad6265SDimitry Andric         DelayedArgs->writeAccessorDefinitions(OS);
314681ad6265SDimitry Andric 
31470b57cec5SDimitry Andric       OS << R.getName() << "Attr *" << R.getName()
31480b57cec5SDimitry Andric          << "Attr::clone(ASTContext &C) const {\n";
3149a7dea167SDimitry Andric       OS << "  auto *A = new (C) " << R.getName() << "Attr(C, *this";
31500b57cec5SDimitry Andric       for (auto const &ai : Args) {
31510b57cec5SDimitry Andric         OS << ", ";
31520b57cec5SDimitry Andric         ai->writeCloneArgs(OS);
31530b57cec5SDimitry Andric       }
3154a7dea167SDimitry Andric       OS << ");\n";
31550b57cec5SDimitry Andric       OS << "  A->Inherited = Inherited;\n";
31560b57cec5SDimitry Andric       OS << "  A->IsPackExpansion = IsPackExpansion;\n";
3157a7dea167SDimitry Andric       OS << "  A->setImplicit(Implicit);\n";
315881ad6265SDimitry Andric       if (DelayedArgs) {
315981ad6265SDimitry Andric         OS << "  A->setDelayedArgs(C, ";
316081ad6265SDimitry Andric         DelayedArgs->writeCloneArgs(OS);
316181ad6265SDimitry Andric         OS << ");\n";
316281ad6265SDimitry Andric       }
31630b57cec5SDimitry Andric       OS << "  return A;\n}\n\n";
31640b57cec5SDimitry Andric 
31650b57cec5SDimitry Andric       writePrettyPrintFunction(R, Args, OS);
31660b57cec5SDimitry Andric       writeGetSpellingFunction(R, OS);
31670b57cec5SDimitry Andric     }
31685ffd83dbSDimitry Andric   }
31695ffd83dbSDimitry Andric }
31705ffd83dbSDimitry Andric // Emits the class definitions for attributes.
31715ffd83dbSDimitry Andric void clang::EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
31725f757f3fSDimitry Andric   emitSourceFileHeader("Attribute classes' definitions", OS, Records);
31735ffd83dbSDimitry Andric 
31745ffd83dbSDimitry Andric   OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
31755ffd83dbSDimitry Andric   OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
31765ffd83dbSDimitry Andric 
31775ffd83dbSDimitry Andric   emitAttributes(Records, OS, true);
31785ffd83dbSDimitry Andric 
31795ffd83dbSDimitry Andric   OS << "#endif // LLVM_CLANG_ATTR_CLASSES_INC\n";
31805ffd83dbSDimitry Andric }
31815ffd83dbSDimitry Andric 
31825ffd83dbSDimitry Andric // Emits the class method definitions for attributes.
31835ffd83dbSDimitry Andric void clang::EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
31845f757f3fSDimitry Andric   emitSourceFileHeader("Attribute classes' member function definitions", OS,
31855f757f3fSDimitry Andric                        Records);
31865ffd83dbSDimitry Andric 
31875ffd83dbSDimitry Andric   emitAttributes(Records, OS, false);
31885ffd83dbSDimitry Andric 
31895ffd83dbSDimitry Andric   std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
31900b57cec5SDimitry Andric 
31910b57cec5SDimitry Andric   // Instead of relying on virtual dispatch we just create a huge dispatch
31920b57cec5SDimitry Andric   // switch. This is both smaller and faster than virtual functions.
31930b57cec5SDimitry Andric   auto EmitFunc = [&](const char *Method) {
31940b57cec5SDimitry Andric     OS << "  switch (getKind()) {\n";
31950b57cec5SDimitry Andric     for (const auto *Attr : Attrs) {
31960b57cec5SDimitry Andric       const Record &R = *Attr;
31970b57cec5SDimitry Andric       if (!R.getValueAsBit("ASTNode"))
31980b57cec5SDimitry Andric         continue;
31990b57cec5SDimitry Andric 
32000b57cec5SDimitry Andric       OS << "  case attr::" << R.getName() << ":\n";
32010b57cec5SDimitry Andric       OS << "    return cast<" << R.getName() << "Attr>(this)->" << Method
32020b57cec5SDimitry Andric          << ";\n";
32030b57cec5SDimitry Andric     }
32040b57cec5SDimitry Andric     OS << "  }\n";
32050b57cec5SDimitry Andric     OS << "  llvm_unreachable(\"Unexpected attribute kind!\");\n";
32060b57cec5SDimitry Andric     OS << "}\n\n";
32070b57cec5SDimitry Andric   };
32080b57cec5SDimitry Andric 
32090b57cec5SDimitry Andric   OS << "const char *Attr::getSpelling() const {\n";
32100b57cec5SDimitry Andric   EmitFunc("getSpelling()");
32110b57cec5SDimitry Andric 
32120b57cec5SDimitry Andric   OS << "Attr *Attr::clone(ASTContext &C) const {\n";
32130b57cec5SDimitry Andric   EmitFunc("clone(C)");
32140b57cec5SDimitry Andric 
32150b57cec5SDimitry Andric   OS << "void Attr::printPretty(raw_ostream &OS, "
32160b57cec5SDimitry Andric         "const PrintingPolicy &Policy) const {\n";
32170b57cec5SDimitry Andric   EmitFunc("printPretty(OS, Policy)");
32180b57cec5SDimitry Andric }
32190b57cec5SDimitry Andric 
32200b57cec5SDimitry Andric static void emitAttrList(raw_ostream &OS, StringRef Class,
32210b57cec5SDimitry Andric                          const std::vector<Record*> &AttrList) {
32220b57cec5SDimitry Andric   for (auto Cur : AttrList) {
32230b57cec5SDimitry Andric     OS << Class << "(" << Cur->getName() << ")\n";
32240b57cec5SDimitry Andric   }
32250b57cec5SDimitry Andric }
32260b57cec5SDimitry Andric 
32270b57cec5SDimitry Andric // Determines if an attribute has a Pragma spelling.
32280b57cec5SDimitry Andric static bool AttrHasPragmaSpelling(const Record *R) {
32290b57cec5SDimitry Andric   std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*R);
3230349cc55cSDimitry Andric   return llvm::any_of(Spellings, [](const FlattenedSpelling &S) {
32310b57cec5SDimitry Andric     return S.variety() == "Pragma";
3232349cc55cSDimitry Andric   });
32330b57cec5SDimitry Andric }
32340b57cec5SDimitry Andric 
32350b57cec5SDimitry Andric namespace {
32360b57cec5SDimitry Andric 
32370b57cec5SDimitry Andric   struct AttrClassDescriptor {
32380b57cec5SDimitry Andric     const char * const MacroName;
32390b57cec5SDimitry Andric     const char * const TableGenName;
32400b57cec5SDimitry Andric   };
32410b57cec5SDimitry Andric 
32420b57cec5SDimitry Andric } // end anonymous namespace
32430b57cec5SDimitry Andric 
32440b57cec5SDimitry Andric static const AttrClassDescriptor AttrClassDescriptors[] = {
32450b57cec5SDimitry Andric   { "ATTR", "Attr" },
32460b57cec5SDimitry Andric   { "TYPE_ATTR", "TypeAttr" },
32470b57cec5SDimitry Andric   { "STMT_ATTR", "StmtAttr" },
3248e8d8bef9SDimitry Andric   { "DECL_OR_STMT_ATTR", "DeclOrStmtAttr" },
32490b57cec5SDimitry Andric   { "INHERITABLE_ATTR", "InheritableAttr" },
32500b57cec5SDimitry Andric   { "DECL_OR_TYPE_ATTR", "DeclOrTypeAttr" },
32510b57cec5SDimitry Andric   { "INHERITABLE_PARAM_ATTR", "InheritableParamAttr" },
3252bdd1243dSDimitry Andric   { "PARAMETER_ABI_ATTR", "ParameterABIAttr" },
3253bdd1243dSDimitry Andric   { "HLSL_ANNOTATION_ATTR", "HLSLAnnotationAttr"}
32540b57cec5SDimitry Andric };
32550b57cec5SDimitry Andric 
32560b57cec5SDimitry Andric static void emitDefaultDefine(raw_ostream &OS, StringRef name,
32570b57cec5SDimitry Andric                               const char *superName) {
32580b57cec5SDimitry Andric   OS << "#ifndef " << name << "\n";
32590b57cec5SDimitry Andric   OS << "#define " << name << "(NAME) ";
32600b57cec5SDimitry Andric   if (superName) OS << superName << "(NAME)";
32610b57cec5SDimitry Andric   OS << "\n#endif\n\n";
32620b57cec5SDimitry Andric }
32630b57cec5SDimitry Andric 
32640b57cec5SDimitry Andric namespace {
32650b57cec5SDimitry Andric 
32660b57cec5SDimitry Andric   /// A class of attributes.
32670b57cec5SDimitry Andric   struct AttrClass {
32680b57cec5SDimitry Andric     const AttrClassDescriptor &Descriptor;
32690b57cec5SDimitry Andric     Record *TheRecord;
32700b57cec5SDimitry Andric     AttrClass *SuperClass = nullptr;
32710b57cec5SDimitry Andric     std::vector<AttrClass*> SubClasses;
32720b57cec5SDimitry Andric     std::vector<Record*> Attrs;
32730b57cec5SDimitry Andric 
32740b57cec5SDimitry Andric     AttrClass(const AttrClassDescriptor &Descriptor, Record *R)
32750b57cec5SDimitry Andric       : Descriptor(Descriptor), TheRecord(R) {}
32760b57cec5SDimitry Andric 
32770b57cec5SDimitry Andric     void emitDefaultDefines(raw_ostream &OS) const {
32780b57cec5SDimitry Andric       // Default the macro unless this is a root class (i.e. Attr).
32790b57cec5SDimitry Andric       if (SuperClass) {
32800b57cec5SDimitry Andric         emitDefaultDefine(OS, Descriptor.MacroName,
32810b57cec5SDimitry Andric                           SuperClass->Descriptor.MacroName);
32820b57cec5SDimitry Andric       }
32830b57cec5SDimitry Andric     }
32840b57cec5SDimitry Andric 
32850b57cec5SDimitry Andric     void emitUndefs(raw_ostream &OS) const {
32860b57cec5SDimitry Andric       OS << "#undef " << Descriptor.MacroName << "\n";
32870b57cec5SDimitry Andric     }
32880b57cec5SDimitry Andric 
32890b57cec5SDimitry Andric     void emitAttrList(raw_ostream &OS) const {
32900b57cec5SDimitry Andric       for (auto SubClass : SubClasses) {
32910b57cec5SDimitry Andric         SubClass->emitAttrList(OS);
32920b57cec5SDimitry Andric       }
32930b57cec5SDimitry Andric 
32940b57cec5SDimitry Andric       ::emitAttrList(OS, Descriptor.MacroName, Attrs);
32950b57cec5SDimitry Andric     }
32960b57cec5SDimitry Andric 
32970b57cec5SDimitry Andric     void classifyAttrOnRoot(Record *Attr) {
32980b57cec5SDimitry Andric       bool result = classifyAttr(Attr);
32990b57cec5SDimitry Andric       assert(result && "failed to classify on root"); (void) result;
33000b57cec5SDimitry Andric     }
33010b57cec5SDimitry Andric 
33020b57cec5SDimitry Andric     void emitAttrRange(raw_ostream &OS) const {
33030b57cec5SDimitry Andric       OS << "ATTR_RANGE(" << Descriptor.TableGenName
33040b57cec5SDimitry Andric          << ", " << getFirstAttr()->getName()
33050b57cec5SDimitry Andric          << ", " << getLastAttr()->getName() << ")\n";
33060b57cec5SDimitry Andric     }
33070b57cec5SDimitry Andric 
33080b57cec5SDimitry Andric   private:
33090b57cec5SDimitry Andric     bool classifyAttr(Record *Attr) {
33100b57cec5SDimitry Andric       // Check all the subclasses.
33110b57cec5SDimitry Andric       for (auto SubClass : SubClasses) {
33120b57cec5SDimitry Andric         if (SubClass->classifyAttr(Attr))
33130b57cec5SDimitry Andric           return true;
33140b57cec5SDimitry Andric       }
33150b57cec5SDimitry Andric 
33160b57cec5SDimitry Andric       // It's not more specific than this class, but it might still belong here.
33170b57cec5SDimitry Andric       if (Attr->isSubClassOf(TheRecord)) {
33180b57cec5SDimitry Andric         Attrs.push_back(Attr);
33190b57cec5SDimitry Andric         return true;
33200b57cec5SDimitry Andric       }
33210b57cec5SDimitry Andric 
33220b57cec5SDimitry Andric       return false;
33230b57cec5SDimitry Andric     }
33240b57cec5SDimitry Andric 
33250b57cec5SDimitry Andric     Record *getFirstAttr() const {
33260b57cec5SDimitry Andric       if (!SubClasses.empty())
33270b57cec5SDimitry Andric         return SubClasses.front()->getFirstAttr();
33280b57cec5SDimitry Andric       return Attrs.front();
33290b57cec5SDimitry Andric     }
33300b57cec5SDimitry Andric 
33310b57cec5SDimitry Andric     Record *getLastAttr() const {
33320b57cec5SDimitry Andric       if (!Attrs.empty())
33330b57cec5SDimitry Andric         return Attrs.back();
33340b57cec5SDimitry Andric       return SubClasses.back()->getLastAttr();
33350b57cec5SDimitry Andric     }
33360b57cec5SDimitry Andric   };
33370b57cec5SDimitry Andric 
33380b57cec5SDimitry Andric   /// The entire hierarchy of attribute classes.
33390b57cec5SDimitry Andric   class AttrClassHierarchy {
33400b57cec5SDimitry Andric     std::vector<std::unique_ptr<AttrClass>> Classes;
33410b57cec5SDimitry Andric 
33420b57cec5SDimitry Andric   public:
33430b57cec5SDimitry Andric     AttrClassHierarchy(RecordKeeper &Records) {
33440b57cec5SDimitry Andric       // Find records for all the classes.
33450b57cec5SDimitry Andric       for (auto &Descriptor : AttrClassDescriptors) {
33460b57cec5SDimitry Andric         Record *ClassRecord = Records.getClass(Descriptor.TableGenName);
33470b57cec5SDimitry Andric         AttrClass *Class = new AttrClass(Descriptor, ClassRecord);
33480b57cec5SDimitry Andric         Classes.emplace_back(Class);
33490b57cec5SDimitry Andric       }
33500b57cec5SDimitry Andric 
33510b57cec5SDimitry Andric       // Link up the hierarchy.
33520b57cec5SDimitry Andric       for (auto &Class : Classes) {
33530b57cec5SDimitry Andric         if (AttrClass *SuperClass = findSuperClass(Class->TheRecord)) {
33540b57cec5SDimitry Andric           Class->SuperClass = SuperClass;
33550b57cec5SDimitry Andric           SuperClass->SubClasses.push_back(Class.get());
33560b57cec5SDimitry Andric         }
33570b57cec5SDimitry Andric       }
33580b57cec5SDimitry Andric 
33590b57cec5SDimitry Andric #ifndef NDEBUG
33600b57cec5SDimitry Andric       for (auto i = Classes.begin(), e = Classes.end(); i != e; ++i) {
33610b57cec5SDimitry Andric         assert((i == Classes.begin()) == ((*i)->SuperClass == nullptr) &&
33620b57cec5SDimitry Andric                "only the first class should be a root class!");
33630b57cec5SDimitry Andric       }
33640b57cec5SDimitry Andric #endif
33650b57cec5SDimitry Andric     }
33660b57cec5SDimitry Andric 
33670b57cec5SDimitry Andric     void emitDefaultDefines(raw_ostream &OS) const {
33680b57cec5SDimitry Andric       for (auto &Class : Classes) {
33690b57cec5SDimitry Andric         Class->emitDefaultDefines(OS);
33700b57cec5SDimitry Andric       }
33710b57cec5SDimitry Andric     }
33720b57cec5SDimitry Andric 
33730b57cec5SDimitry Andric     void emitUndefs(raw_ostream &OS) const {
33740b57cec5SDimitry Andric       for (auto &Class : Classes) {
33750b57cec5SDimitry Andric         Class->emitUndefs(OS);
33760b57cec5SDimitry Andric       }
33770b57cec5SDimitry Andric     }
33780b57cec5SDimitry Andric 
33790b57cec5SDimitry Andric     void emitAttrLists(raw_ostream &OS) const {
33800b57cec5SDimitry Andric       // Just start from the root class.
33810b57cec5SDimitry Andric       Classes[0]->emitAttrList(OS);
33820b57cec5SDimitry Andric     }
33830b57cec5SDimitry Andric 
33840b57cec5SDimitry Andric     void emitAttrRanges(raw_ostream &OS) const {
33850b57cec5SDimitry Andric       for (auto &Class : Classes)
33860b57cec5SDimitry Andric         Class->emitAttrRange(OS);
33870b57cec5SDimitry Andric     }
33880b57cec5SDimitry Andric 
33890b57cec5SDimitry Andric     void classifyAttr(Record *Attr) {
33900b57cec5SDimitry Andric       // Add the attribute to the root class.
33910b57cec5SDimitry Andric       Classes[0]->classifyAttrOnRoot(Attr);
33920b57cec5SDimitry Andric     }
33930b57cec5SDimitry Andric 
33940b57cec5SDimitry Andric   private:
33950b57cec5SDimitry Andric     AttrClass *findClassByRecord(Record *R) const {
33960b57cec5SDimitry Andric       for (auto &Class : Classes) {
33970b57cec5SDimitry Andric         if (Class->TheRecord == R)
33980b57cec5SDimitry Andric           return Class.get();
33990b57cec5SDimitry Andric       }
34000b57cec5SDimitry Andric       return nullptr;
34010b57cec5SDimitry Andric     }
34020b57cec5SDimitry Andric 
34030b57cec5SDimitry Andric     AttrClass *findSuperClass(Record *R) const {
34040b57cec5SDimitry Andric       // TableGen flattens the superclass list, so we just need to walk it
34050b57cec5SDimitry Andric       // in reverse.
34060b57cec5SDimitry Andric       auto SuperClasses = R->getSuperClasses();
34070b57cec5SDimitry Andric       for (signed i = 0, e = SuperClasses.size(); i != e; ++i) {
34080b57cec5SDimitry Andric         auto SuperClass = findClassByRecord(SuperClasses[e - i - 1].first);
34090b57cec5SDimitry Andric         if (SuperClass) return SuperClass;
34100b57cec5SDimitry Andric       }
34110b57cec5SDimitry Andric       return nullptr;
34120b57cec5SDimitry Andric     }
34130b57cec5SDimitry Andric   };
34140b57cec5SDimitry Andric 
34150b57cec5SDimitry Andric } // end anonymous namespace
34160b57cec5SDimitry Andric 
34170b57cec5SDimitry Andric namespace clang {
34180b57cec5SDimitry Andric 
34190b57cec5SDimitry Andric // Emits the enumeration list for attributes.
34200b57cec5SDimitry Andric void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) {
34215f757f3fSDimitry Andric   emitSourceFileHeader("List of all attributes that Clang recognizes", OS,
34225f757f3fSDimitry Andric                        Records);
34230b57cec5SDimitry Andric 
34240b57cec5SDimitry Andric   AttrClassHierarchy Hierarchy(Records);
34250b57cec5SDimitry Andric 
34260b57cec5SDimitry Andric   // Add defaulting macro definitions.
34270b57cec5SDimitry Andric   Hierarchy.emitDefaultDefines(OS);
34280b57cec5SDimitry Andric   emitDefaultDefine(OS, "PRAGMA_SPELLING_ATTR", nullptr);
34290b57cec5SDimitry Andric 
34300b57cec5SDimitry Andric   std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
34310b57cec5SDimitry Andric   std::vector<Record *> PragmaAttrs;
34320b57cec5SDimitry Andric   for (auto *Attr : Attrs) {
34330b57cec5SDimitry Andric     if (!Attr->getValueAsBit("ASTNode"))
34340b57cec5SDimitry Andric       continue;
34350b57cec5SDimitry Andric 
34360b57cec5SDimitry Andric     // Add the attribute to the ad-hoc groups.
34370b57cec5SDimitry Andric     if (AttrHasPragmaSpelling(Attr))
34380b57cec5SDimitry Andric       PragmaAttrs.push_back(Attr);
34390b57cec5SDimitry Andric 
34400b57cec5SDimitry Andric     // Place it in the hierarchy.
34410b57cec5SDimitry Andric     Hierarchy.classifyAttr(Attr);
34420b57cec5SDimitry Andric   }
34430b57cec5SDimitry Andric 
34440b57cec5SDimitry Andric   // Emit the main attribute list.
34450b57cec5SDimitry Andric   Hierarchy.emitAttrLists(OS);
34460b57cec5SDimitry Andric 
34470b57cec5SDimitry Andric   // Emit the ad hoc groups.
34480b57cec5SDimitry Andric   emitAttrList(OS, "PRAGMA_SPELLING_ATTR", PragmaAttrs);
34490b57cec5SDimitry Andric 
34500b57cec5SDimitry Andric   // Emit the attribute ranges.
34510b57cec5SDimitry Andric   OS << "#ifdef ATTR_RANGE\n";
34520b57cec5SDimitry Andric   Hierarchy.emitAttrRanges(OS);
34530b57cec5SDimitry Andric   OS << "#undef ATTR_RANGE\n";
34540b57cec5SDimitry Andric   OS << "#endif\n";
34550b57cec5SDimitry Andric 
34560b57cec5SDimitry Andric   Hierarchy.emitUndefs(OS);
34570b57cec5SDimitry Andric   OS << "#undef PRAGMA_SPELLING_ATTR\n";
34580b57cec5SDimitry Andric }
34590b57cec5SDimitry Andric 
34600b57cec5SDimitry Andric // Emits the enumeration list for attributes.
34610b57cec5SDimitry Andric void EmitClangAttrSubjectMatchRuleList(RecordKeeper &Records, raw_ostream &OS) {
34620b57cec5SDimitry Andric   emitSourceFileHeader(
34635f757f3fSDimitry Andric       "List of all attribute subject matching rules that Clang recognizes", OS,
34645f757f3fSDimitry Andric       Records);
34650b57cec5SDimitry Andric   PragmaClangAttributeSupport &PragmaAttributeSupport =
34660b57cec5SDimitry Andric       getPragmaAttributeSupport(Records);
34670b57cec5SDimitry Andric   emitDefaultDefine(OS, "ATTR_MATCH_RULE", nullptr);
34680b57cec5SDimitry Andric   PragmaAttributeSupport.emitMatchRuleList(OS);
34690b57cec5SDimitry Andric   OS << "#undef ATTR_MATCH_RULE\n";
34700b57cec5SDimitry Andric }
34710b57cec5SDimitry Andric 
34720b57cec5SDimitry Andric // Emits the code to read an attribute from a precompiled header.
34730b57cec5SDimitry Andric void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) {
34745f757f3fSDimitry Andric   emitSourceFileHeader("Attribute deserialization code", OS, Records);
34750b57cec5SDimitry Andric 
34760b57cec5SDimitry Andric   Record *InhClass = Records.getClass("InheritableAttr");
34770b57cec5SDimitry Andric   std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),
34780b57cec5SDimitry Andric                        ArgRecords;
34790b57cec5SDimitry Andric   std::vector<std::unique_ptr<Argument>> Args;
348081ad6265SDimitry Andric   std::unique_ptr<VariadicExprArgument> DelayedArgs;
34810b57cec5SDimitry Andric 
34820b57cec5SDimitry Andric   OS << "  switch (Kind) {\n";
34830b57cec5SDimitry Andric   for (const auto *Attr : Attrs) {
34840b57cec5SDimitry Andric     const Record &R = *Attr;
34850b57cec5SDimitry Andric     if (!R.getValueAsBit("ASTNode"))
34860b57cec5SDimitry Andric       continue;
34870b57cec5SDimitry Andric 
34880b57cec5SDimitry Andric     OS << "  case attr::" << R.getName() << ": {\n";
34890b57cec5SDimitry Andric     if (R.isSubClassOf(InhClass))
34900b57cec5SDimitry Andric       OS << "    bool isInherited = Record.readInt();\n";
34910b57cec5SDimitry Andric     OS << "    bool isImplicit = Record.readInt();\n";
3492e837bb5cSDimitry Andric     OS << "    bool isPackExpansion = Record.readInt();\n";
349381ad6265SDimitry Andric     DelayedArgs = nullptr;
349481ad6265SDimitry Andric     if (Attr->getValueAsBit("AcceptsExprPack")) {
349581ad6265SDimitry Andric       DelayedArgs =
349681ad6265SDimitry Andric           std::make_unique<VariadicExprArgument>("DelayedArgs", R.getName());
349781ad6265SDimitry Andric       DelayedArgs->writePCHReadDecls(OS);
349881ad6265SDimitry Andric     }
34990b57cec5SDimitry Andric     ArgRecords = R.getValueAsListOfDefs("Args");
35000b57cec5SDimitry Andric     Args.clear();
35010b57cec5SDimitry Andric     for (const auto *Arg : ArgRecords) {
35020b57cec5SDimitry Andric       Args.emplace_back(createArgument(*Arg, R.getName()));
35030b57cec5SDimitry Andric       Args.back()->writePCHReadDecls(OS);
35040b57cec5SDimitry Andric     }
3505a7dea167SDimitry Andric     OS << "    New = new (Context) " << R.getName() << "Attr(Context, Info";
35060b57cec5SDimitry Andric     for (auto const &ri : Args) {
35070b57cec5SDimitry Andric       OS << ", ";
35080b57cec5SDimitry Andric       ri->writePCHReadArgs(OS);
35090b57cec5SDimitry Andric     }
3510a7dea167SDimitry Andric     OS << ");\n";
35110b57cec5SDimitry Andric     if (R.isSubClassOf(InhClass))
35120b57cec5SDimitry Andric       OS << "    cast<InheritableAttr>(New)->setInherited(isInherited);\n";
35130b57cec5SDimitry Andric     OS << "    New->setImplicit(isImplicit);\n";
3514e837bb5cSDimitry Andric     OS << "    New->setPackExpansion(isPackExpansion);\n";
351581ad6265SDimitry Andric     if (DelayedArgs) {
351681ad6265SDimitry Andric       OS << "    cast<" << R.getName()
351781ad6265SDimitry Andric          << "Attr>(New)->setDelayedArgs(Context, ";
351881ad6265SDimitry Andric       DelayedArgs->writePCHReadArgs(OS);
351981ad6265SDimitry Andric       OS << ");\n";
352081ad6265SDimitry Andric     }
35210b57cec5SDimitry Andric     OS << "    break;\n";
35220b57cec5SDimitry Andric     OS << "  }\n";
35230b57cec5SDimitry Andric   }
35240b57cec5SDimitry Andric   OS << "  }\n";
35250b57cec5SDimitry Andric }
35260b57cec5SDimitry Andric 
35270b57cec5SDimitry Andric // Emits the code to write an attribute to a precompiled header.
35280b57cec5SDimitry Andric void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) {
35295f757f3fSDimitry Andric   emitSourceFileHeader("Attribute serialization code", OS, Records);
35300b57cec5SDimitry Andric 
35310b57cec5SDimitry Andric   Record *InhClass = Records.getClass("InheritableAttr");
35320b57cec5SDimitry Andric   std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
35330b57cec5SDimitry Andric 
35340b57cec5SDimitry Andric   OS << "  switch (A->getKind()) {\n";
35350b57cec5SDimitry Andric   for (const auto *Attr : Attrs) {
35360b57cec5SDimitry Andric     const Record &R = *Attr;
35370b57cec5SDimitry Andric     if (!R.getValueAsBit("ASTNode"))
35380b57cec5SDimitry Andric       continue;
35390b57cec5SDimitry Andric     OS << "  case attr::" << R.getName() << ": {\n";
35400b57cec5SDimitry Andric     Args = R.getValueAsListOfDefs("Args");
35410b57cec5SDimitry Andric     if (R.isSubClassOf(InhClass) || !Args.empty())
35420b57cec5SDimitry Andric       OS << "    const auto *SA = cast<" << R.getName()
35430b57cec5SDimitry Andric          << "Attr>(A);\n";
35440b57cec5SDimitry Andric     if (R.isSubClassOf(InhClass))
35450b57cec5SDimitry Andric       OS << "    Record.push_back(SA->isInherited());\n";
35460b57cec5SDimitry Andric     OS << "    Record.push_back(A->isImplicit());\n";
3547e837bb5cSDimitry Andric     OS << "    Record.push_back(A->isPackExpansion());\n";
354881ad6265SDimitry Andric     if (Attr->getValueAsBit("AcceptsExprPack"))
354981ad6265SDimitry Andric       VariadicExprArgument("DelayedArgs", R.getName()).writePCHWrite(OS);
35500b57cec5SDimitry Andric 
35510b57cec5SDimitry Andric     for (const auto *Arg : Args)
35520b57cec5SDimitry Andric       createArgument(*Arg, R.getName())->writePCHWrite(OS);
35530b57cec5SDimitry Andric     OS << "    break;\n";
35540b57cec5SDimitry Andric     OS << "  }\n";
35550b57cec5SDimitry Andric   }
35560b57cec5SDimitry Andric   OS << "  }\n";
35570b57cec5SDimitry Andric }
35580b57cec5SDimitry Andric 
3559*0fca6ea1SDimitry Andric } // namespace clang
3560*0fca6ea1SDimitry Andric 
35610b57cec5SDimitry Andric // Helper function for GenerateTargetSpecificAttrChecks that alters the 'Test'
35620b57cec5SDimitry Andric // parameter with only a single check type, if applicable.
35630b57cec5SDimitry Andric static bool GenerateTargetSpecificAttrCheck(const Record *R, std::string &Test,
35640b57cec5SDimitry Andric                                             std::string *FnName,
35650b57cec5SDimitry Andric                                             StringRef ListName,
35660b57cec5SDimitry Andric                                             StringRef CheckAgainst,
35670b57cec5SDimitry Andric                                             StringRef Scope) {
35680b57cec5SDimitry Andric   if (!R->isValueUnset(ListName)) {
35690b57cec5SDimitry Andric     Test += " && (";
35700b57cec5SDimitry Andric     std::vector<StringRef> Items = R->getValueAsListOfStrings(ListName);
35710b57cec5SDimitry Andric     for (auto I = Items.begin(), E = Items.end(); I != E; ++I) {
35720b57cec5SDimitry Andric       StringRef Part = *I;
35730b57cec5SDimitry Andric       Test += CheckAgainst;
35740b57cec5SDimitry Andric       Test += " == ";
35750b57cec5SDimitry Andric       Test += Scope;
35760b57cec5SDimitry Andric       Test += Part;
35770b57cec5SDimitry Andric       if (I + 1 != E)
35780b57cec5SDimitry Andric         Test += " || ";
35790b57cec5SDimitry Andric       if (FnName)
35800b57cec5SDimitry Andric         *FnName += Part;
35810b57cec5SDimitry Andric     }
35820b57cec5SDimitry Andric     Test += ")";
35830b57cec5SDimitry Andric     return true;
35840b57cec5SDimitry Andric   }
35850b57cec5SDimitry Andric   return false;
35860b57cec5SDimitry Andric }
35870b57cec5SDimitry Andric 
35880b57cec5SDimitry Andric // Generate a conditional expression to check if the current target satisfies
35890b57cec5SDimitry Andric // the conditions for a TargetSpecificAttr record, and append the code for
35900b57cec5SDimitry Andric // those checks to the Test string. If the FnName string pointer is non-null,
35910b57cec5SDimitry Andric // append a unique suffix to distinguish this set of target checks from other
35920b57cec5SDimitry Andric // TargetSpecificAttr records.
35930b57cec5SDimitry Andric static bool GenerateTargetSpecificAttrChecks(const Record *R,
35940b57cec5SDimitry Andric                                              std::vector<StringRef> &Arches,
35950b57cec5SDimitry Andric                                              std::string &Test,
35960b57cec5SDimitry Andric                                              std::string *FnName) {
35970b57cec5SDimitry Andric   bool AnyTargetChecks = false;
35980b57cec5SDimitry Andric 
35990b57cec5SDimitry Andric   // It is assumed that there will be an llvm::Triple object
36000b57cec5SDimitry Andric   // named "T" and a TargetInfo object named "Target" within
36010b57cec5SDimitry Andric   // scope that can be used to determine whether the attribute exists in
36020b57cec5SDimitry Andric   // a given target.
36030b57cec5SDimitry Andric   Test += "true";
36040b57cec5SDimitry Andric   // If one or more architectures is specified, check those.  Arches are handled
36050b57cec5SDimitry Andric   // differently because GenerateTargetRequirements needs to combine the list
36060b57cec5SDimitry Andric   // with ParseKind.
36070b57cec5SDimitry Andric   if (!Arches.empty()) {
36080b57cec5SDimitry Andric     AnyTargetChecks = true;
36090b57cec5SDimitry Andric     Test += " && (";
36100b57cec5SDimitry Andric     for (auto I = Arches.begin(), E = Arches.end(); I != E; ++I) {
36110b57cec5SDimitry Andric       StringRef Part = *I;
36120b57cec5SDimitry Andric       Test += "T.getArch() == llvm::Triple::";
36130b57cec5SDimitry Andric       Test += Part;
36140b57cec5SDimitry Andric       if (I + 1 != E)
36150b57cec5SDimitry Andric         Test += " || ";
36160b57cec5SDimitry Andric       if (FnName)
36170b57cec5SDimitry Andric         *FnName += Part;
36180b57cec5SDimitry Andric     }
36190b57cec5SDimitry Andric     Test += ")";
36200b57cec5SDimitry Andric   }
36210b57cec5SDimitry Andric 
36220b57cec5SDimitry Andric   // If the attribute is specific to particular OSes, check those.
36230b57cec5SDimitry Andric   AnyTargetChecks |= GenerateTargetSpecificAttrCheck(
36240b57cec5SDimitry Andric       R, Test, FnName, "OSes", "T.getOS()", "llvm::Triple::");
36250b57cec5SDimitry Andric 
36260b57cec5SDimitry Andric   // If one or more object formats is specified, check those.
36270b57cec5SDimitry Andric   AnyTargetChecks |=
36280b57cec5SDimitry Andric       GenerateTargetSpecificAttrCheck(R, Test, FnName, "ObjectFormats",
36290b57cec5SDimitry Andric                                       "T.getObjectFormat()", "llvm::Triple::");
36300b57cec5SDimitry Andric 
36310b57cec5SDimitry Andric   // If custom code is specified, emit it.
36320b57cec5SDimitry Andric   StringRef Code = R->getValueAsString("CustomCode");
36330b57cec5SDimitry Andric   if (!Code.empty()) {
36340b57cec5SDimitry Andric     AnyTargetChecks = true;
36350b57cec5SDimitry Andric     Test += " && (";
36360b57cec5SDimitry Andric     Test += Code;
36370b57cec5SDimitry Andric     Test += ")";
36380b57cec5SDimitry Andric   }
36390b57cec5SDimitry Andric 
36400b57cec5SDimitry Andric   return AnyTargetChecks;
36410b57cec5SDimitry Andric }
36420b57cec5SDimitry Andric 
36430b57cec5SDimitry Andric static void GenerateHasAttrSpellingStringSwitch(
36445f757f3fSDimitry Andric     const std::vector<std::pair<const Record *, FlattenedSpelling>> &Attrs,
36455f757f3fSDimitry Andric     raw_ostream &OS, const std::string &Variety,
36465f757f3fSDimitry Andric     const std::string &Scope = "") {
36475f757f3fSDimitry Andric   for (const auto &[Attr, Spelling] : Attrs) {
36480b57cec5SDimitry Andric     // C++11-style attributes have specific version information associated with
36490b57cec5SDimitry Andric     // them. If the attribute has no scope, the version information must not
36500b57cec5SDimitry Andric     // have the default value (1), as that's incorrect. Instead, the unscoped
36510b57cec5SDimitry Andric     // attribute version information should be taken from the SD-6 standing
36520b57cec5SDimitry Andric     // document, which can be found at:
36530b57cec5SDimitry Andric     // https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations
3654e8d8bef9SDimitry Andric     //
36555f757f3fSDimitry Andric     // C23-style attributes have the same kind of version information
3656e8d8bef9SDimitry Andric     // associated with them. The unscoped attribute version information should
3657e8d8bef9SDimitry Andric     // be taken from the specification of the attribute in the C Standard.
365806c3fb27SDimitry Andric     //
365906c3fb27SDimitry Andric     // Clang-specific attributes have the same kind of version information
366006c3fb27SDimitry Andric     // associated with them. This version is typically the default value (1).
366106c3fb27SDimitry Andric     // These version values are clang-specific and should typically be
366206c3fb27SDimitry Andric     // incremented once the attribute changes its syntax and/or semantics in a
366306c3fb27SDimitry Andric     // a way that is impactful to the end user.
36640b57cec5SDimitry Andric     int Version = 1;
36650b57cec5SDimitry Andric 
36665f757f3fSDimitry Andric     assert(Spelling.variety() == Variety);
36675f757f3fSDimitry Andric     std::string Name = "";
36685f757f3fSDimitry Andric     if (Spelling.nameSpace().empty() || Scope == Spelling.nameSpace()) {
36695f757f3fSDimitry Andric       Name = Spelling.name();
367006c3fb27SDimitry Andric       Version = static_cast<int>(
367106c3fb27SDimitry Andric           Spelling.getSpellingRecord().getValueAsInt("Version"));
36725f757f3fSDimitry Andric       // Verify that explicitly specified CXX11 and C23 spellings (i.e.
367306c3fb27SDimitry Andric       // not inferred from Clang/GCC spellings) have a version that's
36745f757f3fSDimitry Andric       // different from the default (1).
367506c3fb27SDimitry Andric       bool RequiresValidVersion =
36765f757f3fSDimitry Andric           (Variety == "CXX11" || Variety == "C23") &&
367706c3fb27SDimitry Andric           Spelling.getSpellingRecord().getValueAsString("Variety") == Variety;
367806c3fb27SDimitry Andric       if (RequiresValidVersion && Scope.empty() && Version == 1)
367906c3fb27SDimitry Andric         PrintError(Spelling.getSpellingRecord().getLoc(),
368006c3fb27SDimitry Andric                    "Standard attributes must have "
3681e8d8bef9SDimitry Andric                    "valid version information.");
36820b57cec5SDimitry Andric     }
36830b57cec5SDimitry Andric 
36840b57cec5SDimitry Andric     std::string Test;
36850b57cec5SDimitry Andric     if (Attr->isSubClassOf("TargetSpecificAttr")) {
36860b57cec5SDimitry Andric       const Record *R = Attr->getValueAsDef("Target");
36870b57cec5SDimitry Andric       std::vector<StringRef> Arches = R->getValueAsListOfStrings("Arches");
36880b57cec5SDimitry Andric       GenerateTargetSpecificAttrChecks(R, Arches, Test, nullptr);
36895f757f3fSDimitry Andric     } else if (!Attr->getValueAsListOfDefs("TargetSpecificSpellings").empty()) {
36905f757f3fSDimitry Andric       // Add target checks if this spelling is target-specific.
36915f757f3fSDimitry Andric       const std::vector<Record *> TargetSpellings =
36925f757f3fSDimitry Andric           Attr->getValueAsListOfDefs("TargetSpecificSpellings");
36935f757f3fSDimitry Andric       for (const auto &TargetSpelling : TargetSpellings) {
36945f757f3fSDimitry Andric         // Find spelling that matches current scope and name.
36955f757f3fSDimitry Andric         for (const auto &Spelling : GetFlattenedSpellings(*TargetSpelling)) {
36965f757f3fSDimitry Andric           if (Scope == Spelling.nameSpace() && Name == Spelling.name()) {
36975f757f3fSDimitry Andric             const Record *Target = TargetSpelling->getValueAsDef("Target");
36985f757f3fSDimitry Andric             std::vector<StringRef> Arches =
36995f757f3fSDimitry Andric                 Target->getValueAsListOfStrings("Arches");
37005f757f3fSDimitry Andric             GenerateTargetSpecificAttrChecks(Target, Arches, Test,
37015f757f3fSDimitry Andric                                              /*FnName=*/nullptr);
37025f757f3fSDimitry Andric             break;
37035f757f3fSDimitry Andric           }
37045f757f3fSDimitry Andric         }
37055f757f3fSDimitry Andric       }
3706*0fca6ea1SDimitry Andric     }
37070b57cec5SDimitry Andric 
370806c3fb27SDimitry Andric     std::string TestStr = !Test.empty()
370906c3fb27SDimitry Andric                               ? Test + " ? " + llvm::itostr(Version) + " : 0"
371006c3fb27SDimitry Andric                               : llvm::itostr(Version);
37115f757f3fSDimitry Andric     if (Scope.empty() || Scope == Spelling.nameSpace())
37125f757f3fSDimitry Andric       OS << "    .Case(\"" << Spelling.name() << "\", " << TestStr << ")\n";
37130b57cec5SDimitry Andric   }
37140b57cec5SDimitry Andric   OS << "    .Default(0);\n";
37150b57cec5SDimitry Andric }
37160b57cec5SDimitry Andric 
3717*0fca6ea1SDimitry Andric namespace clang {
3718*0fca6ea1SDimitry Andric 
37197a6dacacSDimitry Andric // Emits list of regular keyword attributes with info about their arguments.
37207a6dacacSDimitry Andric void EmitClangRegularKeywordAttributeInfo(RecordKeeper &Records,
37217a6dacacSDimitry Andric                                           raw_ostream &OS) {
37227a6dacacSDimitry Andric   emitSourceFileHeader(
37237a6dacacSDimitry Andric       "A list of regular keyword attributes generated from the attribute"
372406c3fb27SDimitry Andric       " definitions",
372506c3fb27SDimitry Andric       OS);
372606c3fb27SDimitry Andric   // Assume for now that the same token is not used in multiple regular
372706c3fb27SDimitry Andric   // keyword attributes.
372806c3fb27SDimitry Andric   for (auto *R : Records.getAllDerivedDefinitions("Attr"))
37297a6dacacSDimitry Andric     for (const auto &S : GetFlattenedSpellings(*R)) {
37307a6dacacSDimitry Andric       if (!isRegularKeywordAttribute(S))
37317a6dacacSDimitry Andric         continue;
37327a6dacacSDimitry Andric       std::vector<Record *> Args = R->getValueAsListOfDefs("Args");
37337a6dacacSDimitry Andric       bool HasArgs = llvm::any_of(
37347a6dacacSDimitry Andric           Args, [](const Record *Arg) { return !Arg->getValueAsBit("Fake"); });
37357a6dacacSDimitry Andric 
373606c3fb27SDimitry Andric       OS << "KEYWORD_ATTRIBUTE("
37377a6dacacSDimitry Andric          << S.getSpellingRecord().getValueAsString("Name") << ", "
37387a6dacacSDimitry Andric          << (HasArgs ? "true" : "false") << ", )\n";
373906c3fb27SDimitry Andric     }
374006c3fb27SDimitry Andric   OS << "#undef KEYWORD_ATTRIBUTE\n";
374106c3fb27SDimitry Andric }
374206c3fb27SDimitry Andric 
37430b57cec5SDimitry Andric // Emits the list of spellings for attributes.
37440b57cec5SDimitry Andric void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
37455f757f3fSDimitry Andric   emitSourceFileHeader("Code to implement the __has_attribute logic", OS,
37465f757f3fSDimitry Andric                        Records);
37470b57cec5SDimitry Andric 
37480b57cec5SDimitry Andric   // Separate all of the attributes out into four group: generic, C++11, GNU,
37490b57cec5SDimitry Andric   // and declspecs. Then generate a big switch statement for each of them.
37500b57cec5SDimitry Andric   std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
37515f757f3fSDimitry Andric   std::vector<std::pair<const Record *, FlattenedSpelling>> Declspec, Microsoft,
3752*0fca6ea1SDimitry Andric       GNU, Pragma, HLSLAnnotation;
37535f757f3fSDimitry Andric   std::map<std::string,
37545f757f3fSDimitry Andric            std::vector<std::pair<const Record *, FlattenedSpelling>>>
37555f757f3fSDimitry Andric       CXX, C23;
37560b57cec5SDimitry Andric 
37570b57cec5SDimitry Andric   // Walk over the list of all attributes, and split them out based on the
37580b57cec5SDimitry Andric   // spelling variety.
37590b57cec5SDimitry Andric   for (auto *R : Attrs) {
37600b57cec5SDimitry Andric     std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*R);
37610b57cec5SDimitry Andric     for (const auto &SI : Spellings) {
37620b57cec5SDimitry Andric       const std::string &Variety = SI.variety();
37630b57cec5SDimitry Andric       if (Variety == "GNU")
37645f757f3fSDimitry Andric         GNU.emplace_back(R, SI);
37650b57cec5SDimitry Andric       else if (Variety == "Declspec")
37665f757f3fSDimitry Andric         Declspec.emplace_back(R, SI);
37670b57cec5SDimitry Andric       else if (Variety == "Microsoft")
37685f757f3fSDimitry Andric         Microsoft.emplace_back(R, SI);
37690b57cec5SDimitry Andric       else if (Variety == "CXX11")
37705f757f3fSDimitry Andric         CXX[SI.nameSpace()].emplace_back(R, SI);
37715f757f3fSDimitry Andric       else if (Variety == "C23")
37725f757f3fSDimitry Andric         C23[SI.nameSpace()].emplace_back(R, SI);
37730b57cec5SDimitry Andric       else if (Variety == "Pragma")
37745f757f3fSDimitry Andric         Pragma.emplace_back(R, SI);
3775*0fca6ea1SDimitry Andric       else if (Variety == "HLSLAnnotation")
3776*0fca6ea1SDimitry Andric         HLSLAnnotation.emplace_back(R, SI);
37770b57cec5SDimitry Andric     }
37780b57cec5SDimitry Andric   }
37790b57cec5SDimitry Andric 
37800b57cec5SDimitry Andric   OS << "const llvm::Triple &T = Target.getTriple();\n";
37810b57cec5SDimitry Andric   OS << "switch (Syntax) {\n";
378281ad6265SDimitry Andric   OS << "case AttributeCommonInfo::Syntax::AS_GNU:\n";
37830b57cec5SDimitry Andric   OS << "  return llvm::StringSwitch<int>(Name)\n";
37840b57cec5SDimitry Andric   GenerateHasAttrSpellingStringSwitch(GNU, OS, "GNU");
378581ad6265SDimitry Andric   OS << "case AttributeCommonInfo::Syntax::AS_Declspec:\n";
37860b57cec5SDimitry Andric   OS << "  return llvm::StringSwitch<int>(Name)\n";
37870b57cec5SDimitry Andric   GenerateHasAttrSpellingStringSwitch(Declspec, OS, "Declspec");
378881ad6265SDimitry Andric   OS << "case AttributeCommonInfo::Syntax::AS_Microsoft:\n";
37890b57cec5SDimitry Andric   OS << "  return llvm::StringSwitch<int>(Name)\n";
37900b57cec5SDimitry Andric   GenerateHasAttrSpellingStringSwitch(Microsoft, OS, "Microsoft");
379181ad6265SDimitry Andric   OS << "case AttributeCommonInfo::Syntax::AS_Pragma:\n";
37920b57cec5SDimitry Andric   OS << "  return llvm::StringSwitch<int>(Name)\n";
37930b57cec5SDimitry Andric   GenerateHasAttrSpellingStringSwitch(Pragma, OS, "Pragma");
3794*0fca6ea1SDimitry Andric   OS << "case AttributeCommonInfo::Syntax::AS_HLSLAnnotation:\n";
379581ad6265SDimitry Andric   OS << "  return llvm::StringSwitch<int>(Name)\n";
3796*0fca6ea1SDimitry Andric   GenerateHasAttrSpellingStringSwitch(HLSLAnnotation, OS, "HLSLAnnotation");
379781ad6265SDimitry Andric   auto fn = [&OS](const char *Spelling,
37985f757f3fSDimitry Andric                   const std::map<
37995f757f3fSDimitry Andric                       std::string,
38005f757f3fSDimitry Andric                       std::vector<std::pair<const Record *, FlattenedSpelling>>>
38015f757f3fSDimitry Andric                       &List) {
380281ad6265SDimitry Andric     OS << "case AttributeCommonInfo::Syntax::AS_" << Spelling << ": {\n";
38030b57cec5SDimitry Andric     // C++11-style attributes are further split out based on the Scope.
38040b57cec5SDimitry Andric     for (auto I = List.cbegin(), E = List.cend(); I != E; ++I) {
38050b57cec5SDimitry Andric       if (I != List.cbegin())
38060b57cec5SDimitry Andric         OS << " else ";
38070b57cec5SDimitry Andric       if (I->first.empty())
38080b57cec5SDimitry Andric         OS << "if (ScopeName == \"\") {\n";
38090b57cec5SDimitry Andric       else
38100b57cec5SDimitry Andric         OS << "if (ScopeName == \"" << I->first << "\") {\n";
38110b57cec5SDimitry Andric       OS << "  return llvm::StringSwitch<int>(Name)\n";
38120b57cec5SDimitry Andric       GenerateHasAttrSpellingStringSwitch(I->second, OS, Spelling, I->first);
38130b57cec5SDimitry Andric       OS << "}";
38140b57cec5SDimitry Andric     }
38150b57cec5SDimitry Andric     OS << "\n} break;\n";
38160b57cec5SDimitry Andric   };
381781ad6265SDimitry Andric   fn("CXX11", CXX);
38185f757f3fSDimitry Andric   fn("C23", C23);
381981ad6265SDimitry Andric   OS << "case AttributeCommonInfo::Syntax::AS_Keyword:\n";
382081ad6265SDimitry Andric   OS << "case AttributeCommonInfo::Syntax::AS_ContextSensitiveKeyword:\n";
382181ad6265SDimitry Andric   OS << "  llvm_unreachable(\"hasAttribute not supported for keyword\");\n";
382281ad6265SDimitry Andric   OS << "  return 0;\n";
382306c3fb27SDimitry Andric   OS << "case AttributeCommonInfo::Syntax::AS_Implicit:\n";
382406c3fb27SDimitry Andric   OS << "  llvm_unreachable (\"hasAttribute not supported for "
382506c3fb27SDimitry Andric         "AS_Implicit\");\n";
382606c3fb27SDimitry Andric   OS << "  return 0;\n";
382781ad6265SDimitry Andric 
38280b57cec5SDimitry Andric   OS << "}\n";
38290b57cec5SDimitry Andric }
38300b57cec5SDimitry Andric 
38310b57cec5SDimitry Andric void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) {
38325f757f3fSDimitry Andric   emitSourceFileHeader("Code to translate different attribute spellings into "
38335f757f3fSDimitry Andric                        "internal identifiers",
38345f757f3fSDimitry Andric                        OS, Records);
38350b57cec5SDimitry Andric 
3836a7dea167SDimitry Andric   OS << "  switch (getParsedKind()) {\n";
3837a7dea167SDimitry Andric   OS << "    case IgnoredAttribute:\n";
3838a7dea167SDimitry Andric   OS << "    case UnknownAttribute:\n";
3839a7dea167SDimitry Andric   OS << "    case NoSemaHandlerAttribute:\n";
3840a7dea167SDimitry Andric   OS << "      llvm_unreachable(\"Ignored/unknown shouldn't get here\");\n";
38410b57cec5SDimitry Andric 
38420b57cec5SDimitry Andric   ParsedAttrMap Attrs = getParsedAttrList(Records);
38430b57cec5SDimitry Andric   for (const auto &I : Attrs) {
38440b57cec5SDimitry Andric     const Record &R = *I.second;
38450b57cec5SDimitry Andric     std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
38460b57cec5SDimitry Andric     OS << "  case AT_" << I.first << ": {\n";
38470b57cec5SDimitry Andric     for (unsigned I = 0; I < Spellings.size(); ++ I) {
38480b57cec5SDimitry Andric       OS << "    if (Name == \"" << Spellings[I].name() << "\" && "
3849a7dea167SDimitry Andric          << "getSyntax() == AttributeCommonInfo::AS_" << Spellings[I].variety()
38500b57cec5SDimitry Andric          << " && Scope == \"" << Spellings[I].nameSpace() << "\")\n"
38510b57cec5SDimitry Andric          << "        return " << I << ";\n";
38520b57cec5SDimitry Andric     }
38530b57cec5SDimitry Andric 
38540b57cec5SDimitry Andric     OS << "    break;\n";
38550b57cec5SDimitry Andric     OS << "  }\n";
38560b57cec5SDimitry Andric   }
38570b57cec5SDimitry Andric 
38580b57cec5SDimitry Andric   OS << "  }\n";
38590b57cec5SDimitry Andric   OS << "  return 0;\n";
38600b57cec5SDimitry Andric }
38610b57cec5SDimitry Andric 
38620b57cec5SDimitry Andric // Emits code used by RecursiveASTVisitor to visit attributes
38630b57cec5SDimitry Andric void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS) {
38645f757f3fSDimitry Andric   emitSourceFileHeader("Used by RecursiveASTVisitor to visit attributes.", OS,
38655f757f3fSDimitry Andric                        Records);
38660b57cec5SDimitry Andric 
38670b57cec5SDimitry Andric   std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
38680b57cec5SDimitry Andric 
38690b57cec5SDimitry Andric   // Write method declarations for Traverse* methods.
38700b57cec5SDimitry Andric   // We emit this here because we only generate methods for attributes that
38710b57cec5SDimitry Andric   // are declared as ASTNodes.
38720b57cec5SDimitry Andric   OS << "#ifdef ATTR_VISITOR_DECLS_ONLY\n\n";
38730b57cec5SDimitry Andric   for (const auto *Attr : Attrs) {
38740b57cec5SDimitry Andric     const Record &R = *Attr;
38750b57cec5SDimitry Andric     if (!R.getValueAsBit("ASTNode"))
38760b57cec5SDimitry Andric       continue;
38770b57cec5SDimitry Andric     OS << "  bool Traverse"
38780b57cec5SDimitry Andric        << R.getName() << "Attr(" << R.getName() << "Attr *A);\n";
38790b57cec5SDimitry Andric     OS << "  bool Visit"
38800b57cec5SDimitry Andric        << R.getName() << "Attr(" << R.getName() << "Attr *A) {\n"
38810b57cec5SDimitry Andric        << "    return true; \n"
38820b57cec5SDimitry Andric        << "  }\n";
38830b57cec5SDimitry Andric   }
38840b57cec5SDimitry Andric   OS << "\n#else // ATTR_VISITOR_DECLS_ONLY\n\n";
38850b57cec5SDimitry Andric 
38860b57cec5SDimitry Andric   // Write individual Traverse* methods for each attribute class.
38870b57cec5SDimitry Andric   for (const auto *Attr : Attrs) {
38880b57cec5SDimitry Andric     const Record &R = *Attr;
38890b57cec5SDimitry Andric     if (!R.getValueAsBit("ASTNode"))
38900b57cec5SDimitry Andric       continue;
38910b57cec5SDimitry Andric 
38920b57cec5SDimitry Andric     OS << "template <typename Derived>\n"
38930b57cec5SDimitry Andric        << "bool VISITORCLASS<Derived>::Traverse"
38940b57cec5SDimitry Andric        << R.getName() << "Attr(" << R.getName() << "Attr *A) {\n"
38950b57cec5SDimitry Andric        << "  if (!getDerived().VisitAttr(A))\n"
38960b57cec5SDimitry Andric        << "    return false;\n"
38970b57cec5SDimitry Andric        << "  if (!getDerived().Visit" << R.getName() << "Attr(A))\n"
38980b57cec5SDimitry Andric        << "    return false;\n";
38990b57cec5SDimitry Andric 
39000b57cec5SDimitry Andric     std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
39010b57cec5SDimitry Andric     for (const auto *Arg : ArgRecords)
39020b57cec5SDimitry Andric       createArgument(*Arg, R.getName())->writeASTVisitorTraversal(OS);
39030b57cec5SDimitry Andric 
390481ad6265SDimitry Andric     if (Attr->getValueAsBit("AcceptsExprPack"))
390581ad6265SDimitry Andric       VariadicExprArgument("DelayedArgs", R.getName())
390681ad6265SDimitry Andric           .writeASTVisitorTraversal(OS);
390781ad6265SDimitry Andric 
39080b57cec5SDimitry Andric     OS << "  return true;\n";
39090b57cec5SDimitry Andric     OS << "}\n\n";
39100b57cec5SDimitry Andric   }
39110b57cec5SDimitry Andric 
39120b57cec5SDimitry Andric   // Write generic Traverse routine
39130b57cec5SDimitry Andric   OS << "template <typename Derived>\n"
39140b57cec5SDimitry Andric      << "bool VISITORCLASS<Derived>::TraverseAttr(Attr *A) {\n"
39150b57cec5SDimitry Andric      << "  if (!A)\n"
39160b57cec5SDimitry Andric      << "    return true;\n"
39170b57cec5SDimitry Andric      << "\n"
39180b57cec5SDimitry Andric      << "  switch (A->getKind()) {\n";
39190b57cec5SDimitry Andric 
39200b57cec5SDimitry Andric   for (const auto *Attr : Attrs) {
39210b57cec5SDimitry Andric     const Record &R = *Attr;
39220b57cec5SDimitry Andric     if (!R.getValueAsBit("ASTNode"))
39230b57cec5SDimitry Andric       continue;
39240b57cec5SDimitry Andric 
39250b57cec5SDimitry Andric     OS << "    case attr::" << R.getName() << ":\n"
39260b57cec5SDimitry Andric        << "      return getDerived().Traverse" << R.getName() << "Attr("
39270b57cec5SDimitry Andric        << "cast<" << R.getName() << "Attr>(A));\n";
39280b57cec5SDimitry Andric   }
39290b57cec5SDimitry Andric   OS << "  }\n";  // end switch
39300b57cec5SDimitry Andric   OS << "  llvm_unreachable(\"bad attribute kind\");\n";
39310b57cec5SDimitry Andric   OS << "}\n";  // end function
39320b57cec5SDimitry Andric   OS << "#endif  // ATTR_VISITOR_DECLS_ONLY\n";
39330b57cec5SDimitry Andric }
39340b57cec5SDimitry Andric 
39350b57cec5SDimitry Andric void EmitClangAttrTemplateInstantiateHelper(const std::vector<Record *> &Attrs,
39360b57cec5SDimitry Andric                                             raw_ostream &OS,
39370b57cec5SDimitry Andric                                             bool AppliesToDecl) {
39380b57cec5SDimitry Andric 
39390b57cec5SDimitry Andric   OS << "  switch (At->getKind()) {\n";
39400b57cec5SDimitry Andric   for (const auto *Attr : Attrs) {
39410b57cec5SDimitry Andric     const Record &R = *Attr;
39420b57cec5SDimitry Andric     if (!R.getValueAsBit("ASTNode"))
39430b57cec5SDimitry Andric       continue;
39440b57cec5SDimitry Andric     OS << "    case attr::" << R.getName() << ": {\n";
39450b57cec5SDimitry Andric     bool ShouldClone = R.getValueAsBit("Clone") &&
39460b57cec5SDimitry Andric                        (!AppliesToDecl ||
39470b57cec5SDimitry Andric                         R.getValueAsBit("MeaningfulToClassTemplateDefinition"));
39480b57cec5SDimitry Andric 
39490b57cec5SDimitry Andric     if (!ShouldClone) {
39500b57cec5SDimitry Andric       OS << "      return nullptr;\n";
39510b57cec5SDimitry Andric       OS << "    }\n";
39520b57cec5SDimitry Andric       continue;
39530b57cec5SDimitry Andric     }
39540b57cec5SDimitry Andric 
39550b57cec5SDimitry Andric     OS << "      const auto *A = cast<"
39560b57cec5SDimitry Andric        << R.getName() << "Attr>(At);\n";
39570b57cec5SDimitry Andric     bool TDependent = R.getValueAsBit("TemplateDependent");
39580b57cec5SDimitry Andric 
39590b57cec5SDimitry Andric     if (!TDependent) {
39600b57cec5SDimitry Andric       OS << "      return A->clone(C);\n";
39610b57cec5SDimitry Andric       OS << "    }\n";
39620b57cec5SDimitry Andric       continue;
39630b57cec5SDimitry Andric     }
39640b57cec5SDimitry Andric 
39650b57cec5SDimitry Andric     std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
39660b57cec5SDimitry Andric     std::vector<std::unique_ptr<Argument>> Args;
39670b57cec5SDimitry Andric     Args.reserve(ArgRecords.size());
39680b57cec5SDimitry Andric 
39690b57cec5SDimitry Andric     for (const auto *ArgRecord : ArgRecords)
39700b57cec5SDimitry Andric       Args.emplace_back(createArgument(*ArgRecord, R.getName()));
39710b57cec5SDimitry Andric 
39720b57cec5SDimitry Andric     for (auto const &ai : Args)
39730b57cec5SDimitry Andric       ai->writeTemplateInstantiation(OS);
39740b57cec5SDimitry Andric 
3975a7dea167SDimitry Andric     OS << "      return new (C) " << R.getName() << "Attr(C, *A";
39760b57cec5SDimitry Andric     for (auto const &ai : Args) {
39770b57cec5SDimitry Andric       OS << ", ";
39780b57cec5SDimitry Andric       ai->writeTemplateInstantiationArgs(OS);
39790b57cec5SDimitry Andric     }
3980e8d8bef9SDimitry Andric     OS << ");\n"
3981e8d8bef9SDimitry Andric        << "    }\n";
39820b57cec5SDimitry Andric   }
39830b57cec5SDimitry Andric   OS << "  } // end switch\n"
39840b57cec5SDimitry Andric      << "  llvm_unreachable(\"Unknown attribute!\");\n"
39850b57cec5SDimitry Andric      << "  return nullptr;\n";
39860b57cec5SDimitry Andric }
39870b57cec5SDimitry Andric 
39880b57cec5SDimitry Andric // Emits code to instantiate dependent attributes on templates.
39890b57cec5SDimitry Andric void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) {
39905f757f3fSDimitry Andric   emitSourceFileHeader("Template instantiation code for attributes", OS,
39915f757f3fSDimitry Andric                        Records);
39920b57cec5SDimitry Andric 
39930b57cec5SDimitry Andric   std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
39940b57cec5SDimitry Andric 
39950b57cec5SDimitry Andric   OS << "namespace clang {\n"
39960b57cec5SDimitry Andric      << "namespace sema {\n\n"
39970b57cec5SDimitry Andric      << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, "
39980b57cec5SDimitry Andric      << "Sema &S,\n"
39990b57cec5SDimitry Andric      << "        const MultiLevelTemplateArgumentList &TemplateArgs) {\n";
40000b57cec5SDimitry Andric   EmitClangAttrTemplateInstantiateHelper(Attrs, OS, /*AppliesToDecl*/false);
40010b57cec5SDimitry Andric   OS << "}\n\n"
40020b57cec5SDimitry Andric      << "Attr *instantiateTemplateAttributeForDecl(const Attr *At,\n"
40030b57cec5SDimitry Andric      << " ASTContext &C, Sema &S,\n"
40040b57cec5SDimitry Andric      << "        const MultiLevelTemplateArgumentList &TemplateArgs) {\n";
40050b57cec5SDimitry Andric   EmitClangAttrTemplateInstantiateHelper(Attrs, OS, /*AppliesToDecl*/true);
40060b57cec5SDimitry Andric   OS << "}\n\n"
40070b57cec5SDimitry Andric      << "} // end namespace sema\n"
40080b57cec5SDimitry Andric      << "} // end namespace clang\n";
40090b57cec5SDimitry Andric }
40100b57cec5SDimitry Andric 
40110b57cec5SDimitry Andric // Emits the list of parsed attributes.
40120b57cec5SDimitry Andric void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) {
40135f757f3fSDimitry Andric   emitSourceFileHeader("List of all attributes that Clang recognizes", OS,
40145f757f3fSDimitry Andric                        Records);
40150b57cec5SDimitry Andric 
40160b57cec5SDimitry Andric   OS << "#ifndef PARSED_ATTR\n";
40170b57cec5SDimitry Andric   OS << "#define PARSED_ATTR(NAME) NAME\n";
40180b57cec5SDimitry Andric   OS << "#endif\n\n";
40190b57cec5SDimitry Andric 
40200b57cec5SDimitry Andric   ParsedAttrMap Names = getParsedAttrList(Records);
40210b57cec5SDimitry Andric   for (const auto &I : Names) {
40220b57cec5SDimitry Andric     OS << "PARSED_ATTR(" << I.first << ")\n";
40230b57cec5SDimitry Andric   }
40240b57cec5SDimitry Andric }
40250b57cec5SDimitry Andric 
40260b57cec5SDimitry Andric static bool isArgVariadic(const Record &R, StringRef AttrName) {
40270b57cec5SDimitry Andric   return createArgument(R, AttrName)->isVariadic();
40280b57cec5SDimitry Andric }
40290b57cec5SDimitry Andric 
40300b57cec5SDimitry Andric static void emitArgInfo(const Record &R, raw_ostream &OS) {
40310b57cec5SDimitry Andric   // This function will count the number of arguments specified for the
40320b57cec5SDimitry Andric   // attribute and emit the number of required arguments followed by the
40330b57cec5SDimitry Andric   // number of optional arguments.
40340b57cec5SDimitry Andric   std::vector<Record *> Args = R.getValueAsListOfDefs("Args");
403581ad6265SDimitry Andric   unsigned ArgCount = 0, OptCount = 0, ArgMemberCount = 0;
40360b57cec5SDimitry Andric   bool HasVariadic = false;
40370b57cec5SDimitry Andric   for (const auto *Arg : Args) {
40380b57cec5SDimitry Andric     // If the arg is fake, it's the user's job to supply it: general parsing
40390b57cec5SDimitry Andric     // logic shouldn't need to know anything about it.
40400b57cec5SDimitry Andric     if (Arg->getValueAsBit("Fake"))
40410b57cec5SDimitry Andric       continue;
40420b57cec5SDimitry Andric     Arg->getValueAsBit("Optional") ? ++OptCount : ++ArgCount;
404381ad6265SDimitry Andric     ++ArgMemberCount;
40440b57cec5SDimitry Andric     if (!HasVariadic && isArgVariadic(*Arg, R.getName()))
40450b57cec5SDimitry Andric       HasVariadic = true;
40460b57cec5SDimitry Andric   }
40470b57cec5SDimitry Andric 
40480b57cec5SDimitry Andric   // If there is a variadic argument, we will set the optional argument count
40490b57cec5SDimitry Andric   // to its largest value. Since it's currently a 4-bit number, we set it to 15.
405081ad6265SDimitry Andric   OS << "    /*NumArgs=*/" << ArgCount << ",\n";
405181ad6265SDimitry Andric   OS << "    /*OptArgs=*/" << (HasVariadic ? 15 : OptCount) << ",\n";
405281ad6265SDimitry Andric   OS << "    /*NumArgMembers=*/" << ArgMemberCount << ",\n";
40530b57cec5SDimitry Andric }
40540b57cec5SDimitry Andric 
40550b57cec5SDimitry Andric static std::string GetDiagnosticSpelling(const Record &R) {
40565ffd83dbSDimitry Andric   std::string Ret = std::string(R.getValueAsString("DiagSpelling"));
40570b57cec5SDimitry Andric   if (!Ret.empty())
40580b57cec5SDimitry Andric     return Ret;
40590b57cec5SDimitry Andric 
40600b57cec5SDimitry Andric   // If we couldn't find the DiagSpelling in this object, we can check to see
40610b57cec5SDimitry Andric   // if the object is one that has a base, and if it is, loop up to the Base
40620b57cec5SDimitry Andric   // member recursively.
4063480093f4SDimitry Andric   if (auto Base = R.getValueAsOptionalDef(BaseFieldName))
4064480093f4SDimitry Andric     return GetDiagnosticSpelling(*Base);
40650b57cec5SDimitry Andric 
40660b57cec5SDimitry Andric   return "";
40670b57cec5SDimitry Andric }
40680b57cec5SDimitry Andric 
40690b57cec5SDimitry Andric static std::string CalculateDiagnostic(const Record &S) {
40700b57cec5SDimitry Andric   // If the SubjectList object has a custom diagnostic associated with it,
40710b57cec5SDimitry Andric   // return that directly.
40720b57cec5SDimitry Andric   const StringRef CustomDiag = S.getValueAsString("CustomDiag");
40730b57cec5SDimitry Andric   if (!CustomDiag.empty())
40740b57cec5SDimitry Andric     return ("\"" + Twine(CustomDiag) + "\"").str();
40750b57cec5SDimitry Andric 
40760b57cec5SDimitry Andric   std::vector<std::string> DiagList;
40770b57cec5SDimitry Andric   std::vector<Record *> Subjects = S.getValueAsListOfDefs("Subjects");
40780b57cec5SDimitry Andric   for (const auto *Subject : Subjects) {
40790b57cec5SDimitry Andric     const Record &R = *Subject;
40800b57cec5SDimitry Andric     // Get the diagnostic text from the Decl or Stmt node given.
40810b57cec5SDimitry Andric     std::string V = GetDiagnosticSpelling(R);
40820b57cec5SDimitry Andric     if (V.empty()) {
40830b57cec5SDimitry Andric       PrintError(R.getLoc(),
40840b57cec5SDimitry Andric                  "Could not determine diagnostic spelling for the node: " +
40850b57cec5SDimitry Andric                      R.getName() + "; please add one to DeclNodes.td");
40860b57cec5SDimitry Andric     } else {
40870b57cec5SDimitry Andric       // The node may contain a list of elements itself, so split the elements
40880b57cec5SDimitry Andric       // by a comma, and trim any whitespace.
40890b57cec5SDimitry Andric       SmallVector<StringRef, 2> Frags;
40900b57cec5SDimitry Andric       llvm::SplitString(V, Frags, ",");
40910b57cec5SDimitry Andric       for (auto Str : Frags) {
40925ffd83dbSDimitry Andric         DiagList.push_back(std::string(Str.trim()));
40930b57cec5SDimitry Andric       }
40940b57cec5SDimitry Andric     }
40950b57cec5SDimitry Andric   }
40960b57cec5SDimitry Andric 
40970b57cec5SDimitry Andric   if (DiagList.empty()) {
40980b57cec5SDimitry Andric     PrintFatalError(S.getLoc(),
40990b57cec5SDimitry Andric                     "Could not deduce diagnostic argument for Attr subjects");
41000b57cec5SDimitry Andric     return "";
41010b57cec5SDimitry Andric   }
41020b57cec5SDimitry Andric 
41030b57cec5SDimitry Andric   // FIXME: this is not particularly good for localization purposes and ideally
41040b57cec5SDimitry Andric   // should be part of the diagnostics engine itself with some sort of list
41050b57cec5SDimitry Andric   // specifier.
41060b57cec5SDimitry Andric 
41070b57cec5SDimitry Andric   // A single member of the list can be returned directly.
41080b57cec5SDimitry Andric   if (DiagList.size() == 1)
41090b57cec5SDimitry Andric     return '"' + DiagList.front() + '"';
41100b57cec5SDimitry Andric 
41110b57cec5SDimitry Andric   if (DiagList.size() == 2)
41120b57cec5SDimitry Andric     return '"' + DiagList[0] + " and " + DiagList[1] + '"';
41130b57cec5SDimitry Andric 
41140b57cec5SDimitry Andric   // If there are more than two in the list, we serialize the first N - 1
41150b57cec5SDimitry Andric   // elements with a comma. This leaves the string in the state: foo, bar,
41160b57cec5SDimitry Andric   // baz (but misses quux). We can then add ", and " for the last element
41170b57cec5SDimitry Andric   // manually.
41180b57cec5SDimitry Andric   std::string Diag = llvm::join(DiagList.begin(), DiagList.end() - 1, ", ");
41190b57cec5SDimitry Andric   return '"' + Diag + ", and " + *(DiagList.end() - 1) + '"';
41200b57cec5SDimitry Andric }
41210b57cec5SDimitry Andric 
41220b57cec5SDimitry Andric static std::string GetSubjectWithSuffix(const Record *R) {
41235ffd83dbSDimitry Andric   const std::string &B = std::string(R->getName());
41240b57cec5SDimitry Andric   if (B == "DeclBase")
41250b57cec5SDimitry Andric     return "Decl";
41260b57cec5SDimitry Andric   return B + "Decl";
41270b57cec5SDimitry Andric }
41280b57cec5SDimitry Andric 
41290b57cec5SDimitry Andric static std::string functionNameForCustomAppertainsTo(const Record &Subject) {
41300b57cec5SDimitry Andric   return "is" + Subject.getName().str();
41310b57cec5SDimitry Andric }
41320b57cec5SDimitry Andric 
41335ffd83dbSDimitry Andric static void GenerateCustomAppertainsTo(const Record &Subject, raw_ostream &OS) {
41340b57cec5SDimitry Andric   std::string FnName = functionNameForCustomAppertainsTo(Subject);
41350b57cec5SDimitry Andric 
41365ffd83dbSDimitry Andric   // If this code has already been generated, we don't need to do anything.
41370b57cec5SDimitry Andric   static std::set<std::string> CustomSubjectSet;
41380b57cec5SDimitry Andric   auto I = CustomSubjectSet.find(FnName);
41390b57cec5SDimitry Andric   if (I != CustomSubjectSet.end())
41405ffd83dbSDimitry Andric     return;
41410b57cec5SDimitry Andric 
4142480093f4SDimitry Andric   // This only works with non-root Decls.
4143480093f4SDimitry Andric   Record *Base = Subject.getValueAsDef(BaseFieldName);
41440b57cec5SDimitry Andric 
41450b57cec5SDimitry Andric   // Not currently support custom subjects within custom subjects.
41460b57cec5SDimitry Andric   if (Base->isSubClassOf("SubsetSubject")) {
41470b57cec5SDimitry Andric     PrintFatalError(Subject.getLoc(),
41480b57cec5SDimitry Andric                     "SubsetSubjects within SubsetSubjects is not supported");
41495ffd83dbSDimitry Andric     return;
41500b57cec5SDimitry Andric   }
41510b57cec5SDimitry Andric 
41520b57cec5SDimitry Andric   OS << "static bool " << FnName << "(const Decl *D) {\n";
41530b57cec5SDimitry Andric   OS << "  if (const auto *S = dyn_cast<";
41540b57cec5SDimitry Andric   OS << GetSubjectWithSuffix(Base);
41550b57cec5SDimitry Andric   OS << ">(D))\n";
41560b57cec5SDimitry Andric   OS << "    return " << Subject.getValueAsString("CheckCode") << ";\n";
41570b57cec5SDimitry Andric   OS << "  return false;\n";
41580b57cec5SDimitry Andric   OS << "}\n\n";
41590b57cec5SDimitry Andric 
41600b57cec5SDimitry Andric   CustomSubjectSet.insert(FnName);
41610b57cec5SDimitry Andric }
41620b57cec5SDimitry Andric 
41635ffd83dbSDimitry Andric static void GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) {
41640b57cec5SDimitry Andric   // If the attribute does not contain a Subjects definition, then use the
41650b57cec5SDimitry Andric   // default appertainsTo logic.
41660b57cec5SDimitry Andric   if (Attr.isValueUnset("Subjects"))
41675ffd83dbSDimitry Andric     return;
41680b57cec5SDimitry Andric 
41690b57cec5SDimitry Andric   const Record *SubjectObj = Attr.getValueAsDef("Subjects");
41700b57cec5SDimitry Andric   std::vector<Record *> Subjects = SubjectObj->getValueAsListOfDefs("Subjects");
41710b57cec5SDimitry Andric 
41720b57cec5SDimitry Andric   // If the list of subjects is empty, it is assumed that the attribute
41730b57cec5SDimitry Andric   // appertains to everything.
41740b57cec5SDimitry Andric   if (Subjects.empty())
41755ffd83dbSDimitry Andric     return;
41760b57cec5SDimitry Andric 
41770b57cec5SDimitry Andric   bool Warn = SubjectObj->getValueAsDef("Diag")->getValueAsBit("Warn");
41780b57cec5SDimitry Andric 
4179fe6060f1SDimitry Andric   // Split the subjects into declaration subjects and statement subjects.
4180fe6060f1SDimitry Andric   // FIXME: subset subjects are added to the declaration list until there are
4181fe6060f1SDimitry Andric   // enough statement attributes with custom subject needs to warrant
4182fe6060f1SDimitry Andric   // the implementation effort.
4183fe6060f1SDimitry Andric   std::vector<Record *> DeclSubjects, StmtSubjects;
4184fe6060f1SDimitry Andric   llvm::copy_if(
4185fe6060f1SDimitry Andric       Subjects, std::back_inserter(DeclSubjects), [](const Record *R) {
4186fe6060f1SDimitry Andric         return R->isSubClassOf("SubsetSubject") || !R->isSubClassOf("StmtNode");
4187fe6060f1SDimitry Andric       });
4188fe6060f1SDimitry Andric   llvm::copy_if(Subjects, std::back_inserter(StmtSubjects),
4189fe6060f1SDimitry Andric                 [](const Record *R) { return R->isSubClassOf("StmtNode"); });
4190fe6060f1SDimitry Andric 
4191fe6060f1SDimitry Andric   // We should have sorted all of the subjects into two lists.
4192fe6060f1SDimitry Andric   // FIXME: this assertion will be wrong if we ever add type attribute subjects.
4193fe6060f1SDimitry Andric   assert(DeclSubjects.size() + StmtSubjects.size() == Subjects.size());
4194fe6060f1SDimitry Andric 
4195fe6060f1SDimitry Andric   if (DeclSubjects.empty()) {
4196fe6060f1SDimitry Andric     // If there are no decl subjects but there are stmt subjects, diagnose
4197fe6060f1SDimitry Andric     // trying to apply a statement attribute to a declaration.
4198fe6060f1SDimitry Andric     if (!StmtSubjects.empty()) {
4199fe6060f1SDimitry Andric       OS << "bool diagAppertainsToDecl(Sema &S, const ParsedAttr &AL, ";
4200fe6060f1SDimitry Andric       OS << "const Decl *D) const override {\n";
420181ad6265SDimitry Andric       OS << "  S.Diag(AL.getLoc(), diag::err_attribute_invalid_on_decl)\n";
420206c3fb27SDimitry Andric       OS << "    << AL << AL.isRegularKeywordAttribute() << "
420306c3fb27SDimitry Andric             "D->getLocation();\n";
4204fe6060f1SDimitry Andric       OS << "  return false;\n";
4205fe6060f1SDimitry Andric       OS << "}\n\n";
4206fe6060f1SDimitry Andric     }
4207fe6060f1SDimitry Andric   } else {
4208fe6060f1SDimitry Andric     // Otherwise, generate an appertainsTo check specific to this attribute
4209fe6060f1SDimitry Andric     // which checks all of the given subjects against the Decl passed in.
42105ffd83dbSDimitry Andric     OS << "bool diagAppertainsToDecl(Sema &S, ";
42115ffd83dbSDimitry Andric     OS << "const ParsedAttr &Attr, const Decl *D) const override {\n";
42125ffd83dbSDimitry Andric     OS << "  if (";
4213fe6060f1SDimitry Andric     for (auto I = DeclSubjects.begin(), E = DeclSubjects.end(); I != E; ++I) {
42145ffd83dbSDimitry Andric       // If the subject has custom code associated with it, use the generated
42155ffd83dbSDimitry Andric       // function for it. The function cannot be inlined into this check (yet)
42165ffd83dbSDimitry Andric       // because it requires the subject to be of a specific type, and were that
4217fe6060f1SDimitry Andric       // information inlined here, it would not support an attribute with
4218fe6060f1SDimitry Andric       // multiple custom subjects.
4219fe6060f1SDimitry Andric       if ((*I)->isSubClassOf("SubsetSubject"))
42205ffd83dbSDimitry Andric         OS << "!" << functionNameForCustomAppertainsTo(**I) << "(D)";
4221fe6060f1SDimitry Andric       else
42225ffd83dbSDimitry Andric         OS << "!isa<" << GetSubjectWithSuffix(*I) << ">(D)";
42230b57cec5SDimitry Andric 
42240b57cec5SDimitry Andric       if (I + 1 != E)
42255ffd83dbSDimitry Andric         OS << " && ";
42260b57cec5SDimitry Andric     }
42275ffd83dbSDimitry Andric     OS << ") {\n";
42285ffd83dbSDimitry Andric     OS << "    S.Diag(Attr.getLoc(), diag::";
4229fe6060f1SDimitry Andric     OS << (Warn ? "warn_attribute_wrong_decl_type_str"
4230fe6060f1SDimitry Andric                 : "err_attribute_wrong_decl_type_str");
42315ffd83dbSDimitry Andric     OS << ")\n";
423206c3fb27SDimitry Andric     OS << "      << Attr << Attr.isRegularKeywordAttribute() << ";
42335ffd83dbSDimitry Andric     OS << CalculateDiagnostic(*SubjectObj) << ";\n";
42345ffd83dbSDimitry Andric     OS << "    return false;\n";
42355ffd83dbSDimitry Andric     OS << "  }\n";
42365ffd83dbSDimitry Andric     OS << "  return true;\n";
42375ffd83dbSDimitry Andric     OS << "}\n\n";
42380b57cec5SDimitry Andric   }
42390b57cec5SDimitry Andric 
4240fe6060f1SDimitry Andric   if (StmtSubjects.empty()) {
4241fe6060f1SDimitry Andric     // If there are no stmt subjects but there are decl subjects, diagnose
4242fe6060f1SDimitry Andric     // trying to apply a declaration attribute to a statement.
4243fe6060f1SDimitry Andric     if (!DeclSubjects.empty()) {
4244fe6060f1SDimitry Andric       OS << "bool diagAppertainsToStmt(Sema &S, const ParsedAttr &AL, ";
4245fe6060f1SDimitry Andric       OS << "const Stmt *St) const override {\n";
4246fe6060f1SDimitry Andric       OS << "  S.Diag(AL.getLoc(), diag::err_decl_attribute_invalid_on_stmt)\n";
424706c3fb27SDimitry Andric       OS << "    << AL << AL.isRegularKeywordAttribute() << "
424806c3fb27SDimitry Andric             "St->getBeginLoc();\n";
4249fe6060f1SDimitry Andric       OS << "  return false;\n";
4250fe6060f1SDimitry Andric       OS << "}\n\n";
4251fe6060f1SDimitry Andric     }
4252fe6060f1SDimitry Andric   } else {
4253fe6060f1SDimitry Andric     // Now, do the same for statements.
4254fe6060f1SDimitry Andric     OS << "bool diagAppertainsToStmt(Sema &S, ";
4255fe6060f1SDimitry Andric     OS << "const ParsedAttr &Attr, const Stmt *St) const override {\n";
4256fe6060f1SDimitry Andric     OS << "  if (";
4257fe6060f1SDimitry Andric     for (auto I = StmtSubjects.begin(), E = StmtSubjects.end(); I != E; ++I) {
4258fe6060f1SDimitry Andric       OS << "!isa<" << (*I)->getName() << ">(St)";
4259fe6060f1SDimitry Andric       if (I + 1 != E)
4260fe6060f1SDimitry Andric         OS << " && ";
4261fe6060f1SDimitry Andric     }
4262fe6060f1SDimitry Andric     OS << ") {\n";
4263fe6060f1SDimitry Andric     OS << "    S.Diag(Attr.getLoc(), diag::";
4264fe6060f1SDimitry Andric     OS << (Warn ? "warn_attribute_wrong_decl_type_str"
4265fe6060f1SDimitry Andric                 : "err_attribute_wrong_decl_type_str");
4266fe6060f1SDimitry Andric     OS << ")\n";
426706c3fb27SDimitry Andric     OS << "      << Attr << Attr.isRegularKeywordAttribute() << ";
4268fe6060f1SDimitry Andric     OS << CalculateDiagnostic(*SubjectObj) << ";\n";
4269fe6060f1SDimitry Andric     OS << "    return false;\n";
4270fe6060f1SDimitry Andric     OS << "  }\n";
4271fe6060f1SDimitry Andric     OS << "  return true;\n";
4272fe6060f1SDimitry Andric     OS << "}\n\n";
4273fe6060f1SDimitry Andric   }
4274fe6060f1SDimitry Andric }
4275fe6060f1SDimitry Andric 
4276fe6060f1SDimitry Andric // Generates the mutual exclusion checks. The checks for parsed attributes are
4277fe6060f1SDimitry Andric // written into OS and the checks for merging declaration attributes are
4278fe6060f1SDimitry Andric // written into MergeOS.
4279fe6060f1SDimitry Andric static void GenerateMutualExclusionsChecks(const Record &Attr,
4280fe6060f1SDimitry Andric                                            const RecordKeeper &Records,
4281fe6060f1SDimitry Andric                                            raw_ostream &OS,
4282fe6060f1SDimitry Andric                                            raw_ostream &MergeDeclOS,
4283fe6060f1SDimitry Andric                                            raw_ostream &MergeStmtOS) {
4284fe6060f1SDimitry Andric   // Find all of the definitions that inherit from MutualExclusions and include
4285fe6060f1SDimitry Andric   // the given attribute in the list of exclusions to generate the
4286fe6060f1SDimitry Andric   // diagMutualExclusion() check.
4287fe6060f1SDimitry Andric   std::vector<Record *> ExclusionsList =
4288fe6060f1SDimitry Andric       Records.getAllDerivedDefinitions("MutualExclusions");
4289fe6060f1SDimitry Andric 
4290fe6060f1SDimitry Andric   // We don't do any of this magic for type attributes yet.
4291fe6060f1SDimitry Andric   if (Attr.isSubClassOf("TypeAttr"))
4292fe6060f1SDimitry Andric     return;
4293fe6060f1SDimitry Andric 
4294fe6060f1SDimitry Andric   // This means the attribute is either a statement attribute, a decl
4295fe6060f1SDimitry Andric   // attribute, or both; find out which.
4296fe6060f1SDimitry Andric   bool CurAttrIsStmtAttr =
4297fe6060f1SDimitry Andric       Attr.isSubClassOf("StmtAttr") || Attr.isSubClassOf("DeclOrStmtAttr");
4298fe6060f1SDimitry Andric   bool CurAttrIsDeclAttr =
4299fe6060f1SDimitry Andric       !CurAttrIsStmtAttr || Attr.isSubClassOf("DeclOrStmtAttr");
4300fe6060f1SDimitry Andric 
4301fe6060f1SDimitry Andric   std::vector<std::string> DeclAttrs, StmtAttrs;
4302fe6060f1SDimitry Andric 
4303fe6060f1SDimitry Andric   for (const Record *Exclusion : ExclusionsList) {
4304fe6060f1SDimitry Andric     std::vector<Record *> MutuallyExclusiveAttrs =
4305fe6060f1SDimitry Andric         Exclusion->getValueAsListOfDefs("Exclusions");
4306fe6060f1SDimitry Andric     auto IsCurAttr = [Attr](const Record *R) {
4307fe6060f1SDimitry Andric       return R->getName() == Attr.getName();
4308fe6060f1SDimitry Andric     };
4309fe6060f1SDimitry Andric     if (llvm::any_of(MutuallyExclusiveAttrs, IsCurAttr)) {
4310fe6060f1SDimitry Andric       // This list of exclusions includes the attribute we're looking for, so
4311fe6060f1SDimitry Andric       // add the exclusive attributes to the proper list for checking.
4312fe6060f1SDimitry Andric       for (const Record *AttrToExclude : MutuallyExclusiveAttrs) {
4313fe6060f1SDimitry Andric         if (IsCurAttr(AttrToExclude))
4314fe6060f1SDimitry Andric           continue;
4315fe6060f1SDimitry Andric 
4316fe6060f1SDimitry Andric         if (CurAttrIsStmtAttr)
4317fe6060f1SDimitry Andric           StmtAttrs.push_back((AttrToExclude->getName() + "Attr").str());
4318fe6060f1SDimitry Andric         if (CurAttrIsDeclAttr)
4319fe6060f1SDimitry Andric           DeclAttrs.push_back((AttrToExclude->getName() + "Attr").str());
4320fe6060f1SDimitry Andric       }
4321fe6060f1SDimitry Andric     }
4322fe6060f1SDimitry Andric   }
4323fe6060f1SDimitry Andric 
4324fe6060f1SDimitry Andric   // If there are any decl or stmt attributes, silence -Woverloaded-virtual
4325fe6060f1SDimitry Andric   // warnings for them both.
4326fe6060f1SDimitry Andric   if (!DeclAttrs.empty() || !StmtAttrs.empty())
4327fe6060f1SDimitry Andric     OS << "  using ParsedAttrInfo::diagMutualExclusion;\n\n";
4328fe6060f1SDimitry Andric 
4329fe6060f1SDimitry Andric   // If we discovered any decl or stmt attributes to test for, generate the
4330fe6060f1SDimitry Andric   // predicates for them now.
4331fe6060f1SDimitry Andric   if (!DeclAttrs.empty()) {
4332fe6060f1SDimitry Andric     // Generate the ParsedAttrInfo subclass logic for declarations.
4333fe6060f1SDimitry Andric     OS << "  bool diagMutualExclusion(Sema &S, const ParsedAttr &AL, "
4334fe6060f1SDimitry Andric        << "const Decl *D) const override {\n";
4335fe6060f1SDimitry Andric     for (const std::string &A : DeclAttrs) {
4336fe6060f1SDimitry Andric       OS << "    if (const auto *A = D->getAttr<" << A << ">()) {\n";
4337fe6060f1SDimitry Andric       OS << "      S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)"
433806c3fb27SDimitry Andric          << " << AL << A << (AL.isRegularKeywordAttribute() ||"
433906c3fb27SDimitry Andric          << " A->isRegularKeywordAttribute());\n";
4340fe6060f1SDimitry Andric       OS << "      S.Diag(A->getLocation(), diag::note_conflicting_attribute);";
4341fe6060f1SDimitry Andric       OS << "      \nreturn false;\n";
4342fe6060f1SDimitry Andric       OS << "    }\n";
4343fe6060f1SDimitry Andric     }
4344fe6060f1SDimitry Andric     OS << "    return true;\n";
4345fe6060f1SDimitry Andric     OS << "  }\n\n";
4346fe6060f1SDimitry Andric 
4347fe6060f1SDimitry Andric     // Also generate the declaration attribute merging logic if the current
4348fe6060f1SDimitry Andric     // attribute is one that can be inheritted on a declaration. It is assumed
4349fe6060f1SDimitry Andric     // this code will be executed in the context of a function with parameters:
4350fe6060f1SDimitry Andric     // Sema &S, Decl *D, Attr *A and that returns a bool (false on diagnostic,
4351fe6060f1SDimitry Andric     // true on success).
4352fe6060f1SDimitry Andric     if (Attr.isSubClassOf("InheritableAttr")) {
4353fe6060f1SDimitry Andric       MergeDeclOS << "  if (const auto *Second = dyn_cast<"
4354fe6060f1SDimitry Andric                   << (Attr.getName() + "Attr").str() << ">(A)) {\n";
4355fe6060f1SDimitry Andric       for (const std::string &A : DeclAttrs) {
4356fe6060f1SDimitry Andric         MergeDeclOS << "    if (const auto *First = D->getAttr<" << A
4357fe6060f1SDimitry Andric                     << ">()) {\n";
4358fe6060f1SDimitry Andric         MergeDeclOS << "      S.Diag(First->getLocation(), "
4359fe6060f1SDimitry Andric                     << "diag::err_attributes_are_not_compatible) << First << "
436006c3fb27SDimitry Andric                     << "Second << (First->isRegularKeywordAttribute() || "
436106c3fb27SDimitry Andric                     << "Second->isRegularKeywordAttribute());\n";
4362fe6060f1SDimitry Andric         MergeDeclOS << "      S.Diag(Second->getLocation(), "
4363fe6060f1SDimitry Andric                     << "diag::note_conflicting_attribute);\n";
4364fe6060f1SDimitry Andric         MergeDeclOS << "      return false;\n";
4365fe6060f1SDimitry Andric         MergeDeclOS << "    }\n";
4366fe6060f1SDimitry Andric       }
4367fe6060f1SDimitry Andric       MergeDeclOS << "    return true;\n";
4368fe6060f1SDimitry Andric       MergeDeclOS << "  }\n";
4369fe6060f1SDimitry Andric     }
4370fe6060f1SDimitry Andric   }
4371fe6060f1SDimitry Andric 
4372fe6060f1SDimitry Andric   // Statement attributes are a bit different from declarations. With
4373fe6060f1SDimitry Andric   // declarations, each attribute is added to the declaration as it is
4374fe6060f1SDimitry Andric   // processed, and so you can look on the Decl * itself to see if there is a
4375fe6060f1SDimitry Andric   // conflicting attribute. Statement attributes are processed as a group
4376fe6060f1SDimitry Andric   // because AttributedStmt needs to tail-allocate all of the attribute nodes
4377fe6060f1SDimitry Andric   // at once. This means we cannot check whether the statement already contains
4378fe6060f1SDimitry Andric   // an attribute to check for the conflict. Instead, we need to check whether
4379fe6060f1SDimitry Andric   // the given list of semantic attributes contain any conflicts. It is assumed
4380fe6060f1SDimitry Andric   // this code will be executed in the context of a function with parameters:
4381fe6060f1SDimitry Andric   // Sema &S, const SmallVectorImpl<const Attr *> &C. The code will be within a
4382fe6060f1SDimitry Andric   // loop which loops over the container C with a loop variable named A to
4383fe6060f1SDimitry Andric   // represent the current attribute to check for conflicts.
4384fe6060f1SDimitry Andric   //
4385fe6060f1SDimitry Andric   // FIXME: it would be nice not to walk over the list of potential attributes
4386fe6060f1SDimitry Andric   // to apply to the statement more than once, but statements typically don't
4387fe6060f1SDimitry Andric   // have long lists of attributes on them, so re-walking the list should not
4388fe6060f1SDimitry Andric   // be an expensive operation.
4389fe6060f1SDimitry Andric   if (!StmtAttrs.empty()) {
4390fe6060f1SDimitry Andric     MergeStmtOS << "    if (const auto *Second = dyn_cast<"
4391fe6060f1SDimitry Andric                 << (Attr.getName() + "Attr").str() << ">(A)) {\n";
4392fe6060f1SDimitry Andric     MergeStmtOS << "      auto Iter = llvm::find_if(C, [](const Attr *Check) "
4393fe6060f1SDimitry Andric                 << "{ return isa<";
4394fe6060f1SDimitry Andric     interleave(
4395fe6060f1SDimitry Andric         StmtAttrs, [&](const std::string &Name) { MergeStmtOS << Name; },
4396fe6060f1SDimitry Andric         [&] { MergeStmtOS << ", "; });
4397fe6060f1SDimitry Andric     MergeStmtOS << ">(Check); });\n";
4398fe6060f1SDimitry Andric     MergeStmtOS << "      if (Iter != C.end()) {\n";
4399fe6060f1SDimitry Andric     MergeStmtOS << "        S.Diag((*Iter)->getLocation(), "
4400fe6060f1SDimitry Andric                 << "diag::err_attributes_are_not_compatible) << *Iter << "
440106c3fb27SDimitry Andric                 << "Second << ((*Iter)->isRegularKeywordAttribute() || "
440206c3fb27SDimitry Andric                 << "Second->isRegularKeywordAttribute());\n";
4403fe6060f1SDimitry Andric     MergeStmtOS << "        S.Diag(Second->getLocation(), "
4404fe6060f1SDimitry Andric                 << "diag::note_conflicting_attribute);\n";
4405fe6060f1SDimitry Andric     MergeStmtOS << "        return false;\n";
4406fe6060f1SDimitry Andric     MergeStmtOS << "      }\n";
4407fe6060f1SDimitry Andric     MergeStmtOS << "    }\n";
4408fe6060f1SDimitry Andric   }
4409fe6060f1SDimitry Andric }
4410fe6060f1SDimitry Andric 
44110b57cec5SDimitry Andric static void
44120b57cec5SDimitry Andric emitAttributeMatchRules(PragmaClangAttributeSupport &PragmaAttributeSupport,
44130b57cec5SDimitry Andric                         raw_ostream &OS) {
44140b57cec5SDimitry Andric   OS << "static bool checkAttributeMatchRuleAppliesTo(const Decl *D, "
44150b57cec5SDimitry Andric      << AttributeSubjectMatchRule::EnumName << " rule) {\n";
44160b57cec5SDimitry Andric   OS << "  switch (rule) {\n";
44170b57cec5SDimitry Andric   for (const auto &Rule : PragmaAttributeSupport.Rules) {
44180b57cec5SDimitry Andric     if (Rule.isAbstractRule()) {
44190b57cec5SDimitry Andric       OS << "  case " << Rule.getEnumValue() << ":\n";
44200b57cec5SDimitry Andric       OS << "    assert(false && \"Abstract matcher rule isn't allowed\");\n";
44210b57cec5SDimitry Andric       OS << "    return false;\n";
44220b57cec5SDimitry Andric       continue;
44230b57cec5SDimitry Andric     }
44240b57cec5SDimitry Andric     std::vector<Record *> Subjects = Rule.getSubjects();
44250b57cec5SDimitry Andric     assert(!Subjects.empty() && "Missing subjects");
44260b57cec5SDimitry Andric     OS << "  case " << Rule.getEnumValue() << ":\n";
44270b57cec5SDimitry Andric     OS << "    return ";
44280b57cec5SDimitry Andric     for (auto I = Subjects.begin(), E = Subjects.end(); I != E; ++I) {
44290b57cec5SDimitry Andric       // If the subject has custom code associated with it, use the function
44300b57cec5SDimitry Andric       // that was generated for GenerateAppertainsTo to check if the declaration
44310b57cec5SDimitry Andric       // is valid.
44320b57cec5SDimitry Andric       if ((*I)->isSubClassOf("SubsetSubject"))
44330b57cec5SDimitry Andric         OS << functionNameForCustomAppertainsTo(**I) << "(D)";
44340b57cec5SDimitry Andric       else
44350b57cec5SDimitry Andric         OS << "isa<" << GetSubjectWithSuffix(*I) << ">(D)";
44360b57cec5SDimitry Andric 
44370b57cec5SDimitry Andric       if (I + 1 != E)
44380b57cec5SDimitry Andric         OS << " || ";
44390b57cec5SDimitry Andric     }
44400b57cec5SDimitry Andric     OS << ";\n";
44410b57cec5SDimitry Andric   }
44420b57cec5SDimitry Andric   OS << "  }\n";
44430b57cec5SDimitry Andric   OS << "  llvm_unreachable(\"Invalid match rule\");\nreturn false;\n";
44440b57cec5SDimitry Andric   OS << "}\n\n";
44450b57cec5SDimitry Andric }
44460b57cec5SDimitry Andric 
44475ffd83dbSDimitry Andric static void GenerateLangOptRequirements(const Record &R,
44480b57cec5SDimitry Andric                                         raw_ostream &OS) {
44490b57cec5SDimitry Andric   // If the attribute has an empty or unset list of language requirements,
44505ffd83dbSDimitry Andric   // use the default handler.
44510b57cec5SDimitry Andric   std::vector<Record *> LangOpts = R.getValueAsListOfDefs("LangOpts");
44520b57cec5SDimitry Andric   if (LangOpts.empty())
44535ffd83dbSDimitry Andric     return;
44540b57cec5SDimitry Andric 
4455349cc55cSDimitry Andric   OS << "bool acceptsLangOpts(const LangOptions &LangOpts) const override {\n";
4456349cc55cSDimitry Andric   OS << "  return " << GenerateTestExpression(LangOpts) << ";\n";
44570b57cec5SDimitry Andric   OS << "}\n\n";
44580b57cec5SDimitry Andric }
44590b57cec5SDimitry Andric 
44605ffd83dbSDimitry Andric static void GenerateTargetRequirements(const Record &Attr,
44610b57cec5SDimitry Andric                                        const ParsedAttrMap &Dupes,
44620b57cec5SDimitry Andric                                        raw_ostream &OS) {
44635ffd83dbSDimitry Andric   // If the attribute is not a target specific attribute, use the default
44640b57cec5SDimitry Andric   // target handler.
44650b57cec5SDimitry Andric   if (!Attr.isSubClassOf("TargetSpecificAttr"))
44665ffd83dbSDimitry Andric     return;
44670b57cec5SDimitry Andric 
44680b57cec5SDimitry Andric   // Get the list of architectures to be tested for.
44690b57cec5SDimitry Andric   const Record *R = Attr.getValueAsDef("Target");
44700b57cec5SDimitry Andric   std::vector<StringRef> Arches = R->getValueAsListOfStrings("Arches");
44710b57cec5SDimitry Andric 
44720b57cec5SDimitry Andric   // If there are other attributes which share the same parsed attribute kind,
44730b57cec5SDimitry Andric   // such as target-specific attributes with a shared spelling, collapse the
44740b57cec5SDimitry Andric   // duplicate architectures. This is required because a shared target-specific
44750b57cec5SDimitry Andric   // attribute has only one ParsedAttr::Kind enumeration value, but it
44760b57cec5SDimitry Andric   // applies to multiple target architectures. In order for the attribute to be
44770b57cec5SDimitry Andric   // considered valid, all of its architectures need to be included.
44780b57cec5SDimitry Andric   if (!Attr.isValueUnset("ParseKind")) {
44790b57cec5SDimitry Andric     const StringRef APK = Attr.getValueAsString("ParseKind");
44800b57cec5SDimitry Andric     for (const auto &I : Dupes) {
44810b57cec5SDimitry Andric       if (I.first == APK) {
44820b57cec5SDimitry Andric         std::vector<StringRef> DA =
44830b57cec5SDimitry Andric             I.second->getValueAsDef("Target")->getValueAsListOfStrings(
44840b57cec5SDimitry Andric                 "Arches");
44850b57cec5SDimitry Andric         Arches.insert(Arches.end(), DA.begin(), DA.end());
44860b57cec5SDimitry Andric       }
44870b57cec5SDimitry Andric     }
44880b57cec5SDimitry Andric   }
44890b57cec5SDimitry Andric 
44900b57cec5SDimitry Andric   std::string FnName = "isTarget";
44910b57cec5SDimitry Andric   std::string Test;
44920b57cec5SDimitry Andric   bool UsesT = GenerateTargetSpecificAttrChecks(R, Arches, Test, &FnName);
44930b57cec5SDimitry Andric 
44945ffd83dbSDimitry Andric   OS << "bool existsInTarget(const TargetInfo &Target) const override {\n";
44950b57cec5SDimitry Andric   if (UsesT)
44960b57cec5SDimitry Andric     OS << "  const llvm::Triple &T = Target.getTriple(); (void)T;\n";
44970b57cec5SDimitry Andric   OS << "  return " << Test << ";\n";
44980b57cec5SDimitry Andric   OS << "}\n\n";
44990b57cec5SDimitry Andric }
45000b57cec5SDimitry Andric 
45015f757f3fSDimitry Andric static void
45025f757f3fSDimitry Andric GenerateSpellingTargetRequirements(const Record &Attr,
45035f757f3fSDimitry Andric                                    const std::vector<Record *> &TargetSpellings,
45045f757f3fSDimitry Andric                                    raw_ostream &OS) {
45055f757f3fSDimitry Andric   // If there are no target specific spellings, use the default target handler.
45065f757f3fSDimitry Andric   if (TargetSpellings.empty())
45075f757f3fSDimitry Andric     return;
45085f757f3fSDimitry Andric 
45095f757f3fSDimitry Andric   std::string Test;
45105f757f3fSDimitry Andric   bool UsesT = false;
45115f757f3fSDimitry Andric   const std::vector<FlattenedSpelling> SpellingList =
45125f757f3fSDimitry Andric       GetFlattenedSpellings(Attr);
45135f757f3fSDimitry Andric   for (unsigned TargetIndex = 0; TargetIndex < TargetSpellings.size();
45145f757f3fSDimitry Andric        ++TargetIndex) {
45155f757f3fSDimitry Andric     const auto &TargetSpelling = TargetSpellings[TargetIndex];
45165f757f3fSDimitry Andric     std::vector<FlattenedSpelling> Spellings =
45175f757f3fSDimitry Andric         GetFlattenedSpellings(*TargetSpelling);
45185f757f3fSDimitry Andric 
45195f757f3fSDimitry Andric     Test += "((SpellingListIndex == ";
45205f757f3fSDimitry Andric     for (unsigned Index = 0; Index < Spellings.size(); ++Index) {
45215f757f3fSDimitry Andric       Test +=
45225f757f3fSDimitry Andric           llvm::itostr(getSpellingListIndex(SpellingList, Spellings[Index]));
45235f757f3fSDimitry Andric       if (Index != Spellings.size() - 1)
45245f757f3fSDimitry Andric         Test += " ||\n    SpellingListIndex == ";
45255f757f3fSDimitry Andric       else
45265f757f3fSDimitry Andric         Test += ") && ";
45275f757f3fSDimitry Andric     }
45285f757f3fSDimitry Andric 
45295f757f3fSDimitry Andric     const Record *Target = TargetSpelling->getValueAsDef("Target");
45305f757f3fSDimitry Andric     std::vector<StringRef> Arches = Target->getValueAsListOfStrings("Arches");
45315f757f3fSDimitry Andric     std::string FnName = "isTargetSpelling";
45325f757f3fSDimitry Andric     UsesT |= GenerateTargetSpecificAttrChecks(Target, Arches, Test, &FnName);
45335f757f3fSDimitry Andric     Test += ")";
45345f757f3fSDimitry Andric     if (TargetIndex != TargetSpellings.size() - 1)
45355f757f3fSDimitry Andric       Test += " || ";
45365f757f3fSDimitry Andric   }
45375f757f3fSDimitry Andric 
45385f757f3fSDimitry Andric   OS << "bool spellingExistsInTarget(const TargetInfo &Target,\n";
45395f757f3fSDimitry Andric   OS << "                            const unsigned SpellingListIndex) const "
45405f757f3fSDimitry Andric         "override {\n";
45415f757f3fSDimitry Andric   if (UsesT)
45425f757f3fSDimitry Andric     OS << "  const llvm::Triple &T = Target.getTriple(); (void)T;\n";
45435f757f3fSDimitry Andric   OS << "  return " << Test << ";\n", OS << "}\n\n";
45445f757f3fSDimitry Andric }
45455f757f3fSDimitry Andric 
45465ffd83dbSDimitry Andric static void GenerateSpellingIndexToSemanticSpelling(const Record &Attr,
45470b57cec5SDimitry Andric                                                     raw_ostream &OS) {
45480b57cec5SDimitry Andric   // If the attribute does not have a semantic form, we can bail out early.
45490b57cec5SDimitry Andric   if (!Attr.getValueAsBit("ASTNode"))
45505ffd83dbSDimitry Andric     return;
45510b57cec5SDimitry Andric 
45520b57cec5SDimitry Andric   std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
45530b57cec5SDimitry Andric 
45540b57cec5SDimitry Andric   // If there are zero or one spellings, or all of the spellings share the same
45550b57cec5SDimitry Andric   // name, we can also bail out early.
45560b57cec5SDimitry Andric   if (Spellings.size() <= 1 || SpellingNamesAreCommon(Spellings))
45575ffd83dbSDimitry Andric     return;
45580b57cec5SDimitry Andric 
45590b57cec5SDimitry Andric   // Generate the enumeration we will use for the mapping.
45600b57cec5SDimitry Andric   SemanticSpellingMap SemanticToSyntacticMap;
45610b57cec5SDimitry Andric   std::string Enum = CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);
45620b57cec5SDimitry Andric   std::string Name = Attr.getName().str() + "AttrSpellingMap";
45630b57cec5SDimitry Andric 
45645ffd83dbSDimitry Andric   OS << "unsigned spellingIndexToSemanticSpelling(";
45655ffd83dbSDimitry Andric   OS << "const ParsedAttr &Attr) const override {\n";
45660b57cec5SDimitry Andric   OS << Enum;
45670b57cec5SDimitry Andric   OS << "  unsigned Idx = Attr.getAttributeSpellingListIndex();\n";
45680b57cec5SDimitry Andric   WriteSemanticSpellingSwitch("Idx", SemanticToSyntacticMap, OS);
45690b57cec5SDimitry Andric   OS << "}\n\n";
45705ffd83dbSDimitry Andric }
45710b57cec5SDimitry Andric 
45725ffd83dbSDimitry Andric static void GenerateHandleDeclAttribute(const Record &Attr, raw_ostream &OS) {
45735ffd83dbSDimitry Andric   // Only generate if Attr can be handled simply.
45745ffd83dbSDimitry Andric   if (!Attr.getValueAsBit("SimpleHandler"))
45755ffd83dbSDimitry Andric     return;
45765ffd83dbSDimitry Andric 
45775ffd83dbSDimitry Andric   // Generate a function which just converts from ParsedAttr to the Attr type.
45785ffd83dbSDimitry Andric   OS << "AttrHandling handleDeclAttribute(Sema &S, Decl *D,";
45795ffd83dbSDimitry Andric   OS << "const ParsedAttr &Attr) const override {\n";
45805ffd83dbSDimitry Andric   OS << "  D->addAttr(::new (S.Context) " << Attr.getName();
45815ffd83dbSDimitry Andric   OS << "Attr(S.Context, Attr));\n";
45825ffd83dbSDimitry Andric   OS << "  return AttributeApplied;\n";
45835ffd83dbSDimitry Andric   OS << "}\n\n";
45840b57cec5SDimitry Andric }
45850b57cec5SDimitry Andric 
458681ad6265SDimitry Andric static bool isParamExpr(const Record *Arg) {
458781ad6265SDimitry Andric   return !Arg->getSuperClasses().empty() &&
458881ad6265SDimitry Andric          llvm::StringSwitch<bool>(
458981ad6265SDimitry Andric              Arg->getSuperClasses().back().first->getName())
459081ad6265SDimitry Andric              .Case("ExprArgument", true)
459181ad6265SDimitry Andric              .Case("VariadicExprArgument", true)
459281ad6265SDimitry Andric              .Default(false);
459381ad6265SDimitry Andric }
459481ad6265SDimitry Andric 
459581ad6265SDimitry Andric void GenerateIsParamExpr(const Record &Attr, raw_ostream &OS) {
459681ad6265SDimitry Andric   OS << "bool isParamExpr(size_t N) const override {\n";
459781ad6265SDimitry Andric   OS << "  return ";
459881ad6265SDimitry Andric   auto Args = Attr.getValueAsListOfDefs("Args");
459981ad6265SDimitry Andric   for (size_t I = 0; I < Args.size(); ++I)
460081ad6265SDimitry Andric     if (isParamExpr(Args[I]))
460181ad6265SDimitry Andric       OS << "(N == " << I << ") || ";
460281ad6265SDimitry Andric   OS << "false;\n";
460381ad6265SDimitry Andric   OS << "}\n\n";
460481ad6265SDimitry Andric }
460581ad6265SDimitry Andric 
460681ad6265SDimitry Andric void GenerateHandleAttrWithDelayedArgs(RecordKeeper &Records, raw_ostream &OS) {
460781ad6265SDimitry Andric   OS << "static void handleAttrWithDelayedArgs(Sema &S, Decl *D, ";
460881ad6265SDimitry Andric   OS << "const ParsedAttr &Attr) {\n";
460981ad6265SDimitry Andric   OS << "  SmallVector<Expr *, 4> ArgExprs;\n";
461081ad6265SDimitry Andric   OS << "  ArgExprs.reserve(Attr.getNumArgs());\n";
461181ad6265SDimitry Andric   OS << "  for (unsigned I = 0; I < Attr.getNumArgs(); ++I) {\n";
461281ad6265SDimitry Andric   OS << "    assert(!Attr.isArgIdent(I));\n";
461381ad6265SDimitry Andric   OS << "    ArgExprs.push_back(Attr.getArgAsExpr(I));\n";
461481ad6265SDimitry Andric   OS << "  }\n";
461581ad6265SDimitry Andric   OS << "  clang::Attr *CreatedAttr = nullptr;\n";
461681ad6265SDimitry Andric   OS << "  switch (Attr.getKind()) {\n";
461781ad6265SDimitry Andric   OS << "  default:\n";
461881ad6265SDimitry Andric   OS << "    llvm_unreachable(\"Attribute cannot hold delayed arguments.\");\n";
461981ad6265SDimitry Andric   ParsedAttrMap Attrs = getParsedAttrList(Records);
462081ad6265SDimitry Andric   for (const auto &I : Attrs) {
462181ad6265SDimitry Andric     const Record &R = *I.second;
462281ad6265SDimitry Andric     if (!R.getValueAsBit("AcceptsExprPack"))
462381ad6265SDimitry Andric       continue;
462481ad6265SDimitry Andric     OS << "  case ParsedAttr::AT_" << I.first << ": {\n";
462581ad6265SDimitry Andric     OS << "    CreatedAttr = " << R.getName() << "Attr::CreateWithDelayedArgs";
462681ad6265SDimitry Andric     OS << "(S.Context, ArgExprs.data(), ArgExprs.size(), Attr);\n";
462781ad6265SDimitry Andric     OS << "    break;\n";
462881ad6265SDimitry Andric     OS << "  }\n";
462981ad6265SDimitry Andric   }
463081ad6265SDimitry Andric   OS << "  }\n";
463181ad6265SDimitry Andric   OS << "  D->addAttr(CreatedAttr);\n";
463281ad6265SDimitry Andric   OS << "}\n\n";
463381ad6265SDimitry Andric }
463481ad6265SDimitry Andric 
46350b57cec5SDimitry Andric static bool IsKnownToGCC(const Record &Attr) {
46360b57cec5SDimitry Andric   // Look at the spellings for this subject; if there are any spellings which
46370b57cec5SDimitry Andric   // claim to be known to GCC, the attribute is known to GCC.
46380b57cec5SDimitry Andric   return llvm::any_of(
46390b57cec5SDimitry Andric       GetFlattenedSpellings(Attr),
46400b57cec5SDimitry Andric       [](const FlattenedSpelling &S) { return S.knownToGCC(); });
46410b57cec5SDimitry Andric }
46420b57cec5SDimitry Andric 
46430b57cec5SDimitry Andric /// Emits the parsed attribute helpers
46440b57cec5SDimitry Andric void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
46455f757f3fSDimitry Andric   emitSourceFileHeader("Parsed attribute helpers", OS, Records);
46460b57cec5SDimitry Andric 
4647fe6060f1SDimitry Andric   OS << "#if !defined(WANT_DECL_MERGE_LOGIC) && "
4648fe6060f1SDimitry Andric      << "!defined(WANT_STMT_MERGE_LOGIC)\n";
46490b57cec5SDimitry Andric   PragmaClangAttributeSupport &PragmaAttributeSupport =
46500b57cec5SDimitry Andric       getPragmaAttributeSupport(Records);
46510b57cec5SDimitry Andric 
46520b57cec5SDimitry Andric   // Get the list of parsed attributes, and accept the optional list of
46530b57cec5SDimitry Andric   // duplicates due to the ParseKind.
46540b57cec5SDimitry Andric   ParsedAttrMap Dupes;
46550b57cec5SDimitry Andric   ParsedAttrMap Attrs = getParsedAttrList(Records, &Dupes);
46560b57cec5SDimitry Andric 
46575ffd83dbSDimitry Andric   // Generate all of the custom appertainsTo functions that the attributes
46585ffd83dbSDimitry Andric   // will be using.
465906c3fb27SDimitry Andric   for (const auto &I : Attrs) {
46605ffd83dbSDimitry Andric     const Record &Attr = *I.second;
46615ffd83dbSDimitry Andric     if (Attr.isValueUnset("Subjects"))
46625ffd83dbSDimitry Andric       continue;
46635ffd83dbSDimitry Andric     const Record *SubjectObj = Attr.getValueAsDef("Subjects");
46645ffd83dbSDimitry Andric     for (auto Subject : SubjectObj->getValueAsListOfDefs("Subjects"))
46655ffd83dbSDimitry Andric       if (Subject->isSubClassOf("SubsetSubject"))
46665ffd83dbSDimitry Andric         GenerateCustomAppertainsTo(*Subject, OS);
46675ffd83dbSDimitry Andric   }
46680b57cec5SDimitry Andric 
4669fe6060f1SDimitry Andric   // This stream is used to collect all of the declaration attribute merging
4670fe6060f1SDimitry Andric   // logic for performing mutual exclusion checks. This gets emitted at the
4671fe6060f1SDimitry Andric   // end of the file in a helper function of its own.
4672fe6060f1SDimitry Andric   std::string DeclMergeChecks, StmtMergeChecks;
4673fe6060f1SDimitry Andric   raw_string_ostream MergeDeclOS(DeclMergeChecks), MergeStmtOS(StmtMergeChecks);
4674fe6060f1SDimitry Andric 
46755ffd83dbSDimitry Andric   // Generate a ParsedAttrInfo struct for each of the attributes.
46760b57cec5SDimitry Andric   for (auto I = Attrs.begin(), E = Attrs.end(); I != E; ++I) {
46770b57cec5SDimitry Andric     // TODO: If the attribute's kind appears in the list of duplicates, that is
46780b57cec5SDimitry Andric     // because it is a target-specific attribute that appears multiple times.
46790b57cec5SDimitry Andric     // It would be beneficial to test whether the duplicates are "similar
46800b57cec5SDimitry Andric     // enough" to each other to not cause problems. For instance, check that
46810b57cec5SDimitry Andric     // the spellings are identical, and custom parsing rules match, etc.
46820b57cec5SDimitry Andric 
46830b57cec5SDimitry Andric     // We need to generate struct instances based off ParsedAttrInfo from
46840b57cec5SDimitry Andric     // ParsedAttr.cpp.
46855ffd83dbSDimitry Andric     const std::string &AttrName = I->first;
46865ffd83dbSDimitry Andric     const Record &Attr = *I->second;
46875ffd83dbSDimitry Andric     auto Spellings = GetFlattenedSpellings(Attr);
46885ffd83dbSDimitry Andric     if (!Spellings.empty()) {
46895ffd83dbSDimitry Andric       OS << "static constexpr ParsedAttrInfo::Spelling " << I->first
46905ffd83dbSDimitry Andric          << "Spellings[] = {\n";
46915ffd83dbSDimitry Andric       for (const auto &S : Spellings) {
46925ffd83dbSDimitry Andric         const std::string &RawSpelling = S.name();
46935ffd83dbSDimitry Andric         std::string Spelling;
46945ffd83dbSDimitry Andric         if (!S.nameSpace().empty())
46955ffd83dbSDimitry Andric           Spelling += S.nameSpace() + "::";
46965ffd83dbSDimitry Andric         if (S.variety() == "GNU")
46975ffd83dbSDimitry Andric           Spelling += NormalizeGNUAttrSpelling(RawSpelling);
46985ffd83dbSDimitry Andric         else
46995ffd83dbSDimitry Andric           Spelling += RawSpelling;
47005ffd83dbSDimitry Andric         OS << "  {AttributeCommonInfo::AS_" << S.variety();
47015ffd83dbSDimitry Andric         OS << ", \"" << Spelling << "\"},\n";
47025ffd83dbSDimitry Andric       }
47035ffd83dbSDimitry Andric       OS << "};\n";
47045ffd83dbSDimitry Andric     }
4705349cc55cSDimitry Andric 
4706349cc55cSDimitry Andric     std::vector<std::string> ArgNames;
4707349cc55cSDimitry Andric     for (const auto &Arg : Attr.getValueAsListOfDefs("Args")) {
4708349cc55cSDimitry Andric       bool UnusedUnset;
4709349cc55cSDimitry Andric       if (Arg->getValueAsBitOrUnset("Fake", UnusedUnset))
4710349cc55cSDimitry Andric         continue;
4711349cc55cSDimitry Andric       ArgNames.push_back(Arg->getValueAsString("Name").str());
4712349cc55cSDimitry Andric       for (const auto &Class : Arg->getSuperClasses()) {
47135f757f3fSDimitry Andric         if (Class.first->getName().starts_with("Variadic")) {
4714349cc55cSDimitry Andric           ArgNames.back().append("...");
4715349cc55cSDimitry Andric           break;
4716349cc55cSDimitry Andric         }
4717349cc55cSDimitry Andric       }
4718349cc55cSDimitry Andric     }
4719349cc55cSDimitry Andric     if (!ArgNames.empty()) {
4720349cc55cSDimitry Andric       OS << "static constexpr const char *" << I->first << "ArgNames[] = {\n";
4721349cc55cSDimitry Andric       for (const auto &N : ArgNames)
4722349cc55cSDimitry Andric         OS << '"' << N << "\",";
4723349cc55cSDimitry Andric       OS << "};\n";
4724349cc55cSDimitry Andric     }
4725349cc55cSDimitry Andric 
47265ffd83dbSDimitry Andric     OS << "struct ParsedAttrInfo" << I->first
47275ffd83dbSDimitry Andric        << " final : public ParsedAttrInfo {\n";
472881ad6265SDimitry Andric     OS << "  constexpr ParsedAttrInfo" << I->first << "() : ParsedAttrInfo(\n";
472981ad6265SDimitry Andric     OS << "    /*AttrKind=*/ParsedAttr::AT_" << AttrName << ",\n";
47305ffd83dbSDimitry Andric     emitArgInfo(Attr, OS);
473181ad6265SDimitry Andric     OS << "    /*HasCustomParsing=*/";
473281ad6265SDimitry Andric     OS << Attr.getValueAsBit("HasCustomParsing") << ",\n";
473381ad6265SDimitry Andric     OS << "    /*AcceptsExprPack=*/";
473481ad6265SDimitry Andric     OS << Attr.getValueAsBit("AcceptsExprPack") << ",\n";
473581ad6265SDimitry Andric     OS << "    /*IsTargetSpecific=*/";
473681ad6265SDimitry Andric     OS << Attr.isSubClassOf("TargetSpecificAttr") << ",\n";
473781ad6265SDimitry Andric     OS << "    /*IsType=*/";
473881ad6265SDimitry Andric     OS << (Attr.isSubClassOf("TypeAttr") || Attr.isSubClassOf("DeclOrTypeAttr"))
473981ad6265SDimitry Andric        << ",\n";
474081ad6265SDimitry Andric     OS << "    /*IsStmt=*/";
4741e8d8bef9SDimitry Andric     OS << (Attr.isSubClassOf("StmtAttr") || Attr.isSubClassOf("DeclOrStmtAttr"))
474281ad6265SDimitry Andric        << ",\n";
474381ad6265SDimitry Andric     OS << "    /*IsKnownToGCC=*/";
474481ad6265SDimitry Andric     OS << IsKnownToGCC(Attr) << ",\n";
474581ad6265SDimitry Andric     OS << "    /*IsSupportedByPragmaAttribute=*/";
474681ad6265SDimitry Andric     OS << PragmaAttributeSupport.isAttributedSupported(*I->second) << ",\n";
47475ffd83dbSDimitry Andric     if (!Spellings.empty())
474881ad6265SDimitry Andric       OS << "    /*Spellings=*/" << I->first << "Spellings,\n";
474981ad6265SDimitry Andric     else
475081ad6265SDimitry Andric       OS << "    /*Spellings=*/{},\n";
4751349cc55cSDimitry Andric     if (!ArgNames.empty())
475281ad6265SDimitry Andric       OS << "    /*ArgNames=*/" << I->first << "ArgNames";
475381ad6265SDimitry Andric     else
475481ad6265SDimitry Andric       OS << "    /*ArgNames=*/{}";
475581ad6265SDimitry Andric     OS << ") {}\n";
47565ffd83dbSDimitry Andric     GenerateAppertainsTo(Attr, OS);
4757fe6060f1SDimitry Andric     GenerateMutualExclusionsChecks(Attr, Records, OS, MergeDeclOS, MergeStmtOS);
47585ffd83dbSDimitry Andric     GenerateLangOptRequirements(Attr, OS);
47595ffd83dbSDimitry Andric     GenerateTargetRequirements(Attr, Dupes, OS);
47605f757f3fSDimitry Andric     GenerateSpellingTargetRequirements(
47615f757f3fSDimitry Andric         Attr, Attr.getValueAsListOfDefs("TargetSpecificSpellings"), OS);
47625ffd83dbSDimitry Andric     GenerateSpellingIndexToSemanticSpelling(Attr, OS);
47635ffd83dbSDimitry Andric     PragmaAttributeSupport.generateStrictConformsTo(*I->second, OS);
47645ffd83dbSDimitry Andric     GenerateHandleDeclAttribute(Attr, OS);
476581ad6265SDimitry Andric     GenerateIsParamExpr(Attr, OS);
47665ffd83dbSDimitry Andric     OS << "static const ParsedAttrInfo" << I->first << " Instance;\n";
47675ffd83dbSDimitry Andric     OS << "};\n";
47685ffd83dbSDimitry Andric     OS << "const ParsedAttrInfo" << I->first << " ParsedAttrInfo" << I->first
47695ffd83dbSDimitry Andric        << "::Instance;\n";
47700b57cec5SDimitry Andric   }
47710b57cec5SDimitry Andric 
47725ffd83dbSDimitry Andric   OS << "static const ParsedAttrInfo *AttrInfoMap[] = {\n";
47735ffd83dbSDimitry Andric   for (auto I = Attrs.begin(), E = Attrs.end(); I != E; ++I) {
47745ffd83dbSDimitry Andric     OS << "&ParsedAttrInfo" << I->first << "::Instance,\n";
47755ffd83dbSDimitry Andric   }
47760b57cec5SDimitry Andric   OS << "};\n\n";
47770b57cec5SDimitry Andric 
477881ad6265SDimitry Andric   // Generate function for handling attributes with delayed arguments
477981ad6265SDimitry Andric   GenerateHandleAttrWithDelayedArgs(Records, OS);
478081ad6265SDimitry Andric 
47810b57cec5SDimitry Andric   // Generate the attribute match rules.
47820b57cec5SDimitry Andric   emitAttributeMatchRules(PragmaAttributeSupport, OS);
4783fe6060f1SDimitry Andric 
4784fe6060f1SDimitry Andric   OS << "#elif defined(WANT_DECL_MERGE_LOGIC)\n\n";
4785fe6060f1SDimitry Andric 
4786fe6060f1SDimitry Andric   // Write out the declaration merging check logic.
4787fe6060f1SDimitry Andric   OS << "static bool DiagnoseMutualExclusions(Sema &S, const NamedDecl *D, "
4788fe6060f1SDimitry Andric      << "const Attr *A) {\n";
4789*0fca6ea1SDimitry Andric   OS << DeclMergeChecks;
4790fe6060f1SDimitry Andric   OS << "  return true;\n";
4791fe6060f1SDimitry Andric   OS << "}\n\n";
4792fe6060f1SDimitry Andric 
4793fe6060f1SDimitry Andric   OS << "#elif defined(WANT_STMT_MERGE_LOGIC)\n\n";
4794fe6060f1SDimitry Andric 
4795fe6060f1SDimitry Andric   // Write out the statement merging check logic.
4796fe6060f1SDimitry Andric   OS << "static bool DiagnoseMutualExclusions(Sema &S, "
4797fe6060f1SDimitry Andric      << "const SmallVectorImpl<const Attr *> &C) {\n";
4798fe6060f1SDimitry Andric   OS << "  for (const Attr *A : C) {\n";
4799*0fca6ea1SDimitry Andric   OS << StmtMergeChecks;
4800fe6060f1SDimitry Andric   OS << "  }\n";
4801fe6060f1SDimitry Andric   OS << "  return true;\n";
4802fe6060f1SDimitry Andric   OS << "}\n\n";
4803fe6060f1SDimitry Andric 
4804fe6060f1SDimitry Andric   OS << "#endif\n";
48050b57cec5SDimitry Andric }
48060b57cec5SDimitry Andric 
48070b57cec5SDimitry Andric // Emits the kind list of parsed attributes
48080b57cec5SDimitry Andric void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
48095f757f3fSDimitry Andric   emitSourceFileHeader("Attribute name matcher", OS, Records);
48100b57cec5SDimitry Andric 
48110b57cec5SDimitry Andric   std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
48120b57cec5SDimitry Andric   std::vector<StringMatcher::StringPair> GNU, Declspec, Microsoft, CXX11,
4813*0fca6ea1SDimitry Andric       Keywords, Pragma, C23, HLSLAnnotation;
48140b57cec5SDimitry Andric   std::set<std::string> Seen;
48150b57cec5SDimitry Andric   for (const auto *A : Attrs) {
48160b57cec5SDimitry Andric     const Record &Attr = *A;
48170b57cec5SDimitry Andric 
48180b57cec5SDimitry Andric     bool SemaHandler = Attr.getValueAsBit("SemaHandler");
48190b57cec5SDimitry Andric     bool Ignored = Attr.getValueAsBit("Ignored");
48200b57cec5SDimitry Andric     if (SemaHandler || Ignored) {
48210b57cec5SDimitry Andric       // Attribute spellings can be shared between target-specific attributes,
48220b57cec5SDimitry Andric       // and can be shared between syntaxes for the same attribute. For
48230b57cec5SDimitry Andric       // instance, an attribute can be spelled GNU<"interrupt"> for an ARM-
48240b57cec5SDimitry Andric       // specific attribute, or MSP430-specific attribute. Additionally, an
48250b57cec5SDimitry Andric       // attribute can be spelled GNU<"dllexport"> and Declspec<"dllexport">
48260b57cec5SDimitry Andric       // for the same semantic attribute. Ultimately, we need to map each of
4827a7dea167SDimitry Andric       // these to a single AttributeCommonInfo::Kind value, but the
4828a7dea167SDimitry Andric       // StringMatcher class cannot handle duplicate match strings. So we
4829a7dea167SDimitry Andric       // generate a list of string to match based on the syntax, and emit
4830a7dea167SDimitry Andric       // multiple string matchers depending on the syntax used.
48310b57cec5SDimitry Andric       std::string AttrName;
48320b57cec5SDimitry Andric       if (Attr.isSubClassOf("TargetSpecificAttr") &&
48330b57cec5SDimitry Andric           !Attr.isValueUnset("ParseKind")) {
48345ffd83dbSDimitry Andric         AttrName = std::string(Attr.getValueAsString("ParseKind"));
483581ad6265SDimitry Andric         if (!Seen.insert(AttrName).second)
48360b57cec5SDimitry Andric           continue;
48370b57cec5SDimitry Andric       } else
48380b57cec5SDimitry Andric         AttrName = NormalizeAttrName(StringRef(Attr.getName())).str();
48390b57cec5SDimitry Andric 
48400b57cec5SDimitry Andric       std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
48410b57cec5SDimitry Andric       for (const auto &S : Spellings) {
48420b57cec5SDimitry Andric         const std::string &RawSpelling = S.name();
48430b57cec5SDimitry Andric         std::vector<StringMatcher::StringPair> *Matches = nullptr;
48440b57cec5SDimitry Andric         std::string Spelling;
48450b57cec5SDimitry Andric         const std::string &Variety = S.variety();
48460b57cec5SDimitry Andric         if (Variety == "CXX11") {
48470b57cec5SDimitry Andric           Matches = &CXX11;
48485ffd83dbSDimitry Andric           if (!S.nameSpace().empty())
48495ffd83dbSDimitry Andric             Spelling += S.nameSpace() + "::";
48505f757f3fSDimitry Andric         } else if (Variety == "C23") {
48515f757f3fSDimitry Andric           Matches = &C23;
48525ffd83dbSDimitry Andric           if (!S.nameSpace().empty())
48535ffd83dbSDimitry Andric             Spelling += S.nameSpace() + "::";
48540b57cec5SDimitry Andric         } else if (Variety == "GNU")
48550b57cec5SDimitry Andric           Matches = &GNU;
48560b57cec5SDimitry Andric         else if (Variety == "Declspec")
48570b57cec5SDimitry Andric           Matches = &Declspec;
48580b57cec5SDimitry Andric         else if (Variety == "Microsoft")
48590b57cec5SDimitry Andric           Matches = &Microsoft;
48600b57cec5SDimitry Andric         else if (Variety == "Keyword")
48610b57cec5SDimitry Andric           Matches = &Keywords;
48620b57cec5SDimitry Andric         else if (Variety == "Pragma")
48630b57cec5SDimitry Andric           Matches = &Pragma;
4864*0fca6ea1SDimitry Andric         else if (Variety == "HLSLAnnotation")
4865*0fca6ea1SDimitry Andric           Matches = &HLSLAnnotation;
48660b57cec5SDimitry Andric 
48670b57cec5SDimitry Andric         assert(Matches && "Unsupported spelling variety found");
48680b57cec5SDimitry Andric 
48690b57cec5SDimitry Andric         if (Variety == "GNU")
48700b57cec5SDimitry Andric           Spelling += NormalizeGNUAttrSpelling(RawSpelling);
48710b57cec5SDimitry Andric         else
48720b57cec5SDimitry Andric           Spelling += RawSpelling;
48730b57cec5SDimitry Andric 
48740b57cec5SDimitry Andric         if (SemaHandler)
48750b57cec5SDimitry Andric           Matches->push_back(StringMatcher::StringPair(
4876a7dea167SDimitry Andric               Spelling, "return AttributeCommonInfo::AT_" + AttrName + ";"));
48770b57cec5SDimitry Andric         else
48780b57cec5SDimitry Andric           Matches->push_back(StringMatcher::StringPair(
4879a7dea167SDimitry Andric               Spelling, "return AttributeCommonInfo::IgnoredAttribute;"));
48800b57cec5SDimitry Andric       }
48810b57cec5SDimitry Andric     }
48820b57cec5SDimitry Andric   }
48830b57cec5SDimitry Andric 
4884a7dea167SDimitry Andric   OS << "static AttributeCommonInfo::Kind getAttrKind(StringRef Name, ";
4885a7dea167SDimitry Andric   OS << "AttributeCommonInfo::Syntax Syntax) {\n";
4886a7dea167SDimitry Andric   OS << "  if (AttributeCommonInfo::AS_GNU == Syntax) {\n";
48870b57cec5SDimitry Andric   StringMatcher("Name", GNU, OS).Emit();
4888a7dea167SDimitry Andric   OS << "  } else if (AttributeCommonInfo::AS_Declspec == Syntax) {\n";
48890b57cec5SDimitry Andric   StringMatcher("Name", Declspec, OS).Emit();
4890a7dea167SDimitry Andric   OS << "  } else if (AttributeCommonInfo::AS_Microsoft == Syntax) {\n";
48910b57cec5SDimitry Andric   StringMatcher("Name", Microsoft, OS).Emit();
4892a7dea167SDimitry Andric   OS << "  } else if (AttributeCommonInfo::AS_CXX11 == Syntax) {\n";
48930b57cec5SDimitry Andric   StringMatcher("Name", CXX11, OS).Emit();
48945f757f3fSDimitry Andric   OS << "  } else if (AttributeCommonInfo::AS_C23 == Syntax) {\n";
48955f757f3fSDimitry Andric   StringMatcher("Name", C23, OS).Emit();
4896a7dea167SDimitry Andric   OS << "  } else if (AttributeCommonInfo::AS_Keyword == Syntax || ";
4897a7dea167SDimitry Andric   OS << "AttributeCommonInfo::AS_ContextSensitiveKeyword == Syntax) {\n";
48980b57cec5SDimitry Andric   StringMatcher("Name", Keywords, OS).Emit();
4899a7dea167SDimitry Andric   OS << "  } else if (AttributeCommonInfo::AS_Pragma == Syntax) {\n";
49000b57cec5SDimitry Andric   StringMatcher("Name", Pragma, OS).Emit();
4901*0fca6ea1SDimitry Andric   OS << "  } else if (AttributeCommonInfo::AS_HLSLAnnotation == Syntax) {\n";
4902*0fca6ea1SDimitry Andric   StringMatcher("Name", HLSLAnnotation, OS).Emit();
49030b57cec5SDimitry Andric   OS << "  }\n";
4904a7dea167SDimitry Andric   OS << "  return AttributeCommonInfo::UnknownAttribute;\n"
49050b57cec5SDimitry Andric      << "}\n";
49060b57cec5SDimitry Andric }
49070b57cec5SDimitry Andric 
49080b57cec5SDimitry Andric // Emits the code to dump an attribute.
49090b57cec5SDimitry Andric void EmitClangAttrTextNodeDump(RecordKeeper &Records, raw_ostream &OS) {
49105f757f3fSDimitry Andric   emitSourceFileHeader("Attribute text node dumper", OS, Records);
49110b57cec5SDimitry Andric 
49120b57cec5SDimitry Andric   std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
49130b57cec5SDimitry Andric   for (const auto *Attr : Attrs) {
49140b57cec5SDimitry Andric     const Record &R = *Attr;
49150b57cec5SDimitry Andric     if (!R.getValueAsBit("ASTNode"))
49160b57cec5SDimitry Andric       continue;
49170b57cec5SDimitry Andric 
49180b57cec5SDimitry Andric     // If the attribute has a semantically-meaningful name (which is determined
49190b57cec5SDimitry Andric     // by whether there is a Spelling enumeration for it), then write out the
49200b57cec5SDimitry Andric     // spelling used for the attribute.
49210b57cec5SDimitry Andric 
49220b57cec5SDimitry Andric     std::string FunctionContent;
49230b57cec5SDimitry Andric     llvm::raw_string_ostream SS(FunctionContent);
49240b57cec5SDimitry Andric 
49250b57cec5SDimitry Andric     std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
49260b57cec5SDimitry Andric     if (Spellings.size() > 1 && !SpellingNamesAreCommon(Spellings))
49270b57cec5SDimitry Andric       SS << "    OS << \" \" << A->getSpelling();\n";
49280b57cec5SDimitry Andric 
49290b57cec5SDimitry Andric     Args = R.getValueAsListOfDefs("Args");
49300b57cec5SDimitry Andric     for (const auto *Arg : Args)
49310b57cec5SDimitry Andric       createArgument(*Arg, R.getName())->writeDump(SS);
49320b57cec5SDimitry Andric 
493381ad6265SDimitry Andric     if (Attr->getValueAsBit("AcceptsExprPack"))
493481ad6265SDimitry Andric       VariadicExprArgument("DelayedArgs", R.getName()).writeDump(OS);
493581ad6265SDimitry Andric 
49360b57cec5SDimitry Andric     if (SS.tell()) {
49370b57cec5SDimitry Andric       OS << "  void Visit" << R.getName() << "Attr(const " << R.getName()
49380b57cec5SDimitry Andric          << "Attr *A) {\n";
49390b57cec5SDimitry Andric       if (!Args.empty())
49400b57cec5SDimitry Andric         OS << "    const auto *SA = cast<" << R.getName()
49410b57cec5SDimitry Andric            << "Attr>(A); (void)SA;\n";
4942*0fca6ea1SDimitry Andric       OS << FunctionContent;
49430b57cec5SDimitry Andric       OS << "  }\n";
49440b57cec5SDimitry Andric     }
49450b57cec5SDimitry Andric   }
49460b57cec5SDimitry Andric }
49470b57cec5SDimitry Andric 
49480b57cec5SDimitry Andric void EmitClangAttrNodeTraverse(RecordKeeper &Records, raw_ostream &OS) {
49495f757f3fSDimitry Andric   emitSourceFileHeader("Attribute text node traverser", OS, Records);
49500b57cec5SDimitry Andric 
49510b57cec5SDimitry Andric   std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
49520b57cec5SDimitry Andric   for (const auto *Attr : Attrs) {
49530b57cec5SDimitry Andric     const Record &R = *Attr;
49540b57cec5SDimitry Andric     if (!R.getValueAsBit("ASTNode"))
49550b57cec5SDimitry Andric       continue;
49560b57cec5SDimitry Andric 
49570b57cec5SDimitry Andric     std::string FunctionContent;
49580b57cec5SDimitry Andric     llvm::raw_string_ostream SS(FunctionContent);
49590b57cec5SDimitry Andric 
49600b57cec5SDimitry Andric     Args = R.getValueAsListOfDefs("Args");
49610b57cec5SDimitry Andric     for (const auto *Arg : Args)
49620b57cec5SDimitry Andric       createArgument(*Arg, R.getName())->writeDumpChildren(SS);
496381ad6265SDimitry Andric     if (Attr->getValueAsBit("AcceptsExprPack"))
496481ad6265SDimitry Andric       VariadicExprArgument("DelayedArgs", R.getName()).writeDumpChildren(SS);
49650b57cec5SDimitry Andric     if (SS.tell()) {
49660b57cec5SDimitry Andric       OS << "  void Visit" << R.getName() << "Attr(const " << R.getName()
49670b57cec5SDimitry Andric          << "Attr *A) {\n";
49680b57cec5SDimitry Andric       if (!Args.empty())
49690b57cec5SDimitry Andric         OS << "    const auto *SA = cast<" << R.getName()
49700b57cec5SDimitry Andric            << "Attr>(A); (void)SA;\n";
4971*0fca6ea1SDimitry Andric       OS << FunctionContent;
49720b57cec5SDimitry Andric       OS << "  }\n";
49730b57cec5SDimitry Andric     }
49740b57cec5SDimitry Andric   }
49750b57cec5SDimitry Andric }
49760b57cec5SDimitry Andric 
49775f757f3fSDimitry Andric void EmitClangAttrParserStringSwitches(RecordKeeper &Records, raw_ostream &OS) {
49785f757f3fSDimitry Andric   emitSourceFileHeader("Parser-related llvm::StringSwitch cases", OS, Records);
49790b57cec5SDimitry Andric   emitClangAttrArgContextList(Records, OS);
49800b57cec5SDimitry Andric   emitClangAttrIdentifierArgList(Records, OS);
49815f757f3fSDimitry Andric   emitClangAttrUnevaluatedStringLiteralList(Records, OS);
49820b57cec5SDimitry Andric   emitClangAttrVariadicIdentifierArgList(Records, OS);
49830b57cec5SDimitry Andric   emitClangAttrThisIsaIdentifierArgList(Records, OS);
498481ad6265SDimitry Andric   emitClangAttrAcceptsExprPack(Records, OS);
49850b57cec5SDimitry Andric   emitClangAttrTypeArgList(Records, OS);
49860b57cec5SDimitry Andric   emitClangAttrLateParsedList(Records, OS);
4987*0fca6ea1SDimitry Andric   emitClangAttrLateParsedExperimentalList(Records, OS);
4988*0fca6ea1SDimitry Andric   emitClangAttrStrictIdentifierArgAtIndexList(Records, OS);
49890b57cec5SDimitry Andric }
49900b57cec5SDimitry Andric 
49910b57cec5SDimitry Andric void EmitClangAttrSubjectMatchRulesParserStringSwitches(RecordKeeper &Records,
49920b57cec5SDimitry Andric                                                         raw_ostream &OS) {
49930b57cec5SDimitry Andric   getPragmaAttributeSupport(Records).generateParsingHelpers(OS);
49940b57cec5SDimitry Andric }
49950b57cec5SDimitry Andric 
4996349cc55cSDimitry Andric void EmitClangAttrDocTable(RecordKeeper &Records, raw_ostream &OS) {
49975f757f3fSDimitry Andric   emitSourceFileHeader("Clang attribute documentation", OS, Records);
4998349cc55cSDimitry Andric 
4999349cc55cSDimitry Andric   std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
5000349cc55cSDimitry Andric   for (const auto *A : Attrs) {
5001349cc55cSDimitry Andric     if (!A->getValueAsBit("ASTNode"))
5002349cc55cSDimitry Andric       continue;
5003349cc55cSDimitry Andric     std::vector<Record *> Docs = A->getValueAsListOfDefs("Documentation");
5004349cc55cSDimitry Andric     assert(!Docs.empty());
5005349cc55cSDimitry Andric     // Only look at the first documentation if there are several.
5006349cc55cSDimitry Andric     // (Currently there's only one such attr, revisit if this becomes common).
5007349cc55cSDimitry Andric     StringRef Text =
500881ad6265SDimitry Andric         Docs.front()->getValueAsOptionalString("Content").value_or("");
5009349cc55cSDimitry Andric     OS << "\nstatic const char AttrDoc_" << A->getName() << "[] = "
5010349cc55cSDimitry Andric        << "R\"reST(" << Text.trim() << ")reST\";\n";
5011349cc55cSDimitry Andric   }
5012349cc55cSDimitry Andric }
5013349cc55cSDimitry Andric 
501481ad6265SDimitry Andric enum class SpellingKind : size_t {
50150b57cec5SDimitry Andric   GNU,
50160b57cec5SDimitry Andric   CXX11,
50175f757f3fSDimitry Andric   C23,
50180b57cec5SDimitry Andric   Declspec,
50190b57cec5SDimitry Andric   Microsoft,
50200b57cec5SDimitry Andric   Keyword,
50210b57cec5SDimitry Andric   Pragma,
5022*0fca6ea1SDimitry Andric   HLSLAnnotation,
502381ad6265SDimitry Andric   NumSpellingKinds
50240b57cec5SDimitry Andric };
502581ad6265SDimitry Andric static const size_t NumSpellingKinds = (size_t)SpellingKind::NumSpellingKinds;
50260b57cec5SDimitry Andric 
50270b57cec5SDimitry Andric class SpellingList {
50280b57cec5SDimitry Andric   std::vector<std::string> Spellings[NumSpellingKinds];
50290b57cec5SDimitry Andric 
50300b57cec5SDimitry Andric public:
50310b57cec5SDimitry Andric   ArrayRef<std::string> operator[](SpellingKind K) const {
50320b57cec5SDimitry Andric     return Spellings[(size_t)K];
50330b57cec5SDimitry Andric   }
50340b57cec5SDimitry Andric 
50350b57cec5SDimitry Andric   void add(const Record &Attr, FlattenedSpelling Spelling) {
5036*0fca6ea1SDimitry Andric     SpellingKind Kind =
5037*0fca6ea1SDimitry Andric         StringSwitch<SpellingKind>(Spelling.variety())
50380b57cec5SDimitry Andric             .Case("GNU", SpellingKind::GNU)
50390b57cec5SDimitry Andric             .Case("CXX11", SpellingKind::CXX11)
50405f757f3fSDimitry Andric             .Case("C23", SpellingKind::C23)
50410b57cec5SDimitry Andric             .Case("Declspec", SpellingKind::Declspec)
50420b57cec5SDimitry Andric             .Case("Microsoft", SpellingKind::Microsoft)
50430b57cec5SDimitry Andric             .Case("Keyword", SpellingKind::Keyword)
504481ad6265SDimitry Andric             .Case("Pragma", SpellingKind::Pragma)
5045*0fca6ea1SDimitry Andric             .Case("HLSLAnnotation", SpellingKind::HLSLAnnotation);
50460b57cec5SDimitry Andric     std::string Name;
50470b57cec5SDimitry Andric     if (!Spelling.nameSpace().empty()) {
50480b57cec5SDimitry Andric       switch (Kind) {
50490b57cec5SDimitry Andric       case SpellingKind::CXX11:
50505f757f3fSDimitry Andric       case SpellingKind::C23:
50510b57cec5SDimitry Andric         Name = Spelling.nameSpace() + "::";
50520b57cec5SDimitry Andric         break;
50530b57cec5SDimitry Andric       case SpellingKind::Pragma:
50540b57cec5SDimitry Andric         Name = Spelling.nameSpace() + " ";
50550b57cec5SDimitry Andric         break;
50560b57cec5SDimitry Andric       default:
50570b57cec5SDimitry Andric         PrintFatalError(Attr.getLoc(), "Unexpected namespace in spelling");
50580b57cec5SDimitry Andric       }
50590b57cec5SDimitry Andric     }
50600b57cec5SDimitry Andric     Name += Spelling.name();
50610b57cec5SDimitry Andric 
50620b57cec5SDimitry Andric     Spellings[(size_t)Kind].push_back(Name);
50630b57cec5SDimitry Andric   }
50640b57cec5SDimitry Andric };
50650b57cec5SDimitry Andric 
50660b57cec5SDimitry Andric class DocumentationData {
50670b57cec5SDimitry Andric public:
50680b57cec5SDimitry Andric   const Record *Documentation;
50690b57cec5SDimitry Andric   const Record *Attribute;
50700b57cec5SDimitry Andric   std::string Heading;
50710b57cec5SDimitry Andric   SpellingList SupportedSpellings;
50720b57cec5SDimitry Andric 
50730b57cec5SDimitry Andric   DocumentationData(const Record &Documentation, const Record &Attribute,
50740b57cec5SDimitry Andric                     std::pair<std::string, SpellingList> HeadingAndSpellings)
50750b57cec5SDimitry Andric       : Documentation(&Documentation), Attribute(&Attribute),
50760b57cec5SDimitry Andric         Heading(std::move(HeadingAndSpellings.first)),
50770b57cec5SDimitry Andric         SupportedSpellings(std::move(HeadingAndSpellings.second)) {}
50780b57cec5SDimitry Andric };
50790b57cec5SDimitry Andric 
50800b57cec5SDimitry Andric static void WriteCategoryHeader(const Record *DocCategory,
50810b57cec5SDimitry Andric                                 raw_ostream &OS) {
50820b57cec5SDimitry Andric   const StringRef Name = DocCategory->getValueAsString("Name");
50830b57cec5SDimitry Andric   OS << Name << "\n" << std::string(Name.size(), '=') << "\n";
50840b57cec5SDimitry Andric 
50850b57cec5SDimitry Andric   // If there is content, print that as well.
50860b57cec5SDimitry Andric   const StringRef ContentStr = DocCategory->getValueAsString("Content");
50870b57cec5SDimitry Andric   // Trim leading and trailing newlines and spaces.
50880b57cec5SDimitry Andric   OS << ContentStr.trim();
50890b57cec5SDimitry Andric 
50900b57cec5SDimitry Andric   OS << "\n\n";
50910b57cec5SDimitry Andric }
50920b57cec5SDimitry Andric 
50930b57cec5SDimitry Andric static std::pair<std::string, SpellingList>
50940b57cec5SDimitry Andric GetAttributeHeadingAndSpellings(const Record &Documentation,
509581ad6265SDimitry Andric                                 const Record &Attribute,
509681ad6265SDimitry Andric                                 StringRef Cat) {
50970b57cec5SDimitry Andric   // FIXME: there is no way to have a per-spelling category for the attribute
50980b57cec5SDimitry Andric   // documentation. This may not be a limiting factor since the spellings
50990b57cec5SDimitry Andric   // should generally be consistently applied across the category.
51000b57cec5SDimitry Andric 
51010b57cec5SDimitry Andric   std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attribute);
51020b57cec5SDimitry Andric   if (Spellings.empty())
51030b57cec5SDimitry Andric     PrintFatalError(Attribute.getLoc(),
51040b57cec5SDimitry Andric                     "Attribute has no supported spellings; cannot be "
51050b57cec5SDimitry Andric                     "documented");
51060b57cec5SDimitry Andric 
51070b57cec5SDimitry Andric   // Determine the heading to be used for this attribute.
51085ffd83dbSDimitry Andric   std::string Heading = std::string(Documentation.getValueAsString("Heading"));
51090b57cec5SDimitry Andric   if (Heading.empty()) {
51100b57cec5SDimitry Andric     // If there's only one spelling, we can simply use that.
51110b57cec5SDimitry Andric     if (Spellings.size() == 1)
51120b57cec5SDimitry Andric       Heading = Spellings.begin()->name();
51130b57cec5SDimitry Andric     else {
51140b57cec5SDimitry Andric       std::set<std::string> Uniques;
51150b57cec5SDimitry Andric       for (auto I = Spellings.begin(), E = Spellings.end();
511681ad6265SDimitry Andric            I != E; ++I) {
51175ffd83dbSDimitry Andric         std::string Spelling =
51185ffd83dbSDimitry Andric             std::string(NormalizeNameForSpellingComparison(I->name()));
51190b57cec5SDimitry Andric         Uniques.insert(Spelling);
51200b57cec5SDimitry Andric       }
51210b57cec5SDimitry Andric       // If the semantic map has only one spelling, that is sufficient for our
51220b57cec5SDimitry Andric       // needs.
51230b57cec5SDimitry Andric       if (Uniques.size() == 1)
51240b57cec5SDimitry Andric         Heading = *Uniques.begin();
512581ad6265SDimitry Andric       // If it's in the undocumented category, just construct a header by
512681ad6265SDimitry Andric       // concatenating all the spellings. Might not be great, but better than
512781ad6265SDimitry Andric       // nothing.
512881ad6265SDimitry Andric       else if (Cat == "Undocumented")
512981ad6265SDimitry Andric         Heading = llvm::join(Uniques.begin(), Uniques.end(), ", ");
51300b57cec5SDimitry Andric     }
51310b57cec5SDimitry Andric   }
51320b57cec5SDimitry Andric 
51330b57cec5SDimitry Andric   // If the heading is still empty, it is an error.
51340b57cec5SDimitry Andric   if (Heading.empty())
51350b57cec5SDimitry Andric     PrintFatalError(Attribute.getLoc(),
51360b57cec5SDimitry Andric                     "This attribute requires a heading to be specified");
51370b57cec5SDimitry Andric 
51380b57cec5SDimitry Andric   SpellingList SupportedSpellings;
51390b57cec5SDimitry Andric   for (const auto &I : Spellings)
51400b57cec5SDimitry Andric     SupportedSpellings.add(Attribute, I);
51410b57cec5SDimitry Andric 
51420b57cec5SDimitry Andric   return std::make_pair(std::move(Heading), std::move(SupportedSpellings));
51430b57cec5SDimitry Andric }
51440b57cec5SDimitry Andric 
51450b57cec5SDimitry Andric static void WriteDocumentation(RecordKeeper &Records,
51460b57cec5SDimitry Andric                                const DocumentationData &Doc, raw_ostream &OS) {
51470b57cec5SDimitry Andric   OS << Doc.Heading << "\n" << std::string(Doc.Heading.length(), '-') << "\n";
51480b57cec5SDimitry Andric 
51490b57cec5SDimitry Andric   // List what spelling syntaxes the attribute supports.
5150bdd1243dSDimitry Andric   // Note: "#pragma clang attribute" is handled outside the spelling kinds loop
5151bdd1243dSDimitry Andric   // so it must be last.
51520b57cec5SDimitry Andric   OS << ".. csv-table:: Supported Syntaxes\n";
51535f757f3fSDimitry Andric   OS << "   :header: \"GNU\", \"C++11\", \"C23\", \"``__declspec``\",";
5154*0fca6ea1SDimitry Andric   OS << " \"Keyword\", \"``#pragma``\", \"HLSL Annotation\", \"``#pragma "
5155*0fca6ea1SDimitry Andric         "clang ";
5156bdd1243dSDimitry Andric   OS << "attribute``\"\n\n   \"";
51570b57cec5SDimitry Andric   for (size_t Kind = 0; Kind != NumSpellingKinds; ++Kind) {
51580b57cec5SDimitry Andric     SpellingKind K = (SpellingKind)Kind;
51590b57cec5SDimitry Andric     // TODO: List Microsoft (IDL-style attribute) spellings once we fully
51600b57cec5SDimitry Andric     // support them.
51610b57cec5SDimitry Andric     if (K == SpellingKind::Microsoft)
51620b57cec5SDimitry Andric       continue;
51630b57cec5SDimitry Andric 
51640b57cec5SDimitry Andric     bool PrintedAny = false;
51650b57cec5SDimitry Andric     for (StringRef Spelling : Doc.SupportedSpellings[K]) {
51660b57cec5SDimitry Andric       if (PrintedAny)
51670b57cec5SDimitry Andric         OS << " |br| ";
51680b57cec5SDimitry Andric       OS << "``" << Spelling << "``";
51690b57cec5SDimitry Andric       PrintedAny = true;
51700b57cec5SDimitry Andric     }
51710b57cec5SDimitry Andric 
51720b57cec5SDimitry Andric     OS << "\",\"";
51730b57cec5SDimitry Andric   }
51740b57cec5SDimitry Andric 
51750b57cec5SDimitry Andric   if (getPragmaAttributeSupport(Records).isAttributedSupported(
51760b57cec5SDimitry Andric           *Doc.Attribute))
51770b57cec5SDimitry Andric     OS << "Yes";
51780b57cec5SDimitry Andric   OS << "\"\n\n";
51790b57cec5SDimitry Andric 
51800b57cec5SDimitry Andric   // If the attribute is deprecated, print a message about it, and possibly
51810b57cec5SDimitry Andric   // provide a replacement attribute.
51820b57cec5SDimitry Andric   if (!Doc.Documentation->isValueUnset("Deprecated")) {
51830b57cec5SDimitry Andric     OS << "This attribute has been deprecated, and may be removed in a future "
51840b57cec5SDimitry Andric        << "version of Clang.";
51850b57cec5SDimitry Andric     const Record &Deprecated = *Doc.Documentation->getValueAsDef("Deprecated");
51860b57cec5SDimitry Andric     const StringRef Replacement = Deprecated.getValueAsString("Replacement");
51870b57cec5SDimitry Andric     if (!Replacement.empty())
51880b57cec5SDimitry Andric       OS << "  This attribute has been superseded by ``" << Replacement
51890b57cec5SDimitry Andric          << "``.";
51900b57cec5SDimitry Andric     OS << "\n\n";
51910b57cec5SDimitry Andric   }
51920b57cec5SDimitry Andric 
51930b57cec5SDimitry Andric   const StringRef ContentStr = Doc.Documentation->getValueAsString("Content");
51940b57cec5SDimitry Andric   // Trim leading and trailing newlines and spaces.
51950b57cec5SDimitry Andric   OS << ContentStr.trim();
51960b57cec5SDimitry Andric 
51970b57cec5SDimitry Andric   OS << "\n\n\n";
51980b57cec5SDimitry Andric }
51990b57cec5SDimitry Andric 
52000b57cec5SDimitry Andric void EmitClangAttrDocs(RecordKeeper &Records, raw_ostream &OS) {
52010b57cec5SDimitry Andric   // Get the documentation introduction paragraph.
52020b57cec5SDimitry Andric   const Record *Documentation = Records.getDef("GlobalDocumentation");
52030b57cec5SDimitry Andric   if (!Documentation) {
52040b57cec5SDimitry Andric     PrintFatalError("The Documentation top-level definition is missing, "
52050b57cec5SDimitry Andric                     "no documentation will be generated.");
52060b57cec5SDimitry Andric     return;
52070b57cec5SDimitry Andric   }
52080b57cec5SDimitry Andric 
52090b57cec5SDimitry Andric   OS << Documentation->getValueAsString("Intro") << "\n";
52100b57cec5SDimitry Andric 
52110b57cec5SDimitry Andric   // Gather the Documentation lists from each of the attributes, based on the
52120b57cec5SDimitry Andric   // category provided.
52130b57cec5SDimitry Andric   std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
5214349cc55cSDimitry Andric   struct CategoryLess {
5215349cc55cSDimitry Andric     bool operator()(const Record *L, const Record *R) const {
5216349cc55cSDimitry Andric       return L->getValueAsString("Name") < R->getValueAsString("Name");
5217349cc55cSDimitry Andric     }
5218349cc55cSDimitry Andric   };
5219349cc55cSDimitry Andric   std::map<const Record *, std::vector<DocumentationData>, CategoryLess>
5220349cc55cSDimitry Andric       SplitDocs;
52210b57cec5SDimitry Andric   for (const auto *A : Attrs) {
52220b57cec5SDimitry Andric     const Record &Attr = *A;
52230b57cec5SDimitry Andric     std::vector<Record *> Docs = Attr.getValueAsListOfDefs("Documentation");
52240b57cec5SDimitry Andric     for (const auto *D : Docs) {
52250b57cec5SDimitry Andric       const Record &Doc = *D;
52260b57cec5SDimitry Andric       const Record *Category = Doc.getValueAsDef("Category");
522781ad6265SDimitry Andric       // If the category is "InternalOnly", then there cannot be any other
522881ad6265SDimitry Andric       // documentation categories (otherwise, the attribute would be
522981ad6265SDimitry Andric       // emitted into the docs).
52300b57cec5SDimitry Andric       const StringRef Cat = Category->getValueAsString("Name");
523181ad6265SDimitry Andric       bool InternalOnly = Cat == "InternalOnly";
523281ad6265SDimitry Andric       if (InternalOnly && Docs.size() > 1)
52330b57cec5SDimitry Andric         PrintFatalError(Doc.getLoc(),
523481ad6265SDimitry Andric                         "Attribute is \"InternalOnly\", but has multiple "
52350b57cec5SDimitry Andric                         "documentation categories");
52360b57cec5SDimitry Andric 
523781ad6265SDimitry Andric       if (!InternalOnly)
52380b57cec5SDimitry Andric         SplitDocs[Category].push_back(DocumentationData(
523981ad6265SDimitry Andric             Doc, Attr, GetAttributeHeadingAndSpellings(Doc, Attr, Cat)));
52400b57cec5SDimitry Andric     }
52410b57cec5SDimitry Andric   }
52420b57cec5SDimitry Andric 
52430b57cec5SDimitry Andric   // Having split the attributes out based on what documentation goes where,
52440b57cec5SDimitry Andric   // we can begin to generate sections of documentation.
52450b57cec5SDimitry Andric   for (auto &I : SplitDocs) {
52460b57cec5SDimitry Andric     WriteCategoryHeader(I.first, OS);
52470b57cec5SDimitry Andric 
52480b57cec5SDimitry Andric     llvm::sort(I.second,
52490b57cec5SDimitry Andric                [](const DocumentationData &D1, const DocumentationData &D2) {
52500b57cec5SDimitry Andric                  return D1.Heading < D2.Heading;
52510b57cec5SDimitry Andric                });
52520b57cec5SDimitry Andric 
52530b57cec5SDimitry Andric     // Walk over each of the attributes in the category and write out their
52540b57cec5SDimitry Andric     // documentation.
52550b57cec5SDimitry Andric     for (const auto &Doc : I.second)
52560b57cec5SDimitry Andric       WriteDocumentation(Records, Doc, OS);
52570b57cec5SDimitry Andric   }
52580b57cec5SDimitry Andric }
52590b57cec5SDimitry Andric 
52600b57cec5SDimitry Andric void EmitTestPragmaAttributeSupportedAttributes(RecordKeeper &Records,
52610b57cec5SDimitry Andric                                                 raw_ostream &OS) {
52620b57cec5SDimitry Andric   PragmaClangAttributeSupport Support = getPragmaAttributeSupport(Records);
52630b57cec5SDimitry Andric   ParsedAttrMap Attrs = getParsedAttrList(Records);
52640b57cec5SDimitry Andric   OS << "#pragma clang attribute supports the following attributes:\n";
52650b57cec5SDimitry Andric   for (const auto &I : Attrs) {
52660b57cec5SDimitry Andric     if (!Support.isAttributedSupported(*I.second))
52670b57cec5SDimitry Andric       continue;
52680b57cec5SDimitry Andric     OS << I.first;
52690b57cec5SDimitry Andric     if (I.second->isValueUnset("Subjects")) {
52700b57cec5SDimitry Andric       OS << " ()\n";
52710b57cec5SDimitry Andric       continue;
52720b57cec5SDimitry Andric     }
52730b57cec5SDimitry Andric     const Record *SubjectObj = I.second->getValueAsDef("Subjects");
52740b57cec5SDimitry Andric     std::vector<Record *> Subjects =
52750b57cec5SDimitry Andric         SubjectObj->getValueAsListOfDefs("Subjects");
52760b57cec5SDimitry Andric     OS << " (";
5277fe6060f1SDimitry Andric     bool PrintComma = false;
52780b57cec5SDimitry Andric     for (const auto &Subject : llvm::enumerate(Subjects)) {
5279fe6060f1SDimitry Andric       if (!isSupportedPragmaClangAttributeSubject(*Subject.value()))
5280fe6060f1SDimitry Andric         continue;
5281fe6060f1SDimitry Andric       if (PrintComma)
52820b57cec5SDimitry Andric         OS << ", ";
5283fe6060f1SDimitry Andric       PrintComma = true;
52840b57cec5SDimitry Andric       PragmaClangAttributeSupport::RuleOrAggregateRuleSet &RuleSet =
52850b57cec5SDimitry Andric           Support.SubjectsToRules.find(Subject.value())->getSecond();
52860b57cec5SDimitry Andric       if (RuleSet.isRule()) {
52870b57cec5SDimitry Andric         OS << RuleSet.getRule().getEnumValueName();
52880b57cec5SDimitry Andric         continue;
52890b57cec5SDimitry Andric       }
52900b57cec5SDimitry Andric       OS << "(";
52910b57cec5SDimitry Andric       for (const auto &Rule : llvm::enumerate(RuleSet.getAggregateRuleSet())) {
52920b57cec5SDimitry Andric         if (Rule.index())
52930b57cec5SDimitry Andric           OS << ", ";
52940b57cec5SDimitry Andric         OS << Rule.value().getEnumValueName();
52950b57cec5SDimitry Andric       }
52960b57cec5SDimitry Andric       OS << ")";
52970b57cec5SDimitry Andric     }
52980b57cec5SDimitry Andric     OS << ")\n";
52990b57cec5SDimitry Andric   }
53000b57cec5SDimitry Andric   OS << "End of supported attributes.\n";
53010b57cec5SDimitry Andric }
53020b57cec5SDimitry Andric 
53030b57cec5SDimitry Andric } // end namespace clang
5304