1226586Sdim//===- ClangAttrEmitter.cpp - Generate Clang attribute handling =-*- C++ -*--=// 2226586Sdim// 3226586Sdim// The LLVM Compiler Infrastructure 4226586Sdim// 5226586Sdim// This file is distributed under the University of Illinois Open Source 6226586Sdim// License. See LICENSE.TXT for details. 7226586Sdim// 8226586Sdim//===----------------------------------------------------------------------===// 9226586Sdim// 10226586Sdim// These tablegen backends emit Clang attribute processing code 11226586Sdim// 12226586Sdim//===----------------------------------------------------------------------===// 13226586Sdim 14245431Sdim#include "llvm/ADT/SmallString.h" 15226586Sdim#include "llvm/ADT/StringSwitch.h" 16263509Sdim#include "llvm/ADT/SmallSet.h" 17226586Sdim#include "llvm/TableGen/Record.h" 18245431Sdim#include "llvm/TableGen/StringMatcher.h" 19245431Sdim#include "llvm/TableGen/TableGenBackend.h" 20226586Sdim#include <algorithm> 21226586Sdim#include <cctype> 22226586Sdim 23226586Sdimusing namespace llvm; 24226586Sdim 25226586Sdimstatic const std::vector<StringRef> 26226586SdimgetValueAsListOfStrings(Record &R, StringRef FieldName) { 27226586Sdim ListInit *List = R.getValueAsListInit(FieldName); 28226586Sdim assert (List && "Got a null ListInit"); 29226586Sdim 30226586Sdim std::vector<StringRef> Strings; 31226586Sdim Strings.reserve(List->getSize()); 32226586Sdim 33226586Sdim for (ListInit::const_iterator i = List->begin(), e = List->end(); 34226586Sdim i != e; 35226586Sdim ++i) { 36226586Sdim assert(*i && "Got a null element in a ListInit"); 37245431Sdim if (StringInit *S = dyn_cast<StringInit>(*i)) 38226586Sdim Strings.push_back(S->getValue()); 39226586Sdim else 40226586Sdim assert(false && "Got a non-string, non-code element in a ListInit"); 41226586Sdim } 42226586Sdim 43226586Sdim return Strings; 44226586Sdim} 45226586Sdim 46226586Sdimstatic std::string ReadPCHRecord(StringRef type) { 47226586Sdim return StringSwitch<std::string>(type) 48226586Sdim .EndsWith("Decl *", "GetLocalDeclAs<" 49226586Sdim + std::string(type, 0, type.size()-1) + ">(F, Record[Idx++])") 50263509Sdim .Case("TypeSourceInfo *", "GetTypeSourceInfo(F, Record, Idx)") 51252723Sdim .Case("Expr *", "ReadExpr(F)") 52226586Sdim .Case("IdentifierInfo *", "GetIdentifierInfo(F, Record, Idx)") 53226586Sdim .Case("SourceLocation", "ReadSourceLocation(F, Record, Idx)") 54226586Sdim .Default("Record[Idx++]"); 55226586Sdim} 56226586Sdim 57226586Sdim// Assumes that the way to get the value is SA->getname() 58226586Sdimstatic std::string WritePCHRecord(StringRef type, StringRef name) { 59226586Sdim return StringSwitch<std::string>(type) 60226586Sdim .EndsWith("Decl *", "AddDeclRef(" + std::string(name) + 61226586Sdim ", Record);\n") 62263509Sdim .Case("TypeSourceInfo *", 63263509Sdim "AddTypeSourceInfo(" + std::string(name) + ", Record);\n") 64226586Sdim .Case("Expr *", "AddStmt(" + std::string(name) + ");\n") 65226586Sdim .Case("IdentifierInfo *", 66226586Sdim "AddIdentifierRef(" + std::string(name) + ", Record);\n") 67226586Sdim .Case("SourceLocation", 68226586Sdim "AddSourceLocation(" + std::string(name) + ", Record);\n") 69226586Sdim .Default("Record.push_back(" + std::string(name) + ");\n"); 70226586Sdim} 71226586Sdim 72235633Sdim// Normalize attribute name by removing leading and trailing 73235633Sdim// underscores. For example, __foo, foo__, __foo__ would 74235633Sdim// become foo. 75235633Sdimstatic StringRef NormalizeAttrName(StringRef AttrName) { 76235633Sdim if (AttrName.startswith("__")) 77235633Sdim AttrName = AttrName.substr(2, AttrName.size()); 78235633Sdim 79235633Sdim if (AttrName.endswith("__")) 80235633Sdim AttrName = AttrName.substr(0, AttrName.size() - 2); 81235633Sdim 82235633Sdim return AttrName; 83235633Sdim} 84235633Sdim 85235633Sdim// Normalize attribute spelling only if the spelling has both leading 86235633Sdim// and trailing underscores. For example, __ms_struct__ will be 87235633Sdim// normalized to "ms_struct"; __cdecl will remain intact. 88235633Sdimstatic StringRef NormalizeAttrSpelling(StringRef AttrSpelling) { 89235633Sdim if (AttrSpelling.startswith("__") && AttrSpelling.endswith("__")) { 90235633Sdim AttrSpelling = AttrSpelling.substr(2, AttrSpelling.size() - 4); 91235633Sdim } 92235633Sdim 93235633Sdim return AttrSpelling; 94235633Sdim} 95235633Sdim 96226586Sdimnamespace { 97226586Sdim class Argument { 98226586Sdim std::string lowerName, upperName; 99226586Sdim StringRef attrName; 100263509Sdim bool isOpt; 101226586Sdim 102226586Sdim public: 103226586Sdim Argument(Record &Arg, StringRef Attr) 104226586Sdim : lowerName(Arg.getValueAsString("Name")), upperName(lowerName), 105263509Sdim attrName(Attr), isOpt(false) { 106226586Sdim if (!lowerName.empty()) { 107226586Sdim lowerName[0] = std::tolower(lowerName[0]); 108226586Sdim upperName[0] = std::toupper(upperName[0]); 109226586Sdim } 110226586Sdim } 111226586Sdim virtual ~Argument() {} 112226586Sdim 113226586Sdim StringRef getLowerName() const { return lowerName; } 114226586Sdim StringRef getUpperName() const { return upperName; } 115226586Sdim StringRef getAttrName() const { return attrName; } 116226586Sdim 117263509Sdim bool isOptional() const { return isOpt; } 118263509Sdim void setOptional(bool set) { isOpt = set; } 119263509Sdim 120226586Sdim // These functions print the argument contents formatted in different ways. 121226586Sdim virtual void writeAccessors(raw_ostream &OS) const = 0; 122226586Sdim virtual void writeAccessorDefinitions(raw_ostream &OS) const {} 123226586Sdim virtual void writeCloneArgs(raw_ostream &OS) const = 0; 124235633Sdim virtual void writeTemplateInstantiationArgs(raw_ostream &OS) const = 0; 125235633Sdim virtual void writeTemplateInstantiation(raw_ostream &OS) const {} 126226586Sdim virtual void writeCtorBody(raw_ostream &OS) const {} 127226586Sdim virtual void writeCtorInitializers(raw_ostream &OS) const = 0; 128263509Sdim virtual void writeCtorDefaultInitializers(raw_ostream &OS) const = 0; 129226586Sdim virtual void writeCtorParameters(raw_ostream &OS) const = 0; 130226586Sdim virtual void writeDeclarations(raw_ostream &OS) const = 0; 131226586Sdim virtual void writePCHReadArgs(raw_ostream &OS) const = 0; 132226586Sdim virtual void writePCHReadDecls(raw_ostream &OS) const = 0; 133226586Sdim virtual void writePCHWrite(raw_ostream &OS) const = 0; 134235633Sdim virtual void writeValue(raw_ostream &OS) const = 0; 135252723Sdim virtual void writeDump(raw_ostream &OS) const = 0; 136252723Sdim virtual void writeDumpChildren(raw_ostream &OS) const {} 137252723Sdim virtual void writeHasChildren(raw_ostream &OS) const { OS << "false"; } 138263509Sdim 139263509Sdim virtual bool isEnumArg() const { return false; } 140263509Sdim virtual bool isVariadicEnumArg() const { return false; } 141226586Sdim }; 142226586Sdim 143226586Sdim class SimpleArgument : public Argument { 144226586Sdim std::string type; 145226586Sdim 146226586Sdim public: 147226586Sdim SimpleArgument(Record &Arg, StringRef Attr, std::string T) 148226586Sdim : Argument(Arg, Attr), type(T) 149226586Sdim {} 150226586Sdim 151235633Sdim std::string getType() const { return type; } 152235633Sdim 153226586Sdim void writeAccessors(raw_ostream &OS) const { 154226586Sdim OS << " " << type << " get" << getUpperName() << "() const {\n"; 155226586Sdim OS << " return " << getLowerName() << ";\n"; 156226586Sdim OS << " }"; 157226586Sdim } 158226586Sdim void writeCloneArgs(raw_ostream &OS) const { 159226586Sdim OS << getLowerName(); 160226586Sdim } 161235633Sdim void writeTemplateInstantiationArgs(raw_ostream &OS) const { 162235633Sdim OS << "A->get" << getUpperName() << "()"; 163235633Sdim } 164226586Sdim void writeCtorInitializers(raw_ostream &OS) const { 165226586Sdim OS << getLowerName() << "(" << getUpperName() << ")"; 166226586Sdim } 167263509Sdim void writeCtorDefaultInitializers(raw_ostream &OS) const { 168263509Sdim OS << getLowerName() << "()"; 169263509Sdim } 170226586Sdim void writeCtorParameters(raw_ostream &OS) const { 171226586Sdim OS << type << " " << getUpperName(); 172226586Sdim } 173226586Sdim void writeDeclarations(raw_ostream &OS) const { 174226586Sdim OS << type << " " << getLowerName() << ";"; 175226586Sdim } 176226586Sdim void writePCHReadDecls(raw_ostream &OS) const { 177226586Sdim std::string read = ReadPCHRecord(type); 178226586Sdim OS << " " << type << " " << getLowerName() << " = " << read << ";\n"; 179226586Sdim } 180226586Sdim void writePCHReadArgs(raw_ostream &OS) const { 181226586Sdim OS << getLowerName(); 182226586Sdim } 183226586Sdim void writePCHWrite(raw_ostream &OS) const { 184226586Sdim OS << " " << WritePCHRecord(type, "SA->get" + 185226586Sdim std::string(getUpperName()) + "()"); 186226586Sdim } 187235633Sdim void writeValue(raw_ostream &OS) const { 188235633Sdim if (type == "FunctionDecl *") { 189263509Sdim OS << "\" << get" << getUpperName() 190263509Sdim << "()->getNameInfo().getAsString() << \""; 191235633Sdim } else if (type == "IdentifierInfo *") { 192235633Sdim OS << "\" << get" << getUpperName() << "()->getName() << \""; 193263509Sdim } else if (type == "TypeSourceInfo *") { 194235633Sdim OS << "\" << get" << getUpperName() << "().getAsString() << \""; 195235633Sdim } else if (type == "SourceLocation") { 196235633Sdim OS << "\" << get" << getUpperName() << "().getRawEncoding() << \""; 197235633Sdim } else { 198235633Sdim OS << "\" << get" << getUpperName() << "() << \""; 199235633Sdim } 200235633Sdim } 201252723Sdim void writeDump(raw_ostream &OS) const { 202252723Sdim if (type == "FunctionDecl *") { 203252723Sdim OS << " OS << \" \";\n"; 204252723Sdim OS << " dumpBareDeclRef(SA->get" << getUpperName() << "());\n"; 205252723Sdim } else if (type == "IdentifierInfo *") { 206252723Sdim OS << " OS << \" \" << SA->get" << getUpperName() 207252723Sdim << "()->getName();\n"; 208263509Sdim } else if (type == "TypeSourceInfo *") { 209252723Sdim OS << " OS << \" \" << SA->get" << getUpperName() 210252723Sdim << "().getAsString();\n"; 211252723Sdim } else if (type == "SourceLocation") { 212252723Sdim OS << " OS << \" \";\n"; 213252723Sdim OS << " SA->get" << getUpperName() << "().print(OS, *SM);\n"; 214252723Sdim } else if (type == "bool") { 215252723Sdim OS << " if (SA->get" << getUpperName() << "()) OS << \" " 216252723Sdim << getUpperName() << "\";\n"; 217252723Sdim } else if (type == "int" || type == "unsigned") { 218252723Sdim OS << " OS << \" \" << SA->get" << getUpperName() << "();\n"; 219252723Sdim } else { 220252723Sdim llvm_unreachable("Unknown SimpleArgument type!"); 221252723Sdim } 222252723Sdim } 223226586Sdim }; 224226586Sdim 225226586Sdim class StringArgument : public Argument { 226226586Sdim public: 227226586Sdim StringArgument(Record &Arg, StringRef Attr) 228226586Sdim : Argument(Arg, Attr) 229226586Sdim {} 230226586Sdim 231226586Sdim void writeAccessors(raw_ostream &OS) const { 232226586Sdim OS << " llvm::StringRef get" << getUpperName() << "() const {\n"; 233226586Sdim OS << " return llvm::StringRef(" << getLowerName() << ", " 234226586Sdim << getLowerName() << "Length);\n"; 235226586Sdim OS << " }\n"; 236226586Sdim OS << " unsigned get" << getUpperName() << "Length() const {\n"; 237226586Sdim OS << " return " << getLowerName() << "Length;\n"; 238226586Sdim OS << " }\n"; 239226586Sdim OS << " void set" << getUpperName() 240226586Sdim << "(ASTContext &C, llvm::StringRef S) {\n"; 241226586Sdim OS << " " << getLowerName() << "Length = S.size();\n"; 242226586Sdim OS << " this->" << getLowerName() << " = new (C, 1) char [" 243226586Sdim << getLowerName() << "Length];\n"; 244226586Sdim OS << " std::memcpy(this->" << getLowerName() << ", S.data(), " 245226586Sdim << getLowerName() << "Length);\n"; 246226586Sdim OS << " }"; 247226586Sdim } 248226586Sdim void writeCloneArgs(raw_ostream &OS) const { 249226586Sdim OS << "get" << getUpperName() << "()"; 250226586Sdim } 251235633Sdim void writeTemplateInstantiationArgs(raw_ostream &OS) const { 252235633Sdim OS << "A->get" << getUpperName() << "()"; 253235633Sdim } 254226586Sdim void writeCtorBody(raw_ostream &OS) const { 255226586Sdim OS << " std::memcpy(" << getLowerName() << ", " << getUpperName() 256226586Sdim << ".data(), " << getLowerName() << "Length);"; 257226586Sdim } 258226586Sdim void writeCtorInitializers(raw_ostream &OS) const { 259226586Sdim OS << getLowerName() << "Length(" << getUpperName() << ".size())," 260226586Sdim << getLowerName() << "(new (Ctx, 1) char[" << getLowerName() 261226586Sdim << "Length])"; 262226586Sdim } 263263509Sdim void writeCtorDefaultInitializers(raw_ostream &OS) const { 264263509Sdim OS << getLowerName() << "Length(0)," << getLowerName() << "(0)"; 265263509Sdim } 266226586Sdim void writeCtorParameters(raw_ostream &OS) const { 267226586Sdim OS << "llvm::StringRef " << getUpperName(); 268226586Sdim } 269226586Sdim void writeDeclarations(raw_ostream &OS) const { 270226586Sdim OS << "unsigned " << getLowerName() << "Length;\n"; 271226586Sdim OS << "char *" << getLowerName() << ";"; 272226586Sdim } 273226586Sdim void writePCHReadDecls(raw_ostream &OS) const { 274226586Sdim OS << " std::string " << getLowerName() 275226586Sdim << "= ReadString(Record, Idx);\n"; 276226586Sdim } 277226586Sdim void writePCHReadArgs(raw_ostream &OS) const { 278226586Sdim OS << getLowerName(); 279226586Sdim } 280226586Sdim void writePCHWrite(raw_ostream &OS) const { 281226586Sdim OS << " AddString(SA->get" << getUpperName() << "(), Record);\n"; 282226586Sdim } 283235633Sdim void writeValue(raw_ostream &OS) const { 284235633Sdim OS << "\\\"\" << get" << getUpperName() << "() << \"\\\""; 285235633Sdim } 286252723Sdim void writeDump(raw_ostream &OS) const { 287252723Sdim OS << " OS << \" \\\"\" << SA->get" << getUpperName() 288252723Sdim << "() << \"\\\"\";\n"; 289252723Sdim } 290226586Sdim }; 291226586Sdim 292226586Sdim class AlignedArgument : public Argument { 293226586Sdim public: 294226586Sdim AlignedArgument(Record &Arg, StringRef Attr) 295226586Sdim : Argument(Arg, Attr) 296226586Sdim {} 297226586Sdim 298226586Sdim void writeAccessors(raw_ostream &OS) const { 299226586Sdim OS << " bool is" << getUpperName() << "Dependent() const;\n"; 300226586Sdim 301226586Sdim OS << " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n"; 302226586Sdim 303226586Sdim OS << " bool is" << getUpperName() << "Expr() const {\n"; 304226586Sdim OS << " return is" << getLowerName() << "Expr;\n"; 305226586Sdim OS << " }\n"; 306226586Sdim 307226586Sdim OS << " Expr *get" << getUpperName() << "Expr() const {\n"; 308226586Sdim OS << " assert(is" << getLowerName() << "Expr);\n"; 309226586Sdim OS << " return " << getLowerName() << "Expr;\n"; 310226586Sdim OS << " }\n"; 311226586Sdim 312226586Sdim OS << " TypeSourceInfo *get" << getUpperName() << "Type() const {\n"; 313226586Sdim OS << " assert(!is" << getLowerName() << "Expr);\n"; 314226586Sdim OS << " return " << getLowerName() << "Type;\n"; 315226586Sdim OS << " }"; 316226586Sdim } 317226586Sdim void writeAccessorDefinitions(raw_ostream &OS) const { 318226586Sdim OS << "bool " << getAttrName() << "Attr::is" << getUpperName() 319226586Sdim << "Dependent() const {\n"; 320226586Sdim OS << " if (is" << getLowerName() << "Expr)\n"; 321226586Sdim OS << " return " << getLowerName() << "Expr && (" << getLowerName() 322226586Sdim << "Expr->isValueDependent() || " << getLowerName() 323226586Sdim << "Expr->isTypeDependent());\n"; 324226586Sdim OS << " else\n"; 325226586Sdim OS << " return " << getLowerName() 326226586Sdim << "Type->getType()->isDependentType();\n"; 327226586Sdim OS << "}\n"; 328226586Sdim 329226586Sdim // FIXME: Do not do the calculation here 330226586Sdim // FIXME: Handle types correctly 331226586Sdim // A null pointer means maximum alignment 332226586Sdim // FIXME: Load the platform-specific maximum alignment, rather than 333226586Sdim // 16, the x86 max. 334226586Sdim OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName() 335226586Sdim << "(ASTContext &Ctx) const {\n"; 336226586Sdim OS << " assert(!is" << getUpperName() << "Dependent());\n"; 337226586Sdim OS << " if (is" << getLowerName() << "Expr)\n"; 338226586Sdim OS << " return (" << getLowerName() << "Expr ? " << getLowerName() 339226586Sdim << "Expr->EvaluateKnownConstInt(Ctx).getZExtValue() : 16)" 340226586Sdim << "* Ctx.getCharWidth();\n"; 341226586Sdim OS << " else\n"; 342226586Sdim OS << " return 0; // FIXME\n"; 343226586Sdim OS << "}\n"; 344226586Sdim } 345226586Sdim void writeCloneArgs(raw_ostream &OS) const { 346226586Sdim OS << "is" << getLowerName() << "Expr, is" << getLowerName() 347226586Sdim << "Expr ? static_cast<void*>(" << getLowerName() 348226586Sdim << "Expr) : " << getLowerName() 349226586Sdim << "Type"; 350226586Sdim } 351235633Sdim void writeTemplateInstantiationArgs(raw_ostream &OS) const { 352235633Sdim // FIXME: move the definition in Sema::InstantiateAttrs to here. 353235633Sdim // In the meantime, aligned attributes are cloned. 354235633Sdim } 355226586Sdim void writeCtorBody(raw_ostream &OS) const { 356226586Sdim OS << " if (is" << getLowerName() << "Expr)\n"; 357226586Sdim OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>(" 358226586Sdim << getUpperName() << ");\n"; 359226586Sdim OS << " else\n"; 360226586Sdim OS << " " << getLowerName() 361226586Sdim << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName() 362226586Sdim << ");"; 363226586Sdim } 364226586Sdim void writeCtorInitializers(raw_ostream &OS) const { 365226586Sdim OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)"; 366226586Sdim } 367263509Sdim void writeCtorDefaultInitializers(raw_ostream &OS) const { 368263509Sdim OS << "is" << getLowerName() << "Expr(false)"; 369263509Sdim } 370226586Sdim void writeCtorParameters(raw_ostream &OS) const { 371226586Sdim OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName(); 372226586Sdim } 373226586Sdim void writeDeclarations(raw_ostream &OS) const { 374226586Sdim OS << "bool is" << getLowerName() << "Expr;\n"; 375226586Sdim OS << "union {\n"; 376226586Sdim OS << "Expr *" << getLowerName() << "Expr;\n"; 377226586Sdim OS << "TypeSourceInfo *" << getLowerName() << "Type;\n"; 378226586Sdim OS << "};"; 379226586Sdim } 380226586Sdim void writePCHReadArgs(raw_ostream &OS) const { 381226586Sdim OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr"; 382226586Sdim } 383226586Sdim void writePCHReadDecls(raw_ostream &OS) const { 384226586Sdim OS << " bool is" << getLowerName() << "Expr = Record[Idx++];\n"; 385226586Sdim OS << " void *" << getLowerName() << "Ptr;\n"; 386226586Sdim OS << " if (is" << getLowerName() << "Expr)\n"; 387226586Sdim OS << " " << getLowerName() << "Ptr = ReadExpr(F);\n"; 388226586Sdim OS << " else\n"; 389226586Sdim OS << " " << getLowerName() 390226586Sdim << "Ptr = GetTypeSourceInfo(F, Record, Idx);\n"; 391226586Sdim } 392226586Sdim void writePCHWrite(raw_ostream &OS) const { 393226586Sdim OS << " Record.push_back(SA->is" << getUpperName() << "Expr());\n"; 394226586Sdim OS << " if (SA->is" << getUpperName() << "Expr())\n"; 395226586Sdim OS << " AddStmt(SA->get" << getUpperName() << "Expr());\n"; 396226586Sdim OS << " else\n"; 397226586Sdim OS << " AddTypeSourceInfo(SA->get" << getUpperName() 398226586Sdim << "Type(), Record);\n"; 399226586Sdim } 400235633Sdim void writeValue(raw_ostream &OS) const { 401245431Sdim OS << "\";\n" 402245431Sdim << " " << getLowerName() << "Expr->printPretty(OS, 0, Policy);\n" 403245431Sdim << " OS << \""; 404235633Sdim } 405252723Sdim void writeDump(raw_ostream &OS) const { 406252723Sdim } 407252723Sdim void writeDumpChildren(raw_ostream &OS) const { 408252723Sdim OS << " if (SA->is" << getUpperName() << "Expr()) {\n"; 409252723Sdim OS << " lastChild();\n"; 410252723Sdim OS << " dumpStmt(SA->get" << getUpperName() << "Expr());\n"; 411252723Sdim OS << " } else\n"; 412252723Sdim OS << " dumpType(SA->get" << getUpperName() 413252723Sdim << "Type()->getType());\n"; 414252723Sdim } 415252723Sdim void writeHasChildren(raw_ostream &OS) const { 416252723Sdim OS << "SA->is" << getUpperName() << "Expr()"; 417252723Sdim } 418226586Sdim }; 419226586Sdim 420226586Sdim class VariadicArgument : public Argument { 421226586Sdim std::string type; 422226586Sdim 423226586Sdim public: 424226586Sdim VariadicArgument(Record &Arg, StringRef Attr, std::string T) 425226586Sdim : Argument(Arg, Attr), type(T) 426226586Sdim {} 427226586Sdim 428226586Sdim std::string getType() const { return type; } 429226586Sdim 430226586Sdim void writeAccessors(raw_ostream &OS) const { 431226586Sdim OS << " typedef " << type << "* " << getLowerName() << "_iterator;\n"; 432226586Sdim OS << " " << getLowerName() << "_iterator " << getLowerName() 433226586Sdim << "_begin() const {\n"; 434226586Sdim OS << " return " << getLowerName() << ";\n"; 435226586Sdim OS << " }\n"; 436226586Sdim OS << " " << getLowerName() << "_iterator " << getLowerName() 437226586Sdim << "_end() const {\n"; 438226586Sdim OS << " return " << getLowerName() << " + " << getLowerName() 439226586Sdim << "Size;\n"; 440226586Sdim OS << " }\n"; 441226586Sdim OS << " unsigned " << getLowerName() << "_size() const {\n" 442235633Sdim << " return " << getLowerName() << "Size;\n"; 443226586Sdim OS << " }"; 444226586Sdim } 445226586Sdim void writeCloneArgs(raw_ostream &OS) const { 446226586Sdim OS << getLowerName() << ", " << getLowerName() << "Size"; 447226586Sdim } 448235633Sdim void writeTemplateInstantiationArgs(raw_ostream &OS) const { 449235633Sdim // This isn't elegant, but we have to go through public methods... 450235633Sdim OS << "A->" << getLowerName() << "_begin(), " 451235633Sdim << "A->" << getLowerName() << "_size()"; 452235633Sdim } 453226586Sdim void writeCtorBody(raw_ostream &OS) const { 454226586Sdim // FIXME: memcpy is not safe on non-trivial types. 455226586Sdim OS << " std::memcpy(" << getLowerName() << ", " << getUpperName() 456226586Sdim << ", " << getLowerName() << "Size * sizeof(" << getType() << "));\n"; 457226586Sdim } 458226586Sdim void writeCtorInitializers(raw_ostream &OS) const { 459226586Sdim OS << getLowerName() << "Size(" << getUpperName() << "Size), " 460226586Sdim << getLowerName() << "(new (Ctx, 16) " << getType() << "[" 461226586Sdim << getLowerName() << "Size])"; 462226586Sdim } 463263509Sdim void writeCtorDefaultInitializers(raw_ostream &OS) const { 464263509Sdim OS << getLowerName() << "Size(0), " << getLowerName() << "(0)"; 465263509Sdim } 466226586Sdim void writeCtorParameters(raw_ostream &OS) const { 467226586Sdim OS << getType() << " *" << getUpperName() << ", unsigned " 468226586Sdim << getUpperName() << "Size"; 469226586Sdim } 470226586Sdim void writeDeclarations(raw_ostream &OS) const { 471226586Sdim OS << " unsigned " << getLowerName() << "Size;\n"; 472226586Sdim OS << " " << getType() << " *" << getLowerName() << ";"; 473226586Sdim } 474226586Sdim void writePCHReadDecls(raw_ostream &OS) const { 475226586Sdim OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n"; 476252723Sdim OS << " SmallVector<" << type << ", 4> " << getLowerName() 477226586Sdim << ";\n"; 478226586Sdim OS << " " << getLowerName() << ".reserve(" << getLowerName() 479226586Sdim << "Size);\n"; 480263509Sdim OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n"; 481226586Sdim 482226586Sdim std::string read = ReadPCHRecord(type); 483226586Sdim OS << " " << getLowerName() << ".push_back(" << read << ");\n"; 484226586Sdim } 485226586Sdim void writePCHReadArgs(raw_ostream &OS) const { 486226586Sdim OS << getLowerName() << ".data(), " << getLowerName() << "Size"; 487226586Sdim } 488226586Sdim void writePCHWrite(raw_ostream &OS) const{ 489226586Sdim OS << " Record.push_back(SA->" << getLowerName() << "_size());\n"; 490226586Sdim OS << " for (" << getAttrName() << "Attr::" << getLowerName() 491226586Sdim << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->" 492226586Sdim << getLowerName() << "_end(); i != e; ++i)\n"; 493226586Sdim OS << " " << WritePCHRecord(type, "(*i)"); 494226586Sdim } 495235633Sdim void writeValue(raw_ostream &OS) const { 496235633Sdim OS << "\";\n"; 497235633Sdim OS << " bool isFirst = true;\n" 498235633Sdim << " for (" << getAttrName() << "Attr::" << getLowerName() 499235633Sdim << "_iterator i = " << getLowerName() << "_begin(), e = " 500235633Sdim << getLowerName() << "_end(); i != e; ++i) {\n" 501235633Sdim << " if (isFirst) isFirst = false;\n" 502235633Sdim << " else OS << \", \";\n" 503235633Sdim << " OS << *i;\n" 504235633Sdim << " }\n"; 505235633Sdim OS << " OS << \""; 506235633Sdim } 507252723Sdim void writeDump(raw_ostream &OS) const { 508252723Sdim OS << " for (" << getAttrName() << "Attr::" << getLowerName() 509252723Sdim << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->" 510252723Sdim << getLowerName() << "_end(); I != E; ++I)\n"; 511252723Sdim OS << " OS << \" \" << *I;\n"; 512252723Sdim } 513226586Sdim }; 514226586Sdim 515226586Sdim class EnumArgument : public Argument { 516226586Sdim std::string type; 517252723Sdim std::vector<StringRef> values, enums, uniques; 518226586Sdim public: 519226586Sdim EnumArgument(Record &Arg, StringRef Attr) 520226586Sdim : Argument(Arg, Attr), type(Arg.getValueAsString("Type")), 521226586Sdim values(getValueAsListOfStrings(Arg, "Values")), 522252723Sdim enums(getValueAsListOfStrings(Arg, "Enums")), 523252723Sdim uniques(enums) 524252723Sdim { 525252723Sdim // Calculate the various enum values 526252723Sdim std::sort(uniques.begin(), uniques.end()); 527252723Sdim uniques.erase(std::unique(uniques.begin(), uniques.end()), uniques.end()); 528252723Sdim // FIXME: Emit a proper error 529252723Sdim assert(!uniques.empty()); 530252723Sdim } 531226586Sdim 532263509Sdim bool isEnumArg() const { return true; } 533263509Sdim 534226586Sdim void writeAccessors(raw_ostream &OS) const { 535226586Sdim OS << " " << type << " get" << getUpperName() << "() const {\n"; 536226586Sdim OS << " return " << getLowerName() << ";\n"; 537226586Sdim OS << " }"; 538226586Sdim } 539226586Sdim void writeCloneArgs(raw_ostream &OS) const { 540226586Sdim OS << getLowerName(); 541226586Sdim } 542235633Sdim void writeTemplateInstantiationArgs(raw_ostream &OS) const { 543235633Sdim OS << "A->get" << getUpperName() << "()"; 544235633Sdim } 545226586Sdim void writeCtorInitializers(raw_ostream &OS) const { 546226586Sdim OS << getLowerName() << "(" << getUpperName() << ")"; 547226586Sdim } 548263509Sdim void writeCtorDefaultInitializers(raw_ostream &OS) const { 549263509Sdim OS << getLowerName() << "(" << type << "(0))"; 550263509Sdim } 551226586Sdim void writeCtorParameters(raw_ostream &OS) const { 552226586Sdim OS << type << " " << getUpperName(); 553226586Sdim } 554226586Sdim void writeDeclarations(raw_ostream &OS) const { 555252723Sdim std::vector<StringRef>::const_iterator i = uniques.begin(), 556252723Sdim e = uniques.end(); 557226586Sdim // The last one needs to not have a comma. 558226586Sdim --e; 559226586Sdim 560226586Sdim OS << "public:\n"; 561226586Sdim OS << " enum " << type << " {\n"; 562226586Sdim for (; i != e; ++i) 563226586Sdim OS << " " << *i << ",\n"; 564226586Sdim OS << " " << *e << "\n"; 565226586Sdim OS << " };\n"; 566226586Sdim OS << "private:\n"; 567226586Sdim OS << " " << type << " " << getLowerName() << ";"; 568226586Sdim } 569226586Sdim void writePCHReadDecls(raw_ostream &OS) const { 570226586Sdim OS << " " << getAttrName() << "Attr::" << type << " " << getLowerName() 571226586Sdim << "(static_cast<" << getAttrName() << "Attr::" << type 572226586Sdim << ">(Record[Idx++]));\n"; 573226586Sdim } 574226586Sdim void writePCHReadArgs(raw_ostream &OS) const { 575226586Sdim OS << getLowerName(); 576226586Sdim } 577226586Sdim void writePCHWrite(raw_ostream &OS) const { 578226586Sdim OS << "Record.push_back(SA->get" << getUpperName() << "());\n"; 579226586Sdim } 580235633Sdim void writeValue(raw_ostream &OS) const { 581235633Sdim OS << "\" << get" << getUpperName() << "() << \""; 582235633Sdim } 583252723Sdim void writeDump(raw_ostream &OS) const { 584252723Sdim OS << " switch(SA->get" << getUpperName() << "()) {\n"; 585252723Sdim for (std::vector<StringRef>::const_iterator I = uniques.begin(), 586252723Sdim E = uniques.end(); I != E; ++I) { 587252723Sdim OS << " case " << getAttrName() << "Attr::" << *I << ":\n"; 588252723Sdim OS << " OS << \" " << *I << "\";\n"; 589252723Sdim OS << " break;\n"; 590252723Sdim } 591252723Sdim OS << " }\n"; 592252723Sdim } 593263509Sdim 594263509Sdim void writeConversion(raw_ostream &OS) const { 595263509Sdim OS << " static bool ConvertStrTo" << type << "(StringRef Val, "; 596263509Sdim OS << type << " &Out) {\n"; 597263509Sdim OS << " Optional<" << type << "> R = llvm::StringSwitch<Optional<"; 598263509Sdim OS << type << "> >(Val)\n"; 599263509Sdim for (size_t I = 0; I < enums.size(); ++I) { 600263509Sdim OS << " .Case(\"" << values[I] << "\", "; 601263509Sdim OS << getAttrName() << "Attr::" << enums[I] << ")\n"; 602263509Sdim } 603263509Sdim OS << " .Default(Optional<" << type << ">());\n"; 604263509Sdim OS << " if (R) {\n"; 605263509Sdim OS << " Out = *R;\n return true;\n }\n"; 606263509Sdim OS << " return false;\n"; 607263509Sdim OS << " }\n"; 608263509Sdim } 609226586Sdim }; 610263509Sdim 611263509Sdim class VariadicEnumArgument: public VariadicArgument { 612263509Sdim std::string type, QualifiedTypeName; 613263509Sdim std::vector<StringRef> values, enums, uniques; 614263509Sdim public: 615263509Sdim VariadicEnumArgument(Record &Arg, StringRef Attr) 616263509Sdim : VariadicArgument(Arg, Attr, Arg.getValueAsString("Type")), 617263509Sdim type(Arg.getValueAsString("Type")), 618263509Sdim values(getValueAsListOfStrings(Arg, "Values")), 619263509Sdim enums(getValueAsListOfStrings(Arg, "Enums")), 620263509Sdim uniques(enums) 621263509Sdim { 622263509Sdim // Calculate the various enum values 623263509Sdim std::sort(uniques.begin(), uniques.end()); 624263509Sdim uniques.erase(std::unique(uniques.begin(), uniques.end()), uniques.end()); 625263509Sdim 626263509Sdim QualifiedTypeName = getAttrName().str() + "Attr::" + type; 627263509Sdim 628263509Sdim // FIXME: Emit a proper error 629263509Sdim assert(!uniques.empty()); 630263509Sdim } 631226586Sdim 632263509Sdim bool isVariadicEnumArg() const { return true; } 633263509Sdim 634263509Sdim void writeDeclarations(raw_ostream &OS) const { 635263509Sdim std::vector<StringRef>::const_iterator i = uniques.begin(), 636263509Sdim e = uniques.end(); 637263509Sdim // The last one needs to not have a comma. 638263509Sdim --e; 639263509Sdim 640263509Sdim OS << "public:\n"; 641263509Sdim OS << " enum " << type << " {\n"; 642263509Sdim for (; i != e; ++i) 643263509Sdim OS << " " << *i << ",\n"; 644263509Sdim OS << " " << *e << "\n"; 645263509Sdim OS << " };\n"; 646263509Sdim OS << "private:\n"; 647263509Sdim 648263509Sdim VariadicArgument::writeDeclarations(OS); 649263509Sdim } 650263509Sdim void writeDump(raw_ostream &OS) const { 651263509Sdim OS << " for (" << getAttrName() << "Attr::" << getLowerName() 652263509Sdim << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->" 653263509Sdim << getLowerName() << "_end(); I != E; ++I) {\n"; 654263509Sdim OS << " switch(*I) {\n"; 655263509Sdim for (std::vector<StringRef>::const_iterator UI = uniques.begin(), 656263509Sdim UE = uniques.end(); UI != UE; ++UI) { 657263509Sdim OS << " case " << getAttrName() << "Attr::" << *UI << ":\n"; 658263509Sdim OS << " OS << \" " << *UI << "\";\n"; 659263509Sdim OS << " break;\n"; 660263509Sdim } 661263509Sdim OS << " }\n"; 662263509Sdim OS << " }\n"; 663263509Sdim } 664263509Sdim void writePCHReadDecls(raw_ostream &OS) const { 665263509Sdim OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n"; 666263509Sdim OS << " SmallVector<" << QualifiedTypeName << ", 4> " << getLowerName() 667263509Sdim << ";\n"; 668263509Sdim OS << " " << getLowerName() << ".reserve(" << getLowerName() 669263509Sdim << "Size);\n"; 670263509Sdim OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n"; 671263509Sdim OS << " " << getLowerName() << ".push_back(" << "static_cast<" 672263509Sdim << QualifiedTypeName << ">(Record[Idx++]));\n"; 673263509Sdim } 674263509Sdim void writePCHWrite(raw_ostream &OS) const{ 675263509Sdim OS << " Record.push_back(SA->" << getLowerName() << "_size());\n"; 676263509Sdim OS << " for (" << getAttrName() << "Attr::" << getLowerName() 677263509Sdim << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->" 678263509Sdim << getLowerName() << "_end(); i != e; ++i)\n"; 679263509Sdim OS << " " << WritePCHRecord(QualifiedTypeName, "(*i)"); 680263509Sdim } 681263509Sdim void writeConversion(raw_ostream &OS) const { 682263509Sdim OS << " static bool ConvertStrTo" << type << "(StringRef Val, "; 683263509Sdim OS << type << " &Out) {\n"; 684263509Sdim OS << " Optional<" << type << "> R = llvm::StringSwitch<Optional<"; 685263509Sdim OS << type << "> >(Val)\n"; 686263509Sdim for (size_t I = 0; I < enums.size(); ++I) { 687263509Sdim OS << " .Case(\"" << values[I] << "\", "; 688263509Sdim OS << getAttrName() << "Attr::" << enums[I] << ")\n"; 689263509Sdim } 690263509Sdim OS << " .Default(Optional<" << type << ">());\n"; 691263509Sdim OS << " if (R) {\n"; 692263509Sdim OS << " Out = *R;\n return true;\n }\n"; 693263509Sdim OS << " return false;\n"; 694263509Sdim OS << " }\n"; 695263509Sdim } 696263509Sdim }; 697263509Sdim 698226586Sdim class VersionArgument : public Argument { 699226586Sdim public: 700226586Sdim VersionArgument(Record &Arg, StringRef Attr) 701226586Sdim : Argument(Arg, Attr) 702226586Sdim {} 703226586Sdim 704226586Sdim void writeAccessors(raw_ostream &OS) const { 705226586Sdim OS << " VersionTuple get" << getUpperName() << "() const {\n"; 706226586Sdim OS << " return " << getLowerName() << ";\n"; 707226586Sdim OS << " }\n"; 708226586Sdim OS << " void set" << getUpperName() 709226586Sdim << "(ASTContext &C, VersionTuple V) {\n"; 710226586Sdim OS << " " << getLowerName() << " = V;\n"; 711226586Sdim OS << " }"; 712226586Sdim } 713226586Sdim void writeCloneArgs(raw_ostream &OS) const { 714226586Sdim OS << "get" << getUpperName() << "()"; 715226586Sdim } 716235633Sdim void writeTemplateInstantiationArgs(raw_ostream &OS) const { 717235633Sdim OS << "A->get" << getUpperName() << "()"; 718235633Sdim } 719226586Sdim void writeCtorBody(raw_ostream &OS) const { 720226586Sdim } 721226586Sdim void writeCtorInitializers(raw_ostream &OS) const { 722226586Sdim OS << getLowerName() << "(" << getUpperName() << ")"; 723226586Sdim } 724263509Sdim void writeCtorDefaultInitializers(raw_ostream &OS) const { 725263509Sdim OS << getLowerName() << "()"; 726263509Sdim } 727226586Sdim void writeCtorParameters(raw_ostream &OS) const { 728226586Sdim OS << "VersionTuple " << getUpperName(); 729226586Sdim } 730226586Sdim void writeDeclarations(raw_ostream &OS) const { 731226586Sdim OS << "VersionTuple " << getLowerName() << ";\n"; 732226586Sdim } 733226586Sdim void writePCHReadDecls(raw_ostream &OS) const { 734226586Sdim OS << " VersionTuple " << getLowerName() 735226586Sdim << "= ReadVersionTuple(Record, Idx);\n"; 736226586Sdim } 737226586Sdim void writePCHReadArgs(raw_ostream &OS) const { 738226586Sdim OS << getLowerName(); 739226586Sdim } 740226586Sdim void writePCHWrite(raw_ostream &OS) const { 741226586Sdim OS << " AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n"; 742226586Sdim } 743235633Sdim void writeValue(raw_ostream &OS) const { 744235633Sdim OS << getLowerName() << "=\" << get" << getUpperName() << "() << \""; 745235633Sdim } 746252723Sdim void writeDump(raw_ostream &OS) const { 747252723Sdim OS << " OS << \" \" << SA->get" << getUpperName() << "();\n"; 748252723Sdim } 749226586Sdim }; 750235633Sdim 751235633Sdim class ExprArgument : public SimpleArgument { 752235633Sdim public: 753235633Sdim ExprArgument(Record &Arg, StringRef Attr) 754235633Sdim : SimpleArgument(Arg, Attr, "Expr *") 755235633Sdim {} 756235633Sdim 757235633Sdim void writeTemplateInstantiationArgs(raw_ostream &OS) const { 758235633Sdim OS << "tempInst" << getUpperName(); 759235633Sdim } 760235633Sdim 761235633Sdim void writeTemplateInstantiation(raw_ostream &OS) const { 762235633Sdim OS << " " << getType() << " tempInst" << getUpperName() << ";\n"; 763235633Sdim OS << " {\n"; 764235633Sdim OS << " EnterExpressionEvaluationContext " 765235633Sdim << "Unevaluated(S, Sema::Unevaluated);\n"; 766235633Sdim OS << " ExprResult " << "Result = S.SubstExpr(" 767235633Sdim << "A->get" << getUpperName() << "(), TemplateArgs);\n"; 768235633Sdim OS << " tempInst" << getUpperName() << " = " 769235633Sdim << "Result.takeAs<Expr>();\n"; 770235633Sdim OS << " }\n"; 771235633Sdim } 772252723Sdim 773252723Sdim void writeDump(raw_ostream &OS) const { 774252723Sdim } 775252723Sdim 776252723Sdim void writeDumpChildren(raw_ostream &OS) const { 777252723Sdim OS << " lastChild();\n"; 778252723Sdim OS << " dumpStmt(SA->get" << getUpperName() << "());\n"; 779252723Sdim } 780252723Sdim void writeHasChildren(raw_ostream &OS) const { OS << "true"; } 781235633Sdim }; 782235633Sdim 783235633Sdim class VariadicExprArgument : public VariadicArgument { 784235633Sdim public: 785235633Sdim VariadicExprArgument(Record &Arg, StringRef Attr) 786235633Sdim : VariadicArgument(Arg, Attr, "Expr *") 787235633Sdim {} 788235633Sdim 789235633Sdim void writeTemplateInstantiationArgs(raw_ostream &OS) const { 790235633Sdim OS << "tempInst" << getUpperName() << ", " 791235633Sdim << "A->" << getLowerName() << "_size()"; 792235633Sdim } 793235633Sdim 794235633Sdim void writeTemplateInstantiation(raw_ostream &OS) const { 795235633Sdim OS << " " << getType() << " *tempInst" << getUpperName() 796235633Sdim << " = new (C, 16) " << getType() 797235633Sdim << "[A->" << getLowerName() << "_size()];\n"; 798235633Sdim OS << " {\n"; 799235633Sdim OS << " EnterExpressionEvaluationContext " 800235633Sdim << "Unevaluated(S, Sema::Unevaluated);\n"; 801235633Sdim OS << " " << getType() << " *TI = tempInst" << getUpperName() 802235633Sdim << ";\n"; 803235633Sdim OS << " " << getType() << " *I = A->" << getLowerName() 804235633Sdim << "_begin();\n"; 805235633Sdim OS << " " << getType() << " *E = A->" << getLowerName() 806235633Sdim << "_end();\n"; 807235633Sdim OS << " for (; I != E; ++I, ++TI) {\n"; 808235633Sdim OS << " ExprResult Result = S.SubstExpr(*I, TemplateArgs);\n"; 809235633Sdim OS << " *TI = Result.takeAs<Expr>();\n"; 810235633Sdim OS << " }\n"; 811235633Sdim OS << " }\n"; 812235633Sdim } 813252723Sdim 814252723Sdim void writeDump(raw_ostream &OS) const { 815252723Sdim } 816252723Sdim 817252723Sdim void writeDumpChildren(raw_ostream &OS) const { 818252723Sdim OS << " for (" << getAttrName() << "Attr::" << getLowerName() 819252723Sdim << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->" 820252723Sdim << getLowerName() << "_end(); I != E; ++I) {\n"; 821252723Sdim OS << " if (I + 1 == E)\n"; 822252723Sdim OS << " lastChild();\n"; 823252723Sdim OS << " dumpStmt(*I);\n"; 824252723Sdim OS << " }\n"; 825252723Sdim } 826252723Sdim 827252723Sdim void writeHasChildren(raw_ostream &OS) const { 828252723Sdim OS << "SA->" << getLowerName() << "_begin() != " 829252723Sdim << "SA->" << getLowerName() << "_end()"; 830252723Sdim } 831235633Sdim }; 832263509Sdim 833263509Sdim class TypeArgument : public SimpleArgument { 834263509Sdim public: 835263509Sdim TypeArgument(Record &Arg, StringRef Attr) 836263509Sdim : SimpleArgument(Arg, Attr, "TypeSourceInfo *") 837263509Sdim {} 838263509Sdim 839263509Sdim void writeAccessors(raw_ostream &OS) const { 840263509Sdim OS << " QualType get" << getUpperName() << "() const {\n"; 841263509Sdim OS << " return " << getLowerName() << "->getType();\n"; 842263509Sdim OS << " }"; 843263509Sdim OS << " " << getType() << " get" << getUpperName() << "Loc() const {\n"; 844263509Sdim OS << " return " << getLowerName() << ";\n"; 845263509Sdim OS << " }"; 846263509Sdim } 847263509Sdim void writeTemplateInstantiationArgs(raw_ostream &OS) const { 848263509Sdim OS << "A->get" << getUpperName() << "Loc()"; 849263509Sdim } 850263509Sdim void writePCHWrite(raw_ostream &OS) const { 851263509Sdim OS << " " << WritePCHRecord( 852263509Sdim getType(), "SA->get" + std::string(getUpperName()) + "Loc()"); 853263509Sdim } 854263509Sdim }; 855226586Sdim} 856226586Sdim 857226586Sdimstatic Argument *createArgument(Record &Arg, StringRef Attr, 858226586Sdim Record *Search = 0) { 859226586Sdim if (!Search) 860226586Sdim Search = &Arg; 861226586Sdim 862226586Sdim Argument *Ptr = 0; 863226586Sdim llvm::StringRef ArgName = Search->getName(); 864226586Sdim 865226586Sdim if (ArgName == "AlignedArgument") Ptr = new AlignedArgument(Arg, Attr); 866226586Sdim else if (ArgName == "EnumArgument") Ptr = new EnumArgument(Arg, Attr); 867235633Sdim else if (ArgName == "ExprArgument") Ptr = new ExprArgument(Arg, Attr); 868226586Sdim else if (ArgName == "FunctionArgument") 869226586Sdim Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *"); 870226586Sdim else if (ArgName == "IdentifierArgument") 871226586Sdim Ptr = new SimpleArgument(Arg, Attr, "IdentifierInfo *"); 872226586Sdim else if (ArgName == "BoolArgument") Ptr = new SimpleArgument(Arg, Attr, 873226586Sdim "bool"); 874226586Sdim else if (ArgName == "IntArgument") Ptr = new SimpleArgument(Arg, Attr, "int"); 875226586Sdim else if (ArgName == "StringArgument") Ptr = new StringArgument(Arg, Attr); 876263509Sdim else if (ArgName == "TypeArgument") Ptr = new TypeArgument(Arg, Attr); 877226586Sdim else if (ArgName == "UnsignedArgument") 878226586Sdim Ptr = new SimpleArgument(Arg, Attr, "unsigned"); 879226586Sdim else if (ArgName == "SourceLocArgument") 880226586Sdim Ptr = new SimpleArgument(Arg, Attr, "SourceLocation"); 881226586Sdim else if (ArgName == "VariadicUnsignedArgument") 882226586Sdim Ptr = new VariadicArgument(Arg, Attr, "unsigned"); 883263509Sdim else if (ArgName == "VariadicEnumArgument") 884263509Sdim Ptr = new VariadicEnumArgument(Arg, Attr); 885226586Sdim else if (ArgName == "VariadicExprArgument") 886235633Sdim Ptr = new VariadicExprArgument(Arg, Attr); 887226586Sdim else if (ArgName == "VersionArgument") 888226586Sdim Ptr = new VersionArgument(Arg, Attr); 889226586Sdim 890226586Sdim if (!Ptr) { 891226586Sdim std::vector<Record*> Bases = Search->getSuperClasses(); 892226586Sdim for (std::vector<Record*>::iterator i = Bases.begin(), e = Bases.end(); 893226586Sdim i != e; ++i) { 894226586Sdim Ptr = createArgument(Arg, Attr, *i); 895226586Sdim if (Ptr) 896226586Sdim break; 897226586Sdim } 898226586Sdim } 899263509Sdim 900263509Sdim if (Ptr && Arg.getValueAsBit("Optional")) 901263509Sdim Ptr->setOptional(true); 902263509Sdim 903226586Sdim return Ptr; 904226586Sdim} 905226586Sdim 906235633Sdimstatic void writeAvailabilityValue(raw_ostream &OS) { 907235633Sdim OS << "\" << getPlatform()->getName();\n" 908235633Sdim << " if (!getIntroduced().empty()) OS << \", introduced=\" << getIntroduced();\n" 909235633Sdim << " if (!getDeprecated().empty()) OS << \", deprecated=\" << getDeprecated();\n" 910235633Sdim << " if (!getObsoleted().empty()) OS << \", obsoleted=\" << getObsoleted();\n" 911235633Sdim << " if (getUnavailable()) OS << \", unavailable\";\n" 912235633Sdim << " OS << \""; 913235633Sdim} 914235633Sdim 915252723Sdimstatic void writePrettyPrintFunction(Record &R, std::vector<Argument*> &Args, 916252723Sdim raw_ostream &OS) { 917252723Sdim std::vector<Record*> Spellings = R.getValueAsListOfDefs("Spellings"); 918252723Sdim 919252723Sdim OS << "void " << R.getName() << "Attr::printPretty(" 920252723Sdim << "raw_ostream &OS, const PrintingPolicy &Policy) const {\n"; 921252723Sdim 922252723Sdim if (Spellings.size() == 0) { 923252723Sdim OS << "}\n\n"; 924252723Sdim return; 925252723Sdim } 926252723Sdim 927252723Sdim OS << 928252723Sdim " switch (SpellingListIndex) {\n" 929252723Sdim " default:\n" 930252723Sdim " llvm_unreachable(\"Unknown attribute spelling!\");\n" 931252723Sdim " break;\n"; 932252723Sdim 933252723Sdim for (unsigned I = 0; I < Spellings.size(); ++ I) { 934252723Sdim llvm::SmallString<16> Prefix; 935252723Sdim llvm::SmallString<8> Suffix; 936252723Sdim // The actual spelling of the name and namespace (if applicable) 937252723Sdim // of an attribute without considering prefix and suffix. 938252723Sdim llvm::SmallString<64> Spelling; 939252723Sdim std::string Name = Spellings[I]->getValueAsString("Name"); 940252723Sdim std::string Variety = Spellings[I]->getValueAsString("Variety"); 941252723Sdim 942252723Sdim if (Variety == "GNU") { 943252723Sdim Prefix = " __attribute__(("; 944252723Sdim Suffix = "))"; 945252723Sdim } else if (Variety == "CXX11") { 946252723Sdim Prefix = " [["; 947252723Sdim Suffix = "]]"; 948252723Sdim std::string Namespace = Spellings[I]->getValueAsString("Namespace"); 949252723Sdim if (Namespace != "") { 950252723Sdim Spelling += Namespace; 951252723Sdim Spelling += "::"; 952252723Sdim } 953252723Sdim } else if (Variety == "Declspec") { 954252723Sdim Prefix = " __declspec("; 955252723Sdim Suffix = ")"; 956252723Sdim } else if (Variety == "Keyword") { 957252723Sdim Prefix = " "; 958252723Sdim Suffix = ""; 959252723Sdim } else { 960252723Sdim llvm_unreachable("Unknown attribute syntax variety!"); 961252723Sdim } 962252723Sdim 963252723Sdim Spelling += Name; 964252723Sdim 965252723Sdim OS << 966252723Sdim " case " << I << " : {\n" 967252723Sdim " OS << \"" + Prefix.str() + Spelling.str(); 968252723Sdim 969252723Sdim if (Args.size()) OS << "("; 970252723Sdim if (Spelling == "availability") { 971252723Sdim writeAvailabilityValue(OS); 972252723Sdim } else { 973252723Sdim for (std::vector<Argument*>::const_iterator I = Args.begin(), 974252723Sdim E = Args.end(); I != E; ++ I) { 975252723Sdim if (I != Args.begin()) OS << ", "; 976252723Sdim (*I)->writeValue(OS); 977252723Sdim } 978252723Sdim } 979252723Sdim 980252723Sdim if (Args.size()) OS << ")"; 981252723Sdim OS << Suffix.str() + "\";\n"; 982252723Sdim 983252723Sdim OS << 984252723Sdim " break;\n" 985252723Sdim " }\n"; 986252723Sdim } 987252723Sdim 988252723Sdim // End of the switch statement. 989252723Sdim OS << "}\n"; 990252723Sdim // End of the print function. 991252723Sdim OS << "}\n\n"; 992252723Sdim} 993252723Sdim 994252723Sdim/// \brief Return the index of a spelling in a spelling list. 995252723Sdimstatic unsigned getSpellingListIndex(const std::vector<Record*> &SpellingList, 996252723Sdim const Record &Spelling) { 997252723Sdim assert(SpellingList.size() && "Spelling list is empty!"); 998252723Sdim 999252723Sdim for (unsigned Index = 0; Index < SpellingList.size(); ++Index) { 1000252723Sdim Record *S = SpellingList[Index]; 1001252723Sdim if (S->getValueAsString("Variety") != Spelling.getValueAsString("Variety")) 1002252723Sdim continue; 1003252723Sdim if (S->getValueAsString("Variety") == "CXX11" && 1004252723Sdim S->getValueAsString("Namespace") != 1005252723Sdim Spelling.getValueAsString("Namespace")) 1006252723Sdim continue; 1007252723Sdim if (S->getValueAsString("Name") != Spelling.getValueAsString("Name")) 1008252723Sdim continue; 1009252723Sdim 1010252723Sdim return Index; 1011252723Sdim } 1012252723Sdim 1013252723Sdim llvm_unreachable("Unknown spelling!"); 1014252723Sdim} 1015252723Sdim 1016252723Sdimstatic void writeAttrAccessorDefinition(Record &R, raw_ostream &OS) { 1017252723Sdim std::vector<Record*> Accessors = R.getValueAsListOfDefs("Accessors"); 1018252723Sdim for (std::vector<Record*>::const_iterator I = Accessors.begin(), 1019252723Sdim E = Accessors.end(); I != E; ++I) { 1020252723Sdim Record *Accessor = *I; 1021252723Sdim std::string Name = Accessor->getValueAsString("Name"); 1022252723Sdim std::vector<Record*> Spellings = Accessor->getValueAsListOfDefs( 1023252723Sdim "Spellings"); 1024252723Sdim std::vector<Record*> SpellingList = R.getValueAsListOfDefs("Spellings"); 1025252723Sdim assert(SpellingList.size() && 1026252723Sdim "Attribute with empty spelling list can't have accessors!"); 1027252723Sdim 1028252723Sdim OS << " bool " << Name << "() const { return SpellingListIndex == "; 1029252723Sdim for (unsigned Index = 0; Index < Spellings.size(); ++Index) { 1030252723Sdim OS << getSpellingListIndex(SpellingList, *Spellings[Index]); 1031252723Sdim if (Index != Spellings.size() -1) 1032252723Sdim OS << " ||\n SpellingListIndex == "; 1033252723Sdim else 1034252723Sdim OS << "; }\n"; 1035252723Sdim } 1036252723Sdim } 1037252723Sdim} 1038252723Sdim 1039245431Sdimnamespace clang { 1040245431Sdim 1041245431Sdim// Emits the class definitions for attributes. 1042245431Sdimvoid EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) { 1043252723Sdim emitSourceFileHeader("Attribute classes' definitions", OS); 1044252723Sdim 1045226586Sdim OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n"; 1046226586Sdim OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n"; 1047226586Sdim 1048226586Sdim std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 1049226586Sdim 1050226586Sdim for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(); 1051226586Sdim i != e; ++i) { 1052226586Sdim Record &R = **i; 1053245431Sdim 1054245431Sdim if (!R.getValueAsBit("ASTNode")) 1055245431Sdim continue; 1056245431Sdim 1057263509Sdim const std::vector<Record *> Supers = R.getSuperClasses(); 1058263509Sdim assert(!Supers.empty() && "Forgot to specify a superclass for the attr"); 1059263509Sdim std::string SuperName; 1060263509Sdim for (std::vector<Record *>::const_reverse_iterator I = Supers.rbegin(), 1061263509Sdim E = Supers.rend(); I != E; ++I) { 1062263509Sdim const Record &R = **I; 1063263509Sdim if (R.getName() != "TargetSpecificAttr" && SuperName.empty()) 1064263509Sdim SuperName = R.getName(); 1065263509Sdim } 1066226586Sdim 1067226586Sdim OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n"; 1068226586Sdim 1069226586Sdim std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args"); 1070226586Sdim std::vector<Argument*> Args; 1071226586Sdim std::vector<Argument*>::iterator ai, ae; 1072226586Sdim Args.reserve(ArgRecords.size()); 1073226586Sdim 1074226586Sdim for (std::vector<Record*>::iterator ri = ArgRecords.begin(), 1075226586Sdim re = ArgRecords.end(); 1076226586Sdim ri != re; ++ri) { 1077226586Sdim Record &ArgRecord = **ri; 1078226586Sdim Argument *Arg = createArgument(ArgRecord, R.getName()); 1079226586Sdim assert(Arg); 1080226586Sdim Args.push_back(Arg); 1081226586Sdim 1082226586Sdim Arg->writeDeclarations(OS); 1083226586Sdim OS << "\n\n"; 1084226586Sdim } 1085226586Sdim 1086226586Sdim ae = Args.end(); 1087226586Sdim 1088226586Sdim OS << "\n public:\n"; 1089226586Sdim OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n"; 1090226586Sdim 1091263509Sdim bool HasOpt = false; 1092226586Sdim for (ai = Args.begin(); ai != ae; ++ai) { 1093226586Sdim OS << " , "; 1094226586Sdim (*ai)->writeCtorParameters(OS); 1095226586Sdim OS << "\n"; 1096263509Sdim if ((*ai)->isOptional()) 1097263509Sdim HasOpt = true; 1098226586Sdim } 1099252723Sdim 1100252723Sdim OS << " , "; 1101252723Sdim OS << "unsigned SI = 0\n"; 1102252723Sdim 1103226586Sdim OS << " )\n"; 1104252723Sdim OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n"; 1105226586Sdim 1106226586Sdim for (ai = Args.begin(); ai != ae; ++ai) { 1107226586Sdim OS << " , "; 1108226586Sdim (*ai)->writeCtorInitializers(OS); 1109226586Sdim OS << "\n"; 1110226586Sdim } 1111226586Sdim 1112226586Sdim OS << " {\n"; 1113226586Sdim 1114226586Sdim for (ai = Args.begin(); ai != ae; ++ai) { 1115226586Sdim (*ai)->writeCtorBody(OS); 1116226586Sdim OS << "\n"; 1117226586Sdim } 1118226586Sdim OS << " }\n\n"; 1119226586Sdim 1120263509Sdim // If there are optional arguments, write out a constructor that elides the 1121263509Sdim // optional arguments as well. 1122263509Sdim if (HasOpt) { 1123263509Sdim OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n"; 1124263509Sdim for (ai = Args.begin(); ai != ae; ++ai) { 1125263509Sdim if (!(*ai)->isOptional()) { 1126263509Sdim OS << " , "; 1127263509Sdim (*ai)->writeCtorParameters(OS); 1128263509Sdim OS << "\n"; 1129263509Sdim } 1130263509Sdim } 1131263509Sdim 1132263509Sdim OS << " , "; 1133263509Sdim OS << "unsigned SI = 0\n"; 1134263509Sdim 1135263509Sdim OS << " )\n"; 1136263509Sdim OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n"; 1137263509Sdim 1138263509Sdim for (ai = Args.begin(); ai != ae; ++ai) { 1139263509Sdim OS << " , "; 1140263509Sdim (*ai)->writeCtorDefaultInitializers(OS); 1141263509Sdim OS << "\n"; 1142263509Sdim } 1143263509Sdim 1144263509Sdim OS << " {\n"; 1145263509Sdim 1146263509Sdim for (ai = Args.begin(); ai != ae; ++ai) { 1147263509Sdim if (!(*ai)->isOptional()) { 1148263509Sdim (*ai)->writeCtorBody(OS); 1149263509Sdim OS << "\n"; 1150263509Sdim } 1151263509Sdim } 1152263509Sdim OS << " }\n\n"; 1153263509Sdim } 1154263509Sdim 1155226586Sdim OS << " virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n"; 1156252723Sdim OS << " virtual void printPretty(raw_ostream &OS,\n" 1157245431Sdim << " const PrintingPolicy &Policy) const;\n"; 1158226586Sdim 1159252723Sdim writeAttrAccessorDefinition(R, OS); 1160252723Sdim 1161226586Sdim for (ai = Args.begin(); ai != ae; ++ai) { 1162226586Sdim (*ai)->writeAccessors(OS); 1163226586Sdim OS << "\n\n"; 1164263509Sdim 1165263509Sdim if ((*ai)->isEnumArg()) { 1166263509Sdim EnumArgument *EA = (EnumArgument *)*ai; 1167263509Sdim EA->writeConversion(OS); 1168263509Sdim } else if ((*ai)->isVariadicEnumArg()) { 1169263509Sdim VariadicEnumArgument *VEA = (VariadicEnumArgument *)*ai; 1170263509Sdim VEA->writeConversion(OS); 1171263509Sdim } 1172226586Sdim } 1173226586Sdim 1174235633Sdim OS << R.getValueAsString("AdditionalMembers"); 1175226586Sdim OS << "\n\n"; 1176226586Sdim 1177226586Sdim OS << " static bool classof(const Attr *A) { return A->getKind() == " 1178226586Sdim << "attr::" << R.getName() << "; }\n"; 1179235633Sdim 1180235633Sdim bool LateParsed = R.getValueAsBit("LateParsed"); 1181235633Sdim OS << " virtual bool isLateParsed() const { return " 1182235633Sdim << LateParsed << "; }\n"; 1183235633Sdim 1184226586Sdim OS << "};\n\n"; 1185226586Sdim } 1186226586Sdim 1187226586Sdim OS << "#endif\n"; 1188226586Sdim} 1189226586Sdim 1190263509Sdimstatic bool isIdentifierArgument(Record *Arg) { 1191263509Sdim return !Arg->getSuperClasses().empty() && 1192263509Sdim llvm::StringSwitch<bool>(Arg->getSuperClasses().back()->getName()) 1193263509Sdim .Case("IdentifierArgument", true) 1194263509Sdim .Case("EnumArgument", true) 1195263509Sdim .Default(false); 1196263509Sdim} 1197263509Sdim 1198263509Sdim/// \brief Emits the first-argument-is-type property for attributes. 1199263509Sdimvoid EmitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) { 1200263509Sdim emitSourceFileHeader("llvm::StringSwitch code to match attributes with a " 1201263509Sdim "type argument", OS); 1202263509Sdim 1203263509Sdim std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"); 1204263509Sdim 1205263509Sdim for (std::vector<Record *>::iterator I = Attrs.begin(), E = Attrs.end(); 1206263509Sdim I != E; ++I) { 1207263509Sdim Record &Attr = **I; 1208263509Sdim 1209263509Sdim // Determine whether the first argument is a type. 1210263509Sdim std::vector<Record *> Args = Attr.getValueAsListOfDefs("Args"); 1211263509Sdim if (Args.empty()) 1212263509Sdim continue; 1213263509Sdim 1214263509Sdim if (Args[0]->getSuperClasses().back()->getName() != "TypeArgument") 1215263509Sdim continue; 1216263509Sdim 1217263509Sdim // All these spellings take a single type argument. 1218263509Sdim std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); 1219263509Sdim std::set<std::string> Emitted; 1220263509Sdim for (std::vector<Record*>::const_iterator I = Spellings.begin(), 1221263509Sdim E = Spellings.end(); I != E; ++I) { 1222263509Sdim if (Emitted.insert((*I)->getValueAsString("Name")).second) 1223263509Sdim OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", " 1224263509Sdim << "true" << ")\n"; 1225263509Sdim } 1226263509Sdim } 1227263509Sdim} 1228263509Sdim 1229263509Sdim// Emits the first-argument-is-identifier property for attributes. 1230263509Sdimvoid EmitClangAttrIdentifierArgList(RecordKeeper &Records, raw_ostream &OS) { 1231252723Sdim emitSourceFileHeader("llvm::StringSwitch code to match attributes with " 1232263509Sdim "an identifier argument", OS); 1233252723Sdim 1234252723Sdim std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 1235252723Sdim 1236252723Sdim for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); 1237252723Sdim I != E; ++I) { 1238252723Sdim Record &Attr = **I; 1239252723Sdim 1240263509Sdim // Determine whether the first argument is an identifier. 1241252723Sdim std::vector<Record *> Args = Attr.getValueAsListOfDefs("Args"); 1242263509Sdim if (Args.empty() || !isIdentifierArgument(Args[0])) 1243252723Sdim continue; 1244252723Sdim 1245263509Sdim // All these spellings take an identifier argument. 1246252723Sdim std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); 1247263509Sdim std::set<std::string> Emitted; 1248252723Sdim for (std::vector<Record*>::const_iterator I = Spellings.begin(), 1249252723Sdim E = Spellings.end(); I != E; ++I) { 1250263509Sdim if (Emitted.insert((*I)->getValueAsString("Name")).second) 1251263509Sdim OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", " 1252263509Sdim << "true" << ")\n"; 1253252723Sdim } 1254252723Sdim } 1255252723Sdim} 1256252723Sdim 1257245431Sdim// Emits the class method definitions for attributes. 1258245431Sdimvoid EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) { 1259252723Sdim emitSourceFileHeader("Attribute classes' member function definitions", OS); 1260226586Sdim 1261226586Sdim std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 1262226586Sdim std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ri, re; 1263226586Sdim std::vector<Argument*>::iterator ai, ae; 1264226586Sdim 1265226586Sdim for (; i != e; ++i) { 1266226586Sdim Record &R = **i; 1267245431Sdim 1268245431Sdim if (!R.getValueAsBit("ASTNode")) 1269245431Sdim continue; 1270245431Sdim 1271226586Sdim std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args"); 1272226586Sdim std::vector<Argument*> Args; 1273226586Sdim for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri) 1274226586Sdim Args.push_back(createArgument(**ri, R.getName())); 1275226586Sdim 1276226586Sdim for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai) 1277226586Sdim (*ai)->writeAccessorDefinitions(OS); 1278226586Sdim 1279226586Sdim OS << R.getName() << "Attr *" << R.getName() 1280226586Sdim << "Attr::clone(ASTContext &C) const {\n"; 1281226586Sdim OS << " return new (C) " << R.getName() << "Attr(getLocation(), C"; 1282226586Sdim for (ai = Args.begin(); ai != ae; ++ai) { 1283226586Sdim OS << ", "; 1284226586Sdim (*ai)->writeCloneArgs(OS); 1285226586Sdim } 1286252723Sdim OS << ", getSpellingListIndex());\n}\n\n"; 1287235633Sdim 1288252723Sdim writePrettyPrintFunction(R, Args, OS); 1289226586Sdim } 1290226586Sdim} 1291226586Sdim 1292245431Sdim} // end namespace clang 1293245431Sdim 1294226586Sdimstatic void EmitAttrList(raw_ostream &OS, StringRef Class, 1295226586Sdim const std::vector<Record*> &AttrList) { 1296226586Sdim std::vector<Record*>::const_iterator i = AttrList.begin(), e = AttrList.end(); 1297226586Sdim 1298226586Sdim if (i != e) { 1299226586Sdim // Move the end iterator back to emit the last attribute. 1300245431Sdim for(--e; i != e; ++i) { 1301245431Sdim if (!(*i)->getValueAsBit("ASTNode")) 1302245431Sdim continue; 1303245431Sdim 1304226586Sdim OS << Class << "(" << (*i)->getName() << ")\n"; 1305245431Sdim } 1306226586Sdim 1307226586Sdim OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n"; 1308226586Sdim } 1309226586Sdim} 1310226586Sdim 1311245431Sdimnamespace clang { 1312245431Sdim 1313245431Sdim// Emits the enumeration list for attributes. 1314245431Sdimvoid EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) { 1315252723Sdim emitSourceFileHeader("List of all attributes that Clang recognizes", OS); 1316226586Sdim 1317226586Sdim OS << "#ifndef LAST_ATTR\n"; 1318226586Sdim OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n"; 1319226586Sdim OS << "#endif\n\n"; 1320226586Sdim 1321226586Sdim OS << "#ifndef INHERITABLE_ATTR\n"; 1322226586Sdim OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n"; 1323226586Sdim OS << "#endif\n\n"; 1324226586Sdim 1325226586Sdim OS << "#ifndef LAST_INHERITABLE_ATTR\n"; 1326226586Sdim OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n"; 1327226586Sdim OS << "#endif\n\n"; 1328226586Sdim 1329226586Sdim OS << "#ifndef INHERITABLE_PARAM_ATTR\n"; 1330226586Sdim OS << "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n"; 1331226586Sdim OS << "#endif\n\n"; 1332226586Sdim 1333226586Sdim OS << "#ifndef LAST_INHERITABLE_PARAM_ATTR\n"; 1334226586Sdim OS << "#define LAST_INHERITABLE_PARAM_ATTR(NAME)" 1335226586Sdim " INHERITABLE_PARAM_ATTR(NAME)\n"; 1336226586Sdim OS << "#endif\n\n"; 1337226586Sdim 1338263509Sdim OS << "#ifndef MS_INHERITANCE_ATTR\n"; 1339263509Sdim OS << "#define MS_INHERITANCE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n"; 1340252723Sdim OS << "#endif\n\n"; 1341252723Sdim 1342263509Sdim OS << "#ifndef LAST_MS_INHERITANCE_ATTR\n"; 1343263509Sdim OS << "#define LAST_MS_INHERITANCE_ATTR(NAME)" 1344263509Sdim " MS_INHERITANCE_ATTR(NAME)\n"; 1345252723Sdim OS << "#endif\n\n"; 1346252723Sdim 1347226586Sdim Record *InhClass = Records.getClass("InheritableAttr"); 1348226586Sdim Record *InhParamClass = Records.getClass("InheritableParamAttr"); 1349252723Sdim Record *MSInheritanceClass = Records.getClass("MSInheritanceAttr"); 1350226586Sdim std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), 1351252723Sdim NonInhAttrs, InhAttrs, InhParamAttrs, MSInhAttrs; 1352226586Sdim for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(); 1353226586Sdim i != e; ++i) { 1354245431Sdim if (!(*i)->getValueAsBit("ASTNode")) 1355245431Sdim continue; 1356245431Sdim 1357226586Sdim if ((*i)->isSubClassOf(InhParamClass)) 1358226586Sdim InhParamAttrs.push_back(*i); 1359252723Sdim else if ((*i)->isSubClassOf(MSInheritanceClass)) 1360252723Sdim MSInhAttrs.push_back(*i); 1361226586Sdim else if ((*i)->isSubClassOf(InhClass)) 1362226586Sdim InhAttrs.push_back(*i); 1363226586Sdim else 1364226586Sdim NonInhAttrs.push_back(*i); 1365226586Sdim } 1366226586Sdim 1367226586Sdim EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs); 1368263509Sdim EmitAttrList(OS, "MS_INHERITANCE_ATTR", MSInhAttrs); 1369226586Sdim EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs); 1370226586Sdim EmitAttrList(OS, "ATTR", NonInhAttrs); 1371226586Sdim 1372226586Sdim OS << "#undef LAST_ATTR\n"; 1373226586Sdim OS << "#undef INHERITABLE_ATTR\n"; 1374263509Sdim OS << "#undef MS_INHERITANCE_ATTR\n"; 1375226586Sdim OS << "#undef LAST_INHERITABLE_ATTR\n"; 1376226586Sdim OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n"; 1377263509Sdim OS << "#undef LAST_MS_INHERITANCE_ATTR\n"; 1378226586Sdim OS << "#undef ATTR\n"; 1379226586Sdim} 1380226586Sdim 1381245431Sdim// Emits the code to read an attribute from a precompiled header. 1382245431Sdimvoid EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) { 1383252723Sdim emitSourceFileHeader("Attribute deserialization code", OS); 1384226586Sdim 1385226586Sdim Record *InhClass = Records.getClass("InheritableAttr"); 1386226586Sdim std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), 1387226586Sdim ArgRecords; 1388226586Sdim std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae; 1389226586Sdim std::vector<Argument*> Args; 1390226586Sdim std::vector<Argument*>::iterator ri, re; 1391226586Sdim 1392226586Sdim OS << " switch (Kind) {\n"; 1393226586Sdim OS << " default:\n"; 1394226586Sdim OS << " assert(0 && \"Unknown attribute!\");\n"; 1395226586Sdim OS << " break;\n"; 1396226586Sdim for (; i != e; ++i) { 1397226586Sdim Record &R = **i; 1398245431Sdim if (!R.getValueAsBit("ASTNode")) 1399245431Sdim continue; 1400245431Sdim 1401226586Sdim OS << " case attr::" << R.getName() << ": {\n"; 1402226586Sdim if (R.isSubClassOf(InhClass)) 1403226586Sdim OS << " bool isInherited = Record[Idx++];\n"; 1404226586Sdim ArgRecords = R.getValueAsListOfDefs("Args"); 1405226586Sdim Args.clear(); 1406226586Sdim for (ai = ArgRecords.begin(), ae = ArgRecords.end(); ai != ae; ++ai) { 1407226586Sdim Argument *A = createArgument(**ai, R.getName()); 1408226586Sdim Args.push_back(A); 1409226586Sdim A->writePCHReadDecls(OS); 1410226586Sdim } 1411226586Sdim OS << " New = new (Context) " << R.getName() << "Attr(Range, Context"; 1412226586Sdim for (ri = Args.begin(), re = Args.end(); ri != re; ++ri) { 1413226586Sdim OS << ", "; 1414226586Sdim (*ri)->writePCHReadArgs(OS); 1415226586Sdim } 1416226586Sdim OS << ");\n"; 1417226586Sdim if (R.isSubClassOf(InhClass)) 1418226586Sdim OS << " cast<InheritableAttr>(New)->setInherited(isInherited);\n"; 1419226586Sdim OS << " break;\n"; 1420226586Sdim OS << " }\n"; 1421226586Sdim } 1422226586Sdim OS << " }\n"; 1423226586Sdim} 1424226586Sdim 1425245431Sdim// Emits the code to write an attribute to a precompiled header. 1426245431Sdimvoid EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) { 1427252723Sdim emitSourceFileHeader("Attribute serialization code", OS); 1428252723Sdim 1429226586Sdim Record *InhClass = Records.getClass("InheritableAttr"); 1430226586Sdim std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args; 1431226586Sdim std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae; 1432226586Sdim 1433226586Sdim OS << " switch (A->getKind()) {\n"; 1434226586Sdim OS << " default:\n"; 1435226586Sdim OS << " llvm_unreachable(\"Unknown attribute kind!\");\n"; 1436226586Sdim OS << " break;\n"; 1437226586Sdim for (; i != e; ++i) { 1438226586Sdim Record &R = **i; 1439245431Sdim if (!R.getValueAsBit("ASTNode")) 1440245431Sdim continue; 1441226586Sdim OS << " case attr::" << R.getName() << ": {\n"; 1442226586Sdim Args = R.getValueAsListOfDefs("Args"); 1443226586Sdim if (R.isSubClassOf(InhClass) || !Args.empty()) 1444226586Sdim OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName() 1445226586Sdim << "Attr>(A);\n"; 1446226586Sdim if (R.isSubClassOf(InhClass)) 1447226586Sdim OS << " Record.push_back(SA->isInherited());\n"; 1448226586Sdim for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai) 1449226586Sdim createArgument(**ai, R.getName())->writePCHWrite(OS); 1450226586Sdim OS << " break;\n"; 1451226586Sdim OS << " }\n"; 1452226586Sdim } 1453226586Sdim OS << " }\n"; 1454226586Sdim} 1455226586Sdim 1456245431Sdim// Emits the list of spellings for attributes. 1457245431Sdimvoid EmitClangAttrSpellingList(RecordKeeper &Records, raw_ostream &OS) { 1458252723Sdim emitSourceFileHeader("llvm::StringSwitch code to match all known attributes", 1459252723Sdim OS); 1460226586Sdim 1461226586Sdim std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 1462226586Sdim 1463226586Sdim for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) { 1464226586Sdim Record &Attr = **I; 1465226586Sdim 1466245431Sdim std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); 1467226586Sdim 1468245431Sdim for (std::vector<Record*>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) { 1469245431Sdim OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", true)\n"; 1470226586Sdim } 1471226586Sdim } 1472226586Sdim 1473226586Sdim} 1474226586Sdim 1475252723Sdimvoid EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) { 1476252723Sdim emitSourceFileHeader("Code to translate different attribute spellings " 1477252723Sdim "into internal identifiers", OS); 1478252723Sdim 1479252723Sdim OS << 1480252723Sdim " unsigned Index = 0;\n" 1481252723Sdim " switch (AttrKind) {\n" 1482252723Sdim " default:\n" 1483252723Sdim " llvm_unreachable(\"Unknown attribute kind!\");\n" 1484252723Sdim " break;\n"; 1485252723Sdim 1486252723Sdim std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 1487252723Sdim for (std::vector<Record*>::const_iterator I = Attrs.begin(), E = Attrs.end(); 1488252723Sdim I != E; ++I) { 1489252723Sdim Record &R = **I; 1490252723Sdim // We only care about attributes that participate in Sema checking, so 1491252723Sdim // skip those attributes that are not able to make their way to Sema. 1492252723Sdim if (!R.getValueAsBit("SemaHandler")) 1493252723Sdim continue; 1494252723Sdim 1495252723Sdim std::vector<Record*> Spellings = R.getValueAsListOfDefs("Spellings"); 1496252723Sdim // Each distinct spelling yields an attribute kind. 1497252723Sdim if (R.getValueAsBit("DistinctSpellings")) { 1498252723Sdim for (unsigned I = 0; I < Spellings.size(); ++ I) { 1499252723Sdim OS << 1500252723Sdim " case AT_" << Spellings[I]->getValueAsString("Name") << ": \n" 1501252723Sdim " Index = " << I << ";\n" 1502252723Sdim " break;\n"; 1503252723Sdim } 1504252723Sdim } else { 1505252723Sdim OS << " case AT_" << R.getName() << " : {\n"; 1506252723Sdim for (unsigned I = 0; I < Spellings.size(); ++ I) { 1507252723Sdim SmallString<16> Namespace; 1508252723Sdim if (Spellings[I]->getValueAsString("Variety") == "CXX11") 1509252723Sdim Namespace = Spellings[I]->getValueAsString("Namespace"); 1510252723Sdim else 1511252723Sdim Namespace = ""; 1512252723Sdim 1513252723Sdim OS << " if (Name == \"" 1514252723Sdim << Spellings[I]->getValueAsString("Name") << "\" && " 1515252723Sdim << "SyntaxUsed == " 1516252723Sdim << StringSwitch<unsigned>(Spellings[I]->getValueAsString("Variety")) 1517252723Sdim .Case("GNU", 0) 1518252723Sdim .Case("CXX11", 1) 1519252723Sdim .Case("Declspec", 2) 1520252723Sdim .Case("Keyword", 3) 1521252723Sdim .Default(0) 1522252723Sdim << " && Scope == \"" << Namespace << "\")\n" 1523252723Sdim << " return " << I << ";\n"; 1524252723Sdim } 1525252723Sdim 1526252723Sdim OS << " break;\n"; 1527252723Sdim OS << " }\n"; 1528252723Sdim } 1529252723Sdim } 1530252723Sdim 1531252723Sdim OS << " }\n"; 1532252723Sdim OS << " return Index;\n"; 1533252723Sdim} 1534252723Sdim 1535245431Sdim// Emits the LateParsed property for attributes. 1536245431Sdimvoid EmitClangAttrLateParsedList(RecordKeeper &Records, raw_ostream &OS) { 1537252723Sdim emitSourceFileHeader("llvm::StringSwitch code to match late parsed " 1538252723Sdim "attributes", OS); 1539226586Sdim 1540226586Sdim std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 1541226586Sdim 1542226586Sdim for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); 1543226586Sdim I != E; ++I) { 1544226586Sdim Record &Attr = **I; 1545226586Sdim 1546226586Sdim bool LateParsed = Attr.getValueAsBit("LateParsed"); 1547226586Sdim 1548226586Sdim if (LateParsed) { 1549245431Sdim std::vector<Record*> Spellings = 1550245431Sdim Attr.getValueAsListOfDefs("Spellings"); 1551226586Sdim 1552245431Sdim // FIXME: Handle non-GNU attributes 1553245431Sdim for (std::vector<Record*>::const_iterator I = Spellings.begin(), 1554226586Sdim E = Spellings.end(); I != E; ++I) { 1555245431Sdim if ((*I)->getValueAsString("Variety") != "GNU") 1556245431Sdim continue; 1557245431Sdim OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", " 1558245431Sdim << LateParsed << ")\n"; 1559226586Sdim } 1560226586Sdim } 1561226586Sdim } 1562226586Sdim} 1563235633Sdim 1564245431Sdim// Emits code to instantiate dependent attributes on templates. 1565245431Sdimvoid EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) { 1566252723Sdim emitSourceFileHeader("Template instantiation code for attributes", OS); 1567235633Sdim 1568235633Sdim std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 1569235633Sdim 1570235633Sdim OS << "namespace clang {\n" 1571235633Sdim << "namespace sema {\n\n" 1572235633Sdim << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, " 1573235633Sdim << "Sema &S,\n" 1574235633Sdim << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n" 1575235633Sdim << " switch (At->getKind()) {\n" 1576235633Sdim << " default:\n" 1577235633Sdim << " break;\n"; 1578235633Sdim 1579235633Sdim for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); 1580235633Sdim I != E; ++I) { 1581235633Sdim Record &R = **I; 1582245431Sdim if (!R.getValueAsBit("ASTNode")) 1583245431Sdim continue; 1584235633Sdim 1585235633Sdim OS << " case attr::" << R.getName() << ": {\n"; 1586245431Sdim bool ShouldClone = R.getValueAsBit("Clone"); 1587245431Sdim 1588245431Sdim if (!ShouldClone) { 1589245431Sdim OS << " return NULL;\n"; 1590245431Sdim OS << " }\n"; 1591245431Sdim continue; 1592245431Sdim } 1593245431Sdim 1594235633Sdim OS << " const " << R.getName() << "Attr *A = cast<" 1595235633Sdim << R.getName() << "Attr>(At);\n"; 1596235633Sdim bool TDependent = R.getValueAsBit("TemplateDependent"); 1597235633Sdim 1598235633Sdim if (!TDependent) { 1599235633Sdim OS << " return A->clone(C);\n"; 1600235633Sdim OS << " }\n"; 1601235633Sdim continue; 1602235633Sdim } 1603235633Sdim 1604235633Sdim std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args"); 1605235633Sdim std::vector<Argument*> Args; 1606235633Sdim std::vector<Argument*>::iterator ai, ae; 1607235633Sdim Args.reserve(ArgRecords.size()); 1608235633Sdim 1609235633Sdim for (std::vector<Record*>::iterator ri = ArgRecords.begin(), 1610235633Sdim re = ArgRecords.end(); 1611235633Sdim ri != re; ++ri) { 1612235633Sdim Record &ArgRecord = **ri; 1613235633Sdim Argument *Arg = createArgument(ArgRecord, R.getName()); 1614235633Sdim assert(Arg); 1615235633Sdim Args.push_back(Arg); 1616235633Sdim } 1617235633Sdim ae = Args.end(); 1618235633Sdim 1619235633Sdim for (ai = Args.begin(); ai != ae; ++ai) { 1620235633Sdim (*ai)->writeTemplateInstantiation(OS); 1621235633Sdim } 1622235633Sdim OS << " return new (C) " << R.getName() << "Attr(A->getLocation(), C"; 1623235633Sdim for (ai = Args.begin(); ai != ae; ++ai) { 1624235633Sdim OS << ", "; 1625235633Sdim (*ai)->writeTemplateInstantiationArgs(OS); 1626235633Sdim } 1627235633Sdim OS << ");\n }\n"; 1628235633Sdim } 1629235633Sdim OS << " } // end switch\n" 1630235633Sdim << " llvm_unreachable(\"Unknown attribute!\");\n" 1631235633Sdim << " return 0;\n" 1632235633Sdim << "}\n\n" 1633235633Sdim << "} // end namespace sema\n" 1634235633Sdim << "} // end namespace clang\n"; 1635235633Sdim} 1636235633Sdim 1637263509Sdimtypedef std::vector<std::pair<std::string, Record *> > ParsedAttrMap; 1638252723Sdim 1639263509Sdimstatic ParsedAttrMap getParsedAttrList(const RecordKeeper &Records) { 1640235633Sdim std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 1641263509Sdim ParsedAttrMap R; 1642235633Sdim for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); 1643235633Sdim I != E; ++I) { 1644235633Sdim Record &Attr = **I; 1645235633Sdim 1646235633Sdim bool SemaHandler = Attr.getValueAsBit("SemaHandler"); 1647245431Sdim bool DistinctSpellings = Attr.getValueAsBit("DistinctSpellings"); 1648245431Sdim 1649235633Sdim if (SemaHandler) { 1650245431Sdim if (DistinctSpellings) { 1651245431Sdim std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); 1652245431Sdim 1653245431Sdim for (std::vector<Record*>::const_iterator I = Spellings.begin(), 1654245431Sdim E = Spellings.end(); I != E; ++I) { 1655245431Sdim std::string AttrName = (*I)->getValueAsString("Name"); 1656235633Sdim 1657245431Sdim StringRef Spelling = NormalizeAttrName(AttrName); 1658263509Sdim R.push_back(std::make_pair(Spelling.str(), &Attr)); 1659245431Sdim } 1660245431Sdim } else { 1661245431Sdim StringRef AttrName = Attr.getName(); 1662235633Sdim AttrName = NormalizeAttrName(AttrName); 1663263509Sdim R.push_back(std::make_pair(AttrName.str(), *I)); 1664235633Sdim } 1665235633Sdim } 1666235633Sdim } 1667263509Sdim return R; 1668235633Sdim} 1669235633Sdim 1670263509Sdim// Emits the list of parsed attributes. 1671263509Sdimvoid EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) { 1672263509Sdim emitSourceFileHeader("List of all attributes that Clang recognizes", OS); 1673263509Sdim 1674263509Sdim OS << "#ifndef PARSED_ATTR\n"; 1675263509Sdim OS << "#define PARSED_ATTR(NAME) NAME\n"; 1676263509Sdim OS << "#endif\n\n"; 1677263509Sdim 1678263509Sdim ParsedAttrMap Names = getParsedAttrList(Records); 1679263509Sdim for (ParsedAttrMap::iterator I = Names.begin(), E = Names.end(); I != E; 1680263509Sdim ++I) { 1681263509Sdim OS << "PARSED_ATTR(" << I->first << ")\n"; 1682263509Sdim } 1683263509Sdim} 1684263509Sdim 1685263509Sdimstatic void emitArgInfo(const Record &R, raw_ostream &OS) { 1686263509Sdim // This function will count the number of arguments specified for the 1687263509Sdim // attribute and emit the number of required arguments followed by the 1688263509Sdim // number of optional arguments. 1689263509Sdim std::vector<Record *> Args = R.getValueAsListOfDefs("Args"); 1690263509Sdim unsigned ArgCount = 0, OptCount = 0; 1691263509Sdim for (std::vector<Record *>::const_iterator I = Args.begin(), E = Args.end(); 1692263509Sdim I != E; ++I) { 1693263509Sdim const Record &Arg = **I; 1694263509Sdim Arg.getValueAsBit("Optional") ? ++OptCount : ++ArgCount; 1695263509Sdim } 1696263509Sdim OS << ArgCount << ", " << OptCount; 1697263509Sdim} 1698263509Sdim 1699263509Sdim/// Emits the parsed attribute helpers 1700263509Sdimvoid EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) { 1701263509Sdim emitSourceFileHeader("Parsed attribute helpers", OS); 1702263509Sdim 1703263509Sdim ParsedAttrMap Attrs = getParsedAttrList(Records); 1704263509Sdim 1705263509Sdim OS << "static const ParsedAttrInfo AttrInfoMap[AttributeList::UnknownAttribute + 1] = {\n"; 1706263509Sdim for (ParsedAttrMap::iterator I = Attrs.begin(), E = Attrs.end(); I != E; 1707263509Sdim ++I) { 1708263509Sdim // We need to generate struct instances based off ParsedAttrInfo from 1709263509Sdim // AttributeList.cpp. 1710263509Sdim OS << " { "; 1711263509Sdim emitArgInfo(*I->second, OS); 1712263509Sdim OS << ", " << I->second->getValueAsBit("HasCustomParsing"); 1713263509Sdim OS << " }"; 1714263509Sdim 1715263509Sdim if (I + 1 != E) 1716263509Sdim OS << ","; 1717263509Sdim 1718263509Sdim OS << " // AT_" << I->first << "\n"; 1719263509Sdim } 1720263509Sdim OS << "};\n\n"; 1721263509Sdim} 1722263509Sdim 1723245431Sdim// Emits the kind list of parsed attributes 1724245431Sdimvoid EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) { 1725252723Sdim emitSourceFileHeader("Attribute name matcher", OS); 1726252723Sdim 1727235633Sdim std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 1728235633Sdim 1729245431Sdim std::vector<StringMatcher::StringPair> Matches; 1730235633Sdim for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); 1731235633Sdim I != E; ++I) { 1732235633Sdim Record &Attr = **I; 1733235633Sdim 1734235633Sdim bool SemaHandler = Attr.getValueAsBit("SemaHandler"); 1735245431Sdim bool Ignored = Attr.getValueAsBit("Ignored"); 1736245431Sdim bool DistinctSpellings = Attr.getValueAsBit("DistinctSpellings"); 1737245431Sdim if (SemaHandler || Ignored) { 1738245431Sdim std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); 1739235633Sdim 1740245431Sdim for (std::vector<Record*>::const_iterator I = Spellings.begin(), 1741235633Sdim E = Spellings.end(); I != E; ++I) { 1742245431Sdim std::string RawSpelling = (*I)->getValueAsString("Name"); 1743245431Sdim StringRef AttrName = NormalizeAttrName(DistinctSpellings 1744245431Sdim ? StringRef(RawSpelling) 1745245431Sdim : StringRef(Attr.getName())); 1746235633Sdim 1747245431Sdim SmallString<64> Spelling; 1748245431Sdim if ((*I)->getValueAsString("Variety") == "CXX11") { 1749245431Sdim Spelling += (*I)->getValueAsString("Namespace"); 1750245431Sdim Spelling += "::"; 1751245431Sdim } 1752245431Sdim Spelling += NormalizeAttrSpelling(RawSpelling); 1753245431Sdim 1754245431Sdim if (SemaHandler) 1755245431Sdim Matches.push_back( 1756245431Sdim StringMatcher::StringPair( 1757245431Sdim StringRef(Spelling), 1758245431Sdim "return AttributeList::AT_" + AttrName.str() + ";")); 1759245431Sdim else 1760245431Sdim Matches.push_back( 1761245431Sdim StringMatcher::StringPair( 1762245431Sdim StringRef(Spelling), 1763245431Sdim "return AttributeList::IgnoredAttribute;")); 1764235633Sdim } 1765235633Sdim } 1766235633Sdim } 1767245431Sdim 1768245431Sdim OS << "static AttributeList::Kind getAttrKind(StringRef Name) {\n"; 1769245431Sdim StringMatcher("Name", Matches, OS).Emit(); 1770245431Sdim OS << "return AttributeList::UnknownAttribute;\n" 1771245431Sdim << "}\n"; 1772235633Sdim} 1773235633Sdim 1774252723Sdim// Emits the code to dump an attribute. 1775252723Sdimvoid EmitClangAttrDump(RecordKeeper &Records, raw_ostream &OS) { 1776252723Sdim emitSourceFileHeader("Attribute dumper", OS); 1777252723Sdim 1778252723Sdim OS << 1779252723Sdim " switch (A->getKind()) {\n" 1780252723Sdim " default:\n" 1781252723Sdim " llvm_unreachable(\"Unknown attribute kind!\");\n" 1782252723Sdim " break;\n"; 1783252723Sdim std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args; 1784252723Sdim for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); 1785252723Sdim I != E; ++I) { 1786252723Sdim Record &R = **I; 1787252723Sdim if (!R.getValueAsBit("ASTNode")) 1788252723Sdim continue; 1789252723Sdim OS << " case attr::" << R.getName() << ": {\n"; 1790252723Sdim Args = R.getValueAsListOfDefs("Args"); 1791252723Sdim if (!Args.empty()) { 1792252723Sdim OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName() 1793252723Sdim << "Attr>(A);\n"; 1794252723Sdim for (std::vector<Record*>::iterator I = Args.begin(), E = Args.end(); 1795252723Sdim I != E; ++I) 1796252723Sdim createArgument(**I, R.getName())->writeDump(OS); 1797252723Sdim 1798252723Sdim // Code for detecting the last child. 1799252723Sdim OS << " bool OldMoreChildren = hasMoreChildren();\n"; 1800252723Sdim OS << " bool MoreChildren = OldMoreChildren;\n"; 1801252723Sdim 1802252723Sdim for (std::vector<Record*>::iterator I = Args.begin(), E = Args.end(); 1803252723Sdim I != E; ++I) { 1804252723Sdim // More code for detecting the last child. 1805252723Sdim OS << " MoreChildren = OldMoreChildren"; 1806252723Sdim for (std::vector<Record*>::iterator Next = I + 1; Next != E; ++Next) { 1807252723Sdim OS << " || "; 1808252723Sdim createArgument(**Next, R.getName())->writeHasChildren(OS); 1809252723Sdim } 1810252723Sdim OS << ";\n"; 1811252723Sdim OS << " setMoreChildren(MoreChildren);\n"; 1812252723Sdim 1813252723Sdim createArgument(**I, R.getName())->writeDumpChildren(OS); 1814252723Sdim } 1815252723Sdim 1816252723Sdim // Reset the last child. 1817252723Sdim OS << " setMoreChildren(OldMoreChildren);\n"; 1818252723Sdim } 1819252723Sdim OS << 1820252723Sdim " break;\n" 1821252723Sdim " }\n"; 1822252723Sdim } 1823252723Sdim OS << " }\n"; 1824252723Sdim} 1825252723Sdim 1826245431Sdim} // end namespace clang 1827