1 //===--- AttributeList.h - Parsed attribute sets ----------------*- 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 // This file defines the AttributeList class, which is used to collect 11 // parsed attributes. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_CLANG_SEMA_ATTRLIST_H 16 #define LLVM_CLANG_SEMA_ATTRLIST_H 17 18 #include "llvm/Support/Allocator.h" 19 #include "llvm/ADT/SmallVector.h" 20 #include "clang/Basic/SourceLocation.h" 21 #include "clang/Basic/VersionTuple.h" 22 #include <cassert> 23 24 namespace clang { 25 class ASTContext; 26 class IdentifierInfo; 27 class Expr; 28 29 /// \brief Represents information about a change in availability for 30 /// an entity, which is part of the encoding of the 'availability' 31 /// attribute. 32 struct AvailabilityChange { 33 /// \brief The location of the keyword indicating the kind of change. 34 SourceLocation KeywordLoc; 35 36 /// \brief The version number at which the change occurred. 37 VersionTuple Version; 38 39 /// \brief The source range covering the version number. 40 SourceRange VersionRange; 41 42 /// \brief Determine whether this availability change is valid. 43 bool isValid() const { return !Version.empty(); } 44 }; 45 46 /// AttributeList - Represents GCC's __attribute__ declaration. There are 47 /// 4 forms of this construct...they are: 48 /// 49 /// 1: __attribute__(( const )). ParmName/Args/NumArgs will all be unused. 50 /// 2: __attribute__(( mode(byte) )). ParmName used, Args/NumArgs unused. 51 /// 3: __attribute__(( format(printf, 1, 2) )). ParmName/Args/NumArgs all used. 52 /// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used. 53 /// 54 class AttributeList { // TODO: This should really be called ParsedAttribute 55 private: 56 IdentifierInfo *AttrName; 57 IdentifierInfo *ScopeName; 58 IdentifierInfo *ParmName; 59 SourceRange AttrRange; 60 SourceLocation ScopeLoc; 61 SourceLocation ParmLoc; 62 63 /// The number of expression arguments this attribute has. 64 /// The expressions themselves are stored after the object. 65 unsigned NumArgs : 16; 66 67 /// True if Microsoft style: declspec(foo). 68 unsigned DeclspecAttribute : 1; 69 70 /// True if C++0x-style: [[foo]]. 71 unsigned CXX0XAttribute : 1; 72 73 /// True if already diagnosed as invalid. 74 mutable unsigned Invalid : 1; 75 76 /// True if this attribute was used as a type attribute. 77 mutable unsigned UsedAsTypeAttr : 1; 78 79 /// True if this has the extra information associated with an 80 /// availability attribute. 81 unsigned IsAvailability : 1; 82 83 unsigned AttrKind : 8; 84 85 /// \brief The location of the 'unavailable' keyword in an 86 /// availability attribute. 87 SourceLocation UnavailableLoc; 88 89 /// The next attribute in the current position. 90 AttributeList *NextInPosition; 91 92 /// The next attribute allocated in the current Pool. 93 AttributeList *NextInPool; 94 95 Expr **getArgsBuffer() { 96 return reinterpret_cast<Expr**>(this+1); 97 } 98 Expr * const *getArgsBuffer() const { 99 return reinterpret_cast<Expr* const *>(this+1); 100 } 101 102 enum AvailabilitySlot { 103 IntroducedSlot, DeprecatedSlot, ObsoletedSlot 104 }; 105 106 AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) { 107 return reinterpret_cast<AvailabilityChange*>(this+1)[index]; 108 } 109 const AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) const { 110 return reinterpret_cast<const AvailabilityChange*>(this+1)[index]; 111 } 112 113 AttributeList(const AttributeList &); // DO NOT IMPLEMENT 114 void operator=(const AttributeList &); // DO NOT IMPLEMENT 115 void operator delete(void *); // DO NOT IMPLEMENT 116 ~AttributeList(); // DO NOT IMPLEMENT 117 118 size_t allocated_size() const; 119 120 AttributeList(IdentifierInfo *attrName, SourceRange attrRange, 121 IdentifierInfo *scopeName, SourceLocation scopeLoc, 122 IdentifierInfo *parmName, SourceLocation parmLoc, 123 Expr **args, unsigned numArgs, 124 bool declspec, bool cxx0x) 125 : AttrName(attrName), ScopeName(scopeName), ParmName(parmName), 126 AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc), 127 NumArgs(numArgs), 128 DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), Invalid(false), 129 UsedAsTypeAttr(false), IsAvailability(false), 130 NextInPosition(0), NextInPool(0) { 131 if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(Expr*)); 132 AttrKind = getKind(getName()); 133 } 134 135 AttributeList(IdentifierInfo *attrName, SourceRange attrRange, 136 IdentifierInfo *scopeName, SourceLocation scopeLoc, 137 IdentifierInfo *parmName, SourceLocation parmLoc, 138 const AvailabilityChange &introduced, 139 const AvailabilityChange &deprecated, 140 const AvailabilityChange &obsoleted, 141 SourceLocation unavailable, 142 bool declspec, bool cxx0x) 143 : AttrName(attrName), ScopeName(scopeName), ParmName(parmName), 144 AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc), 145 NumArgs(0), DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), 146 Invalid(false), UsedAsTypeAttr(false), IsAvailability(true), 147 UnavailableLoc(unavailable), NextInPosition(0), NextInPool(0) { 148 new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced); 149 new (&getAvailabilitySlot(DeprecatedSlot)) AvailabilityChange(deprecated); 150 new (&getAvailabilitySlot(ObsoletedSlot)) AvailabilityChange(obsoleted); 151 AttrKind = getKind(getName()); 152 } 153 154 friend class AttributePool; 155 friend class AttributeFactory; 156 157 public: 158 enum Kind { // Please keep this list alphabetized. 159 AT_acquired_after, 160 AT_acquired_before, 161 AT_address_space, 162 AT_alias, 163 AT_aligned, 164 AT_always_inline, 165 AT_analyzer_noreturn, 166 AT_annotate, 167 AT_arc_weakref_unavailable, 168 AT_availability, // Clang-specific 169 AT_base_check, 170 AT_blocks, 171 AT_carries_dependency, 172 AT_cdecl, 173 AT_cf_audited_transfer, // Clang-specific. 174 AT_cf_consumed, // Clang-specific. 175 AT_cf_returns_autoreleased, // Clang-specific. 176 AT_cf_returns_not_retained, // Clang-specific. 177 AT_cf_returns_retained, // Clang-specific. 178 AT_cf_unknown_transfer, // Clang-specific. 179 AT_cleanup, 180 AT_common, 181 AT_const, 182 AT_constant, 183 AT_constructor, 184 AT_deprecated, 185 AT_destructor, 186 AT_device, 187 AT_dllexport, 188 AT_dllimport, 189 AT_exclusive_lock_function, 190 AT_exclusive_locks_required, 191 AT_exclusive_trylock_function, 192 AT_ext_vector_type, 193 AT_fastcall, 194 AT_format, 195 AT_format_arg, 196 AT_global, 197 AT_gnu_inline, 198 AT_guarded_by, 199 AT_guarded_var, 200 AT_host, 201 AT_IBAction, // Clang-specific. 202 AT_IBOutlet, // Clang-specific. 203 AT_IBOutletCollection, // Clang-specific. 204 AT_init_priority, 205 AT_launch_bounds, 206 AT_lock_returned, 207 AT_lockable, 208 AT_locks_excluded, 209 AT_malloc, 210 AT_may_alias, 211 AT_mode, 212 AT_MsStruct, 213 AT_naked, 214 AT_neon_polyvector_type, // Clang-specific. 215 AT_neon_vector_type, // Clang-specific. 216 AT_no_instrument_function, 217 AT_no_thread_safety_analysis, 218 AT_nocommon, 219 AT_nodebug, 220 AT_noinline, 221 AT_nonnull, 222 AT_noreturn, 223 AT_nothrow, 224 AT_ns_bridged, // Clang-specific. 225 AT_ns_consumed, // Clang-specific. 226 AT_ns_consumes_self, // Clang-specific. 227 AT_ns_returns_autoreleased, // Clang-specific. 228 AT_ns_returns_not_retained, // Clang-specific. 229 AT_ns_returns_retained, // Clang-specific. 230 AT_nsobject, 231 AT_objc_exception, 232 AT_objc_gc, 233 AT_objc_method_family, 234 AT_objc_ownership, // Clang-specific. 235 AT_objc_precise_lifetime, // Clang-specific. 236 AT_objc_returns_inner_pointer, // Clang-specific. 237 AT_opencl_image_access, // OpenCL-specific. 238 AT_opencl_kernel_function, // OpenCL-specific. 239 AT_overloadable, // Clang-specific. 240 AT_ownership_holds, // Clang-specific. 241 AT_ownership_returns, // Clang-specific. 242 AT_ownership_takes, // Clang-specific. 243 AT_packed, 244 AT_pascal, 245 AT_pcs, // ARM specific 246 AT_pt_guarded_by, 247 AT_pt_guarded_var, 248 AT_pure, 249 AT_regparm, 250 AT_reqd_wg_size, 251 AT_scoped_lockable, 252 AT_section, 253 AT_sentinel, 254 AT_shared, 255 AT_shared_lock_function, 256 AT_shared_locks_required, 257 AT_shared_trylock_function, 258 AT_stdcall, 259 AT_thiscall, 260 AT_transparent_union, 261 AT_unavailable, 262 AT_unlock_function, 263 AT_unused, 264 AT_used, 265 AT_uuid, 266 AT_vecreturn, // PS3 PPU-specific. 267 AT_vector_size, 268 AT_visibility, 269 AT_warn_unused_result, 270 AT_weak, 271 AT_weak_import, 272 AT_weakref, 273 AT_returns_twice, 274 IgnoredAttribute, 275 UnknownAttribute 276 }; 277 278 IdentifierInfo *getName() const { return AttrName; } 279 SourceLocation getLoc() const { return AttrRange.getBegin(); } 280 SourceRange getRange() const { return AttrRange; } 281 282 bool hasScope() const { return ScopeName; } 283 IdentifierInfo *getScopeName() const { return ScopeName; } 284 SourceLocation getScopeLoc() const { return ScopeLoc; } 285 286 IdentifierInfo *getParameterName() const { return ParmName; } 287 SourceLocation getParameterLoc() const { return ParmLoc; } 288 289 bool isDeclspecAttribute() const { return DeclspecAttribute; } 290 bool isCXX0XAttribute() const { return CXX0XAttribute; } 291 292 bool isInvalid() const { return Invalid; } 293 void setInvalid(bool b = true) const { Invalid = b; } 294 295 bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; } 296 void setUsedAsTypeAttr() { UsedAsTypeAttr = true; } 297 298 Kind getKind() const { return Kind(AttrKind); } 299 static Kind getKind(const IdentifierInfo *Name); 300 301 AttributeList *getNext() const { return NextInPosition; } 302 void setNext(AttributeList *N) { NextInPosition = N; } 303 304 /// getNumArgs - Return the number of actual arguments to this attribute. 305 unsigned getNumArgs() const { return NumArgs; } 306 307 /// hasParameterOrArguments - Return true if this attribute has a parameter, 308 /// or has a non empty argument expression list. 309 bool hasParameterOrArguments() const { return ParmName || NumArgs; } 310 311 /// getArg - Return the specified argument. 312 Expr *getArg(unsigned Arg) const { 313 assert(Arg < NumArgs && "Arg access out of range!"); 314 return getArgsBuffer()[Arg]; 315 } 316 317 class arg_iterator { 318 Expr * const *X; 319 unsigned Idx; 320 public: 321 arg_iterator(Expr * const *x, unsigned idx) : X(x), Idx(idx) {} 322 323 arg_iterator& operator++() { 324 ++Idx; 325 return *this; 326 } 327 328 bool operator==(const arg_iterator& I) const { 329 assert (X == I.X && 330 "compared arg_iterators are for different argument lists"); 331 return Idx == I.Idx; 332 } 333 334 bool operator!=(const arg_iterator& I) const { 335 return !operator==(I); 336 } 337 338 Expr* operator*() const { 339 return X[Idx]; 340 } 341 342 unsigned getArgNum() const { 343 return Idx+1; 344 } 345 }; 346 347 arg_iterator arg_begin() const { 348 return arg_iterator(getArgsBuffer(), 0); 349 } 350 351 arg_iterator arg_end() const { 352 return arg_iterator(getArgsBuffer(), NumArgs); 353 } 354 355 const AvailabilityChange &getAvailabilityIntroduced() const { 356 assert(getKind() == AT_availability && "Not an availability attribute"); 357 return getAvailabilitySlot(IntroducedSlot); 358 } 359 360 const AvailabilityChange &getAvailabilityDeprecated() const { 361 assert(getKind() == AT_availability && "Not an availability attribute"); 362 return getAvailabilitySlot(DeprecatedSlot); 363 } 364 365 const AvailabilityChange &getAvailabilityObsoleted() const { 366 assert(getKind() == AT_availability && "Not an availability attribute"); 367 return getAvailabilitySlot(ObsoletedSlot); 368 } 369 370 SourceLocation getUnavailableLoc() const { 371 assert(getKind() == AT_availability && "Not an availability attribute"); 372 return UnavailableLoc; 373 } 374 }; 375 376 /// A factory, from which one makes pools, from which one creates 377 /// individual attributes which are deallocated with the pool. 378 /// 379 /// Note that it's tolerably cheap to create and destroy one of 380 /// these as long as you don't actually allocate anything in it. 381 class AttributeFactory { 382 public: 383 enum { 384 /// The required allocation size of an availability attribute, 385 /// which we want to ensure is a multiple of sizeof(void*). 386 AvailabilityAllocSize = 387 sizeof(AttributeList) 388 + ((3 * sizeof(AvailabilityChange) + sizeof(void*) - 1) 389 / sizeof(void*) * sizeof(void*)) 390 }; 391 392 private: 393 enum { 394 /// The number of free lists we want to be sure to support 395 /// inline. This is just enough that availability attributes 396 /// don't surpass it. It's actually very unlikely we'll see an 397 /// attribute that needs more than that; on x86-64 you'd need 10 398 /// expression arguments, and on i386 you'd need 19. 399 InlineFreeListsCapacity = 400 1 + (AvailabilityAllocSize - sizeof(AttributeList)) / sizeof(void*) 401 }; 402 403 llvm::BumpPtrAllocator Alloc; 404 405 /// Free lists. The index is determined by the following formula: 406 /// (size - sizeof(AttributeList)) / sizeof(void*) 407 SmallVector<AttributeList*, InlineFreeListsCapacity> FreeLists; 408 409 // The following are the private interface used by AttributePool. 410 friend class AttributePool; 411 412 /// Allocate an attribute of the given size. 413 void *allocate(size_t size); 414 415 /// Reclaim all the attributes in the given pool chain, which is 416 /// non-empty. Note that the current implementation is safe 417 /// against reclaiming things which were not actually allocated 418 /// with the allocator, although of course it's important to make 419 /// sure that their allocator lives at least as long as this one. 420 void reclaimPool(AttributeList *head); 421 422 public: 423 AttributeFactory(); 424 ~AttributeFactory(); 425 }; 426 427 class AttributePool { 428 AttributeFactory &Factory; 429 AttributeList *Head; 430 431 void *allocate(size_t size) { 432 return Factory.allocate(size); 433 } 434 435 AttributeList *add(AttributeList *attr) { 436 // We don't care about the order of the pool. 437 attr->NextInPool = Head; 438 Head = attr; 439 return attr; 440 } 441 442 void takePool(AttributeList *pool); 443 444 public: 445 /// Create a new pool for a factory. 446 AttributePool(AttributeFactory &factory) : Factory(factory), Head(0) {} 447 448 /// Move the given pool's allocations to this pool. 449 AttributePool(AttributePool &pool) : Factory(pool.Factory), Head(pool.Head) { 450 pool.Head = 0; 451 } 452 453 AttributeFactory &getFactory() const { return Factory; } 454 455 void clear() { 456 if (Head) { 457 Factory.reclaimPool(Head); 458 Head = 0; 459 } 460 } 461 462 /// Take the given pool's allocations and add them to this pool. 463 void takeAllFrom(AttributePool &pool) { 464 if (pool.Head) { 465 takePool(pool.Head); 466 pool.Head = 0; 467 } 468 } 469 470 ~AttributePool() { 471 if (Head) Factory.reclaimPool(Head); 472 } 473 474 AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, 475 IdentifierInfo *scopeName, SourceLocation scopeLoc, 476 IdentifierInfo *parmName, SourceLocation parmLoc, 477 Expr **args, unsigned numArgs, 478 bool declspec = false, bool cxx0x = false) { 479 void *memory = allocate(sizeof(AttributeList) 480 + numArgs * sizeof(Expr*)); 481 return add(new (memory) AttributeList(attrName, attrRange, 482 scopeName, scopeLoc, 483 parmName, parmLoc, 484 args, numArgs, 485 declspec, cxx0x)); 486 } 487 488 AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, 489 IdentifierInfo *scopeName, SourceLocation scopeLoc, 490 IdentifierInfo *parmName, SourceLocation parmLoc, 491 const AvailabilityChange &introduced, 492 const AvailabilityChange &deprecated, 493 const AvailabilityChange &obsoleted, 494 SourceLocation unavailable, 495 bool declspec = false, bool cxx0x = false) { 496 void *memory = allocate(AttributeFactory::AvailabilityAllocSize); 497 return add(new (memory) AttributeList(attrName, attrRange, 498 scopeName, scopeLoc, 499 parmName, parmLoc, 500 introduced, deprecated, obsoleted, 501 unavailable, 502 declspec, cxx0x)); 503 } 504 505 AttributeList *createIntegerAttribute(ASTContext &C, IdentifierInfo *Name, 506 SourceLocation TokLoc, int Arg); 507 }; 508 509 /// addAttributeLists - Add two AttributeLists together 510 /// The right-hand list is appended to the left-hand list, if any 511 /// A pointer to the joined list is returned. 512 /// Note: the lists are not left unmodified. 513 inline AttributeList *addAttributeLists(AttributeList *Left, 514 AttributeList *Right) { 515 if (!Left) 516 return Right; 517 518 AttributeList *next = Left, *prev; 519 do { 520 prev = next; 521 next = next->getNext(); 522 } while (next); 523 prev->setNext(Right); 524 return Left; 525 } 526 527 /// CXX0XAttributeList - A wrapper around a C++0x attribute list. 528 /// Stores, in addition to the list proper, whether or not an actual list was 529 /// (as opposed to an empty list, which may be ill-formed in some places) and 530 /// the source range of the list. 531 struct CXX0XAttributeList { 532 AttributeList *AttrList; 533 SourceRange Range; 534 bool HasAttr; 535 CXX0XAttributeList (AttributeList *attrList, SourceRange range, bool hasAttr) 536 : AttrList(attrList), Range(range), HasAttr (hasAttr) { 537 } 538 CXX0XAttributeList () 539 : AttrList(0), Range(), HasAttr(false) { 540 } 541 }; 542 543 /// ParsedAttributes - A collection of parsed attributes. Currently 544 /// we don't differentiate between the various attribute syntaxes, 545 /// which is basically silly. 546 /// 547 /// Right now this is a very lightweight container, but the expectation 548 /// is that this will become significantly more serious. 549 class ParsedAttributes { 550 public: 551 ParsedAttributes(AttributeFactory &factory) 552 : pool(factory), list(0) { 553 } 554 555 ParsedAttributes(ParsedAttributes &attrs) 556 : pool(attrs.pool), list(attrs.list) { 557 attrs.list = 0; 558 } 559 560 AttributePool &getPool() const { return pool; } 561 562 bool empty() const { return list == 0; } 563 564 void add(AttributeList *newAttr) { 565 assert(newAttr); 566 assert(newAttr->getNext() == 0); 567 newAttr->setNext(list); 568 list = newAttr; 569 } 570 571 void addAll(AttributeList *newList) { 572 if (!newList) return; 573 574 AttributeList *lastInNewList = newList; 575 while (AttributeList *next = lastInNewList->getNext()) 576 lastInNewList = next; 577 578 lastInNewList->setNext(list); 579 list = newList; 580 } 581 582 void set(AttributeList *newList) { 583 list = newList; 584 } 585 586 void takeAllFrom(ParsedAttributes &attrs) { 587 addAll(attrs.list); 588 attrs.list = 0; 589 pool.takeAllFrom(attrs.pool); 590 } 591 592 void clear() { list = 0; pool.clear(); } 593 AttributeList *getList() const { return list; } 594 595 /// Returns a reference to the attribute list. Try not to introduce 596 /// dependencies on this method, it may not be long-lived. 597 AttributeList *&getListRef() { return list; } 598 599 600 AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange, 601 IdentifierInfo *scopeName, SourceLocation scopeLoc, 602 IdentifierInfo *parmName, SourceLocation parmLoc, 603 Expr **args, unsigned numArgs, 604 bool declspec = false, bool cxx0x = false) { 605 AttributeList *attr = 606 pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc, 607 args, numArgs, declspec, cxx0x); 608 add(attr); 609 return attr; 610 } 611 612 AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange, 613 IdentifierInfo *scopeName, SourceLocation scopeLoc, 614 IdentifierInfo *parmName, SourceLocation parmLoc, 615 const AvailabilityChange &introduced, 616 const AvailabilityChange &deprecated, 617 const AvailabilityChange &obsoleted, 618 SourceLocation unavailable, 619 bool declspec = false, bool cxx0x = false) { 620 AttributeList *attr = 621 pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc, 622 introduced, deprecated, obsoleted, unavailable, 623 declspec, cxx0x); 624 add(attr); 625 return attr; 626 } 627 628 AttributeList *addNewInteger(ASTContext &C, IdentifierInfo *name, 629 SourceLocation loc, int arg) { 630 AttributeList *attr = 631 pool.createIntegerAttribute(C, name, loc, arg); 632 add(attr); 633 return attr; 634 } 635 636 637 private: 638 mutable AttributePool pool; 639 AttributeList *list; 640 }; 641 642 } // end namespace clang 643 644 #endif 645