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