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