1 //===--- AttributeList.h - Parsed attribute sets ----------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the AttributeList class, which is used to collect
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CLANG_SEMA_ATTRLIST_H
16 #define LLVM_CLANG_SEMA_ATTRLIST_H
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 "clang/Sema/Ownership.h"
30 /// \brief Represents information about a change in availability for
31 /// an entity, which is part of the encoding of the 'availability'
33 struct AvailabilityChange {
34 /// \brief The location of the keyword indicating the kind of change.
35 SourceLocation KeywordLoc;
37 /// \brief The version number at which the change occurred.
40 /// \brief The source range covering the version number.
41 SourceRange VersionRange;
43 /// \brief Determine whether this availability change is valid.
44 bool isValid() const { return !Version.empty(); }
47 /// AttributeList - Represents GCC's __attribute__ declaration. There are
48 /// 4 forms of this construct...they are:
50 /// 1: __attribute__(( const )). ParmName/Args/NumArgs will all be unused.
51 /// 2: __attribute__(( mode(byte) )). ParmName used, Args/NumArgs unused.
52 /// 3: __attribute__(( format(printf, 1, 2) )). ParmName/Args/NumArgs all used.
53 /// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used.
55 class AttributeList { // TODO: This should really be called ParsedAttribute
57 /// The style used to specify an attribute.
62 // eg) __w64, __ptr32, etc. It is implied that an MSTypespec is also
67 IdentifierInfo *AttrName;
68 IdentifierInfo *ScopeName;
69 IdentifierInfo *ParmName;
70 SourceRange AttrRange;
71 SourceLocation ScopeLoc;
72 SourceLocation ParmLoc;
74 /// The number of expression arguments this attribute has.
75 /// The expressions themselves are stored after the object.
76 unsigned NumArgs : 16;
78 /// Corresponds to the Syntax enum.
79 unsigned SyntaxUsed : 2;
81 /// True if already diagnosed as invalid.
82 mutable unsigned Invalid : 1;
84 /// True if this attribute was used as a type attribute.
85 mutable unsigned UsedAsTypeAttr : 1;
87 /// True if this has the extra information associated with an
88 /// availability attribute.
89 unsigned IsAvailability : 1;
91 /// True if this has extra information associated with a
92 /// type_tag_for_datatype attribute.
93 unsigned IsTypeTagForDatatype : 1;
95 unsigned AttrKind : 8;
97 /// \brief The location of the 'unavailable' keyword in an
98 /// availability attribute.
99 SourceLocation UnavailableLoc;
101 const Expr *MessageExpr;
103 /// The next attribute in the current position.
104 AttributeList *NextInPosition;
106 /// The next attribute allocated in the current Pool.
107 AttributeList *NextInPool;
109 Expr **getArgsBuffer() {
110 return reinterpret_cast<Expr**>(this+1);
112 Expr * const *getArgsBuffer() const {
113 return reinterpret_cast<Expr* const *>(this+1);
116 enum AvailabilitySlot {
117 IntroducedSlot, DeprecatedSlot, ObsoletedSlot
120 AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) {
121 return reinterpret_cast<AvailabilityChange*>(this+1)[index];
123 const AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) const {
124 return reinterpret_cast<const AvailabilityChange*>(this+1)[index];
128 struct TypeTagForDatatypeData {
129 ParsedType *MatchingCType;
130 unsigned LayoutCompatible : 1;
131 unsigned MustBeNull : 1;
135 TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() {
136 return *reinterpret_cast<TypeTagForDatatypeData *>(this + 1);
139 const TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const {
140 return *reinterpret_cast<const TypeTagForDatatypeData *>(this + 1);
143 AttributeList(const AttributeList &) LLVM_DELETED_FUNCTION;
144 void operator=(const AttributeList &) LLVM_DELETED_FUNCTION;
145 void operator delete(void *) LLVM_DELETED_FUNCTION;
146 ~AttributeList() LLVM_DELETED_FUNCTION;
148 size_t allocated_size() const;
150 /// Constructor for attributes with expression arguments.
151 AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
152 IdentifierInfo *scopeName, SourceLocation scopeLoc,
153 IdentifierInfo *parmName, SourceLocation parmLoc,
154 Expr **args, unsigned numArgs,
156 : AttrName(attrName), ScopeName(scopeName), ParmName(parmName),
157 AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
158 NumArgs(numArgs), SyntaxUsed(syntaxUsed), Invalid(false),
159 UsedAsTypeAttr(false), IsAvailability(false),
160 IsTypeTagForDatatype(false), NextInPosition(0), NextInPool(0) {
161 if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(Expr*));
162 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
165 /// Constructor for availability attributes.
166 AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
167 IdentifierInfo *scopeName, SourceLocation scopeLoc,
168 IdentifierInfo *parmName, SourceLocation parmLoc,
169 const AvailabilityChange &introduced,
170 const AvailabilityChange &deprecated,
171 const AvailabilityChange &obsoleted,
172 SourceLocation unavailable,
173 const Expr *messageExpr,
175 : AttrName(attrName), ScopeName(scopeName), ParmName(parmName),
176 AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
177 NumArgs(0), SyntaxUsed(syntaxUsed),
178 Invalid(false), UsedAsTypeAttr(false), IsAvailability(true),
179 IsTypeTagForDatatype(false),
180 UnavailableLoc(unavailable), MessageExpr(messageExpr),
181 NextInPosition(0), NextInPool(0) {
182 new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced);
183 new (&getAvailabilitySlot(DeprecatedSlot)) AvailabilityChange(deprecated);
184 new (&getAvailabilitySlot(ObsoletedSlot)) AvailabilityChange(obsoleted);
185 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
188 /// Constructor for type_tag_for_datatype attribute.
189 AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
190 IdentifierInfo *scopeName, SourceLocation scopeLoc,
191 IdentifierInfo *argumentKindName,
192 SourceLocation argumentKindLoc,
193 ParsedType matchingCType, bool layoutCompatible,
194 bool mustBeNull, Syntax syntaxUsed)
195 : AttrName(attrName), ScopeName(scopeName), ParmName(argumentKindName),
196 AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(argumentKindLoc),
197 NumArgs(0), SyntaxUsed(syntaxUsed),
198 Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
199 IsTypeTagForDatatype(true), NextInPosition(NULL), NextInPool(NULL) {
200 TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot();
201 new (&ExtraData.MatchingCType) ParsedType(matchingCType);
202 ExtraData.LayoutCompatible = layoutCompatible;
203 ExtraData.MustBeNull = mustBeNull;
204 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
207 friend class AttributePool;
208 friend class AttributeFactory;
212 #define PARSED_ATTR(NAME) AT_##NAME,
213 #include "clang/Sema/AttrParsedAttrList.inc"
219 IdentifierInfo *getName() const { return AttrName; }
220 SourceLocation getLoc() const { return AttrRange.getBegin(); }
221 SourceRange getRange() const { return AttrRange; }
223 bool hasScope() const { return ScopeName; }
224 IdentifierInfo *getScopeName() const { return ScopeName; }
225 SourceLocation getScopeLoc() const { return ScopeLoc; }
227 IdentifierInfo *getParameterName() const { return ParmName; }
228 SourceLocation getParameterLoc() const { return ParmLoc; }
230 /// Returns true if the attribute is a pure __declspec or a synthesized
231 /// declspec representing a type specification (like __w64 or __ptr32).
232 bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec ||
233 SyntaxUsed == AS_MSTypespec; }
234 bool isCXX0XAttribute() const { return SyntaxUsed == AS_CXX11; }
235 bool isMSTypespecAttribute() const { return SyntaxUsed == AS_MSTypespec; }
237 bool isInvalid() const { return Invalid; }
238 void setInvalid(bool b = true) const { Invalid = b; }
240 bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; }
241 void setUsedAsTypeAttr() { UsedAsTypeAttr = true; }
243 Kind getKind() const { return Kind(AttrKind); }
244 static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope,
247 AttributeList *getNext() const { return NextInPosition; }
248 void setNext(AttributeList *N) { NextInPosition = N; }
250 /// getNumArgs - Return the number of actual arguments to this attribute.
251 unsigned getNumArgs() const { return NumArgs; }
253 /// hasParameterOrArguments - Return true if this attribute has a parameter,
254 /// or has a non empty argument expression list.
255 bool hasParameterOrArguments() const { return ParmName || NumArgs; }
257 /// getArg - Return the specified argument.
258 Expr *getArg(unsigned Arg) const {
259 assert(Arg < NumArgs && "Arg access out of range!");
260 return getArgsBuffer()[Arg];
267 arg_iterator(Expr * const *x, unsigned idx) : X(x), Idx(idx) {}
269 arg_iterator& operator++() {
274 bool operator==(const arg_iterator& I) const {
276 "compared arg_iterators are for different argument lists");
280 bool operator!=(const arg_iterator& I) const {
281 return !operator==(I);
284 Expr* operator*() const {
288 unsigned getArgNum() const {
293 arg_iterator arg_begin() const {
294 return arg_iterator(getArgsBuffer(), 0);
297 arg_iterator arg_end() const {
298 return arg_iterator(getArgsBuffer(), NumArgs);
301 const AvailabilityChange &getAvailabilityIntroduced() const {
302 assert(getKind() == AT_Availability && "Not an availability attribute");
303 return getAvailabilitySlot(IntroducedSlot);
306 const AvailabilityChange &getAvailabilityDeprecated() const {
307 assert(getKind() == AT_Availability && "Not an availability attribute");
308 return getAvailabilitySlot(DeprecatedSlot);
311 const AvailabilityChange &getAvailabilityObsoleted() const {
312 assert(getKind() == AT_Availability && "Not an availability attribute");
313 return getAvailabilitySlot(ObsoletedSlot);
316 SourceLocation getUnavailableLoc() const {
317 assert(getKind() == AT_Availability && "Not an availability attribute");
318 return UnavailableLoc;
321 const Expr * getMessageExpr() const {
322 assert(getKind() == AT_Availability && "Not an availability attribute");
326 const ParsedType &getMatchingCType() const {
327 assert(getKind() == AT_TypeTagForDatatype &&
328 "Not a type_tag_for_datatype attribute");
329 return *getTypeTagForDatatypeDataSlot().MatchingCType;
332 bool getLayoutCompatible() const {
333 assert(getKind() == AT_TypeTagForDatatype &&
334 "Not a type_tag_for_datatype attribute");
335 return getTypeTagForDatatypeDataSlot().LayoutCompatible;
338 bool getMustBeNull() const {
339 assert(getKind() == AT_TypeTagForDatatype &&
340 "Not a type_tag_for_datatype attribute");
341 return getTypeTagForDatatypeDataSlot().MustBeNull;
345 /// A factory, from which one makes pools, from which one creates
346 /// individual attributes which are deallocated with the pool.
348 /// Note that it's tolerably cheap to create and destroy one of
349 /// these as long as you don't actually allocate anything in it.
350 class AttributeFactory {
353 /// The required allocation size of an availability attribute,
354 /// which we want to ensure is a multiple of sizeof(void*).
355 AvailabilityAllocSize =
356 sizeof(AttributeList)
357 + ((3 * sizeof(AvailabilityChange) + sizeof(void*) - 1)
358 / sizeof(void*) * sizeof(void*)),
359 TypeTagForDatatypeAllocSize =
360 sizeof(AttributeList)
361 + (sizeof(AttributeList::TypeTagForDatatypeData) + sizeof(void *) - 1)
362 / sizeof(void*) * sizeof(void*)
367 /// The number of free lists we want to be sure to support
368 /// inline. This is just enough that availability attributes
369 /// don't surpass it. It's actually very unlikely we'll see an
370 /// attribute that needs more than that; on x86-64 you'd need 10
371 /// expression arguments, and on i386 you'd need 19.
372 InlineFreeListsCapacity =
373 1 + (AvailabilityAllocSize - sizeof(AttributeList)) / sizeof(void*)
376 llvm::BumpPtrAllocator Alloc;
378 /// Free lists. The index is determined by the following formula:
379 /// (size - sizeof(AttributeList)) / sizeof(void*)
380 SmallVector<AttributeList*, InlineFreeListsCapacity> FreeLists;
382 // The following are the private interface used by AttributePool.
383 friend class AttributePool;
385 /// Allocate an attribute of the given size.
386 void *allocate(size_t size);
388 /// Reclaim all the attributes in the given pool chain, which is
389 /// non-empty. Note that the current implementation is safe
390 /// against reclaiming things which were not actually allocated
391 /// with the allocator, although of course it's important to make
392 /// sure that their allocator lives at least as long as this one.
393 void reclaimPool(AttributeList *head);
400 class AttributePool {
401 AttributeFactory &Factory;
404 void *allocate(size_t size) {
405 return Factory.allocate(size);
408 AttributeList *add(AttributeList *attr) {
409 // We don't care about the order of the pool.
410 attr->NextInPool = Head;
415 void takePool(AttributeList *pool);
418 /// Create a new pool for a factory.
419 AttributePool(AttributeFactory &factory) : Factory(factory), Head(0) {}
421 /// Move the given pool's allocations to this pool.
422 AttributePool(AttributePool &pool) : Factory(pool.Factory), Head(pool.Head) {
426 AttributeFactory &getFactory() const { return Factory; }
430 Factory.reclaimPool(Head);
435 /// Take the given pool's allocations and add them to this pool.
436 void takeAllFrom(AttributePool &pool) {
444 if (Head) Factory.reclaimPool(Head);
447 AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
448 IdentifierInfo *scopeName, SourceLocation scopeLoc,
449 IdentifierInfo *parmName, SourceLocation parmLoc,
450 Expr **args, unsigned numArgs,
451 AttributeList::Syntax syntax) {
452 void *memory = allocate(sizeof(AttributeList)
453 + numArgs * sizeof(Expr*));
454 return add(new (memory) AttributeList(attrName, attrRange,
457 args, numArgs, syntax));
460 AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
461 IdentifierInfo *scopeName, SourceLocation scopeLoc,
462 IdentifierInfo *parmName, SourceLocation parmLoc,
463 const AvailabilityChange &introduced,
464 const AvailabilityChange &deprecated,
465 const AvailabilityChange &obsoleted,
466 SourceLocation unavailable,
467 const Expr *MessageExpr,
468 AttributeList::Syntax syntax) {
469 void *memory = allocate(AttributeFactory::AvailabilityAllocSize);
470 return add(new (memory) AttributeList(attrName, attrRange,
473 introduced, deprecated, obsoleted,
474 unavailable, MessageExpr, syntax));
477 AttributeList *createIntegerAttribute(ASTContext &C, IdentifierInfo *Name,
478 SourceLocation TokLoc, int Arg);
480 AttributeList *createTypeTagForDatatype(
481 IdentifierInfo *attrName, SourceRange attrRange,
482 IdentifierInfo *scopeName, SourceLocation scopeLoc,
483 IdentifierInfo *argumentKindName,
484 SourceLocation argumentKindLoc,
485 ParsedType matchingCType, bool layoutCompatible,
486 bool mustBeNull, AttributeList::Syntax syntax) {
487 void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize);
488 return add(new (memory) AttributeList(attrName, attrRange,
490 argumentKindName, argumentKindLoc,
491 matchingCType, layoutCompatible,
492 mustBeNull, syntax));
496 /// addAttributeLists - Add two AttributeLists together
497 /// The right-hand list is appended to the left-hand list, if any
498 /// A pointer to the joined list is returned.
499 /// Note: the lists are not left unmodified.
500 inline AttributeList *addAttributeLists(AttributeList *Left,
501 AttributeList *Right) {
505 AttributeList *next = Left, *prev;
508 next = next->getNext();
510 prev->setNext(Right);
514 /// CXX0XAttributeList - A wrapper around a C++0x attribute list.
515 /// Stores, in addition to the list proper, whether or not an actual list was
516 /// (as opposed to an empty list, which may be ill-formed in some places) and
517 /// the source range of the list.
518 struct CXX0XAttributeList {
519 AttributeList *AttrList;
522 CXX0XAttributeList (AttributeList *attrList, SourceRange range, bool hasAttr)
523 : AttrList(attrList), Range(range), HasAttr (hasAttr) {
525 CXX0XAttributeList ()
526 : AttrList(0), Range(), HasAttr(false) {
530 /// ParsedAttributes - A collection of parsed attributes. Currently
531 /// we don't differentiate between the various attribute syntaxes,
532 /// which is basically silly.
534 /// Right now this is a very lightweight container, but the expectation
535 /// is that this will become significantly more serious.
536 class ParsedAttributes {
538 ParsedAttributes(AttributeFactory &factory)
539 : pool(factory), list(0) {
542 ParsedAttributes(ParsedAttributes &attrs)
543 : pool(attrs.pool), list(attrs.list) {
547 AttributePool &getPool() const { return pool; }
549 bool empty() const { return list == 0; }
551 void add(AttributeList *newAttr) {
553 assert(newAttr->getNext() == 0);
554 newAttr->setNext(list);
558 void addAll(AttributeList *newList) {
559 if (!newList) return;
561 AttributeList *lastInNewList = newList;
562 while (AttributeList *next = lastInNewList->getNext())
563 lastInNewList = next;
565 lastInNewList->setNext(list);
569 void set(AttributeList *newList) {
573 void takeAllFrom(ParsedAttributes &attrs) {
576 pool.takeAllFrom(attrs.pool);
579 void clear() { list = 0; pool.clear(); }
580 AttributeList *getList() const { return list; }
582 /// Returns a reference to the attribute list. Try not to introduce
583 /// dependencies on this method, it may not be long-lived.
584 AttributeList *&getListRef() { return list; }
586 /// Add attribute with expression arguments.
587 AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
588 IdentifierInfo *scopeName, SourceLocation scopeLoc,
589 IdentifierInfo *parmName, SourceLocation parmLoc,
590 Expr **args, unsigned numArgs,
591 AttributeList::Syntax syntax) {
592 AttributeList *attr =
593 pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc,
594 args, numArgs, syntax);
599 /// Add availability attribute.
600 AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
601 IdentifierInfo *scopeName, SourceLocation scopeLoc,
602 IdentifierInfo *parmName, SourceLocation parmLoc,
603 const AvailabilityChange &introduced,
604 const AvailabilityChange &deprecated,
605 const AvailabilityChange &obsoleted,
606 SourceLocation unavailable,
607 const Expr *MessageExpr,
608 AttributeList::Syntax syntax) {
609 AttributeList *attr =
610 pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc,
611 introduced, deprecated, obsoleted, unavailable,
612 MessageExpr, syntax);
617 /// Add type_tag_for_datatype attribute.
618 AttributeList *addNewTypeTagForDatatype(
619 IdentifierInfo *attrName, SourceRange attrRange,
620 IdentifierInfo *scopeName, SourceLocation scopeLoc,
621 IdentifierInfo *argumentKindName,
622 SourceLocation argumentKindLoc,
623 ParsedType matchingCType, bool layoutCompatible,
624 bool mustBeNull, AttributeList::Syntax syntax) {
625 AttributeList *attr =
626 pool.createTypeTagForDatatype(attrName, attrRange,
628 argumentKindName, argumentKindLoc,
629 matchingCType, layoutCompatible,
635 AttributeList *addNewInteger(ASTContext &C, IdentifierInfo *name,
636 SourceLocation loc, int arg) {
637 AttributeList *attr =
638 pool.createIntegerAttribute(C, name, loc, arg);
645 mutable AttributePool pool;
649 } // end namespace clang