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