Path: blob/main/contrib/llvm-project/clang/utils/TableGen/ClangAttrEmitter.cpp
35230 views
//===- ClangAttrEmitter.cpp - Generate Clang attribute handling =-*- C++ -*--=//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// These tablegen backends emit Clang attribute processing code9//10//===----------------------------------------------------------------------===//1112#include "TableGenBackends.h"13#include "ASTTableGen.h"1415#include "llvm/ADT/ArrayRef.h"16#include "llvm/ADT/DenseMap.h"17#include "llvm/ADT/DenseSet.h"18#include "llvm/ADT/MapVector.h"19#include "llvm/ADT/STLExtras.h"20#include "llvm/ADT/SmallString.h"21#include "llvm/ADT/StringExtras.h"22#include "llvm/ADT/StringRef.h"23#include "llvm/ADT/StringSet.h"24#include "llvm/ADT/StringSwitch.h"25#include "llvm/ADT/iterator_range.h"26#include "llvm/Support/ErrorHandling.h"27#include "llvm/Support/raw_ostream.h"28#include "llvm/TableGen/Error.h"29#include "llvm/TableGen/Record.h"30#include "llvm/TableGen/StringMatcher.h"31#include "llvm/TableGen/TableGenBackend.h"32#include <algorithm>33#include <cassert>34#include <cctype>35#include <cstddef>36#include <cstdint>37#include <map>38#include <memory>39#include <optional>40#include <set>41#include <sstream>42#include <string>43#include <utility>44#include <vector>4546using namespace llvm;4748namespace {4950class FlattenedSpelling {51std::string V, N, NS;52bool K = false;53const Record &OriginalSpelling;5455public:56FlattenedSpelling(const std::string &Variety, const std::string &Name,57const std::string &Namespace, bool KnownToGCC,58const Record &OriginalSpelling)59: V(Variety), N(Name), NS(Namespace), K(KnownToGCC),60OriginalSpelling(OriginalSpelling) {}61explicit FlattenedSpelling(const Record &Spelling)62: V(std::string(Spelling.getValueAsString("Variety"))),63N(std::string(Spelling.getValueAsString("Name"))),64OriginalSpelling(Spelling) {65assert(V != "GCC" && V != "Clang" &&66"Given a GCC spelling, which means this hasn't been flattened!");67if (V == "CXX11" || V == "C23" || V == "Pragma")68NS = std::string(Spelling.getValueAsString("Namespace"));69}7071const std::string &variety() const { return V; }72const std::string &name() const { return N; }73const std::string &nameSpace() const { return NS; }74bool knownToGCC() const { return K; }75const Record &getSpellingRecord() const { return OriginalSpelling; }76};7778} // end anonymous namespace7980static std::vector<FlattenedSpelling>81GetFlattenedSpellings(const Record &Attr) {82std::vector<Record *> Spellings = Attr.getValueAsListOfDefs("Spellings");83std::vector<FlattenedSpelling> Ret;8485for (const auto &Spelling : Spellings) {86StringRef Variety = Spelling->getValueAsString("Variety");87StringRef Name = Spelling->getValueAsString("Name");88if (Variety == "GCC") {89Ret.emplace_back("GNU", std::string(Name), "", true, *Spelling);90Ret.emplace_back("CXX11", std::string(Name), "gnu", true, *Spelling);91if (Spelling->getValueAsBit("AllowInC"))92Ret.emplace_back("C23", std::string(Name), "gnu", true, *Spelling);93} else if (Variety == "Clang") {94Ret.emplace_back("GNU", std::string(Name), "", false, *Spelling);95Ret.emplace_back("CXX11", std::string(Name), "clang", false, *Spelling);96if (Spelling->getValueAsBit("AllowInC"))97Ret.emplace_back("C23", std::string(Name), "clang", false, *Spelling);98} else99Ret.push_back(FlattenedSpelling(*Spelling));100}101102return Ret;103}104105static std::string ReadPCHRecord(StringRef type) {106return StringSwitch<std::string>(type)107.EndsWith("Decl *", "Record.readDeclAs<" +108std::string(type.data(), 0, type.size() - 1) +109">()")110.Case("TypeSourceInfo *", "Record.readTypeSourceInfo()")111.Case("Expr *", "Record.readExpr()")112.Case("IdentifierInfo *", "Record.readIdentifier()")113.Case("StringRef", "Record.readString()")114.Case("ParamIdx", "ParamIdx::deserialize(Record.readInt())")115.Case("OMPTraitInfo *", "Record.readOMPTraitInfo()")116.Default("Record.readInt()");117}118119// Get a type that is suitable for storing an object of the specified type.120static StringRef getStorageType(StringRef type) {121return StringSwitch<StringRef>(type)122.Case("StringRef", "std::string")123.Default(type);124}125126// Assumes that the way to get the value is SA->getname()127static std::string WritePCHRecord(StringRef type, StringRef name) {128return "Record." +129StringSwitch<std::string>(type)130.EndsWith("Decl *", "AddDeclRef(" + std::string(name) + ");\n")131.Case("TypeSourceInfo *",132"AddTypeSourceInfo(" + std::string(name) + ");\n")133.Case("Expr *", "AddStmt(" + std::string(name) + ");\n")134.Case("IdentifierInfo *",135"AddIdentifierRef(" + std::string(name) + ");\n")136.Case("StringRef", "AddString(" + std::string(name) + ");\n")137.Case("ParamIdx",138"push_back(" + std::string(name) + ".serialize());\n")139.Case("OMPTraitInfo *",140"writeOMPTraitInfo(" + std::string(name) + ");\n")141.Default("push_back(" + std::string(name) + ");\n");142}143144// Normalize attribute name by removing leading and trailing145// underscores. For example, __foo, foo__, __foo__ would146// become foo.147static StringRef NormalizeAttrName(StringRef AttrName) {148AttrName.consume_front("__");149AttrName.consume_back("__");150return AttrName;151}152153// Normalize the name by removing any and all leading and trailing underscores.154// This is different from NormalizeAttrName in that it also handles names like155// _pascal and __pascal.156static StringRef NormalizeNameForSpellingComparison(StringRef Name) {157return Name.trim("_");158}159160// Normalize the spelling of a GNU attribute (i.e. "x" in "__attribute__((x))"),161// removing "__" if it appears at the beginning and end of the attribute's name.162static StringRef NormalizeGNUAttrSpelling(StringRef AttrSpelling) {163if (AttrSpelling.starts_with("__") && AttrSpelling.ends_with("__")) {164AttrSpelling = AttrSpelling.substr(2, AttrSpelling.size() - 4);165}166167return AttrSpelling;168}169170typedef std::vector<std::pair<std::string, const Record *>> ParsedAttrMap;171172static ParsedAttrMap getParsedAttrList(const RecordKeeper &Records,173ParsedAttrMap *Dupes = nullptr,174bool SemaOnly = true) {175std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");176std::set<std::string> Seen;177ParsedAttrMap R;178for (const auto *Attr : Attrs) {179if (!SemaOnly || Attr->getValueAsBit("SemaHandler")) {180std::string AN;181if (Attr->isSubClassOf("TargetSpecificAttr") &&182!Attr->isValueUnset("ParseKind")) {183AN = std::string(Attr->getValueAsString("ParseKind"));184185// If this attribute has already been handled, it does not need to be186// handled again.187if (Seen.find(AN) != Seen.end()) {188if (Dupes)189Dupes->push_back(std::make_pair(AN, Attr));190continue;191}192Seen.insert(AN);193} else194AN = NormalizeAttrName(Attr->getName()).str();195196R.push_back(std::make_pair(AN, Attr));197}198}199return R;200}201202namespace {203204class Argument {205std::string lowerName, upperName;206StringRef attrName;207bool isOpt;208bool Fake;209210public:211Argument(StringRef Arg, StringRef Attr)212: lowerName(std::string(Arg)), upperName(lowerName), attrName(Attr),213isOpt(false), Fake(false) {214if (!lowerName.empty()) {215lowerName[0] = std::tolower(lowerName[0]);216upperName[0] = std::toupper(upperName[0]);217}218// Work around MinGW's macro definition of 'interface' to 'struct'. We219// have an attribute argument called 'Interface', so only the lower case220// name conflicts with the macro definition.221if (lowerName == "interface")222lowerName = "interface_";223}224Argument(const Record &Arg, StringRef Attr)225: Argument(Arg.getValueAsString("Name"), Attr) {}226virtual ~Argument() = default;227228StringRef getLowerName() const { return lowerName; }229StringRef getUpperName() const { return upperName; }230StringRef getAttrName() const { return attrName; }231232bool isOptional() const { return isOpt; }233void setOptional(bool set) { isOpt = set; }234235bool isFake() const { return Fake; }236void setFake(bool fake) { Fake = fake; }237238// These functions print the argument contents formatted in different ways.239virtual void writeAccessors(raw_ostream &OS) const = 0;240virtual void writeAccessorDefinitions(raw_ostream &OS) const {}241virtual void writeASTVisitorTraversal(raw_ostream &OS) const {}242virtual void writeCloneArgs(raw_ostream &OS) const = 0;243virtual void writeTemplateInstantiationArgs(raw_ostream &OS) const = 0;244virtual void writeTemplateInstantiation(raw_ostream &OS) const {}245virtual void writeCtorBody(raw_ostream &OS) const {}246virtual void writeCtorInitializers(raw_ostream &OS) const = 0;247virtual void writeCtorDefaultInitializers(raw_ostream &OS) const = 0;248virtual void writeCtorParameters(raw_ostream &OS) const = 0;249virtual void writeDeclarations(raw_ostream &OS) const = 0;250virtual void writePCHReadArgs(raw_ostream &OS) const = 0;251virtual void writePCHReadDecls(raw_ostream &OS) const = 0;252virtual void writePCHWrite(raw_ostream &OS) const = 0;253virtual std::string getIsOmitted() const { return "false"; }254virtual void writeValue(raw_ostream &OS) const = 0;255virtual void writeDump(raw_ostream &OS) const = 0;256virtual void writeDumpChildren(raw_ostream &OS) const {}257virtual void writeHasChildren(raw_ostream &OS) const { OS << "false"; }258259virtual bool isEnumArg() const { return false; }260virtual bool isVariadicEnumArg() const { return false; }261virtual bool isVariadic() const { return false; }262263virtual void writeImplicitCtorArgs(raw_ostream &OS) const {264OS << getUpperName();265}266};267268class SimpleArgument : public Argument {269std::string type;270271public:272SimpleArgument(const Record &Arg, StringRef Attr, std::string T)273: Argument(Arg, Attr), type(std::move(T)) {}274275std::string getType() const { return type; }276277void writeAccessors(raw_ostream &OS) const override {278OS << " " << type << " get" << getUpperName() << "() const {\n";279OS << " return " << getLowerName() << ";\n";280OS << " }";281}282283void writeCloneArgs(raw_ostream &OS) const override {284OS << getLowerName();285}286287void writeTemplateInstantiationArgs(raw_ostream &OS) const override {288OS << "A->get" << getUpperName() << "()";289}290291void writeCtorInitializers(raw_ostream &OS) const override {292OS << getLowerName() << "(" << getUpperName() << ")";293}294295void writeCtorDefaultInitializers(raw_ostream &OS) const override {296OS << getLowerName() << "()";297}298299void writeCtorParameters(raw_ostream &OS) const override {300OS << type << " " << getUpperName();301}302303void writeDeclarations(raw_ostream &OS) const override {304OS << type << " " << getLowerName() << ";";305}306307void writePCHReadDecls(raw_ostream &OS) const override {308std::string read = ReadPCHRecord(type);309OS << " " << type << " " << getLowerName() << " = " << read << ";\n";310}311312void writePCHReadArgs(raw_ostream &OS) const override {313OS << getLowerName();314}315316void writePCHWrite(raw_ostream &OS) const override {317OS << " "318<< WritePCHRecord(type,319"SA->get" + std::string(getUpperName()) + "()");320}321322std::string getIsOmitted() const override {323auto IsOneOf = [](StringRef subject, auto... list) {324return ((subject == list) || ...);325};326327if (IsOneOf(type, "IdentifierInfo *", "Expr *"))328return "!get" + getUpperName().str() + "()";329if (IsOneOf(type, "TypeSourceInfo *"))330return "!get" + getUpperName().str() + "Loc()";331if (IsOneOf(type, "ParamIdx"))332return "!get" + getUpperName().str() + "().isValid()";333334assert(IsOneOf(type, "unsigned", "int", "bool", "FunctionDecl *",335"VarDecl *"));336return "false";337}338339void writeValue(raw_ostream &OS) const override {340if (type == "FunctionDecl *")341OS << "\" << get" << getUpperName()342<< "()->getNameInfo().getAsString() << \"";343else if (type == "IdentifierInfo *")344// Some non-optional (comma required) identifier arguments can be the345// empty string but are then recorded as a nullptr.346OS << "\" << (get" << getUpperName() << "() ? get" << getUpperName()347<< "()->getName() : \"\") << \"";348else if (type == "VarDecl *")349OS << "\" << get" << getUpperName() << "()->getName() << \"";350else if (type == "TypeSourceInfo *")351OS << "\" << get" << getUpperName() << "().getAsString() << \"";352else if (type == "ParamIdx")353OS << "\" << get" << getUpperName() << "().getSourceIndex() << \"";354else355OS << "\" << get" << getUpperName() << "() << \"";356}357358void writeDump(raw_ostream &OS) const override {359if (StringRef(type).ends_with("Decl *")) {360OS << " OS << \" \";\n";361OS << " dumpBareDeclRef(SA->get" << getUpperName() << "());\n";362} else if (type == "IdentifierInfo *") {363// Some non-optional (comma required) identifier arguments can be the364// empty string but are then recorded as a nullptr.365OS << " if (SA->get" << getUpperName() << "())\n"366<< " OS << \" \" << SA->get" << getUpperName()367<< "()->getName();\n";368} else if (type == "TypeSourceInfo *") {369if (isOptional())370OS << " if (SA->get" << getUpperName() << "Loc())";371OS << " OS << \" \" << SA->get" << getUpperName()372<< "().getAsString();\n";373} else if (type == "bool") {374OS << " if (SA->get" << getUpperName() << "()) OS << \" "375<< getUpperName() << "\";\n";376} else if (type == "int" || type == "unsigned") {377OS << " OS << \" \" << SA->get" << getUpperName() << "();\n";378} else if (type == "ParamIdx") {379if (isOptional())380OS << " if (SA->get" << getUpperName() << "().isValid())\n ";381OS << " OS << \" \" << SA->get" << getUpperName()382<< "().getSourceIndex();\n";383} else if (type == "OMPTraitInfo *") {384OS << " OS << \" \" << SA->get" << getUpperName() << "();\n";385} else {386llvm_unreachable("Unknown SimpleArgument type!");387}388}389};390391class DefaultSimpleArgument : public SimpleArgument {392int64_t Default;393394public:395DefaultSimpleArgument(const Record &Arg, StringRef Attr,396std::string T, int64_t Default)397: SimpleArgument(Arg, Attr, T), Default(Default) {}398399void writeAccessors(raw_ostream &OS) const override {400SimpleArgument::writeAccessors(OS);401402OS << "\n\n static const " << getType() << " Default" << getUpperName()403<< " = ";404if (getType() == "bool")405OS << (Default != 0 ? "true" : "false");406else407OS << Default;408OS << ";";409}410};411412class StringArgument : public Argument {413public:414StringArgument(const Record &Arg, StringRef Attr)415: Argument(Arg, Attr)416{}417418void writeAccessors(raw_ostream &OS) const override {419OS << " llvm::StringRef get" << getUpperName() << "() const {\n";420OS << " return llvm::StringRef(" << getLowerName() << ", "421<< getLowerName() << "Length);\n";422OS << " }\n";423OS << " unsigned get" << getUpperName() << "Length() const {\n";424OS << " return " << getLowerName() << "Length;\n";425OS << " }\n";426OS << " void set" << getUpperName()427<< "(ASTContext &C, llvm::StringRef S) {\n";428OS << " " << getLowerName() << "Length = S.size();\n";429OS << " this->" << getLowerName() << " = new (C, 1) char ["430<< getLowerName() << "Length];\n";431OS << " if (!S.empty())\n";432OS << " std::memcpy(this->" << getLowerName() << ", S.data(), "433<< getLowerName() << "Length);\n";434OS << " }";435}436437void writeCloneArgs(raw_ostream &OS) const override {438OS << "get" << getUpperName() << "()";439}440441void writeTemplateInstantiationArgs(raw_ostream &OS) const override {442OS << "A->get" << getUpperName() << "()";443}444445void writeCtorBody(raw_ostream &OS) const override {446OS << " if (!" << getUpperName() << ".empty())\n";447OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()448<< ".data(), " << getLowerName() << "Length);\n";449}450451void writeCtorInitializers(raw_ostream &OS) const override {452OS << getLowerName() << "Length(" << getUpperName() << ".size()),"453<< getLowerName() << "(new (Ctx, 1) char[" << getLowerName()454<< "Length])";455}456457void writeCtorDefaultInitializers(raw_ostream &OS) const override {458OS << getLowerName() << "Length(0)," << getLowerName() << "(nullptr)";459}460461void writeCtorParameters(raw_ostream &OS) const override {462OS << "llvm::StringRef " << getUpperName();463}464465void writeDeclarations(raw_ostream &OS) const override {466OS << "unsigned " << getLowerName() << "Length;\n";467OS << "char *" << getLowerName() << ";";468}469470void writePCHReadDecls(raw_ostream &OS) const override {471OS << " std::string " << getLowerName()472<< "= Record.readString();\n";473}474475void writePCHReadArgs(raw_ostream &OS) const override {476OS << getLowerName();477}478479void writePCHWrite(raw_ostream &OS) const override {480OS << " Record.AddString(SA->get" << getUpperName() << "());\n";481}482483void writeValue(raw_ostream &OS) const override {484OS << "\\\"\" << get" << getUpperName() << "() << \"\\\"";485}486487void writeDump(raw_ostream &OS) const override {488OS << " OS << \" \\\"\" << SA->get" << getUpperName()489<< "() << \"\\\"\";\n";490}491};492493class AlignedArgument : public Argument {494public:495AlignedArgument(const Record &Arg, StringRef Attr)496: Argument(Arg, Attr)497{}498499void writeAccessors(raw_ostream &OS) const override {500OS << " bool is" << getUpperName() << "Dependent() const;\n";501OS << " bool is" << getUpperName() << "ErrorDependent() const;\n";502503OS << " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n";504505OS << " bool is" << getUpperName() << "Expr() const {\n";506OS << " return is" << getLowerName() << "Expr;\n";507OS << " }\n";508509OS << " Expr *get" << getUpperName() << "Expr() const {\n";510OS << " assert(is" << getLowerName() << "Expr);\n";511OS << " return " << getLowerName() << "Expr;\n";512OS << " }\n";513514OS << " TypeSourceInfo *get" << getUpperName() << "Type() const {\n";515OS << " assert(!is" << getLowerName() << "Expr);\n";516OS << " return " << getLowerName() << "Type;\n";517OS << " }";518519OS << " std::optional<unsigned> getCached" << getUpperName()520<< "Value() const {\n";521OS << " return " << getLowerName() << "Cache;\n";522OS << " }";523524OS << " void setCached" << getUpperName()525<< "Value(unsigned AlignVal) {\n";526OS << " " << getLowerName() << "Cache = AlignVal;\n";527OS << " }";528}529530void writeAccessorDefinitions(raw_ostream &OS) const override {531OS << "bool " << getAttrName() << "Attr::is" << getUpperName()532<< "Dependent() const {\n";533OS << " if (is" << getLowerName() << "Expr)\n";534OS << " return " << getLowerName() << "Expr && (" << getLowerName()535<< "Expr->isValueDependent() || " << getLowerName()536<< "Expr->isTypeDependent());\n";537OS << " else\n";538OS << " return " << getLowerName()539<< "Type->getType()->isDependentType();\n";540OS << "}\n";541542OS << "bool " << getAttrName() << "Attr::is" << getUpperName()543<< "ErrorDependent() const {\n";544OS << " if (is" << getLowerName() << "Expr)\n";545OS << " return " << getLowerName() << "Expr && " << getLowerName()546<< "Expr->containsErrors();\n";547OS << " return " << getLowerName()548<< "Type->getType()->containsErrors();\n";549OS << "}\n";550}551552void writeASTVisitorTraversal(raw_ostream &OS) const override {553StringRef Name = getUpperName();554OS << " if (A->is" << Name << "Expr()) {\n"555<< " if (!getDerived().TraverseStmt(A->get" << Name << "Expr()))\n"556<< " return false;\n"557<< " } else if (auto *TSI = A->get" << Name << "Type()) {\n"558<< " if (!getDerived().TraverseTypeLoc(TSI->getTypeLoc()))\n"559<< " return false;\n"560<< " }\n";561}562563void writeCloneArgs(raw_ostream &OS) const override {564OS << "is" << getLowerName() << "Expr, is" << getLowerName()565<< "Expr ? static_cast<void*>(" << getLowerName()566<< "Expr) : " << getLowerName()567<< "Type";568}569570void writeTemplateInstantiationArgs(raw_ostream &OS) const override {571// FIXME: move the definition in Sema::InstantiateAttrs to here.572// In the meantime, aligned attributes are cloned.573}574575void writeCtorBody(raw_ostream &OS) const override {576OS << " if (is" << getLowerName() << "Expr)\n";577OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>("578<< getUpperName() << ");\n";579OS << " else\n";580OS << " " << getLowerName()581<< "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName()582<< ");\n";583}584585void writeCtorInitializers(raw_ostream &OS) const override {586OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)";587}588589void writeCtorDefaultInitializers(raw_ostream &OS) const override {590OS << "is" << getLowerName() << "Expr(false)";591}592593void writeCtorParameters(raw_ostream &OS) const override {594OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName();595}596597void writeImplicitCtorArgs(raw_ostream &OS) const override {598OS << "Is" << getUpperName() << "Expr, " << getUpperName();599}600601void writeDeclarations(raw_ostream &OS) const override {602OS << "bool is" << getLowerName() << "Expr;\n";603OS << "union {\n";604OS << "Expr *" << getLowerName() << "Expr;\n";605OS << "TypeSourceInfo *" << getLowerName() << "Type;\n";606OS << "};\n";607OS << "std::optional<unsigned> " << getLowerName() << "Cache;\n";608}609610void writePCHReadArgs(raw_ostream &OS) const override {611OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr";612}613614void writePCHReadDecls(raw_ostream &OS) const override {615OS << " bool is" << getLowerName() << "Expr = Record.readInt();\n";616OS << " void *" << getLowerName() << "Ptr;\n";617OS << " if (is" << getLowerName() << "Expr)\n";618OS << " " << getLowerName() << "Ptr = Record.readExpr();\n";619OS << " else\n";620OS << " " << getLowerName()621<< "Ptr = Record.readTypeSourceInfo();\n";622}623624void writePCHWrite(raw_ostream &OS) const override {625OS << " Record.push_back(SA->is" << getUpperName() << "Expr());\n";626OS << " if (SA->is" << getUpperName() << "Expr())\n";627OS << " Record.AddStmt(SA->get" << getUpperName() << "Expr());\n";628OS << " else\n";629OS << " Record.AddTypeSourceInfo(SA->get" << getUpperName()630<< "Type());\n";631}632633std::string getIsOmitted() const override {634return "!((is" + getLowerName().str() + "Expr && " +635getLowerName().str() + "Expr) || (!is" + getLowerName().str() +636"Expr && " + getLowerName().str() + "Type))";637}638639void writeValue(raw_ostream &OS) const override {640OS << "\";\n";641OS << " if (is" << getLowerName() << "Expr && " << getLowerName()642<< "Expr)";643OS << " " << getLowerName()644<< "Expr->printPretty(OS, nullptr, Policy);\n";645OS << " if (!is" << getLowerName() << "Expr && " << getLowerName()646<< "Type)";647OS << " " << getLowerName()648<< "Type->getType().print(OS, Policy);\n";649OS << " OS << \"";650}651652void writeDump(raw_ostream &OS) const override {653OS << " if (!SA->is" << getUpperName() << "Expr())\n";654OS << " dumpType(SA->get" << getUpperName()655<< "Type()->getType());\n";656}657658void writeDumpChildren(raw_ostream &OS) const override {659OS << " if (SA->is" << getUpperName() << "Expr())\n";660OS << " Visit(SA->get" << getUpperName() << "Expr());\n";661}662663void writeHasChildren(raw_ostream &OS) const override {664OS << "SA->is" << getUpperName() << "Expr()";665}666};667668class VariadicArgument : public Argument {669std::string Type, ArgName, ArgSizeName, RangeName;670671protected:672// Assumed to receive a parameter: raw_ostream OS.673virtual void writeValueImpl(raw_ostream &OS) const {674OS << " OS << Val;\n";675}676// Assumed to receive a parameter: raw_ostream OS.677virtual void writeDumpImpl(raw_ostream &OS) const {678OS << " OS << \" \" << Val;\n";679}680681public:682VariadicArgument(const Record &Arg, StringRef Attr, std::string T)683: Argument(Arg, Attr), Type(std::move(T)),684ArgName(getLowerName().str() + "_"), ArgSizeName(ArgName + "Size"),685RangeName(std::string(getLowerName())) {}686687VariadicArgument(StringRef Arg, StringRef Attr, std::string T)688: Argument(Arg, Attr), Type(std::move(T)),689ArgName(getLowerName().str() + "_"), ArgSizeName(ArgName + "Size"),690RangeName(std::string(getLowerName())) {}691692const std::string &getType() const { return Type; }693const std::string &getArgName() const { return ArgName; }694const std::string &getArgSizeName() const { return ArgSizeName; }695bool isVariadic() const override { return true; }696697void writeAccessors(raw_ostream &OS) const override {698std::string IteratorType = getLowerName().str() + "_iterator";699std::string BeginFn = getLowerName().str() + "_begin()";700std::string EndFn = getLowerName().str() + "_end()";701702OS << " typedef " << Type << "* " << IteratorType << ";\n";703OS << " " << IteratorType << " " << BeginFn << " const {"704<< " return " << ArgName << "; }\n";705OS << " " << IteratorType << " " << EndFn << " const {"706<< " return " << ArgName << " + " << ArgSizeName << "; }\n";707OS << " unsigned " << getLowerName() << "_size() const {"708<< " return " << ArgSizeName << "; }\n";709OS << " llvm::iterator_range<" << IteratorType << "> " << RangeName710<< "() const { return llvm::make_range(" << BeginFn << ", " << EndFn711<< "); }\n";712}713714void writeSetter(raw_ostream &OS) const {715OS << " void set" << getUpperName() << "(ASTContext &Ctx, ";716writeCtorParameters(OS);717OS << ") {\n";718OS << " " << ArgSizeName << " = " << getUpperName() << "Size;\n";719OS << " " << ArgName << " = new (Ctx, 16) " << getType() << "["720<< ArgSizeName << "];\n";721OS << " ";722writeCtorBody(OS);723OS << " }\n";724}725726void writeCloneArgs(raw_ostream &OS) const override {727OS << ArgName << ", " << ArgSizeName;728}729730void writeTemplateInstantiationArgs(raw_ostream &OS) const override {731// This isn't elegant, but we have to go through public methods...732OS << "A->" << getLowerName() << "_begin(), "733<< "A->" << getLowerName() << "_size()";734}735736void writeASTVisitorTraversal(raw_ostream &OS) const override {737// FIXME: Traverse the elements.738}739740void writeCtorBody(raw_ostream &OS) const override {741OS << " std::copy(" << getUpperName() << ", " << getUpperName() << " + "742<< ArgSizeName << ", " << ArgName << ");\n";743}744745void writeCtorInitializers(raw_ostream &OS) const override {746OS << ArgSizeName << "(" << getUpperName() << "Size), "747<< ArgName << "(new (Ctx, 16) " << getType() << "["748<< ArgSizeName << "])";749}750751void writeCtorDefaultInitializers(raw_ostream &OS) const override {752OS << ArgSizeName << "(0), " << ArgName << "(nullptr)";753}754755void writeCtorParameters(raw_ostream &OS) const override {756OS << getType() << " *" << getUpperName() << ", unsigned "757<< getUpperName() << "Size";758}759760void writeImplicitCtorArgs(raw_ostream &OS) const override {761OS << getUpperName() << ", " << getUpperName() << "Size";762}763764void writeDeclarations(raw_ostream &OS) const override {765OS << " unsigned " << ArgSizeName << ";\n";766OS << " " << getType() << " *" << ArgName << ";";767}768769void writePCHReadDecls(raw_ostream &OS) const override {770OS << " unsigned " << getLowerName() << "Size = Record.readInt();\n";771OS << " SmallVector<" << getType() << ", 4> "772<< getLowerName() << ";\n";773OS << " " << getLowerName() << ".reserve(" << getLowerName()774<< "Size);\n";775776// If we can't store the values in the current type (if it's something777// like StringRef), store them in a different type and convert the778// container afterwards.779std::string StorageType = std::string(getStorageType(getType()));780std::string StorageName = std::string(getLowerName());781if (StorageType != getType()) {782StorageName += "Storage";783OS << " SmallVector<" << StorageType << ", 4> "784<< StorageName << ";\n";785OS << " " << StorageName << ".reserve(" << getLowerName()786<< "Size);\n";787}788789OS << " for (unsigned i = 0; i != " << getLowerName() << "Size; ++i)\n";790std::string read = ReadPCHRecord(Type);791OS << " " << StorageName << ".push_back(" << read << ");\n";792793if (StorageType != getType()) {794OS << " for (unsigned i = 0; i != " << getLowerName() << "Size; ++i)\n";795OS << " " << getLowerName() << ".push_back("796<< StorageName << "[i]);\n";797}798}799800void writePCHReadArgs(raw_ostream &OS) const override {801OS << getLowerName() << ".data(), " << getLowerName() << "Size";802}803804void writePCHWrite(raw_ostream &OS) const override {805OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";806OS << " for (auto &Val : SA->" << RangeName << "())\n";807OS << " " << WritePCHRecord(Type, "Val");808}809810void writeValue(raw_ostream &OS) const override {811OS << "\";\n";812OS << " for (const auto &Val : " << RangeName << "()) {\n"813<< " DelimitAttributeArgument(OS, IsFirstArgument);\n";814writeValueImpl(OS);815OS << " }\n";816OS << " OS << \"";817}818819void writeDump(raw_ostream &OS) const override {820OS << " for (const auto &Val : SA->" << RangeName << "())\n";821writeDumpImpl(OS);822}823};824825class VariadicOMPInteropInfoArgument : public VariadicArgument {826public:827VariadicOMPInteropInfoArgument(const Record &Arg, StringRef Attr)828: VariadicArgument(Arg, Attr, "OMPInteropInfo") {}829830void writeDump(raw_ostream &OS) const override {831OS << " for (" << getAttrName() << "Attr::" << getLowerName()832<< "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"833<< getLowerName() << "_end(); I != E; ++I) {\n";834OS << " if (I->IsTarget && I->IsTargetSync)\n";835OS << " OS << \" Target_TargetSync\";\n";836OS << " else if (I->IsTarget)\n";837OS << " OS << \" Target\";\n";838OS << " else\n";839OS << " OS << \" TargetSync\";\n";840OS << " }\n";841}842843void writePCHReadDecls(raw_ostream &OS) const override {844OS << " unsigned " << getLowerName() << "Size = Record.readInt();\n";845OS << " SmallVector<OMPInteropInfo, 4> " << getLowerName() << ";\n";846OS << " " << getLowerName() << ".reserve(" << getLowerName()847<< "Size);\n";848OS << " for (unsigned I = 0, E = " << getLowerName() << "Size; ";849OS << "I != E; ++I) {\n";850OS << " bool IsTarget = Record.readBool();\n";851OS << " bool IsTargetSync = Record.readBool();\n";852OS << " " << getLowerName()853<< ".emplace_back(IsTarget, IsTargetSync);\n";854OS << " }\n";855}856857void writePCHWrite(raw_ostream &OS) const override {858OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";859OS << " for (" << getAttrName() << "Attr::" << getLowerName()860<< "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"861<< getLowerName() << "_end(); I != E; ++I) {\n";862OS << " Record.writeBool(I->IsTarget);\n";863OS << " Record.writeBool(I->IsTargetSync);\n";864OS << " }\n";865}866};867868class VariadicParamIdxArgument : public VariadicArgument {869public:870VariadicParamIdxArgument(const Record &Arg, StringRef Attr)871: VariadicArgument(Arg, Attr, "ParamIdx") {}872873public:874void writeValueImpl(raw_ostream &OS) const override {875OS << " OS << Val.getSourceIndex();\n";876}877878void writeDumpImpl(raw_ostream &OS) const override {879OS << " OS << \" \" << Val.getSourceIndex();\n";880}881};882883struct VariadicParamOrParamIdxArgument : public VariadicArgument {884VariadicParamOrParamIdxArgument(const Record &Arg, StringRef Attr)885: VariadicArgument(Arg, Attr, "int") {}886};887888// Unique the enums, but maintain the original declaration ordering.889std::vector<StringRef>890uniqueEnumsInOrder(const std::vector<StringRef> &enums) {891std::vector<StringRef> uniques;892SmallDenseSet<StringRef, 8> unique_set;893for (const auto &i : enums) {894if (unique_set.insert(i).second)895uniques.push_back(i);896}897return uniques;898}899900class EnumArgument : public Argument {901std::string fullType;902StringRef shortType;903std::vector<StringRef> values, enums, uniques;904bool isExternal;905bool isCovered;906907public:908EnumArgument(const Record &Arg, StringRef Attr)909: Argument(Arg, Attr), values(Arg.getValueAsListOfStrings("Values")),910enums(Arg.getValueAsListOfStrings("Enums")),911uniques(uniqueEnumsInOrder(enums)),912isExternal(Arg.getValueAsBit("IsExternalType")),913isCovered(Arg.getValueAsBit("IsCovered")) {914StringRef Type = Arg.getValueAsString("Type");915shortType = isExternal ? Type.rsplit("::").second : Type;916// If shortType didn't contain :: at all rsplit will give us an empty917// string.918if (shortType.empty())919shortType = Type;920fullType = isExternal ? Type : (getAttrName() + "Attr::" + Type).str();921922// FIXME: Emit a proper error923assert(!uniques.empty());924}925926bool isEnumArg() const override { return true; }927928void writeAccessors(raw_ostream &OS) const override {929OS << " " << fullType << " get" << getUpperName() << "() const {\n";930OS << " return " << getLowerName() << ";\n";931OS << " }";932}933934void writeCloneArgs(raw_ostream &OS) const override {935OS << getLowerName();936}937938void writeTemplateInstantiationArgs(raw_ostream &OS) const override {939OS << "A->get" << getUpperName() << "()";940}941void writeCtorInitializers(raw_ostream &OS) const override {942OS << getLowerName() << "(" << getUpperName() << ")";943}944void writeCtorDefaultInitializers(raw_ostream &OS) const override {945OS << getLowerName() << "(" << fullType << "(0))";946}947void writeCtorParameters(raw_ostream &OS) const override {948OS << fullType << " " << getUpperName();949}950void writeDeclarations(raw_ostream &OS) const override {951if (!isExternal) {952auto i = uniques.cbegin(), e = uniques.cend();953// The last one needs to not have a comma.954--e;955956OS << "public:\n";957OS << " enum " << shortType << " {\n";958for (; i != e; ++i)959OS << " " << *i << ",\n";960OS << " " << *e << "\n";961OS << " };\n";962}963964OS << "private:\n";965OS << " " << fullType << " " << getLowerName() << ";";966}967968void writePCHReadDecls(raw_ostream &OS) const override {969OS << " " << fullType << " " << getLowerName() << "(static_cast<"970<< fullType << ">(Record.readInt()));\n";971}972973void writePCHReadArgs(raw_ostream &OS) const override {974OS << getLowerName();975}976977void writePCHWrite(raw_ostream &OS) const override {978OS << "Record.push_back(static_cast<uint64_t>(SA->get" << getUpperName()979<< "()));\n";980}981982void writeValue(raw_ostream &OS) const override {983// FIXME: this isn't 100% correct -- some enum arguments require printing984// as a string literal, while others require printing as an identifier.985// Tablegen currently does not distinguish between the two forms.986OS << "\\\"\" << " << getAttrName() << "Attr::Convert" << shortType987<< "ToStr(get" << getUpperName() << "()) << \"\\\"";988}989990void writeDump(raw_ostream &OS) const override {991OS << " switch(SA->get" << getUpperName() << "()) {\n";992for (const auto &I : uniques) {993OS << " case " << fullType << "::" << I << ":\n";994OS << " OS << \" " << I << "\";\n";995OS << " break;\n";996}997if (!isCovered) {998OS << " default:\n";999OS << " llvm_unreachable(\"Invalid attribute value\");\n";1000}1001OS << " }\n";1002}10031004void writeConversion(raw_ostream &OS, bool Header) const {1005if (Header) {1006OS << " static bool ConvertStrTo" << shortType << "(StringRef Val, "1007<< fullType << " &Out);\n";1008OS << " static const char *Convert" << shortType << "ToStr("1009<< fullType << " Val);\n";1010return;1011}10121013OS << "bool " << getAttrName() << "Attr::ConvertStrTo" << shortType1014<< "(StringRef Val, " << fullType << " &Out) {\n";1015OS << " std::optional<" << fullType << "> "1016<< "R = llvm::StringSwitch<std::optional<" << fullType << ">>(Val)\n";1017for (size_t I = 0; I < enums.size(); ++I) {1018OS << " .Case(\"" << values[I] << "\", ";1019OS << fullType << "::" << enums[I] << ")\n";1020}1021OS << " .Default(std::optional<" << fullType << ">());\n";1022OS << " if (R) {\n";1023OS << " Out = *R;\n return true;\n }\n";1024OS << " return false;\n";1025OS << "}\n\n";10261027// Mapping from enumeration values back to enumeration strings isn't1028// trivial because some enumeration values have multiple named1029// enumerators, such as type_visibility(internal) and1030// type_visibility(hidden) both mapping to TypeVisibilityAttr::Hidden.1031OS << "const char *" << getAttrName() << "Attr::Convert" << shortType1032<< "ToStr(" << fullType << " Val) {\n"1033<< " switch(Val) {\n";1034SmallDenseSet<StringRef, 8> Uniques;1035for (size_t I = 0; I < enums.size(); ++I) {1036if (Uniques.insert(enums[I]).second)1037OS << " case " << fullType << "::" << enums[I] << ": return \""1038<< values[I] << "\";\n";1039}1040if (!isCovered) {1041OS << " default: llvm_unreachable(\"Invalid attribute value\");\n";1042}1043OS << " }\n"1044<< " llvm_unreachable(\"No enumerator with that value\");\n"1045<< "}\n";1046}1047};10481049class VariadicEnumArgument: public VariadicArgument {1050std::string fullType;1051StringRef shortType;1052std::vector<StringRef> values, enums, uniques;1053bool isExternal;1054bool isCovered;10551056protected:1057void writeValueImpl(raw_ostream &OS) const override {1058// FIXME: this isn't 100% correct -- some enum arguments require printing1059// as a string literal, while others require printing as an identifier.1060// Tablegen currently does not distinguish between the two forms.1061OS << " OS << \"\\\"\" << " << getAttrName() << "Attr::Convert"1062<< shortType << "ToStr(Val)"1063<< "<< \"\\\"\";\n";1064}10651066public:1067VariadicEnumArgument(const Record &Arg, StringRef Attr)1068: VariadicArgument(Arg, Attr,1069std::string(Arg.getValueAsString("Type"))),1070values(Arg.getValueAsListOfStrings("Values")),1071enums(Arg.getValueAsListOfStrings("Enums")),1072uniques(uniqueEnumsInOrder(enums)),1073isExternal(Arg.getValueAsBit("IsExternalType")),1074isCovered(Arg.getValueAsBit("IsCovered")) {1075StringRef Type = Arg.getValueAsString("Type");1076shortType = isExternal ? Type.rsplit("::").second : Type;1077// If shortType didn't contain :: at all rsplit will give us an empty1078// string.1079if (shortType.empty())1080shortType = Type;1081fullType = isExternal ? Type : (getAttrName() + "Attr::" + Type).str();10821083// FIXME: Emit a proper error1084assert(!uniques.empty());1085}10861087bool isVariadicEnumArg() const override { return true; }10881089void writeDeclarations(raw_ostream &OS) const override {1090if (!isExternal) {1091auto i = uniques.cbegin(), e = uniques.cend();1092// The last one needs to not have a comma.1093--e;10941095OS << "public:\n";1096OS << " enum " << shortType << " {\n";1097for (; i != e; ++i)1098OS << " " << *i << ",\n";1099OS << " " << *e << "\n";1100OS << " };\n";1101}1102OS << "private:\n";11031104VariadicArgument::writeDeclarations(OS);1105}11061107void writeDump(raw_ostream &OS) const override {1108OS << " for (" << getAttrName() << "Attr::" << getLowerName()1109<< "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"1110<< getLowerName() << "_end(); I != E; ++I) {\n";1111OS << " switch(*I) {\n";1112for (const auto &UI : uniques) {1113OS << " case " << fullType << "::" << UI << ":\n";1114OS << " OS << \" " << UI << "\";\n";1115OS << " break;\n";1116}1117if (!isCovered) {1118OS << " default:\n";1119OS << " llvm_unreachable(\"Invalid attribute value\");\n";1120}1121OS << " }\n";1122OS << " }\n";1123}11241125void writePCHReadDecls(raw_ostream &OS) const override {1126OS << " unsigned " << getLowerName() << "Size = Record.readInt();\n";1127OS << " SmallVector<" << fullType << ", 4> " << getLowerName()1128<< ";\n";1129OS << " " << getLowerName() << ".reserve(" << getLowerName()1130<< "Size);\n";1131OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n";1132OS << " " << getLowerName() << ".push_back("1133<< "static_cast<" << fullType << ">(Record.readInt()));\n";1134}11351136void writePCHWrite(raw_ostream &OS) const override {1137OS << " Record.push_back(SA->" << getLowerName() << "_size());\n";1138OS << " for (" << getAttrName() << "Attr::" << getLowerName()1139<< "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"1140<< getLowerName() << "_end(); i != e; ++i)\n";1141OS << " " << WritePCHRecord(fullType, "(*i)");1142}11431144void writeConversion(raw_ostream &OS, bool Header) const {1145if (Header) {1146OS << " static bool ConvertStrTo" << shortType << "(StringRef Val, "1147<< fullType << " &Out);\n";1148OS << " static const char *Convert" << shortType << "ToStr("1149<< fullType << " Val);\n";1150return;1151}11521153OS << "bool " << getAttrName() << "Attr::ConvertStrTo" << shortType1154<< "(StringRef Val, ";1155OS << fullType << " &Out) {\n";1156OS << " std::optional<" << fullType1157<< "> R = llvm::StringSwitch<std::optional<";1158OS << fullType << ">>(Val)\n";1159for (size_t I = 0; I < enums.size(); ++I) {1160OS << " .Case(\"" << values[I] << "\", ";1161OS << fullType << "::" << enums[I] << ")\n";1162}1163OS << " .Default(std::optional<" << fullType << ">());\n";1164OS << " if (R) {\n";1165OS << " Out = *R;\n return true;\n }\n";1166OS << " return false;\n";1167OS << "}\n\n";11681169OS << "const char *" << getAttrName() << "Attr::Convert" << shortType1170<< "ToStr(" << fullType << " Val) {\n"1171<< " switch(Val) {\n";1172SmallDenseSet<StringRef, 8> Uniques;1173for (size_t I = 0; I < enums.size(); ++I) {1174if (Uniques.insert(enums[I]).second)1175OS << " case " << fullType << "::" << enums[I] << ": return \""1176<< values[I] << "\";\n";1177}1178if (!isCovered) {1179OS << " default: llvm_unreachable(\"Invalid attribute value\");\n";1180}1181OS << " }\n"1182<< " llvm_unreachable(\"No enumerator with that value\");\n"1183<< "}\n";1184}1185};11861187class VersionArgument : public Argument {1188public:1189VersionArgument(const Record &Arg, StringRef Attr)1190: Argument(Arg, Attr)1191{}11921193void writeAccessors(raw_ostream &OS) const override {1194OS << " VersionTuple get" << getUpperName() << "() const {\n";1195OS << " return " << getLowerName() << ";\n";1196OS << " }\n";1197OS << " void set" << getUpperName()1198<< "(ASTContext &C, VersionTuple V) {\n";1199OS << " " << getLowerName() << " = V;\n";1200OS << " }";1201}12021203void writeCloneArgs(raw_ostream &OS) const override {1204OS << "get" << getUpperName() << "()";1205}12061207void writeTemplateInstantiationArgs(raw_ostream &OS) const override {1208OS << "A->get" << getUpperName() << "()";1209}12101211void writeCtorInitializers(raw_ostream &OS) const override {1212OS << getLowerName() << "(" << getUpperName() << ")";1213}12141215void writeCtorDefaultInitializers(raw_ostream &OS) const override {1216OS << getLowerName() << "()";1217}12181219void writeCtorParameters(raw_ostream &OS) const override {1220OS << "VersionTuple " << getUpperName();1221}12221223void writeDeclarations(raw_ostream &OS) const override {1224OS << "VersionTuple " << getLowerName() << ";\n";1225}12261227void writePCHReadDecls(raw_ostream &OS) const override {1228OS << " VersionTuple " << getLowerName()1229<< "= Record.readVersionTuple();\n";1230}12311232void writePCHReadArgs(raw_ostream &OS) const override {1233OS << getLowerName();1234}12351236void writePCHWrite(raw_ostream &OS) const override {1237OS << " Record.AddVersionTuple(SA->get" << getUpperName() << "());\n";1238}12391240void writeValue(raw_ostream &OS) const override {1241OS << getLowerName() << "=\" << get" << getUpperName() << "() << \"";1242}12431244void writeDump(raw_ostream &OS) const override {1245OS << " OS << \" \" << SA->get" << getUpperName() << "();\n";1246}1247};12481249class ExprArgument : public SimpleArgument {1250public:1251ExprArgument(const Record &Arg, StringRef Attr)1252: SimpleArgument(Arg, Attr, "Expr *")1253{}12541255void writeASTVisitorTraversal(raw_ostream &OS) const override {1256OS << " if (!"1257<< "getDerived().TraverseStmt(A->get" << getUpperName() << "()))\n";1258OS << " return false;\n";1259}12601261void writeTemplateInstantiationArgs(raw_ostream &OS) const override {1262OS << "tempInst" << getUpperName();1263}12641265void writeTemplateInstantiation(raw_ostream &OS) const override {1266OS << " " << getType() << " tempInst" << getUpperName() << ";\n";1267OS << " {\n";1268OS << " EnterExpressionEvaluationContext "1269<< "Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);\n";1270OS << " ExprResult " << "Result = S.SubstExpr("1271<< "A->get" << getUpperName() << "(), TemplateArgs);\n";1272OS << " if (Result.isInvalid())\n";1273OS << " return nullptr;\n";1274OS << " tempInst" << getUpperName() << " = Result.get();\n";1275OS << " }\n";1276}12771278void writeValue(raw_ostream &OS) const override {1279OS << "\";\n";1280OS << " get" << getUpperName()1281<< "()->printPretty(OS, nullptr, Policy);\n";1282OS << " OS << \"";1283}12841285void writeDump(raw_ostream &OS) const override {}12861287void writeDumpChildren(raw_ostream &OS) const override {1288OS << " Visit(SA->get" << getUpperName() << "());\n";1289}12901291void writeHasChildren(raw_ostream &OS) const override { OS << "true"; }1292};12931294class VariadicExprArgument : public VariadicArgument {1295public:1296VariadicExprArgument(const Record &Arg, StringRef Attr)1297: VariadicArgument(Arg, Attr, "Expr *")1298{}12991300VariadicExprArgument(StringRef ArgName, StringRef Attr)1301: VariadicArgument(ArgName, Attr, "Expr *") {}13021303void writeASTVisitorTraversal(raw_ostream &OS) const override {1304OS << " {\n";1305OS << " " << getType() << " *I = A->" << getLowerName()1306<< "_begin();\n";1307OS << " " << getType() << " *E = A->" << getLowerName()1308<< "_end();\n";1309OS << " for (; I != E; ++I) {\n";1310OS << " if (!getDerived().TraverseStmt(*I))\n";1311OS << " return false;\n";1312OS << " }\n";1313OS << " }\n";1314}13151316void writeTemplateInstantiationArgs(raw_ostream &OS) const override {1317OS << "tempInst" << getUpperName() << ", "1318<< "A->" << getLowerName() << "_size()";1319}13201321void writeTemplateInstantiation(raw_ostream &OS) const override {1322OS << " auto *tempInst" << getUpperName()1323<< " = new (C, 16) " << getType()1324<< "[A->" << getLowerName() << "_size()];\n";1325OS << " {\n";1326OS << " EnterExpressionEvaluationContext "1327<< "Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);\n";1328OS << " " << getType() << " *TI = tempInst" << getUpperName()1329<< ";\n";1330OS << " " << getType() << " *I = A->" << getLowerName()1331<< "_begin();\n";1332OS << " " << getType() << " *E = A->" << getLowerName()1333<< "_end();\n";1334OS << " for (; I != E; ++I, ++TI) {\n";1335OS << " ExprResult Result = S.SubstExpr(*I, TemplateArgs);\n";1336OS << " if (Result.isInvalid())\n";1337OS << " return nullptr;\n";1338OS << " *TI = Result.get();\n";1339OS << " }\n";1340OS << " }\n";1341}13421343void writeDump(raw_ostream &OS) const override {}13441345void writeDumpChildren(raw_ostream &OS) const override {1346OS << " for (" << getAttrName() << "Attr::" << getLowerName()1347<< "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"1348<< getLowerName() << "_end(); I != E; ++I)\n";1349OS << " Visit(*I);\n";1350}13511352void writeHasChildren(raw_ostream &OS) const override {1353OS << "SA->" << getLowerName() << "_begin() != "1354<< "SA->" << getLowerName() << "_end()";1355}1356};13571358class VariadicIdentifierArgument : public VariadicArgument {1359public:1360VariadicIdentifierArgument(const Record &Arg, StringRef Attr)1361: VariadicArgument(Arg, Attr, "IdentifierInfo *")1362{}1363};13641365class VariadicStringArgument : public VariadicArgument {1366public:1367VariadicStringArgument(const Record &Arg, StringRef Attr)1368: VariadicArgument(Arg, Attr, "StringRef")1369{}13701371void writeCtorBody(raw_ostream &OS) const override {1372OS << " for (size_t I = 0, E = " << getArgSizeName() << "; I != E;\n"1373" ++I) {\n"1374" StringRef Ref = " << getUpperName() << "[I];\n"1375" if (!Ref.empty()) {\n"1376" char *Mem = new (Ctx, 1) char[Ref.size()];\n"1377" std::memcpy(Mem, Ref.data(), Ref.size());\n"1378" " << getArgName() << "[I] = StringRef(Mem, Ref.size());\n"1379" }\n"1380" }\n";1381}13821383void writeValueImpl(raw_ostream &OS) const override {1384OS << " OS << \"\\\"\" << Val << \"\\\"\";\n";1385}1386};13871388class TypeArgument : public SimpleArgument {1389public:1390TypeArgument(const Record &Arg, StringRef Attr)1391: SimpleArgument(Arg, Attr, "TypeSourceInfo *")1392{}13931394void writeAccessors(raw_ostream &OS) const override {1395OS << " QualType get" << getUpperName() << "() const {\n";1396OS << " return " << getLowerName() << "->getType();\n";1397OS << " }";1398OS << " " << getType() << " get" << getUpperName() << "Loc() const {\n";1399OS << " return " << getLowerName() << ";\n";1400OS << " }";1401}14021403void writeASTVisitorTraversal(raw_ostream &OS) const override {1404OS << " if (auto *TSI = A->get" << getUpperName() << "Loc())\n";1405OS << " if (!getDerived().TraverseTypeLoc(TSI->getTypeLoc()))\n";1406OS << " return false;\n";1407}14081409void writeTemplateInstantiation(raw_ostream &OS) const override {1410OS << " " << getType() << " tempInst" << getUpperName() << " =\n";1411OS << " S.SubstType(A->get" << getUpperName() << "Loc(), "1412<< "TemplateArgs, A->getLoc(), A->getAttrName());\n";1413OS << " if (!tempInst" << getUpperName() << ")\n";1414OS << " return nullptr;\n";1415}14161417void writeTemplateInstantiationArgs(raw_ostream &OS) const override {1418OS << "tempInst" << getUpperName();1419}14201421void writePCHWrite(raw_ostream &OS) const override {1422OS << " "1423<< WritePCHRecord(getType(),1424"SA->get" + std::string(getUpperName()) + "Loc()");1425}1426};14271428class WrappedAttr : public SimpleArgument {1429public:1430WrappedAttr(const Record &Arg, StringRef Attr)1431: SimpleArgument(Arg, Attr, "Attr *") {}14321433void writePCHReadDecls(raw_ostream &OS) const override {1434OS << " Attr *" << getLowerName() << " = Record.readAttr();";1435}14361437void writePCHWrite(raw_ostream &OS) const override {1438OS << " AddAttr(SA->get" << getUpperName() << "());";1439}14401441void writeDump(raw_ostream &OS) const override {}14421443void writeDumpChildren(raw_ostream &OS) const override {1444OS << " Visit(SA->get" << getUpperName() << "());\n";1445}14461447void writeHasChildren(raw_ostream &OS) const override { OS << "true"; }1448};14491450} // end anonymous namespace14511452static std::unique_ptr<Argument>1453createArgument(const Record &Arg, StringRef Attr,1454const Record *Search = nullptr) {1455if (!Search)1456Search = &Arg;14571458std::unique_ptr<Argument> Ptr;1459llvm::StringRef ArgName = Search->getName();14601461if (ArgName == "AlignedArgument")1462Ptr = std::make_unique<AlignedArgument>(Arg, Attr);1463else if (ArgName == "EnumArgument")1464Ptr = std::make_unique<EnumArgument>(Arg, Attr);1465else if (ArgName == "ExprArgument")1466Ptr = std::make_unique<ExprArgument>(Arg, Attr);1467else if (ArgName == "DeclArgument")1468Ptr = std::make_unique<SimpleArgument>(1469Arg, Attr, (Arg.getValueAsDef("Kind")->getName() + "Decl *").str());1470else if (ArgName == "IdentifierArgument")1471Ptr = std::make_unique<SimpleArgument>(Arg, Attr, "IdentifierInfo *");1472else if (ArgName == "DefaultBoolArgument")1473Ptr = std::make_unique<DefaultSimpleArgument>(1474Arg, Attr, "bool", Arg.getValueAsBit("Default"));1475else if (ArgName == "BoolArgument")1476Ptr = std::make_unique<SimpleArgument>(Arg, Attr, "bool");1477else if (ArgName == "DefaultIntArgument")1478Ptr = std::make_unique<DefaultSimpleArgument>(1479Arg, Attr, "int", Arg.getValueAsInt("Default"));1480else if (ArgName == "IntArgument")1481Ptr = std::make_unique<SimpleArgument>(Arg, Attr, "int");1482else if (ArgName == "StringArgument")1483Ptr = std::make_unique<StringArgument>(Arg, Attr);1484else if (ArgName == "TypeArgument")1485Ptr = std::make_unique<TypeArgument>(Arg, Attr);1486else if (ArgName == "UnsignedArgument")1487Ptr = std::make_unique<SimpleArgument>(Arg, Attr, "unsigned");1488else if (ArgName == "VariadicUnsignedArgument")1489Ptr = std::make_unique<VariadicArgument>(Arg, Attr, "unsigned");1490else if (ArgName == "VariadicStringArgument")1491Ptr = std::make_unique<VariadicStringArgument>(Arg, Attr);1492else if (ArgName == "VariadicEnumArgument")1493Ptr = std::make_unique<VariadicEnumArgument>(Arg, Attr);1494else if (ArgName == "VariadicExprArgument")1495Ptr = std::make_unique<VariadicExprArgument>(Arg, Attr);1496else if (ArgName == "VariadicParamIdxArgument")1497Ptr = std::make_unique<VariadicParamIdxArgument>(Arg, Attr);1498else if (ArgName == "VariadicParamOrParamIdxArgument")1499Ptr = std::make_unique<VariadicParamOrParamIdxArgument>(Arg, Attr);1500else if (ArgName == "ParamIdxArgument")1501Ptr = std::make_unique<SimpleArgument>(Arg, Attr, "ParamIdx");1502else if (ArgName == "VariadicIdentifierArgument")1503Ptr = std::make_unique<VariadicIdentifierArgument>(Arg, Attr);1504else if (ArgName == "VersionArgument")1505Ptr = std::make_unique<VersionArgument>(Arg, Attr);1506else if (ArgName == "WrappedAttr")1507Ptr = std::make_unique<WrappedAttr>(Arg, Attr);1508else if (ArgName == "OMPTraitInfoArgument")1509Ptr = std::make_unique<SimpleArgument>(Arg, Attr, "OMPTraitInfo *");1510else if (ArgName == "VariadicOMPInteropInfoArgument")1511Ptr = std::make_unique<VariadicOMPInteropInfoArgument>(Arg, Attr);15121513if (!Ptr) {1514// Search in reverse order so that the most-derived type is handled first.1515ArrayRef<std::pair<Record*, SMRange>> Bases = Search->getSuperClasses();1516for (const auto &Base : llvm::reverse(Bases)) {1517if ((Ptr = createArgument(Arg, Attr, Base.first)))1518break;1519}1520}15211522if (Ptr && Arg.getValueAsBit("Optional"))1523Ptr->setOptional(true);15241525if (Ptr && Arg.getValueAsBit("Fake"))1526Ptr->setFake(true);15271528return Ptr;1529}15301531static void writeAvailabilityValue(raw_ostream &OS) {1532OS << "\" << getPlatform()->getName();\n"1533<< " if (getStrict()) OS << \", strict\";\n"1534<< " if (!getIntroduced().empty()) OS << \", introduced=\" << getIntroduced();\n"1535<< " if (!getDeprecated().empty()) OS << \", deprecated=\" << getDeprecated();\n"1536<< " if (!getObsoleted().empty()) OS << \", obsoleted=\" << getObsoleted();\n"1537<< " if (getUnavailable()) OS << \", unavailable\";\n"1538<< " OS << \"";1539}15401541static void writeDeprecatedAttrValue(raw_ostream &OS, std::string &Variety) {1542OS << "\\\"\" << getMessage() << \"\\\"\";\n";1543// Only GNU deprecated has an optional fixit argument at the second position.1544if (Variety == "GNU")1545OS << " if (!getReplacement().empty()) OS << \", \\\"\""1546" << getReplacement() << \"\\\"\";\n";1547OS << " OS << \"";1548}15491550static void writeGetSpellingFunction(const Record &R, raw_ostream &OS) {1551std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);15521553OS << "const char *" << R.getName() << "Attr::getSpelling() const {\n";1554if (Spellings.empty()) {1555OS << " return \"(No spelling)\";\n}\n\n";1556return;1557}15581559OS << " switch (getAttributeSpellingListIndex()) {\n"1560" default:\n"1561" llvm_unreachable(\"Unknown attribute spelling!\");\n"1562" return \"(No spelling)\";\n";15631564for (unsigned I = 0; I < Spellings.size(); ++I)1565OS << " case " << I << ":\n"1566" return \"" << Spellings[I].name() << "\";\n";1567// End of the switch statement.1568OS << " }\n";1569// End of the getSpelling function.1570OS << "}\n\n";1571}15721573static void1574writePrettyPrintFunction(const Record &R,1575const std::vector<std::unique_ptr<Argument>> &Args,1576raw_ostream &OS) {1577std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);15781579OS << "void " << R.getName() << "Attr::printPretty("1580<< "raw_ostream &OS, const PrintingPolicy &Policy) const {\n";15811582if (Spellings.empty()) {1583OS << "}\n\n";1584return;1585}15861587OS << " bool IsFirstArgument = true; (void)IsFirstArgument;\n"1588<< " unsigned TrailingOmittedArgs = 0; (void)TrailingOmittedArgs;\n"1589<< " switch (getAttributeSpellingListIndex()) {\n"1590<< " default:\n"1591<< " llvm_unreachable(\"Unknown attribute spelling!\");\n"1592<< " break;\n";15931594for (unsigned I = 0; I < Spellings.size(); ++ I) {1595llvm::SmallString<16> Prefix;1596llvm::SmallString<8> Suffix;1597// The actual spelling of the name and namespace (if applicable)1598// of an attribute without considering prefix and suffix.1599llvm::SmallString<64> Spelling;1600std::string Name = Spellings[I].name();1601std::string Variety = Spellings[I].variety();16021603if (Variety == "GNU") {1604Prefix = "__attribute__((";1605Suffix = "))";1606} else if (Variety == "CXX11" || Variety == "C23") {1607Prefix = "[[";1608Suffix = "]]";1609std::string Namespace = Spellings[I].nameSpace();1610if (!Namespace.empty()) {1611Spelling += Namespace;1612Spelling += "::";1613}1614} else if (Variety == "Declspec") {1615Prefix = "__declspec(";1616Suffix = ")";1617} else if (Variety == "Microsoft") {1618Prefix = "[";1619Suffix = "]";1620} else if (Variety == "Keyword") {1621Prefix = "";1622Suffix = "";1623} else if (Variety == "Pragma") {1624Prefix = "#pragma ";1625Suffix = "\n";1626std::string Namespace = Spellings[I].nameSpace();1627if (!Namespace.empty()) {1628Spelling += Namespace;1629Spelling += " ";1630}1631} else if (Variety == "HLSLAnnotation") {1632Prefix = ":";1633Suffix = "";1634} else {1635llvm_unreachable("Unknown attribute syntax variety!");1636}16371638Spelling += Name;16391640OS << " case " << I << " : {\n"1641<< " OS << \"" << Prefix << Spelling << "\";\n";16421643if (Variety == "Pragma") {1644OS << " printPrettyPragma(OS, Policy);\n";1645OS << " OS << \"\\n\";";1646OS << " break;\n";1647OS << " }\n";1648continue;1649}16501651if (Spelling == "availability") {1652OS << " OS << \"(";1653writeAvailabilityValue(OS);1654OS << ")\";\n";1655} else if (Spelling == "deprecated" || Spelling == "gnu::deprecated") {1656OS << " OS << \"(";1657writeDeprecatedAttrValue(OS, Variety);1658OS << ")\";\n";1659} else {1660// To avoid printing parentheses around an empty argument list or1661// printing spurious commas at the end of an argument list, we need to1662// determine where the last provided non-fake argument is.1663bool FoundNonOptArg = false;1664for (const auto &arg : llvm::reverse(Args)) {1665if (arg->isFake())1666continue;1667if (FoundNonOptArg)1668continue;1669// FIXME: arg->getIsOmitted() == "false" means we haven't implemented1670// any way to detect whether the argument was omitted.1671if (!arg->isOptional() || arg->getIsOmitted() == "false") {1672FoundNonOptArg = true;1673continue;1674}1675OS << " if (" << arg->getIsOmitted() << ")\n"1676<< " ++TrailingOmittedArgs;\n";1677}1678unsigned ArgIndex = 0;1679for (const auto &arg : Args) {1680if (arg->isFake())1681continue;1682std::string IsOmitted = arg->getIsOmitted();1683if (arg->isOptional() && IsOmitted != "false")1684OS << " if (!(" << IsOmitted << ")) {\n";1685// Variadic arguments print their own leading comma.1686if (!arg->isVariadic())1687OS << " DelimitAttributeArgument(OS, IsFirstArgument);\n";1688OS << " OS << \"";1689arg->writeValue(OS);1690OS << "\";\n";1691if (arg->isOptional() && IsOmitted != "false")1692OS << " }\n";1693++ArgIndex;1694}1695if (ArgIndex != 0)1696OS << " if (!IsFirstArgument)\n"1697<< " OS << \")\";\n";1698}1699OS << " OS << \"" << Suffix << "\";\n"1700<< " break;\n"1701<< " }\n";1702}17031704// End of the switch statement.1705OS << "}\n";1706// End of the print function.1707OS << "}\n\n";1708}17091710/// Return the index of a spelling in a spelling list.1711static unsigned1712getSpellingListIndex(const std::vector<FlattenedSpelling> &SpellingList,1713const FlattenedSpelling &Spelling) {1714assert(!SpellingList.empty() && "Spelling list is empty!");17151716for (unsigned Index = 0; Index < SpellingList.size(); ++Index) {1717const FlattenedSpelling &S = SpellingList[Index];1718if (S.variety() != Spelling.variety())1719continue;1720if (S.nameSpace() != Spelling.nameSpace())1721continue;1722if (S.name() != Spelling.name())1723continue;17241725return Index;1726}17271728llvm_unreachable("Unknown spelling!");1729}17301731static void writeAttrAccessorDefinition(const Record &R, raw_ostream &OS) {1732std::vector<Record*> Accessors = R.getValueAsListOfDefs("Accessors");1733if (Accessors.empty())1734return;17351736const std::vector<FlattenedSpelling> SpellingList = GetFlattenedSpellings(R);1737assert(!SpellingList.empty() &&1738"Attribute with empty spelling list can't have accessors!");1739for (const auto *Accessor : Accessors) {1740const StringRef Name = Accessor->getValueAsString("Name");1741std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Accessor);17421743OS << " bool " << Name1744<< "() const { return getAttributeSpellingListIndex() == ";1745for (unsigned Index = 0; Index < Spellings.size(); ++Index) {1746OS << getSpellingListIndex(SpellingList, Spellings[Index]);1747if (Index != Spellings.size() - 1)1748OS << " ||\n getAttributeSpellingListIndex() == ";1749else1750OS << "; }\n";1751}1752}1753}17541755static bool1756SpellingNamesAreCommon(const std::vector<FlattenedSpelling>& Spellings) {1757assert(!Spellings.empty() && "An empty list of spellings was provided");1758std::string FirstName =1759std::string(NormalizeNameForSpellingComparison(Spellings.front().name()));1760for (const auto &Spelling : llvm::drop_begin(Spellings)) {1761std::string Name =1762std::string(NormalizeNameForSpellingComparison(Spelling.name()));1763if (Name != FirstName)1764return false;1765}1766return true;1767}17681769typedef std::map<unsigned, std::string> SemanticSpellingMap;1770static std::string1771CreateSemanticSpellings(const std::vector<FlattenedSpelling> &Spellings,1772SemanticSpellingMap &Map) {1773// The enumerants are automatically generated based on the variety,1774// namespace (if present) and name for each attribute spelling. However,1775// care is taken to avoid trampling on the reserved namespace due to1776// underscores.1777std::string Ret(" enum Spelling {\n");1778std::set<std::string> Uniques;1779unsigned Idx = 0;17801781// If we have a need to have this many spellings we likely need to add an1782// extra bit to the SpellingIndex in AttributeCommonInfo, then increase the1783// value of SpellingNotCalculated there and here.1784assert(Spellings.size() < 15 &&1785"Too many spellings, would step on SpellingNotCalculated in "1786"AttributeCommonInfo");1787for (auto I = Spellings.begin(), E = Spellings.end(); I != E; ++I, ++Idx) {1788const FlattenedSpelling &S = *I;1789const std::string &Variety = S.variety();1790const std::string &Spelling = S.name();1791const std::string &Namespace = S.nameSpace();1792std::string EnumName;17931794EnumName += (Variety + "_");1795if (!Namespace.empty())1796EnumName += (NormalizeNameForSpellingComparison(Namespace).str() +1797"_");1798EnumName += NormalizeNameForSpellingComparison(Spelling);17991800// Even if the name is not unique, this spelling index corresponds to a1801// particular enumerant name that we've calculated.1802Map[Idx] = EnumName;18031804// Since we have been stripping underscores to avoid trampling on the1805// reserved namespace, we may have inadvertently created duplicate1806// enumerant names. These duplicates are not considered part of the1807// semantic spelling, and can be elided.1808if (Uniques.find(EnumName) != Uniques.end())1809continue;18101811Uniques.insert(EnumName);1812if (I != Spellings.begin())1813Ret += ",\n";1814// Duplicate spellings are not considered part of the semantic spelling1815// enumeration, but the spelling index and semantic spelling values are1816// meant to be equivalent, so we must specify a concrete value for each1817// enumerator.1818Ret += " " + EnumName + " = " + llvm::utostr(Idx);1819}1820Ret += ",\n SpellingNotCalculated = 15\n";1821Ret += "\n };\n\n";1822return Ret;1823}18241825void WriteSemanticSpellingSwitch(const std::string &VarName,1826const SemanticSpellingMap &Map,1827raw_ostream &OS) {1828OS << " switch (" << VarName << ") {\n default: "1829<< "llvm_unreachable(\"Unknown spelling list index\");\n";1830for (const auto &I : Map)1831OS << " case " << I.first << ": return " << I.second << ";\n";1832OS << " }\n";1833}18341835// Note: these values need to match the values used by LateAttrParseKind in1836// `Attr.td`1837enum class LateAttrParseKind { Never = 0, Standard = 1, ExperimentalExt = 2 };18381839static LateAttrParseKind getLateAttrParseKind(const Record *Attr) {1840// This function basically does1841// `Attr->getValueAsDef("LateParsed")->getValueAsInt("Kind")` but does a bunch1842// of sanity checking to ensure that `LateAttrParseMode` in `Attr.td` is in1843// sync with the `LateAttrParseKind` enum in this source file.18441845static constexpr StringRef LateParsedStr = "LateParsed";1846static constexpr StringRef LateAttrParseKindStr = "LateAttrParseKind";1847static constexpr StringRef KindFieldStr = "Kind";18481849auto *LAPK = Attr->getValueAsDef(LateParsedStr);18501851// Typecheck the `LateParsed` field.1852SmallVector<Record *, 1> SuperClasses;1853LAPK->getDirectSuperClasses(SuperClasses);1854if (SuperClasses.size() != 1)1855PrintFatalError(Attr, "Field `" + llvm::Twine(LateParsedStr) +1856"`should only have one super class");18571858if (SuperClasses[0]->getName() != LateAttrParseKindStr)1859PrintFatalError(Attr, "Field `" + llvm::Twine(LateParsedStr) +1860"`should only have type `" +1861llvm::Twine(LateAttrParseKindStr) +1862"` but found type `" +1863SuperClasses[0]->getName() + "`");18641865// Get Kind and verify the enum name matches the name in `Attr.td`.1866unsigned Kind = LAPK->getValueAsInt(KindFieldStr);1867switch (LateAttrParseKind(Kind)) {1868#define CASE(X) \1869case LateAttrParseKind::X: \1870if (LAPK->getName().compare("LateAttrParse" #X) != 0) { \1871PrintFatalError(Attr, \1872"Field `" + llvm::Twine(LateParsedStr) + "` set to `" + \1873LAPK->getName() + \1874"` but this converts to `LateAttrParseKind::" + \1875llvm::Twine(#X) + "`"); \1876} \1877return LateAttrParseKind::X;18781879CASE(Never)1880CASE(Standard)1881CASE(ExperimentalExt)1882#undef CASE1883}18841885// The Kind value is completely invalid1886auto KindValueStr = llvm::utostr(Kind);1887PrintFatalError(Attr, "Field `" + llvm::Twine(LateParsedStr) + "` set to `" +1888LAPK->getName() + "` has unexpected `" +1889llvm::Twine(KindFieldStr) + "` value of " +1890KindValueStr);1891}18921893// Emits the LateParsed property for attributes.1894static void emitClangAttrLateParsedListImpl(RecordKeeper &Records,1895raw_ostream &OS,1896LateAttrParseKind LateParseMode) {1897std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");18981899for (const auto *Attr : Attrs) {1900if (LateAttrParseKind LateParsed = getLateAttrParseKind(Attr);1901LateParsed != LateParseMode)1902continue;19031904std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr);19051906// FIXME: Handle non-GNU attributes1907for (const auto &I : Spellings) {1908if (I.variety() != "GNU")1909continue;1910OS << ".Case(\"" << I.name() << "\", 1)\n";1911}1912}1913}19141915static void emitClangAttrLateParsedList(RecordKeeper &Records,1916raw_ostream &OS) {1917OS << "#if defined(CLANG_ATTR_LATE_PARSED_LIST)\n";1918emitClangAttrLateParsedListImpl(Records, OS, LateAttrParseKind::Standard);1919OS << "#endif // CLANG_ATTR_LATE_PARSED_LIST\n\n";1920}19211922static void emitClangAttrLateParsedExperimentalList(RecordKeeper &Records,1923raw_ostream &OS) {1924OS << "#if defined(CLANG_ATTR_LATE_PARSED_EXPERIMENTAL_EXT_LIST)\n";1925emitClangAttrLateParsedListImpl(Records, OS,1926LateAttrParseKind::ExperimentalExt);1927OS << "#endif // CLANG_ATTR_LATE_PARSED_EXPERIMENTAL_EXT_LIST\n\n";1928}19291930static bool hasGNUorCXX11Spelling(const Record &Attribute) {1931std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attribute);1932for (const auto &I : Spellings) {1933if (I.variety() == "GNU" || I.variety() == "CXX11")1934return true;1935}1936return false;1937}19381939namespace {19401941struct AttributeSubjectMatchRule {1942const Record *MetaSubject;1943const Record *Constraint;19441945AttributeSubjectMatchRule(const Record *MetaSubject, const Record *Constraint)1946: MetaSubject(MetaSubject), Constraint(Constraint) {1947assert(MetaSubject && "Missing subject");1948}19491950bool isSubRule() const { return Constraint != nullptr; }19511952std::vector<Record *> getSubjects() const {1953return (Constraint ? Constraint : MetaSubject)1954->getValueAsListOfDefs("Subjects");1955}19561957std::vector<Record *> getLangOpts() const {1958if (Constraint) {1959// Lookup the options in the sub-rule first, in case the sub-rule1960// overrides the rules options.1961std::vector<Record *> Opts = Constraint->getValueAsListOfDefs("LangOpts");1962if (!Opts.empty())1963return Opts;1964}1965return MetaSubject->getValueAsListOfDefs("LangOpts");1966}19671968// Abstract rules are used only for sub-rules1969bool isAbstractRule() const { return getSubjects().empty(); }19701971StringRef getName() const {1972return (Constraint ? Constraint : MetaSubject)->getValueAsString("Name");1973}19741975bool isNegatedSubRule() const {1976assert(isSubRule() && "Not a sub-rule");1977return Constraint->getValueAsBit("Negated");1978}19791980std::string getSpelling() const {1981std::string Result = std::string(MetaSubject->getValueAsString("Name"));1982if (isSubRule()) {1983Result += '(';1984if (isNegatedSubRule())1985Result += "unless(";1986Result += getName();1987if (isNegatedSubRule())1988Result += ')';1989Result += ')';1990}1991return Result;1992}19931994std::string getEnumValueName() const {1995SmallString<128> Result;1996Result += "SubjectMatchRule_";1997Result += MetaSubject->getValueAsString("Name");1998if (isSubRule()) {1999Result += "_";2000if (isNegatedSubRule())2001Result += "not_";2002Result += Constraint->getValueAsString("Name");2003}2004if (isAbstractRule())2005Result += "_abstract";2006return std::string(Result);2007}20082009std::string getEnumValue() const { return "attr::" + getEnumValueName(); }20102011static const char *EnumName;2012};20132014const char *AttributeSubjectMatchRule::EnumName = "attr::SubjectMatchRule";20152016struct PragmaClangAttributeSupport {2017std::vector<AttributeSubjectMatchRule> Rules;20182019class RuleOrAggregateRuleSet {2020std::vector<AttributeSubjectMatchRule> Rules;2021bool IsRule;2022RuleOrAggregateRuleSet(ArrayRef<AttributeSubjectMatchRule> Rules,2023bool IsRule)2024: Rules(Rules), IsRule(IsRule) {}20252026public:2027bool isRule() const { return IsRule; }20282029const AttributeSubjectMatchRule &getRule() const {2030assert(IsRule && "not a rule!");2031return Rules[0];2032}20332034ArrayRef<AttributeSubjectMatchRule> getAggregateRuleSet() const {2035return Rules;2036}20372038static RuleOrAggregateRuleSet2039getRule(const AttributeSubjectMatchRule &Rule) {2040return RuleOrAggregateRuleSet(Rule, /*IsRule=*/true);2041}2042static RuleOrAggregateRuleSet2043getAggregateRuleSet(ArrayRef<AttributeSubjectMatchRule> Rules) {2044return RuleOrAggregateRuleSet(Rules, /*IsRule=*/false);2045}2046};2047llvm::DenseMap<const Record *, RuleOrAggregateRuleSet> SubjectsToRules;20482049PragmaClangAttributeSupport(RecordKeeper &Records);20502051bool isAttributedSupported(const Record &Attribute);20522053void emitMatchRuleList(raw_ostream &OS);20542055void generateStrictConformsTo(const Record &Attr, raw_ostream &OS);20562057void generateParsingHelpers(raw_ostream &OS);2058};20592060} // end anonymous namespace20612062static bool isSupportedPragmaClangAttributeSubject(const Record &Subject) {2063// FIXME: #pragma clang attribute does not currently support statement2064// attributes, so test whether the subject is one that appertains to a2065// declaration node. However, it may be reasonable for support for statement2066// attributes to be added.2067if (Subject.isSubClassOf("DeclNode") || Subject.isSubClassOf("DeclBase") ||2068Subject.getName() == "DeclBase")2069return true;20702071if (Subject.isSubClassOf("SubsetSubject"))2072return isSupportedPragmaClangAttributeSubject(2073*Subject.getValueAsDef("Base"));20742075return false;2076}20772078static bool doesDeclDeriveFrom(const Record *D, const Record *Base) {2079const Record *CurrentBase = D->getValueAsOptionalDef(BaseFieldName);2080if (!CurrentBase)2081return false;2082if (CurrentBase == Base)2083return true;2084return doesDeclDeriveFrom(CurrentBase, Base);2085}20862087PragmaClangAttributeSupport::PragmaClangAttributeSupport(2088RecordKeeper &Records) {2089std::vector<Record *> MetaSubjects =2090Records.getAllDerivedDefinitions("AttrSubjectMatcherRule");2091auto MapFromSubjectsToRules = [this](const Record *SubjectContainer,2092const Record *MetaSubject,2093const Record *Constraint) {2094Rules.emplace_back(MetaSubject, Constraint);2095std::vector<Record *> ApplicableSubjects =2096SubjectContainer->getValueAsListOfDefs("Subjects");2097for (const auto *Subject : ApplicableSubjects) {2098bool Inserted =2099SubjectsToRules2100.try_emplace(Subject, RuleOrAggregateRuleSet::getRule(2101AttributeSubjectMatchRule(MetaSubject,2102Constraint)))2103.second;2104if (!Inserted) {2105PrintFatalError("Attribute subject match rules should not represent"2106"same attribute subjects.");2107}2108}2109};2110for (const auto *MetaSubject : MetaSubjects) {2111MapFromSubjectsToRules(MetaSubject, MetaSubject, /*Constraints=*/nullptr);2112std::vector<Record *> Constraints =2113MetaSubject->getValueAsListOfDefs("Constraints");2114for (const auto *Constraint : Constraints)2115MapFromSubjectsToRules(Constraint, MetaSubject, Constraint);2116}21172118std::vector<Record *> Aggregates =2119Records.getAllDerivedDefinitions("AttrSubjectMatcherAggregateRule");2120std::vector<Record *> DeclNodes =2121Records.getAllDerivedDefinitions(DeclNodeClassName);2122for (const auto *Aggregate : Aggregates) {2123Record *SubjectDecl = Aggregate->getValueAsDef("Subject");21242125// Gather sub-classes of the aggregate subject that act as attribute2126// subject rules.2127std::vector<AttributeSubjectMatchRule> Rules;2128for (const auto *D : DeclNodes) {2129if (doesDeclDeriveFrom(D, SubjectDecl)) {2130auto It = SubjectsToRules.find(D);2131if (It == SubjectsToRules.end())2132continue;2133if (!It->second.isRule() || It->second.getRule().isSubRule())2134continue; // Assume that the rule will be included as well.2135Rules.push_back(It->second.getRule());2136}2137}21382139bool Inserted =2140SubjectsToRules2141.try_emplace(SubjectDecl,2142RuleOrAggregateRuleSet::getAggregateRuleSet(Rules))2143.second;2144if (!Inserted) {2145PrintFatalError("Attribute subject match rules should not represent"2146"same attribute subjects.");2147}2148}2149}21502151static PragmaClangAttributeSupport &2152getPragmaAttributeSupport(RecordKeeper &Records) {2153static PragmaClangAttributeSupport Instance(Records);2154return Instance;2155}21562157void PragmaClangAttributeSupport::emitMatchRuleList(raw_ostream &OS) {2158OS << "#ifndef ATTR_MATCH_SUB_RULE\n";2159OS << "#define ATTR_MATCH_SUB_RULE(Value, Spelling, IsAbstract, Parent, "2160"IsNegated) "2161<< "ATTR_MATCH_RULE(Value, Spelling, IsAbstract)\n";2162OS << "#endif\n";2163for (const auto &Rule : Rules) {2164OS << (Rule.isSubRule() ? "ATTR_MATCH_SUB_RULE" : "ATTR_MATCH_RULE") << '(';2165OS << Rule.getEnumValueName() << ", \"" << Rule.getSpelling() << "\", "2166<< Rule.isAbstractRule();2167if (Rule.isSubRule())2168OS << ", "2169<< AttributeSubjectMatchRule(Rule.MetaSubject, nullptr).getEnumValue()2170<< ", " << Rule.isNegatedSubRule();2171OS << ")\n";2172}2173OS << "#undef ATTR_MATCH_SUB_RULE\n";2174}21752176bool PragmaClangAttributeSupport::isAttributedSupported(2177const Record &Attribute) {2178// If the attribute explicitly specified whether to support #pragma clang2179// attribute, use that setting.2180bool Unset;2181bool SpecifiedResult =2182Attribute.getValueAsBitOrUnset("PragmaAttributeSupport", Unset);2183if (!Unset)2184return SpecifiedResult;21852186// Opt-out rules:21872188// An attribute requires delayed parsing (LateParsed is on).2189switch (getLateAttrParseKind(&Attribute)) {2190case LateAttrParseKind::Never:2191break;2192case LateAttrParseKind::Standard:2193return false;2194case LateAttrParseKind::ExperimentalExt:2195// This is only late parsed in certain parsing contexts when2196// `LangOpts.ExperimentalLateParseAttributes` is true. Information about the2197// parsing context and `LangOpts` is not available in this method so just2198// opt this attribute out.2199return false;2200}22012202// An attribute has no GNU/CXX11 spelling2203if (!hasGNUorCXX11Spelling(Attribute))2204return false;2205// An attribute subject list has a subject that isn't covered by one of the2206// subject match rules or has no subjects at all.2207if (Attribute.isValueUnset("Subjects"))2208return false;2209const Record *SubjectObj = Attribute.getValueAsDef("Subjects");2210std::vector<Record *> Subjects = SubjectObj->getValueAsListOfDefs("Subjects");2211bool HasAtLeastOneValidSubject = false;2212for (const auto *Subject : Subjects) {2213if (!isSupportedPragmaClangAttributeSubject(*Subject))2214continue;2215if (!SubjectsToRules.contains(Subject))2216return false;2217HasAtLeastOneValidSubject = true;2218}2219return HasAtLeastOneValidSubject;2220}22212222static std::string GenerateTestExpression(ArrayRef<Record *> LangOpts) {2223std::string Test;22242225for (auto *E : LangOpts) {2226if (!Test.empty())2227Test += " || ";22282229const StringRef Code = E->getValueAsString("CustomCode");2230if (!Code.empty()) {2231Test += "(";2232Test += Code;2233Test += ")";2234if (!E->getValueAsString("Name").empty()) {2235PrintWarning(2236E->getLoc(),2237"non-empty 'Name' field ignored because 'CustomCode' was supplied");2238}2239} else {2240Test += "LangOpts.";2241Test += E->getValueAsString("Name");2242}2243}22442245if (Test.empty())2246return "true";22472248return Test;2249}22502251void2252PragmaClangAttributeSupport::generateStrictConformsTo(const Record &Attr,2253raw_ostream &OS) {2254if (!isAttributedSupported(Attr) || Attr.isValueUnset("Subjects"))2255return;2256// Generate a function that constructs a set of matching rules that describe2257// to which declarations the attribute should apply to.2258OS << "void getPragmaAttributeMatchRules("2259<< "llvm::SmallVectorImpl<std::pair<"2260<< AttributeSubjectMatchRule::EnumName2261<< ", bool>> &MatchRules, const LangOptions &LangOpts) const override {\n";2262const Record *SubjectObj = Attr.getValueAsDef("Subjects");2263std::vector<Record *> Subjects = SubjectObj->getValueAsListOfDefs("Subjects");2264for (const auto *Subject : Subjects) {2265if (!isSupportedPragmaClangAttributeSubject(*Subject))2266continue;2267auto It = SubjectsToRules.find(Subject);2268assert(It != SubjectsToRules.end() &&2269"This attribute is unsupported by #pragma clang attribute");2270for (const auto &Rule : It->getSecond().getAggregateRuleSet()) {2271// The rule might be language specific, so only subtract it from the given2272// rules if the specific language options are specified.2273std::vector<Record *> LangOpts = Rule.getLangOpts();2274OS << " MatchRules.push_back(std::make_pair(" << Rule.getEnumValue()2275<< ", /*IsSupported=*/" << GenerateTestExpression(LangOpts)2276<< "));\n";2277}2278}2279OS << "}\n\n";2280}22812282void PragmaClangAttributeSupport::generateParsingHelpers(raw_ostream &OS) {2283// Generate routines that check the names of sub-rules.2284OS << "std::optional<attr::SubjectMatchRule> "2285"defaultIsAttributeSubjectMatchSubRuleFor(StringRef, bool) {\n";2286OS << " return std::nullopt;\n";2287OS << "}\n\n";22882289llvm::MapVector<const Record *, std::vector<AttributeSubjectMatchRule>>2290SubMatchRules;2291for (const auto &Rule : Rules) {2292if (!Rule.isSubRule())2293continue;2294SubMatchRules[Rule.MetaSubject].push_back(Rule);2295}22962297for (const auto &SubMatchRule : SubMatchRules) {2298OS << "std::optional<attr::SubjectMatchRule> "2299"isAttributeSubjectMatchSubRuleFor_"2300<< SubMatchRule.first->getValueAsString("Name")2301<< "(StringRef Name, bool IsUnless) {\n";2302OS << " if (IsUnless)\n";2303OS << " return "2304"llvm::StringSwitch<std::optional<attr::SubjectMatchRule>>(Name).\n";2305for (const auto &Rule : SubMatchRule.second) {2306if (Rule.isNegatedSubRule())2307OS << " Case(\"" << Rule.getName() << "\", " << Rule.getEnumValue()2308<< ").\n";2309}2310OS << " Default(std::nullopt);\n";2311OS << " return "2312"llvm::StringSwitch<std::optional<attr::SubjectMatchRule>>(Name).\n";2313for (const auto &Rule : SubMatchRule.second) {2314if (!Rule.isNegatedSubRule())2315OS << " Case(\"" << Rule.getName() << "\", " << Rule.getEnumValue()2316<< ").\n";2317}2318OS << " Default(std::nullopt);\n";2319OS << "}\n\n";2320}23212322// Generate the function that checks for the top-level rules.2323OS << "std::pair<std::optional<attr::SubjectMatchRule>, "2324"std::optional<attr::SubjectMatchRule> (*)(StringRef, "2325"bool)> isAttributeSubjectMatchRule(StringRef Name) {\n";2326OS << " return "2327"llvm::StringSwitch<std::pair<std::optional<attr::SubjectMatchRule>, "2328"std::optional<attr::SubjectMatchRule> (*) (StringRef, "2329"bool)>>(Name).\n";2330for (const auto &Rule : Rules) {2331if (Rule.isSubRule())2332continue;2333std::string SubRuleFunction;2334if (SubMatchRules.count(Rule.MetaSubject))2335SubRuleFunction =2336("isAttributeSubjectMatchSubRuleFor_" + Rule.getName()).str();2337else2338SubRuleFunction = "defaultIsAttributeSubjectMatchSubRuleFor";2339OS << " Case(\"" << Rule.getName() << "\", std::make_pair("2340<< Rule.getEnumValue() << ", " << SubRuleFunction << ")).\n";2341}2342OS << " Default(std::make_pair(std::nullopt, "2343"defaultIsAttributeSubjectMatchSubRuleFor));\n";2344OS << "}\n\n";23452346// Generate the function that checks for the submatch rules.2347OS << "const char *validAttributeSubjectMatchSubRules("2348<< AttributeSubjectMatchRule::EnumName << " Rule) {\n";2349OS << " switch (Rule) {\n";2350for (const auto &SubMatchRule : SubMatchRules) {2351OS << " case "2352<< AttributeSubjectMatchRule(SubMatchRule.first, nullptr).getEnumValue()2353<< ":\n";2354OS << " return \"'";2355bool IsFirst = true;2356for (const auto &Rule : SubMatchRule.second) {2357if (!IsFirst)2358OS << ", '";2359IsFirst = false;2360if (Rule.isNegatedSubRule())2361OS << "unless(";2362OS << Rule.getName();2363if (Rule.isNegatedSubRule())2364OS << ')';2365OS << "'";2366}2367OS << "\";\n";2368}2369OS << " default: return nullptr;\n";2370OS << " }\n";2371OS << "}\n\n";2372}23732374template <typename Fn>2375static void forEachUniqueSpelling(const Record &Attr, Fn &&F) {2376std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);2377SmallDenseSet<StringRef, 8> Seen;2378for (const FlattenedSpelling &S : Spellings) {2379if (Seen.insert(S.name()).second)2380F(S);2381}2382}23832384static bool isTypeArgument(const Record *Arg) {2385return !Arg->getSuperClasses().empty() &&2386Arg->getSuperClasses().back().first->getName() == "TypeArgument";2387}23882389/// Emits the first-argument-is-type property for attributes.2390static void emitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) {2391OS << "#if defined(CLANG_ATTR_TYPE_ARG_LIST)\n";2392std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");23932394for (const auto *Attr : Attrs) {2395// Determine whether the first argument is a type.2396std::vector<Record *> Args = Attr->getValueAsListOfDefs("Args");2397if (Args.empty())2398continue;23992400if (!isTypeArgument(Args[0]))2401continue;24022403// All these spellings take a single type argument.2404forEachUniqueSpelling(*Attr, [&](const FlattenedSpelling &S) {2405OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n";2406});2407}2408OS << "#endif // CLANG_ATTR_TYPE_ARG_LIST\n\n";2409}24102411/// Emits the parse-arguments-in-unevaluated-context property for2412/// attributes.2413static void emitClangAttrArgContextList(RecordKeeper &Records, raw_ostream &OS) {2414OS << "#if defined(CLANG_ATTR_ARG_CONTEXT_LIST)\n";2415ParsedAttrMap Attrs = getParsedAttrList(Records);2416for (const auto &I : Attrs) {2417const Record &Attr = *I.second;24182419if (!Attr.getValueAsBit("ParseArgumentsAsUnevaluated"))2420continue;24212422// All these spellings take are parsed unevaluated.2423forEachUniqueSpelling(Attr, [&](const FlattenedSpelling &S) {2424OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n";2425});2426}2427OS << "#endif // CLANG_ATTR_ARG_CONTEXT_LIST\n\n";2428}24292430static bool isIdentifierArgument(const Record *Arg) {2431return !Arg->getSuperClasses().empty() &&2432llvm::StringSwitch<bool>(Arg->getSuperClasses().back().first->getName())2433.Case("IdentifierArgument", true)2434.Case("EnumArgument", true)2435.Case("VariadicEnumArgument", true)2436.Default(false);2437}24382439static bool isVariadicIdentifierArgument(const Record *Arg) {2440return !Arg->getSuperClasses().empty() &&2441llvm::StringSwitch<bool>(2442Arg->getSuperClasses().back().first->getName())2443.Case("VariadicIdentifierArgument", true)2444.Case("VariadicParamOrParamIdxArgument", true)2445.Default(false);2446}24472448static bool isVariadicExprArgument(const Record *Arg) {2449return !Arg->getSuperClasses().empty() &&2450llvm::StringSwitch<bool>(2451Arg->getSuperClasses().back().first->getName())2452.Case("VariadicExprArgument", true)2453.Default(false);2454}24552456static bool isStringLiteralArgument(const Record *Arg) {2457if (Arg->getSuperClasses().empty())2458return false;2459StringRef ArgKind = Arg->getSuperClasses().back().first->getName();2460if (ArgKind == "EnumArgument")2461return Arg->getValueAsBit("IsString");2462return ArgKind == "StringArgument";2463}24642465static bool isVariadicStringLiteralArgument(const Record *Arg) {2466if (Arg->getSuperClasses().empty())2467return false;2468StringRef ArgKind = Arg->getSuperClasses().back().first->getName();2469if (ArgKind == "VariadicEnumArgument")2470return Arg->getValueAsBit("IsString");2471return ArgKind == "VariadicStringArgument";2472}24732474static void emitClangAttrVariadicIdentifierArgList(RecordKeeper &Records,2475raw_ostream &OS) {2476OS << "#if defined(CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST)\n";2477std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");2478for (const auto *A : Attrs) {2479// Determine whether the first argument is a variadic identifier.2480std::vector<Record *> Args = A->getValueAsListOfDefs("Args");2481if (Args.empty() || !isVariadicIdentifierArgument(Args[0]))2482continue;24832484// All these spellings take an identifier argument.2485forEachUniqueSpelling(*A, [&](const FlattenedSpelling &S) {2486OS << ".Case(\"" << S.name() << "\", "2487<< "true"2488<< ")\n";2489});2490}2491OS << "#endif // CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST\n\n";2492}24932494static bool GenerateTargetSpecificAttrChecks(const Record *R,2495std::vector<StringRef> &Arches,2496std::string &Test,2497std::string *FnName);24982499// Emits the list of arguments that should be parsed as unevaluated string2500// literals for each attribute.2501static void emitClangAttrUnevaluatedStringLiteralList(RecordKeeper &Records,2502raw_ostream &OS) {2503OS << "#if defined(CLANG_ATTR_STRING_LITERAL_ARG_LIST)\n";25042505auto MakeMask = [](ArrayRef<Record *> Args) {2506uint32_t Bits = 0;2507assert(Args.size() <= 32 && "unsupported number of arguments in attribute");2508for (uint32_t N = 0; N < Args.size(); ++N) {2509Bits |= (isStringLiteralArgument(Args[N]) << N);2510// If we have a variadic string argument, set all the remaining bits to 12511if (isVariadicStringLiteralArgument(Args[N])) {2512Bits |= maskTrailingZeros<decltype(Bits)>(N);2513break;2514}2515}2516return Bits;2517};25182519auto AddMaskWithTargetCheck = [](const Record *Attr, uint32_t Mask,2520std::string &MaskStr) {2521const Record *T = Attr->getValueAsDef("Target");2522std::vector<StringRef> Arches = T->getValueAsListOfStrings("Arches");2523std::string Test;2524GenerateTargetSpecificAttrChecks(T, Arches, Test, nullptr);2525MaskStr.append(Test + " ? " + std::to_string(Mask) + " : ");2526};25272528ParsedAttrMap Dupes;2529ParsedAttrMap Attrs = getParsedAttrList(Records, &Dupes, /*SemaOnly=*/false);2530for (const auto &[AttrName, Attr] : Attrs) {2531std::string MaskStr;2532if (Attr->isSubClassOf("TargetSpecificAttr") &&2533!Attr->isValueUnset("ParseKind")) {2534if (uint32_t Mask = MakeMask(Attr->getValueAsListOfDefs("Args")))2535AddMaskWithTargetCheck(Attr, Mask, MaskStr);2536StringRef ParseKind = Attr->getValueAsString("ParseKind");2537for (const auto &[DupeParseKind, DupAttr] : Dupes) {2538if (DupeParseKind != ParseKind)2539continue;2540if (uint32_t Mask = MakeMask(DupAttr->getValueAsListOfDefs("Args")))2541AddMaskWithTargetCheck(DupAttr, Mask, MaskStr);2542}2543if (!MaskStr.empty())2544MaskStr.append("0");2545} else {2546if (uint32_t Mask = MakeMask(Attr->getValueAsListOfDefs("Args")))2547MaskStr = std::to_string(Mask);2548}25492550if (MaskStr.empty())2551continue;25522553// All these spellings have at least one string literal has argument.2554forEachUniqueSpelling(*Attr, [&](const FlattenedSpelling &S) {2555OS << ".Case(\"" << S.name() << "\", " << MaskStr << ")\n";2556});2557}2558OS << "#endif // CLANG_ATTR_STRING_LITERAL_ARG_LIST\n\n";2559}25602561// Emits the first-argument-is-identifier property for attributes.2562static void emitClangAttrIdentifierArgList(RecordKeeper &Records, raw_ostream &OS) {2563OS << "#if defined(CLANG_ATTR_IDENTIFIER_ARG_LIST)\n";2564std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");25652566for (const auto *Attr : Attrs) {2567// Determine whether the first argument is an identifier.2568std::vector<Record *> Args = Attr->getValueAsListOfDefs("Args");2569if (Args.empty() || !isIdentifierArgument(Args[0]))2570continue;25712572// All these spellings take an identifier argument.2573forEachUniqueSpelling(*Attr, [&](const FlattenedSpelling &S) {2574OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n";2575});2576}2577OS << "#endif // CLANG_ATTR_IDENTIFIER_ARG_LIST\n\n";2578}25792580// Emits the indexed-argument-is-identifier property for attributes.2581static void emitClangAttrStrictIdentifierArgAtIndexList(RecordKeeper &Records,2582raw_ostream &OS) {2583OS << "#if defined(CLANG_ATTR_STRICT_IDENTIFIER_ARG_AT_INDEX_LIST)\n";2584std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");25852586for (const auto *Attr : Attrs) {2587if (!Attr->getValueAsBit("StrictEnumParameters"))2588continue;2589// Determine whether the first argument is an identifier.2590std::vector<Record *> Args = Attr->getValueAsListOfDefs("Args");2591uint64_t enumAtIndex = 0;2592for (size_t i = 0; i < Args.size(); i++) {2593enumAtIndex |= ((uint64_t)isIdentifierArgument(Args[0])) << i;2594}2595if (!enumAtIndex)2596continue;25972598// All these spellings take an identifier argument.2599forEachUniqueSpelling(*Attr, [&](const FlattenedSpelling &S) {2600OS << ".Case(\"" << S.name() << "\", " << enumAtIndex << "ull)\n";2601});2602}2603OS << "#endif // CLANG_ATTR_STRICT_IDENTIFIER_ARG_AT_INDEX_LIST\n\n";2604}26052606static bool keywordThisIsaIdentifierInArgument(const Record *Arg) {2607return !Arg->getSuperClasses().empty() &&2608llvm::StringSwitch<bool>(2609Arg->getSuperClasses().back().first->getName())2610.Case("VariadicParamOrParamIdxArgument", true)2611.Default(false);2612}26132614static void emitClangAttrThisIsaIdentifierArgList(RecordKeeper &Records,2615raw_ostream &OS) {2616OS << "#if defined(CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST)\n";2617std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");2618for (const auto *A : Attrs) {2619// Determine whether the first argument is a variadic identifier.2620std::vector<Record *> Args = A->getValueAsListOfDefs("Args");2621if (Args.empty() || !keywordThisIsaIdentifierInArgument(Args[0]))2622continue;26232624// All these spellings take an identifier argument.2625forEachUniqueSpelling(*A, [&](const FlattenedSpelling &S) {2626OS << ".Case(\"" << S.name() << "\", "2627<< "true"2628<< ")\n";2629});2630}2631OS << "#endif // CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST\n\n";2632}26332634static void emitClangAttrAcceptsExprPack(RecordKeeper &Records,2635raw_ostream &OS) {2636OS << "#if defined(CLANG_ATTR_ACCEPTS_EXPR_PACK)\n";2637ParsedAttrMap Attrs = getParsedAttrList(Records);2638for (const auto &I : Attrs) {2639const Record &Attr = *I.second;26402641if (!Attr.getValueAsBit("AcceptsExprPack"))2642continue;26432644forEachUniqueSpelling(Attr, [&](const FlattenedSpelling &S) {2645OS << ".Case(\"" << S.name() << "\", true)\n";2646});2647}2648OS << "#endif // CLANG_ATTR_ACCEPTS_EXPR_PACK\n\n";2649}26502651static bool isRegularKeywordAttribute(const FlattenedSpelling &S) {2652return (S.variety() == "Keyword" &&2653!S.getSpellingRecord().getValueAsBit("HasOwnParseRules"));2654}26552656static void emitFormInitializer(raw_ostream &OS,2657const FlattenedSpelling &Spelling,2658StringRef SpellingIndex) {2659bool IsAlignas =2660(Spelling.variety() == "Keyword" && Spelling.name() == "alignas");2661OS << "{AttributeCommonInfo::AS_" << Spelling.variety() << ", "2662<< SpellingIndex << ", " << (IsAlignas ? "true" : "false")2663<< " /*IsAlignas*/, "2664<< (isRegularKeywordAttribute(Spelling) ? "true" : "false")2665<< " /*IsRegularKeywordAttribute*/}";2666}26672668static void emitAttributes(RecordKeeper &Records, raw_ostream &OS,2669bool Header) {2670std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");2671ParsedAttrMap AttrMap = getParsedAttrList(Records);26722673// Helper to print the starting character of an attribute argument. If there2674// hasn't been an argument yet, it prints an opening parenthese; otherwise it2675// prints a comma.2676OS << "static inline void DelimitAttributeArgument("2677<< "raw_ostream& OS, bool& IsFirst) {\n"2678<< " if (IsFirst) {\n"2679<< " IsFirst = false;\n"2680<< " OS << \"(\";\n"2681<< " } else\n"2682<< " OS << \", \";\n"2683<< "}\n";26842685for (const auto *Attr : Attrs) {2686const Record &R = *Attr;26872688// FIXME: Currently, documentation is generated as-needed due to the fact2689// that there is no way to allow a generated project "reach into" the docs2690// directory (for instance, it may be an out-of-tree build). However, we want2691// to ensure that every attribute has a Documentation field, and produce an2692// error if it has been neglected. Otherwise, the on-demand generation which2693// happens server-side will fail. This code is ensuring that functionality,2694// even though this Emitter doesn't technically need the documentation.2695// When attribute documentation can be generated as part of the build2696// itself, this code can be removed.2697(void)R.getValueAsListOfDefs("Documentation");26982699if (!R.getValueAsBit("ASTNode"))2700continue;27012702ArrayRef<std::pair<Record *, SMRange>> Supers = R.getSuperClasses();2703assert(!Supers.empty() && "Forgot to specify a superclass for the attr");2704std::string SuperName;2705bool Inheritable = false;2706for (const auto &Super : llvm::reverse(Supers)) {2707const Record *R = Super.first;2708if (R->getName() != "TargetSpecificAttr" &&2709R->getName() != "DeclOrTypeAttr" && SuperName.empty())2710SuperName = std::string(R->getName());2711if (R->getName() == "InheritableAttr")2712Inheritable = true;2713}27142715if (Header)2716OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n";2717else2718OS << "\n// " << R.getName() << "Attr implementation\n\n";27192720std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");2721std::vector<std::unique_ptr<Argument>> Args;2722Args.reserve(ArgRecords.size());27232724bool AttrAcceptsExprPack = Attr->getValueAsBit("AcceptsExprPack");2725if (AttrAcceptsExprPack) {2726for (size_t I = 0; I < ArgRecords.size(); ++I) {2727const Record *ArgR = ArgRecords[I];2728if (isIdentifierArgument(ArgR) || isVariadicIdentifierArgument(ArgR) ||2729isTypeArgument(ArgR))2730PrintFatalError(Attr->getLoc(),2731"Attributes accepting packs cannot also "2732"have identifier or type arguments.");2733// When trying to determine if value-dependent expressions can populate2734// the attribute without prior instantiation, the decision is made based2735// on the assumption that only the last argument is ever variadic.2736if (I < (ArgRecords.size() - 1) && isVariadicExprArgument(ArgR))2737PrintFatalError(Attr->getLoc(),2738"Attributes accepting packs can only have the last "2739"argument be variadic.");2740}2741}27422743bool HasOptArg = false;2744bool HasFakeArg = false;2745for (const auto *ArgRecord : ArgRecords) {2746Args.emplace_back(createArgument(*ArgRecord, R.getName()));2747if (Header) {2748Args.back()->writeDeclarations(OS);2749OS << "\n\n";2750}27512752// For these purposes, fake takes priority over optional.2753if (Args.back()->isFake()) {2754HasFakeArg = true;2755} else if (Args.back()->isOptional()) {2756HasOptArg = true;2757}2758}27592760std::unique_ptr<VariadicExprArgument> DelayedArgs = nullptr;2761if (AttrAcceptsExprPack) {2762DelayedArgs =2763std::make_unique<VariadicExprArgument>("DelayedArgs", R.getName());2764if (Header) {2765DelayedArgs->writeDeclarations(OS);2766OS << "\n\n";2767}2768}27692770if (Header)2771OS << "public:\n";27722773std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);27742775// If there are zero or one spellings, all spelling-related functionality2776// can be elided. If all of the spellings share the same name, the spelling2777// functionality can also be elided.2778bool ElideSpelling = (Spellings.size() <= 1) ||2779SpellingNamesAreCommon(Spellings);27802781// This maps spelling index values to semantic Spelling enumerants.2782SemanticSpellingMap SemanticToSyntacticMap;27832784std::string SpellingEnum;2785if (Spellings.size() > 1)2786SpellingEnum = CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);2787if (Header)2788OS << SpellingEnum;27892790const auto &ParsedAttrSpellingItr = llvm::find_if(2791AttrMap, [R](const std::pair<std::string, const Record *> &P) {2792return &R == P.second;2793});27942795// Emit CreateImplicit factory methods.2796auto emitCreate = [&](bool Implicit, bool DelayedArgsOnly, bool emitFake) {2797if (Header)2798OS << " static ";2799OS << R.getName() << "Attr *";2800if (!Header)2801OS << R.getName() << "Attr::";2802OS << "Create";2803if (Implicit)2804OS << "Implicit";2805if (DelayedArgsOnly)2806OS << "WithDelayedArgs";2807OS << "(";2808OS << "ASTContext &Ctx";2809if (!DelayedArgsOnly) {2810for (auto const &ai : Args) {2811if (ai->isFake() && !emitFake)2812continue;2813OS << ", ";2814ai->writeCtorParameters(OS);2815}2816} else {2817OS << ", ";2818DelayedArgs->writeCtorParameters(OS);2819}2820OS << ", const AttributeCommonInfo &CommonInfo";2821OS << ")";2822if (Header) {2823OS << ";\n";2824return;2825}28262827OS << " {\n";2828OS << " auto *A = new (Ctx) " << R.getName();2829OS << "Attr(Ctx, CommonInfo";28302831if (!DelayedArgsOnly) {2832for (auto const &ai : Args) {2833if (ai->isFake() && !emitFake)2834continue;2835OS << ", ";2836ai->writeImplicitCtorArgs(OS);2837}2838}2839OS << ");\n";2840if (Implicit) {2841OS << " A->setImplicit(true);\n";2842}2843if (Implicit || ElideSpelling) {2844OS << " if (!A->isAttributeSpellingListCalculated() && "2845"!A->getAttrName())\n";2846OS << " A->setAttributeSpellingListIndex(0);\n";2847}2848if (DelayedArgsOnly) {2849OS << " A->setDelayedArgs(Ctx, ";2850DelayedArgs->writeImplicitCtorArgs(OS);2851OS << ");\n";2852}2853OS << " return A;\n}\n\n";2854};28552856auto emitCreateNoCI = [&](bool Implicit, bool DelayedArgsOnly,2857bool emitFake) {2858if (Header)2859OS << " static ";2860OS << R.getName() << "Attr *";2861if (!Header)2862OS << R.getName() << "Attr::";2863OS << "Create";2864if (Implicit)2865OS << "Implicit";2866if (DelayedArgsOnly)2867OS << "WithDelayedArgs";2868OS << "(";2869OS << "ASTContext &Ctx";2870if (!DelayedArgsOnly) {2871for (auto const &ai : Args) {2872if (ai->isFake() && !emitFake)2873continue;2874OS << ", ";2875ai->writeCtorParameters(OS);2876}2877} else {2878OS << ", ";2879DelayedArgs->writeCtorParameters(OS);2880}2881OS << ", SourceRange Range";2882if (Header)2883OS << " = {}";2884if (Spellings.size() > 1) {2885OS << ", Spelling S";2886if (Header)2887OS << " = " << SemanticToSyntacticMap[0];2888}2889OS << ")";2890if (Header) {2891OS << ";\n";2892return;2893}28942895OS << " {\n";2896OS << " AttributeCommonInfo I(Range, ";28972898if (ParsedAttrSpellingItr != std::end(AttrMap))2899OS << "AT_" << ParsedAttrSpellingItr->first;2900else2901OS << "NoSemaHandlerAttribute";29022903if (Spellings.size() == 0) {2904OS << ", AttributeCommonInfo::Form::Implicit()";2905} else if (Spellings.size() == 1) {2906OS << ", ";2907emitFormInitializer(OS, Spellings[0], "0");2908} else {2909OS << ", [&]() {\n";2910OS << " switch (S) {\n";2911std::set<std::string> Uniques;2912unsigned Idx = 0;2913for (auto I = Spellings.begin(), E = Spellings.end(); I != E;2914++I, ++Idx) {2915const FlattenedSpelling &S = *I;2916const auto &Name = SemanticToSyntacticMap[Idx];2917if (Uniques.insert(Name).second) {2918OS << " case " << Name << ":\n";2919OS << " return AttributeCommonInfo::Form";2920emitFormInitializer(OS, S, Name);2921OS << ";\n";2922}2923}2924OS << " default:\n";2925OS << " llvm_unreachable(\"Unknown attribute spelling!\");\n"2926<< " return AttributeCommonInfo::Form";2927emitFormInitializer(OS, Spellings[0], "0");2928OS << ";\n"2929<< " }\n"2930<< " }()";2931}29322933OS << ");\n";2934OS << " return Create";2935if (Implicit)2936OS << "Implicit";2937if (DelayedArgsOnly)2938OS << "WithDelayedArgs";2939OS << "(Ctx";2940if (!DelayedArgsOnly) {2941for (auto const &ai : Args) {2942if (ai->isFake() && !emitFake)2943continue;2944OS << ", ";2945ai->writeImplicitCtorArgs(OS);2946}2947} else {2948OS << ", ";2949DelayedArgs->writeImplicitCtorArgs(OS);2950}2951OS << ", I);\n";2952OS << "}\n\n";2953};29542955auto emitCreates = [&](bool DelayedArgsOnly, bool emitFake) {2956emitCreate(true, DelayedArgsOnly, emitFake);2957emitCreate(false, DelayedArgsOnly, emitFake);2958emitCreateNoCI(true, DelayedArgsOnly, emitFake);2959emitCreateNoCI(false, DelayedArgsOnly, emitFake);2960};29612962if (Header)2963OS << " // Factory methods\n";29642965// Emit a CreateImplicit that takes all the arguments.2966emitCreates(false, true);29672968// Emit a CreateImplicit that takes all the non-fake arguments.2969if (HasFakeArg)2970emitCreates(false, false);29712972// Emit a CreateWithDelayedArgs that takes only the dependent argument2973// expressions.2974if (DelayedArgs)2975emitCreates(true, false);29762977// Emit constructors.2978auto emitCtor = [&](bool emitOpt, bool emitFake, bool emitNoArgs) {2979auto shouldEmitArg = [=](const std::unique_ptr<Argument> &arg) {2980if (emitNoArgs)2981return false;2982if (arg->isFake())2983return emitFake;2984if (arg->isOptional())2985return emitOpt;2986return true;2987};2988if (Header)2989OS << " ";2990else2991OS << R.getName() << "Attr::";2992OS << R.getName()2993<< "Attr(ASTContext &Ctx, const AttributeCommonInfo &CommonInfo";2994OS << '\n';2995for (auto const &ai : Args) {2996if (!shouldEmitArg(ai))2997continue;2998OS << " , ";2999ai->writeCtorParameters(OS);3000OS << "\n";3001}30023003OS << " )";3004if (Header) {3005OS << ";\n";3006return;3007}3008OS << "\n : " << SuperName << "(Ctx, CommonInfo, ";3009OS << "attr::" << R.getName() << ", ";30103011// Handle different late parsing modes.3012OS << "/*IsLateParsed=*/";3013switch (getLateAttrParseKind(&R)) {3014case LateAttrParseKind::Never:3015OS << "false";3016break;3017case LateAttrParseKind::ExperimentalExt:3018// Currently no clients need to know the distinction between `Standard`3019// and `ExperimentalExt` so treat `ExperimentalExt` just like3020// `Standard` for now.3021case LateAttrParseKind::Standard:3022// Note: This is misleading. `IsLateParsed` doesn't mean the3023// attribute was actually late parsed. Instead it means the attribute in3024// `Attr.td` is marked as being late parsed. Maybe it should be called3025// `IsLateParseable`?3026OS << "true";3027break;3028}30293030if (Inheritable) {3031OS << ", "3032<< (R.getValueAsBit("InheritEvenIfAlreadyPresent") ? "true"3033: "false");3034}3035OS << ")\n";30363037for (auto const &ai : Args) {3038OS << " , ";3039if (!shouldEmitArg(ai)) {3040ai->writeCtorDefaultInitializers(OS);3041} else {3042ai->writeCtorInitializers(OS);3043}3044OS << "\n";3045}3046if (DelayedArgs) {3047OS << " , ";3048DelayedArgs->writeCtorDefaultInitializers(OS);3049OS << "\n";3050}30513052OS << " {\n";30533054for (auto const &ai : Args) {3055if (!shouldEmitArg(ai))3056continue;3057ai->writeCtorBody(OS);3058}3059OS << "}\n\n";3060};30613062if (Header)3063OS << "\n // Constructors\n";30643065// Emit a constructor that includes all the arguments.3066// This is necessary for cloning.3067emitCtor(true, true, false);30683069// Emit a constructor that takes all the non-fake arguments.3070if (HasFakeArg)3071emitCtor(true, false, false);30723073// Emit a constructor that takes all the non-fake, non-optional arguments.3074if (HasOptArg)3075emitCtor(false, false, false);30763077// Emit constructors that takes no arguments if none already exists.3078// This is used for delaying arguments.3079bool HasRequiredArgs =3080llvm::count_if(Args, [=](const std::unique_ptr<Argument> &arg) {3081return !arg->isFake() && !arg->isOptional();3082});3083if (DelayedArgs && HasRequiredArgs)3084emitCtor(false, false, true);30853086if (Header) {3087OS << '\n';3088OS << " " << R.getName() << "Attr *clone(ASTContext &C) const;\n";3089OS << " void printPretty(raw_ostream &OS,\n"3090<< " const PrintingPolicy &Policy) const;\n";3091OS << " const char *getSpelling() const;\n";3092}30933094if (!ElideSpelling) {3095assert(!SemanticToSyntacticMap.empty() && "Empty semantic mapping list");3096if (Header)3097OS << " Spelling getSemanticSpelling() const;\n";3098else {3099OS << R.getName() << "Attr::Spelling " << R.getName()3100<< "Attr::getSemanticSpelling() const {\n";3101WriteSemanticSpellingSwitch("getAttributeSpellingListIndex()",3102SemanticToSyntacticMap, OS);3103OS << "}\n";3104}3105}31063107if (Header)3108writeAttrAccessorDefinition(R, OS);31093110for (auto const &ai : Args) {3111if (Header) {3112ai->writeAccessors(OS);3113} else {3114ai->writeAccessorDefinitions(OS);3115}3116OS << "\n\n";31173118// Don't write conversion routines for fake arguments.3119if (ai->isFake()) continue;31203121if (ai->isEnumArg())3122static_cast<const EnumArgument *>(ai.get())->writeConversion(OS,3123Header);3124else if (ai->isVariadicEnumArg())3125static_cast<const VariadicEnumArgument *>(ai.get())->writeConversion(3126OS, Header);3127}31283129if (Header) {3130if (DelayedArgs) {3131DelayedArgs->writeAccessors(OS);3132DelayedArgs->writeSetter(OS);3133}31343135OS << R.getValueAsString("AdditionalMembers");3136OS << "\n\n";31373138OS << " static bool classof(const Attr *A) { return A->getKind() == "3139<< "attr::" << R.getName() << "; }\n";31403141OS << "};\n\n";3142} else {3143if (DelayedArgs)3144DelayedArgs->writeAccessorDefinitions(OS);31453146OS << R.getName() << "Attr *" << R.getName()3147<< "Attr::clone(ASTContext &C) const {\n";3148OS << " auto *A = new (C) " << R.getName() << "Attr(C, *this";3149for (auto const &ai : Args) {3150OS << ", ";3151ai->writeCloneArgs(OS);3152}3153OS << ");\n";3154OS << " A->Inherited = Inherited;\n";3155OS << " A->IsPackExpansion = IsPackExpansion;\n";3156OS << " A->setImplicit(Implicit);\n";3157if (DelayedArgs) {3158OS << " A->setDelayedArgs(C, ";3159DelayedArgs->writeCloneArgs(OS);3160OS << ");\n";3161}3162OS << " return A;\n}\n\n";31633164writePrettyPrintFunction(R, Args, OS);3165writeGetSpellingFunction(R, OS);3166}3167}3168}3169// Emits the class definitions for attributes.3170void clang::EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {3171emitSourceFileHeader("Attribute classes' definitions", OS, Records);31723173OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";3174OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";31753176emitAttributes(Records, OS, true);31773178OS << "#endif // LLVM_CLANG_ATTR_CLASSES_INC\n";3179}31803181// Emits the class method definitions for attributes.3182void clang::EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) {3183emitSourceFileHeader("Attribute classes' member function definitions", OS,3184Records);31853186emitAttributes(Records, OS, false);31873188std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");31893190// Instead of relying on virtual dispatch we just create a huge dispatch3191// switch. This is both smaller and faster than virtual functions.3192auto EmitFunc = [&](const char *Method) {3193OS << " switch (getKind()) {\n";3194for (const auto *Attr : Attrs) {3195const Record &R = *Attr;3196if (!R.getValueAsBit("ASTNode"))3197continue;31983199OS << " case attr::" << R.getName() << ":\n";3200OS << " return cast<" << R.getName() << "Attr>(this)->" << Method3201<< ";\n";3202}3203OS << " }\n";3204OS << " llvm_unreachable(\"Unexpected attribute kind!\");\n";3205OS << "}\n\n";3206};32073208OS << "const char *Attr::getSpelling() const {\n";3209EmitFunc("getSpelling()");32103211OS << "Attr *Attr::clone(ASTContext &C) const {\n";3212EmitFunc("clone(C)");32133214OS << "void Attr::printPretty(raw_ostream &OS, "3215"const PrintingPolicy &Policy) const {\n";3216EmitFunc("printPretty(OS, Policy)");3217}32183219static void emitAttrList(raw_ostream &OS, StringRef Class,3220const std::vector<Record*> &AttrList) {3221for (auto Cur : AttrList) {3222OS << Class << "(" << Cur->getName() << ")\n";3223}3224}32253226// Determines if an attribute has a Pragma spelling.3227static bool AttrHasPragmaSpelling(const Record *R) {3228std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*R);3229return llvm::any_of(Spellings, [](const FlattenedSpelling &S) {3230return S.variety() == "Pragma";3231});3232}32333234namespace {32353236struct AttrClassDescriptor {3237const char * const MacroName;3238const char * const TableGenName;3239};32403241} // end anonymous namespace32423243static const AttrClassDescriptor AttrClassDescriptors[] = {3244{ "ATTR", "Attr" },3245{ "TYPE_ATTR", "TypeAttr" },3246{ "STMT_ATTR", "StmtAttr" },3247{ "DECL_OR_STMT_ATTR", "DeclOrStmtAttr" },3248{ "INHERITABLE_ATTR", "InheritableAttr" },3249{ "DECL_OR_TYPE_ATTR", "DeclOrTypeAttr" },3250{ "INHERITABLE_PARAM_ATTR", "InheritableParamAttr" },3251{ "PARAMETER_ABI_ATTR", "ParameterABIAttr" },3252{ "HLSL_ANNOTATION_ATTR", "HLSLAnnotationAttr"}3253};32543255static void emitDefaultDefine(raw_ostream &OS, StringRef name,3256const char *superName) {3257OS << "#ifndef " << name << "\n";3258OS << "#define " << name << "(NAME) ";3259if (superName) OS << superName << "(NAME)";3260OS << "\n#endif\n\n";3261}32623263namespace {32643265/// A class of attributes.3266struct AttrClass {3267const AttrClassDescriptor &Descriptor;3268Record *TheRecord;3269AttrClass *SuperClass = nullptr;3270std::vector<AttrClass*> SubClasses;3271std::vector<Record*> Attrs;32723273AttrClass(const AttrClassDescriptor &Descriptor, Record *R)3274: Descriptor(Descriptor), TheRecord(R) {}32753276void emitDefaultDefines(raw_ostream &OS) const {3277// Default the macro unless this is a root class (i.e. Attr).3278if (SuperClass) {3279emitDefaultDefine(OS, Descriptor.MacroName,3280SuperClass->Descriptor.MacroName);3281}3282}32833284void emitUndefs(raw_ostream &OS) const {3285OS << "#undef " << Descriptor.MacroName << "\n";3286}32873288void emitAttrList(raw_ostream &OS) const {3289for (auto SubClass : SubClasses) {3290SubClass->emitAttrList(OS);3291}32923293::emitAttrList(OS, Descriptor.MacroName, Attrs);3294}32953296void classifyAttrOnRoot(Record *Attr) {3297bool result = classifyAttr(Attr);3298assert(result && "failed to classify on root"); (void) result;3299}33003301void emitAttrRange(raw_ostream &OS) const {3302OS << "ATTR_RANGE(" << Descriptor.TableGenName3303<< ", " << getFirstAttr()->getName()3304<< ", " << getLastAttr()->getName() << ")\n";3305}33063307private:3308bool classifyAttr(Record *Attr) {3309// Check all the subclasses.3310for (auto SubClass : SubClasses) {3311if (SubClass->classifyAttr(Attr))3312return true;3313}33143315// It's not more specific than this class, but it might still belong here.3316if (Attr->isSubClassOf(TheRecord)) {3317Attrs.push_back(Attr);3318return true;3319}33203321return false;3322}33233324Record *getFirstAttr() const {3325if (!SubClasses.empty())3326return SubClasses.front()->getFirstAttr();3327return Attrs.front();3328}33293330Record *getLastAttr() const {3331if (!Attrs.empty())3332return Attrs.back();3333return SubClasses.back()->getLastAttr();3334}3335};33363337/// The entire hierarchy of attribute classes.3338class AttrClassHierarchy {3339std::vector<std::unique_ptr<AttrClass>> Classes;33403341public:3342AttrClassHierarchy(RecordKeeper &Records) {3343// Find records for all the classes.3344for (auto &Descriptor : AttrClassDescriptors) {3345Record *ClassRecord = Records.getClass(Descriptor.TableGenName);3346AttrClass *Class = new AttrClass(Descriptor, ClassRecord);3347Classes.emplace_back(Class);3348}33493350// Link up the hierarchy.3351for (auto &Class : Classes) {3352if (AttrClass *SuperClass = findSuperClass(Class->TheRecord)) {3353Class->SuperClass = SuperClass;3354SuperClass->SubClasses.push_back(Class.get());3355}3356}33573358#ifndef NDEBUG3359for (auto i = Classes.begin(), e = Classes.end(); i != e; ++i) {3360assert((i == Classes.begin()) == ((*i)->SuperClass == nullptr) &&3361"only the first class should be a root class!");3362}3363#endif3364}33653366void emitDefaultDefines(raw_ostream &OS) const {3367for (auto &Class : Classes) {3368Class->emitDefaultDefines(OS);3369}3370}33713372void emitUndefs(raw_ostream &OS) const {3373for (auto &Class : Classes) {3374Class->emitUndefs(OS);3375}3376}33773378void emitAttrLists(raw_ostream &OS) const {3379// Just start from the root class.3380Classes[0]->emitAttrList(OS);3381}33823383void emitAttrRanges(raw_ostream &OS) const {3384for (auto &Class : Classes)3385Class->emitAttrRange(OS);3386}33873388void classifyAttr(Record *Attr) {3389// Add the attribute to the root class.3390Classes[0]->classifyAttrOnRoot(Attr);3391}33923393private:3394AttrClass *findClassByRecord(Record *R) const {3395for (auto &Class : Classes) {3396if (Class->TheRecord == R)3397return Class.get();3398}3399return nullptr;3400}34013402AttrClass *findSuperClass(Record *R) const {3403// TableGen flattens the superclass list, so we just need to walk it3404// in reverse.3405auto SuperClasses = R->getSuperClasses();3406for (signed i = 0, e = SuperClasses.size(); i != e; ++i) {3407auto SuperClass = findClassByRecord(SuperClasses[e - i - 1].first);3408if (SuperClass) return SuperClass;3409}3410return nullptr;3411}3412};34133414} // end anonymous namespace34153416namespace clang {34173418// Emits the enumeration list for attributes.3419void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) {3420emitSourceFileHeader("List of all attributes that Clang recognizes", OS,3421Records);34223423AttrClassHierarchy Hierarchy(Records);34243425// Add defaulting macro definitions.3426Hierarchy.emitDefaultDefines(OS);3427emitDefaultDefine(OS, "PRAGMA_SPELLING_ATTR", nullptr);34283429std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");3430std::vector<Record *> PragmaAttrs;3431for (auto *Attr : Attrs) {3432if (!Attr->getValueAsBit("ASTNode"))3433continue;34343435// Add the attribute to the ad-hoc groups.3436if (AttrHasPragmaSpelling(Attr))3437PragmaAttrs.push_back(Attr);34383439// Place it in the hierarchy.3440Hierarchy.classifyAttr(Attr);3441}34423443// Emit the main attribute list.3444Hierarchy.emitAttrLists(OS);34453446// Emit the ad hoc groups.3447emitAttrList(OS, "PRAGMA_SPELLING_ATTR", PragmaAttrs);34483449// Emit the attribute ranges.3450OS << "#ifdef ATTR_RANGE\n";3451Hierarchy.emitAttrRanges(OS);3452OS << "#undef ATTR_RANGE\n";3453OS << "#endif\n";34543455Hierarchy.emitUndefs(OS);3456OS << "#undef PRAGMA_SPELLING_ATTR\n";3457}34583459// Emits the enumeration list for attributes.3460void EmitClangAttrSubjectMatchRuleList(RecordKeeper &Records, raw_ostream &OS) {3461emitSourceFileHeader(3462"List of all attribute subject matching rules that Clang recognizes", OS,3463Records);3464PragmaClangAttributeSupport &PragmaAttributeSupport =3465getPragmaAttributeSupport(Records);3466emitDefaultDefine(OS, "ATTR_MATCH_RULE", nullptr);3467PragmaAttributeSupport.emitMatchRuleList(OS);3468OS << "#undef ATTR_MATCH_RULE\n";3469}34703471// Emits the code to read an attribute from a precompiled header.3472void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) {3473emitSourceFileHeader("Attribute deserialization code", OS, Records);34743475Record *InhClass = Records.getClass("InheritableAttr");3476std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"),3477ArgRecords;3478std::vector<std::unique_ptr<Argument>> Args;3479std::unique_ptr<VariadicExprArgument> DelayedArgs;34803481OS << " switch (Kind) {\n";3482for (const auto *Attr : Attrs) {3483const Record &R = *Attr;3484if (!R.getValueAsBit("ASTNode"))3485continue;34863487OS << " case attr::" << R.getName() << ": {\n";3488if (R.isSubClassOf(InhClass))3489OS << " bool isInherited = Record.readInt();\n";3490OS << " bool isImplicit = Record.readInt();\n";3491OS << " bool isPackExpansion = Record.readInt();\n";3492DelayedArgs = nullptr;3493if (Attr->getValueAsBit("AcceptsExprPack")) {3494DelayedArgs =3495std::make_unique<VariadicExprArgument>("DelayedArgs", R.getName());3496DelayedArgs->writePCHReadDecls(OS);3497}3498ArgRecords = R.getValueAsListOfDefs("Args");3499Args.clear();3500for (const auto *Arg : ArgRecords) {3501Args.emplace_back(createArgument(*Arg, R.getName()));3502Args.back()->writePCHReadDecls(OS);3503}3504OS << " New = new (Context) " << R.getName() << "Attr(Context, Info";3505for (auto const &ri : Args) {3506OS << ", ";3507ri->writePCHReadArgs(OS);3508}3509OS << ");\n";3510if (R.isSubClassOf(InhClass))3511OS << " cast<InheritableAttr>(New)->setInherited(isInherited);\n";3512OS << " New->setImplicit(isImplicit);\n";3513OS << " New->setPackExpansion(isPackExpansion);\n";3514if (DelayedArgs) {3515OS << " cast<" << R.getName()3516<< "Attr>(New)->setDelayedArgs(Context, ";3517DelayedArgs->writePCHReadArgs(OS);3518OS << ");\n";3519}3520OS << " break;\n";3521OS << " }\n";3522}3523OS << " }\n";3524}35253526// Emits the code to write an attribute to a precompiled header.3527void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) {3528emitSourceFileHeader("Attribute serialization code", OS, Records);35293530Record *InhClass = Records.getClass("InheritableAttr");3531std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;35323533OS << " switch (A->getKind()) {\n";3534for (const auto *Attr : Attrs) {3535const Record &R = *Attr;3536if (!R.getValueAsBit("ASTNode"))3537continue;3538OS << " case attr::" << R.getName() << ": {\n";3539Args = R.getValueAsListOfDefs("Args");3540if (R.isSubClassOf(InhClass) || !Args.empty())3541OS << " const auto *SA = cast<" << R.getName()3542<< "Attr>(A);\n";3543if (R.isSubClassOf(InhClass))3544OS << " Record.push_back(SA->isInherited());\n";3545OS << " Record.push_back(A->isImplicit());\n";3546OS << " Record.push_back(A->isPackExpansion());\n";3547if (Attr->getValueAsBit("AcceptsExprPack"))3548VariadicExprArgument("DelayedArgs", R.getName()).writePCHWrite(OS);35493550for (const auto *Arg : Args)3551createArgument(*Arg, R.getName())->writePCHWrite(OS);3552OS << " break;\n";3553OS << " }\n";3554}3555OS << " }\n";3556}35573558} // namespace clang35593560// Helper function for GenerateTargetSpecificAttrChecks that alters the 'Test'3561// parameter with only a single check type, if applicable.3562static bool GenerateTargetSpecificAttrCheck(const Record *R, std::string &Test,3563std::string *FnName,3564StringRef ListName,3565StringRef CheckAgainst,3566StringRef Scope) {3567if (!R->isValueUnset(ListName)) {3568Test += " && (";3569std::vector<StringRef> Items = R->getValueAsListOfStrings(ListName);3570for (auto I = Items.begin(), E = Items.end(); I != E; ++I) {3571StringRef Part = *I;3572Test += CheckAgainst;3573Test += " == ";3574Test += Scope;3575Test += Part;3576if (I + 1 != E)3577Test += " || ";3578if (FnName)3579*FnName += Part;3580}3581Test += ")";3582return true;3583}3584return false;3585}35863587// Generate a conditional expression to check if the current target satisfies3588// the conditions for a TargetSpecificAttr record, and append the code for3589// those checks to the Test string. If the FnName string pointer is non-null,3590// append a unique suffix to distinguish this set of target checks from other3591// TargetSpecificAttr records.3592static bool GenerateTargetSpecificAttrChecks(const Record *R,3593std::vector<StringRef> &Arches,3594std::string &Test,3595std::string *FnName) {3596bool AnyTargetChecks = false;35973598// It is assumed that there will be an llvm::Triple object3599// named "T" and a TargetInfo object named "Target" within3600// scope that can be used to determine whether the attribute exists in3601// a given target.3602Test += "true";3603// If one or more architectures is specified, check those. Arches are handled3604// differently because GenerateTargetRequirements needs to combine the list3605// with ParseKind.3606if (!Arches.empty()) {3607AnyTargetChecks = true;3608Test += " && (";3609for (auto I = Arches.begin(), E = Arches.end(); I != E; ++I) {3610StringRef Part = *I;3611Test += "T.getArch() == llvm::Triple::";3612Test += Part;3613if (I + 1 != E)3614Test += " || ";3615if (FnName)3616*FnName += Part;3617}3618Test += ")";3619}36203621// If the attribute is specific to particular OSes, check those.3622AnyTargetChecks |= GenerateTargetSpecificAttrCheck(3623R, Test, FnName, "OSes", "T.getOS()", "llvm::Triple::");36243625// If one or more object formats is specified, check those.3626AnyTargetChecks |=3627GenerateTargetSpecificAttrCheck(R, Test, FnName, "ObjectFormats",3628"T.getObjectFormat()", "llvm::Triple::");36293630// If custom code is specified, emit it.3631StringRef Code = R->getValueAsString("CustomCode");3632if (!Code.empty()) {3633AnyTargetChecks = true;3634Test += " && (";3635Test += Code;3636Test += ")";3637}36383639return AnyTargetChecks;3640}36413642static void GenerateHasAttrSpellingStringSwitch(3643const std::vector<std::pair<const Record *, FlattenedSpelling>> &Attrs,3644raw_ostream &OS, const std::string &Variety,3645const std::string &Scope = "") {3646for (const auto &[Attr, Spelling] : Attrs) {3647// C++11-style attributes have specific version information associated with3648// them. If the attribute has no scope, the version information must not3649// have the default value (1), as that's incorrect. Instead, the unscoped3650// attribute version information should be taken from the SD-6 standing3651// document, which can be found at:3652// https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations3653//3654// C23-style attributes have the same kind of version information3655// associated with them. The unscoped attribute version information should3656// be taken from the specification of the attribute in the C Standard.3657//3658// Clang-specific attributes have the same kind of version information3659// associated with them. This version is typically the default value (1).3660// These version values are clang-specific and should typically be3661// incremented once the attribute changes its syntax and/or semantics in a3662// a way that is impactful to the end user.3663int Version = 1;36643665assert(Spelling.variety() == Variety);3666std::string Name = "";3667if (Spelling.nameSpace().empty() || Scope == Spelling.nameSpace()) {3668Name = Spelling.name();3669Version = static_cast<int>(3670Spelling.getSpellingRecord().getValueAsInt("Version"));3671// Verify that explicitly specified CXX11 and C23 spellings (i.e.3672// not inferred from Clang/GCC spellings) have a version that's3673// different from the default (1).3674bool RequiresValidVersion =3675(Variety == "CXX11" || Variety == "C23") &&3676Spelling.getSpellingRecord().getValueAsString("Variety") == Variety;3677if (RequiresValidVersion && Scope.empty() && Version == 1)3678PrintError(Spelling.getSpellingRecord().getLoc(),3679"Standard attributes must have "3680"valid version information.");3681}36823683std::string Test;3684if (Attr->isSubClassOf("TargetSpecificAttr")) {3685const Record *R = Attr->getValueAsDef("Target");3686std::vector<StringRef> Arches = R->getValueAsListOfStrings("Arches");3687GenerateTargetSpecificAttrChecks(R, Arches, Test, nullptr);3688} else if (!Attr->getValueAsListOfDefs("TargetSpecificSpellings").empty()) {3689// Add target checks if this spelling is target-specific.3690const std::vector<Record *> TargetSpellings =3691Attr->getValueAsListOfDefs("TargetSpecificSpellings");3692for (const auto &TargetSpelling : TargetSpellings) {3693// Find spelling that matches current scope and name.3694for (const auto &Spelling : GetFlattenedSpellings(*TargetSpelling)) {3695if (Scope == Spelling.nameSpace() && Name == Spelling.name()) {3696const Record *Target = TargetSpelling->getValueAsDef("Target");3697std::vector<StringRef> Arches =3698Target->getValueAsListOfStrings("Arches");3699GenerateTargetSpecificAttrChecks(Target, Arches, Test,3700/*FnName=*/nullptr);3701break;3702}3703}3704}3705}37063707std::string TestStr = !Test.empty()3708? Test + " ? " + llvm::itostr(Version) + " : 0"3709: llvm::itostr(Version);3710if (Scope.empty() || Scope == Spelling.nameSpace())3711OS << " .Case(\"" << Spelling.name() << "\", " << TestStr << ")\n";3712}3713OS << " .Default(0);\n";3714}37153716namespace clang {37173718// Emits list of regular keyword attributes with info about their arguments.3719void EmitClangRegularKeywordAttributeInfo(RecordKeeper &Records,3720raw_ostream &OS) {3721emitSourceFileHeader(3722"A list of regular keyword attributes generated from the attribute"3723" definitions",3724OS);3725// Assume for now that the same token is not used in multiple regular3726// keyword attributes.3727for (auto *R : Records.getAllDerivedDefinitions("Attr"))3728for (const auto &S : GetFlattenedSpellings(*R)) {3729if (!isRegularKeywordAttribute(S))3730continue;3731std::vector<Record *> Args = R->getValueAsListOfDefs("Args");3732bool HasArgs = llvm::any_of(3733Args, [](const Record *Arg) { return !Arg->getValueAsBit("Fake"); });37343735OS << "KEYWORD_ATTRIBUTE("3736<< S.getSpellingRecord().getValueAsString("Name") << ", "3737<< (HasArgs ? "true" : "false") << ", )\n";3738}3739OS << "#undef KEYWORD_ATTRIBUTE\n";3740}37413742// Emits the list of spellings for attributes.3743void EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) {3744emitSourceFileHeader("Code to implement the __has_attribute logic", OS,3745Records);37463747// Separate all of the attributes out into four group: generic, C++11, GNU,3748// and declspecs. Then generate a big switch statement for each of them.3749std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");3750std::vector<std::pair<const Record *, FlattenedSpelling>> Declspec, Microsoft,3751GNU, Pragma, HLSLAnnotation;3752std::map<std::string,3753std::vector<std::pair<const Record *, FlattenedSpelling>>>3754CXX, C23;37553756// Walk over the list of all attributes, and split them out based on the3757// spelling variety.3758for (auto *R : Attrs) {3759std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*R);3760for (const auto &SI : Spellings) {3761const std::string &Variety = SI.variety();3762if (Variety == "GNU")3763GNU.emplace_back(R, SI);3764else if (Variety == "Declspec")3765Declspec.emplace_back(R, SI);3766else if (Variety == "Microsoft")3767Microsoft.emplace_back(R, SI);3768else if (Variety == "CXX11")3769CXX[SI.nameSpace()].emplace_back(R, SI);3770else if (Variety == "C23")3771C23[SI.nameSpace()].emplace_back(R, SI);3772else if (Variety == "Pragma")3773Pragma.emplace_back(R, SI);3774else if (Variety == "HLSLAnnotation")3775HLSLAnnotation.emplace_back(R, SI);3776}3777}37783779OS << "const llvm::Triple &T = Target.getTriple();\n";3780OS << "switch (Syntax) {\n";3781OS << "case AttributeCommonInfo::Syntax::AS_GNU:\n";3782OS << " return llvm::StringSwitch<int>(Name)\n";3783GenerateHasAttrSpellingStringSwitch(GNU, OS, "GNU");3784OS << "case AttributeCommonInfo::Syntax::AS_Declspec:\n";3785OS << " return llvm::StringSwitch<int>(Name)\n";3786GenerateHasAttrSpellingStringSwitch(Declspec, OS, "Declspec");3787OS << "case AttributeCommonInfo::Syntax::AS_Microsoft:\n";3788OS << " return llvm::StringSwitch<int>(Name)\n";3789GenerateHasAttrSpellingStringSwitch(Microsoft, OS, "Microsoft");3790OS << "case AttributeCommonInfo::Syntax::AS_Pragma:\n";3791OS << " return llvm::StringSwitch<int>(Name)\n";3792GenerateHasAttrSpellingStringSwitch(Pragma, OS, "Pragma");3793OS << "case AttributeCommonInfo::Syntax::AS_HLSLAnnotation:\n";3794OS << " return llvm::StringSwitch<int>(Name)\n";3795GenerateHasAttrSpellingStringSwitch(HLSLAnnotation, OS, "HLSLAnnotation");3796auto fn = [&OS](const char *Spelling,3797const std::map<3798std::string,3799std::vector<std::pair<const Record *, FlattenedSpelling>>>3800&List) {3801OS << "case AttributeCommonInfo::Syntax::AS_" << Spelling << ": {\n";3802// C++11-style attributes are further split out based on the Scope.3803for (auto I = List.cbegin(), E = List.cend(); I != E; ++I) {3804if (I != List.cbegin())3805OS << " else ";3806if (I->first.empty())3807OS << "if (ScopeName == \"\") {\n";3808else3809OS << "if (ScopeName == \"" << I->first << "\") {\n";3810OS << " return llvm::StringSwitch<int>(Name)\n";3811GenerateHasAttrSpellingStringSwitch(I->second, OS, Spelling, I->first);3812OS << "}";3813}3814OS << "\n} break;\n";3815};3816fn("CXX11", CXX);3817fn("C23", C23);3818OS << "case AttributeCommonInfo::Syntax::AS_Keyword:\n";3819OS << "case AttributeCommonInfo::Syntax::AS_ContextSensitiveKeyword:\n";3820OS << " llvm_unreachable(\"hasAttribute not supported for keyword\");\n";3821OS << " return 0;\n";3822OS << "case AttributeCommonInfo::Syntax::AS_Implicit:\n";3823OS << " llvm_unreachable (\"hasAttribute not supported for "3824"AS_Implicit\");\n";3825OS << " return 0;\n";38263827OS << "}\n";3828}38293830void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) {3831emitSourceFileHeader("Code to translate different attribute spellings into "3832"internal identifiers",3833OS, Records);38343835OS << " switch (getParsedKind()) {\n";3836OS << " case IgnoredAttribute:\n";3837OS << " case UnknownAttribute:\n";3838OS << " case NoSemaHandlerAttribute:\n";3839OS << " llvm_unreachable(\"Ignored/unknown shouldn't get here\");\n";38403841ParsedAttrMap Attrs = getParsedAttrList(Records);3842for (const auto &I : Attrs) {3843const Record &R = *I.second;3844std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);3845OS << " case AT_" << I.first << ": {\n";3846for (unsigned I = 0; I < Spellings.size(); ++ I) {3847OS << " if (Name == \"" << Spellings[I].name() << "\" && "3848<< "getSyntax() == AttributeCommonInfo::AS_" << Spellings[I].variety()3849<< " && Scope == \"" << Spellings[I].nameSpace() << "\")\n"3850<< " return " << I << ";\n";3851}38523853OS << " break;\n";3854OS << " }\n";3855}38563857OS << " }\n";3858OS << " return 0;\n";3859}38603861// Emits code used by RecursiveASTVisitor to visit attributes3862void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS) {3863emitSourceFileHeader("Used by RecursiveASTVisitor to visit attributes.", OS,3864Records);38653866std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");38673868// Write method declarations for Traverse* methods.3869// We emit this here because we only generate methods for attributes that3870// are declared as ASTNodes.3871OS << "#ifdef ATTR_VISITOR_DECLS_ONLY\n\n";3872for (const auto *Attr : Attrs) {3873const Record &R = *Attr;3874if (!R.getValueAsBit("ASTNode"))3875continue;3876OS << " bool Traverse"3877<< R.getName() << "Attr(" << R.getName() << "Attr *A);\n";3878OS << " bool Visit"3879<< R.getName() << "Attr(" << R.getName() << "Attr *A) {\n"3880<< " return true; \n"3881<< " }\n";3882}3883OS << "\n#else // ATTR_VISITOR_DECLS_ONLY\n\n";38843885// Write individual Traverse* methods for each attribute class.3886for (const auto *Attr : Attrs) {3887const Record &R = *Attr;3888if (!R.getValueAsBit("ASTNode"))3889continue;38903891OS << "template <typename Derived>\n"3892<< "bool VISITORCLASS<Derived>::Traverse"3893<< R.getName() << "Attr(" << R.getName() << "Attr *A) {\n"3894<< " if (!getDerived().VisitAttr(A))\n"3895<< " return false;\n"3896<< " if (!getDerived().Visit" << R.getName() << "Attr(A))\n"3897<< " return false;\n";38983899std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");3900for (const auto *Arg : ArgRecords)3901createArgument(*Arg, R.getName())->writeASTVisitorTraversal(OS);39023903if (Attr->getValueAsBit("AcceptsExprPack"))3904VariadicExprArgument("DelayedArgs", R.getName())3905.writeASTVisitorTraversal(OS);39063907OS << " return true;\n";3908OS << "}\n\n";3909}39103911// Write generic Traverse routine3912OS << "template <typename Derived>\n"3913<< "bool VISITORCLASS<Derived>::TraverseAttr(Attr *A) {\n"3914<< " if (!A)\n"3915<< " return true;\n"3916<< "\n"3917<< " switch (A->getKind()) {\n";39183919for (const auto *Attr : Attrs) {3920const Record &R = *Attr;3921if (!R.getValueAsBit("ASTNode"))3922continue;39233924OS << " case attr::" << R.getName() << ":\n"3925<< " return getDerived().Traverse" << R.getName() << "Attr("3926<< "cast<" << R.getName() << "Attr>(A));\n";3927}3928OS << " }\n"; // end switch3929OS << " llvm_unreachable(\"bad attribute kind\");\n";3930OS << "}\n"; // end function3931OS << "#endif // ATTR_VISITOR_DECLS_ONLY\n";3932}39333934void EmitClangAttrTemplateInstantiateHelper(const std::vector<Record *> &Attrs,3935raw_ostream &OS,3936bool AppliesToDecl) {39373938OS << " switch (At->getKind()) {\n";3939for (const auto *Attr : Attrs) {3940const Record &R = *Attr;3941if (!R.getValueAsBit("ASTNode"))3942continue;3943OS << " case attr::" << R.getName() << ": {\n";3944bool ShouldClone = R.getValueAsBit("Clone") &&3945(!AppliesToDecl ||3946R.getValueAsBit("MeaningfulToClassTemplateDefinition"));39473948if (!ShouldClone) {3949OS << " return nullptr;\n";3950OS << " }\n";3951continue;3952}39533954OS << " const auto *A = cast<"3955<< R.getName() << "Attr>(At);\n";3956bool TDependent = R.getValueAsBit("TemplateDependent");39573958if (!TDependent) {3959OS << " return A->clone(C);\n";3960OS << " }\n";3961continue;3962}39633964std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");3965std::vector<std::unique_ptr<Argument>> Args;3966Args.reserve(ArgRecords.size());39673968for (const auto *ArgRecord : ArgRecords)3969Args.emplace_back(createArgument(*ArgRecord, R.getName()));39703971for (auto const &ai : Args)3972ai->writeTemplateInstantiation(OS);39733974OS << " return new (C) " << R.getName() << "Attr(C, *A";3975for (auto const &ai : Args) {3976OS << ", ";3977ai->writeTemplateInstantiationArgs(OS);3978}3979OS << ");\n"3980<< " }\n";3981}3982OS << " } // end switch\n"3983<< " llvm_unreachable(\"Unknown attribute!\");\n"3984<< " return nullptr;\n";3985}39863987// Emits code to instantiate dependent attributes on templates.3988void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) {3989emitSourceFileHeader("Template instantiation code for attributes", OS,3990Records);39913992std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");39933994OS << "namespace clang {\n"3995<< "namespace sema {\n\n"3996<< "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, "3997<< "Sema &S,\n"3998<< " const MultiLevelTemplateArgumentList &TemplateArgs) {\n";3999EmitClangAttrTemplateInstantiateHelper(Attrs, OS, /*AppliesToDecl*/false);4000OS << "}\n\n"4001<< "Attr *instantiateTemplateAttributeForDecl(const Attr *At,\n"4002<< " ASTContext &C, Sema &S,\n"4003<< " const MultiLevelTemplateArgumentList &TemplateArgs) {\n";4004EmitClangAttrTemplateInstantiateHelper(Attrs, OS, /*AppliesToDecl*/true);4005OS << "}\n\n"4006<< "} // end namespace sema\n"4007<< "} // end namespace clang\n";4008}40094010// Emits the list of parsed attributes.4011void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) {4012emitSourceFileHeader("List of all attributes that Clang recognizes", OS,4013Records);40144015OS << "#ifndef PARSED_ATTR\n";4016OS << "#define PARSED_ATTR(NAME) NAME\n";4017OS << "#endif\n\n";40184019ParsedAttrMap Names = getParsedAttrList(Records);4020for (const auto &I : Names) {4021OS << "PARSED_ATTR(" << I.first << ")\n";4022}4023}40244025static bool isArgVariadic(const Record &R, StringRef AttrName) {4026return createArgument(R, AttrName)->isVariadic();4027}40284029static void emitArgInfo(const Record &R, raw_ostream &OS) {4030// This function will count the number of arguments specified for the4031// attribute and emit the number of required arguments followed by the4032// number of optional arguments.4033std::vector<Record *> Args = R.getValueAsListOfDefs("Args");4034unsigned ArgCount = 0, OptCount = 0, ArgMemberCount = 0;4035bool HasVariadic = false;4036for (const auto *Arg : Args) {4037// If the arg is fake, it's the user's job to supply it: general parsing4038// logic shouldn't need to know anything about it.4039if (Arg->getValueAsBit("Fake"))4040continue;4041Arg->getValueAsBit("Optional") ? ++OptCount : ++ArgCount;4042++ArgMemberCount;4043if (!HasVariadic && isArgVariadic(*Arg, R.getName()))4044HasVariadic = true;4045}40464047// If there is a variadic argument, we will set the optional argument count4048// to its largest value. Since it's currently a 4-bit number, we set it to 15.4049OS << " /*NumArgs=*/" << ArgCount << ",\n";4050OS << " /*OptArgs=*/" << (HasVariadic ? 15 : OptCount) << ",\n";4051OS << " /*NumArgMembers=*/" << ArgMemberCount << ",\n";4052}40534054static std::string GetDiagnosticSpelling(const Record &R) {4055std::string Ret = std::string(R.getValueAsString("DiagSpelling"));4056if (!Ret.empty())4057return Ret;40584059// If we couldn't find the DiagSpelling in this object, we can check to see4060// if the object is one that has a base, and if it is, loop up to the Base4061// member recursively.4062if (auto Base = R.getValueAsOptionalDef(BaseFieldName))4063return GetDiagnosticSpelling(*Base);40644065return "";4066}40674068static std::string CalculateDiagnostic(const Record &S) {4069// If the SubjectList object has a custom diagnostic associated with it,4070// return that directly.4071const StringRef CustomDiag = S.getValueAsString("CustomDiag");4072if (!CustomDiag.empty())4073return ("\"" + Twine(CustomDiag) + "\"").str();40744075std::vector<std::string> DiagList;4076std::vector<Record *> Subjects = S.getValueAsListOfDefs("Subjects");4077for (const auto *Subject : Subjects) {4078const Record &R = *Subject;4079// Get the diagnostic text from the Decl or Stmt node given.4080std::string V = GetDiagnosticSpelling(R);4081if (V.empty()) {4082PrintError(R.getLoc(),4083"Could not determine diagnostic spelling for the node: " +4084R.getName() + "; please add one to DeclNodes.td");4085} else {4086// The node may contain a list of elements itself, so split the elements4087// by a comma, and trim any whitespace.4088SmallVector<StringRef, 2> Frags;4089llvm::SplitString(V, Frags, ",");4090for (auto Str : Frags) {4091DiagList.push_back(std::string(Str.trim()));4092}4093}4094}40954096if (DiagList.empty()) {4097PrintFatalError(S.getLoc(),4098"Could not deduce diagnostic argument for Attr subjects");4099return "";4100}41014102// FIXME: this is not particularly good for localization purposes and ideally4103// should be part of the diagnostics engine itself with some sort of list4104// specifier.41054106// A single member of the list can be returned directly.4107if (DiagList.size() == 1)4108return '"' + DiagList.front() + '"';41094110if (DiagList.size() == 2)4111return '"' + DiagList[0] + " and " + DiagList[1] + '"';41124113// If there are more than two in the list, we serialize the first N - 14114// elements with a comma. This leaves the string in the state: foo, bar,4115// baz (but misses quux). We can then add ", and " for the last element4116// manually.4117std::string Diag = llvm::join(DiagList.begin(), DiagList.end() - 1, ", ");4118return '"' + Diag + ", and " + *(DiagList.end() - 1) + '"';4119}41204121static std::string GetSubjectWithSuffix(const Record *R) {4122const std::string &B = std::string(R->getName());4123if (B == "DeclBase")4124return "Decl";4125return B + "Decl";4126}41274128static std::string functionNameForCustomAppertainsTo(const Record &Subject) {4129return "is" + Subject.getName().str();4130}41314132static void GenerateCustomAppertainsTo(const Record &Subject, raw_ostream &OS) {4133std::string FnName = functionNameForCustomAppertainsTo(Subject);41344135// If this code has already been generated, we don't need to do anything.4136static std::set<std::string> CustomSubjectSet;4137auto I = CustomSubjectSet.find(FnName);4138if (I != CustomSubjectSet.end())4139return;41404141// This only works with non-root Decls.4142Record *Base = Subject.getValueAsDef(BaseFieldName);41434144// Not currently support custom subjects within custom subjects.4145if (Base->isSubClassOf("SubsetSubject")) {4146PrintFatalError(Subject.getLoc(),4147"SubsetSubjects within SubsetSubjects is not supported");4148return;4149}41504151OS << "static bool " << FnName << "(const Decl *D) {\n";4152OS << " if (const auto *S = dyn_cast<";4153OS << GetSubjectWithSuffix(Base);4154OS << ">(D))\n";4155OS << " return " << Subject.getValueAsString("CheckCode") << ";\n";4156OS << " return false;\n";4157OS << "}\n\n";41584159CustomSubjectSet.insert(FnName);4160}41614162static void GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) {4163// If the attribute does not contain a Subjects definition, then use the4164// default appertainsTo logic.4165if (Attr.isValueUnset("Subjects"))4166return;41674168const Record *SubjectObj = Attr.getValueAsDef("Subjects");4169std::vector<Record *> Subjects = SubjectObj->getValueAsListOfDefs("Subjects");41704171// If the list of subjects is empty, it is assumed that the attribute4172// appertains to everything.4173if (Subjects.empty())4174return;41754176bool Warn = SubjectObj->getValueAsDef("Diag")->getValueAsBit("Warn");41774178// Split the subjects into declaration subjects and statement subjects.4179// FIXME: subset subjects are added to the declaration list until there are4180// enough statement attributes with custom subject needs to warrant4181// the implementation effort.4182std::vector<Record *> DeclSubjects, StmtSubjects;4183llvm::copy_if(4184Subjects, std::back_inserter(DeclSubjects), [](const Record *R) {4185return R->isSubClassOf("SubsetSubject") || !R->isSubClassOf("StmtNode");4186});4187llvm::copy_if(Subjects, std::back_inserter(StmtSubjects),4188[](const Record *R) { return R->isSubClassOf("StmtNode"); });41894190// We should have sorted all of the subjects into two lists.4191// FIXME: this assertion will be wrong if we ever add type attribute subjects.4192assert(DeclSubjects.size() + StmtSubjects.size() == Subjects.size());41934194if (DeclSubjects.empty()) {4195// If there are no decl subjects but there are stmt subjects, diagnose4196// trying to apply a statement attribute to a declaration.4197if (!StmtSubjects.empty()) {4198OS << "bool diagAppertainsToDecl(Sema &S, const ParsedAttr &AL, ";4199OS << "const Decl *D) const override {\n";4200OS << " S.Diag(AL.getLoc(), diag::err_attribute_invalid_on_decl)\n";4201OS << " << AL << AL.isRegularKeywordAttribute() << "4202"D->getLocation();\n";4203OS << " return false;\n";4204OS << "}\n\n";4205}4206} else {4207// Otherwise, generate an appertainsTo check specific to this attribute4208// which checks all of the given subjects against the Decl passed in.4209OS << "bool diagAppertainsToDecl(Sema &S, ";4210OS << "const ParsedAttr &Attr, const Decl *D) const override {\n";4211OS << " if (";4212for (auto I = DeclSubjects.begin(), E = DeclSubjects.end(); I != E; ++I) {4213// If the subject has custom code associated with it, use the generated4214// function for it. The function cannot be inlined into this check (yet)4215// because it requires the subject to be of a specific type, and were that4216// information inlined here, it would not support an attribute with4217// multiple custom subjects.4218if ((*I)->isSubClassOf("SubsetSubject"))4219OS << "!" << functionNameForCustomAppertainsTo(**I) << "(D)";4220else4221OS << "!isa<" << GetSubjectWithSuffix(*I) << ">(D)";42224223if (I + 1 != E)4224OS << " && ";4225}4226OS << ") {\n";4227OS << " S.Diag(Attr.getLoc(), diag::";4228OS << (Warn ? "warn_attribute_wrong_decl_type_str"4229: "err_attribute_wrong_decl_type_str");4230OS << ")\n";4231OS << " << Attr << Attr.isRegularKeywordAttribute() << ";4232OS << CalculateDiagnostic(*SubjectObj) << ";\n";4233OS << " return false;\n";4234OS << " }\n";4235OS << " return true;\n";4236OS << "}\n\n";4237}42384239if (StmtSubjects.empty()) {4240// If there are no stmt subjects but there are decl subjects, diagnose4241// trying to apply a declaration attribute to a statement.4242if (!DeclSubjects.empty()) {4243OS << "bool diagAppertainsToStmt(Sema &S, const ParsedAttr &AL, ";4244OS << "const Stmt *St) const override {\n";4245OS << " S.Diag(AL.getLoc(), diag::err_decl_attribute_invalid_on_stmt)\n";4246OS << " << AL << AL.isRegularKeywordAttribute() << "4247"St->getBeginLoc();\n";4248OS << " return false;\n";4249OS << "}\n\n";4250}4251} else {4252// Now, do the same for statements.4253OS << "bool diagAppertainsToStmt(Sema &S, ";4254OS << "const ParsedAttr &Attr, const Stmt *St) const override {\n";4255OS << " if (";4256for (auto I = StmtSubjects.begin(), E = StmtSubjects.end(); I != E; ++I) {4257OS << "!isa<" << (*I)->getName() << ">(St)";4258if (I + 1 != E)4259OS << " && ";4260}4261OS << ") {\n";4262OS << " S.Diag(Attr.getLoc(), diag::";4263OS << (Warn ? "warn_attribute_wrong_decl_type_str"4264: "err_attribute_wrong_decl_type_str");4265OS << ")\n";4266OS << " << Attr << Attr.isRegularKeywordAttribute() << ";4267OS << CalculateDiagnostic(*SubjectObj) << ";\n";4268OS << " return false;\n";4269OS << " }\n";4270OS << " return true;\n";4271OS << "}\n\n";4272}4273}42744275// Generates the mutual exclusion checks. The checks for parsed attributes are4276// written into OS and the checks for merging declaration attributes are4277// written into MergeOS.4278static void GenerateMutualExclusionsChecks(const Record &Attr,4279const RecordKeeper &Records,4280raw_ostream &OS,4281raw_ostream &MergeDeclOS,4282raw_ostream &MergeStmtOS) {4283// Find all of the definitions that inherit from MutualExclusions and include4284// the given attribute in the list of exclusions to generate the4285// diagMutualExclusion() check.4286std::vector<Record *> ExclusionsList =4287Records.getAllDerivedDefinitions("MutualExclusions");42884289// We don't do any of this magic for type attributes yet.4290if (Attr.isSubClassOf("TypeAttr"))4291return;42924293// This means the attribute is either a statement attribute, a decl4294// attribute, or both; find out which.4295bool CurAttrIsStmtAttr =4296Attr.isSubClassOf("StmtAttr") || Attr.isSubClassOf("DeclOrStmtAttr");4297bool CurAttrIsDeclAttr =4298!CurAttrIsStmtAttr || Attr.isSubClassOf("DeclOrStmtAttr");42994300std::vector<std::string> DeclAttrs, StmtAttrs;43014302for (const Record *Exclusion : ExclusionsList) {4303std::vector<Record *> MutuallyExclusiveAttrs =4304Exclusion->getValueAsListOfDefs("Exclusions");4305auto IsCurAttr = [Attr](const Record *R) {4306return R->getName() == Attr.getName();4307};4308if (llvm::any_of(MutuallyExclusiveAttrs, IsCurAttr)) {4309// This list of exclusions includes the attribute we're looking for, so4310// add the exclusive attributes to the proper list for checking.4311for (const Record *AttrToExclude : MutuallyExclusiveAttrs) {4312if (IsCurAttr(AttrToExclude))4313continue;43144315if (CurAttrIsStmtAttr)4316StmtAttrs.push_back((AttrToExclude->getName() + "Attr").str());4317if (CurAttrIsDeclAttr)4318DeclAttrs.push_back((AttrToExclude->getName() + "Attr").str());4319}4320}4321}43224323// If there are any decl or stmt attributes, silence -Woverloaded-virtual4324// warnings for them both.4325if (!DeclAttrs.empty() || !StmtAttrs.empty())4326OS << " using ParsedAttrInfo::diagMutualExclusion;\n\n";43274328// If we discovered any decl or stmt attributes to test for, generate the4329// predicates for them now.4330if (!DeclAttrs.empty()) {4331// Generate the ParsedAttrInfo subclass logic for declarations.4332OS << " bool diagMutualExclusion(Sema &S, const ParsedAttr &AL, "4333<< "const Decl *D) const override {\n";4334for (const std::string &A : DeclAttrs) {4335OS << " if (const auto *A = D->getAttr<" << A << ">()) {\n";4336OS << " S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible)"4337<< " << AL << A << (AL.isRegularKeywordAttribute() ||"4338<< " A->isRegularKeywordAttribute());\n";4339OS << " S.Diag(A->getLocation(), diag::note_conflicting_attribute);";4340OS << " \nreturn false;\n";4341OS << " }\n";4342}4343OS << " return true;\n";4344OS << " }\n\n";43454346// Also generate the declaration attribute merging logic if the current4347// attribute is one that can be inheritted on a declaration. It is assumed4348// this code will be executed in the context of a function with parameters:4349// Sema &S, Decl *D, Attr *A and that returns a bool (false on diagnostic,4350// true on success).4351if (Attr.isSubClassOf("InheritableAttr")) {4352MergeDeclOS << " if (const auto *Second = dyn_cast<"4353<< (Attr.getName() + "Attr").str() << ">(A)) {\n";4354for (const std::string &A : DeclAttrs) {4355MergeDeclOS << " if (const auto *First = D->getAttr<" << A4356<< ">()) {\n";4357MergeDeclOS << " S.Diag(First->getLocation(), "4358<< "diag::err_attributes_are_not_compatible) << First << "4359<< "Second << (First->isRegularKeywordAttribute() || "4360<< "Second->isRegularKeywordAttribute());\n";4361MergeDeclOS << " S.Diag(Second->getLocation(), "4362<< "diag::note_conflicting_attribute);\n";4363MergeDeclOS << " return false;\n";4364MergeDeclOS << " }\n";4365}4366MergeDeclOS << " return true;\n";4367MergeDeclOS << " }\n";4368}4369}43704371// Statement attributes are a bit different from declarations. With4372// declarations, each attribute is added to the declaration as it is4373// processed, and so you can look on the Decl * itself to see if there is a4374// conflicting attribute. Statement attributes are processed as a group4375// because AttributedStmt needs to tail-allocate all of the attribute nodes4376// at once. This means we cannot check whether the statement already contains4377// an attribute to check for the conflict. Instead, we need to check whether4378// the given list of semantic attributes contain any conflicts. It is assumed4379// this code will be executed in the context of a function with parameters:4380// Sema &S, const SmallVectorImpl<const Attr *> &C. The code will be within a4381// loop which loops over the container C with a loop variable named A to4382// represent the current attribute to check for conflicts.4383//4384// FIXME: it would be nice not to walk over the list of potential attributes4385// to apply to the statement more than once, but statements typically don't4386// have long lists of attributes on them, so re-walking the list should not4387// be an expensive operation.4388if (!StmtAttrs.empty()) {4389MergeStmtOS << " if (const auto *Second = dyn_cast<"4390<< (Attr.getName() + "Attr").str() << ">(A)) {\n";4391MergeStmtOS << " auto Iter = llvm::find_if(C, [](const Attr *Check) "4392<< "{ return isa<";4393interleave(4394StmtAttrs, [&](const std::string &Name) { MergeStmtOS << Name; },4395[&] { MergeStmtOS << ", "; });4396MergeStmtOS << ">(Check); });\n";4397MergeStmtOS << " if (Iter != C.end()) {\n";4398MergeStmtOS << " S.Diag((*Iter)->getLocation(), "4399<< "diag::err_attributes_are_not_compatible) << *Iter << "4400<< "Second << ((*Iter)->isRegularKeywordAttribute() || "4401<< "Second->isRegularKeywordAttribute());\n";4402MergeStmtOS << " S.Diag(Second->getLocation(), "4403<< "diag::note_conflicting_attribute);\n";4404MergeStmtOS << " return false;\n";4405MergeStmtOS << " }\n";4406MergeStmtOS << " }\n";4407}4408}44094410static void4411emitAttributeMatchRules(PragmaClangAttributeSupport &PragmaAttributeSupport,4412raw_ostream &OS) {4413OS << "static bool checkAttributeMatchRuleAppliesTo(const Decl *D, "4414<< AttributeSubjectMatchRule::EnumName << " rule) {\n";4415OS << " switch (rule) {\n";4416for (const auto &Rule : PragmaAttributeSupport.Rules) {4417if (Rule.isAbstractRule()) {4418OS << " case " << Rule.getEnumValue() << ":\n";4419OS << " assert(false && \"Abstract matcher rule isn't allowed\");\n";4420OS << " return false;\n";4421continue;4422}4423std::vector<Record *> Subjects = Rule.getSubjects();4424assert(!Subjects.empty() && "Missing subjects");4425OS << " case " << Rule.getEnumValue() << ":\n";4426OS << " return ";4427for (auto I = Subjects.begin(), E = Subjects.end(); I != E; ++I) {4428// If the subject has custom code associated with it, use the function4429// that was generated for GenerateAppertainsTo to check if the declaration4430// is valid.4431if ((*I)->isSubClassOf("SubsetSubject"))4432OS << functionNameForCustomAppertainsTo(**I) << "(D)";4433else4434OS << "isa<" << GetSubjectWithSuffix(*I) << ">(D)";44354436if (I + 1 != E)4437OS << " || ";4438}4439OS << ";\n";4440}4441OS << " }\n";4442OS << " llvm_unreachable(\"Invalid match rule\");\nreturn false;\n";4443OS << "}\n\n";4444}44454446static void GenerateLangOptRequirements(const Record &R,4447raw_ostream &OS) {4448// If the attribute has an empty or unset list of language requirements,4449// use the default handler.4450std::vector<Record *> LangOpts = R.getValueAsListOfDefs("LangOpts");4451if (LangOpts.empty())4452return;44534454OS << "bool acceptsLangOpts(const LangOptions &LangOpts) const override {\n";4455OS << " return " << GenerateTestExpression(LangOpts) << ";\n";4456OS << "}\n\n";4457}44584459static void GenerateTargetRequirements(const Record &Attr,4460const ParsedAttrMap &Dupes,4461raw_ostream &OS) {4462// If the attribute is not a target specific attribute, use the default4463// target handler.4464if (!Attr.isSubClassOf("TargetSpecificAttr"))4465return;44664467// Get the list of architectures to be tested for.4468const Record *R = Attr.getValueAsDef("Target");4469std::vector<StringRef> Arches = R->getValueAsListOfStrings("Arches");44704471// If there are other attributes which share the same parsed attribute kind,4472// such as target-specific attributes with a shared spelling, collapse the4473// duplicate architectures. This is required because a shared target-specific4474// attribute has only one ParsedAttr::Kind enumeration value, but it4475// applies to multiple target architectures. In order for the attribute to be4476// considered valid, all of its architectures need to be included.4477if (!Attr.isValueUnset("ParseKind")) {4478const StringRef APK = Attr.getValueAsString("ParseKind");4479for (const auto &I : Dupes) {4480if (I.first == APK) {4481std::vector<StringRef> DA =4482I.second->getValueAsDef("Target")->getValueAsListOfStrings(4483"Arches");4484Arches.insert(Arches.end(), DA.begin(), DA.end());4485}4486}4487}44884489std::string FnName = "isTarget";4490std::string Test;4491bool UsesT = GenerateTargetSpecificAttrChecks(R, Arches, Test, &FnName);44924493OS << "bool existsInTarget(const TargetInfo &Target) const override {\n";4494if (UsesT)4495OS << " const llvm::Triple &T = Target.getTriple(); (void)T;\n";4496OS << " return " << Test << ";\n";4497OS << "}\n\n";4498}44994500static void4501GenerateSpellingTargetRequirements(const Record &Attr,4502const std::vector<Record *> &TargetSpellings,4503raw_ostream &OS) {4504// If there are no target specific spellings, use the default target handler.4505if (TargetSpellings.empty())4506return;45074508std::string Test;4509bool UsesT = false;4510const std::vector<FlattenedSpelling> SpellingList =4511GetFlattenedSpellings(Attr);4512for (unsigned TargetIndex = 0; TargetIndex < TargetSpellings.size();4513++TargetIndex) {4514const auto &TargetSpelling = TargetSpellings[TargetIndex];4515std::vector<FlattenedSpelling> Spellings =4516GetFlattenedSpellings(*TargetSpelling);45174518Test += "((SpellingListIndex == ";4519for (unsigned Index = 0; Index < Spellings.size(); ++Index) {4520Test +=4521llvm::itostr(getSpellingListIndex(SpellingList, Spellings[Index]));4522if (Index != Spellings.size() - 1)4523Test += " ||\n SpellingListIndex == ";4524else4525Test += ") && ";4526}45274528const Record *Target = TargetSpelling->getValueAsDef("Target");4529std::vector<StringRef> Arches = Target->getValueAsListOfStrings("Arches");4530std::string FnName = "isTargetSpelling";4531UsesT |= GenerateTargetSpecificAttrChecks(Target, Arches, Test, &FnName);4532Test += ")";4533if (TargetIndex != TargetSpellings.size() - 1)4534Test += " || ";4535}45364537OS << "bool spellingExistsInTarget(const TargetInfo &Target,\n";4538OS << " const unsigned SpellingListIndex) const "4539"override {\n";4540if (UsesT)4541OS << " const llvm::Triple &T = Target.getTriple(); (void)T;\n";4542OS << " return " << Test << ";\n", OS << "}\n\n";4543}45444545static void GenerateSpellingIndexToSemanticSpelling(const Record &Attr,4546raw_ostream &OS) {4547// If the attribute does not have a semantic form, we can bail out early.4548if (!Attr.getValueAsBit("ASTNode"))4549return;45504551std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);45524553// If there are zero or one spellings, or all of the spellings share the same4554// name, we can also bail out early.4555if (Spellings.size() <= 1 || SpellingNamesAreCommon(Spellings))4556return;45574558// Generate the enumeration we will use for the mapping.4559SemanticSpellingMap SemanticToSyntacticMap;4560std::string Enum = CreateSemanticSpellings(Spellings, SemanticToSyntacticMap);4561std::string Name = Attr.getName().str() + "AttrSpellingMap";45624563OS << "unsigned spellingIndexToSemanticSpelling(";4564OS << "const ParsedAttr &Attr) const override {\n";4565OS << Enum;4566OS << " unsigned Idx = Attr.getAttributeSpellingListIndex();\n";4567WriteSemanticSpellingSwitch("Idx", SemanticToSyntacticMap, OS);4568OS << "}\n\n";4569}45704571static void GenerateHandleDeclAttribute(const Record &Attr, raw_ostream &OS) {4572// Only generate if Attr can be handled simply.4573if (!Attr.getValueAsBit("SimpleHandler"))4574return;45754576// Generate a function which just converts from ParsedAttr to the Attr type.4577OS << "AttrHandling handleDeclAttribute(Sema &S, Decl *D,";4578OS << "const ParsedAttr &Attr) const override {\n";4579OS << " D->addAttr(::new (S.Context) " << Attr.getName();4580OS << "Attr(S.Context, Attr));\n";4581OS << " return AttributeApplied;\n";4582OS << "}\n\n";4583}45844585static bool isParamExpr(const Record *Arg) {4586return !Arg->getSuperClasses().empty() &&4587llvm::StringSwitch<bool>(4588Arg->getSuperClasses().back().first->getName())4589.Case("ExprArgument", true)4590.Case("VariadicExprArgument", true)4591.Default(false);4592}45934594void GenerateIsParamExpr(const Record &Attr, raw_ostream &OS) {4595OS << "bool isParamExpr(size_t N) const override {\n";4596OS << " return ";4597auto Args = Attr.getValueAsListOfDefs("Args");4598for (size_t I = 0; I < Args.size(); ++I)4599if (isParamExpr(Args[I]))4600OS << "(N == " << I << ") || ";4601OS << "false;\n";4602OS << "}\n\n";4603}46044605void GenerateHandleAttrWithDelayedArgs(RecordKeeper &Records, raw_ostream &OS) {4606OS << "static void handleAttrWithDelayedArgs(Sema &S, Decl *D, ";4607OS << "const ParsedAttr &Attr) {\n";4608OS << " SmallVector<Expr *, 4> ArgExprs;\n";4609OS << " ArgExprs.reserve(Attr.getNumArgs());\n";4610OS << " for (unsigned I = 0; I < Attr.getNumArgs(); ++I) {\n";4611OS << " assert(!Attr.isArgIdent(I));\n";4612OS << " ArgExprs.push_back(Attr.getArgAsExpr(I));\n";4613OS << " }\n";4614OS << " clang::Attr *CreatedAttr = nullptr;\n";4615OS << " switch (Attr.getKind()) {\n";4616OS << " default:\n";4617OS << " llvm_unreachable(\"Attribute cannot hold delayed arguments.\");\n";4618ParsedAttrMap Attrs = getParsedAttrList(Records);4619for (const auto &I : Attrs) {4620const Record &R = *I.second;4621if (!R.getValueAsBit("AcceptsExprPack"))4622continue;4623OS << " case ParsedAttr::AT_" << I.first << ": {\n";4624OS << " CreatedAttr = " << R.getName() << "Attr::CreateWithDelayedArgs";4625OS << "(S.Context, ArgExprs.data(), ArgExprs.size(), Attr);\n";4626OS << " break;\n";4627OS << " }\n";4628}4629OS << " }\n";4630OS << " D->addAttr(CreatedAttr);\n";4631OS << "}\n\n";4632}46334634static bool IsKnownToGCC(const Record &Attr) {4635// Look at the spellings for this subject; if there are any spellings which4636// claim to be known to GCC, the attribute is known to GCC.4637return llvm::any_of(4638GetFlattenedSpellings(Attr),4639[](const FlattenedSpelling &S) { return S.knownToGCC(); });4640}46414642/// Emits the parsed attribute helpers4643void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) {4644emitSourceFileHeader("Parsed attribute helpers", OS, Records);46454646OS << "#if !defined(WANT_DECL_MERGE_LOGIC) && "4647<< "!defined(WANT_STMT_MERGE_LOGIC)\n";4648PragmaClangAttributeSupport &PragmaAttributeSupport =4649getPragmaAttributeSupport(Records);46504651// Get the list of parsed attributes, and accept the optional list of4652// duplicates due to the ParseKind.4653ParsedAttrMap Dupes;4654ParsedAttrMap Attrs = getParsedAttrList(Records, &Dupes);46554656// Generate all of the custom appertainsTo functions that the attributes4657// will be using.4658for (const auto &I : Attrs) {4659const Record &Attr = *I.second;4660if (Attr.isValueUnset("Subjects"))4661continue;4662const Record *SubjectObj = Attr.getValueAsDef("Subjects");4663for (auto Subject : SubjectObj->getValueAsListOfDefs("Subjects"))4664if (Subject->isSubClassOf("SubsetSubject"))4665GenerateCustomAppertainsTo(*Subject, OS);4666}46674668// This stream is used to collect all of the declaration attribute merging4669// logic for performing mutual exclusion checks. This gets emitted at the4670// end of the file in a helper function of its own.4671std::string DeclMergeChecks, StmtMergeChecks;4672raw_string_ostream MergeDeclOS(DeclMergeChecks), MergeStmtOS(StmtMergeChecks);46734674// Generate a ParsedAttrInfo struct for each of the attributes.4675for (auto I = Attrs.begin(), E = Attrs.end(); I != E; ++I) {4676// TODO: If the attribute's kind appears in the list of duplicates, that is4677// because it is a target-specific attribute that appears multiple times.4678// It would be beneficial to test whether the duplicates are "similar4679// enough" to each other to not cause problems. For instance, check that4680// the spellings are identical, and custom parsing rules match, etc.46814682// We need to generate struct instances based off ParsedAttrInfo from4683// ParsedAttr.cpp.4684const std::string &AttrName = I->first;4685const Record &Attr = *I->second;4686auto Spellings = GetFlattenedSpellings(Attr);4687if (!Spellings.empty()) {4688OS << "static constexpr ParsedAttrInfo::Spelling " << I->first4689<< "Spellings[] = {\n";4690for (const auto &S : Spellings) {4691const std::string &RawSpelling = S.name();4692std::string Spelling;4693if (!S.nameSpace().empty())4694Spelling += S.nameSpace() + "::";4695if (S.variety() == "GNU")4696Spelling += NormalizeGNUAttrSpelling(RawSpelling);4697else4698Spelling += RawSpelling;4699OS << " {AttributeCommonInfo::AS_" << S.variety();4700OS << ", \"" << Spelling << "\"},\n";4701}4702OS << "};\n";4703}47044705std::vector<std::string> ArgNames;4706for (const auto &Arg : Attr.getValueAsListOfDefs("Args")) {4707bool UnusedUnset;4708if (Arg->getValueAsBitOrUnset("Fake", UnusedUnset))4709continue;4710ArgNames.push_back(Arg->getValueAsString("Name").str());4711for (const auto &Class : Arg->getSuperClasses()) {4712if (Class.first->getName().starts_with("Variadic")) {4713ArgNames.back().append("...");4714break;4715}4716}4717}4718if (!ArgNames.empty()) {4719OS << "static constexpr const char *" << I->first << "ArgNames[] = {\n";4720for (const auto &N : ArgNames)4721OS << '"' << N << "\",";4722OS << "};\n";4723}47244725OS << "struct ParsedAttrInfo" << I->first4726<< " final : public ParsedAttrInfo {\n";4727OS << " constexpr ParsedAttrInfo" << I->first << "() : ParsedAttrInfo(\n";4728OS << " /*AttrKind=*/ParsedAttr::AT_" << AttrName << ",\n";4729emitArgInfo(Attr, OS);4730OS << " /*HasCustomParsing=*/";4731OS << Attr.getValueAsBit("HasCustomParsing") << ",\n";4732OS << " /*AcceptsExprPack=*/";4733OS << Attr.getValueAsBit("AcceptsExprPack") << ",\n";4734OS << " /*IsTargetSpecific=*/";4735OS << Attr.isSubClassOf("TargetSpecificAttr") << ",\n";4736OS << " /*IsType=*/";4737OS << (Attr.isSubClassOf("TypeAttr") || Attr.isSubClassOf("DeclOrTypeAttr"))4738<< ",\n";4739OS << " /*IsStmt=*/";4740OS << (Attr.isSubClassOf("StmtAttr") || Attr.isSubClassOf("DeclOrStmtAttr"))4741<< ",\n";4742OS << " /*IsKnownToGCC=*/";4743OS << IsKnownToGCC(Attr) << ",\n";4744OS << " /*IsSupportedByPragmaAttribute=*/";4745OS << PragmaAttributeSupport.isAttributedSupported(*I->second) << ",\n";4746if (!Spellings.empty())4747OS << " /*Spellings=*/" << I->first << "Spellings,\n";4748else4749OS << " /*Spellings=*/{},\n";4750if (!ArgNames.empty())4751OS << " /*ArgNames=*/" << I->first << "ArgNames";4752else4753OS << " /*ArgNames=*/{}";4754OS << ") {}\n";4755GenerateAppertainsTo(Attr, OS);4756GenerateMutualExclusionsChecks(Attr, Records, OS, MergeDeclOS, MergeStmtOS);4757GenerateLangOptRequirements(Attr, OS);4758GenerateTargetRequirements(Attr, Dupes, OS);4759GenerateSpellingTargetRequirements(4760Attr, Attr.getValueAsListOfDefs("TargetSpecificSpellings"), OS);4761GenerateSpellingIndexToSemanticSpelling(Attr, OS);4762PragmaAttributeSupport.generateStrictConformsTo(*I->second, OS);4763GenerateHandleDeclAttribute(Attr, OS);4764GenerateIsParamExpr(Attr, OS);4765OS << "static const ParsedAttrInfo" << I->first << " Instance;\n";4766OS << "};\n";4767OS << "const ParsedAttrInfo" << I->first << " ParsedAttrInfo" << I->first4768<< "::Instance;\n";4769}47704771OS << "static const ParsedAttrInfo *AttrInfoMap[] = {\n";4772for (auto I = Attrs.begin(), E = Attrs.end(); I != E; ++I) {4773OS << "&ParsedAttrInfo" << I->first << "::Instance,\n";4774}4775OS << "};\n\n";47764777// Generate function for handling attributes with delayed arguments4778GenerateHandleAttrWithDelayedArgs(Records, OS);47794780// Generate the attribute match rules.4781emitAttributeMatchRules(PragmaAttributeSupport, OS);47824783OS << "#elif defined(WANT_DECL_MERGE_LOGIC)\n\n";47844785// Write out the declaration merging check logic.4786OS << "static bool DiagnoseMutualExclusions(Sema &S, const NamedDecl *D, "4787<< "const Attr *A) {\n";4788OS << DeclMergeChecks;4789OS << " return true;\n";4790OS << "}\n\n";47914792OS << "#elif defined(WANT_STMT_MERGE_LOGIC)\n\n";47934794// Write out the statement merging check logic.4795OS << "static bool DiagnoseMutualExclusions(Sema &S, "4796<< "const SmallVectorImpl<const Attr *> &C) {\n";4797OS << " for (const Attr *A : C) {\n";4798OS << StmtMergeChecks;4799OS << " }\n";4800OS << " return true;\n";4801OS << "}\n\n";48024803OS << "#endif\n";4804}48054806// Emits the kind list of parsed attributes4807void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {4808emitSourceFileHeader("Attribute name matcher", OS, Records);48094810std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");4811std::vector<StringMatcher::StringPair> GNU, Declspec, Microsoft, CXX11,4812Keywords, Pragma, C23, HLSLAnnotation;4813std::set<std::string> Seen;4814for (const auto *A : Attrs) {4815const Record &Attr = *A;48164817bool SemaHandler = Attr.getValueAsBit("SemaHandler");4818bool Ignored = Attr.getValueAsBit("Ignored");4819if (SemaHandler || Ignored) {4820// Attribute spellings can be shared between target-specific attributes,4821// and can be shared between syntaxes for the same attribute. For4822// instance, an attribute can be spelled GNU<"interrupt"> for an ARM-4823// specific attribute, or MSP430-specific attribute. Additionally, an4824// attribute can be spelled GNU<"dllexport"> and Declspec<"dllexport">4825// for the same semantic attribute. Ultimately, we need to map each of4826// these to a single AttributeCommonInfo::Kind value, but the4827// StringMatcher class cannot handle duplicate match strings. So we4828// generate a list of string to match based on the syntax, and emit4829// multiple string matchers depending on the syntax used.4830std::string AttrName;4831if (Attr.isSubClassOf("TargetSpecificAttr") &&4832!Attr.isValueUnset("ParseKind")) {4833AttrName = std::string(Attr.getValueAsString("ParseKind"));4834if (!Seen.insert(AttrName).second)4835continue;4836} else4837AttrName = NormalizeAttrName(StringRef(Attr.getName())).str();48384839std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);4840for (const auto &S : Spellings) {4841const std::string &RawSpelling = S.name();4842std::vector<StringMatcher::StringPair> *Matches = nullptr;4843std::string Spelling;4844const std::string &Variety = S.variety();4845if (Variety == "CXX11") {4846Matches = &CXX11;4847if (!S.nameSpace().empty())4848Spelling += S.nameSpace() + "::";4849} else if (Variety == "C23") {4850Matches = &C23;4851if (!S.nameSpace().empty())4852Spelling += S.nameSpace() + "::";4853} else if (Variety == "GNU")4854Matches = &GNU;4855else if (Variety == "Declspec")4856Matches = &Declspec;4857else if (Variety == "Microsoft")4858Matches = &Microsoft;4859else if (Variety == "Keyword")4860Matches = &Keywords;4861else if (Variety == "Pragma")4862Matches = &Pragma;4863else if (Variety == "HLSLAnnotation")4864Matches = &HLSLAnnotation;48654866assert(Matches && "Unsupported spelling variety found");48674868if (Variety == "GNU")4869Spelling += NormalizeGNUAttrSpelling(RawSpelling);4870else4871Spelling += RawSpelling;48724873if (SemaHandler)4874Matches->push_back(StringMatcher::StringPair(4875Spelling, "return AttributeCommonInfo::AT_" + AttrName + ";"));4876else4877Matches->push_back(StringMatcher::StringPair(4878Spelling, "return AttributeCommonInfo::IgnoredAttribute;"));4879}4880}4881}48824883OS << "static AttributeCommonInfo::Kind getAttrKind(StringRef Name, ";4884OS << "AttributeCommonInfo::Syntax Syntax) {\n";4885OS << " if (AttributeCommonInfo::AS_GNU == Syntax) {\n";4886StringMatcher("Name", GNU, OS).Emit();4887OS << " } else if (AttributeCommonInfo::AS_Declspec == Syntax) {\n";4888StringMatcher("Name", Declspec, OS).Emit();4889OS << " } else if (AttributeCommonInfo::AS_Microsoft == Syntax) {\n";4890StringMatcher("Name", Microsoft, OS).Emit();4891OS << " } else if (AttributeCommonInfo::AS_CXX11 == Syntax) {\n";4892StringMatcher("Name", CXX11, OS).Emit();4893OS << " } else if (AttributeCommonInfo::AS_C23 == Syntax) {\n";4894StringMatcher("Name", C23, OS).Emit();4895OS << " } else if (AttributeCommonInfo::AS_Keyword == Syntax || ";4896OS << "AttributeCommonInfo::AS_ContextSensitiveKeyword == Syntax) {\n";4897StringMatcher("Name", Keywords, OS).Emit();4898OS << " } else if (AttributeCommonInfo::AS_Pragma == Syntax) {\n";4899StringMatcher("Name", Pragma, OS).Emit();4900OS << " } else if (AttributeCommonInfo::AS_HLSLAnnotation == Syntax) {\n";4901StringMatcher("Name", HLSLAnnotation, OS).Emit();4902OS << " }\n";4903OS << " return AttributeCommonInfo::UnknownAttribute;\n"4904<< "}\n";4905}49064907// Emits the code to dump an attribute.4908void EmitClangAttrTextNodeDump(RecordKeeper &Records, raw_ostream &OS) {4909emitSourceFileHeader("Attribute text node dumper", OS, Records);49104911std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;4912for (const auto *Attr : Attrs) {4913const Record &R = *Attr;4914if (!R.getValueAsBit("ASTNode"))4915continue;49164917// If the attribute has a semantically-meaningful name (which is determined4918// by whether there is a Spelling enumeration for it), then write out the4919// spelling used for the attribute.49204921std::string FunctionContent;4922llvm::raw_string_ostream SS(FunctionContent);49234924std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);4925if (Spellings.size() > 1 && !SpellingNamesAreCommon(Spellings))4926SS << " OS << \" \" << A->getSpelling();\n";49274928Args = R.getValueAsListOfDefs("Args");4929for (const auto *Arg : Args)4930createArgument(*Arg, R.getName())->writeDump(SS);49314932if (Attr->getValueAsBit("AcceptsExprPack"))4933VariadicExprArgument("DelayedArgs", R.getName()).writeDump(OS);49344935if (SS.tell()) {4936OS << " void Visit" << R.getName() << "Attr(const " << R.getName()4937<< "Attr *A) {\n";4938if (!Args.empty())4939OS << " const auto *SA = cast<" << R.getName()4940<< "Attr>(A); (void)SA;\n";4941OS << FunctionContent;4942OS << " }\n";4943}4944}4945}49464947void EmitClangAttrNodeTraverse(RecordKeeper &Records, raw_ostream &OS) {4948emitSourceFileHeader("Attribute text node traverser", OS, Records);49494950std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;4951for (const auto *Attr : Attrs) {4952const Record &R = *Attr;4953if (!R.getValueAsBit("ASTNode"))4954continue;49554956std::string FunctionContent;4957llvm::raw_string_ostream SS(FunctionContent);49584959Args = R.getValueAsListOfDefs("Args");4960for (const auto *Arg : Args)4961createArgument(*Arg, R.getName())->writeDumpChildren(SS);4962if (Attr->getValueAsBit("AcceptsExprPack"))4963VariadicExprArgument("DelayedArgs", R.getName()).writeDumpChildren(SS);4964if (SS.tell()) {4965OS << " void Visit" << R.getName() << "Attr(const " << R.getName()4966<< "Attr *A) {\n";4967if (!Args.empty())4968OS << " const auto *SA = cast<" << R.getName()4969<< "Attr>(A); (void)SA;\n";4970OS << FunctionContent;4971OS << " }\n";4972}4973}4974}49754976void EmitClangAttrParserStringSwitches(RecordKeeper &Records, raw_ostream &OS) {4977emitSourceFileHeader("Parser-related llvm::StringSwitch cases", OS, Records);4978emitClangAttrArgContextList(Records, OS);4979emitClangAttrIdentifierArgList(Records, OS);4980emitClangAttrUnevaluatedStringLiteralList(Records, OS);4981emitClangAttrVariadicIdentifierArgList(Records, OS);4982emitClangAttrThisIsaIdentifierArgList(Records, OS);4983emitClangAttrAcceptsExprPack(Records, OS);4984emitClangAttrTypeArgList(Records, OS);4985emitClangAttrLateParsedList(Records, OS);4986emitClangAttrLateParsedExperimentalList(Records, OS);4987emitClangAttrStrictIdentifierArgAtIndexList(Records, OS);4988}49894990void EmitClangAttrSubjectMatchRulesParserStringSwitches(RecordKeeper &Records,4991raw_ostream &OS) {4992getPragmaAttributeSupport(Records).generateParsingHelpers(OS);4993}49944995void EmitClangAttrDocTable(RecordKeeper &Records, raw_ostream &OS) {4996emitSourceFileHeader("Clang attribute documentation", OS, Records);49974998std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");4999for (const auto *A : Attrs) {5000if (!A->getValueAsBit("ASTNode"))5001continue;5002std::vector<Record *> Docs = A->getValueAsListOfDefs("Documentation");5003assert(!Docs.empty());5004// Only look at the first documentation if there are several.5005// (Currently there's only one such attr, revisit if this becomes common).5006StringRef Text =5007Docs.front()->getValueAsOptionalString("Content").value_or("");5008OS << "\nstatic const char AttrDoc_" << A->getName() << "[] = "5009<< "R\"reST(" << Text.trim() << ")reST\";\n";5010}5011}50125013enum class SpellingKind : size_t {5014GNU,5015CXX11,5016C23,5017Declspec,5018Microsoft,5019Keyword,5020Pragma,5021HLSLAnnotation,5022NumSpellingKinds5023};5024static const size_t NumSpellingKinds = (size_t)SpellingKind::NumSpellingKinds;50255026class SpellingList {5027std::vector<std::string> Spellings[NumSpellingKinds];50285029public:5030ArrayRef<std::string> operator[](SpellingKind K) const {5031return Spellings[(size_t)K];5032}50335034void add(const Record &Attr, FlattenedSpelling Spelling) {5035SpellingKind Kind =5036StringSwitch<SpellingKind>(Spelling.variety())5037.Case("GNU", SpellingKind::GNU)5038.Case("CXX11", SpellingKind::CXX11)5039.Case("C23", SpellingKind::C23)5040.Case("Declspec", SpellingKind::Declspec)5041.Case("Microsoft", SpellingKind::Microsoft)5042.Case("Keyword", SpellingKind::Keyword)5043.Case("Pragma", SpellingKind::Pragma)5044.Case("HLSLAnnotation", SpellingKind::HLSLAnnotation);5045std::string Name;5046if (!Spelling.nameSpace().empty()) {5047switch (Kind) {5048case SpellingKind::CXX11:5049case SpellingKind::C23:5050Name = Spelling.nameSpace() + "::";5051break;5052case SpellingKind::Pragma:5053Name = Spelling.nameSpace() + " ";5054break;5055default:5056PrintFatalError(Attr.getLoc(), "Unexpected namespace in spelling");5057}5058}5059Name += Spelling.name();50605061Spellings[(size_t)Kind].push_back(Name);5062}5063};50645065class DocumentationData {5066public:5067const Record *Documentation;5068const Record *Attribute;5069std::string Heading;5070SpellingList SupportedSpellings;50715072DocumentationData(const Record &Documentation, const Record &Attribute,5073std::pair<std::string, SpellingList> HeadingAndSpellings)5074: Documentation(&Documentation), Attribute(&Attribute),5075Heading(std::move(HeadingAndSpellings.first)),5076SupportedSpellings(std::move(HeadingAndSpellings.second)) {}5077};50785079static void WriteCategoryHeader(const Record *DocCategory,5080raw_ostream &OS) {5081const StringRef Name = DocCategory->getValueAsString("Name");5082OS << Name << "\n" << std::string(Name.size(), '=') << "\n";50835084// If there is content, print that as well.5085const StringRef ContentStr = DocCategory->getValueAsString("Content");5086// Trim leading and trailing newlines and spaces.5087OS << ContentStr.trim();50885089OS << "\n\n";5090}50915092static std::pair<std::string, SpellingList>5093GetAttributeHeadingAndSpellings(const Record &Documentation,5094const Record &Attribute,5095StringRef Cat) {5096// FIXME: there is no way to have a per-spelling category for the attribute5097// documentation. This may not be a limiting factor since the spellings5098// should generally be consistently applied across the category.50995100std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attribute);5101if (Spellings.empty())5102PrintFatalError(Attribute.getLoc(),5103"Attribute has no supported spellings; cannot be "5104"documented");51055106// Determine the heading to be used for this attribute.5107std::string Heading = std::string(Documentation.getValueAsString("Heading"));5108if (Heading.empty()) {5109// If there's only one spelling, we can simply use that.5110if (Spellings.size() == 1)5111Heading = Spellings.begin()->name();5112else {5113std::set<std::string> Uniques;5114for (auto I = Spellings.begin(), E = Spellings.end();5115I != E; ++I) {5116std::string Spelling =5117std::string(NormalizeNameForSpellingComparison(I->name()));5118Uniques.insert(Spelling);5119}5120// If the semantic map has only one spelling, that is sufficient for our5121// needs.5122if (Uniques.size() == 1)5123Heading = *Uniques.begin();5124// If it's in the undocumented category, just construct a header by5125// concatenating all the spellings. Might not be great, but better than5126// nothing.5127else if (Cat == "Undocumented")5128Heading = llvm::join(Uniques.begin(), Uniques.end(), ", ");5129}5130}51315132// If the heading is still empty, it is an error.5133if (Heading.empty())5134PrintFatalError(Attribute.getLoc(),5135"This attribute requires a heading to be specified");51365137SpellingList SupportedSpellings;5138for (const auto &I : Spellings)5139SupportedSpellings.add(Attribute, I);51405141return std::make_pair(std::move(Heading), std::move(SupportedSpellings));5142}51435144static void WriteDocumentation(RecordKeeper &Records,5145const DocumentationData &Doc, raw_ostream &OS) {5146OS << Doc.Heading << "\n" << std::string(Doc.Heading.length(), '-') << "\n";51475148// List what spelling syntaxes the attribute supports.5149// Note: "#pragma clang attribute" is handled outside the spelling kinds loop5150// so it must be last.5151OS << ".. csv-table:: Supported Syntaxes\n";5152OS << " :header: \"GNU\", \"C++11\", \"C23\", \"``__declspec``\",";5153OS << " \"Keyword\", \"``#pragma``\", \"HLSL Annotation\", \"``#pragma "5154"clang ";5155OS << "attribute``\"\n\n \"";5156for (size_t Kind = 0; Kind != NumSpellingKinds; ++Kind) {5157SpellingKind K = (SpellingKind)Kind;5158// TODO: List Microsoft (IDL-style attribute) spellings once we fully5159// support them.5160if (K == SpellingKind::Microsoft)5161continue;51625163bool PrintedAny = false;5164for (StringRef Spelling : Doc.SupportedSpellings[K]) {5165if (PrintedAny)5166OS << " |br| ";5167OS << "``" << Spelling << "``";5168PrintedAny = true;5169}51705171OS << "\",\"";5172}51735174if (getPragmaAttributeSupport(Records).isAttributedSupported(5175*Doc.Attribute))5176OS << "Yes";5177OS << "\"\n\n";51785179// If the attribute is deprecated, print a message about it, and possibly5180// provide a replacement attribute.5181if (!Doc.Documentation->isValueUnset("Deprecated")) {5182OS << "This attribute has been deprecated, and may be removed in a future "5183<< "version of Clang.";5184const Record &Deprecated = *Doc.Documentation->getValueAsDef("Deprecated");5185const StringRef Replacement = Deprecated.getValueAsString("Replacement");5186if (!Replacement.empty())5187OS << " This attribute has been superseded by ``" << Replacement5188<< "``.";5189OS << "\n\n";5190}51915192const StringRef ContentStr = Doc.Documentation->getValueAsString("Content");5193// Trim leading and trailing newlines and spaces.5194OS << ContentStr.trim();51955196OS << "\n\n\n";5197}51985199void EmitClangAttrDocs(RecordKeeper &Records, raw_ostream &OS) {5200// Get the documentation introduction paragraph.5201const Record *Documentation = Records.getDef("GlobalDocumentation");5202if (!Documentation) {5203PrintFatalError("The Documentation top-level definition is missing, "5204"no documentation will be generated.");5205return;5206}52075208OS << Documentation->getValueAsString("Intro") << "\n";52095210// Gather the Documentation lists from each of the attributes, based on the5211// category provided.5212std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");5213struct CategoryLess {5214bool operator()(const Record *L, const Record *R) const {5215return L->getValueAsString("Name") < R->getValueAsString("Name");5216}5217};5218std::map<const Record *, std::vector<DocumentationData>, CategoryLess>5219SplitDocs;5220for (const auto *A : Attrs) {5221const Record &Attr = *A;5222std::vector<Record *> Docs = Attr.getValueAsListOfDefs("Documentation");5223for (const auto *D : Docs) {5224const Record &Doc = *D;5225const Record *Category = Doc.getValueAsDef("Category");5226// If the category is "InternalOnly", then there cannot be any other5227// documentation categories (otherwise, the attribute would be5228// emitted into the docs).5229const StringRef Cat = Category->getValueAsString("Name");5230bool InternalOnly = Cat == "InternalOnly";5231if (InternalOnly && Docs.size() > 1)5232PrintFatalError(Doc.getLoc(),5233"Attribute is \"InternalOnly\", but has multiple "5234"documentation categories");52355236if (!InternalOnly)5237SplitDocs[Category].push_back(DocumentationData(5238Doc, Attr, GetAttributeHeadingAndSpellings(Doc, Attr, Cat)));5239}5240}52415242// Having split the attributes out based on what documentation goes where,5243// we can begin to generate sections of documentation.5244for (auto &I : SplitDocs) {5245WriteCategoryHeader(I.first, OS);52465247llvm::sort(I.second,5248[](const DocumentationData &D1, const DocumentationData &D2) {5249return D1.Heading < D2.Heading;5250});52515252// Walk over each of the attributes in the category and write out their5253// documentation.5254for (const auto &Doc : I.second)5255WriteDocumentation(Records, Doc, OS);5256}5257}52585259void EmitTestPragmaAttributeSupportedAttributes(RecordKeeper &Records,5260raw_ostream &OS) {5261PragmaClangAttributeSupport Support = getPragmaAttributeSupport(Records);5262ParsedAttrMap Attrs = getParsedAttrList(Records);5263OS << "#pragma clang attribute supports the following attributes:\n";5264for (const auto &I : Attrs) {5265if (!Support.isAttributedSupported(*I.second))5266continue;5267OS << I.first;5268if (I.second->isValueUnset("Subjects")) {5269OS << " ()\n";5270continue;5271}5272const Record *SubjectObj = I.second->getValueAsDef("Subjects");5273std::vector<Record *> Subjects =5274SubjectObj->getValueAsListOfDefs("Subjects");5275OS << " (";5276bool PrintComma = false;5277for (const auto &Subject : llvm::enumerate(Subjects)) {5278if (!isSupportedPragmaClangAttributeSubject(*Subject.value()))5279continue;5280if (PrintComma)5281OS << ", ";5282PrintComma = true;5283PragmaClangAttributeSupport::RuleOrAggregateRuleSet &RuleSet =5284Support.SubjectsToRules.find(Subject.value())->getSecond();5285if (RuleSet.isRule()) {5286OS << RuleSet.getRule().getEnumValueName();5287continue;5288}5289OS << "(";5290for (const auto &Rule : llvm::enumerate(RuleSet.getAggregateRuleSet())) {5291if (Rule.index())5292OS << ", ";5293OS << Rule.value().getEnumValueName();5294}5295OS << ")";5296}5297OS << ")\n";5298}5299OS << "End of supported attributes.\n";5300}53015302} // end namespace clang530353045305