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 14239462Sdim#include "llvm/ADT/SmallString.h" 15226586Sdim#include "llvm/ADT/StringSwitch.h" 16263508Sdim#include "llvm/ADT/SmallSet.h" 17226586Sdim#include "llvm/TableGen/Record.h" 18239462Sdim#include "llvm/TableGen/StringMatcher.h" 19239462Sdim#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"); 37243830Sdim 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++])") 50263508Sdim .Case("TypeSourceInfo *", "GetTypeSourceInfo(F, Record, Idx)") 51249423Sdim .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") 62263508Sdim .Case("TypeSourceInfo *", 63263508Sdim "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 72234353Sdim// Normalize attribute name by removing leading and trailing 73234353Sdim// underscores. For example, __foo, foo__, __foo__ would 74234353Sdim// become foo. 75234353Sdimstatic StringRef NormalizeAttrName(StringRef AttrName) { 76234353Sdim if (AttrName.startswith("__")) 77234353Sdim AttrName = AttrName.substr(2, AttrName.size()); 78234353Sdim 79234353Sdim if (AttrName.endswith("__")) 80234353Sdim AttrName = AttrName.substr(0, AttrName.size() - 2); 81234353Sdim 82234353Sdim return AttrName; 83234353Sdim} 84234353Sdim 85234353Sdim// Normalize attribute spelling only if the spelling has both leading 86234353Sdim// and trailing underscores. For example, __ms_struct__ will be 87234353Sdim// normalized to "ms_struct"; __cdecl will remain intact. 88234353Sdimstatic StringRef NormalizeAttrSpelling(StringRef AttrSpelling) { 89234353Sdim if (AttrSpelling.startswith("__") && AttrSpelling.endswith("__")) { 90234353Sdim AttrSpelling = AttrSpelling.substr(2, AttrSpelling.size() - 4); 91234353Sdim } 92234353Sdim 93234353Sdim return AttrSpelling; 94234353Sdim} 95234353Sdim 96226586Sdimnamespace { 97226586Sdim class Argument { 98226586Sdim std::string lowerName, upperName; 99226586Sdim StringRef attrName; 100263508Sdim bool isOpt; 101226586Sdim 102226586Sdim public: 103226586Sdim Argument(Record &Arg, StringRef Attr) 104226586Sdim : lowerName(Arg.getValueAsString("Name")), upperName(lowerName), 105263508Sdim 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 117263508Sdim bool isOptional() const { return isOpt; } 118263508Sdim void setOptional(bool set) { isOpt = set; } 119263508Sdim 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; 124234353Sdim virtual void writeTemplateInstantiationArgs(raw_ostream &OS) const = 0; 125234353Sdim virtual void writeTemplateInstantiation(raw_ostream &OS) const {} 126226586Sdim virtual void writeCtorBody(raw_ostream &OS) const {} 127226586Sdim virtual void writeCtorInitializers(raw_ostream &OS) const = 0; 128263508Sdim 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; 134234353Sdim virtual void writeValue(raw_ostream &OS) const = 0; 135249423Sdim virtual void writeDump(raw_ostream &OS) const = 0; 136249423Sdim virtual void writeDumpChildren(raw_ostream &OS) const {} 137249423Sdim virtual void writeHasChildren(raw_ostream &OS) const { OS << "false"; } 138263508Sdim 139263508Sdim virtual bool isEnumArg() const { return false; } 140263508Sdim 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 151234353Sdim std::string getType() const { return type; } 152234353Sdim 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 } 161234353Sdim void writeTemplateInstantiationArgs(raw_ostream &OS) const { 162234353Sdim OS << "A->get" << getUpperName() << "()"; 163234353Sdim } 164226586Sdim void writeCtorInitializers(raw_ostream &OS) const { 165226586Sdim OS << getLowerName() << "(" << getUpperName() << ")"; 166226586Sdim } 167263508Sdim void writeCtorDefaultInitializers(raw_ostream &OS) const { 168263508Sdim OS << getLowerName() << "()"; 169263508Sdim } 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 } 187234353Sdim void writeValue(raw_ostream &OS) const { 188234353Sdim if (type == "FunctionDecl *") { 189263508Sdim OS << "\" << get" << getUpperName() 190263508Sdim << "()->getNameInfo().getAsString() << \""; 191234353Sdim } else if (type == "IdentifierInfo *") { 192234353Sdim OS << "\" << get" << getUpperName() << "()->getName() << \""; 193263508Sdim } else if (type == "TypeSourceInfo *") { 194234353Sdim OS << "\" << get" << getUpperName() << "().getAsString() << \""; 195234353Sdim } else if (type == "SourceLocation") { 196234353Sdim OS << "\" << get" << getUpperName() << "().getRawEncoding() << \""; 197234353Sdim } else { 198234353Sdim OS << "\" << get" << getUpperName() << "() << \""; 199234353Sdim } 200234353Sdim } 201249423Sdim void writeDump(raw_ostream &OS) const { 202249423Sdim if (type == "FunctionDecl *") { 203249423Sdim OS << " OS << \" \";\n"; 204249423Sdim OS << " dumpBareDeclRef(SA->get" << getUpperName() << "());\n"; 205249423Sdim } else if (type == "IdentifierInfo *") { 206249423Sdim OS << " OS << \" \" << SA->get" << getUpperName() 207249423Sdim << "()->getName();\n"; 208263508Sdim } else if (type == "TypeSourceInfo *") { 209249423Sdim OS << " OS << \" \" << SA->get" << getUpperName() 210249423Sdim << "().getAsString();\n"; 211249423Sdim } else if (type == "SourceLocation") { 212249423Sdim OS << " OS << \" \";\n"; 213249423Sdim OS << " SA->get" << getUpperName() << "().print(OS, *SM);\n"; 214249423Sdim } else if (type == "bool") { 215249423Sdim OS << " if (SA->get" << getUpperName() << "()) OS << \" " 216249423Sdim << getUpperName() << "\";\n"; 217249423Sdim } else if (type == "int" || type == "unsigned") { 218249423Sdim OS << " OS << \" \" << SA->get" << getUpperName() << "();\n"; 219249423Sdim } else { 220249423Sdim llvm_unreachable("Unknown SimpleArgument type!"); 221249423Sdim } 222249423Sdim } 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 } 251234353Sdim void writeTemplateInstantiationArgs(raw_ostream &OS) const { 252234353Sdim OS << "A->get" << getUpperName() << "()"; 253234353Sdim } 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 } 263263508Sdim void writeCtorDefaultInitializers(raw_ostream &OS) const { 264263508Sdim OS << getLowerName() << "Length(0)," << getLowerName() << "(0)"; 265263508Sdim } 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 } 283234353Sdim void writeValue(raw_ostream &OS) const { 284234353Sdim OS << "\\\"\" << get" << getUpperName() << "() << \"\\\""; 285234353Sdim } 286249423Sdim void writeDump(raw_ostream &OS) const { 287249423Sdim OS << " OS << \" \\\"\" << SA->get" << getUpperName() 288249423Sdim << "() << \"\\\"\";\n"; 289249423Sdim } 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 } 351234353Sdim void writeTemplateInstantiationArgs(raw_ostream &OS) const { 352234353Sdim // FIXME: move the definition in Sema::InstantiateAttrs to here. 353234353Sdim // In the meantime, aligned attributes are cloned. 354234353Sdim } 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 } 367263508Sdim void writeCtorDefaultInitializers(raw_ostream &OS) const { 368263508Sdim OS << "is" << getLowerName() << "Expr(false)"; 369263508Sdim } 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 } 400234353Sdim void writeValue(raw_ostream &OS) const { 401239462Sdim OS << "\";\n" 402239462Sdim << " " << getLowerName() << "Expr->printPretty(OS, 0, Policy);\n" 403239462Sdim << " OS << \""; 404234353Sdim } 405249423Sdim void writeDump(raw_ostream &OS) const { 406249423Sdim } 407249423Sdim void writeDumpChildren(raw_ostream &OS) const { 408249423Sdim OS << " if (SA->is" << getUpperName() << "Expr()) {\n"; 409249423Sdim OS << " lastChild();\n"; 410249423Sdim OS << " dumpStmt(SA->get" << getUpperName() << "Expr());\n"; 411249423Sdim OS << " } else\n"; 412249423Sdim OS << " dumpType(SA->get" << getUpperName() 413249423Sdim << "Type()->getType());\n"; 414249423Sdim } 415249423Sdim void writeHasChildren(raw_ostream &OS) const { 416249423Sdim OS << "SA->is" << getUpperName() << "Expr()"; 417249423Sdim } 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" 442234353Sdim << " return " << getLowerName() << "Size;\n"; 443226586Sdim OS << " }"; 444226586Sdim } 445226586Sdim void writeCloneArgs(raw_ostream &OS) const { 446226586Sdim OS << getLowerName() << ", " << getLowerName() << "Size"; 447226586Sdim } 448234353Sdim void writeTemplateInstantiationArgs(raw_ostream &OS) const { 449234353Sdim // This isn't elegant, but we have to go through public methods... 450234353Sdim OS << "A->" << getLowerName() << "_begin(), " 451234353Sdim << "A->" << getLowerName() << "_size()"; 452234353Sdim } 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 } 463263508Sdim void writeCtorDefaultInitializers(raw_ostream &OS) const { 464263508Sdim OS << getLowerName() << "Size(0), " << getLowerName() << "(0)"; 465263508Sdim } 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"; 476249423Sdim OS << " SmallVector<" << type << ", 4> " << getLowerName() 477226586Sdim << ";\n"; 478226586Sdim OS << " " << getLowerName() << ".reserve(" << getLowerName() 479226586Sdim << "Size);\n"; 480263508Sdim 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 } 495234353Sdim void writeValue(raw_ostream &OS) const { 496234353Sdim OS << "\";\n"; 497234353Sdim OS << " bool isFirst = true;\n" 498234353Sdim << " for (" << getAttrName() << "Attr::" << getLowerName() 499234353Sdim << "_iterator i = " << getLowerName() << "_begin(), e = " 500234353Sdim << getLowerName() << "_end(); i != e; ++i) {\n" 501234353Sdim << " if (isFirst) isFirst = false;\n" 502234353Sdim << " else OS << \", \";\n" 503234353Sdim << " OS << *i;\n" 504234353Sdim << " }\n"; 505234353Sdim OS << " OS << \""; 506234353Sdim } 507249423Sdim void writeDump(raw_ostream &OS) const { 508249423Sdim OS << " for (" << getAttrName() << "Attr::" << getLowerName() 509249423Sdim << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->" 510249423Sdim << getLowerName() << "_end(); I != E; ++I)\n"; 511249423Sdim OS << " OS << \" \" << *I;\n"; 512249423Sdim } 513226586Sdim }; 514226586Sdim 515226586Sdim class EnumArgument : public Argument { 516226586Sdim std::string type; 517249423Sdim 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")), 522249423Sdim enums(getValueAsListOfStrings(Arg, "Enums")), 523249423Sdim uniques(enums) 524249423Sdim { 525249423Sdim // Calculate the various enum values 526249423Sdim std::sort(uniques.begin(), uniques.end()); 527249423Sdim uniques.erase(std::unique(uniques.begin(), uniques.end()), uniques.end()); 528249423Sdim // FIXME: Emit a proper error 529249423Sdim assert(!uniques.empty()); 530249423Sdim } 531226586Sdim 532263508Sdim bool isEnumArg() const { return true; } 533263508Sdim 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 } 542234353Sdim void writeTemplateInstantiationArgs(raw_ostream &OS) const { 543234353Sdim OS << "A->get" << getUpperName() << "()"; 544234353Sdim } 545226586Sdim void writeCtorInitializers(raw_ostream &OS) const { 546226586Sdim OS << getLowerName() << "(" << getUpperName() << ")"; 547226586Sdim } 548263508Sdim void writeCtorDefaultInitializers(raw_ostream &OS) const { 549263508Sdim OS << getLowerName() << "(" << type << "(0))"; 550263508Sdim } 551226586Sdim void writeCtorParameters(raw_ostream &OS) const { 552226586Sdim OS << type << " " << getUpperName(); 553226586Sdim } 554226586Sdim void writeDeclarations(raw_ostream &OS) const { 555249423Sdim std::vector<StringRef>::const_iterator i = uniques.begin(), 556249423Sdim 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 } 580234353Sdim void writeValue(raw_ostream &OS) const { 581234353Sdim OS << "\" << get" << getUpperName() << "() << \""; 582234353Sdim } 583249423Sdim void writeDump(raw_ostream &OS) const { 584249423Sdim OS << " switch(SA->get" << getUpperName() << "()) {\n"; 585249423Sdim for (std::vector<StringRef>::const_iterator I = uniques.begin(), 586249423Sdim E = uniques.end(); I != E; ++I) { 587249423Sdim OS << " case " << getAttrName() << "Attr::" << *I << ":\n"; 588249423Sdim OS << " OS << \" " << *I << "\";\n"; 589249423Sdim OS << " break;\n"; 590249423Sdim } 591249423Sdim OS << " }\n"; 592249423Sdim } 593263508Sdim 594263508Sdim void writeConversion(raw_ostream &OS) const { 595263508Sdim OS << " static bool ConvertStrTo" << type << "(StringRef Val, "; 596263508Sdim OS << type << " &Out) {\n"; 597263508Sdim OS << " Optional<" << type << "> R = llvm::StringSwitch<Optional<"; 598263508Sdim OS << type << "> >(Val)\n"; 599263508Sdim for (size_t I = 0; I < enums.size(); ++I) { 600263508Sdim OS << " .Case(\"" << values[I] << "\", "; 601263508Sdim OS << getAttrName() << "Attr::" << enums[I] << ")\n"; 602263508Sdim } 603263508Sdim OS << " .Default(Optional<" << type << ">());\n"; 604263508Sdim OS << " if (R) {\n"; 605263508Sdim OS << " Out = *R;\n return true;\n }\n"; 606263508Sdim OS << " return false;\n"; 607263508Sdim OS << " }\n"; 608263508Sdim } 609226586Sdim }; 610263508Sdim 611263508Sdim class VariadicEnumArgument: public VariadicArgument { 612263508Sdim std::string type, QualifiedTypeName; 613263508Sdim std::vector<StringRef> values, enums, uniques; 614263508Sdim public: 615263508Sdim VariadicEnumArgument(Record &Arg, StringRef Attr) 616263508Sdim : VariadicArgument(Arg, Attr, Arg.getValueAsString("Type")), 617263508Sdim type(Arg.getValueAsString("Type")), 618263508Sdim values(getValueAsListOfStrings(Arg, "Values")), 619263508Sdim enums(getValueAsListOfStrings(Arg, "Enums")), 620263508Sdim uniques(enums) 621263508Sdim { 622263508Sdim // Calculate the various enum values 623263508Sdim std::sort(uniques.begin(), uniques.end()); 624263508Sdim uniques.erase(std::unique(uniques.begin(), uniques.end()), uniques.end()); 625263508Sdim 626263508Sdim QualifiedTypeName = getAttrName().str() + "Attr::" + type; 627263508Sdim 628263508Sdim // FIXME: Emit a proper error 629263508Sdim assert(!uniques.empty()); 630263508Sdim } 631226586Sdim 632263508Sdim bool isVariadicEnumArg() const { return true; } 633263508Sdim 634263508Sdim void writeDeclarations(raw_ostream &OS) const { 635263508Sdim std::vector<StringRef>::const_iterator i = uniques.begin(), 636263508Sdim e = uniques.end(); 637263508Sdim // The last one needs to not have a comma. 638263508Sdim --e; 639263508Sdim 640263508Sdim OS << "public:\n"; 641263508Sdim OS << " enum " << type << " {\n"; 642263508Sdim for (; i != e; ++i) 643263508Sdim OS << " " << *i << ",\n"; 644263508Sdim OS << " " << *e << "\n"; 645263508Sdim OS << " };\n"; 646263508Sdim OS << "private:\n"; 647263508Sdim 648263508Sdim VariadicArgument::writeDeclarations(OS); 649263508Sdim } 650263508Sdim void writeDump(raw_ostream &OS) const { 651263508Sdim OS << " for (" << getAttrName() << "Attr::" << getLowerName() 652263508Sdim << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->" 653263508Sdim << getLowerName() << "_end(); I != E; ++I) {\n"; 654263508Sdim OS << " switch(*I) {\n"; 655263508Sdim for (std::vector<StringRef>::const_iterator UI = uniques.begin(), 656263508Sdim UE = uniques.end(); UI != UE; ++UI) { 657263508Sdim OS << " case " << getAttrName() << "Attr::" << *UI << ":\n"; 658263508Sdim OS << " OS << \" " << *UI << "\";\n"; 659263508Sdim OS << " break;\n"; 660263508Sdim } 661263508Sdim OS << " }\n"; 662263508Sdim OS << " }\n"; 663263508Sdim } 664263508Sdim void writePCHReadDecls(raw_ostream &OS) const { 665263508Sdim OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n"; 666263508Sdim OS << " SmallVector<" << QualifiedTypeName << ", 4> " << getLowerName() 667263508Sdim << ";\n"; 668263508Sdim OS << " " << getLowerName() << ".reserve(" << getLowerName() 669263508Sdim << "Size);\n"; 670263508Sdim OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n"; 671263508Sdim OS << " " << getLowerName() << ".push_back(" << "static_cast<" 672263508Sdim << QualifiedTypeName << ">(Record[Idx++]));\n"; 673263508Sdim } 674263508Sdim void writePCHWrite(raw_ostream &OS) const{ 675263508Sdim OS << " Record.push_back(SA->" << getLowerName() << "_size());\n"; 676263508Sdim OS << " for (" << getAttrName() << "Attr::" << getLowerName() 677263508Sdim << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->" 678263508Sdim << getLowerName() << "_end(); i != e; ++i)\n"; 679263508Sdim OS << " " << WritePCHRecord(QualifiedTypeName, "(*i)"); 680263508Sdim } 681263508Sdim void writeConversion(raw_ostream &OS) const { 682263508Sdim OS << " static bool ConvertStrTo" << type << "(StringRef Val, "; 683263508Sdim OS << type << " &Out) {\n"; 684263508Sdim OS << " Optional<" << type << "> R = llvm::StringSwitch<Optional<"; 685263508Sdim OS << type << "> >(Val)\n"; 686263508Sdim for (size_t I = 0; I < enums.size(); ++I) { 687263508Sdim OS << " .Case(\"" << values[I] << "\", "; 688263508Sdim OS << getAttrName() << "Attr::" << enums[I] << ")\n"; 689263508Sdim } 690263508Sdim OS << " .Default(Optional<" << type << ">());\n"; 691263508Sdim OS << " if (R) {\n"; 692263508Sdim OS << " Out = *R;\n return true;\n }\n"; 693263508Sdim OS << " return false;\n"; 694263508Sdim OS << " }\n"; 695263508Sdim } 696263508Sdim }; 697263508Sdim 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 } 716234353Sdim void writeTemplateInstantiationArgs(raw_ostream &OS) const { 717234353Sdim OS << "A->get" << getUpperName() << "()"; 718234353Sdim } 719226586Sdim void writeCtorBody(raw_ostream &OS) const { 720226586Sdim } 721226586Sdim void writeCtorInitializers(raw_ostream &OS) const { 722226586Sdim OS << getLowerName() << "(" << getUpperName() << ")"; 723226586Sdim } 724263508Sdim void writeCtorDefaultInitializers(raw_ostream &OS) const { 725263508Sdim OS << getLowerName() << "()"; 726263508Sdim } 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 } 743234353Sdim void writeValue(raw_ostream &OS) const { 744234353Sdim OS << getLowerName() << "=\" << get" << getUpperName() << "() << \""; 745234353Sdim } 746249423Sdim void writeDump(raw_ostream &OS) const { 747249423Sdim OS << " OS << \" \" << SA->get" << getUpperName() << "();\n"; 748249423Sdim } 749226586Sdim }; 750234353Sdim 751234353Sdim class ExprArgument : public SimpleArgument { 752234353Sdim public: 753234353Sdim ExprArgument(Record &Arg, StringRef Attr) 754234353Sdim : SimpleArgument(Arg, Attr, "Expr *") 755234353Sdim {} 756234353Sdim 757234353Sdim void writeTemplateInstantiationArgs(raw_ostream &OS) const { 758234353Sdim OS << "tempInst" << getUpperName(); 759234353Sdim } 760234353Sdim 761234353Sdim void writeTemplateInstantiation(raw_ostream &OS) const { 762234353Sdim OS << " " << getType() << " tempInst" << getUpperName() << ";\n"; 763234353Sdim OS << " {\n"; 764234353Sdim OS << " EnterExpressionEvaluationContext " 765234353Sdim << "Unevaluated(S, Sema::Unevaluated);\n"; 766234353Sdim OS << " ExprResult " << "Result = S.SubstExpr(" 767234353Sdim << "A->get" << getUpperName() << "(), TemplateArgs);\n"; 768234353Sdim OS << " tempInst" << getUpperName() << " = " 769234353Sdim << "Result.takeAs<Expr>();\n"; 770234353Sdim OS << " }\n"; 771234353Sdim } 772249423Sdim 773249423Sdim void writeDump(raw_ostream &OS) const { 774249423Sdim } 775249423Sdim 776249423Sdim void writeDumpChildren(raw_ostream &OS) const { 777249423Sdim OS << " lastChild();\n"; 778249423Sdim OS << " dumpStmt(SA->get" << getUpperName() << "());\n"; 779249423Sdim } 780249423Sdim void writeHasChildren(raw_ostream &OS) const { OS << "true"; } 781234353Sdim }; 782234353Sdim 783234353Sdim class VariadicExprArgument : public VariadicArgument { 784234353Sdim public: 785234353Sdim VariadicExprArgument(Record &Arg, StringRef Attr) 786234353Sdim : VariadicArgument(Arg, Attr, "Expr *") 787234353Sdim {} 788234353Sdim 789234353Sdim void writeTemplateInstantiationArgs(raw_ostream &OS) const { 790234353Sdim OS << "tempInst" << getUpperName() << ", " 791234353Sdim << "A->" << getLowerName() << "_size()"; 792234353Sdim } 793234353Sdim 794234353Sdim void writeTemplateInstantiation(raw_ostream &OS) const { 795234353Sdim OS << " " << getType() << " *tempInst" << getUpperName() 796234353Sdim << " = new (C, 16) " << getType() 797234353Sdim << "[A->" << getLowerName() << "_size()];\n"; 798234353Sdim OS << " {\n"; 799234353Sdim OS << " EnterExpressionEvaluationContext " 800234353Sdim << "Unevaluated(S, Sema::Unevaluated);\n"; 801234353Sdim OS << " " << getType() << " *TI = tempInst" << getUpperName() 802234353Sdim << ";\n"; 803234353Sdim OS << " " << getType() << " *I = A->" << getLowerName() 804234353Sdim << "_begin();\n"; 805234353Sdim OS << " " << getType() << " *E = A->" << getLowerName() 806234353Sdim << "_end();\n"; 807234353Sdim OS << " for (; I != E; ++I, ++TI) {\n"; 808234353Sdim OS << " ExprResult Result = S.SubstExpr(*I, TemplateArgs);\n"; 809234353Sdim OS << " *TI = Result.takeAs<Expr>();\n"; 810234353Sdim OS << " }\n"; 811234353Sdim OS << " }\n"; 812234353Sdim } 813249423Sdim 814249423Sdim void writeDump(raw_ostream &OS) const { 815249423Sdim } 816249423Sdim 817249423Sdim void writeDumpChildren(raw_ostream &OS) const { 818249423Sdim OS << " for (" << getAttrName() << "Attr::" << getLowerName() 819249423Sdim << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->" 820249423Sdim << getLowerName() << "_end(); I != E; ++I) {\n"; 821249423Sdim OS << " if (I + 1 == E)\n"; 822249423Sdim OS << " lastChild();\n"; 823249423Sdim OS << " dumpStmt(*I);\n"; 824249423Sdim OS << " }\n"; 825249423Sdim } 826249423Sdim 827249423Sdim void writeHasChildren(raw_ostream &OS) const { 828249423Sdim OS << "SA->" << getLowerName() << "_begin() != " 829249423Sdim << "SA->" << getLowerName() << "_end()"; 830249423Sdim } 831234353Sdim }; 832263508Sdim 833263508Sdim class TypeArgument : public SimpleArgument { 834263508Sdim public: 835263508Sdim TypeArgument(Record &Arg, StringRef Attr) 836263508Sdim : SimpleArgument(Arg, Attr, "TypeSourceInfo *") 837263508Sdim {} 838263508Sdim 839263508Sdim void writeAccessors(raw_ostream &OS) const { 840263508Sdim OS << " QualType get" << getUpperName() << "() const {\n"; 841263508Sdim OS << " return " << getLowerName() << "->getType();\n"; 842263508Sdim OS << " }"; 843263508Sdim OS << " " << getType() << " get" << getUpperName() << "Loc() const {\n"; 844263508Sdim OS << " return " << getLowerName() << ";\n"; 845263508Sdim OS << " }"; 846263508Sdim } 847263508Sdim void writeTemplateInstantiationArgs(raw_ostream &OS) const { 848263508Sdim OS << "A->get" << getUpperName() << "Loc()"; 849263508Sdim } 850263508Sdim void writePCHWrite(raw_ostream &OS) const { 851263508Sdim OS << " " << WritePCHRecord( 852263508Sdim getType(), "SA->get" + std::string(getUpperName()) + "Loc()"); 853263508Sdim } 854263508Sdim }; 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); 867234353Sdim 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); 876263508Sdim 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"); 883263508Sdim else if (ArgName == "VariadicEnumArgument") 884263508Sdim Ptr = new VariadicEnumArgument(Arg, Attr); 885226586Sdim else if (ArgName == "VariadicExprArgument") 886234353Sdim 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 } 899263508Sdim 900263508Sdim if (Ptr && Arg.getValueAsBit("Optional")) 901263508Sdim Ptr->setOptional(true); 902263508Sdim 903226586Sdim return Ptr; 904226586Sdim} 905226586Sdim 906234353Sdimstatic void writeAvailabilityValue(raw_ostream &OS) { 907234353Sdim OS << "\" << getPlatform()->getName();\n" 908234353Sdim << " if (!getIntroduced().empty()) OS << \", introduced=\" << getIntroduced();\n" 909234353Sdim << " if (!getDeprecated().empty()) OS << \", deprecated=\" << getDeprecated();\n" 910234353Sdim << " if (!getObsoleted().empty()) OS << \", obsoleted=\" << getObsoleted();\n" 911234353Sdim << " if (getUnavailable()) OS << \", unavailable\";\n" 912234353Sdim << " OS << \""; 913234353Sdim} 914234353Sdim 915249423Sdimstatic void writePrettyPrintFunction(Record &R, std::vector<Argument*> &Args, 916249423Sdim raw_ostream &OS) { 917249423Sdim std::vector<Record*> Spellings = R.getValueAsListOfDefs("Spellings"); 918249423Sdim 919249423Sdim OS << "void " << R.getName() << "Attr::printPretty(" 920249423Sdim << "raw_ostream &OS, const PrintingPolicy &Policy) const {\n"; 921249423Sdim 922249423Sdim if (Spellings.size() == 0) { 923249423Sdim OS << "}\n\n"; 924249423Sdim return; 925249423Sdim } 926249423Sdim 927249423Sdim OS << 928249423Sdim " switch (SpellingListIndex) {\n" 929249423Sdim " default:\n" 930249423Sdim " llvm_unreachable(\"Unknown attribute spelling!\");\n" 931249423Sdim " break;\n"; 932249423Sdim 933249423Sdim for (unsigned I = 0; I < Spellings.size(); ++ I) { 934249423Sdim llvm::SmallString<16> Prefix; 935249423Sdim llvm::SmallString<8> Suffix; 936249423Sdim // The actual spelling of the name and namespace (if applicable) 937249423Sdim // of an attribute without considering prefix and suffix. 938249423Sdim llvm::SmallString<64> Spelling; 939249423Sdim std::string Name = Spellings[I]->getValueAsString("Name"); 940249423Sdim std::string Variety = Spellings[I]->getValueAsString("Variety"); 941249423Sdim 942249423Sdim if (Variety == "GNU") { 943249423Sdim Prefix = " __attribute__(("; 944249423Sdim Suffix = "))"; 945249423Sdim } else if (Variety == "CXX11") { 946249423Sdim Prefix = " [["; 947249423Sdim Suffix = "]]"; 948249423Sdim std::string Namespace = Spellings[I]->getValueAsString("Namespace"); 949249423Sdim if (Namespace != "") { 950249423Sdim Spelling += Namespace; 951249423Sdim Spelling += "::"; 952249423Sdim } 953249423Sdim } else if (Variety == "Declspec") { 954249423Sdim Prefix = " __declspec("; 955249423Sdim Suffix = ")"; 956249423Sdim } else if (Variety == "Keyword") { 957249423Sdim Prefix = " "; 958249423Sdim Suffix = ""; 959249423Sdim } else { 960249423Sdim llvm_unreachable("Unknown attribute syntax variety!"); 961249423Sdim } 962249423Sdim 963249423Sdim Spelling += Name; 964249423Sdim 965249423Sdim OS << 966249423Sdim " case " << I << " : {\n" 967249423Sdim " OS << \"" + Prefix.str() + Spelling.str(); 968249423Sdim 969249423Sdim if (Args.size()) OS << "("; 970249423Sdim if (Spelling == "availability") { 971249423Sdim writeAvailabilityValue(OS); 972249423Sdim } else { 973249423Sdim for (std::vector<Argument*>::const_iterator I = Args.begin(), 974249423Sdim E = Args.end(); I != E; ++ I) { 975249423Sdim if (I != Args.begin()) OS << ", "; 976249423Sdim (*I)->writeValue(OS); 977249423Sdim } 978249423Sdim } 979249423Sdim 980249423Sdim if (Args.size()) OS << ")"; 981249423Sdim OS << Suffix.str() + "\";\n"; 982249423Sdim 983249423Sdim OS << 984249423Sdim " break;\n" 985249423Sdim " }\n"; 986249423Sdim } 987249423Sdim 988249423Sdim // End of the switch statement. 989249423Sdim OS << "}\n"; 990249423Sdim // End of the print function. 991249423Sdim OS << "}\n\n"; 992249423Sdim} 993249423Sdim 994249423Sdim/// \brief Return the index of a spelling in a spelling list. 995249423Sdimstatic unsigned getSpellingListIndex(const std::vector<Record*> &SpellingList, 996249423Sdim const Record &Spelling) { 997249423Sdim assert(SpellingList.size() && "Spelling list is empty!"); 998249423Sdim 999249423Sdim for (unsigned Index = 0; Index < SpellingList.size(); ++Index) { 1000249423Sdim Record *S = SpellingList[Index]; 1001249423Sdim if (S->getValueAsString("Variety") != Spelling.getValueAsString("Variety")) 1002249423Sdim continue; 1003249423Sdim if (S->getValueAsString("Variety") == "CXX11" && 1004249423Sdim S->getValueAsString("Namespace") != 1005249423Sdim Spelling.getValueAsString("Namespace")) 1006249423Sdim continue; 1007249423Sdim if (S->getValueAsString("Name") != Spelling.getValueAsString("Name")) 1008249423Sdim continue; 1009249423Sdim 1010249423Sdim return Index; 1011249423Sdim } 1012249423Sdim 1013249423Sdim llvm_unreachable("Unknown spelling!"); 1014249423Sdim} 1015249423Sdim 1016249423Sdimstatic void writeAttrAccessorDefinition(Record &R, raw_ostream &OS) { 1017249423Sdim std::vector<Record*> Accessors = R.getValueAsListOfDefs("Accessors"); 1018249423Sdim for (std::vector<Record*>::const_iterator I = Accessors.begin(), 1019249423Sdim E = Accessors.end(); I != E; ++I) { 1020249423Sdim Record *Accessor = *I; 1021249423Sdim std::string Name = Accessor->getValueAsString("Name"); 1022249423Sdim std::vector<Record*> Spellings = Accessor->getValueAsListOfDefs( 1023249423Sdim "Spellings"); 1024249423Sdim std::vector<Record*> SpellingList = R.getValueAsListOfDefs("Spellings"); 1025249423Sdim assert(SpellingList.size() && 1026249423Sdim "Attribute with empty spelling list can't have accessors!"); 1027249423Sdim 1028249423Sdim OS << " bool " << Name << "() const { return SpellingListIndex == "; 1029249423Sdim for (unsigned Index = 0; Index < Spellings.size(); ++Index) { 1030249423Sdim OS << getSpellingListIndex(SpellingList, *Spellings[Index]); 1031249423Sdim if (Index != Spellings.size() -1) 1032249423Sdim OS << " ||\n SpellingListIndex == "; 1033249423Sdim else 1034249423Sdim OS << "; }\n"; 1035249423Sdim } 1036249423Sdim } 1037249423Sdim} 1038249423Sdim 1039239462Sdimnamespace clang { 1040239462Sdim 1041239462Sdim// Emits the class definitions for attributes. 1042239462Sdimvoid EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) { 1043249423Sdim emitSourceFileHeader("Attribute classes' definitions", OS); 1044249423Sdim 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; 1053239462Sdim 1054239462Sdim if (!R.getValueAsBit("ASTNode")) 1055239462Sdim continue; 1056239462Sdim 1057263508Sdim const std::vector<Record *> Supers = R.getSuperClasses(); 1058263508Sdim assert(!Supers.empty() && "Forgot to specify a superclass for the attr"); 1059263508Sdim std::string SuperName; 1060263508Sdim for (std::vector<Record *>::const_reverse_iterator I = Supers.rbegin(), 1061263508Sdim E = Supers.rend(); I != E; ++I) { 1062263508Sdim const Record &R = **I; 1063263508Sdim if (R.getName() != "TargetSpecificAttr" && SuperName.empty()) 1064263508Sdim SuperName = R.getName(); 1065263508Sdim } 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 1091263508Sdim bool HasOpt = false; 1092226586Sdim for (ai = Args.begin(); ai != ae; ++ai) { 1093226586Sdim OS << " , "; 1094226586Sdim (*ai)->writeCtorParameters(OS); 1095226586Sdim OS << "\n"; 1096263508Sdim if ((*ai)->isOptional()) 1097263508Sdim HasOpt = true; 1098226586Sdim } 1099249423Sdim 1100249423Sdim OS << " , "; 1101249423Sdim OS << "unsigned SI = 0\n"; 1102249423Sdim 1103226586Sdim OS << " )\n"; 1104249423Sdim 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 1120263508Sdim // If there are optional arguments, write out a constructor that elides the 1121263508Sdim // optional arguments as well. 1122263508Sdim if (HasOpt) { 1123263508Sdim OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n"; 1124263508Sdim for (ai = Args.begin(); ai != ae; ++ai) { 1125263508Sdim if (!(*ai)->isOptional()) { 1126263508Sdim OS << " , "; 1127263508Sdim (*ai)->writeCtorParameters(OS); 1128263508Sdim OS << "\n"; 1129263508Sdim } 1130263508Sdim } 1131263508Sdim 1132263508Sdim OS << " , "; 1133263508Sdim OS << "unsigned SI = 0\n"; 1134263508Sdim 1135263508Sdim OS << " )\n"; 1136263508Sdim OS << " : " << SuperName << "(attr::" << R.getName() << ", R, SI)\n"; 1137263508Sdim 1138263508Sdim for (ai = Args.begin(); ai != ae; ++ai) { 1139263508Sdim OS << " , "; 1140263508Sdim (*ai)->writeCtorDefaultInitializers(OS); 1141263508Sdim OS << "\n"; 1142263508Sdim } 1143263508Sdim 1144263508Sdim OS << " {\n"; 1145263508Sdim 1146263508Sdim for (ai = Args.begin(); ai != ae; ++ai) { 1147263508Sdim if (!(*ai)->isOptional()) { 1148263508Sdim (*ai)->writeCtorBody(OS); 1149263508Sdim OS << "\n"; 1150263508Sdim } 1151263508Sdim } 1152263508Sdim OS << " }\n\n"; 1153263508Sdim } 1154263508Sdim 1155226586Sdim OS << " virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n"; 1156249423Sdim OS << " virtual void printPretty(raw_ostream &OS,\n" 1157239462Sdim << " const PrintingPolicy &Policy) const;\n"; 1158226586Sdim 1159249423Sdim writeAttrAccessorDefinition(R, OS); 1160249423Sdim 1161226586Sdim for (ai = Args.begin(); ai != ae; ++ai) { 1162226586Sdim (*ai)->writeAccessors(OS); 1163226586Sdim OS << "\n\n"; 1164263508Sdim 1165263508Sdim if ((*ai)->isEnumArg()) { 1166263508Sdim EnumArgument *EA = (EnumArgument *)*ai; 1167263508Sdim EA->writeConversion(OS); 1168263508Sdim } else if ((*ai)->isVariadicEnumArg()) { 1169263508Sdim VariadicEnumArgument *VEA = (VariadicEnumArgument *)*ai; 1170263508Sdim VEA->writeConversion(OS); 1171263508Sdim } 1172226586Sdim } 1173226586Sdim 1174234353Sdim 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"; 1179234353Sdim 1180234353Sdim bool LateParsed = R.getValueAsBit("LateParsed"); 1181234353Sdim OS << " virtual bool isLateParsed() const { return " 1182234353Sdim << LateParsed << "; }\n"; 1183234353Sdim 1184226586Sdim OS << "};\n\n"; 1185226586Sdim } 1186226586Sdim 1187226586Sdim OS << "#endif\n"; 1188226586Sdim} 1189226586Sdim 1190263508Sdimstatic bool isIdentifierArgument(Record *Arg) { 1191263508Sdim return !Arg->getSuperClasses().empty() && 1192263508Sdim llvm::StringSwitch<bool>(Arg->getSuperClasses().back()->getName()) 1193263508Sdim .Case("IdentifierArgument", true) 1194263508Sdim .Case("EnumArgument", true) 1195263508Sdim .Default(false); 1196263508Sdim} 1197263508Sdim 1198263508Sdim/// \brief Emits the first-argument-is-type property for attributes. 1199263508Sdimvoid EmitClangAttrTypeArgList(RecordKeeper &Records, raw_ostream &OS) { 1200263508Sdim emitSourceFileHeader("llvm::StringSwitch code to match attributes with a " 1201263508Sdim "type argument", OS); 1202263508Sdim 1203263508Sdim std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"); 1204263508Sdim 1205263508Sdim for (std::vector<Record *>::iterator I = Attrs.begin(), E = Attrs.end(); 1206263508Sdim I != E; ++I) { 1207263508Sdim Record &Attr = **I; 1208263508Sdim 1209263508Sdim // Determine whether the first argument is a type. 1210263508Sdim std::vector<Record *> Args = Attr.getValueAsListOfDefs("Args"); 1211263508Sdim if (Args.empty()) 1212263508Sdim continue; 1213263508Sdim 1214263508Sdim if (Args[0]->getSuperClasses().back()->getName() != "TypeArgument") 1215263508Sdim continue; 1216263508Sdim 1217263508Sdim // All these spellings take a single type argument. 1218263508Sdim std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); 1219263508Sdim std::set<std::string> Emitted; 1220263508Sdim for (std::vector<Record*>::const_iterator I = Spellings.begin(), 1221263508Sdim E = Spellings.end(); I != E; ++I) { 1222263508Sdim if (Emitted.insert((*I)->getValueAsString("Name")).second) 1223263508Sdim OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", " 1224263508Sdim << "true" << ")\n"; 1225263508Sdim } 1226263508Sdim } 1227263508Sdim} 1228263508Sdim 1229263508Sdim// Emits the first-argument-is-identifier property for attributes. 1230263508Sdimvoid EmitClangAttrIdentifierArgList(RecordKeeper &Records, raw_ostream &OS) { 1231251662Sdim emitSourceFileHeader("llvm::StringSwitch code to match attributes with " 1232263508Sdim "an identifier argument", OS); 1233251662Sdim 1234251662Sdim std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 1235251662Sdim 1236251662Sdim for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); 1237251662Sdim I != E; ++I) { 1238251662Sdim Record &Attr = **I; 1239251662Sdim 1240263508Sdim // Determine whether the first argument is an identifier. 1241251662Sdim std::vector<Record *> Args = Attr.getValueAsListOfDefs("Args"); 1242263508Sdim if (Args.empty() || !isIdentifierArgument(Args[0])) 1243251662Sdim continue; 1244251662Sdim 1245263508Sdim // All these spellings take an identifier argument. 1246251662Sdim std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); 1247263508Sdim std::set<std::string> Emitted; 1248251662Sdim for (std::vector<Record*>::const_iterator I = Spellings.begin(), 1249251662Sdim E = Spellings.end(); I != E; ++I) { 1250263508Sdim if (Emitted.insert((*I)->getValueAsString("Name")).second) 1251263508Sdim OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", " 1252263508Sdim << "true" << ")\n"; 1253251662Sdim } 1254251662Sdim } 1255251662Sdim} 1256251662Sdim 1257239462Sdim// Emits the class method definitions for attributes. 1258239462Sdimvoid EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) { 1259249423Sdim 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; 1267239462Sdim 1268239462Sdim if (!R.getValueAsBit("ASTNode")) 1269239462Sdim continue; 1270239462Sdim 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 } 1286249423Sdim OS << ", getSpellingListIndex());\n}\n\n"; 1287234353Sdim 1288249423Sdim writePrettyPrintFunction(R, Args, OS); 1289226586Sdim } 1290226586Sdim} 1291226586Sdim 1292239462Sdim} // end namespace clang 1293239462Sdim 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. 1300239462Sdim for(--e; i != e; ++i) { 1301239462Sdim if (!(*i)->getValueAsBit("ASTNode")) 1302239462Sdim continue; 1303239462Sdim 1304226586Sdim OS << Class << "(" << (*i)->getName() << ")\n"; 1305239462Sdim } 1306226586Sdim 1307226586Sdim OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n"; 1308226586Sdim } 1309226586Sdim} 1310226586Sdim 1311239462Sdimnamespace clang { 1312239462Sdim 1313239462Sdim// Emits the enumeration list for attributes. 1314239462Sdimvoid EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) { 1315249423Sdim 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 1338263508Sdim OS << "#ifndef MS_INHERITANCE_ATTR\n"; 1339263508Sdim OS << "#define MS_INHERITANCE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n"; 1340249423Sdim OS << "#endif\n\n"; 1341249423Sdim 1342263508Sdim OS << "#ifndef LAST_MS_INHERITANCE_ATTR\n"; 1343263508Sdim OS << "#define LAST_MS_INHERITANCE_ATTR(NAME)" 1344263508Sdim " MS_INHERITANCE_ATTR(NAME)\n"; 1345249423Sdim OS << "#endif\n\n"; 1346249423Sdim 1347226586Sdim Record *InhClass = Records.getClass("InheritableAttr"); 1348226586Sdim Record *InhParamClass = Records.getClass("InheritableParamAttr"); 1349249423Sdim Record *MSInheritanceClass = Records.getClass("MSInheritanceAttr"); 1350226586Sdim std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), 1351249423Sdim NonInhAttrs, InhAttrs, InhParamAttrs, MSInhAttrs; 1352226586Sdim for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(); 1353226586Sdim i != e; ++i) { 1354239462Sdim if (!(*i)->getValueAsBit("ASTNode")) 1355239462Sdim continue; 1356239462Sdim 1357226586Sdim if ((*i)->isSubClassOf(InhParamClass)) 1358226586Sdim InhParamAttrs.push_back(*i); 1359249423Sdim else if ((*i)->isSubClassOf(MSInheritanceClass)) 1360249423Sdim 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); 1368263508Sdim 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"; 1374263508Sdim OS << "#undef MS_INHERITANCE_ATTR\n"; 1375226586Sdim OS << "#undef LAST_INHERITABLE_ATTR\n"; 1376226586Sdim OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n"; 1377263508Sdim OS << "#undef LAST_MS_INHERITANCE_ATTR\n"; 1378226586Sdim OS << "#undef ATTR\n"; 1379226586Sdim} 1380226586Sdim 1381239462Sdim// Emits the code to read an attribute from a precompiled header. 1382239462Sdimvoid EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) { 1383249423Sdim 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; 1398239462Sdim if (!R.getValueAsBit("ASTNode")) 1399239462Sdim continue; 1400239462Sdim 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 1425239462Sdim// Emits the code to write an attribute to a precompiled header. 1426239462Sdimvoid EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) { 1427249423Sdim emitSourceFileHeader("Attribute serialization code", OS); 1428249423Sdim 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; 1439239462Sdim if (!R.getValueAsBit("ASTNode")) 1440239462Sdim 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 1456239462Sdim// Emits the list of spellings for attributes. 1457239462Sdimvoid EmitClangAttrSpellingList(RecordKeeper &Records, raw_ostream &OS) { 1458249423Sdim emitSourceFileHeader("llvm::StringSwitch code to match all known attributes", 1459249423Sdim 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 1466239462Sdim std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); 1467226586Sdim 1468239462Sdim for (std::vector<Record*>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) { 1469239462Sdim OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", true)\n"; 1470226586Sdim } 1471226586Sdim } 1472226586Sdim 1473226586Sdim} 1474226586Sdim 1475249423Sdimvoid EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) { 1476249423Sdim emitSourceFileHeader("Code to translate different attribute spellings " 1477249423Sdim "into internal identifiers", OS); 1478249423Sdim 1479249423Sdim OS << 1480249423Sdim " unsigned Index = 0;\n" 1481249423Sdim " switch (AttrKind) {\n" 1482249423Sdim " default:\n" 1483249423Sdim " llvm_unreachable(\"Unknown attribute kind!\");\n" 1484249423Sdim " break;\n"; 1485249423Sdim 1486249423Sdim std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 1487249423Sdim for (std::vector<Record*>::const_iterator I = Attrs.begin(), E = Attrs.end(); 1488249423Sdim I != E; ++I) { 1489249423Sdim Record &R = **I; 1490249423Sdim // We only care about attributes that participate in Sema checking, so 1491249423Sdim // skip those attributes that are not able to make their way to Sema. 1492249423Sdim if (!R.getValueAsBit("SemaHandler")) 1493249423Sdim continue; 1494249423Sdim 1495249423Sdim std::vector<Record*> Spellings = R.getValueAsListOfDefs("Spellings"); 1496249423Sdim // Each distinct spelling yields an attribute kind. 1497249423Sdim if (R.getValueAsBit("DistinctSpellings")) { 1498249423Sdim for (unsigned I = 0; I < Spellings.size(); ++ I) { 1499249423Sdim OS << 1500249423Sdim " case AT_" << Spellings[I]->getValueAsString("Name") << ": \n" 1501249423Sdim " Index = " << I << ";\n" 1502249423Sdim " break;\n"; 1503249423Sdim } 1504249423Sdim } else { 1505249423Sdim OS << " case AT_" << R.getName() << " : {\n"; 1506249423Sdim for (unsigned I = 0; I < Spellings.size(); ++ I) { 1507249423Sdim SmallString<16> Namespace; 1508249423Sdim if (Spellings[I]->getValueAsString("Variety") == "CXX11") 1509249423Sdim Namespace = Spellings[I]->getValueAsString("Namespace"); 1510249423Sdim else 1511249423Sdim Namespace = ""; 1512249423Sdim 1513249423Sdim OS << " if (Name == \"" 1514249423Sdim << Spellings[I]->getValueAsString("Name") << "\" && " 1515249423Sdim << "SyntaxUsed == " 1516249423Sdim << StringSwitch<unsigned>(Spellings[I]->getValueAsString("Variety")) 1517249423Sdim .Case("GNU", 0) 1518249423Sdim .Case("CXX11", 1) 1519249423Sdim .Case("Declspec", 2) 1520249423Sdim .Case("Keyword", 3) 1521249423Sdim .Default(0) 1522249423Sdim << " && Scope == \"" << Namespace << "\")\n" 1523249423Sdim << " return " << I << ";\n"; 1524249423Sdim } 1525249423Sdim 1526249423Sdim OS << " break;\n"; 1527249423Sdim OS << " }\n"; 1528249423Sdim } 1529249423Sdim } 1530249423Sdim 1531249423Sdim OS << " }\n"; 1532249423Sdim OS << " return Index;\n"; 1533249423Sdim} 1534249423Sdim 1535239462Sdim// Emits the LateParsed property for attributes. 1536239462Sdimvoid EmitClangAttrLateParsedList(RecordKeeper &Records, raw_ostream &OS) { 1537249423Sdim emitSourceFileHeader("llvm::StringSwitch code to match late parsed " 1538249423Sdim "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) { 1549239462Sdim std::vector<Record*> Spellings = 1550239462Sdim Attr.getValueAsListOfDefs("Spellings"); 1551226586Sdim 1552239462Sdim // FIXME: Handle non-GNU attributes 1553239462Sdim for (std::vector<Record*>::const_iterator I = Spellings.begin(), 1554226586Sdim E = Spellings.end(); I != E; ++I) { 1555239462Sdim if ((*I)->getValueAsString("Variety") != "GNU") 1556239462Sdim continue; 1557239462Sdim OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", " 1558239462Sdim << LateParsed << ")\n"; 1559226586Sdim } 1560226586Sdim } 1561226586Sdim } 1562226586Sdim} 1563234353Sdim 1564239462Sdim// Emits code to instantiate dependent attributes on templates. 1565239462Sdimvoid EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) { 1566249423Sdim emitSourceFileHeader("Template instantiation code for attributes", OS); 1567234353Sdim 1568234353Sdim std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 1569234353Sdim 1570234353Sdim OS << "namespace clang {\n" 1571234353Sdim << "namespace sema {\n\n" 1572234353Sdim << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, " 1573234353Sdim << "Sema &S,\n" 1574234353Sdim << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n" 1575234353Sdim << " switch (At->getKind()) {\n" 1576234353Sdim << " default:\n" 1577234353Sdim << " break;\n"; 1578234353Sdim 1579234353Sdim for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); 1580234353Sdim I != E; ++I) { 1581234353Sdim Record &R = **I; 1582239462Sdim if (!R.getValueAsBit("ASTNode")) 1583239462Sdim continue; 1584234353Sdim 1585234353Sdim OS << " case attr::" << R.getName() << ": {\n"; 1586239462Sdim bool ShouldClone = R.getValueAsBit("Clone"); 1587239462Sdim 1588239462Sdim if (!ShouldClone) { 1589239462Sdim OS << " return NULL;\n"; 1590239462Sdim OS << " }\n"; 1591239462Sdim continue; 1592239462Sdim } 1593239462Sdim 1594234353Sdim OS << " const " << R.getName() << "Attr *A = cast<" 1595234353Sdim << R.getName() << "Attr>(At);\n"; 1596234353Sdim bool TDependent = R.getValueAsBit("TemplateDependent"); 1597234353Sdim 1598234353Sdim if (!TDependent) { 1599234353Sdim OS << " return A->clone(C);\n"; 1600234353Sdim OS << " }\n"; 1601234353Sdim continue; 1602234353Sdim } 1603234353Sdim 1604234353Sdim std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args"); 1605234353Sdim std::vector<Argument*> Args; 1606234353Sdim std::vector<Argument*>::iterator ai, ae; 1607234353Sdim Args.reserve(ArgRecords.size()); 1608234353Sdim 1609234353Sdim for (std::vector<Record*>::iterator ri = ArgRecords.begin(), 1610234353Sdim re = ArgRecords.end(); 1611234353Sdim ri != re; ++ri) { 1612234353Sdim Record &ArgRecord = **ri; 1613234353Sdim Argument *Arg = createArgument(ArgRecord, R.getName()); 1614234353Sdim assert(Arg); 1615234353Sdim Args.push_back(Arg); 1616234353Sdim } 1617234353Sdim ae = Args.end(); 1618234353Sdim 1619234353Sdim for (ai = Args.begin(); ai != ae; ++ai) { 1620234353Sdim (*ai)->writeTemplateInstantiation(OS); 1621234353Sdim } 1622234353Sdim OS << " return new (C) " << R.getName() << "Attr(A->getLocation(), C"; 1623234353Sdim for (ai = Args.begin(); ai != ae; ++ai) { 1624234353Sdim OS << ", "; 1625234353Sdim (*ai)->writeTemplateInstantiationArgs(OS); 1626234353Sdim } 1627234353Sdim OS << ");\n }\n"; 1628234353Sdim } 1629234353Sdim OS << " } // end switch\n" 1630234353Sdim << " llvm_unreachable(\"Unknown attribute!\");\n" 1631234353Sdim << " return 0;\n" 1632234353Sdim << "}\n\n" 1633234353Sdim << "} // end namespace sema\n" 1634234353Sdim << "} // end namespace clang\n"; 1635234353Sdim} 1636234353Sdim 1637263508Sdimtypedef std::vector<std::pair<std::string, Record *> > ParsedAttrMap; 1638249423Sdim 1639263508Sdimstatic ParsedAttrMap getParsedAttrList(const RecordKeeper &Records) { 1640234353Sdim std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 1641263508Sdim ParsedAttrMap R; 1642234353Sdim for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); 1643234353Sdim I != E; ++I) { 1644234353Sdim Record &Attr = **I; 1645234353Sdim 1646234353Sdim bool SemaHandler = Attr.getValueAsBit("SemaHandler"); 1647239462Sdim bool DistinctSpellings = Attr.getValueAsBit("DistinctSpellings"); 1648239462Sdim 1649234353Sdim if (SemaHandler) { 1650239462Sdim if (DistinctSpellings) { 1651239462Sdim std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); 1652239462Sdim 1653239462Sdim for (std::vector<Record*>::const_iterator I = Spellings.begin(), 1654239462Sdim E = Spellings.end(); I != E; ++I) { 1655239462Sdim std::string AttrName = (*I)->getValueAsString("Name"); 1656234353Sdim 1657239462Sdim StringRef Spelling = NormalizeAttrName(AttrName); 1658263508Sdim R.push_back(std::make_pair(Spelling.str(), &Attr)); 1659239462Sdim } 1660239462Sdim } else { 1661239462Sdim StringRef AttrName = Attr.getName(); 1662234353Sdim AttrName = NormalizeAttrName(AttrName); 1663263508Sdim R.push_back(std::make_pair(AttrName.str(), *I)); 1664234353Sdim } 1665234353Sdim } 1666234353Sdim } 1667263508Sdim return R; 1668234353Sdim} 1669234353Sdim 1670263508Sdim// Emits the list of parsed attributes. 1671263508Sdimvoid EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) { 1672263508Sdim emitSourceFileHeader("List of all attributes that Clang recognizes", OS); 1673263508Sdim 1674263508Sdim OS << "#ifndef PARSED_ATTR\n"; 1675263508Sdim OS << "#define PARSED_ATTR(NAME) NAME\n"; 1676263508Sdim OS << "#endif\n\n"; 1677263508Sdim 1678263508Sdim ParsedAttrMap Names = getParsedAttrList(Records); 1679263508Sdim for (ParsedAttrMap::iterator I = Names.begin(), E = Names.end(); I != E; 1680263508Sdim ++I) { 1681263508Sdim OS << "PARSED_ATTR(" << I->first << ")\n"; 1682263508Sdim } 1683263508Sdim} 1684263508Sdim 1685263508Sdimstatic void emitArgInfo(const Record &R, raw_ostream &OS) { 1686263508Sdim // This function will count the number of arguments specified for the 1687263508Sdim // attribute and emit the number of required arguments followed by the 1688263508Sdim // number of optional arguments. 1689263508Sdim std::vector<Record *> Args = R.getValueAsListOfDefs("Args"); 1690263508Sdim unsigned ArgCount = 0, OptCount = 0; 1691263508Sdim for (std::vector<Record *>::const_iterator I = Args.begin(), E = Args.end(); 1692263508Sdim I != E; ++I) { 1693263508Sdim const Record &Arg = **I; 1694263508Sdim Arg.getValueAsBit("Optional") ? ++OptCount : ++ArgCount; 1695263508Sdim } 1696263508Sdim OS << ArgCount << ", " << OptCount; 1697263508Sdim} 1698263508Sdim 1699263508Sdim/// Emits the parsed attribute helpers 1700263508Sdimvoid EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) { 1701263508Sdim emitSourceFileHeader("Parsed attribute helpers", OS); 1702263508Sdim 1703263508Sdim ParsedAttrMap Attrs = getParsedAttrList(Records); 1704263508Sdim 1705263508Sdim OS << "static const ParsedAttrInfo AttrInfoMap[AttributeList::UnknownAttribute + 1] = {\n"; 1706263508Sdim for (ParsedAttrMap::iterator I = Attrs.begin(), E = Attrs.end(); I != E; 1707263508Sdim ++I) { 1708263508Sdim // We need to generate struct instances based off ParsedAttrInfo from 1709263508Sdim // AttributeList.cpp. 1710263508Sdim OS << " { "; 1711263508Sdim emitArgInfo(*I->second, OS); 1712263508Sdim OS << ", " << I->second->getValueAsBit("HasCustomParsing"); 1713263508Sdim OS << " }"; 1714263508Sdim 1715263508Sdim if (I + 1 != E) 1716263508Sdim OS << ","; 1717263508Sdim 1718263508Sdim OS << " // AT_" << I->first << "\n"; 1719263508Sdim } 1720263508Sdim OS << "};\n\n"; 1721263508Sdim} 1722263508Sdim 1723239462Sdim// Emits the kind list of parsed attributes 1724239462Sdimvoid EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) { 1725249423Sdim emitSourceFileHeader("Attribute name matcher", OS); 1726249423Sdim 1727234353Sdim std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 1728234353Sdim 1729239462Sdim std::vector<StringMatcher::StringPair> Matches; 1730234353Sdim for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); 1731234353Sdim I != E; ++I) { 1732234353Sdim Record &Attr = **I; 1733234353Sdim 1734234353Sdim bool SemaHandler = Attr.getValueAsBit("SemaHandler"); 1735239462Sdim bool Ignored = Attr.getValueAsBit("Ignored"); 1736239462Sdim bool DistinctSpellings = Attr.getValueAsBit("DistinctSpellings"); 1737239462Sdim if (SemaHandler || Ignored) { 1738239462Sdim std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); 1739234353Sdim 1740239462Sdim for (std::vector<Record*>::const_iterator I = Spellings.begin(), 1741234353Sdim E = Spellings.end(); I != E; ++I) { 1742239462Sdim std::string RawSpelling = (*I)->getValueAsString("Name"); 1743239462Sdim StringRef AttrName = NormalizeAttrName(DistinctSpellings 1744239462Sdim ? StringRef(RawSpelling) 1745239462Sdim : StringRef(Attr.getName())); 1746234353Sdim 1747239462Sdim SmallString<64> Spelling; 1748239462Sdim if ((*I)->getValueAsString("Variety") == "CXX11") { 1749239462Sdim Spelling += (*I)->getValueAsString("Namespace"); 1750239462Sdim Spelling += "::"; 1751239462Sdim } 1752239462Sdim Spelling += NormalizeAttrSpelling(RawSpelling); 1753239462Sdim 1754239462Sdim if (SemaHandler) 1755239462Sdim Matches.push_back( 1756239462Sdim StringMatcher::StringPair( 1757239462Sdim StringRef(Spelling), 1758239462Sdim "return AttributeList::AT_" + AttrName.str() + ";")); 1759239462Sdim else 1760239462Sdim Matches.push_back( 1761239462Sdim StringMatcher::StringPair( 1762239462Sdim StringRef(Spelling), 1763239462Sdim "return AttributeList::IgnoredAttribute;")); 1764234353Sdim } 1765234353Sdim } 1766234353Sdim } 1767239462Sdim 1768239462Sdim OS << "static AttributeList::Kind getAttrKind(StringRef Name) {\n"; 1769239462Sdim StringMatcher("Name", Matches, OS).Emit(); 1770239462Sdim OS << "return AttributeList::UnknownAttribute;\n" 1771239462Sdim << "}\n"; 1772234353Sdim} 1773234353Sdim 1774249423Sdim// Emits the code to dump an attribute. 1775249423Sdimvoid EmitClangAttrDump(RecordKeeper &Records, raw_ostream &OS) { 1776249423Sdim emitSourceFileHeader("Attribute dumper", OS); 1777249423Sdim 1778249423Sdim OS << 1779249423Sdim " switch (A->getKind()) {\n" 1780249423Sdim " default:\n" 1781249423Sdim " llvm_unreachable(\"Unknown attribute kind!\");\n" 1782249423Sdim " break;\n"; 1783249423Sdim std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args; 1784249423Sdim for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); 1785249423Sdim I != E; ++I) { 1786249423Sdim Record &R = **I; 1787249423Sdim if (!R.getValueAsBit("ASTNode")) 1788249423Sdim continue; 1789249423Sdim OS << " case attr::" << R.getName() << ": {\n"; 1790249423Sdim Args = R.getValueAsListOfDefs("Args"); 1791249423Sdim if (!Args.empty()) { 1792249423Sdim OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName() 1793249423Sdim << "Attr>(A);\n"; 1794249423Sdim for (std::vector<Record*>::iterator I = Args.begin(), E = Args.end(); 1795249423Sdim I != E; ++I) 1796249423Sdim createArgument(**I, R.getName())->writeDump(OS); 1797249423Sdim 1798249423Sdim // Code for detecting the last child. 1799249423Sdim OS << " bool OldMoreChildren = hasMoreChildren();\n"; 1800249423Sdim OS << " bool MoreChildren = OldMoreChildren;\n"; 1801249423Sdim 1802249423Sdim for (std::vector<Record*>::iterator I = Args.begin(), E = Args.end(); 1803249423Sdim I != E; ++I) { 1804249423Sdim // More code for detecting the last child. 1805249423Sdim OS << " MoreChildren = OldMoreChildren"; 1806249423Sdim for (std::vector<Record*>::iterator Next = I + 1; Next != E; ++Next) { 1807249423Sdim OS << " || "; 1808249423Sdim createArgument(**Next, R.getName())->writeHasChildren(OS); 1809249423Sdim } 1810249423Sdim OS << ";\n"; 1811249423Sdim OS << " setMoreChildren(MoreChildren);\n"; 1812249423Sdim 1813249423Sdim createArgument(**I, R.getName())->writeDumpChildren(OS); 1814249423Sdim } 1815249423Sdim 1816249423Sdim // Reset the last child. 1817249423Sdim OS << " setMoreChildren(OldMoreChildren);\n"; 1818249423Sdim } 1819249423Sdim OS << 1820249423Sdim " break;\n" 1821249423Sdim " }\n"; 1822249423Sdim } 1823249423Sdim OS << " }\n"; 1824249423Sdim} 1825249423Sdim 1826239462Sdim} // end namespace clang 1827