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 = dynamic_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 OS << " static bool classof(const " << R.getName() 747 << "Attr *) { return true; }\n"; 748 749 bool LateParsed = R.getValueAsBit("LateParsed"); 750 OS << " virtual bool isLateParsed() const { return " 751 << LateParsed << "; }\n"; 752 753 OS << "};\n\n"; 754 } 755 756 OS << "#endif\n"; 757} 758 759// Emits the class method definitions for attributes. 760void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) { 761 OS << "// This file is generated by TableGen. Do not edit.\n\n"; 762 763 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 764 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ri, re; 765 std::vector<Argument*>::iterator ai, ae; 766 767 for (; i != e; ++i) { 768 Record &R = **i; 769 770 if (!R.getValueAsBit("ASTNode")) 771 continue; 772 773 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args"); 774 std::vector<Record*> Spellings = R.getValueAsListOfDefs("Spellings"); 775 std::vector<Argument*> Args; 776 for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri) 777 Args.push_back(createArgument(**ri, R.getName())); 778 779 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai) 780 (*ai)->writeAccessorDefinitions(OS); 781 782 OS << R.getName() << "Attr *" << R.getName() 783 << "Attr::clone(ASTContext &C) const {\n"; 784 OS << " return new (C) " << R.getName() << "Attr(getLocation(), C"; 785 for (ai = Args.begin(); ai != ae; ++ai) { 786 OS << ", "; 787 (*ai)->writeCloneArgs(OS); 788 } 789 OS << ");\n}\n\n"; 790 791 OS << "void " << R.getName() << "Attr::printPretty(" 792 << "llvm::raw_ostream &OS, const PrintingPolicy &Policy) const {\n"; 793 if (Spellings.begin() != Spellings.end()) { 794 std::string Spelling = (*Spellings.begin())->getValueAsString("Name"); 795 OS << " OS << \" __attribute__((" << Spelling; 796 if (Args.size()) OS << "("; 797 if (Spelling == "availability") { 798 writeAvailabilityValue(OS); 799 } else { 800 for (ai = Args.begin(); ai != ae; ++ai) { 801 if (ai!=Args.begin()) OS <<", "; 802 (*ai)->writeValue(OS); 803 } 804 } 805 if (Args.size()) OS << ")"; 806 OS << "))\";\n"; 807 } 808 OS << "}\n\n"; 809 } 810} 811 812} // end namespace clang 813 814static void EmitAttrList(raw_ostream &OS, StringRef Class, 815 const std::vector<Record*> &AttrList) { 816 std::vector<Record*>::const_iterator i = AttrList.begin(), e = AttrList.end(); 817 818 if (i != e) { 819 // Move the end iterator back to emit the last attribute. 820 for(--e; i != e; ++i) { 821 if (!(*i)->getValueAsBit("ASTNode")) 822 continue; 823 824 OS << Class << "(" << (*i)->getName() << ")\n"; 825 } 826 827 OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n"; 828 } 829} 830 831namespace clang { 832 833// Emits the enumeration list for attributes. 834void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) { 835 OS << "// This file is generated by TableGen. Do not edit.\n\n"; 836 837 OS << "#ifndef LAST_ATTR\n"; 838 OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n"; 839 OS << "#endif\n\n"; 840 841 OS << "#ifndef INHERITABLE_ATTR\n"; 842 OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n"; 843 OS << "#endif\n\n"; 844 845 OS << "#ifndef LAST_INHERITABLE_ATTR\n"; 846 OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n"; 847 OS << "#endif\n\n"; 848 849 OS << "#ifndef INHERITABLE_PARAM_ATTR\n"; 850 OS << "#define INHERITABLE_PARAM_ATTR(NAME) ATTR(NAME)\n"; 851 OS << "#endif\n\n"; 852 853 OS << "#ifndef LAST_INHERITABLE_PARAM_ATTR\n"; 854 OS << "#define LAST_INHERITABLE_PARAM_ATTR(NAME)" 855 " INHERITABLE_PARAM_ATTR(NAME)\n"; 856 OS << "#endif\n\n"; 857 858 Record *InhClass = Records.getClass("InheritableAttr"); 859 Record *InhParamClass = Records.getClass("InheritableParamAttr"); 860 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), 861 NonInhAttrs, InhAttrs, InhParamAttrs; 862 for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(); 863 i != e; ++i) { 864 if (!(*i)->getValueAsBit("ASTNode")) 865 continue; 866 867 if ((*i)->isSubClassOf(InhParamClass)) 868 InhParamAttrs.push_back(*i); 869 else if ((*i)->isSubClassOf(InhClass)) 870 InhAttrs.push_back(*i); 871 else 872 NonInhAttrs.push_back(*i); 873 } 874 875 EmitAttrList(OS, "INHERITABLE_PARAM_ATTR", InhParamAttrs); 876 EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs); 877 EmitAttrList(OS, "ATTR", NonInhAttrs); 878 879 OS << "#undef LAST_ATTR\n"; 880 OS << "#undef INHERITABLE_ATTR\n"; 881 OS << "#undef LAST_INHERITABLE_ATTR\n"; 882 OS << "#undef LAST_INHERITABLE_PARAM_ATTR\n"; 883 OS << "#undef ATTR\n"; 884} 885 886// Emits the code to read an attribute from a precompiled header. 887void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS) { 888 OS << "// This file is generated by TableGen. Do not edit.\n\n"; 889 890 Record *InhClass = Records.getClass("InheritableAttr"); 891 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), 892 ArgRecords; 893 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae; 894 std::vector<Argument*> Args; 895 std::vector<Argument*>::iterator ri, re; 896 897 OS << " switch (Kind) {\n"; 898 OS << " default:\n"; 899 OS << " assert(0 && \"Unknown attribute!\");\n"; 900 OS << " break;\n"; 901 for (; i != e; ++i) { 902 Record &R = **i; 903 if (!R.getValueAsBit("ASTNode")) 904 continue; 905 906 OS << " case attr::" << R.getName() << ": {\n"; 907 if (R.isSubClassOf(InhClass)) 908 OS << " bool isInherited = Record[Idx++];\n"; 909 ArgRecords = R.getValueAsListOfDefs("Args"); 910 Args.clear(); 911 for (ai = ArgRecords.begin(), ae = ArgRecords.end(); ai != ae; ++ai) { 912 Argument *A = createArgument(**ai, R.getName()); 913 Args.push_back(A); 914 A->writePCHReadDecls(OS); 915 } 916 OS << " New = new (Context) " << R.getName() << "Attr(Range, Context"; 917 for (ri = Args.begin(), re = Args.end(); ri != re; ++ri) { 918 OS << ", "; 919 (*ri)->writePCHReadArgs(OS); 920 } 921 OS << ");\n"; 922 if (R.isSubClassOf(InhClass)) 923 OS << " cast<InheritableAttr>(New)->setInherited(isInherited);\n"; 924 OS << " break;\n"; 925 OS << " }\n"; 926 } 927 OS << " }\n"; 928} 929 930// Emits the code to write an attribute to a precompiled header. 931void EmitClangAttrPCHWrite(RecordKeeper &Records, raw_ostream &OS) { 932 Record *InhClass = Records.getClass("InheritableAttr"); 933 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args; 934 std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae; 935 936 OS << " switch (A->getKind()) {\n"; 937 OS << " default:\n"; 938 OS << " llvm_unreachable(\"Unknown attribute kind!\");\n"; 939 OS << " break;\n"; 940 for (; i != e; ++i) { 941 Record &R = **i; 942 if (!R.getValueAsBit("ASTNode")) 943 continue; 944 OS << " case attr::" << R.getName() << ": {\n"; 945 Args = R.getValueAsListOfDefs("Args"); 946 if (R.isSubClassOf(InhClass) || !Args.empty()) 947 OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName() 948 << "Attr>(A);\n"; 949 if (R.isSubClassOf(InhClass)) 950 OS << " Record.push_back(SA->isInherited());\n"; 951 for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai) 952 createArgument(**ai, R.getName())->writePCHWrite(OS); 953 OS << " break;\n"; 954 OS << " }\n"; 955 } 956 OS << " }\n"; 957} 958 959// Emits the list of spellings for attributes. 960void EmitClangAttrSpellingList(RecordKeeper &Records, raw_ostream &OS) { 961 OS << "// This file is generated by TableGen. Do not edit.\n\n"; 962 963 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 964 965 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) { 966 Record &Attr = **I; 967 968 std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); 969 970 for (std::vector<Record*>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) { 971 OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", true)\n"; 972 } 973 } 974 975} 976 977// Emits the LateParsed property for attributes. 978void EmitClangAttrLateParsedList(RecordKeeper &Records, raw_ostream &OS) { 979 OS << "// This file is generated by TableGen. Do not edit.\n\n"; 980 981 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 982 983 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); 984 I != E; ++I) { 985 Record &Attr = **I; 986 987 bool LateParsed = Attr.getValueAsBit("LateParsed"); 988 989 if (LateParsed) { 990 std::vector<Record*> Spellings = 991 Attr.getValueAsListOfDefs("Spellings"); 992 993 // FIXME: Handle non-GNU attributes 994 for (std::vector<Record*>::const_iterator I = Spellings.begin(), 995 E = Spellings.end(); I != E; ++I) { 996 if ((*I)->getValueAsString("Variety") != "GNU") 997 continue; 998 OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", " 999 << LateParsed << ")\n"; 1000 } 1001 } 1002 } 1003} 1004 1005// Emits code to instantiate dependent attributes on templates. 1006void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) { 1007 OS << "// This file is generated by TableGen. Do not edit.\n\n"; 1008 1009 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 1010 1011 OS << "namespace clang {\n" 1012 << "namespace sema {\n\n" 1013 << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, " 1014 << "Sema &S,\n" 1015 << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n" 1016 << " switch (At->getKind()) {\n" 1017 << " default:\n" 1018 << " break;\n"; 1019 1020 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); 1021 I != E; ++I) { 1022 Record &R = **I; 1023 if (!R.getValueAsBit("ASTNode")) 1024 continue; 1025 1026 OS << " case attr::" << R.getName() << ": {\n"; 1027 bool ShouldClone = R.getValueAsBit("Clone"); 1028 1029 if (!ShouldClone) { 1030 OS << " return NULL;\n"; 1031 OS << " }\n"; 1032 continue; 1033 } 1034 1035 OS << " const " << R.getName() << "Attr *A = cast<" 1036 << R.getName() << "Attr>(At);\n"; 1037 bool TDependent = R.getValueAsBit("TemplateDependent"); 1038 1039 if (!TDependent) { 1040 OS << " return A->clone(C);\n"; 1041 OS << " }\n"; 1042 continue; 1043 } 1044 1045 std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args"); 1046 std::vector<Argument*> Args; 1047 std::vector<Argument*>::iterator ai, ae; 1048 Args.reserve(ArgRecords.size()); 1049 1050 for (std::vector<Record*>::iterator ri = ArgRecords.begin(), 1051 re = ArgRecords.end(); 1052 ri != re; ++ri) { 1053 Record &ArgRecord = **ri; 1054 Argument *Arg = createArgument(ArgRecord, R.getName()); 1055 assert(Arg); 1056 Args.push_back(Arg); 1057 } 1058 ae = Args.end(); 1059 1060 for (ai = Args.begin(); ai != ae; ++ai) { 1061 (*ai)->writeTemplateInstantiation(OS); 1062 } 1063 OS << " return new (C) " << R.getName() << "Attr(A->getLocation(), C"; 1064 for (ai = Args.begin(); ai != ae; ++ai) { 1065 OS << ", "; 1066 (*ai)->writeTemplateInstantiationArgs(OS); 1067 } 1068 OS << ");\n }\n"; 1069 } 1070 OS << " } // end switch\n" 1071 << " llvm_unreachable(\"Unknown attribute!\");\n" 1072 << " return 0;\n" 1073 << "}\n\n" 1074 << "} // end namespace sema\n" 1075 << "} // end namespace clang\n"; 1076} 1077 1078// Emits the list of parsed attributes. 1079void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) { 1080 OS << "// This file is generated by TableGen. Do not edit.\n\n"; 1081 1082 OS << "#ifndef PARSED_ATTR\n"; 1083 OS << "#define PARSED_ATTR(NAME) NAME\n"; 1084 OS << "#endif\n\n"; 1085 1086 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 1087 1088 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); 1089 I != E; ++I) { 1090 Record &Attr = **I; 1091 1092 bool SemaHandler = Attr.getValueAsBit("SemaHandler"); 1093 bool DistinctSpellings = Attr.getValueAsBit("DistinctSpellings"); 1094 1095 if (SemaHandler) { 1096 if (DistinctSpellings) { 1097 std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); 1098 1099 for (std::vector<Record*>::const_iterator I = Spellings.begin(), 1100 E = Spellings.end(); I != E; ++I) { 1101 std::string AttrName = (*I)->getValueAsString("Name"); 1102 1103 StringRef Spelling = NormalizeAttrName(AttrName); 1104 1105 OS << "PARSED_ATTR(" << Spelling << ")\n"; 1106 } 1107 } else { 1108 StringRef AttrName = Attr.getName(); 1109 AttrName = NormalizeAttrName(AttrName); 1110 OS << "PARSED_ATTR(" << AttrName << ")\n"; 1111 } 1112 } 1113 } 1114} 1115 1116// Emits the kind list of parsed attributes 1117void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) { 1118 OS << "// This file is generated by TableGen. Do not edit.\n\n"; 1119 OS << "\n"; 1120 1121 std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); 1122 1123 std::vector<StringMatcher::StringPair> Matches; 1124 for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); 1125 I != E; ++I) { 1126 Record &Attr = **I; 1127 1128 bool SemaHandler = Attr.getValueAsBit("SemaHandler"); 1129 bool Ignored = Attr.getValueAsBit("Ignored"); 1130 bool DistinctSpellings = Attr.getValueAsBit("DistinctSpellings"); 1131 if (SemaHandler || Ignored) { 1132 std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); 1133 1134 for (std::vector<Record*>::const_iterator I = Spellings.begin(), 1135 E = Spellings.end(); I != E; ++I) { 1136 std::string RawSpelling = (*I)->getValueAsString("Name"); 1137 StringRef AttrName = NormalizeAttrName(DistinctSpellings 1138 ? StringRef(RawSpelling) 1139 : StringRef(Attr.getName())); 1140 1141 SmallString<64> Spelling; 1142 if ((*I)->getValueAsString("Variety") == "CXX11") { 1143 Spelling += (*I)->getValueAsString("Namespace"); 1144 Spelling += "::"; 1145 } 1146 Spelling += NormalizeAttrSpelling(RawSpelling); 1147 1148 if (SemaHandler) 1149 Matches.push_back( 1150 StringMatcher::StringPair( 1151 StringRef(Spelling), 1152 "return AttributeList::AT_" + AttrName.str() + ";")); 1153 else 1154 Matches.push_back( 1155 StringMatcher::StringPair( 1156 StringRef(Spelling), 1157 "return AttributeList::IgnoredAttribute;")); 1158 } 1159 } 1160 } 1161 1162 OS << "static AttributeList::Kind getAttrKind(StringRef Name) {\n"; 1163 StringMatcher("Name", Matches, OS).Emit(); 1164 OS << "return AttributeList::UnknownAttribute;\n" 1165 << "}\n"; 1166} 1167 1168} // end namespace clang 1169