• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
24 namespace 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.
32 struct 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.
isValidAvailabilityChange43   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 ///
54 class AttributeList { // TODO: This should really be called ParsedAttribute
55 private:
56   IdentifierInfo *AttrName;
57   IdentifierInfo *ScopeName;
58   IdentifierInfo *ParmName;
59   SourceRange AttrRange;
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 attribute was used as a type attribute.
77   mutable unsigned UsedAsTypeAttr : 1;
78 
79   /// True if this has the extra information associated with an
80   /// availability attribute.
81   unsigned IsAvailability : 1;
82 
83   unsigned AttrKind : 8;
84 
85   /// \brief The location of the 'unavailable' keyword in an
86   /// availability attribute.
87   SourceLocation UnavailableLoc;
88 
89   const Expr *MessageExpr;
90 
91   /// The next attribute in the current position.
92   AttributeList *NextInPosition;
93 
94   /// The next attribute allocated in the current Pool.
95   AttributeList *NextInPool;
96 
getArgsBuffer()97   Expr **getArgsBuffer() {
98     return reinterpret_cast<Expr**>(this+1);
99   }
getArgsBuffer()100   Expr * const *getArgsBuffer() const {
101     return reinterpret_cast<Expr* const *>(this+1);
102   }
103 
104   enum AvailabilitySlot {
105     IntroducedSlot, DeprecatedSlot, ObsoletedSlot
106   };
107 
getAvailabilitySlot(AvailabilitySlot index)108   AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) {
109     return reinterpret_cast<AvailabilityChange*>(this+1)[index];
110   }
getAvailabilitySlot(AvailabilitySlot index)111   const AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) const {
112     return reinterpret_cast<const AvailabilityChange*>(this+1)[index];
113   }
114 
115   AttributeList(const AttributeList &); // DO NOT IMPLEMENT
116   void operator=(const AttributeList &); // DO NOT IMPLEMENT
117   void operator delete(void *); // DO NOT IMPLEMENT
118   ~AttributeList(); // DO NOT IMPLEMENT
119 
120   size_t allocated_size() const;
121 
AttributeList(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * parmName,SourceLocation parmLoc,Expr ** args,unsigned numArgs,bool declspec,bool cxx0x)122   AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
123                 IdentifierInfo *scopeName, SourceLocation scopeLoc,
124                 IdentifierInfo *parmName, SourceLocation parmLoc,
125                 Expr **args, unsigned numArgs,
126                 bool declspec, bool cxx0x)
127     : AttrName(attrName), ScopeName(scopeName), ParmName(parmName),
128       AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
129       NumArgs(numArgs),
130       DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), Invalid(false),
131       UsedAsTypeAttr(false), IsAvailability(false),
132       NextInPosition(0), NextInPool(0) {
133     if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(Expr*));
134     AttrKind = getKind(getName());
135   }
136 
AttributeList(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * parmName,SourceLocation parmLoc,const AvailabilityChange & introduced,const AvailabilityChange & deprecated,const AvailabilityChange & obsoleted,SourceLocation unavailable,const Expr * messageExpr,bool declspec,bool cxx0x)137   AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
138                 IdentifierInfo *scopeName, SourceLocation scopeLoc,
139                 IdentifierInfo *parmName, SourceLocation parmLoc,
140                 const AvailabilityChange &introduced,
141                 const AvailabilityChange &deprecated,
142                 const AvailabilityChange &obsoleted,
143                 SourceLocation unavailable,
144                 const Expr *messageExpr,
145                 bool declspec, bool cxx0x)
146     : AttrName(attrName), ScopeName(scopeName), ParmName(parmName),
147       AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
148       NumArgs(0), DeclspecAttribute(declspec), CXX0XAttribute(cxx0x),
149       Invalid(false), UsedAsTypeAttr(false), IsAvailability(true),
150       UnavailableLoc(unavailable), MessageExpr(messageExpr),
151       NextInPosition(0), NextInPool(0) {
152     new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced);
153     new (&getAvailabilitySlot(DeprecatedSlot)) AvailabilityChange(deprecated);
154     new (&getAvailabilitySlot(ObsoletedSlot)) AvailabilityChange(obsoleted);
155     AttrKind = getKind(getName());
156   }
157 
158   friend class AttributePool;
159   friend class AttributeFactory;
160 
161 public:
162   enum Kind {
163     #define PARSED_ATTR(NAME) AT_##NAME,
164     #include "clang/Sema/AttrParsedAttrList.inc"
165     PARSED_ATTR(address_space)
166     PARSED_ATTR(base_check)
167     PARSED_ATTR(cf_returns_autoreleased)
168     PARSED_ATTR(ext_vector_type)
169     PARSED_ATTR(mode)
170     PARSED_ATTR(neon_polyvector_type)
171     PARSED_ATTR(neon_vector_type)
172     PARSED_ATTR(objc_gc)
173     PARSED_ATTR(objc_ownership)
174     PARSED_ATTR(opencl_image_access)
175     PARSED_ATTR(vector_size)
176     #undef PARSED_ATTR
177     IgnoredAttribute,
178     UnknownAttribute
179   };
180 
getName()181   IdentifierInfo *getName() const { return AttrName; }
getLoc()182   SourceLocation getLoc() const { return AttrRange.getBegin(); }
getRange()183   SourceRange getRange() const { return AttrRange; }
184 
hasScope()185   bool hasScope() const { return ScopeName; }
getScopeName()186   IdentifierInfo *getScopeName() const { return ScopeName; }
getScopeLoc()187   SourceLocation getScopeLoc() const { return ScopeLoc; }
188 
getParameterName()189   IdentifierInfo *getParameterName() const { return ParmName; }
getParameterLoc()190   SourceLocation getParameterLoc() const { return ParmLoc; }
191 
isDeclspecAttribute()192   bool isDeclspecAttribute() const { return DeclspecAttribute; }
isCXX0XAttribute()193   bool isCXX0XAttribute() const { return CXX0XAttribute; }
194 
isInvalid()195   bool isInvalid() const { return Invalid; }
196   void setInvalid(bool b = true) const { Invalid = b; }
197 
isUsedAsTypeAttr()198   bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; }
setUsedAsTypeAttr()199   void setUsedAsTypeAttr() { UsedAsTypeAttr = true; }
200 
getKind()201   Kind getKind() const { return Kind(AttrKind); }
202   static Kind getKind(const IdentifierInfo *Name);
203 
getNext()204   AttributeList *getNext() const { return NextInPosition; }
setNext(AttributeList * N)205   void setNext(AttributeList *N) { NextInPosition = N; }
206 
207   /// getNumArgs - Return the number of actual arguments to this attribute.
getNumArgs()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.
hasParameterOrArguments()212   bool hasParameterOrArguments() const { return ParmName || NumArgs; }
213 
214   /// getArg - Return the specified argument.
getArg(unsigned Arg)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:
arg_iterator(Expr * const * x,unsigned idx)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 
getArgNum()245     unsigned getArgNum() const {
246       return Idx+1;
247     }
248   };
249 
arg_begin()250   arg_iterator arg_begin() const {
251     return arg_iterator(getArgsBuffer(), 0);
252   }
253 
arg_end()254   arg_iterator arg_end() const {
255     return arg_iterator(getArgsBuffer(), NumArgs);
256   }
257 
getAvailabilityIntroduced()258   const AvailabilityChange &getAvailabilityIntroduced() const {
259     assert(getKind() == AT_availability && "Not an availability attribute");
260     return getAvailabilitySlot(IntroducedSlot);
261   }
262 
getAvailabilityDeprecated()263   const AvailabilityChange &getAvailabilityDeprecated() const {
264     assert(getKind() == AT_availability && "Not an availability attribute");
265     return getAvailabilitySlot(DeprecatedSlot);
266   }
267 
getAvailabilityObsoleted()268   const AvailabilityChange &getAvailabilityObsoleted() const {
269     assert(getKind() == AT_availability && "Not an availability attribute");
270     return getAvailabilitySlot(ObsoletedSlot);
271   }
272 
getUnavailableLoc()273   SourceLocation getUnavailableLoc() const {
274     assert(getKind() == AT_availability && "Not an availability attribute");
275     return UnavailableLoc;
276   }
277 
getMessageExpr()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.
289 class AttributeFactory {
290 public:
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 
300 private:
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 
330 public:
331   AttributeFactory();
332   ~AttributeFactory();
333 };
334 
335 class AttributePool {
336   AttributeFactory &Factory;
337   AttributeList *Head;
338 
allocate(size_t size)339   void *allocate(size_t size) {
340     return Factory.allocate(size);
341   }
342 
add(AttributeList * attr)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 
352 public:
353   /// Create a new pool for a factory.
AttributePool(AttributeFactory & factory)354   AttributePool(AttributeFactory &factory) : Factory(factory), Head(0) {}
355 
356   /// Move the given pool's allocations to this pool.
AttributePool(AttributePool & pool)357   AttributePool(AttributePool &pool) : Factory(pool.Factory), Head(pool.Head) {
358     pool.Head = 0;
359   }
360 
getFactory()361   AttributeFactory &getFactory() const { return Factory; }
362 
clear()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.
takeAllFrom(AttributePool & pool)371   void takeAllFrom(AttributePool &pool) {
372     if (pool.Head) {
373       takePool(pool.Head);
374       pool.Head = 0;
375     }
376   }
377 
~AttributePool()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                         bool declspec = false, bool cxx0x = false) {
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,
393                                           declspec, cxx0x));
394   }
395 
396   AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
397                         IdentifierInfo *scopeName, SourceLocation scopeLoc,
398                         IdentifierInfo *parmName, SourceLocation parmLoc,
399                         const AvailabilityChange &introduced,
400                         const AvailabilityChange &deprecated,
401                         const AvailabilityChange &obsoleted,
402                         SourceLocation unavailable,
403                         const Expr *MessageExpr,
404                         bool declspec = false, bool cxx0x = false) {
405     void *memory = allocate(AttributeFactory::AvailabilityAllocSize);
406     return add(new (memory) AttributeList(attrName, attrRange,
407                                           scopeName, scopeLoc,
408                                           parmName, parmLoc,
409                                           introduced, deprecated, obsoleted,
410                                           unavailable, MessageExpr,
411                                           declspec, cxx0x));
412   }
413 
414   AttributeList *createIntegerAttribute(ASTContext &C, IdentifierInfo *Name,
415                                         SourceLocation TokLoc, int Arg);
416 };
417 
418 /// addAttributeLists - Add two AttributeLists together
419 /// The right-hand list is appended to the left-hand list, if any
420 /// A pointer to the joined list is returned.
421 /// Note: the lists are not left unmodified.
addAttributeLists(AttributeList * Left,AttributeList * Right)422 inline AttributeList *addAttributeLists(AttributeList *Left,
423                                         AttributeList *Right) {
424   if (!Left)
425     return Right;
426 
427   AttributeList *next = Left, *prev;
428   do {
429     prev = next;
430     next = next->getNext();
431   } while (next);
432   prev->setNext(Right);
433   return Left;
434 }
435 
436 /// CXX0XAttributeList - A wrapper around a C++0x attribute list.
437 /// Stores, in addition to the list proper, whether or not an actual list was
438 /// (as opposed to an empty list, which may be ill-formed in some places) and
439 /// the source range of the list.
440 struct CXX0XAttributeList {
441   AttributeList *AttrList;
442   SourceRange Range;
443   bool HasAttr;
CXX0XAttributeListCXX0XAttributeList444   CXX0XAttributeList (AttributeList *attrList, SourceRange range, bool hasAttr)
445     : AttrList(attrList), Range(range), HasAttr (hasAttr) {
446   }
CXX0XAttributeListCXX0XAttributeList447   CXX0XAttributeList ()
448     : AttrList(0), Range(), HasAttr(false) {
449   }
450 };
451 
452 /// ParsedAttributes - A collection of parsed attributes.  Currently
453 /// we don't differentiate between the various attribute syntaxes,
454 /// which is basically silly.
455 ///
456 /// Right now this is a very lightweight container, but the expectation
457 /// is that this will become significantly more serious.
458 class ParsedAttributes {
459 public:
ParsedAttributes(AttributeFactory & factory)460   ParsedAttributes(AttributeFactory &factory)
461     : pool(factory), list(0) {
462   }
463 
ParsedAttributes(ParsedAttributes & attrs)464   ParsedAttributes(ParsedAttributes &attrs)
465     : pool(attrs.pool), list(attrs.list) {
466     attrs.list = 0;
467   }
468 
getPool()469   AttributePool &getPool() const { return pool; }
470 
empty()471   bool empty() const { return list == 0; }
472 
add(AttributeList * newAttr)473   void add(AttributeList *newAttr) {
474     assert(newAttr);
475     assert(newAttr->getNext() == 0);
476     newAttr->setNext(list);
477     list = newAttr;
478   }
479 
addAll(AttributeList * newList)480   void addAll(AttributeList *newList) {
481     if (!newList) return;
482 
483     AttributeList *lastInNewList = newList;
484     while (AttributeList *next = lastInNewList->getNext())
485       lastInNewList = next;
486 
487     lastInNewList->setNext(list);
488     list = newList;
489   }
490 
set(AttributeList * newList)491   void set(AttributeList *newList) {
492     list = newList;
493   }
494 
takeAllFrom(ParsedAttributes & attrs)495   void takeAllFrom(ParsedAttributes &attrs) {
496     addAll(attrs.list);
497     attrs.list = 0;
498     pool.takeAllFrom(attrs.pool);
499   }
500 
clear()501   void clear() { list = 0; pool.clear(); }
getList()502   AttributeList *getList() const { return list; }
503 
504   /// Returns a reference to the attribute list.  Try not to introduce
505   /// dependencies on this method, it may not be long-lived.
getListRef()506   AttributeList *&getListRef() { return list; }
507 
508 
509   AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
510                         IdentifierInfo *scopeName, SourceLocation scopeLoc,
511                         IdentifierInfo *parmName, SourceLocation parmLoc,
512                         Expr **args, unsigned numArgs,
513                         bool declspec = false, bool cxx0x = false) {
514     AttributeList *attr =
515       pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc,
516                   args, numArgs, declspec, cxx0x);
517     add(attr);
518     return attr;
519   }
520 
521   AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
522                         IdentifierInfo *scopeName, SourceLocation scopeLoc,
523                         IdentifierInfo *parmName, SourceLocation parmLoc,
524                         const AvailabilityChange &introduced,
525                         const AvailabilityChange &deprecated,
526                         const AvailabilityChange &obsoleted,
527                         SourceLocation unavailable,
528                         const Expr *MessageExpr,
529                         bool declspec = false, bool cxx0x = false) {
530     AttributeList *attr =
531       pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc,
532                   introduced, deprecated, obsoleted, unavailable,
533                   MessageExpr,
534                   declspec, cxx0x);
535     add(attr);
536     return attr;
537   }
538 
addNewInteger(ASTContext & C,IdentifierInfo * name,SourceLocation loc,int arg)539   AttributeList *addNewInteger(ASTContext &C, IdentifierInfo *name,
540                                SourceLocation loc, int arg) {
541     AttributeList *attr =
542       pool.createIntegerAttribute(C, name, loc, arg);
543     add(attr);
544     return attr;
545   }
546 
547 
548 private:
549   mutable AttributePool pool;
550   AttributeList *list;
551 };
552 
553 }  // end namespace clang
554 
555 #endif
556