151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===- ClangAttrEmitter.cpp - Generate Clang attribute handling =-*- C++ -*--=// 251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// 351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// The LLVM Compiler Infrastructure 451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// 551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// This file is distributed under the University of Illinois Open Source 651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// License. See LICENSE.TXT for details. 751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// 851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===// 951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// 1051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// These tablegen backends emit Clang attribute processing code 1151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// 1251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===// 1351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1493f95f2a2cbb6bb3d17bfb5fc74ce1cccea751b6Sean Hunt#include "llvm/ADT/SmallString.h" 15651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/ADT/STLExtras.h" 16bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman#include "llvm/ADT/SmallSet.h" 17651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/ADT/StringSwitch.h" 18651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/TableGen/Error.h" 1951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include "llvm/TableGen/Record.h" 200c19b3c38e356058aeb2424d175eae232bf014d9Douglas Gregor#include "llvm/TableGen/StringMatcher.h" 213cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/TableGen/TableGenBackend.h" 2251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include <algorithm> 2351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include <cctype> 24651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include <memory> 25651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include <set> 26651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include <sstream> 2751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 2851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourneusing namespace llvm; 2951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 30651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesclass FlattenedSpelling { 31651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string V, N, NS; 32651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool K; 33651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 34651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinespublic: 35651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FlattenedSpelling(const std::string &Variety, const std::string &Name, 36651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const std::string &Namespace, bool KnownToGCC) : 37651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines V(Variety), N(Name), NS(Namespace), K(KnownToGCC) {} 38651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines explicit FlattenedSpelling(const Record &Spelling) : 39651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines V(Spelling.getValueAsString("Variety")), 40651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines N(Spelling.getValueAsString("Name")) { 41651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 42651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines assert(V != "GCC" && "Given a GCC spelling, which means this hasn't been" 43651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "flattened!"); 44ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (V == "CXX11" || V == "Pragma") 45651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines NS = Spelling.getValueAsString("Namespace"); 46651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool Unset; 47651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines K = Spelling.getValueAsBitOrUnset("KnownToGCC", Unset); 48651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 4951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 50651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const std::string &variety() const { return V; } 51651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const std::string &name() const { return N; } 52651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const std::string &nameSpace() const { return NS; } 53651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool knownToGCC() const { return K; } 54651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}; 55651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 56651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstd::vector<FlattenedSpelling> GetFlattenedSpellings(const Record &Attr) { 57651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<Record *> Spellings = Attr.getValueAsListOfDefs("Spellings"); 58651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<FlattenedSpelling> Ret; 59651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 60651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto &Spelling : Spellings) { 61651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Spelling->getValueAsString("Variety") == "GCC") { 62651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Gin up two new spelling objects to add into the list. 63651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Ret.push_back(FlattenedSpelling("GNU", Spelling->getValueAsString("Name"), 64651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "", true)); 65651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Ret.push_back(FlattenedSpelling( 66651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "CXX11", Spelling->getValueAsString("Name"), "gnu", true)); 67651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } else 68651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Ret.push_back(FlattenedSpelling(*Spelling)); 6951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 7051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 71651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return Ret; 7251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 7351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 7451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string ReadPCHRecord(StringRef type) { 7551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return StringSwitch<std::string>(type) 7651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne .EndsWith("Decl *", "GetLocalDeclAs<" 7751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne + std::string(type, 0, type.size()-1) + ">(F, Record[Idx++])") 78ddc2a53584f91b1fdcc466f1ea1345d97c428802Richard Smith .Case("TypeSourceInfo *", "GetTypeSourceInfo(F, Record, Idx)") 79350aea7b794e4824f61d92f96140fbdcc0393588Argyrios Kyrtzidis .Case("Expr *", "ReadExpr(F)") 8051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne .Case("IdentifierInfo *", "GetIdentifierInfo(F, Record, Idx)") 8151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne .Default("Record[Idx++]"); 8251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 8351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 8451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Assumes that the way to get the value is SA->getname() 8551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string WritePCHRecord(StringRef type, StringRef name) { 8651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne return StringSwitch<std::string>(type) 8751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne .EndsWith("Decl *", "AddDeclRef(" + std::string(name) + 8851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne ", Record);\n") 89ddc2a53584f91b1fdcc466f1ea1345d97c428802Richard Smith .Case("TypeSourceInfo *", 90ddc2a53584f91b1fdcc466f1ea1345d97c428802Richard Smith "AddTypeSourceInfo(" + std::string(name) + ", Record);\n") 9151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne .Case("Expr *", "AddStmt(" + std::string(name) + ");\n") 9251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne .Case("IdentifierInfo *", 9351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne "AddIdentifierRef(" + std::string(name) + ", Record);\n") 9451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne .Default("Record.push_back(" + std::string(name) + ");\n"); 9551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 9651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 97e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han// Normalize attribute name by removing leading and trailing 98e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han// underscores. For example, __foo, foo__, __foo__ would 99e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han// become foo. 100e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Hanstatic StringRef NormalizeAttrName(StringRef AttrName) { 101e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han if (AttrName.startswith("__")) 102e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han AttrName = AttrName.substr(2, AttrName.size()); 103e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han 104e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han if (AttrName.endswith("__")) 105e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han AttrName = AttrName.substr(0, AttrName.size() - 2); 106e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han 107e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han return AttrName; 108e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han} 109e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han 110651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// Normalize the name by removing any and all leading and trailing underscores. 111651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// This is different from NormalizeAttrName in that it also handles names like 112651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// _pascal and __pascal. 113651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic StringRef NormalizeNameForSpellingComparison(StringRef Name) { 114651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines while (Name.startswith("_")) 115651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Name = Name.substr(1, Name.size()); 116651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines while (Name.endswith("_")) 117651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Name = Name.substr(0, Name.size() - 1); 118651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return Name; 119651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 120651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 121e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han// Normalize attribute spelling only if the spelling has both leading 122e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han// and trailing underscores. For example, __ms_struct__ will be 123e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han// normalized to "ms_struct"; __cdecl will remain intact. 124e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Hanstatic StringRef NormalizeAttrSpelling(StringRef AttrSpelling) { 125e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han if (AttrSpelling.startswith("__") && AttrSpelling.endswith("__")) { 126e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han AttrSpelling = AttrSpelling.substr(2, AttrSpelling.size() - 4); 127e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han } 128e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han 129e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han return AttrSpelling; 130e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han} 131e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han 1326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinestypedef std::vector<std::pair<std::string, const Record *>> ParsedAttrMap; 133651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 134651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic ParsedAttrMap getParsedAttrList(const RecordKeeper &Records, 1356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ParsedAttrMap *Dupes = nullptr) { 136651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"); 137651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::set<std::string> Seen; 138651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ParsedAttrMap R; 1396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *Attr : Attrs) { 140651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Attr->getValueAsBit("SemaHandler")) { 141651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string AN; 142651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Attr->isSubClassOf("TargetSpecificAttr") && 143651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines !Attr->isValueUnset("ParseKind")) { 144651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines AN = Attr->getValueAsString("ParseKind"); 145651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 146651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // If this attribute has already been handled, it does not need to be 147651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // handled again. 148651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Seen.find(AN) != Seen.end()) { 149651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Dupes) 150651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Dupes->push_back(std::make_pair(AN, Attr)); 151651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 152651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 153651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Seen.insert(AN); 154651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } else 155651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines AN = NormalizeAttrName(Attr->getName()).str(); 156651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 157651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines R.push_back(std::make_pair(AN, Attr)); 158651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 159651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 160651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return R; 161651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 162651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 16351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournenamespace { 16451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne class Argument { 16551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string lowerName, upperName; 16651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne StringRef attrName; 167bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman bool isOpt; 16851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 16951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne public: 1706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Argument(const Record &Arg, StringRef Attr) 17151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne : lowerName(Arg.getValueAsString("Name")), upperName(lowerName), 172bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman attrName(Attr), isOpt(false) { 17351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (!lowerName.empty()) { 17451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne lowerName[0] = std::tolower(lowerName[0]); 17551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne upperName[0] = std::toupper(upperName[0]); 17651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 17751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 17851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne virtual ~Argument() {} 17951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 18051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne StringRef getLowerName() const { return lowerName; } 18151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne StringRef getUpperName() const { return upperName; } 18251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne StringRef getAttrName() const { return attrName; } 18351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 184bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman bool isOptional() const { return isOpt; } 185bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman void setOptional(bool set) { isOpt = set; } 186bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman 18751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // These functions print the argument contents formatted in different ways. 18851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne virtual void writeAccessors(raw_ostream &OS) const = 0; 18951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne virtual void writeAccessorDefinitions(raw_ostream &OS) const {} 190651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines virtual void writeASTVisitorTraversal(raw_ostream &OS) const {} 19151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne virtual void writeCloneArgs(raw_ostream &OS) const = 0; 1927b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins virtual void writeTemplateInstantiationArgs(raw_ostream &OS) const = 0; 193b880609697b3db5ae3df77387532f8b0cec89274Daniel Dunbar virtual void writeTemplateInstantiation(raw_ostream &OS) const {} 19451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne virtual void writeCtorBody(raw_ostream &OS) const {} 19551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne virtual void writeCtorInitializers(raw_ostream &OS) const = 0; 196bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman virtual void writeCtorDefaultInitializers(raw_ostream &OS) const = 0; 19751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne virtual void writeCtorParameters(raw_ostream &OS) const = 0; 19851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne virtual void writeDeclarations(raw_ostream &OS) const = 0; 19951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne virtual void writePCHReadArgs(raw_ostream &OS) const = 0; 20051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne virtual void writePCHReadDecls(raw_ostream &OS) const = 0; 20151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne virtual void writePCHWrite(raw_ostream &OS) const = 0; 2021bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor virtual void writeValue(raw_ostream &OS) const = 0; 203c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko virtual void writeDump(raw_ostream &OS) const = 0; 204c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko virtual void writeDumpChildren(raw_ostream &OS) const {} 205e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu virtual void writeHasChildren(raw_ostream &OS) const { OS << "false"; } 206d068607c136298bec0891d750389a55bac9f5c98Aaron Ballman 207d068607c136298bec0891d750389a55bac9f5c98Aaron Ballman virtual bool isEnumArg() const { return false; } 20866540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins virtual bool isVariadicEnumArg() const { return false; } 209651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 210651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines virtual void writeImplicitCtorArgs(raw_ostream &OS) const { 211651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << getUpperName(); 212651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 21351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne }; 21451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 21551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne class SimpleArgument : public Argument { 21651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string type; 21751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 21851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne public: 2196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines SimpleArgument(const Record &Arg, StringRef Attr, std::string T) 22051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne : Argument(Arg, Attr), type(T) 22151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne {} 22251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 2237b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins std::string getType() const { return type; } 2247b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins 225651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeAccessors(raw_ostream &OS) const override { 22651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " " << type << " get" << getUpperName() << "() const {\n"; 22751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " return " << getLowerName() << ";\n"; 22851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " }"; 22951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 230651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeCloneArgs(raw_ostream &OS) const override { 23151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << getLowerName(); 23251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 233651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeTemplateInstantiationArgs(raw_ostream &OS) const override { 2347b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << "A->get" << getUpperName() << "()"; 2357b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins } 236651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeCtorInitializers(raw_ostream &OS) const override { 23751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << getLowerName() << "(" << getUpperName() << ")"; 23851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 239651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeCtorDefaultInitializers(raw_ostream &OS) const override { 240bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman OS << getLowerName() << "()"; 241bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman } 242651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeCtorParameters(raw_ostream &OS) const override { 24351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << type << " " << getUpperName(); 24451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 245651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeDeclarations(raw_ostream &OS) const override { 24651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << type << " " << getLowerName() << ";"; 24751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 248651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writePCHReadDecls(raw_ostream &OS) const override { 24951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string read = ReadPCHRecord(type); 25051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " " << type << " " << getLowerName() << " = " << read << ";\n"; 25151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 252651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writePCHReadArgs(raw_ostream &OS) const override { 25351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << getLowerName(); 25451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 255651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writePCHWrite(raw_ostream &OS) const override { 25651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " " << WritePCHRecord(type, "SA->get" + 25751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string(getUpperName()) + "()"); 25851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 259651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeValue(raw_ostream &OS) const override { 2601bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor if (type == "FunctionDecl *") { 261ddc2a53584f91b1fdcc466f1ea1345d97c428802Richard Smith OS << "\" << get" << getUpperName() 262ddc2a53584f91b1fdcc466f1ea1345d97c428802Richard Smith << "()->getNameInfo().getAsString() << \""; 2631bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor } else if (type == "IdentifierInfo *") { 2641bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor OS << "\" << get" << getUpperName() << "()->getName() << \""; 265ddc2a53584f91b1fdcc466f1ea1345d97c428802Richard Smith } else if (type == "TypeSourceInfo *") { 2661bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor OS << "\" << get" << getUpperName() << "().getAsString() << \""; 2671bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor } else { 2681bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor OS << "\" << get" << getUpperName() << "() << \""; 2691bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor } 2701bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor } 271651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeDump(raw_ostream &OS) const override { 272c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko if (type == "FunctionDecl *") { 273c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko OS << " OS << \" \";\n"; 274c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko OS << " dumpBareDeclRef(SA->get" << getUpperName() << "());\n"; 275c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko } else if (type == "IdentifierInfo *") { 276c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko OS << " OS << \" \" << SA->get" << getUpperName() 277c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko << "()->getName();\n"; 278ddc2a53584f91b1fdcc466f1ea1345d97c428802Richard Smith } else if (type == "TypeSourceInfo *") { 279c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko OS << " OS << \" \" << SA->get" << getUpperName() 280c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko << "().getAsString();\n"; 281c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko } else if (type == "bool") { 282c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko OS << " if (SA->get" << getUpperName() << "()) OS << \" " 283c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko << getUpperName() << "\";\n"; 284c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko } else if (type == "int" || type == "unsigned") { 285c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko OS << " OS << \" \" << SA->get" << getUpperName() << "();\n"; 286c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko } else { 287c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko llvm_unreachable("Unknown SimpleArgument type!"); 288c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko } 289c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko } 29051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne }; 29151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 292651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines class DefaultSimpleArgument : public SimpleArgument { 293651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines int64_t Default; 294651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 295651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines public: 2966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines DefaultSimpleArgument(const Record &Arg, StringRef Attr, 297651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string T, int64_t Default) 298651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines : SimpleArgument(Arg, Attr, T), Default(Default) {} 299651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 300651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeAccessors(raw_ostream &OS) const override { 301651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SimpleArgument::writeAccessors(OS); 302651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 303651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "\n\n static const " << getType() << " Default" << getUpperName() 304651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << " = " << Default << ";"; 305651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 306651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines }; 307651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 30851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne class StringArgument : public Argument { 30951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne public: 3106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines StringArgument(const Record &Arg, StringRef Attr) 31151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne : Argument(Arg, Attr) 31251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne {} 31351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 314651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeAccessors(raw_ostream &OS) const override { 31551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " llvm::StringRef get" << getUpperName() << "() const {\n"; 31651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " return llvm::StringRef(" << getLowerName() << ", " 31751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << getLowerName() << "Length);\n"; 31851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " }\n"; 31951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " unsigned get" << getUpperName() << "Length() const {\n"; 32051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " return " << getLowerName() << "Length;\n"; 32151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " }\n"; 32251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " void set" << getUpperName() 32351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << "(ASTContext &C, llvm::StringRef S) {\n"; 32451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " " << getLowerName() << "Length = S.size();\n"; 32551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " this->" << getLowerName() << " = new (C, 1) char [" 32651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << getLowerName() << "Length];\n"; 32751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " std::memcpy(this->" << getLowerName() << ", S.data(), " 32851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << getLowerName() << "Length);\n"; 32951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " }"; 33051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 331651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeCloneArgs(raw_ostream &OS) const override { 33251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "get" << getUpperName() << "()"; 33351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 334651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeTemplateInstantiationArgs(raw_ostream &OS) const override { 3357b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << "A->get" << getUpperName() << "()"; 3367b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins } 337651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeCtorBody(raw_ostream &OS) const override { 33851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " std::memcpy(" << getLowerName() << ", " << getUpperName() 33951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << ".data(), " << getLowerName() << "Length);"; 34051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 341651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeCtorInitializers(raw_ostream &OS) const override { 34251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << getLowerName() << "Length(" << getUpperName() << ".size())," 34351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << getLowerName() << "(new (Ctx, 1) char[" << getLowerName() 34451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << "Length])"; 34551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 346651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeCtorDefaultInitializers(raw_ostream &OS) const override { 347bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman OS << getLowerName() << "Length(0)," << getLowerName() << "(0)"; 348bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman } 349651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeCtorParameters(raw_ostream &OS) const override { 35051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "llvm::StringRef " << getUpperName(); 35151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 352651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeDeclarations(raw_ostream &OS) const override { 35351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "unsigned " << getLowerName() << "Length;\n"; 35451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "char *" << getLowerName() << ";"; 35551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 356651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writePCHReadDecls(raw_ostream &OS) const override { 35751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " std::string " << getLowerName() 35851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << "= ReadString(Record, Idx);\n"; 35951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 360651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writePCHReadArgs(raw_ostream &OS) const override { 36151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << getLowerName(); 36251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 363651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writePCHWrite(raw_ostream &OS) const override { 36451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " AddString(SA->get" << getUpperName() << "(), Record);\n"; 36551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 366651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeValue(raw_ostream &OS) const override { 3671bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor OS << "\\\"\" << get" << getUpperName() << "() << \"\\\""; 3681bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor } 369651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeDump(raw_ostream &OS) const override { 370c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko OS << " OS << \" \\\"\" << SA->get" << getUpperName() 371c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko << "() << \"\\\"\";\n"; 372c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko } 37351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne }; 37451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 37551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne class AlignedArgument : public Argument { 37651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne public: 3776bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines AlignedArgument(const Record &Arg, StringRef Attr) 37851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne : Argument(Arg, Attr) 37951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne {} 38051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 381651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeAccessors(raw_ostream &OS) const override { 38251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " bool is" << getUpperName() << "Dependent() const;\n"; 38351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 38451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n"; 38551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 38651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " bool is" << getUpperName() << "Expr() const {\n"; 38751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " return is" << getLowerName() << "Expr;\n"; 38851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " }\n"; 38951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 39051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " Expr *get" << getUpperName() << "Expr() const {\n"; 39151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " assert(is" << getLowerName() << "Expr);\n"; 39251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " return " << getLowerName() << "Expr;\n"; 39351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " }\n"; 39451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 39551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " TypeSourceInfo *get" << getUpperName() << "Type() const {\n"; 39651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " assert(!is" << getLowerName() << "Expr);\n"; 39751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " return " << getLowerName() << "Type;\n"; 39851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " }"; 39951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 400651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeAccessorDefinitions(raw_ostream &OS) const override { 40151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "bool " << getAttrName() << "Attr::is" << getUpperName() 40251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << "Dependent() const {\n"; 40351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " if (is" << getLowerName() << "Expr)\n"; 40451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " return " << getLowerName() << "Expr && (" << getLowerName() 40551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << "Expr->isValueDependent() || " << getLowerName() 40651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << "Expr->isTypeDependent());\n"; 40751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " else\n"; 40851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " return " << getLowerName() 40951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << "Type->getType()->isDependentType();\n"; 41051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "}\n"; 41151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 41251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // FIXME: Do not do the calculation here 41351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // FIXME: Handle types correctly 41451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // A null pointer means maximum alignment 41551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // FIXME: Load the platform-specific maximum alignment, rather than 41651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // 16, the x86 max. 41751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName() 41851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << "(ASTContext &Ctx) const {\n"; 41951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " assert(!is" << getUpperName() << "Dependent());\n"; 42051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " if (is" << getLowerName() << "Expr)\n"; 42151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " return (" << getLowerName() << "Expr ? " << getLowerName() 422a6b8b2c09610b8bc4330e948ece8b940c2386406Richard Smith << "Expr->EvaluateKnownConstInt(Ctx).getZExtValue() : 16)" 42351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << "* Ctx.getCharWidth();\n"; 42451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " else\n"; 42551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " return 0; // FIXME\n"; 42651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "}\n"; 42751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 428651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeCloneArgs(raw_ostream &OS) const override { 42951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "is" << getLowerName() << "Expr, is" << getLowerName() 43051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << "Expr ? static_cast<void*>(" << getLowerName() 43151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << "Expr) : " << getLowerName() 43251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << "Type"; 43351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 434651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeTemplateInstantiationArgs(raw_ostream &OS) const override { 4357b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins // FIXME: move the definition in Sema::InstantiateAttrs to here. 4367b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins // In the meantime, aligned attributes are cloned. 4377b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins } 438651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeCtorBody(raw_ostream &OS) const override { 43951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " if (is" << getLowerName() << "Expr)\n"; 44051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>(" 44151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << getUpperName() << ");\n"; 44251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " else\n"; 44351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " " << getLowerName() 44451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName() 44551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << ");"; 44651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 447651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeCtorInitializers(raw_ostream &OS) const override { 44851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)"; 44951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 450651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeCtorDefaultInitializers(raw_ostream &OS) const override { 451bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman OS << "is" << getLowerName() << "Expr(false)"; 452bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman } 453651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeCtorParameters(raw_ostream &OS) const override { 45451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName(); 45551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 456651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeImplicitCtorArgs(raw_ostream &OS) const override { 457651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "Is" << getUpperName() << "Expr, " << getUpperName(); 458651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 459651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeDeclarations(raw_ostream &OS) const override { 46051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "bool is" << getLowerName() << "Expr;\n"; 46151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "union {\n"; 46251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "Expr *" << getLowerName() << "Expr;\n"; 46351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "TypeSourceInfo *" << getLowerName() << "Type;\n"; 46451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "};"; 46551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 466651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writePCHReadArgs(raw_ostream &OS) const override { 46751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr"; 46851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 469651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writePCHReadDecls(raw_ostream &OS) const override { 47051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " bool is" << getLowerName() << "Expr = Record[Idx++];\n"; 47151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " void *" << getLowerName() << "Ptr;\n"; 47251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " if (is" << getLowerName() << "Expr)\n"; 47351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " " << getLowerName() << "Ptr = ReadExpr(F);\n"; 47451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " else\n"; 47551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " " << getLowerName() 47651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << "Ptr = GetTypeSourceInfo(F, Record, Idx);\n"; 47751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 478651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writePCHWrite(raw_ostream &OS) const override { 47951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " Record.push_back(SA->is" << getUpperName() << "Expr());\n"; 48051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " if (SA->is" << getUpperName() << "Expr())\n"; 48151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " AddStmt(SA->get" << getUpperName() << "Expr());\n"; 48251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " else\n"; 48351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " AddTypeSourceInfo(SA->get" << getUpperName() 48451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << "Type(), Record);\n"; 48551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 486651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeValue(raw_ostream &OS) const override { 487ef8225444452a1486bd721f3285301fe84643b00Stephen Hines OS << "\";\n"; 488ef8225444452a1486bd721f3285301fe84643b00Stephen Hines OS << " assert(is" << getLowerName() << "Expr && " << getLowerName() 489ef8225444452a1486bd721f3285301fe84643b00Stephen Hines << "Expr != nullptr);\n"; 490ef8225444452a1486bd721f3285301fe84643b00Stephen Hines OS << " " << getLowerName() << "Expr->printPretty(OS, 0, Policy);\n"; 491ef8225444452a1486bd721f3285301fe84643b00Stephen Hines OS << " OS << \""; 4921bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor } 493651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeDump(raw_ostream &OS) const override { 494c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko } 495651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeDumpChildren(raw_ostream &OS) const override { 496e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu OS << " if (SA->is" << getUpperName() << "Expr()) {\n"; 497e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu OS << " lastChild();\n"; 498c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko OS << " dumpStmt(SA->get" << getUpperName() << "Expr());\n"; 499e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu OS << " } else\n"; 500c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko OS << " dumpType(SA->get" << getUpperName() 501c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko << "Type()->getType());\n"; 502c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko } 503651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeHasChildren(raw_ostream &OS) const override { 504e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu OS << "SA->is" << getUpperName() << "Expr()"; 505e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu } 50651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne }; 50751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 50851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne class VariadicArgument : public Argument { 5096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines std::string Type, ArgName, ArgSizeName, RangeName; 51051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 51151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne public: 5126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines VariadicArgument(const Record &Arg, StringRef Attr, std::string T) 5136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines : Argument(Arg, Attr), Type(T), ArgName(getLowerName().str() + "_"), 5146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ArgSizeName(ArgName + "Size"), RangeName(getLowerName()) {} 51551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 5166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines std::string getType() const { return Type; } 51751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 518651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeAccessors(raw_ostream &OS) const override { 5196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines std::string IteratorType = getLowerName().str() + "_iterator"; 5206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines std::string BeginFn = getLowerName().str() + "_begin()"; 5216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines std::string EndFn = getLowerName().str() + "_end()"; 5226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 5236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines OS << " typedef " << Type << "* " << IteratorType << ";\n"; 5246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines OS << " " << IteratorType << " " << BeginFn << " const {" 5256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines << " return " << ArgName << "; }\n"; 5266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines OS << " " << IteratorType << " " << EndFn << " const {" 5276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines << " return " << ArgName << " + " << ArgSizeName << "; }\n"; 5286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines OS << " unsigned " << getLowerName() << "_size() const {" 5296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines << " return " << ArgSizeName << "; }\n"; 5306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines OS << " llvm::iterator_range<" << IteratorType << "> " << RangeName 5316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines << "() const { return llvm::make_range(" << BeginFn << ", " << EndFn 5326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines << "); }\n"; 53351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 534651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeCloneArgs(raw_ostream &OS) const override { 5356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines OS << ArgName << ", " << ArgSizeName; 53651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 537651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeTemplateInstantiationArgs(raw_ostream &OS) const override { 5387b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins // This isn't elegant, but we have to go through public methods... 5397b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << "A->" << getLowerName() << "_begin(), " 5407b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins << "A->" << getLowerName() << "_size()"; 5417b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins } 542651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeCtorBody(raw_ostream &OS) const override { 5436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines OS << " std::copy(" << getUpperName() << ", " << getUpperName() 5446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines << " + " << ArgSizeName << ", " << ArgName << ");"; 54551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 546651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeCtorInitializers(raw_ostream &OS) const override { 5476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines OS << ArgSizeName << "(" << getUpperName() << "Size), " 5486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines << ArgName << "(new (Ctx, 16) " << getType() << "[" 5496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines << ArgSizeName << "])"; 55051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 551651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeCtorDefaultInitializers(raw_ostream &OS) const override { 5526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines OS << ArgSizeName << "(0), " << ArgName << "(nullptr)"; 553bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman } 554651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeCtorParameters(raw_ostream &OS) const override { 55551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << getType() << " *" << getUpperName() << ", unsigned " 55651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << getUpperName() << "Size"; 55751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 558651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeImplicitCtorArgs(raw_ostream &OS) const override { 559651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << getUpperName() << ", " << getUpperName() << "Size"; 560651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 561651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeDeclarations(raw_ostream &OS) const override { 5626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines OS << " unsigned " << ArgSizeName << ";\n"; 5636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines OS << " " << getType() << " *" << ArgName << ";"; 56451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 565651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writePCHReadDecls(raw_ostream &OS) const override { 56651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n"; 5676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines OS << " SmallVector<" << Type << ", 4> " << getLowerName() 56851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << ";\n"; 56951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " " << getLowerName() << ".reserve(" << getLowerName() 57051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << "Size);\n"; 57166540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n"; 57251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 5736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines std::string read = ReadPCHRecord(Type); 57451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " " << getLowerName() << ".push_back(" << read << ");\n"; 57551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 576651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writePCHReadArgs(raw_ostream &OS) const override { 57751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << getLowerName() << ".data(), " << getLowerName() << "Size"; 57851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 579651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writePCHWrite(raw_ostream &OS) const override { 58051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " Record.push_back(SA->" << getLowerName() << "_size());\n"; 5816bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines OS << " for (auto &Val : SA->" << RangeName << "())\n"; 5826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines OS << " " << WritePCHRecord(Type, "Val"); 58351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 584651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeValue(raw_ostream &OS) const override { 5851bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor OS << "\";\n"; 5861bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor OS << " bool isFirst = true;\n" 5876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines << " for (const auto &Val : " << RangeName << "()) {\n" 5881bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor << " if (isFirst) isFirst = false;\n" 5891bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor << " else OS << \", \";\n" 5906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines << " OS << Val;\n" 5911bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor << " }\n"; 5921bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor OS << " OS << \""; 5931bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor } 594651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeDump(raw_ostream &OS) const override { 5956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines OS << " for (const auto &Val : SA->" << RangeName << "())\n"; 5966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines OS << " OS << \" \" << Val;\n"; 597c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko } 59851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne }; 59951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 600651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Unique the enums, but maintain the original declaration ordering. 601651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<std::string> 602651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines uniqueEnumsInOrder(const std::vector<std::string> &enums) { 603651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<std::string> uniques; 604651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::set<std::string> unique_set(enums.begin(), enums.end()); 605651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto &i : enums) { 606651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::set<std::string>::iterator set_i = unique_set.find(i); 607651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (set_i != unique_set.end()) { 608651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines uniques.push_back(i); 609651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines unique_set.erase(set_i); 610651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 611651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 612651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return uniques; 613651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 614651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 61551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne class EnumArgument : public Argument { 61651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::string type; 617651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<std::string> values, enums, uniques; 61851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne public: 6196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines EnumArgument(const Record &Arg, StringRef Attr) 62051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne : Argument(Arg, Attr), type(Arg.getValueAsString("Type")), 621651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines values(Arg.getValueAsListOfStrings("Values")), 622651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines enums(Arg.getValueAsListOfStrings("Enums")), 623651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines uniques(uniqueEnumsInOrder(enums)) 624c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko { 625c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko // FIXME: Emit a proper error 626c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko assert(!uniques.empty()); 627c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko } 62851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 629651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool isEnumArg() const override { return true; } 630d068607c136298bec0891d750389a55bac9f5c98Aaron Ballman 631651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeAccessors(raw_ostream &OS) const override { 63251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " " << type << " get" << getUpperName() << "() const {\n"; 63351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " return " << getLowerName() << ";\n"; 63451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " }"; 63551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 636651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeCloneArgs(raw_ostream &OS) const override { 63751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << getLowerName(); 63851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 639651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeTemplateInstantiationArgs(raw_ostream &OS) const override { 6407b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << "A->get" << getUpperName() << "()"; 6417b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins } 642651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeCtorInitializers(raw_ostream &OS) const override { 64351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << getLowerName() << "(" << getUpperName() << ")"; 64451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 645651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeCtorDefaultInitializers(raw_ostream &OS) const override { 646bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman OS << getLowerName() << "(" << type << "(0))"; 647bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman } 648651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeCtorParameters(raw_ostream &OS) const override { 64951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << type << " " << getUpperName(); 65051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 651651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeDeclarations(raw_ostream &OS) const override { 652651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<std::string>::const_iterator i = uniques.begin(), 653651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines e = uniques.end(); 65451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // The last one needs to not have a comma. 65551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne --e; 65651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 65751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "public:\n"; 65851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " enum " << type << " {\n"; 65951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne for (; i != e; ++i) 66051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " " << *i << ",\n"; 66151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " " << *e << "\n"; 66251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " };\n"; 66351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "private:\n"; 66451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " " << type << " " << getLowerName() << ";"; 66551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 666651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writePCHReadDecls(raw_ostream &OS) const override { 66751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " " << getAttrName() << "Attr::" << type << " " << getLowerName() 66851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << "(static_cast<" << getAttrName() << "Attr::" << type 66951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << ">(Record[Idx++]));\n"; 67051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 671651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writePCHReadArgs(raw_ostream &OS) const override { 67251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << getLowerName(); 67351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 674651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writePCHWrite(raw_ostream &OS) const override { 67551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "Record.push_back(SA->get" << getUpperName() << "());\n"; 67651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 677651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeValue(raw_ostream &OS) const override { 6781bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor OS << "\" << get" << getUpperName() << "() << \""; 6791bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor } 680651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeDump(raw_ostream &OS) const override { 681c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko OS << " switch(SA->get" << getUpperName() << "()) {\n"; 682651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto &I : uniques) { 683651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " case " << getAttrName() << "Attr::" << I << ":\n"; 684651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " OS << \" " << I << "\";\n"; 685c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko OS << " break;\n"; 686c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko } 687c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko OS << " }\n"; 688c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko } 689d068607c136298bec0891d750389a55bac9f5c98Aaron Ballman 690d068607c136298bec0891d750389a55bac9f5c98Aaron Ballman void writeConversion(raw_ostream &OS) const { 691d068607c136298bec0891d750389a55bac9f5c98Aaron Ballman OS << " static bool ConvertStrTo" << type << "(StringRef Val, "; 692d068607c136298bec0891d750389a55bac9f5c98Aaron Ballman OS << type << " &Out) {\n"; 693d068607c136298bec0891d750389a55bac9f5c98Aaron Ballman OS << " Optional<" << type << "> R = llvm::StringSwitch<Optional<"; 694651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << type << ">>(Val)\n"; 695d068607c136298bec0891d750389a55bac9f5c98Aaron Ballman for (size_t I = 0; I < enums.size(); ++I) { 696d068607c136298bec0891d750389a55bac9f5c98Aaron Ballman OS << " .Case(\"" << values[I] << "\", "; 697d068607c136298bec0891d750389a55bac9f5c98Aaron Ballman OS << getAttrName() << "Attr::" << enums[I] << ")\n"; 698d068607c136298bec0891d750389a55bac9f5c98Aaron Ballman } 699d068607c136298bec0891d750389a55bac9f5c98Aaron Ballman OS << " .Default(Optional<" << type << ">());\n"; 700d068607c136298bec0891d750389a55bac9f5c98Aaron Ballman OS << " if (R) {\n"; 701d068607c136298bec0891d750389a55bac9f5c98Aaron Ballman OS << " Out = *R;\n return true;\n }\n"; 702d068607c136298bec0891d750389a55bac9f5c98Aaron Ballman OS << " return false;\n"; 703d068607c136298bec0891d750389a55bac9f5c98Aaron Ballman OS << " }\n"; 704d068607c136298bec0891d750389a55bac9f5c98Aaron Ballman } 70551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne }; 70666540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins 70766540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins class VariadicEnumArgument: public VariadicArgument { 70866540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins std::string type, QualifiedTypeName; 709651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<std::string> values, enums, uniques; 71066540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins public: 7116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines VariadicEnumArgument(const Record &Arg, StringRef Attr) 71266540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins : VariadicArgument(Arg, Attr, Arg.getValueAsString("Type")), 71366540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins type(Arg.getValueAsString("Type")), 714651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines values(Arg.getValueAsListOfStrings("Values")), 715651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines enums(Arg.getValueAsListOfStrings("Enums")), 716651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines uniques(uniqueEnumsInOrder(enums)) 71766540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins { 71866540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins QualifiedTypeName = getAttrName().str() + "Attr::" + type; 71966540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins 72066540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins // FIXME: Emit a proper error 72166540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins assert(!uniques.empty()); 72266540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins } 72366540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins 724651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool isVariadicEnumArg() const override { return true; } 72566540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins 726651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeDeclarations(raw_ostream &OS) const override { 727651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<std::string>::const_iterator i = uniques.begin(), 728651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines e = uniques.end(); 72966540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins // The last one needs to not have a comma. 73066540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins --e; 73166540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins 73266540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << "public:\n"; 73366540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << " enum " << type << " {\n"; 73466540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins for (; i != e; ++i) 73566540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << " " << *i << ",\n"; 73666540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << " " << *e << "\n"; 73766540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << " };\n"; 73866540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << "private:\n"; 73966540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins 74066540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins VariadicArgument::writeDeclarations(OS); 74166540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins } 742651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeDump(raw_ostream &OS) const override { 74366540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << " for (" << getAttrName() << "Attr::" << getLowerName() 74466540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->" 74566540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins << getLowerName() << "_end(); I != E; ++I) {\n"; 74666540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << " switch(*I) {\n"; 747651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto &UI : uniques) { 748651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " case " << getAttrName() << "Attr::" << UI << ":\n"; 749651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " OS << \" " << UI << "\";\n"; 75066540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << " break;\n"; 75166540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins } 75266540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << " }\n"; 75366540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << " }\n"; 75466540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins } 755651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writePCHReadDecls(raw_ostream &OS) const override { 75666540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n"; 75766540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << " SmallVector<" << QualifiedTypeName << ", 4> " << getLowerName() 75866540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins << ";\n"; 75966540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << " " << getLowerName() << ".reserve(" << getLowerName() 76066540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins << "Size);\n"; 76166540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n"; 76266540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << " " << getLowerName() << ".push_back(" << "static_cast<" 76366540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins << QualifiedTypeName << ">(Record[Idx++]));\n"; 76466540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins } 765651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writePCHWrite(raw_ostream &OS) const override { 76666540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << " Record.push_back(SA->" << getLowerName() << "_size());\n"; 76766540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << " for (" << getAttrName() << "Attr::" << getLowerName() 76866540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->" 76966540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins << getLowerName() << "_end(); i != e; ++i)\n"; 77066540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << " " << WritePCHRecord(QualifiedTypeName, "(*i)"); 77166540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins } 77266540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins void writeConversion(raw_ostream &OS) const { 77366540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << " static bool ConvertStrTo" << type << "(StringRef Val, "; 77466540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << type << " &Out) {\n"; 77566540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << " Optional<" << type << "> R = llvm::StringSwitch<Optional<"; 776651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << type << ">>(Val)\n"; 77766540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins for (size_t I = 0; I < enums.size(); ++I) { 77866540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << " .Case(\"" << values[I] << "\", "; 77966540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << getAttrName() << "Attr::" << enums[I] << ")\n"; 78066540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins } 78166540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << " .Default(Optional<" << type << ">());\n"; 78266540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << " if (R) {\n"; 78366540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << " Out = *R;\n return true;\n }\n"; 78466540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << " return false;\n"; 78566540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins OS << " }\n"; 78666540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins } 78766540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins }; 78851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 78951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne class VersionArgument : public Argument { 79051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne public: 7916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines VersionArgument(const Record &Arg, StringRef Attr) 79251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne : Argument(Arg, Attr) 79351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne {} 79451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 795651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeAccessors(raw_ostream &OS) const override { 79651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " VersionTuple get" << getUpperName() << "() const {\n"; 79751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " return " << getLowerName() << ";\n"; 79851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " }\n"; 79951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " void set" << getUpperName() 80051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << "(ASTContext &C, VersionTuple V) {\n"; 80151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " " << getLowerName() << " = V;\n"; 80251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " }"; 80351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 804651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeCloneArgs(raw_ostream &OS) const override { 80551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "get" << getUpperName() << "()"; 80651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 807651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeTemplateInstantiationArgs(raw_ostream &OS) const override { 8087b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << "A->get" << getUpperName() << "()"; 8097b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins } 810651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeCtorInitializers(raw_ostream &OS) const override { 81151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << getLowerName() << "(" << getUpperName() << ")"; 81251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 813651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeCtorDefaultInitializers(raw_ostream &OS) const override { 814bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman OS << getLowerName() << "()"; 815bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman } 816651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeCtorParameters(raw_ostream &OS) const override { 81751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "VersionTuple " << getUpperName(); 81851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 819651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeDeclarations(raw_ostream &OS) const override { 82051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "VersionTuple " << getLowerName() << ";\n"; 82151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 822651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writePCHReadDecls(raw_ostream &OS) const override { 82351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " VersionTuple " << getLowerName() 82451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << "= ReadVersionTuple(Record, Idx);\n"; 82551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 826651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writePCHReadArgs(raw_ostream &OS) const override { 82751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << getLowerName(); 82851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 829651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writePCHWrite(raw_ostream &OS) const override { 83051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n"; 83151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 832651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeValue(raw_ostream &OS) const override { 8331bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor OS << getLowerName() << "=\" << get" << getUpperName() << "() << \""; 8341bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor } 835651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeDump(raw_ostream &OS) const override { 836c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko OS << " OS << \" \" << SA->get" << getUpperName() << "();\n"; 837c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko } 83851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne }; 8397b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins 8407b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins class ExprArgument : public SimpleArgument { 8417b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins public: 8426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ExprArgument(const Record &Arg, StringRef Attr) 8437b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins : SimpleArgument(Arg, Attr, "Expr *") 8447b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins {} 8457b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins 846651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeASTVisitorTraversal(raw_ostream &OS) const override { 847651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " if (!" 848651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << "getDerived().TraverseStmt(A->get" << getUpperName() << "()))\n"; 849651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " return false;\n"; 850651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 851651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 852651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeTemplateInstantiationArgs(raw_ostream &OS) const override { 8537b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << "tempInst" << getUpperName(); 8547b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins } 8557b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins 856651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeTemplateInstantiation(raw_ostream &OS) const override { 8577b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << " " << getType() << " tempInst" << getUpperName() << ";\n"; 8587b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << " {\n"; 8597b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << " EnterExpressionEvaluationContext " 8607b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins << "Unevaluated(S, Sema::Unevaluated);\n"; 8617b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << " ExprResult " << "Result = S.SubstExpr(" 8627b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins << "A->get" << getUpperName() << "(), TemplateArgs);\n"; 8637b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << " tempInst" << getUpperName() << " = " 864ef8225444452a1486bd721f3285301fe84643b00Stephen Hines << "Result.getAs<Expr>();\n"; 8657b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << " }\n"; 8667b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins } 867c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko 868651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeDump(raw_ostream &OS) const override {} 869c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko 870651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeDumpChildren(raw_ostream &OS) const override { 871e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu OS << " lastChild();\n"; 872c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko OS << " dumpStmt(SA->get" << getUpperName() << "());\n"; 873c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko } 874651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeHasChildren(raw_ostream &OS) const override { OS << "true"; } 8757b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins }; 8767b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins 8777b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins class VariadicExprArgument : public VariadicArgument { 8787b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins public: 8796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines VariadicExprArgument(const Record &Arg, StringRef Attr) 8807b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins : VariadicArgument(Arg, Attr, "Expr *") 8817b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins {} 8827b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins 883651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeASTVisitorTraversal(raw_ostream &OS) const override { 884651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " {\n"; 885651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " " << getType() << " *I = A->" << getLowerName() 886651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << "_begin();\n"; 887651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " " << getType() << " *E = A->" << getLowerName() 888651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << "_end();\n"; 889651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " for (; I != E; ++I) {\n"; 890651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " if (!getDerived().TraverseStmt(*I))\n"; 891651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " return false;\n"; 892651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " }\n"; 893651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " }\n"; 894651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 895651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 896651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeTemplateInstantiationArgs(raw_ostream &OS) const override { 8977b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << "tempInst" << getUpperName() << ", " 8987b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins << "A->" << getLowerName() << "_size()"; 8997b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins } 9007b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins 901651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeTemplateInstantiation(raw_ostream &OS) const override { 9027b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << " " << getType() << " *tempInst" << getUpperName() 9037b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins << " = new (C, 16) " << getType() 9047b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins << "[A->" << getLowerName() << "_size()];\n"; 9057b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << " {\n"; 9067b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << " EnterExpressionEvaluationContext " 9077b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins << "Unevaluated(S, Sema::Unevaluated);\n"; 9087b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << " " << getType() << " *TI = tempInst" << getUpperName() 9097b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins << ";\n"; 9107b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << " " << getType() << " *I = A->" << getLowerName() 9117b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins << "_begin();\n"; 9127b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << " " << getType() << " *E = A->" << getLowerName() 9137b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins << "_end();\n"; 9147b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << " for (; I != E; ++I, ++TI) {\n"; 9157b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << " ExprResult Result = S.SubstExpr(*I, TemplateArgs);\n"; 916ef8225444452a1486bd721f3285301fe84643b00Stephen Hines OS << " *TI = Result.getAs<Expr>();\n"; 9177b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << " }\n"; 9187b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << " }\n"; 9197b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins } 920c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko 921651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeDump(raw_ostream &OS) const override {} 922c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko 923651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeDumpChildren(raw_ostream &OS) const override { 924c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko OS << " for (" << getAttrName() << "Attr::" << getLowerName() 925c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->" 926e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu << getLowerName() << "_end(); I != E; ++I) {\n"; 927e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu OS << " if (I + 1 == E)\n"; 928e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu OS << " lastChild();\n"; 929c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko OS << " dumpStmt(*I);\n"; 930e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu OS << " }\n"; 931e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu } 932e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu 933651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeHasChildren(raw_ostream &OS) const override { 934e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu OS << "SA->" << getLowerName() << "_begin() != " 935e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu << "SA->" << getLowerName() << "_end()"; 936c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko } 9377b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins }; 938ddc2a53584f91b1fdcc466f1ea1345d97c428802Richard Smith 939ddc2a53584f91b1fdcc466f1ea1345d97c428802Richard Smith class TypeArgument : public SimpleArgument { 940ddc2a53584f91b1fdcc466f1ea1345d97c428802Richard Smith public: 9416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines TypeArgument(const Record &Arg, StringRef Attr) 942ddc2a53584f91b1fdcc466f1ea1345d97c428802Richard Smith : SimpleArgument(Arg, Attr, "TypeSourceInfo *") 943ddc2a53584f91b1fdcc466f1ea1345d97c428802Richard Smith {} 944ddc2a53584f91b1fdcc466f1ea1345d97c428802Richard Smith 945651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeAccessors(raw_ostream &OS) const override { 946ddc2a53584f91b1fdcc466f1ea1345d97c428802Richard Smith OS << " QualType get" << getUpperName() << "() const {\n"; 947ddc2a53584f91b1fdcc466f1ea1345d97c428802Richard Smith OS << " return " << getLowerName() << "->getType();\n"; 948ddc2a53584f91b1fdcc466f1ea1345d97c428802Richard Smith OS << " }"; 949ddc2a53584f91b1fdcc466f1ea1345d97c428802Richard Smith OS << " " << getType() << " get" << getUpperName() << "Loc() const {\n"; 950ddc2a53584f91b1fdcc466f1ea1345d97c428802Richard Smith OS << " return " << getLowerName() << ";\n"; 951ddc2a53584f91b1fdcc466f1ea1345d97c428802Richard Smith OS << " }"; 952ddc2a53584f91b1fdcc466f1ea1345d97c428802Richard Smith } 953651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeTemplateInstantiationArgs(raw_ostream &OS) const override { 954ddc2a53584f91b1fdcc466f1ea1345d97c428802Richard Smith OS << "A->get" << getUpperName() << "Loc()"; 955ddc2a53584f91b1fdcc466f1ea1345d97c428802Richard Smith } 956651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writePCHWrite(raw_ostream &OS) const override { 957ddc2a53584f91b1fdcc466f1ea1345d97c428802Richard Smith OS << " " << WritePCHRecord( 958ddc2a53584f91b1fdcc466f1ea1345d97c428802Richard Smith getType(), "SA->get" + std::string(getUpperName()) + "Loc()"); 959ddc2a53584f91b1fdcc466f1ea1345d97c428802Richard Smith } 960ddc2a53584f91b1fdcc466f1ea1345d97c428802Richard Smith }; 96151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 96251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 9636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesstatic std::unique_ptr<Argument> 9646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen HinescreateArgument(const Record &Arg, StringRef Attr, 9656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const Record *Search = nullptr) { 96651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (!Search) 96751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne Search = &Arg; 96851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 9696bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Argument *Ptr = nullptr; 97051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne llvm::StringRef ArgName = Search->getName(); 97151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 97251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (ArgName == "AlignedArgument") Ptr = new AlignedArgument(Arg, Attr); 97351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne else if (ArgName == "EnumArgument") Ptr = new EnumArgument(Arg, Attr); 9747b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins else if (ArgName == "ExprArgument") Ptr = new ExprArgument(Arg, Attr); 97551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne else if (ArgName == "FunctionArgument") 97651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *"); 97751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne else if (ArgName == "IdentifierArgument") 97851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne Ptr = new SimpleArgument(Arg, Attr, "IdentifierInfo *"); 979651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines else if (ArgName == "DefaultBoolArgument") 980651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Ptr = new DefaultSimpleArgument(Arg, Attr, "bool", 981651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Arg.getValueAsBit("Default")); 98251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne else if (ArgName == "BoolArgument") Ptr = new SimpleArgument(Arg, Attr, 98351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne "bool"); 984651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines else if (ArgName == "DefaultIntArgument") 985651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Ptr = new DefaultSimpleArgument(Arg, Attr, "int", 986651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Arg.getValueAsInt("Default")); 98751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne else if (ArgName == "IntArgument") Ptr = new SimpleArgument(Arg, Attr, "int"); 98851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne else if (ArgName == "StringArgument") Ptr = new StringArgument(Arg, Attr); 989ddc2a53584f91b1fdcc466f1ea1345d97c428802Richard Smith else if (ArgName == "TypeArgument") Ptr = new TypeArgument(Arg, Attr); 99051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne else if (ArgName == "UnsignedArgument") 99151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne Ptr = new SimpleArgument(Arg, Attr, "unsigned"); 99251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne else if (ArgName == "VariadicUnsignedArgument") 99351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne Ptr = new VariadicArgument(Arg, Attr, "unsigned"); 99466540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins else if (ArgName == "VariadicEnumArgument") 99566540857c08de7f1be9bea48381548d3942cf9d1DeLesley Hutchins Ptr = new VariadicEnumArgument(Arg, Attr); 99651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne else if (ArgName == "VariadicExprArgument") 9977b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins Ptr = new VariadicExprArgument(Arg, Attr); 99851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne else if (ArgName == "VersionArgument") 99951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne Ptr = new VersionArgument(Arg, Attr); 100051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 100151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (!Ptr) { 1002651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Search in reverse order so that the most-derived type is handled first. 100351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::vector<Record*> Bases = Search->getSuperClasses(); 10046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *Base : llvm::make_range(Bases.rbegin(), Bases.rend())) { 10056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Ptr = createArgument(Arg, Attr, Base).release(); 100651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (Ptr) 100751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne break; 100851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 100951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 1010bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman 1011bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman if (Ptr && Arg.getValueAsBit("Optional")) 1012bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman Ptr->setOptional(true); 1013bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman 1014651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return std::unique_ptr<Argument>(Ptr); 101551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 101651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 10171bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregorstatic void writeAvailabilityValue(raw_ostream &OS) { 10181bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor OS << "\" << getPlatform()->getName();\n" 10191bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor << " if (!getIntroduced().empty()) OS << \", introduced=\" << getIntroduced();\n" 10201bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor << " if (!getDeprecated().empty()) OS << \", deprecated=\" << getDeprecated();\n" 10211bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor << " if (!getObsoleted().empty()) OS << \", obsoleted=\" << getObsoleted();\n" 10221bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor << " if (getUnavailable()) OS << \", unavailable\";\n" 10231bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor << " OS << \""; 10241bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor} 10251bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor 1026651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic void writeGetSpellingFunction(Record &R, raw_ostream &OS) { 1027651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R); 1028651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1029651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "const char *" << R.getName() << "Attr::getSpelling() const {\n"; 1030651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Spellings.empty()) { 1031651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " return \"(No spelling)\";\n}\n\n"; 1032651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return; 1033651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1034651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1035651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " switch (SpellingListIndex) {\n" 1036651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines " default:\n" 1037651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines " llvm_unreachable(\"Unknown attribute spelling!\");\n" 1038651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines " return \"(No spelling)\";\n"; 1039651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1040651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (unsigned I = 0; I < Spellings.size(); ++I) 1041651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " case " << I << ":\n" 1042651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines " return \"" << Spellings[I].name() << "\";\n"; 1043651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // End of the switch statement. 1044651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " }\n"; 1045651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // End of the getSpelling function. 1046651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "}\n\n"; 1047651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 1048651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1049651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic void 1050651f13cea278ec967336033dd032faef0e9fc2ecStephen HineswritePrettyPrintFunction(Record &R, 1051651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const std::vector<std::unique_ptr<Argument>> &Args, 1052651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines raw_ostream &OS) { 1053651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R); 105451d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han 105551d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han OS << "void " << R.getName() << "Attr::printPretty(" 105651d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han << "raw_ostream &OS, const PrintingPolicy &Policy) const {\n"; 105751d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han 1058ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (Spellings.empty()) { 105951d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han OS << "}\n\n"; 106051d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han return; 106151d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han } 106251d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han 106351d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han OS << 106451d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han " switch (SpellingListIndex) {\n" 106551d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han " default:\n" 106651d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han " llvm_unreachable(\"Unknown attribute spelling!\");\n" 106751d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han " break;\n"; 106851d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han 106951d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han for (unsigned I = 0; I < Spellings.size(); ++ I) { 107051d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han llvm::SmallString<16> Prefix; 107151d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han llvm::SmallString<8> Suffix; 107251d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han // The actual spelling of the name and namespace (if applicable) 107351d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han // of an attribute without considering prefix and suffix. 107451d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han llvm::SmallString<64> Spelling; 1075651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string Name = Spellings[I].name(); 1076651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string Variety = Spellings[I].variety(); 107751d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han 107851d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han if (Variety == "GNU") { 107951d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han Prefix = " __attribute__(("; 108051d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han Suffix = "))"; 108151d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han } else if (Variety == "CXX11") { 108251d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han Prefix = " [["; 108351d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han Suffix = "]]"; 1084651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string Namespace = Spellings[I].nameSpace(); 1085ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (!Namespace.empty()) { 108651d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han Spelling += Namespace; 108751d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han Spelling += "::"; 108851d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han } 108951d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han } else if (Variety == "Declspec") { 109051d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han Prefix = " __declspec("; 109151d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han Suffix = ")"; 10925cd532ca0bc1cb8110e24586d064f72332d8b767Richard Smith } else if (Variety == "Keyword") { 10935cd532ca0bc1cb8110e24586d064f72332d8b767Richard Smith Prefix = " "; 10945cd532ca0bc1cb8110e24586d064f72332d8b767Richard Smith Suffix = ""; 1095ef8225444452a1486bd721f3285301fe84643b00Stephen Hines } else if (Variety == "Pragma") { 1096ef8225444452a1486bd721f3285301fe84643b00Stephen Hines Prefix = "#pragma "; 1097ef8225444452a1486bd721f3285301fe84643b00Stephen Hines Suffix = "\n"; 1098ef8225444452a1486bd721f3285301fe84643b00Stephen Hines std::string Namespace = Spellings[I].nameSpace(); 1099ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (!Namespace.empty()) { 1100ef8225444452a1486bd721f3285301fe84643b00Stephen Hines Spelling += Namespace; 1101ef8225444452a1486bd721f3285301fe84643b00Stephen Hines Spelling += " "; 1102ef8225444452a1486bd721f3285301fe84643b00Stephen Hines } 110351d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han } else { 11045cd532ca0bc1cb8110e24586d064f72332d8b767Richard Smith llvm_unreachable("Unknown attribute syntax variety!"); 110551d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han } 110651d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han 110751d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han Spelling += Name; 110851d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han 110951d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han OS << 111051d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han " case " << I << " : {\n" 111151d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han " OS << \"" + Prefix.str() + Spelling.str(); 111251d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han 1113ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (Variety == "Pragma") { 1114ef8225444452a1486bd721f3285301fe84643b00Stephen Hines OS << " \";\n"; 1115ef8225444452a1486bd721f3285301fe84643b00Stephen Hines OS << " printPrettyPragma(OS, Policy);\n"; 1116ef8225444452a1486bd721f3285301fe84643b00Stephen Hines OS << " break;\n"; 1117ef8225444452a1486bd721f3285301fe84643b00Stephen Hines OS << " }\n"; 1118ef8225444452a1486bd721f3285301fe84643b00Stephen Hines continue; 1119ef8225444452a1486bd721f3285301fe84643b00Stephen Hines } 1120ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 1121651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!Args.empty()) 1122651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "("; 112351d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han if (Spelling == "availability") { 112451d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han writeAvailabilityValue(OS); 112551d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han } else { 1126651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto I = Args.begin(), E = Args.end(); I != E; ++ I) { 112751d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han if (I != Args.begin()) OS << ", "; 112851d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han (*I)->writeValue(OS); 112951d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han } 113051d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han } 113151d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han 1132651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!Args.empty()) 1133651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << ")"; 113451d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han OS << Suffix.str() + "\";\n"; 113551d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han 113651d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han OS << 113751d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han " break;\n" 113851d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han " }\n"; 113951d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han } 114051d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han 114151d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han // End of the switch statement. 114251d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han OS << "}\n"; 114351d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han // End of the print function. 114451d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han OS << "}\n\n"; 114551d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han} 114651d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han 1147a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han/// \brief Return the index of a spelling in a spelling list. 1148651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic unsigned 1149651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesgetSpellingListIndex(const std::vector<FlattenedSpelling> &SpellingList, 1150651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const FlattenedSpelling &Spelling) { 1151a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han assert(SpellingList.size() && "Spelling list is empty!"); 1152a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han 1153a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han for (unsigned Index = 0; Index < SpellingList.size(); ++Index) { 1154651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const FlattenedSpelling &S = SpellingList[Index]; 1155651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (S.variety() != Spelling.variety()) 1156a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han continue; 1157651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (S.nameSpace() != Spelling.nameSpace()) 1158a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han continue; 1159651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (S.name() != Spelling.name()) 1160a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han continue; 1161a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han 1162a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han return Index; 1163a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han } 1164a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han 1165a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han llvm_unreachable("Unknown spelling!"); 1166a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han} 1167a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han 1168651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic void writeAttrAccessorDefinition(const Record &R, raw_ostream &OS) { 1169a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han std::vector<Record*> Accessors = R.getValueAsListOfDefs("Accessors"); 11706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *Accessor : Accessors) { 1171a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han std::string Name = Accessor->getValueAsString("Name"); 1172651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<FlattenedSpelling> Spellings = 1173651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines GetFlattenedSpellings(*Accessor); 1174651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<FlattenedSpelling> SpellingList = GetFlattenedSpellings(R); 1175a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han assert(SpellingList.size() && 1176a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han "Attribute with empty spelling list can't have accessors!"); 1177a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han 1178a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han OS << " bool " << Name << "() const { return SpellingListIndex == "; 1179a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han for (unsigned Index = 0; Index < Spellings.size(); ++Index) { 1180651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << getSpellingListIndex(SpellingList, Spellings[Index]); 1181a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han if (Index != Spellings.size() -1) 1182a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han OS << " ||\n SpellingListIndex == "; 1183a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han else 1184a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han OS << "; }\n"; 1185a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han } 1186a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han } 1187a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han} 1188a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han 1189651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic bool 1190651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesSpellingNamesAreCommon(const std::vector<FlattenedSpelling>& Spellings) { 1191651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines assert(!Spellings.empty() && "An empty list of spellings was provided"); 1192651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string FirstName = NormalizeNameForSpellingComparison( 1193651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Spellings.front().name()); 11946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto &Spelling : 11956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines llvm::make_range(std::next(Spellings.begin()), Spellings.end())) { 11966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines std::string Name = NormalizeNameForSpellingComparison(Spelling.name()); 1197651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Name != FirstName) 1198651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return false; 1199651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1200651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return true; 1201651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 1202651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1203651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinestypedef std::map<unsigned, std::string> SemanticSpellingMap; 1204651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic std::string 1205651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesCreateSemanticSpellings(const std::vector<FlattenedSpelling> &Spellings, 1206651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SemanticSpellingMap &Map) { 1207651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // The enumerants are automatically generated based on the variety, 1208651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // namespace (if present) and name for each attribute spelling. However, 1209651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // care is taken to avoid trampling on the reserved namespace due to 1210651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // underscores. 1211651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string Ret(" enum Spelling {\n"); 1212651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::set<std::string> Uniques; 1213651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines unsigned Idx = 0; 1214651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto I = Spellings.begin(), E = Spellings.end(); I != E; ++I, ++Idx) { 1215651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const FlattenedSpelling &S = *I; 1216651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string Variety = S.variety(); 1217651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string Spelling = S.name(); 1218651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string Namespace = S.nameSpace(); 1219651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string EnumName = ""; 1220651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1221651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EnumName += (Variety + "_"); 1222651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!Namespace.empty()) 1223651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EnumName += (NormalizeNameForSpellingComparison(Namespace).str() + 1224651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "_"); 1225651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EnumName += NormalizeNameForSpellingComparison(Spelling); 1226651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1227651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Even if the name is not unique, this spelling index corresponds to a 1228651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // particular enumerant name that we've calculated. 1229651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Map[Idx] = EnumName; 1230651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1231651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Since we have been stripping underscores to avoid trampling on the 1232651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // reserved namespace, we may have inadvertently created duplicate 1233651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // enumerant names. These duplicates are not considered part of the 1234651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // semantic spelling, and can be elided. 1235651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Uniques.find(EnumName) != Uniques.end()) 1236651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 1237651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1238651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Uniques.insert(EnumName); 1239651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (I != Spellings.begin()) 1240651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Ret += ",\n"; 1241651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Ret += " " + EnumName; 1242651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1243651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Ret += "\n };\n\n"; 1244651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return Ret; 1245651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 1246651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1247651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid WriteSemanticSpellingSwitch(const std::string &VarName, 1248651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const SemanticSpellingMap &Map, 1249651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines raw_ostream &OS) { 1250651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " switch (" << VarName << ") {\n default: " 1251651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << "llvm_unreachable(\"Unknown spelling list index\");\n"; 1252651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto &I : Map) 1253651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " case " << I.first << ": return " << I.second << ";\n"; 1254651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " }\n"; 1255651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 1256651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1257651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// Emits the LateParsed property for attributes. 1258651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic void emitClangAttrLateParsedList(RecordKeeper &Records, raw_ostream &OS) { 1259651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "#if defined(CLANG_ATTR_LATE_PARSED_LIST)\n"; 1260651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 1261651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 12626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *Attr : Attrs) { 1263651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool LateParsed = Attr->getValueAsBit("LateParsed"); 1264651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1265651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (LateParsed) { 1266651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr); 1267651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1268651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // FIXME: Handle non-GNU attributes 1269651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto &I : Spellings) { 1270651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (I.variety() != "GNU") 1271651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 1272651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << ".Case(\"" << I.name() << "\", " << LateParsed << ")\n"; 1273651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1274651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1275651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1276651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "#endif // CLANG_ATTR_LATE_PARSED_LIST\n\n"; 1277651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 1278651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1279651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// \brief Emits the first-argument-is-type property for attributes. 1280651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic void emitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) { 1281651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "#if defined(CLANG_ATTR_TYPE_ARG_LIST)\n"; 1282651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"); 1283651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 12846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *Attr : Attrs) { 1285651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Determine whether the first argument is a type. 1286651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<Record *> Args = Attr->getValueAsListOfDefs("Args"); 1287651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Args.empty()) 1288651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 1289651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1290651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Args[0]->getSuperClasses().back()->getName() != "TypeArgument") 1291651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 1292651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1293651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // All these spellings take a single type argument. 1294651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr); 1295651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::set<std::string> Emitted; 1296651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto &S : Spellings) { 1297651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Emitted.insert(S.name()).second) 1298651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n"; 1299651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1300651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1301651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "#endif // CLANG_ATTR_TYPE_ARG_LIST\n\n"; 1302651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 1303651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1304651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// \brief Emits the parse-arguments-in-unevaluated-context property for 1305651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// attributes. 1306651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic void emitClangAttrArgContextList(RecordKeeper &Records, raw_ostream &OS) { 1307651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "#if defined(CLANG_ATTR_ARG_CONTEXT_LIST)\n"; 1308651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ParsedAttrMap Attrs = getParsedAttrList(Records); 1309651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto &I : Attrs) { 1310651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const Record &Attr = *I.second; 1311651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1312651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!Attr.getValueAsBit("ParseArgumentsAsUnevaluated")) 1313651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 1314651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1315651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // All these spellings take are parsed unevaluated. 1316651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr); 1317651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::set<std::string> Emitted; 1318651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto &S : Spellings) { 1319651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Emitted.insert(S.name()).second) 1320651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n"; 1321651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1322651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1323651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "#endif // CLANG_ATTR_ARG_CONTEXT_LIST\n\n"; 1324651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 1325651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1326651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic bool isIdentifierArgument(Record *Arg) { 1327651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return !Arg->getSuperClasses().empty() && 1328651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines llvm::StringSwitch<bool>(Arg->getSuperClasses().back()->getName()) 1329651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines .Case("IdentifierArgument", true) 1330651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines .Case("EnumArgument", true) 1331651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines .Default(false); 1332651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 1333651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1334651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// Emits the first-argument-is-identifier property for attributes. 1335651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic void emitClangAttrIdentifierArgList(RecordKeeper &Records, raw_ostream &OS) { 1336651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "#if defined(CLANG_ATTR_IDENTIFIER_ARG_LIST)\n"; 1337651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 1338651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 13396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *Attr : Attrs) { 1340651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Determine whether the first argument is an identifier. 1341651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<Record *> Args = Attr->getValueAsListOfDefs("Args"); 1342651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Args.empty() || !isIdentifierArgument(Args[0])) 1343651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 1344651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1345651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // All these spellings take an identifier argument. 1346651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr); 1347651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::set<std::string> Emitted; 1348651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto &S : Spellings) { 1349651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Emitted.insert(S.name()).second) 1350651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << ".Case(\"" << S.name() << "\", " << "true" << ")\n"; 1351651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1352651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1353651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "#endif // CLANG_ATTR_IDENTIFIER_ARG_LIST\n\n"; 1354651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 1355651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 13563cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesennamespace clang { 13573cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen 13583cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen// Emits the class definitions for attributes. 13593cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) { 13608f1fa25a9e9f3fa4f2d7ecc0a08ebb08c0c4e642Dmitri Gribenko emitSourceFileHeader("Attribute classes' definitions", OS); 13618f1fa25a9e9f3fa4f2d7ecc0a08ebb08c0c4e642Dmitri Gribenko 136251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n"; 136351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n"; 136451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 136551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 136651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 13676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *Attr : Attrs) { 13686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const Record &R = *Attr; 1369651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1370651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // FIXME: Currently, documentation is generated as-needed due to the fact 1371651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // that there is no way to allow a generated project "reach into" the docs 1372651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // directory (for instance, it may be an out-of-tree build). However, we want 1373651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // to ensure that every attribute has a Documentation field, and produce an 1374651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // error if it has been neglected. Otherwise, the on-demand generation which 1375651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // happens server-side will fail. This code is ensuring that functionality, 1376651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // even though this Emitter doesn't technically need the documentation. 1377651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // When attribute documentation can be generated as part of the build 1378651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // itself, this code can be removed. 1379651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines (void)R.getValueAsListOfDefs("Documentation"); 13803e7d31aa6050a2fb6cb35912793eb3f1b3a22030Douglas Gregor 13813e7d31aa6050a2fb6cb35912793eb3f1b3a22030Douglas Gregor if (!R.getValueAsBit("ASTNode")) 13823e7d31aa6050a2fb6cb35912793eb3f1b3a22030Douglas Gregor continue; 13833e7d31aa6050a2fb6cb35912793eb3f1b3a22030Douglas Gregor 1384201bddcfeb53db9f0c84df46ec4afccc65286e5cAaron Ballman const std::vector<Record *> Supers = R.getSuperClasses(); 1385201bddcfeb53db9f0c84df46ec4afccc65286e5cAaron Ballman assert(!Supers.empty() && "Forgot to specify a superclass for the attr"); 1386201bddcfeb53db9f0c84df46ec4afccc65286e5cAaron Ballman std::string SuperName; 13876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *Super : llvm::make_range(Supers.rbegin(), Supers.rend())) { 13886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const Record &R = *Super; 1389ce7565213b315fe12074b66ac12c530ff4a95fc9Aaron Ballman if (R.getName() != "TargetSpecificAttr" && SuperName.empty()) 1390201bddcfeb53db9f0c84df46ec4afccc65286e5cAaron Ballman SuperName = R.getName(); 1391201bddcfeb53db9f0c84df46ec4afccc65286e5cAaron Ballman } 139251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 139351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n"; 139451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 139551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args"); 1396651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<std::unique_ptr<Argument>> Args; 139751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne Args.reserve(ArgRecords.size()); 139851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 13996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *ArgRecord : ArgRecords) { 1400651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Args.emplace_back(createArgument(*ArgRecord, R.getName())); 1401651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Args.back()->writeDeclarations(OS); 140251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "\n\n"; 140351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 140451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1405651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "\npublic:\n"; 1406651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1407651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R); 1408651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1409651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // If there are zero or one spellings, all spelling-related functionality 1410651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // can be elided. If all of the spellings share the same name, the spelling 1411651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // functionality can also be elided. 1412651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool ElideSpelling = (Spellings.size() <= 1) || 1413651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SpellingNamesAreCommon(Spellings); 1414651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1415651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // This maps spelling index values to semantic Spelling enumerants. 1416651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SemanticSpellingMap SemanticToSyntacticMap; 1417651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1418651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!ElideSpelling) 1419651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << CreateSemanticSpellings(Spellings, SemanticToSyntacticMap); 1420651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1421651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " static " << R.getName() << "Attr *CreateImplicit("; 1422651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "ASTContext &Ctx"; 1423651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!ElideSpelling) 1424651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << ", Spelling S"; 1425651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto const &ai : Args) { 1426651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << ", "; 1427651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ai->writeCtorParameters(OS); 1428651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1429651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << ", SourceRange Loc = SourceRange()"; 1430651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << ") {\n"; 1431651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " " << R.getName() << "Attr *A = new (Ctx) " << R.getName(); 1432651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "Attr(Loc, Ctx, "; 1433651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto const &ai : Args) { 1434651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ai->writeImplicitCtorArgs(OS); 1435651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << ", "; 1436651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1437651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << (ElideSpelling ? "0" : "S") << ");\n"; 1438651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " A->setImplicit(true);\n"; 1439651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " return A;\n }\n\n"; 144051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 144151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n"; 144251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1443bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman bool HasOpt = false; 1444651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto const &ai : Args) { 144551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " , "; 1446651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ai->writeCtorParameters(OS); 144751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "\n"; 1448651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (ai->isOptional()) 1449bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman HasOpt = true; 145051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 145151d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han 145251d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han OS << " , "; 1453651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "unsigned SI\n"; 145451d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han 145551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " )\n"; 145651d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n"; 145751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1458651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto const &ai : Args) { 145951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " , "; 1460651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ai->writeCtorInitializers(OS); 146151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "\n"; 146251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 146351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 146451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " {\n"; 146551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1466651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto const &ai : Args) { 1467651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ai->writeCtorBody(OS); 146851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "\n"; 146951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 147051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " }\n\n"; 147151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1472bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman // If there are optional arguments, write out a constructor that elides the 1473bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman // optional arguments as well. 1474bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman if (HasOpt) { 1475bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n"; 1476651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto const &ai : Args) { 1477651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!ai->isOptional()) { 1478bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman OS << " , "; 1479651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ai->writeCtorParameters(OS); 1480bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman OS << "\n"; 1481bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman } 1482bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman } 1483bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman 1484bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman OS << " , "; 1485651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "unsigned SI\n"; 1486bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman 1487bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman OS << " )\n"; 1488bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n"; 1489bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman 1490651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto const &ai : Args) { 1491bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman OS << " , "; 1492651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ai->writeCtorDefaultInitializers(OS); 1493bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman OS << "\n"; 1494bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman } 1495bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman 1496bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman OS << " {\n"; 1497bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman 1498651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto const &ai : Args) { 1499651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!ai->isOptional()) { 1500651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ai->writeCtorBody(OS); 1501bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman OS << "\n"; 1502bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman } 1503bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman } 1504bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman OS << " }\n\n"; 1505bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman } 1506bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman 1507651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " " << R.getName() << "Attr *clone(ASTContext &C) const override;\n"; 1508651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " void printPretty(raw_ostream &OS,\n" 1509651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << " const PrintingPolicy &Policy) const override;\n"; 1510651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " const char *getSpelling() const override;\n"; 1511651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1512651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!ElideSpelling) { 1513651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines assert(!SemanticToSyntacticMap.empty() && "Empty semantic mapping list"); 1514651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " Spelling getSemanticSpelling() const {\n"; 1515651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines WriteSemanticSpellingSwitch("SpellingListIndex", SemanticToSyntacticMap, 1516651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS); 1517651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " }\n"; 1518651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 151951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1520a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han writeAttrAccessorDefinition(R, OS); 1521a31f65b10e61ca8f2f427b1df176c10ea8a0efa2Michael Han 1522651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto const &ai : Args) { 1523651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ai->writeAccessors(OS); 152451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "\n\n"; 1525d068607c136298bec0891d750389a55bac9f5c98Aaron Ballman 1526651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (ai->isEnumArg()) 1527651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines static_cast<const EnumArgument *>(ai.get())->writeConversion(OS); 1528651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines else if (ai->isVariadicEnumArg()) 1529651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines static_cast<const VariadicEnumArgument *>(ai.get()) 1530651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ->writeConversion(OS); 153151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 153251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1533eb666737bae8a5af8fb6b485cd15e2e62caa5cafJakob Stoklund Olesen OS << R.getValueAsString("AdditionalMembers"); 153451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "\n\n"; 153551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 153651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " static bool classof(const Attr *A) { return A->getKind() == " 153751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << "attr::" << R.getName() << "; }\n"; 153823323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins 153923323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins bool LateParsed = R.getValueAsBit("LateParsed"); 1540651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " bool isLateParsed() const override { return " 154123323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins << LateParsed << "; }\n"; 154223323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins 1543651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (R.getValueAsBit("DuplicatesAllowedWhileMerging")) 1544651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " bool duplicatesAllowed() const override { return true; }\n\n"; 1545651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 154651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "};\n\n"; 154751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 154851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 154951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#endif\n"; 155051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 155151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 15523cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen// Emits the class method definitions for attributes. 15533cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) { 15548f1fa25a9e9f3fa4f2d7ecc0a08ebb08c0c4e642Dmitri Gribenko emitSourceFileHeader("Attribute classes' member function definitions", OS); 155551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 155651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 155751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 15586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (auto *Attr : Attrs) { 15596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Record &R = *Attr; 15603e7d31aa6050a2fb6cb35912793eb3f1b3a22030Douglas Gregor 15613e7d31aa6050a2fb6cb35912793eb3f1b3a22030Douglas Gregor if (!R.getValueAsBit("ASTNode")) 15623e7d31aa6050a2fb6cb35912793eb3f1b3a22030Douglas Gregor continue; 1563651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 156451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args"); 1565651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<std::unique_ptr<Argument>> Args; 15666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *Arg : ArgRecords) 15676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Args.emplace_back(createArgument(*Arg, R.getName())); 156851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1569651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto const &ai : Args) 1570651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ai->writeAccessorDefinitions(OS); 157151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 157251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << R.getName() << "Attr *" << R.getName() 157351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << "Attr::clone(ASTContext &C) const {\n"; 1574ef8225444452a1486bd721f3285301fe84643b00Stephen Hines OS << " auto *A = new (C) " << R.getName() << "Attr(getLocation(), C"; 1575651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto const &ai : Args) { 157651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << ", "; 1577651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ai->writeCloneArgs(OS); 157851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 1579ef8225444452a1486bd721f3285301fe84643b00Stephen Hines OS << ", getSpellingListIndex());\n"; 1580ef8225444452a1486bd721f3285301fe84643b00Stephen Hines OS << " A->Inherited = Inherited;\n"; 1581ef8225444452a1486bd721f3285301fe84643b00Stephen Hines OS << " A->IsPackExpansion = IsPackExpansion;\n"; 1582ef8225444452a1486bd721f3285301fe84643b00Stephen Hines OS << " A->Implicit = Implicit;\n"; 1583ef8225444452a1486bd721f3285301fe84643b00Stephen Hines OS << " return A;\n}\n\n"; 15841bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor 158551d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han writePrettyPrintFunction(R, Args, OS); 1586651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines writeGetSpellingFunction(R, OS); 158751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 158851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 158951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 15903cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // end namespace clang 15913cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen 159251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic void EmitAttrList(raw_ostream &OS, StringRef Class, 159351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne const std::vector<Record*> &AttrList) { 159451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::vector<Record*>::const_iterator i = AttrList.begin(), e = AttrList.end(); 159551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 159651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (i != e) { 159751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne // Move the end iterator back to emit the last attribute. 15983e7d31aa6050a2fb6cb35912793eb3f1b3a22030Douglas Gregor for(--e; i != e; ++i) { 15993e7d31aa6050a2fb6cb35912793eb3f1b3a22030Douglas Gregor if (!(*i)->getValueAsBit("ASTNode")) 16003e7d31aa6050a2fb6cb35912793eb3f1b3a22030Douglas Gregor continue; 16013e7d31aa6050a2fb6cb35912793eb3f1b3a22030Douglas Gregor 160251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << Class << "(" << (*i)->getName() << ")\n"; 16033e7d31aa6050a2fb6cb35912793eb3f1b3a22030Douglas Gregor } 160451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 160551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n"; 160651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 160751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 160851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 16093cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesennamespace clang { 16103cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen 16113cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen// Emits the enumeration list for attributes. 16123cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) { 16138f1fa25a9e9f3fa4f2d7ecc0a08ebb08c0c4e642Dmitri Gribenko emitSourceFileHeader("List of all attributes that Clang recognizes", OS); 161451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 161551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#ifndef LAST_ATTR\n"; 161651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n"; 161751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#endif\n\n"; 161851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 161951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#ifndef INHERITABLE_ATTR\n"; 162051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n"; 162151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#endif\n\n"; 162251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 162351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#ifndef LAST_INHERITABLE_ATTR\n"; 162451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n"; 162551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#endif\n\n"; 162651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 162751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#ifndef INHERITABLE_PARAM_ATTR\n"; 162851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n"; 162951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#endif\n\n"; 163051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 163151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#ifndef LAST_INHERITABLE_PARAM_ATTR\n"; 163251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#define LAST_INHERITABLE_PARAM_ATTR(NAME)" 163351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne " INHERITABLE_PARAM_ATTR(NAME)\n"; 163451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#endif\n\n"; 163551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 163651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne Record *InhClass = Records.getClass("InheritableAttr"); 163751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne Record *InhParamClass = Records.getClass("InheritableParamAttr"); 163851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), 1639651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines NonInhAttrs, InhAttrs, InhParamAttrs; 16406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (auto *Attr : Attrs) { 16416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (!Attr->getValueAsBit("ASTNode")) 16423e7d31aa6050a2fb6cb35912793eb3f1b3a22030Douglas Gregor continue; 16433e7d31aa6050a2fb6cb35912793eb3f1b3a22030Douglas Gregor 16446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (Attr->isSubClassOf(InhParamClass)) 16456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines InhParamAttrs.push_back(Attr); 16466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines else if (Attr->isSubClassOf(InhClass)) 16476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines InhAttrs.push_back(Attr); 164851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne else 16496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines NonInhAttrs.push_back(Attr); 165051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 165151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 165251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs); 165351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs); 165451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne EmitAttrList(OS, "ATTR", NonInhAttrs); 165551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 165651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#undef LAST_ATTR\n"; 165751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#undef INHERITABLE_ATTR\n"; 165851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#undef LAST_INHERITABLE_ATTR\n"; 165951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n"; 166051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << "#undef ATTR\n"; 166151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 166251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 16633cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen// Emits the code to read an attribute from a precompiled header. 16643cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) { 16658f1fa25a9e9f3fa4f2d7ecc0a08ebb08c0c4e642Dmitri Gribenko emitSourceFileHeader("Attribute deserialization code", OS); 166651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 166751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne Record *InhClass = Records.getClass("InheritableAttr"); 166851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), 166951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne ArgRecords; 1670651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<std::unique_ptr<Argument>> Args; 167151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 167251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " switch (Kind) {\n"; 167351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " default:\n"; 1674ef8225444452a1486bd721f3285301fe84643b00Stephen Hines OS << " llvm_unreachable(\"Unknown attribute!\");\n"; 16756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *Attr : Attrs) { 16766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const Record &R = *Attr; 16773e7d31aa6050a2fb6cb35912793eb3f1b3a22030Douglas Gregor if (!R.getValueAsBit("ASTNode")) 16783e7d31aa6050a2fb6cb35912793eb3f1b3a22030Douglas Gregor continue; 16793e7d31aa6050a2fb6cb35912793eb3f1b3a22030Douglas Gregor 168051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " case attr::" << R.getName() << ": {\n"; 168151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (R.isSubClassOf(InhClass)) 168251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " bool isInherited = Record[Idx++];\n"; 1683651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " bool isImplicit = Record[Idx++];\n"; 1684651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " unsigned Spelling = Record[Idx++];\n"; 168551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne ArgRecords = R.getValueAsListOfDefs("Args"); 168651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne Args.clear(); 16876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *Arg : ArgRecords) { 16886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Args.emplace_back(createArgument(*Arg, R.getName())); 1689651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Args.back()->writePCHReadDecls(OS); 169051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 169151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " New = new (Context) " << R.getName() << "Attr(Range, Context"; 1692651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto const &ri : Args) { 169351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << ", "; 1694651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ri->writePCHReadArgs(OS); 169551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 1696651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << ", Spelling);\n"; 169751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (R.isSubClassOf(InhClass)) 169851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " cast<InheritableAttr>(New)->setInherited(isInherited);\n"; 1699651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " New->setImplicit(isImplicit);\n"; 170051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " break;\n"; 170151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " }\n"; 170251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 170351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " }\n"; 170451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 170551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 17063cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen// Emits the code to write an attribute to a precompiled header. 17073cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) { 17088f1fa25a9e9f3fa4f2d7ecc0a08ebb08c0c4e642Dmitri Gribenko emitSourceFileHeader("Attribute serialization code", OS); 17098f1fa25a9e9f3fa4f2d7ecc0a08ebb08c0c4e642Dmitri Gribenko 171051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne Record *InhClass = Records.getClass("InheritableAttr"); 171151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args; 171251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 171351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " switch (A->getKind()) {\n"; 171451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " default:\n"; 171551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " llvm_unreachable(\"Unknown attribute kind!\");\n"; 171651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " break;\n"; 17176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *Attr : Attrs) { 17186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const Record &R = *Attr; 17193e7d31aa6050a2fb6cb35912793eb3f1b3a22030Douglas Gregor if (!R.getValueAsBit("ASTNode")) 17203e7d31aa6050a2fb6cb35912793eb3f1b3a22030Douglas Gregor continue; 172151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " case attr::" << R.getName() << ": {\n"; 172251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne Args = R.getValueAsListOfDefs("Args"); 172351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (R.isSubClassOf(InhClass) || !Args.empty()) 172451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName() 172551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne << "Attr>(A);\n"; 172651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne if (R.isSubClassOf(InhClass)) 172751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " Record.push_back(SA->isInherited());\n"; 1728651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " Record.push_back(A->isImplicit());\n"; 1729651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " Record.push_back(A->getSpellingListIndex());\n"; 1730651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 17316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *Arg : Args) 17326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines createArgument(*Arg, R.getName())->writePCHWrite(OS); 173351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " break;\n"; 173451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " }\n"; 173551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 173651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne OS << " }\n"; 173751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 173851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1739651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic void GenerateHasAttrSpellingStringSwitch( 1740651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const std::vector<Record *> &Attrs, raw_ostream &OS, 1741651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const std::string &Variety = "", const std::string &Scope = "") { 1742651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto *Attr : Attrs) { 1743651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // It is assumed that there will be an llvm::Triple object named T within 1744651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // scope that can be used to determine whether the attribute exists in 1745651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // a given target. 1746651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string Test; 1747651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Attr->isSubClassOf("TargetSpecificAttr")) { 1748651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const Record *R = Attr->getValueAsDef("Target"); 1749651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<std::string> Arches = R->getValueAsListOfStrings("Arches"); 1750651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1751651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Test += "("; 1752651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto AI = Arches.begin(), AE = Arches.end(); AI != AE; ++AI) { 1753651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string Part = *AI; 1754651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Test += "T.getArch() == llvm::Triple::" + Part; 1755651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (AI + 1 != AE) 1756651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Test += " || "; 1757651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1758651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Test += ")"; 1759651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1760651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<std::string> OSes; 1761651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!R->isValueUnset("OSes")) { 1762651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Test += " && ("; 1763651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<std::string> OSes = R->getValueAsListOfStrings("OSes"); 1764651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto AI = OSes.begin(), AE = OSes.end(); AI != AE; ++AI) { 1765651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string Part = *AI; 1766651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1767651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Test += "T.getOS() == llvm::Triple::" + Part; 1768651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (AI + 1 != AE) 1769651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Test += " || "; 1770651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1771651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Test += ")"; 1772651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1773651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1774651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // If this is the C++11 variety, also add in the LangOpts test. 1775651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Variety == "CXX11") 1776651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Test += " && LangOpts.CPlusPlus11"; 1777651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } else if (Variety == "CXX11") 1778651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // C++11 mode should be checked against LangOpts, which is presumed to be 1779651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // present in the caller. 1780651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Test = "LangOpts.CPlusPlus11"; 1781651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines else 1782651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Test = "true"; 178351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1784651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Attr); 1785651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto &S : Spellings) 1786651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Variety.empty() || (Variety == S.variety() && 1787651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines (Scope.empty() || Scope == S.nameSpace()))) 1788651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " .Case(\"" << S.name() << "\", " << Test << ")\n"; 1789651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1790651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " .Default(false);\n"; 1791651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 179251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1793651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// Emits the list of spellings for attributes. 1794651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid EmitClangAttrHasAttrImpl(RecordKeeper &Records, raw_ostream &OS) { 1795651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines emitSourceFileHeader("Code to implement the __has_attribute logic", OS); 179651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1797651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Separate all of the attributes out into four group: generic, C++11, GNU, 1798651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // and declspecs. Then generate a big switch statement for each of them. 1799651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"); 1800ef8225444452a1486bd721f3285301fe84643b00Stephen Hines std::vector<Record *> Declspec, GNU, Pragma; 1801651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::map<std::string, std::vector<Record *>> CXX; 1802651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1803651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Walk over the list of all attributes, and split them out based on the 1804651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // spelling variety. 1805651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto *R : Attrs) { 1806651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*R); 1807651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto &SI : Spellings) { 1808651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string Variety = SI.variety(); 1809651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Variety == "GNU") 1810651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines GNU.push_back(R); 1811651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines else if (Variety == "Declspec") 1812651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Declspec.push_back(R); 1813ef8225444452a1486bd721f3285301fe84643b00Stephen Hines else if (Variety == "CXX11") 1814651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CXX[SI.nameSpace()].push_back(R); 1815ef8225444452a1486bd721f3285301fe84643b00Stephen Hines else if (Variety == "Pragma") 1816ef8225444452a1486bd721f3285301fe84643b00Stephen Hines Pragma.push_back(R); 181751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 181851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 181951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1820651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "switch (Syntax) {\n"; 1821651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "case AttrSyntax::Generic:\n"; 1822651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " return llvm::StringSwitch<bool>(Name)\n"; 1823651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines GenerateHasAttrSpellingStringSwitch(Attrs, OS); 1824651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "case AttrSyntax::GNU:\n"; 1825651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " return llvm::StringSwitch<bool>(Name)\n"; 1826651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines GenerateHasAttrSpellingStringSwitch(GNU, OS, "GNU"); 1827651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "case AttrSyntax::Declspec:\n"; 1828651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " return llvm::StringSwitch<bool>(Name)\n"; 1829651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines GenerateHasAttrSpellingStringSwitch(Declspec, OS, "Declspec"); 1830ef8225444452a1486bd721f3285301fe84643b00Stephen Hines OS << "case AttrSyntax::Pragma:\n"; 1831ef8225444452a1486bd721f3285301fe84643b00Stephen Hines OS << " return llvm::StringSwitch<bool>(Name)\n"; 1832ef8225444452a1486bd721f3285301fe84643b00Stephen Hines GenerateHasAttrSpellingStringSwitch(Pragma, OS, "Pragma"); 1833651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "case AttrSyntax::CXX: {\n"; 1834651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // C++11-style attributes are further split out based on the Scope. 1835651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (std::map<std::string, std::vector<Record *>>::iterator I = CXX.begin(), 1836651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines E = CXX.end(); 1837651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines I != E; ++I) { 1838651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (I != CXX.begin()) 1839651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " else "; 1840651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (I->first.empty()) 1841651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "if (!Scope || Scope->getName() == \"\") {\n"; 1842651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines else 1843651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "if (Scope->getName() == \"" << I->first << "\") {\n"; 1844651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " return llvm::StringSwitch<bool>(Name)\n"; 1845651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines GenerateHasAttrSpellingStringSwitch(I->second, OS, "CXX11", I->first); 1846651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "}"; 1847651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1848651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "\n}\n"; 1849651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "}\n"; 185051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 185151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 185251d8c52ad36129760eaa586f85176037e2cd0d0eMichael Hanvoid EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) { 18538f1fa25a9e9f3fa4f2d7ecc0a08ebb08c0c4e642Dmitri Gribenko emitSourceFileHeader("Code to translate different attribute spellings " 18548f1fa25a9e9f3fa4f2d7ecc0a08ebb08c0c4e642Dmitri Gribenko "into internal identifiers", OS); 185551d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han 185651d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han OS << 185751d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han " switch (AttrKind) {\n" 185851d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han " default:\n" 185951d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han " llvm_unreachable(\"Unknown attribute kind!\");\n" 186051d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han " break;\n"; 186151d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han 1862651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ParsedAttrMap Attrs = getParsedAttrList(Records); 1863651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto &I : Attrs) { 18646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const Record &R = *I.second; 1865651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R); 1866651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " case AT_" << I.first << ": {\n"; 1867651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (unsigned I = 0; I < Spellings.size(); ++ I) { 1868ef8225444452a1486bd721f3285301fe84643b00Stephen Hines OS << " if (Name == \"" << Spellings[I].name() << "\" && " 1869ef8225444452a1486bd721f3285301fe84643b00Stephen Hines << "SyntaxUsed == " 1870ef8225444452a1486bd721f3285301fe84643b00Stephen Hines << StringSwitch<unsigned>(Spellings[I].variety()) 1871ef8225444452a1486bd721f3285301fe84643b00Stephen Hines .Case("GNU", 0) 1872ef8225444452a1486bd721f3285301fe84643b00Stephen Hines .Case("CXX11", 1) 1873ef8225444452a1486bd721f3285301fe84643b00Stephen Hines .Case("Declspec", 2) 1874ef8225444452a1486bd721f3285301fe84643b00Stephen Hines .Case("Keyword", 3) 1875ef8225444452a1486bd721f3285301fe84643b00Stephen Hines .Case("Pragma", 4) 1876ef8225444452a1486bd721f3285301fe84643b00Stephen Hines .Default(0) 1877ef8225444452a1486bd721f3285301fe84643b00Stephen Hines << " && Scope == \"" << Spellings[I].nameSpace() << "\")\n" 1878ef8225444452a1486bd721f3285301fe84643b00Stephen Hines << " return " << I << ";\n"; 187951d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han } 1880651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1881651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " break;\n"; 1882651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " }\n"; 188351d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han } 188451d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han 188551d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han OS << " }\n"; 1886651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " return 0;\n"; 188751d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han} 188851d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han 1889651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// Emits code used by RecursiveASTVisitor to visit attributes 1890651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS) { 1891651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines emitSourceFileHeader("Used by RecursiveASTVisitor to visit attributes.", OS); 189251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 189351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 189451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1895651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Write method declarations for Traverse* methods. 1896651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // We emit this here because we only generate methods for attributes that 1897651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // are declared as ASTNodes. 1898651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "#ifdef ATTR_VISITOR_DECLS_ONLY\n\n"; 18996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *Attr : Attrs) { 19006bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const Record &R = *Attr; 1901651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!R.getValueAsBit("ASTNode")) 1902651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 1903651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " bool Traverse" 1904651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << R.getName() << "Attr(" << R.getName() << "Attr *A);\n"; 1905651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " bool Visit" 1906651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << R.getName() << "Attr(" << R.getName() << "Attr *A) {\n" 1907651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << " return true; \n" 1908651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << " };\n"; 1909651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1910651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "\n#else // ATTR_VISITOR_DECLS_ONLY\n\n"; 191151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1912651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Write individual Traverse* methods for each attribute class. 19136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *Attr : Attrs) { 19146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const Record &R = *Attr; 1915651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!R.getValueAsBit("ASTNode")) 1916651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 191751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1918651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "template <typename Derived>\n" 1919651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << "bool VISITORCLASS<Derived>::Traverse" 1920651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << R.getName() << "Attr(" << R.getName() << "Attr *A) {\n" 1921651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << " if (!getDerived().VisitAttr(A))\n" 1922651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << " return false;\n" 1923651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << " if (!getDerived().Visit" << R.getName() << "Attr(A))\n" 1924651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << " return false;\n"; 192551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne 1926651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args"); 19276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *Arg : ArgRecords) 19286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines createArgument(*Arg, R.getName())->writeASTVisitorTraversal(OS); 1929651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1930651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " return true;\n"; 1931651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "}\n\n"; 1932651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1933651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1934651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Write generic Traverse routine 1935651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "template <typename Derived>\n" 1936651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << "bool VISITORCLASS<Derived>::TraverseAttr(Attr *A) {\n" 1937651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << " if (!A)\n" 1938651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << " return true;\n" 1939651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << "\n" 1940651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << " switch (A->getKind()) {\n" 1941651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << " default:\n" 1942651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << " return true;\n"; 1943651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 19446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *Attr : Attrs) { 19456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const Record &R = *Attr; 1946651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!R.getValueAsBit("ASTNode")) 1947651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 1948651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1949651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " case attr::" << R.getName() << ":\n" 1950651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << " return getDerived().Traverse" << R.getName() << "Attr(" 1951651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << "cast<" << R.getName() << "Attr>(A));\n"; 195251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne } 1953651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " }\n"; // end case 1954651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "}\n"; // end function 1955651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "#endif // ATTR_VISITOR_DECLS_ONLY\n"; 195651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} 19577b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins 19583cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen// Emits code to instantiate dependent attributes on templates. 19593cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) { 19608f1fa25a9e9f3fa4f2d7ecc0a08ebb08c0c4e642Dmitri Gribenko emitSourceFileHeader("Template instantiation code for attributes", OS); 19617b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins 19627b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 19637b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins 19645bbc385ad2d8e487edfbc2756eaf4fb0b920cfe4Benjamin Kramer OS << "namespace clang {\n" 19655bbc385ad2d8e487edfbc2756eaf4fb0b920cfe4Benjamin Kramer << "namespace sema {\n\n" 19665bbc385ad2d8e487edfbc2756eaf4fb0b920cfe4Benjamin Kramer << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, " 19677b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins << "Sema &S,\n" 19687b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n" 19697b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins << " switch (At->getKind()) {\n" 19707b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins << " default:\n" 19717b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins << " break;\n"; 19727b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins 19736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *Attr : Attrs) { 19746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const Record &R = *Attr; 19753e7d31aa6050a2fb6cb35912793eb3f1b3a22030Douglas Gregor if (!R.getValueAsBit("ASTNode")) 19763e7d31aa6050a2fb6cb35912793eb3f1b3a22030Douglas Gregor continue; 19777b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins 19787b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << " case attr::" << R.getName() << ": {\n"; 197931c195ac0f3869e742d42f9d02b6cd33442fb630Rafael Espindola bool ShouldClone = R.getValueAsBit("Clone"); 198031c195ac0f3869e742d42f9d02b6cd33442fb630Rafael Espindola 198131c195ac0f3869e742d42f9d02b6cd33442fb630Rafael Espindola if (!ShouldClone) { 198231c195ac0f3869e742d42f9d02b6cd33442fb630Rafael Espindola OS << " return NULL;\n"; 198331c195ac0f3869e742d42f9d02b6cd33442fb630Rafael Espindola OS << " }\n"; 198431c195ac0f3869e742d42f9d02b6cd33442fb630Rafael Espindola continue; 198531c195ac0f3869e742d42f9d02b6cd33442fb630Rafael Espindola } 198631c195ac0f3869e742d42f9d02b6cd33442fb630Rafael Espindola 19877b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << " const " << R.getName() << "Attr *A = cast<" 19887b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins << R.getName() << "Attr>(At);\n"; 19897b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins bool TDependent = R.getValueAsBit("TemplateDependent"); 19907b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins 19917b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins if (!TDependent) { 19927b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << " return A->clone(C);\n"; 19937b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << " }\n"; 19947b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins continue; 19957b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins } 19967b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins 19977b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args"); 1998651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<std::unique_ptr<Argument>> Args; 19997b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins Args.reserve(ArgRecords.size()); 20007b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins 20016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *ArgRecord : ArgRecords) 2002651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Args.emplace_back(createArgument(*ArgRecord, R.getName())); 2003651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2004651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto const &ai : Args) 2005651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ai->writeTemplateInstantiation(OS); 20067b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins 20077b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << " return new (C) " << R.getName() << "Attr(A->getLocation(), C"; 2008651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto const &ai : Args) { 20097b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << ", "; 2010651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ai->writeTemplateInstantiationArgs(OS); 20117b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins } 2012651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << ", A->getSpellingListIndex());\n }\n"; 20137b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins } 20147b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins OS << " } // end switch\n" 20157b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins << " llvm_unreachable(\"Unknown attribute!\");\n" 20167b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins << " return 0;\n" 20175bbc385ad2d8e487edfbc2756eaf4fb0b920cfe4Benjamin Kramer << "}\n\n" 20185bbc385ad2d8e487edfbc2756eaf4fb0b920cfe4Benjamin Kramer << "} // end namespace sema\n" 20195bbc385ad2d8e487edfbc2756eaf4fb0b920cfe4Benjamin Kramer << "} // end namespace clang\n"; 20207b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins} 20217b9ff0c09025dcbe48ec7db71330e2066d1e1863DeLesley Hutchins 2022bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman// Emits the list of parsed attributes. 2023bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballmanvoid EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) { 2024bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman emitSourceFileHeader("List of all attributes that Clang recognizes", OS); 2025bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman 2026bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman OS << "#ifndef PARSED_ATTR\n"; 2027bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman OS << "#define PARSED_ATTR(NAME) NAME\n"; 2028bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman OS << "#endif\n\n"; 2029bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman 2030bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman ParsedAttrMap Names = getParsedAttrList(Records); 2031651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto &I : Names) { 2032651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "PARSED_ATTR(" << I.first << ")\n"; 2033bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman } 2034bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman} 2035bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman 2036651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic void emitArgInfo(const Record &R, std::stringstream &OS) { 2037bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman // This function will count the number of arguments specified for the 2038bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman // attribute and emit the number of required arguments followed by the 2039bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman // number of optional arguments. 2040bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman std::vector<Record *> Args = R.getValueAsListOfDefs("Args"); 2041bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman unsigned ArgCount = 0, OptCount = 0; 20426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *Arg : Args) { 2043651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Arg->getValueAsBit("Optional") ? ++OptCount : ++ArgCount; 2044bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman } 2045bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman OS << ArgCount << ", " << OptCount; 2046bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman} 2047bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman 2048651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic void GenerateDefaultAppertainsTo(raw_ostream &OS) { 2049651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "static bool defaultAppertainsTo(Sema &, const AttributeList &,"; 2050651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "const Decl *) {\n"; 2051651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " return true;\n"; 2052651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "}\n\n"; 2053651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 2054651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2055651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic std::string CalculateDiagnostic(const Record &S) { 2056651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // If the SubjectList object has a custom diagnostic associated with it, 2057651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // return that directly. 2058651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string CustomDiag = S.getValueAsString("CustomDiag"); 2059651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!CustomDiag.empty()) 2060651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return CustomDiag; 2061651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2062651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Given the list of subjects, determine what diagnostic best fits. 2063651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines enum { 2064651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Func = 1U << 0, 2065651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Var = 1U << 1, 2066651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCMethod = 1U << 2, 2067651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Param = 1U << 3, 2068651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Class = 1U << 4, 2069651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines GenericRecord = 1U << 5, 2070651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Type = 1U << 6, 2071651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCIVar = 1U << 7, 2072651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCProp = 1U << 8, 2073651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCInterface = 1U << 9, 2074651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Block = 1U << 10, 2075651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Namespace = 1U << 11, 20766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines Field = 1U << 12, 20776bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines CXXMethod = 1U << 13, 20786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ObjCProtocol = 1U << 14 2079651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines }; 2080651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines uint32_t SubMask = 0; 2081651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2082651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<Record *> Subjects = S.getValueAsListOfDefs("Subjects"); 20836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *Subject : Subjects) { 20846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const Record &R = *Subject; 2085651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string Name; 2086651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2087651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (R.isSubClassOf("SubsetSubject")) { 2088651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PrintError(R.getLoc(), "SubsetSubjects should use a custom diagnostic"); 2089651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // As a fallback, look through the SubsetSubject to see what its base 2090651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // type is, and use that. This needs to be updated if SubsetSubjects 2091651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // are allowed within other SubsetSubjects. 2092651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Name = R.getValueAsDef("Base")->getName(); 2093651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } else 2094651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Name = R.getName(); 2095651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2096651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines uint32_t V = StringSwitch<uint32_t>(Name) 2097651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines .Case("Function", Func) 2098651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines .Case("Var", Var) 2099651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines .Case("ObjCMethod", ObjCMethod) 2100651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines .Case("ParmVar", Param) 2101651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines .Case("TypedefName", Type) 2102651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines .Case("ObjCIvar", ObjCIVar) 2103651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines .Case("ObjCProperty", ObjCProp) 2104651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines .Case("Record", GenericRecord) 2105651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines .Case("ObjCInterface", ObjCInterface) 2106651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines .Case("ObjCProtocol", ObjCProtocol) 2107651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines .Case("Block", Block) 2108651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines .Case("CXXRecord", Class) 2109651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines .Case("Namespace", Namespace) 2110651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines .Case("Field", Field) 2111651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines .Case("CXXMethod", CXXMethod) 2112651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines .Default(0); 2113651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!V) { 2114651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Something wasn't in our mapping, so be helpful and let the developer 2115651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // know about it. 2116651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PrintFatalError(R.getLoc(), "Unknown subject type: " + R.getName()); 2117651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return ""; 2118651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2119651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2120651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SubMask |= V; 2121651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2122651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2123651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines switch (SubMask) { 2124651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // For the simple cases where there's only a single entry in the mask, we 2125651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // don't have to resort to bit fiddling. 2126651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines case Func: return "ExpectedFunction"; 2127651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines case Var: return "ExpectedVariable"; 2128651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines case Param: return "ExpectedParameter"; 2129651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines case Class: return "ExpectedClass"; 2130651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines case CXXMethod: 2131651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // FIXME: Currently, this maps to ExpectedMethod based on existing code, 2132651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // but should map to something a bit more accurate at some point. 2133651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines case ObjCMethod: return "ExpectedMethod"; 2134651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines case Type: return "ExpectedType"; 2135651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines case ObjCInterface: return "ExpectedObjectiveCInterface"; 2136651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines case ObjCProtocol: return "ExpectedObjectiveCProtocol"; 2137651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2138651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // "GenericRecord" means struct, union or class; check the language options 2139651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // and if not compiling for C++, strip off the class part. Note that this 2140651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // relies on the fact that the context for this declares "Sema &S". 2141651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines case GenericRecord: 2142651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return "(S.getLangOpts().CPlusPlus ? ExpectedStructOrUnionOrClass : " 2143651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "ExpectedStructOrUnion)"; 2144651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines case Func | ObjCMethod | Block: return "ExpectedFunctionMethodOrBlock"; 2145651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines case Func | ObjCMethod | Class: return "ExpectedFunctionMethodOrClass"; 2146651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines case Func | Param: 2147651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines case Func | ObjCMethod | Param: return "ExpectedFunctionMethodOrParameter"; 2148651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines case Func | ObjCMethod: return "ExpectedFunctionOrMethod"; 2149651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines case Func | Var: return "ExpectedVariableOrFunction"; 2150651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2151651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // If not compiling for C++, the class portion does not apply. 2152651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines case Func | Var | Class: 2153651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return "(S.getLangOpts().CPlusPlus ? ExpectedFunctionVariableOrClass : " 2154651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "ExpectedVariableOrFunction)"; 2155651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2156651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines case ObjCMethod | ObjCProp: return "ExpectedMethodOrProperty"; 2157651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines case Field | Var: return "ExpectedFieldOrGlobalVar"; 2158651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2159651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2160651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PrintFatalError(S.getLoc(), 2161651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "Could not deduce diagnostic argument for Attr subjects"); 2162651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2163651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return ""; 2164651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 2165651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2166651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic std::string GetSubjectWithSuffix(const Record *R) { 2167651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string B = R->getName(); 2168651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (B == "DeclBase") 2169651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return "Decl"; 2170651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return B + "Decl"; 2171651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 2172651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic std::string GenerateCustomAppertainsTo(const Record &Subject, 2173651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines raw_ostream &OS) { 2174651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string FnName = "is" + Subject.getName(); 2175651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2176651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // If this code has already been generated, simply return the previous 2177651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // instance of it. 2178651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines static std::set<std::string> CustomSubjectSet; 2179651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::set<std::string>::iterator I = CustomSubjectSet.find(FnName); 2180651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (I != CustomSubjectSet.end()) 2181651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return *I; 2182651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2183651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Record *Base = Subject.getValueAsDef("Base"); 2184651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2185651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Not currently support custom subjects within custom subjects. 2186651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Base->isSubClassOf("SubsetSubject")) { 2187651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PrintFatalError(Subject.getLoc(), 2188651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "SubsetSubjects within SubsetSubjects is not supported"); 2189651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return ""; 2190651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2191651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2192651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "static bool " << FnName << "(const Decl *D) {\n"; 2193651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " if (const " << GetSubjectWithSuffix(Base) << " *S = dyn_cast<"; 2194651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << GetSubjectWithSuffix(Base); 2195651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << ">(D))\n"; 2196651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " return " << Subject.getValueAsString("CheckCode") << ";\n"; 2197651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " return false;\n"; 2198651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "}\n\n"; 2199651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2200651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CustomSubjectSet.insert(FnName); 2201651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return FnName; 2202651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 2203651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2204651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic std::string GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) { 2205651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // If the attribute does not contain a Subjects definition, then use the 2206651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // default appertainsTo logic. 2207651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Attr.isValueUnset("Subjects")) 2208651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return "defaultAppertainsTo"; 2209651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2210651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const Record *SubjectObj = Attr.getValueAsDef("Subjects"); 2211651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<Record*> Subjects = SubjectObj->getValueAsListOfDefs("Subjects"); 2212651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2213651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // If the list of subjects is empty, it is assumed that the attribute 2214651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // appertains to everything. 2215651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Subjects.empty()) 2216651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return "defaultAppertainsTo"; 2217651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2218651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool Warn = SubjectObj->getValueAsDef("Diag")->getValueAsBit("Warn"); 2219651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2220651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Otherwise, generate an appertainsTo check specific to this attribute which 2221651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // checks all of the given subjects against the Decl passed in. Return the 2222651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // name of that check to the caller. 2223651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string FnName = "check" + Attr.getName() + "AppertainsTo"; 2224651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::stringstream SS; 2225651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SS << "static bool " << FnName << "(Sema &S, const AttributeList &Attr, "; 2226651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SS << "const Decl *D) {\n"; 2227651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SS << " if ("; 2228651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto I = Subjects.begin(), E = Subjects.end(); I != E; ++I) { 2229651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // If the subject has custom code associated with it, generate a function 2230651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // for it. The function cannot be inlined into this check (yet) because it 2231651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // requires the subject to be of a specific type, and were that information 2232651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // inlined here, it would not support an attribute with multiple custom 2233651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // subjects. 2234651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if ((*I)->isSubClassOf("SubsetSubject")) { 2235651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SS << "!" << GenerateCustomAppertainsTo(**I, OS) << "(D)"; 2236651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } else { 2237651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SS << "!isa<" << GetSubjectWithSuffix(*I) << ">(D)"; 2238651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2239651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2240651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (I + 1 != E) 2241651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SS << " && "; 2242651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2243651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SS << ") {\n"; 2244651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SS << " S.Diag(Attr.getLoc(), diag::"; 2245651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SS << (Warn ? "warn_attribute_wrong_decl_type" : 2246651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "err_attribute_wrong_decl_type"); 2247651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SS << ")\n"; 2248651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SS << " << Attr.getName() << "; 2249651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SS << CalculateDiagnostic(*SubjectObj) << ";\n"; 2250651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SS << " return false;\n"; 2251651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SS << " }\n"; 2252651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SS << " return true;\n"; 2253651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SS << "}\n\n"; 2254651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2255651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << SS.str(); 2256651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return FnName; 2257651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 2258651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2259651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic void GenerateDefaultLangOptRequirements(raw_ostream &OS) { 2260651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "static bool defaultDiagnoseLangOpts(Sema &, "; 2261651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "const AttributeList &) {\n"; 2262651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " return true;\n"; 2263651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "}\n\n"; 2264651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 2265651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2266651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic std::string GenerateLangOptRequirements(const Record &R, 2267651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines raw_ostream &OS) { 2268651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // If the attribute has an empty or unset list of language requirements, 2269651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // return the default handler. 2270651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<Record *> LangOpts = R.getValueAsListOfDefs("LangOpts"); 2271651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (LangOpts.empty()) 2272651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return "defaultDiagnoseLangOpts"; 2273651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2274651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Generate the test condition, as well as a unique function name for the 2275651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // diagnostic test. The list of options should usually be short (one or two 2276651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // options), and the uniqueness isn't strictly necessary (it is just for 2277651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // codegen efficiency). 2278651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string FnName = "check", Test; 2279651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto I = LangOpts.begin(), E = LangOpts.end(); I != E; ++I) { 2280651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string Part = (*I)->getValueAsString("Name"); 2281651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Test += "S.LangOpts." + Part; 2282651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (I + 1 != E) 2283651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Test += " || "; 2284651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FnName += Part; 2285651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2286651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FnName += "LangOpts"; 2287651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2288651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // If this code has already been generated, simply return the previous 2289651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // instance of it. 2290651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines static std::set<std::string> CustomLangOptsSet; 2291651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::set<std::string>::iterator I = CustomLangOptsSet.find(FnName); 2292651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (I != CustomLangOptsSet.end()) 2293651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return *I; 2294651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2295651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "static bool " << FnName << "(Sema &S, const AttributeList &Attr) {\n"; 2296651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " if (" << Test << ")\n"; 2297651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " return true;\n\n"; 2298651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) "; 2299651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "<< Attr.getName();\n"; 2300651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " return false;\n"; 2301651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "}\n\n"; 2302651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2303651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CustomLangOptsSet.insert(FnName); 2304651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return FnName; 2305651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 2306651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2307651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic void GenerateDefaultTargetRequirements(raw_ostream &OS) { 2308651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "static bool defaultTargetRequirements(const llvm::Triple &) {\n"; 2309651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " return true;\n"; 2310651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "}\n\n"; 2311651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 2312651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2313651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic std::string GenerateTargetRequirements(const Record &Attr, 2314651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const ParsedAttrMap &Dupes, 2315651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines raw_ostream &OS) { 2316651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // If the attribute is not a target specific attribute, return the default 2317651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // target handler. 2318651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!Attr.isSubClassOf("TargetSpecificAttr")) 2319651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return "defaultTargetRequirements"; 2320651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2321651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Get the list of architectures to be tested for. 2322651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const Record *R = Attr.getValueAsDef("Target"); 2323651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<std::string> Arches = R->getValueAsListOfStrings("Arches"); 2324651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Arches.empty()) { 2325651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PrintError(Attr.getLoc(), "Empty list of target architectures for a " 2326651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "target-specific attr"); 2327651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return "defaultTargetRequirements"; 2328651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2329651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2330651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // If there are other attributes which share the same parsed attribute kind, 2331651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // such as target-specific attributes with a shared spelling, collapse the 2332651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // duplicate architectures. This is required because a shared target-specific 2333651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // attribute has only one AttributeList::Kind enumeration value, but it 2334651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // applies to multiple target architectures. In order for the attribute to be 2335651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // considered valid, all of its architectures need to be included. 2336651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!Attr.isValueUnset("ParseKind")) { 2337651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string APK = Attr.getValueAsString("ParseKind"); 2338651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto &I : Dupes) { 2339651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (I.first == APK) { 2340651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<std::string> DA = I.second->getValueAsDef("Target") 2341651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ->getValueAsListOfStrings("Arches"); 2342651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::copy(DA.begin(), DA.end(), std::back_inserter(Arches)); 2343651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2344651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2345651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2346651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2347651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string FnName = "isTarget", Test = "("; 2348651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto I = Arches.begin(), E = Arches.end(); I != E; ++I) { 2349651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string Part = *I; 2350651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Test += "Arch == llvm::Triple::" + Part; 2351651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (I + 1 != E) 2352651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Test += " || "; 2353651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FnName += Part; 2354651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2355651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Test += ")"; 2356651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2357651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // If the target also requires OS testing, generate those tests as well. 2358651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool UsesOS = false; 2359651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!R->isValueUnset("OSes")) { 2360651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines UsesOS = true; 2361651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2362651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // We know that there was at least one arch test, so we need to and in the 2363651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // OS tests. 2364651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Test += " && ("; 2365651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<std::string> OSes = R->getValueAsListOfStrings("OSes"); 2366651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto I = OSes.begin(), E = OSes.end(); I != E; ++I) { 2367651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string Part = *I; 2368651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2369651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Test += "OS == llvm::Triple::" + Part; 2370651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (I + 1 != E) 2371651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Test += " || "; 2372651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FnName += Part; 2373651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2374651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Test += ")"; 2375651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2376651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2377651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // If this code has already been generated, simply return the previous 2378651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // instance of it. 2379651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines static std::set<std::string> CustomTargetSet; 2380651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::set<std::string>::iterator I = CustomTargetSet.find(FnName); 2381651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (I != CustomTargetSet.end()) 2382651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return *I; 2383651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2384651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "static bool " << FnName << "(const llvm::Triple &T) {\n"; 2385651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " llvm::Triple::ArchType Arch = T.getArch();\n"; 2386651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (UsesOS) 2387651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " llvm::Triple::OSType OS = T.getOS();\n"; 2388651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " return " << Test << ";\n"; 2389651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "}\n\n"; 2390651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2391651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CustomTargetSet.insert(FnName); 2392651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return FnName; 2393651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 2394651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2395651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic void GenerateDefaultSpellingIndexToSemanticSpelling(raw_ostream &OS) { 2396651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "static unsigned defaultSpellingIndexToSemanticSpelling(" 2397651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << "const AttributeList &Attr) {\n"; 2398651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " return UINT_MAX;\n"; 2399651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "}\n\n"; 2400651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 2401651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2402651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic std::string GenerateSpellingIndexToSemanticSpelling(const Record &Attr, 2403651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines raw_ostream &OS) { 2404651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // If the attribute does not have a semantic form, we can bail out early. 2405651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!Attr.getValueAsBit("ASTNode")) 2406651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return "defaultSpellingIndexToSemanticSpelling"; 2407651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2408651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr); 2409651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2410651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // If there are zero or one spellings, or all of the spellings share the same 2411651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // name, we can also bail out early. 2412651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Spellings.size() <= 1 || SpellingNamesAreCommon(Spellings)) 2413651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return "defaultSpellingIndexToSemanticSpelling"; 2414651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2415651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Generate the enumeration we will use for the mapping. 2416651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SemanticSpellingMap SemanticToSyntacticMap; 2417651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string Enum = CreateSemanticSpellings(Spellings, SemanticToSyntacticMap); 2418651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string Name = Attr.getName() + "AttrSpellingMap"; 2419651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2420651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "static unsigned " << Name << "(const AttributeList &Attr) {\n"; 2421651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << Enum; 2422651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " unsigned Idx = Attr.getAttributeSpellingListIndex();\n"; 2423651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines WriteSemanticSpellingSwitch("Idx", SemanticToSyntacticMap, OS); 2424651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "}\n\n"; 2425651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2426651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return Name; 2427651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 2428651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2429651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic bool IsKnownToGCC(const Record &Attr) { 2430651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Look at the spellings for this subject; if there are any spellings which 2431651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // claim to be known to GCC, the attribute is known to GCC. 2432651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr); 2433651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto &I : Spellings) { 2434651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (I.knownToGCC()) 2435651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return true; 2436651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2437651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return false; 2438651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 2439651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2440bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman/// Emits the parsed attribute helpers 2441bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballmanvoid EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) { 2442bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman emitSourceFileHeader("Parsed attribute helpers", OS); 2443bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman 2444651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Get the list of parsed attributes, and accept the optional list of 2445651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // duplicates due to the ParseKind. 2446651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ParsedAttrMap Dupes; 2447651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ParsedAttrMap Attrs = getParsedAttrList(Records, &Dupes); 2448651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2449651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Generate the default appertainsTo, target and language option diagnostic, 2450651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // and spelling list index mapping methods. 2451651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines GenerateDefaultAppertainsTo(OS); 2452651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines GenerateDefaultLangOptRequirements(OS); 2453651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines GenerateDefaultTargetRequirements(OS); 2454651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines GenerateDefaultSpellingIndexToSemanticSpelling(OS); 2455651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2456651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Generate the appertainsTo diagnostic methods and write their names into 2457651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // another mapping. At the same time, generate the AttrInfoMap object 2458651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // contents. Due to the reliance on generated code, use separate streams so 2459651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // that code will not be interleaved. 2460651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::stringstream SS; 2461651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto I = Attrs.begin(), E = Attrs.end(); I != E; ++I) { 2462651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // TODO: If the attribute's kind appears in the list of duplicates, that is 2463651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // because it is a target-specific attribute that appears multiple times. 2464651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // It would be beneficial to test whether the duplicates are "similar 2465651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // enough" to each other to not cause problems. For instance, check that 2466651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // the spellings are identical, and custom parsing rules match, etc. 2467bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman 2468bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman // We need to generate struct instances based off ParsedAttrInfo from 2469bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman // AttributeList.cpp. 2470651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SS << " { "; 2471651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines emitArgInfo(*I->second, SS); 2472651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SS << ", " << I->second->getValueAsBit("HasCustomParsing"); 2473651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SS << ", " << I->second->isSubClassOf("TargetSpecificAttr"); 2474651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SS << ", " << I->second->isSubClassOf("TypeAttr"); 2475651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SS << ", " << IsKnownToGCC(*I->second); 2476651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SS << ", " << GenerateAppertainsTo(*I->second, OS); 2477651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SS << ", " << GenerateLangOptRequirements(*I->second, OS); 2478651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SS << ", " << GenerateTargetRequirements(*I->second, Dupes, OS); 2479651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SS << ", " << GenerateSpellingIndexToSemanticSpelling(*I->second, OS); 2480651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SS << " }"; 2481bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman 2482bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman if (I + 1 != E) 2483651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SS << ","; 2484651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2485651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SS << " // AT_" << I->first << "\n"; 2486bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman } 2487651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2488651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "static const ParsedAttrInfo AttrInfoMap[AttributeList::UnknownAttribute + 1] = {\n"; 2489651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << SS.str(); 2490bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman OS << "};\n\n"; 2491e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han} 2492e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han 24933cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen// Emits the kind list of parsed attributes 24943cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) { 24958f1fa25a9e9f3fa4f2d7ecc0a08ebb08c0c4e642Dmitri Gribenko emitSourceFileHeader("Attribute name matcher", OS); 24968f1fa25a9e9f3fa4f2d7ecc0a08ebb08c0c4e642Dmitri Gribenko 2497651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"); 2498ef8225444452a1486bd721f3285301fe84643b00Stephen Hines std::vector<StringMatcher::StringPair> GNU, Declspec, CXX11, Keywords, Pragma; 2499651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::set<std::string> Seen; 25006bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *A : Attrs) { 25016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const Record &Attr = *A; 2502e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han 2503e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han bool SemaHandler = Attr.getValueAsBit("SemaHandler"); 2504331d2ec7cd4c6b5e29cc61fcdc617bf708223cd4Douglas Gregor bool Ignored = Attr.getValueAsBit("Ignored"); 2505331d2ec7cd4c6b5e29cc61fcdc617bf708223cd4Douglas Gregor if (SemaHandler || Ignored) { 2506651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Attribute spellings can be shared between target-specific attributes, 2507651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // and can be shared between syntaxes for the same attribute. For 2508651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // instance, an attribute can be spelled GNU<"interrupt"> for an ARM- 2509651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // specific attribute, or MSP430-specific attribute. Additionally, an 2510651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // attribute can be spelled GNU<"dllexport"> and Declspec<"dllexport"> 2511651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // for the same semantic attribute. Ultimately, we need to map each of 2512651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // these to a single AttributeList::Kind value, but the StringMatcher 2513651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // class cannot handle duplicate match strings. So we generate a list of 2514651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // string to match based on the syntax, and emit multiple string matchers 2515651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // depending on the syntax used. 2516651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string AttrName; 2517651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Attr.isSubClassOf("TargetSpecificAttr") && 2518651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines !Attr.isValueUnset("ParseKind")) { 2519651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines AttrName = Attr.getValueAsString("ParseKind"); 2520651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Seen.find(AttrName) != Seen.end()) 2521651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 2522651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Seen.insert(AttrName); 2523651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } else 2524651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines AttrName = NormalizeAttrName(StringRef(Attr.getName())).str(); 2525651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2526651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr); 2527651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto &S : Spellings) { 2528651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string RawSpelling = S.name(); 25296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines std::vector<StringMatcher::StringPair> *Matches = nullptr; 2530651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string Spelling, Variety = S.variety(); 2531651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Variety == "CXX11") { 2532651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Matches = &CXX11; 2533651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Spelling += S.nameSpace(); 25348e083e71d48f7f4d6ef40c00531c2e14df745486Sean Hunt Spelling += "::"; 2535651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } else if (Variety == "GNU") 2536651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Matches = &GNU; 2537651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines else if (Variety == "Declspec") 2538651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Matches = &Declspec; 2539651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines else if (Variety == "Keyword") 2540651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Matches = &Keywords; 2541ef8225444452a1486bd721f3285301fe84643b00Stephen Hines else if (Variety == "Pragma") 2542ef8225444452a1486bd721f3285301fe84643b00Stephen Hines Matches = &Pragma; 2543651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2544651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines assert(Matches && "Unsupported spelling variety found"); 254593f95f2a2cbb6bb3d17bfb5fc74ce1cccea751b6Sean Hunt 2546651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Spelling += NormalizeAttrSpelling(RawSpelling); 2547331d2ec7cd4c6b5e29cc61fcdc617bf708223cd4Douglas Gregor if (SemaHandler) 2548651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Matches->push_back(StringMatcher::StringPair(Spelling, 2549651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "return AttributeList::AT_" + AttrName + ";")); 2550331d2ec7cd4c6b5e29cc61fcdc617bf708223cd4Douglas Gregor else 2551651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Matches->push_back(StringMatcher::StringPair(Spelling, 2552651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "return AttributeList::IgnoredAttribute;")); 2553e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han } 2554e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han } 2555e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han } 25560c19b3c38e356058aeb2424d175eae232bf014d9Douglas Gregor 2557651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "static AttributeList::Kind getAttrKind(StringRef Name, "; 2558651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "AttributeList::Syntax Syntax) {\n"; 2559651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " if (AttributeList::AS_GNU == Syntax) {\n"; 2560651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines StringMatcher("Name", GNU, OS).Emit(); 2561651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " } else if (AttributeList::AS_Declspec == Syntax) {\n"; 2562651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines StringMatcher("Name", Declspec, OS).Emit(); 2563651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " } else if (AttributeList::AS_CXX11 == Syntax) {\n"; 2564651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines StringMatcher("Name", CXX11, OS).Emit(); 2565651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " } else if (AttributeList::AS_Keyword == Syntax) {\n"; 2566651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines StringMatcher("Name", Keywords, OS).Emit(); 2567ef8225444452a1486bd721f3285301fe84643b00Stephen Hines OS << " } else if (AttributeList::AS_Pragma == Syntax) {\n"; 2568ef8225444452a1486bd721f3285301fe84643b00Stephen Hines StringMatcher("Name", Pragma, OS).Emit(); 2569651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " }\n"; 2570651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " return AttributeList::UnknownAttribute;\n" 25710c19b3c38e356058aeb2424d175eae232bf014d9Douglas Gregor << "}\n"; 2572e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han} 2573e53ac8aea2d9e8bbb11191398ea3cc2edb2d171aMichael Han 2574c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko// Emits the code to dump an attribute. 2575c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienkovoid EmitClangAttrDump(RecordKeeper &Records, raw_ostream &OS) { 25768f1fa25a9e9f3fa4f2d7ecc0a08ebb08c0c4e642Dmitri Gribenko emitSourceFileHeader("Attribute dumper", OS); 25778f1fa25a9e9f3fa4f2d7ecc0a08ebb08c0c4e642Dmitri Gribenko 2578c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko OS << 2579c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko " switch (A->getKind()) {\n" 2580c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko " default:\n" 2581c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko " llvm_unreachable(\"Unknown attribute kind!\");\n" 2582c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko " break;\n"; 2583c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args; 25846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *Attr : Attrs) { 25856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const Record &R = *Attr; 2586c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko if (!R.getValueAsBit("ASTNode")) 2587c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko continue; 2588c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko OS << " case attr::" << R.getName() << ": {\n"; 2589651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2590651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // If the attribute has a semantically-meaningful name (which is determined 2591651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // by whether there is a Spelling enumeration for it), then write out the 2592651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // spelling used for the attribute. 2593651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R); 2594651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Spellings.size() > 1 && !SpellingNamesAreCommon(Spellings)) 2595651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " OS << \" \" << A->getSpelling();\n"; 2596651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2597c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko Args = R.getValueAsListOfDefs("Args"); 2598c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko if (!Args.empty()) { 2599c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName() 2600c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko << "Attr>(A);\n"; 26016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *Arg : Args) 26026bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines createArgument(*Arg, R.getName())->writeDump(OS); 2603e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu 2604e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu // Code for detecting the last child. 2605e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu OS << " bool OldMoreChildren = hasMoreChildren();\n"; 2606651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " bool MoreChildren;\n"; 2607e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu 2608651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto AI = Args.begin(), AE = Args.end(); AI != AE; ++AI) { 2609e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu // More code for detecting the last child. 2610e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu OS << " MoreChildren = OldMoreChildren"; 2611651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto Next = AI + 1; Next != AE; ++Next) { 2612e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu OS << " || "; 2613e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu createArgument(**Next, R.getName())->writeHasChildren(OS); 2614e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu } 2615e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu OS << ";\n"; 2616e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu OS << " setMoreChildren(MoreChildren);\n"; 2617e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu 2618651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines createArgument(**AI, R.getName())->writeDumpChildren(OS); 2619e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu } 2620e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu 2621e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu // Reset the last child. 2622e8d411997899a87e1a9f63ad3f52b38e7931687cRichard Trieu OS << " setMoreChildren(OldMoreChildren);\n"; 2623c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko } 2624c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko OS << 2625c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko " break;\n" 2626c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko " }\n"; 2627c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko } 2628c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko OS << " }\n"; 2629c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko} 2630c3cd2b0d538e4db78f1bcbedd0085e2005ce5c51Alexander Kornienko 2631651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid EmitClangAttrParserStringSwitches(RecordKeeper &Records, 2632651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines raw_ostream &OS) { 2633651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines emitSourceFileHeader("Parser-related llvm::StringSwitch cases", OS); 2634651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines emitClangAttrArgContextList(Records, OS); 2635651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines emitClangAttrIdentifierArgList(Records, OS); 2636651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines emitClangAttrTypeArgList(Records, OS); 2637651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines emitClangAttrLateParsedList(Records, OS); 2638651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 2639651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2640651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesclass DocumentationData { 2641651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinespublic: 2642651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const Record *Documentation; 2643651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const Record *Attribute; 2644651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2645651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines DocumentationData(const Record &Documentation, const Record &Attribute) 2646651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines : Documentation(&Documentation), Attribute(&Attribute) {} 2647651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}; 2648651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2649651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic void WriteCategoryHeader(const Record *DocCategory, 2650651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines raw_ostream &OS) { 2651651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const std::string &Name = DocCategory->getValueAsString("Name"); 2652651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << Name << "\n" << std::string(Name.length(), '=') << "\n"; 2653651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2654651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // If there is content, print that as well. 2655651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string ContentStr = DocCategory->getValueAsString("Content"); 2656651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!ContentStr.empty()) { 2657651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Trim leading and trailing newlines and spaces. 2658651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines StringRef Content(ContentStr); 2659651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines while (Content.startswith("\r") || Content.startswith("\n") || 2660651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Content.startswith(" ") || Content.startswith("\t")) 2661651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Content = Content.substr(1); 2662651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines while (Content.endswith("\r") || Content.endswith("\n") || 2663651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Content.endswith(" ") || Content.endswith("\t")) 2664651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Content = Content.substr(0, Content.size() - 1); 2665651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << Content; 2666651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2667651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "\n\n"; 2668651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 2669651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2670651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesenum SpellingKind { 2671651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines GNU = 1 << 0, 2672651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CXX11 = 1 << 1, 2673651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Declspec = 1 << 2, 2674ef8225444452a1486bd721f3285301fe84643b00Stephen Hines Keyword = 1 << 3, 2675ef8225444452a1486bd721f3285301fe84643b00Stephen Hines Pragma = 1 << 4 2676651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}; 2677651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2678651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic void WriteDocumentation(const DocumentationData &Doc, 2679651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines raw_ostream &OS) { 2680651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // FIXME: there is no way to have a per-spelling category for the attribute 2681651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // documentation. This may not be a limiting factor since the spellings 2682651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // should generally be consistently applied across the category. 2683651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2684651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(*Doc.Attribute); 2685651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2686651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Determine the heading to be used for this attribute. 2687651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string Heading = Doc.Documentation->getValueAsString("Heading"); 2688651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool CustomHeading = !Heading.empty(); 2689651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Heading.empty()) { 2690651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // If there's only one spelling, we can simply use that. 2691651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Spellings.size() == 1) 2692651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Heading = Spellings.begin()->name(); 2693651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines else { 2694651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::set<std::string> Uniques; 2695651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto I = Spellings.begin(), E = Spellings.end(); 2696651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines I != E && Uniques.size() <= 1; ++I) { 2697651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string Spelling = NormalizeNameForSpellingComparison(I->name()); 2698651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Uniques.insert(Spelling); 2699651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2700651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // If the semantic map has only one spelling, that is sufficient for our 2701651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // needs. 2702651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Uniques.size() == 1) 2703651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Heading = *Uniques.begin(); 2704651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2705651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2706651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2707651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // If the heading is still empty, it is an error. 2708651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Heading.empty()) 2709651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PrintFatalError(Doc.Attribute->getLoc(), 2710651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "This attribute requires a heading to be specified"); 2711651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2712651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Gather a list of unique spellings; this is not the same as the semantic 2713651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // spelling for the attribute. Variations in underscores and other non- 2714651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // semantic characters are still acceptable. 2715651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<std::string> Names; 2716651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2717651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines unsigned SupportedSpellings = 0; 2718651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto &I : Spellings) { 2719651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SpellingKind Kind = StringSwitch<SpellingKind>(I.variety()) 2720ef8225444452a1486bd721f3285301fe84643b00Stephen Hines .Case("GNU", GNU) 2721ef8225444452a1486bd721f3285301fe84643b00Stephen Hines .Case("CXX11", CXX11) 2722ef8225444452a1486bd721f3285301fe84643b00Stephen Hines .Case("Declspec", Declspec) 2723ef8225444452a1486bd721f3285301fe84643b00Stephen Hines .Case("Keyword", Keyword) 2724ef8225444452a1486bd721f3285301fe84643b00Stephen Hines .Case("Pragma", Pragma); 2725651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2726651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Mask in the supported spelling. 2727651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SupportedSpellings |= Kind; 2728651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2729651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string Name; 2730651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Kind == CXX11 && !I.nameSpace().empty()) 2731651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Name = I.nameSpace() + "::"; 2732651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Name += I.name(); 2733651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2734651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // If this name is the same as the heading, do not add it. 2735651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Name != Heading) 2736651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Names.push_back(Name); 2737651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2738651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2739651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Print out the heading for the attribute. If there are alternate spellings, 2740651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // then display those after the heading. 2741651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!CustomHeading && !Names.empty()) { 2742651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Heading += " ("; 2743651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto I = Names.begin(), E = Names.end(); I != E; ++I) { 2744651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (I != Names.begin()) 2745651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Heading += ", "; 2746651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Heading += *I; 2747651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2748651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Heading += ")"; 2749651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2750651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << Heading << "\n" << std::string(Heading.length(), '-') << "\n"; 2751651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2752651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!SupportedSpellings) 2753651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PrintFatalError(Doc.Attribute->getLoc(), 2754651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "Attribute has no supported spellings; cannot be " 2755651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "documented"); 2756651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2757651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // List what spelling syntaxes the attribute supports. 2758651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << ".. csv-table:: Supported Syntaxes\n"; 2759ef8225444452a1486bd721f3285301fe84643b00Stephen Hines OS << " :header: \"GNU\", \"C++11\", \"__declspec\", \"Keyword\","; 2760ef8225444452a1486bd721f3285301fe84643b00Stephen Hines OS << " \"Pragma\"\n\n"; 2761651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " \""; 2762651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (SupportedSpellings & GNU) OS << "X"; 2763651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "\",\""; 2764651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (SupportedSpellings & CXX11) OS << "X"; 2765651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "\",\""; 2766651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (SupportedSpellings & Declspec) OS << "X"; 2767651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "\",\""; 2768651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (SupportedSpellings & Keyword) OS << "X"; 2769ef8225444452a1486bd721f3285301fe84643b00Stephen Hines OS << "\", \""; 2770ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (SupportedSpellings & Pragma) OS << "X"; 2771651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "\"\n\n"; 2772651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2773651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // If the attribute is deprecated, print a message about it, and possibly 2774651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // provide a replacement attribute. 2775651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!Doc.Documentation->isValueUnset("Deprecated")) { 2776651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "This attribute has been deprecated, and may be removed in a future " 2777651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << "version of Clang."; 2778651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const Record &Deprecated = *Doc.Documentation->getValueAsDef("Deprecated"); 2779651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string Replacement = Deprecated.getValueAsString("Replacement"); 2780651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!Replacement.empty()) 2781651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " This attribute has been superseded by ``" 2782651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << Replacement << "``."; 2783651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "\n\n"; 2784651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2785651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2786651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string ContentStr = Doc.Documentation->getValueAsString("Content"); 2787651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Trim leading and trailing newlines and spaces. 2788651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines StringRef Content(ContentStr); 2789651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines while (Content.startswith("\r") || Content.startswith("\n") || 2790651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Content.startswith(" ") || Content.startswith("\t")) 2791651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Content = Content.substr(1); 2792651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines while (Content.endswith("\r") || Content.endswith("\n") || 2793651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Content.endswith(" ") || Content.endswith("\t")) 2794651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Content = Content.substr(0, Content.size() - 1); 2795651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << Content; 2796651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2797651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "\n\n\n"; 2798651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 2799651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2800651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid EmitClangAttrDocs(RecordKeeper &Records, raw_ostream &OS) { 2801651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Get the documentation introduction paragraph. 2802651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const Record *Documentation = Records.getDef("GlobalDocumentation"); 2803651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!Documentation) { 2804651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PrintFatalError("The Documentation top-level definition is missing, " 2805651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "no documentation will be generated."); 2806651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return; 2807651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2808651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2809651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << Documentation->getValueAsString("Intro") << "\n"; 2810651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2811651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Gather the Documentation lists from each of the attributes, based on the 2812651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // category provided. 2813651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"); 2814651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::map<const Record *, std::vector<DocumentationData>> SplitDocs; 28156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *A : Attrs) { 28166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const Record &Attr = *A; 2817651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<Record *> Docs = Attr.getValueAsListOfDefs("Documentation"); 28186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines for (const auto *D : Docs) { 28196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const Record &Doc = *D; 2820651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const Record *Category = Doc.getValueAsDef("Category"); 2821651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // If the category is "undocumented", then there cannot be any other 2822651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // documentation categories (otherwise, the attribute would become 2823651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // documented). 2824651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string Cat = Category->getValueAsString("Name"); 2825651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool Undocumented = Cat == "Undocumented"; 2826651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Undocumented && Docs.size() > 1) 2827651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PrintFatalError(Doc.getLoc(), 2828651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "Attribute is \"Undocumented\", but has multiple " 2829651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "documentation categories"); 2830651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2831651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!Undocumented) 2832651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SplitDocs[Category].push_back(DocumentationData(Doc, Attr)); 2833651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2834651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2835651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2836651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Having split the attributes out based on what documentation goes where, 2837651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // we can begin to generate sections of documentation. 2838651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto &I : SplitDocs) { 2839651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines WriteCategoryHeader(I.first, OS); 2840651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2841651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Walk over each of the attributes in the category and write out their 2842651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // documentation. 2843651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto &Doc : I.second) 2844651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines WriteDocumentation(Doc, OS); 2845651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2846651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 2847651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 28483cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // end namespace clang 2849