ClangAttrEmitter.cpp revision b43d87b0646aa04951056c7e0d1ab9a58eb09f66
1//===- ClangAttrEmitter.cpp - Generate Clang attribute handling =-*- C++ -*--=// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// These tablegen backends emit Clang attribute processing code 11// 12//===----------------------------------------------------------------------===// 13 14#include "llvm/ADT/SmallString.h" 15#include "llvm/ADT/StringSwitch.h" 16#include "llvm/TableGen/Record.h" 17#include "llvm/TableGen/StringMatcher.h" 18#include "llvm/TableGen/TableGenBackend.h" 19#include <algorithm> 20#include <cctype> 21 22using namespace llvm; 23 24static const std::vector<StringRef> 25getValueAsListOfStrings(Record &R, StringRef FieldName) { 26 ListInit *List = R.getValueAsListInit(FieldName); 27 assert (List && "Got a null ListInit"); 28 29 std::vector<StringRef> Strings; 30 Strings.reserve(List->getSize()); 31 32 for (ListInit::const_iterator i = List->begin(), e = List->end(); 33 i != e; 34 ++i) { 35 assert(*i && "Got a null element in a ListInit"); 36 if (StringInit *S = dyn_cast<StringInit>(*i)) 37 Strings.push_back(S->getValue()); 38 else 39 assert(false && "Got a non-string, non-code element in a ListInit"); 40 } 41 42 return Strings; 43} 44 45static std::string ReadPCHRecord(StringRef type) { 46 return StringSwitch<std::string>(type) 47 .EndsWith("Decl *", "GetLocalDeclAs<" 48 + std::string(type, 0, type.size()-1) + ">(F, Record[Idx++])") 49 .Case("QualType", "getLocalType(F, Record[Idx++])") 50 .Case("Expr *", "ReadSubExpr()") 51 .Case("IdentifierInfo *", "GetIdentifierInfo(F, Record, Idx)") 52 .Case("SourceLocation", "ReadSourceLocation(F, Record, Idx)") 53 .Default("Record[Idx++]"); 54} 55 56// Assumes that the way to get the value is SA->getname() 57static std::string WritePCHRecord(StringRef type, StringRef name) { 58 return StringSwitch<std::string>(type) 59 .EndsWith("Decl *", "AddDeclRef(" + std::string(name) + 60 ", Record);\n") 61 .Case("QualType", "AddTypeRef(" + std::string(name) + ", Record);\n") 62 .Case("Expr *", "AddStmt(" + std::string(name) + ");\n") 63 .Case("IdentifierInfo *", 64 "AddIdentifierRef(" + std::string(name) + ", Record);\n") 65 .Case("SourceLocation", 66 "AddSourceLocation(" + std::string(name) + ", Record);\n") 67 .Default("Record.push_back(" + std::string(name) + ");\n"); 68} 69 70// Normalize attribute name by removing leading and trailing 71// underscores. For example, __foo, foo__, __foo__ would 72// become foo. 73static StringRef NormalizeAttrName(StringRef AttrName) { 74 if (AttrName.startswith("__")) 75 AttrName = AttrName.substr(2, AttrName.size()); 76 77 if (AttrName.endswith("__")) 78 AttrName = AttrName.substr(0, AttrName.size() - 2); 79 80 return AttrName; 81} 82 83// Normalize attribute spelling only if the spelling has both leading 84// and trailing underscores. For example, __ms_struct__ will be 85// normalized to "ms_struct"; __cdecl will remain intact. 86static StringRef NormalizeAttrSpelling(StringRef AttrSpelling) { 87 if (AttrSpelling.startswith("__") && AttrSpelling.endswith("__")) { 88 AttrSpelling = AttrSpelling.substr(2, AttrSpelling.size() - 4); 89 } 90 91 return AttrSpelling; 92} 93 94namespace { 95 class Argument { 96 std::string lowerName, upperName; 97 StringRef attrName; 98 99 public: 100 Argument(Record &Arg, StringRef Attr) 101 : lowerName(Arg.getValueAsString("Name")), upperName(lowerName), 102 attrName(Attr) { 103 if (!lowerName.empty()) { 104 lowerName[0] = std::tolower(lowerName[0]); 105 upperName[0] = std::toupper(upperName[0]); 106 } 107 } 108 virtual ~Argument() {} 109 110 StringRef getLowerName() const { return lowerName; } 111 StringRef getUpperName() const { return upperName; } 112 StringRef getAttrName() const { return attrName; } 113 114 // These functions print the argument contents formatted in different ways. 115 virtual void writeAccessors(raw_ostream &OS) const = 0; 116 virtual void writeAccessorDefinitions(raw_ostream &OS) const {} 117 virtual void writeCloneArgs(raw_ostream &OS) const = 0; 118 virtual void writeTemplateInstantiationArgs(raw_ostream &OS) const = 0; 119 virtual void writeTemplateInstantiation(raw_ostream &OS) const {} 120 virtual void writeCtorBody(raw_ostream &OS) const {} 121 virtual void writeCtorInitializers(raw_ostream &OS) const = 0; 122 virtual void writeCtorParameters(raw_ostream &OS) const = 0; 123 virtual void writeDeclarations(raw_ostream &OS) const = 0; 124 virtual void writePCHReadArgs(raw_ostream &OS) const = 0; 125 virtual void writePCHReadDecls(raw_ostream &OS) const = 0; 126 virtual void writePCHWrite(raw_ostream &OS) const = 0; 127 virtual void writeValue(raw_ostream &OS) const = 0; 128 }; 129 130 class SimpleArgument : public Argument { 131 std::string type; 132 133 public: 134 SimpleArgument(Record &Arg, StringRef Attr, std::string T) 135 : Argument(Arg, Attr), type(T) 136 {} 137 138 std::string getType() const { return type; } 139 140 void writeAccessors(raw_ostream &OS) const { 141 OS << " " << type << " get" << getUpperName() << "() const {\n"; 142 OS << " return " << getLowerName() << ";\n"; 143 OS << " }"; 144 } 145 void writeCloneArgs(raw_ostream &OS) const { 146 OS << getLowerName(); 147 } 148 void writeTemplateInstantiationArgs(raw_ostream &OS) const { 149 OS << "A->get" << getUpperName() << "()"; 150 } 151 void writeCtorInitializers(raw_ostream &OS) const { 152 OS << getLowerName() << "(" << getUpperName() << ")"; 153 } 154 void writeCtorParameters(raw_ostream &OS) const { 155 OS << type << " " << getUpperName(); 156 } 157 void writeDeclarations(raw_ostream &OS) const { 158 OS << type << " " << getLowerName() << ";"; 159 } 160 void writePCHReadDecls(raw_ostream &OS) const { 161 std::string read = ReadPCHRecord(type); 162 OS << " " << type << " " << getLowerName() << " = " << read << ";\n"; 163 } 164 void writePCHReadArgs(raw_ostream &OS) const { 165 OS << getLowerName(); 166 } 167 void writePCHWrite(raw_ostream &OS) const { 168 OS << " " << WritePCHRecord(type, "SA->get" + 169 std::string(getUpperName()) + "()"); 170 } 171 void writeValue(raw_ostream &OS) const { 172 if (type == "FunctionDecl *") { 173 OS << "\" << get" << getUpperName() << "()->getNameInfo().getAsString() << \""; 174 } else if (type == "IdentifierInfo *") { 175 OS << "\" << get" << getUpperName() << "()->getName() << \""; 176 } else if (type == "QualType") { 177 OS << "\" << get" << getUpperName() << "().getAsString() << \""; 178 } else if (type == "SourceLocation") { 179 OS << "\" << get" << getUpperName() << "().getRawEncoding() << \""; 180 } else { 181 OS << "\" << get" << getUpperName() << "() << \""; 182 } 183 } 184 }; 185 186 class StringArgument : public Argument { 187 public: 188 StringArgument(Record &Arg, StringRef Attr) 189 : Argument(Arg, Attr) 190 {} 191 192 void writeAccessors(raw_ostream &OS) const { 193 OS << " llvm::StringRef get" << getUpperName() << "() const {\n"; 194 OS << " return llvm::StringRef(" << getLowerName() << ", " 195 << getLowerName() << "Length);\n"; 196 OS << " }\n"; 197 OS << " unsigned get" << getUpperName() << "Length() const {\n"; 198 OS << " return " << getLowerName() << "Length;\n"; 199 OS << " }\n"; 200 OS << " void set" << getUpperName() 201 << "(ASTContext &C, llvm::StringRef S) {\n"; 202 OS << " " << getLowerName() << "Length = S.size();\n"; 203 OS << " this->" << getLowerName() << " = new (C, 1) char [" 204 << getLowerName() << "Length];\n"; 205 OS << " std::memcpy(this->" << getLowerName() << ", S.data(), " 206 << getLowerName() << "Length);\n"; 207 OS << " }"; 208 } 209 void writeCloneArgs(raw_ostream &OS) const { 210 OS << "get" << getUpperName() << "()"; 211 } 212 void writeTemplateInstantiationArgs(raw_ostream &OS) const { 213 OS << "A->get" << getUpperName() << "()"; 214 } 215 void writeCtorBody(raw_ostream &OS) const { 216 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName() 217 << ".data(), " << getLowerName() << "Length);"; 218 } 219 void writeCtorInitializers(raw_ostream &OS) const { 220 OS << getLowerName() << "Length(" << getUpperName() << ".size())," 221 << getLowerName() << "(new (Ctx, 1) char[" << getLowerName() 222 << "Length])"; 223 } 224 void writeCtorParameters(raw_ostream &OS) const { 225 OS << "llvm::StringRef " << getUpperName(); 226 } 227 void writeDeclarations(raw_ostream &OS) const { 228 OS << "unsigned " << getLowerName() << "Length;\n"; 229 OS << "char *" << getLowerName() << ";"; 230 } 231 void writePCHReadDecls(raw_ostream &OS) const { 232 OS << " std::string " << getLowerName() 233 << "= ReadString(Record, Idx);\n"; 234 } 235 void writePCHReadArgs(raw_ostream &OS) const { 236 OS << getLowerName(); 237 } 238 void writePCHWrite(raw_ostream &OS) const { 239 OS << " AddString(SA->get" << getUpperName() << "(), Record);\n"; 240 } 241 void writeValue(raw_ostream &OS) const { 242 OS << "\\\"\" << get" << getUpperName() << "() << \"\\\""; 243 } 244 }; 245 246 class AlignedArgument : public Argument { 247 public: 248 AlignedArgument(Record &Arg, StringRef Attr) 249 : Argument(Arg, Attr) 250 {} 251 252 void writeAccessors(raw_ostream &OS) const { 253 OS << " bool is" << getUpperName() << "Dependent() const;\n"; 254 255 OS << " unsigned get" << getUpperName() << "(ASTContext &Ctx) const;\n"; 256 257 OS << " bool is" << getUpperName() << "Expr() const {\n"; 258 OS << " return is" << getLowerName() << "Expr;\n"; 259 OS << " }\n"; 260 261 OS << " Expr *get" << getUpperName() << "Expr() const {\n"; 262 OS << " assert(is" << getLowerName() << "Expr);\n"; 263 OS << " return " << getLowerName() << "Expr;\n"; 264 OS << " }\n"; 265 266 OS << " TypeSourceInfo *get" << getUpperName() << "Type() const {\n"; 267 OS << " assert(!is" << getLowerName() << "Expr);\n"; 268 OS << " return " << getLowerName() << "Type;\n"; 269 OS << " }"; 270 } 271 void writeAccessorDefinitions(raw_ostream &OS) const { 272 OS << "bool " << getAttrName() << "Attr::is" << getUpperName() 273 << "Dependent() const {\n"; 274 OS << " if (is" << getLowerName() << "Expr)\n"; 275 OS << " return " << getLowerName() << "Expr && (" << getLowerName() 276 << "Expr->isValueDependent() || " << getLowerName() 277 << "Expr->isTypeDependent());\n"; 278 OS << " else\n"; 279 OS << " return " << getLowerName() 280 << "Type->getType()->isDependentType();\n"; 281 OS << "}\n"; 282 283 // FIXME: Do not do the calculation here 284 // FIXME: Handle types correctly 285 // A null pointer means maximum alignment 286 // FIXME: Load the platform-specific maximum alignment, rather than 287 // 16, the x86 max. 288 OS << "unsigned " << getAttrName() << "Attr::get" << getUpperName() 289 << "(ASTContext &Ctx) const {\n"; 290 OS << " assert(!is" << getUpperName() << "Dependent());\n"; 291 OS << " if (is" << getLowerName() << "Expr)\n"; 292 OS << " return (" << getLowerName() << "Expr ? " << getLowerName() 293 << "Expr->EvaluateKnownConstInt(Ctx).getZExtValue() : 16)" 294 << "* Ctx.getCharWidth();\n"; 295 OS << " else\n"; 296 OS << " return 0; // FIXME\n"; 297 OS << "}\n"; 298 } 299 void writeCloneArgs(raw_ostream &OS) const { 300 OS << "is" << getLowerName() << "Expr, is" << getLowerName() 301 << "Expr ? static_cast<void*>(" << getLowerName() 302 << "Expr) : " << getLowerName() 303 << "Type"; 304 } 305 void writeTemplateInstantiationArgs(raw_ostream &OS) const { 306 // FIXME: move the definition in Sema::InstantiateAttrs to here. 307 // In the meantime, aligned attributes are cloned. 308 } 309 void writeCtorBody(raw_ostream &OS) const { 310 OS << " if (is" << getLowerName() << "Expr)\n"; 311 OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>(" 312 << getUpperName() << ");\n"; 313 OS << " else\n"; 314 OS << " " << getLowerName() 315 << "Type = reinterpret_cast<TypeSourceInfo *>(" << getUpperName() 316 << ");"; 317 } 318 void writeCtorInitializers(raw_ostream &OS) const { 319 OS << "is" << getLowerName() << "Expr(Is" << getUpperName() << "Expr)"; 320 } 321 void writeCtorParameters(raw_ostream &OS) const { 322 OS << "bool Is" << getUpperName() << "Expr, void *" << getUpperName(); 323 } 324 void writeDeclarations(raw_ostream &OS) const { 325 OS << "bool is" << getLowerName() << "Expr;\n"; 326 OS << "union {\n"; 327 OS << "Expr *" << getLowerName() << "Expr;\n"; 328 OS << "TypeSourceInfo *" << getLowerName() << "Type;\n"; 329 OS << "};"; 330 } 331 void writePCHReadArgs(raw_ostream &OS) const { 332 OS << "is" << getLowerName() << "Expr, " << getLowerName() << "Ptr"; 333 } 334 void writePCHReadDecls(raw_ostream &OS) const { 335 OS << " bool is" << getLowerName() << "Expr = Record[Idx++];\n"; 336 OS << " void *" << getLowerName() << "Ptr;\n"; 337 OS << " if (is" << getLowerName() << "Expr)\n"; 338 OS << " " << getLowerName() << "Ptr = ReadExpr(F);\n"; 339 OS << " else\n"; 340 OS << " " << getLowerName() 341 << "Ptr = GetTypeSourceInfo(F, Record, Idx);\n"; 342 } 343 void writePCHWrite(raw_ostream &OS) const { 344 OS << " Record.push_back(SA->is" << getUpperName() << "Expr());\n"; 345 OS << " if (SA->is" << getUpperName() << "Expr())\n"; 346 OS << " AddStmt(SA->get" << getUpperName() << "Expr());\n"; 347 OS << " else\n"; 348 OS << " AddTypeSourceInfo(SA->get" << getUpperName() 349 << "Type(), Record);\n"; 350 } 351 void writeValue(raw_ostream &OS) const { 352 OS << "\";\n" 353 << " " << getLowerName() << "Expr->printPretty(OS, 0, Policy);\n" 354 << " OS << \""; 355 } 356 }; 357 358 class VariadicArgument : public Argument { 359 std::string type; 360 361 public: 362 VariadicArgument(Record &Arg, StringRef Attr, std::string T) 363 : Argument(Arg, Attr), type(T) 364 {} 365 366 std::string getType() const { return type; } 367 368 void writeAccessors(raw_ostream &OS) const { 369 OS << " typedef " << type << "* " << getLowerName() << "_iterator;\n"; 370 OS << " " << getLowerName() << "_iterator " << getLowerName() 371 << "_begin() const {\n"; 372 OS << " return " << getLowerName() << ";\n"; 373 OS << " }\n"; 374 OS << " " << getLowerName() << "_iterator " << getLowerName() 375 << "_end() const {\n"; 376 OS << " return " << getLowerName() << " + " << getLowerName() 377 << "Size;\n"; 378 OS << " }\n"; 379 OS << " unsigned " << getLowerName() << "_size() const {\n" 380 << " return " << getLowerName() << "Size;\n"; 381 OS << " }"; 382 } 383 void writeCloneArgs(raw_ostream &OS) const { 384 OS << getLowerName() << ", " << getLowerName() << "Size"; 385 } 386 void writeTemplateInstantiationArgs(raw_ostream &OS) const { 387 // This isn't elegant, but we have to go through public methods... 388 OS << "A->" << getLowerName() << "_begin(), " 389 << "A->" << getLowerName() << "_size()"; 390 } 391 void writeCtorBody(raw_ostream &OS) const { 392 // FIXME: memcpy is not safe on non-trivial types. 393 OS << " std::memcpy(" << getLowerName() << ", " << getUpperName() 394 << ", " << getLowerName() << "Size * sizeof(" << getType() << "));\n"; 395 } 396 void writeCtorInitializers(raw_ostream &OS) const { 397 OS << getLowerName() << "Size(" << getUpperName() << "Size), " 398 << getLowerName() << "(new (Ctx, 16) " << getType() << "[" 399 << getLowerName() << "Size])"; 400 } 401 void writeCtorParameters(raw_ostream &OS) const { 402 OS << getType() << " *" << getUpperName() << ", unsigned " 403 << getUpperName() << "Size"; 404 } 405 void writeDeclarations(raw_ostream &OS) const { 406 OS << " unsigned " << getLowerName() << "Size;\n"; 407 OS << " " << getType() << " *" << getLowerName() << ";"; 408 } 409 void writePCHReadDecls(raw_ostream &OS) const { 410 OS << " unsigned " << getLowerName() << "Size = Record[Idx++];\n"; 411 OS << " llvm::SmallVector<" << type << ", 4> " << getLowerName() 412 << ";\n"; 413 OS << " " << getLowerName() << ".reserve(" << getLowerName() 414 << "Size);\n"; 415 OS << " for (unsigned i = " << getLowerName() << "Size; i; --i)\n"; 416 417 std::string read = ReadPCHRecord(type); 418 OS << " " << getLowerName() << ".push_back(" << read << ");\n"; 419 } 420 void writePCHReadArgs(raw_ostream &OS) const { 421 OS << getLowerName() << ".data(), " << getLowerName() << "Size"; 422 } 423 void writePCHWrite(raw_ostream &OS) const{ 424 OS << " Record.push_back(SA->" << getLowerName() << "_size());\n"; 425 OS << " for (" << getAttrName() << "Attr::" << getLowerName() 426 << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->" 427 << getLowerName() << "_end(); i != e; ++i)\n"; 428 OS << " " << WritePCHRecord(type, "(*i)"); 429 } 430 void writeValue(raw_ostream &OS) const { 431 OS << "\";\n"; 432 OS << " bool isFirst = true;\n" 433 << " for (" << getAttrName() << "Attr::" << getLowerName() 434 << "_iterator i = " << getLowerName() << "_begin(), e = " 435 << getLowerName() << "_end(); i != e; ++i) {\n" 436 << " if (isFirst) isFirst = false;\n" 437 << " else OS << \", \";\n" 438 << " OS << *i;\n" 439 << " }\n"; 440 OS << " OS << \""; 441 } 442 }; 443 444 class EnumArgument : public Argument { 445 std::string type; 446 std::vector<StringRef> values, enums; 447 public: 448 EnumArgument(Record &Arg, StringRef Attr) 449 : Argument(Arg, Attr), type(Arg.getValueAsString("Type")), 450 values(getValueAsListOfStrings(Arg, "Values")), 451 enums(getValueAsListOfStrings(Arg, "Enums")) 452 {} 453 454 void writeAccessors(raw_ostream &OS) const { 455 OS << " " << type << " get" << getUpperName() << "() const {\n"; 456 OS << " return " << getLowerName() << ";\n"; 457 OS << " }"; 458 } 459 void writeCloneArgs(raw_ostream &OS) const { 460 OS << getLowerName(); 461 } 462 void writeTemplateInstantiationArgs(raw_ostream &OS) const { 463 OS << "A->get" << getUpperName() << "()"; 464 } 465 void writeCtorInitializers(raw_ostream &OS) const { 466 OS << getLowerName() << "(" << getUpperName() << ")"; 467 } 468 void writeCtorParameters(raw_ostream &OS) const { 469 OS << type << " " << getUpperName(); 470 } 471 void writeDeclarations(raw_ostream &OS) const { 472 // Calculate the various enum values 473 std::vector<StringRef> uniques(enums); 474 std::sort(uniques.begin(), uniques.end()); 475 uniques.erase(std::unique(uniques.begin(), uniques.end()), 476 uniques.end()); 477 // FIXME: Emit a proper error 478 assert(!uniques.empty()); 479 480 std::vector<StringRef>::iterator i = uniques.begin(), 481 e = uniques.end(); 482 // The last one needs to not have a comma. 483 --e; 484 485 OS << "public:\n"; 486 OS << " enum " << type << " {\n"; 487 for (; i != e; ++i) 488 OS << " " << *i << ",\n"; 489 OS << " " << *e << "\n"; 490 OS << " };\n"; 491 OS << "private:\n"; 492 OS << " " << type << " " << getLowerName() << ";"; 493 } 494 void writePCHReadDecls(raw_ostream &OS) const { 495 OS << " " << getAttrName() << "Attr::" << type << " " << getLowerName() 496 << "(static_cast<" << getAttrName() << "Attr::" << type 497 << ">(Record[Idx++]));\n"; 498 } 499 void writePCHReadArgs(raw_ostream &OS) const { 500 OS << getLowerName(); 501 } 502 void writePCHWrite(raw_ostream &OS) const { 503 OS << "Record.push_back(SA->get" << getUpperName() << "());\n"; 504 } 505 void writeValue(raw_ostream &OS) const { 506 OS << "\" << get" << getUpperName() << "() << \""; 507 } 508 }; 509 510 class VersionArgument : public Argument { 511 public: 512 VersionArgument(Record &Arg, StringRef Attr) 513 : Argument(Arg, Attr) 514 {} 515 516 void writeAccessors(raw_ostream &OS) const { 517 OS << " VersionTuple get" << getUpperName() << "() const {\n"; 518 OS << " return " << getLowerName() << ";\n"; 519 OS << " }\n"; 520 OS << " void set" << getUpperName() 521 << "(ASTContext &C, VersionTuple V) {\n"; 522 OS << " " << getLowerName() << " = V;\n"; 523 OS << " }"; 524 } 525 void writeCloneArgs(raw_ostream &OS) const { 526 OS << "get" << getUpperName() << "()"; 527 } 528 void writeTemplateInstantiationArgs(raw_ostream &OS) const { 529 OS << "A->get" << getUpperName() << "()"; 530 } 531 void writeCtorBody(raw_ostream &OS) const { 532 } 533 void writeCtorInitializers(raw_ostream &OS) const { 534 OS << getLowerName() << "(" << getUpperName() << ")"; 535 } 536 void writeCtorParameters(raw_ostream &OS) const { 537 OS << "VersionTuple " << getUpperName(); 538 } 539 void writeDeclarations(raw_ostream &OS) const { 540 OS << "VersionTuple " << getLowerName() << ";\n"; 541 } 542 void writePCHReadDecls(raw_ostream &OS) const { 543 OS << " VersionTuple " << getLowerName() 544 << "= ReadVersionTuple(Record, Idx);\n"; 545 } 546 void writePCHReadArgs(raw_ostream &OS) const { 547 OS << getLowerName(); 548 } 549 void writePCHWrite(raw_ostream &OS) const { 550 OS << " AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n"; 551 } 552 void writeValue(raw_ostream &OS) const { 553 OS << getLowerName() << "=\" << get" << getUpperName() << "() << \""; 554 } 555 }; 556 557 class ExprArgument : public SimpleArgument { 558 public: 559 ExprArgument(Record &Arg, StringRef Attr) 560 : SimpleArgument(Arg, Attr, "Expr *") 561 {} 562 563 void writeTemplateInstantiationArgs(raw_ostream &OS) const { 564 OS << "tempInst" << getUpperName(); 565 } 566 567 void writeTemplateInstantiation(raw_ostream &OS) const { 568 OS << " " << getType() << " tempInst" << getUpperName() << ";\n"; 569 OS << " {\n"; 570 OS << " EnterExpressionEvaluationContext " 571 << "Unevaluated(S, Sema::Unevaluated);\n"; 572 OS << " ExprResult " << "Result = S.SubstExpr(" 573 << "A->get" << getUpperName() << "(), TemplateArgs);\n"; 574 OS << " tempInst" << getUpperName() << " = " 575 << "Result.takeAs<Expr>();\n"; 576 OS << " }\n"; 577 } 578 }; 579 580 class VariadicExprArgument : public VariadicArgument { 581 public: 582 VariadicExprArgument(Record &Arg, StringRef Attr) 583 : VariadicArgument(Arg, Attr, "Expr *") 584 {} 585 586 void writeTemplateInstantiationArgs(raw_ostream &OS) const { 587 OS << "tempInst" << getUpperName() << ", " 588 << "A->" << getLowerName() << "_size()"; 589 } 590 591 void writeTemplateInstantiation(raw_ostream &OS) const { 592 OS << " " << getType() << " *tempInst" << getUpperName() 593 << " = new (C, 16) " << getType() 594 << "[A->" << getLowerName() << "_size()];\n"; 595 OS << " {\n"; 596 OS << " EnterExpressionEvaluationContext " 597 << "Unevaluated(S, Sema::Unevaluated);\n"; 598 OS << " " << getType() << " *TI = tempInst" << getUpperName() 599 << ";\n"; 600 OS << " " << getType() << " *I = A->" << getLowerName() 601 << "_begin();\n"; 602 OS << " " << getType() << " *E = A->" << getLowerName() 603 << "_end();\n"; 604 OS << " for (; I != E; ++I, ++TI) {\n"; 605 OS << " ExprResult Result = S.SubstExpr(*I, TemplateArgs);\n"; 606 OS << " *TI = Result.takeAs<Expr>();\n"; 607 OS << " }\n"; 608 OS << " }\n"; 609 } 610 }; 611} 612 613static Argument *createArgument(Record &Arg, StringRef Attr, 614 Record *Search = 0) { 615 if (!Search) 616 Search = &Arg; 617 618 Argument *Ptr = 0; 619 llvm::StringRef ArgName = Search->getName(); 620 621 if (ArgName == "AlignedArgument") Ptr = new AlignedArgument(Arg, Attr); 622 else if (ArgName == "EnumArgument") Ptr = new EnumArgument(Arg, Attr); 623 else if (ArgName == "ExprArgument") Ptr = new ExprArgument(Arg, Attr); 624 else if (ArgName == "FunctionArgument") 625 Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *"); 626 else if (ArgName == "IdentifierArgument") 627 Ptr = new SimpleArgument(Arg, Attr, "IdentifierInfo *"); 628 else if (ArgName == "BoolArgument") Ptr = new SimpleArgument(Arg, Attr, 629 "bool"); 630 else if (ArgName == "IntArgument") Ptr = new SimpleArgument(Arg, Attr, "int"); 631 else if (ArgName == "StringArgument") Ptr = new StringArgument(Arg, Attr); 632 else if (ArgName == "TypeArgument") 633 Ptr = new SimpleArgument(Arg, Attr, "QualType"); 634 else if (ArgName == "UnsignedArgument") 635 Ptr = new SimpleArgument(Arg, Attr, "unsigned"); 636 else if (ArgName == "SourceLocArgument") 637 Ptr = new SimpleArgument(Arg, Attr, "SourceLocation"); 638 else if (ArgName == "VariadicUnsignedArgument") 639 Ptr = new VariadicArgument(Arg, Attr, "unsigned"); 640 else if (ArgName == "VariadicExprArgument") 641 Ptr = new VariadicExprArgument(Arg, Attr); 642 else if (ArgName == "VersionArgument") 643 Ptr = new VersionArgument(Arg, Attr); 644 645 if (!Ptr) { 646 std::vector<Record*> Bases = Search->getSuperClasses(); 647 for (std::vector<Record*>::iterator i = Bases.begin(), e = Bases.end(); 648 i != e; ++i) { 649 Ptr = createArgument(Arg, Attr, *i); 650 if (Ptr) 651 break; 652 } 653 } 654 return Ptr; 655} 656 657static void writeAvailabilityValue(raw_ostream &OS) { 658 OS << "\" << getPlatform()->getName();\n" 659 << " if (!getIntroduced().empty()) OS << \", introduced=\" << getIntroduced();\n" 660 << " if (!getDeprecated().empty()) OS << \", deprecated=\" << getDeprecated();\n" 661 << " if (!getObsoleted().empty()) OS << \", obsoleted=\" << getObsoleted();\n" 662 << " if (getUnavailable()) OS << \", unavailable\";\n" 663 << " OS << \""; 664} 665 666namespace clang { 667 668// Emits the class definitions for attributes. 669void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) { 670 OS << "// This file is generated by TableGen. Do not edit.\n\n"; 671 OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n"; 672 OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n"; 673 674 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 675 676 for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(); 677 i != e; ++i) { 678 Record &R = **i; 679 680 if (!R.getValueAsBit("ASTNode")) 681 continue; 682 683 const std::string &SuperName = R.getSuperClasses().back()->getName(); 684 685 OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n"; 686 687 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args"); 688 std::vector<Argument*> Args; 689 std::vector<Argument*>::iterator ai, ae; 690 Args.reserve(ArgRecords.size()); 691 692 for (std::vector<Record*>::iterator ri = ArgRecords.begin(), 693 re = ArgRecords.end(); 694 ri != re; ++ri) { 695 Record &ArgRecord = **ri; 696 Argument *Arg = createArgument(ArgRecord, R.getName()); 697 assert(Arg); 698 Args.push_back(Arg); 699 700 Arg->writeDeclarations(OS); 701 OS << "\n\n"; 702 } 703 704 ae = Args.end(); 705 706 OS << "\n public:\n"; 707 OS << " " << R.getName() << "Attr(SourceRange R, ASTContext &Ctx\n"; 708 709 for (ai = Args.begin(); ai != ae; ++ai) { 710 OS << " , "; 711 (*ai)->writeCtorParameters(OS); 712 OS << "\n"; 713 } 714 715 OS << " )\n"; 716 OS << " : " << SuperName << "(attr::" << R.getName() << ", R)\n"; 717 718 for (ai = Args.begin(); ai != ae; ++ai) { 719 OS << " , "; 720 (*ai)->writeCtorInitializers(OS); 721 OS << "\n"; 722 } 723 724 OS << " {\n"; 725 726 for (ai = Args.begin(); ai != ae; ++ai) { 727 (*ai)->writeCtorBody(OS); 728 OS << "\n"; 729 } 730 OS << " }\n\n"; 731 732 OS << " virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n"; 733 OS << " virtual void printPretty(llvm::raw_ostream &OS," 734 << " const PrintingPolicy &Policy) const;\n"; 735 736 for (ai = Args.begin(); ai != ae; ++ai) { 737 (*ai)->writeAccessors(OS); 738 OS << "\n\n"; 739 } 740 741 OS << R.getValueAsString("AdditionalMembers"); 742 OS << "\n\n"; 743 744 OS << " static bool classof(const Attr *A) { return A->getKind() == " 745 << "attr::" << R.getName() << "; }\n"; 746 747 bool LateParsed = R.getValueAsBit("LateParsed"); 748 OS << " virtual bool isLateParsed() const { return " 749 << LateParsed << "; }\n"; 750 751 OS << "};\n\n"; 752 } 753 754 OS << "#endif\n"; 755} 756 757// Emits the class method definitions for attributes. 758void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) { 759 OS << "// This file is generated by TableGen. Do not edit.\n\n"; 760 761 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 762 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ri, re; 763 std::vector<Argument*>::iterator ai, ae; 764 765 for (; i != e; ++i) { 766 Record &R = **i; 767 768 if (!R.getValueAsBit("ASTNode")) 769 continue; 770 771 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args"); 772 std::vector<Record*> Spellings = R.getValueAsListOfDefs("Spellings"); 773 std::vector<Argument*> Args; 774 for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri) 775 Args.push_back(createArgument(**ri, R.getName())); 776 777 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai) 778 (*ai)->writeAccessorDefinitions(OS); 779 780 OS << R.getName() << "Attr *" << R.getName() 781 << "Attr::clone(ASTContext &C) const {\n"; 782 OS << " return new (C) " << R.getName() << "Attr(getLocation(), C"; 783 for (ai = Args.begin(); ai != ae; ++ai) { 784 OS << ", "; 785 (*ai)->writeCloneArgs(OS); 786 } 787 OS << ");\n}\n\n"; 788 789 OS << "void " << R.getName() << "Attr::printPretty(" 790 << "llvm::raw_ostream &OS, const PrintingPolicy &Policy) const {\n"; 791 if (Spellings.begin() != Spellings.end()) { 792 std::string Spelling = (*Spellings.begin())->getValueAsString("Name"); 793 OS << " OS << \" __attribute__((" << Spelling; 794 if (Args.size()) OS << "("; 795 if (Spelling == "availability") { 796 writeAvailabilityValue(OS); 797 } else { 798 for (ai = Args.begin(); ai != ae; ++ai) { 799 if (ai!=Args.begin()) OS <<", "; 800 (*ai)->writeValue(OS); 801 } 802 } 803 if (Args.size()) OS << ")"; 804 OS << "))\";\n"; 805 } 806 OS << "}\n\n"; 807 } 808} 809 810} // end namespace clang 811 812static void EmitAttrList(raw_ostream &OS, StringRef Class, 813 const std::vector<Record*> &AttrList) { 814 std::vector<Record*>::const_iterator i = AttrList.begin(), e = AttrList.end(); 815 816 if (i != e) { 817 // Move the end iterator back to emit the last attribute. 818 for(--e; i != e; ++i) { 819 if (!(*i)->getValueAsBit("ASTNode")) 820 continue; 821 822 OS << Class << "(" << (*i)->getName() << ")\n"; 823 } 824 825 OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n"; 826 } 827} 828 829namespace clang { 830 831// Emits the enumeration list for attributes. 832void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) { 833 OS << "// This file is generated by TableGen. Do not edit.\n\n"; 834 835 OS << "#ifndef LAST_ATTR\n"; 836 OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n"; 837 OS << "#endif\n\n"; 838 839 OS << "#ifndef INHERITABLE_ATTR\n"; 840 OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n"; 841 OS << "#endif\n\n"; 842 843 OS << "#ifndef LAST_INHERITABLE_ATTR\n"; 844 OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n"; 845 OS << "#endif\n\n"; 846 847 OS << "#ifndef INHERITABLE_PARAM_ATTR\n"; 848 OS << "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n"; 849 OS << "#endif\n\n"; 850 851 OS << "#ifndef LAST_INHERITABLE_PARAM_ATTR\n"; 852 OS << "#define LAST_INHERITABLE_PARAM_ATTR(NAME)" 853 " INHERITABLE_PARAM_ATTR(NAME)\n"; 854 OS << "#endif\n\n"; 855 856 Record *InhClass = Records.getClass("InheritableAttr"); 857 Record *InhParamClass = Records.getClass("InheritableParamAttr"); 858 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), 859 NonInhAttrs, InhAttrs, InhParamAttrs; 860 for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(); 861 i != e; ++i) { 862 if (!(*i)->getValueAsBit("ASTNode")) 863 continue; 864 865 if ((*i)->isSubClassOf(InhParamClass)) 866 InhParamAttrs.push_back(*i); 867 else if ((*i)->isSubClassOf(InhClass)) 868 InhAttrs.push_back(*i); 869 else 870 NonInhAttrs.push_back(*i); 871 } 872 873 EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs); 874 EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs); 875 EmitAttrList(OS, "ATTR", NonInhAttrs); 876 877 OS << "#undef LAST_ATTR\n"; 878 OS << "#undef INHERITABLE_ATTR\n"; 879 OS << "#undef LAST_INHERITABLE_ATTR\n"; 880 OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n"; 881 OS << "#undef ATTR\n"; 882} 883 884// Emits the code to read an attribute from a precompiled header. 885void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) { 886 OS << "// This file is generated by TableGen. Do not edit.\n\n"; 887 888 Record *InhClass = Records.getClass("InheritableAttr"); 889 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), 890 ArgRecords; 891 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae; 892 std::vector<Argument*> Args; 893 std::vector<Argument*>::iterator ri, re; 894 895 OS << " switch (Kind) {\n"; 896 OS << " default:\n"; 897 OS << " assert(0 && \"Unknown attribute!\");\n"; 898 OS << " break;\n"; 899 for (; i != e; ++i) { 900 Record &R = **i; 901 if (!R.getValueAsBit("ASTNode")) 902 continue; 903 904 OS << " case attr::" << R.getName() << ": {\n"; 905 if (R.isSubClassOf(InhClass)) 906 OS << " bool isInherited = Record[Idx++];\n"; 907 ArgRecords = R.getValueAsListOfDefs("Args"); 908 Args.clear(); 909 for (ai = ArgRecords.begin(), ae = ArgRecords.end(); ai != ae; ++ai) { 910 Argument *A = createArgument(**ai, R.getName()); 911 Args.push_back(A); 912 A->writePCHReadDecls(OS); 913 } 914 OS << " New = new (Context) " << R.getName() << "Attr(Range, Context"; 915 for (ri = Args.begin(), re = Args.end(); ri != re; ++ri) { 916 OS << ", "; 917 (*ri)->writePCHReadArgs(OS); 918 } 919 OS << ");\n"; 920 if (R.isSubClassOf(InhClass)) 921 OS << " cast<InheritableAttr>(New)->setInherited(isInherited);\n"; 922 OS << " break;\n"; 923 OS << " }\n"; 924 } 925 OS << " }\n"; 926} 927 928// Emits the code to write an attribute to a precompiled header. 929void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) { 930 Record *InhClass = Records.getClass("InheritableAttr"); 931 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args; 932 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae; 933 934 OS << " switch (A->getKind()) {\n"; 935 OS << " default:\n"; 936 OS << " llvm_unreachable(\"Unknown attribute kind!\");\n"; 937 OS << " break;\n"; 938 for (; i != e; ++i) { 939 Record &R = **i; 940 if (!R.getValueAsBit("ASTNode")) 941 continue; 942 OS << " case attr::" << R.getName() << ": {\n"; 943 Args = R.getValueAsListOfDefs("Args"); 944 if (R.isSubClassOf(InhClass) || !Args.empty()) 945 OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName() 946 << "Attr>(A);\n"; 947 if (R.isSubClassOf(InhClass)) 948 OS << " Record.push_back(SA->isInherited());\n"; 949 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai) 950 createArgument(**ai, R.getName())->writePCHWrite(OS); 951 OS << " break;\n"; 952 OS << " }\n"; 953 } 954 OS << " }\n"; 955} 956 957// Emits the list of spellings for attributes. 958void EmitClangAttrSpellingList(RecordKeeper &Records, raw_ostream &OS) { 959 OS << "// This file is generated by TableGen. Do not edit.\n\n"; 960 961 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 962 963 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) { 964 Record &Attr = **I; 965 966 std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); 967 968 for (std::vector<Record*>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) { 969 OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", true)\n"; 970 } 971 } 972 973} 974 975// Emits the LateParsed property for attributes. 976void EmitClangAttrLateParsedList(RecordKeeper &Records, raw_ostream &OS) { 977 OS << "// This file is generated by TableGen. Do not edit.\n\n"; 978 979 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 980 981 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); 982 I != E; ++I) { 983 Record &Attr = **I; 984 985 bool LateParsed = Attr.getValueAsBit("LateParsed"); 986 987 if (LateParsed) { 988 std::vector<Record*> Spellings = 989 Attr.getValueAsListOfDefs("Spellings"); 990 991 // FIXME: Handle non-GNU attributes 992 for (std::vector<Record*>::const_iterator I = Spellings.begin(), 993 E = Spellings.end(); I != E; ++I) { 994 if ((*I)->getValueAsString("Variety") != "GNU") 995 continue; 996 OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", " 997 << LateParsed << ")\n"; 998 } 999 } 1000 } 1001} 1002 1003// Emits code to instantiate dependent attributes on templates. 1004void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) { 1005 OS << "// This file is generated by TableGen. Do not edit.\n\n"; 1006 1007 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 1008 1009 OS << "namespace clang {\n" 1010 << "namespace sema {\n\n" 1011 << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, " 1012 << "Sema &S,\n" 1013 << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n" 1014 << " switch (At->getKind()) {\n" 1015 << " default:\n" 1016 << " break;\n"; 1017 1018 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); 1019 I != E; ++I) { 1020 Record &R = **I; 1021 if (!R.getValueAsBit("ASTNode")) 1022 continue; 1023 1024 OS << " case attr::" << R.getName() << ": {\n"; 1025 bool ShouldClone = R.getValueAsBit("Clone"); 1026 1027 if (!ShouldClone) { 1028 OS << " return NULL;\n"; 1029 OS << " }\n"; 1030 continue; 1031 } 1032 1033 OS << " const " << R.getName() << "Attr *A = cast<" 1034 << R.getName() << "Attr>(At);\n"; 1035 bool TDependent = R.getValueAsBit("TemplateDependent"); 1036 1037 if (!TDependent) { 1038 OS << " return A->clone(C);\n"; 1039 OS << " }\n"; 1040 continue; 1041 } 1042 1043 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args"); 1044 std::vector<Argument*> Args; 1045 std::vector<Argument*>::iterator ai, ae; 1046 Args.reserve(ArgRecords.size()); 1047 1048 for (std::vector<Record*>::iterator ri = ArgRecords.begin(), 1049 re = ArgRecords.end(); 1050 ri != re; ++ri) { 1051 Record &ArgRecord = **ri; 1052 Argument *Arg = createArgument(ArgRecord, R.getName()); 1053 assert(Arg); 1054 Args.push_back(Arg); 1055 } 1056 ae = Args.end(); 1057 1058 for (ai = Args.begin(); ai != ae; ++ai) { 1059 (*ai)->writeTemplateInstantiation(OS); 1060 } 1061 OS << " return new (C) " << R.getName() << "Attr(A->getLocation(), C"; 1062 for (ai = Args.begin(); ai != ae; ++ai) { 1063 OS << ", "; 1064 (*ai)->writeTemplateInstantiationArgs(OS); 1065 } 1066 OS << ");\n }\n"; 1067 } 1068 OS << " } // end switch\n" 1069 << " llvm_unreachable(\"Unknown attribute!\");\n" 1070 << " return 0;\n" 1071 << "}\n\n" 1072 << "} // end namespace sema\n" 1073 << "} // end namespace clang\n"; 1074} 1075 1076// Emits the list of parsed attributes. 1077void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) { 1078 OS << "// This file is generated by TableGen. Do not edit.\n\n"; 1079 1080 OS << "#ifndef PARSED_ATTR\n"; 1081 OS << "#define PARSED_ATTR(NAME) NAME\n"; 1082 OS << "#endif\n\n"; 1083 1084 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 1085 1086 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); 1087 I != E; ++I) { 1088 Record &Attr = **I; 1089 1090 bool SemaHandler = Attr.getValueAsBit("SemaHandler"); 1091 bool DistinctSpellings = Attr.getValueAsBit("DistinctSpellings"); 1092 1093 if (SemaHandler) { 1094 if (DistinctSpellings) { 1095 std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); 1096 1097 for (std::vector<Record*>::const_iterator I = Spellings.begin(), 1098 E = Spellings.end(); I != E; ++I) { 1099 std::string AttrName = (*I)->getValueAsString("Name"); 1100 1101 StringRef Spelling = NormalizeAttrName(AttrName); 1102 1103 OS << "PARSED_ATTR(" << Spelling << ")\n"; 1104 } 1105 } else { 1106 StringRef AttrName = Attr.getName(); 1107 AttrName = NormalizeAttrName(AttrName); 1108 OS << "PARSED_ATTR(" << AttrName << ")\n"; 1109 } 1110 } 1111 } 1112} 1113 1114// Emits the kind list of parsed attributes 1115void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) { 1116 OS << "// This file is generated by TableGen. Do not edit.\n\n"; 1117 OS << "\n"; 1118 1119 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 1120 1121 std::vector<StringMatcher::StringPair> Matches; 1122 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); 1123 I != E; ++I) { 1124 Record &Attr = **I; 1125 1126 bool SemaHandler = Attr.getValueAsBit("SemaHandler"); 1127 bool Ignored = Attr.getValueAsBit("Ignored"); 1128 bool DistinctSpellings = Attr.getValueAsBit("DistinctSpellings"); 1129 if (SemaHandler || Ignored) { 1130 std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); 1131 1132 for (std::vector<Record*>::const_iterator I = Spellings.begin(), 1133 E = Spellings.end(); I != E; ++I) { 1134 std::string RawSpelling = (*I)->getValueAsString("Name"); 1135 StringRef AttrName = NormalizeAttrName(DistinctSpellings 1136 ? StringRef(RawSpelling) 1137 : StringRef(Attr.getName())); 1138 1139 SmallString<64> Spelling; 1140 if ((*I)->getValueAsString("Variety") == "CXX11") { 1141 Spelling += (*I)->getValueAsString("Namespace"); 1142 Spelling += "::"; 1143 } 1144 Spelling += NormalizeAttrSpelling(RawSpelling); 1145 1146 if (SemaHandler) 1147 Matches.push_back( 1148 StringMatcher::StringPair( 1149 StringRef(Spelling), 1150 "return AttributeList::AT_" + AttrName.str() + ";")); 1151 else 1152 Matches.push_back( 1153 StringMatcher::StringPair( 1154 StringRef(Spelling), 1155 "return AttributeList::IgnoredAttribute;")); 1156 } 1157 } 1158 } 1159 1160 OS << "static AttributeList::Kind getAttrKind(StringRef Name) {\n"; 1161 StringMatcher("Name", Matches, OS).Emit(); 1162 OS << "return AttributeList::UnknownAttribute;\n" 1163 << "}\n"; 1164} 1165 1166} // end namespace clang 1167