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