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