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