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