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 "clang/Sema/Ownership.h"
23 #include <cassert>
24
25 namespace clang {
26 class ASTContext;
27 class IdentifierInfo;
28 class Expr;
29
30 /// \brief Represents information about a change in availability for
31 /// an entity, which is part of the encoding of the 'availability'
32 /// attribute.
33 struct AvailabilityChange {
34 /// \brief The location of the keyword indicating the kind of change.
35 SourceLocation KeywordLoc;
36
37 /// \brief The version number at which the change occurred.
38 VersionTuple Version;
39
40 /// \brief The source range covering the version number.
41 SourceRange VersionRange;
42
43 /// \brief Determine whether this availability change is valid.
isValidAvailabilityChange44 bool isValid() const { return !Version.empty(); }
45 };
46
47 /// AttributeList - Represents GCC's __attribute__ declaration. There are
48 /// 4 forms of this construct...they are:
49 ///
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.
54 ///
55 class AttributeList { // TODO: This should really be called ParsedAttribute
56 public:
57 /// The style used to specify an attribute.
58 enum Syntax {
59 AS_GNU,
60 AS_CXX11,
61 AS_Declspec,
62 // eg) __w64, __ptr32, etc. It is implied that an MSTypespec is also
63 // a declspec.
64 AS_MSTypespec
65 };
66 private:
67 IdentifierInfo *AttrName;
68 IdentifierInfo *ScopeName;
69 IdentifierInfo *ParmName;
70 SourceRange AttrRange;
71 SourceLocation ScopeLoc;
72 SourceLocation ParmLoc;
73
74 /// The number of expression arguments this attribute has.
75 /// The expressions themselves are stored after the object.
76 unsigned NumArgs : 16;
77
78 /// Corresponds to the Syntax enum.
79 unsigned SyntaxUsed : 2;
80
81 /// True if already diagnosed as invalid.
82 mutable unsigned Invalid : 1;
83
84 /// True if this attribute was used as a type attribute.
85 mutable unsigned UsedAsTypeAttr : 1;
86
87 /// True if this has the extra information associated with an
88 /// availability attribute.
89 unsigned IsAvailability : 1;
90
91 /// True if this has extra information associated with a
92 /// type_tag_for_datatype attribute.
93 unsigned IsTypeTagForDatatype : 1;
94
95 unsigned AttrKind : 8;
96
97 /// \brief The location of the 'unavailable' keyword in an
98 /// availability attribute.
99 SourceLocation UnavailableLoc;
100
101 const Expr *MessageExpr;
102
103 /// The next attribute in the current position.
104 AttributeList *NextInPosition;
105
106 /// The next attribute allocated in the current Pool.
107 AttributeList *NextInPool;
108
getArgsBuffer()109 Expr **getArgsBuffer() {
110 return reinterpret_cast<Expr**>(this+1);
111 }
getArgsBuffer()112 Expr * const *getArgsBuffer() const {
113 return reinterpret_cast<Expr* const *>(this+1);
114 }
115
116 enum AvailabilitySlot {
117 IntroducedSlot, DeprecatedSlot, ObsoletedSlot
118 };
119
getAvailabilitySlot(AvailabilitySlot index)120 AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) {
121 return reinterpret_cast<AvailabilityChange*>(this+1)[index];
122 }
getAvailabilitySlot(AvailabilitySlot index)123 const AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) const {
124 return reinterpret_cast<const AvailabilityChange*>(this+1)[index];
125 }
126
127 public:
128 struct TypeTagForDatatypeData {
129 ParsedType *MatchingCType;
130 unsigned LayoutCompatible : 1;
131 unsigned MustBeNull : 1;
132 };
133
134 private:
getTypeTagForDatatypeDataSlot()135 TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() {
136 return *reinterpret_cast<TypeTagForDatatypeData *>(this + 1);
137 }
138
getTypeTagForDatatypeDataSlot()139 const TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const {
140 return *reinterpret_cast<const TypeTagForDatatypeData *>(this + 1);
141 }
142
143 AttributeList(const AttributeList &); // DO NOT IMPLEMENT
144 void operator=(const AttributeList &); // DO NOT IMPLEMENT
145 void operator delete(void *); // DO NOT IMPLEMENT
146 ~AttributeList(); // DO NOT IMPLEMENT
147
148 size_t allocated_size() const;
149
150 /// Constructor for attributes with expression arguments.
AttributeList(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * parmName,SourceLocation parmLoc,Expr ** args,unsigned numArgs,Syntax syntaxUsed)151 AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
152 IdentifierInfo *scopeName, SourceLocation scopeLoc,
153 IdentifierInfo *parmName, SourceLocation parmLoc,
154 Expr **args, unsigned numArgs,
155 Syntax syntaxUsed)
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);
163 }
164
165 /// Constructor for availability attributes.
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,Syntax syntaxUsed)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,
174 Syntax syntaxUsed)
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);
186 }
187
188 /// Constructor for type_tag_for_datatype attribute.
AttributeList(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * argumentKindName,SourceLocation argumentKindLoc,ParsedType matchingCType,bool layoutCompatible,bool mustBeNull,Syntax syntaxUsed)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);
205 }
206
207 friend class AttributePool;
208 friend class AttributeFactory;
209
210 public:
211 enum Kind {
212 #define PARSED_ATTR(NAME) AT_##NAME,
213 #include "clang/Sema/AttrParsedAttrList.inc"
214 #undef PARSED_ATTR
215 IgnoredAttribute,
216 UnknownAttribute
217 };
218
getName()219 IdentifierInfo *getName() const { return AttrName; }
getLoc()220 SourceLocation getLoc() const { return AttrRange.getBegin(); }
getRange()221 SourceRange getRange() const { return AttrRange; }
222
hasScope()223 bool hasScope() const { return ScopeName; }
getScopeName()224 IdentifierInfo *getScopeName() const { return ScopeName; }
getScopeLoc()225 SourceLocation getScopeLoc() const { return ScopeLoc; }
226
getParameterName()227 IdentifierInfo *getParameterName() const { return ParmName; }
getParameterLoc()228 SourceLocation getParameterLoc() const { return ParmLoc; }
229
230 /// Returns true if the attribute is a pure __declspec or a synthesized
231 /// declspec representing a type specification (like __w64 or __ptr32).
isDeclspecAttribute()232 bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec ||
233 SyntaxUsed == AS_MSTypespec; }
isCXX0XAttribute()234 bool isCXX0XAttribute() const { return SyntaxUsed == AS_CXX11; }
isMSTypespecAttribute()235 bool isMSTypespecAttribute() const { return SyntaxUsed == AS_MSTypespec; }
236
isInvalid()237 bool isInvalid() const { return Invalid; }
238 void setInvalid(bool b = true) const { Invalid = b; }
239
isUsedAsTypeAttr()240 bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; }
setUsedAsTypeAttr()241 void setUsedAsTypeAttr() { UsedAsTypeAttr = true; }
242
getKind()243 Kind getKind() const { return Kind(AttrKind); }
244 static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope,
245 Syntax SyntaxUsed);
246
getNext()247 AttributeList *getNext() const { return NextInPosition; }
setNext(AttributeList * N)248 void setNext(AttributeList *N) { NextInPosition = N; }
249
250 /// getNumArgs - Return the number of actual arguments to this attribute.
getNumArgs()251 unsigned getNumArgs() const { return NumArgs; }
252
253 /// hasParameterOrArguments - Return true if this attribute has a parameter,
254 /// or has a non empty argument expression list.
hasParameterOrArguments()255 bool hasParameterOrArguments() const { return ParmName || NumArgs; }
256
257 /// getArg - Return the specified argument.
getArg(unsigned Arg)258 Expr *getArg(unsigned Arg) const {
259 assert(Arg < NumArgs && "Arg access out of range!");
260 return getArgsBuffer()[Arg];
261 }
262
263 class arg_iterator {
264 Expr * const *X;
265 unsigned Idx;
266 public:
arg_iterator(Expr * const * x,unsigned idx)267 arg_iterator(Expr * const *x, unsigned idx) : X(x), Idx(idx) {}
268
269 arg_iterator& operator++() {
270 ++Idx;
271 return *this;
272 }
273
274 bool operator==(const arg_iterator& I) const {
275 assert (X == I.X &&
276 "compared arg_iterators are for different argument lists");
277 return Idx == I.Idx;
278 }
279
280 bool operator!=(const arg_iterator& I) const {
281 return !operator==(I);
282 }
283
284 Expr* operator*() const {
285 return X[Idx];
286 }
287
getArgNum()288 unsigned getArgNum() const {
289 return Idx+1;
290 }
291 };
292
arg_begin()293 arg_iterator arg_begin() const {
294 return arg_iterator(getArgsBuffer(), 0);
295 }
296
arg_end()297 arg_iterator arg_end() const {
298 return arg_iterator(getArgsBuffer(), NumArgs);
299 }
300
getAvailabilityIntroduced()301 const AvailabilityChange &getAvailabilityIntroduced() const {
302 assert(getKind() == AT_Availability && "Not an availability attribute");
303 return getAvailabilitySlot(IntroducedSlot);
304 }
305
getAvailabilityDeprecated()306 const AvailabilityChange &getAvailabilityDeprecated() const {
307 assert(getKind() == AT_Availability && "Not an availability attribute");
308 return getAvailabilitySlot(DeprecatedSlot);
309 }
310
getAvailabilityObsoleted()311 const AvailabilityChange &getAvailabilityObsoleted() const {
312 assert(getKind() == AT_Availability && "Not an availability attribute");
313 return getAvailabilitySlot(ObsoletedSlot);
314 }
315
getUnavailableLoc()316 SourceLocation getUnavailableLoc() const {
317 assert(getKind() == AT_Availability && "Not an availability attribute");
318 return UnavailableLoc;
319 }
320
getMessageExpr()321 const Expr * getMessageExpr() const {
322 assert(getKind() == AT_Availability && "Not an availability attribute");
323 return MessageExpr;
324 }
325
getMatchingCType()326 const ParsedType &getMatchingCType() const {
327 assert(getKind() == AT_TypeTagForDatatype &&
328 "Not a type_tag_for_datatype attribute");
329 return *getTypeTagForDatatypeDataSlot().MatchingCType;
330 }
331
getLayoutCompatible()332 bool getLayoutCompatible() const {
333 assert(getKind() == AT_TypeTagForDatatype &&
334 "Not a type_tag_for_datatype attribute");
335 return getTypeTagForDatatypeDataSlot().LayoutCompatible;
336 }
337
getMustBeNull()338 bool getMustBeNull() const {
339 assert(getKind() == AT_TypeTagForDatatype &&
340 "Not a type_tag_for_datatype attribute");
341 return getTypeTagForDatatypeDataSlot().MustBeNull;
342 }
343 };
344
345 /// A factory, from which one makes pools, from which one creates
346 /// individual attributes which are deallocated with the pool.
347 ///
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 {
351 public:
352 enum {
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*)
363 };
364
365 private:
366 enum {
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*)
374 };
375
376 llvm::BumpPtrAllocator Alloc;
377
378 /// Free lists. The index is determined by the following formula:
379 /// (size - sizeof(AttributeList)) / sizeof(void*)
380 SmallVector<AttributeList*, InlineFreeListsCapacity> FreeLists;
381
382 // The following are the private interface used by AttributePool.
383 friend class AttributePool;
384
385 /// Allocate an attribute of the given size.
386 void *allocate(size_t size);
387
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);
394
395 public:
396 AttributeFactory();
397 ~AttributeFactory();
398 };
399
400 class AttributePool {
401 AttributeFactory &Factory;
402 AttributeList *Head;
403
allocate(size_t size)404 void *allocate(size_t size) {
405 return Factory.allocate(size);
406 }
407
add(AttributeList * attr)408 AttributeList *add(AttributeList *attr) {
409 // We don't care about the order of the pool.
410 attr->NextInPool = Head;
411 Head = attr;
412 return attr;
413 }
414
415 void takePool(AttributeList *pool);
416
417 public:
418 /// Create a new pool for a factory.
AttributePool(AttributeFactory & factory)419 AttributePool(AttributeFactory &factory) : Factory(factory), Head(0) {}
420
421 /// Move the given pool's allocations to this pool.
AttributePool(AttributePool & pool)422 AttributePool(AttributePool &pool) : Factory(pool.Factory), Head(pool.Head) {
423 pool.Head = 0;
424 }
425
getFactory()426 AttributeFactory &getFactory() const { return Factory; }
427
clear()428 void clear() {
429 if (Head) {
430 Factory.reclaimPool(Head);
431 Head = 0;
432 }
433 }
434
435 /// Take the given pool's allocations and add them to this pool.
takeAllFrom(AttributePool & pool)436 void takeAllFrom(AttributePool &pool) {
437 if (pool.Head) {
438 takePool(pool.Head);
439 pool.Head = 0;
440 }
441 }
442
~AttributePool()443 ~AttributePool() {
444 if (Head) Factory.reclaimPool(Head);
445 }
446
create(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * parmName,SourceLocation parmLoc,Expr ** args,unsigned numArgs,AttributeList::Syntax syntax)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,
455 scopeName, scopeLoc,
456 parmName, parmLoc,
457 args, numArgs, syntax));
458 }
459
create(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,AttributeList::Syntax 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,
471 scopeName, scopeLoc,
472 parmName, parmLoc,
473 introduced, deprecated, obsoleted,
474 unavailable, MessageExpr, syntax));
475 }
476
477 AttributeList *createIntegerAttribute(ASTContext &C, IdentifierInfo *Name,
478 SourceLocation TokLoc, int Arg);
479
createTypeTagForDatatype(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * argumentKindName,SourceLocation argumentKindLoc,ParsedType matchingCType,bool layoutCompatible,bool mustBeNull,AttributeList::Syntax syntax)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,
489 scopeName, scopeLoc,
490 argumentKindName, argumentKindLoc,
491 matchingCType, layoutCompatible,
492 mustBeNull, syntax));
493 }
494 };
495
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.
addAttributeLists(AttributeList * Left,AttributeList * Right)500 inline AttributeList *addAttributeLists(AttributeList *Left,
501 AttributeList *Right) {
502 if (!Left)
503 return Right;
504
505 AttributeList *next = Left, *prev;
506 do {
507 prev = next;
508 next = next->getNext();
509 } while (next);
510 prev->setNext(Right);
511 return Left;
512 }
513
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;
520 SourceRange Range;
521 bool HasAttr;
CXX0XAttributeListCXX0XAttributeList522 CXX0XAttributeList (AttributeList *attrList, SourceRange range, bool hasAttr)
523 : AttrList(attrList), Range(range), HasAttr (hasAttr) {
524 }
CXX0XAttributeListCXX0XAttributeList525 CXX0XAttributeList ()
526 : AttrList(0), Range(), HasAttr(false) {
527 }
528 };
529
530 /// ParsedAttributes - A collection of parsed attributes. Currently
531 /// we don't differentiate between the various attribute syntaxes,
532 /// which is basically silly.
533 ///
534 /// Right now this is a very lightweight container, but the expectation
535 /// is that this will become significantly more serious.
536 class ParsedAttributes {
537 public:
ParsedAttributes(AttributeFactory & factory)538 ParsedAttributes(AttributeFactory &factory)
539 : pool(factory), list(0) {
540 }
541
ParsedAttributes(ParsedAttributes & attrs)542 ParsedAttributes(ParsedAttributes &attrs)
543 : pool(attrs.pool), list(attrs.list) {
544 attrs.list = 0;
545 }
546
getPool()547 AttributePool &getPool() const { return pool; }
548
empty()549 bool empty() const { return list == 0; }
550
add(AttributeList * newAttr)551 void add(AttributeList *newAttr) {
552 assert(newAttr);
553 assert(newAttr->getNext() == 0);
554 newAttr->setNext(list);
555 list = newAttr;
556 }
557
addAll(AttributeList * newList)558 void addAll(AttributeList *newList) {
559 if (!newList) return;
560
561 AttributeList *lastInNewList = newList;
562 while (AttributeList *next = lastInNewList->getNext())
563 lastInNewList = next;
564
565 lastInNewList->setNext(list);
566 list = newList;
567 }
568
set(AttributeList * newList)569 void set(AttributeList *newList) {
570 list = newList;
571 }
572
takeAllFrom(ParsedAttributes & attrs)573 void takeAllFrom(ParsedAttributes &attrs) {
574 addAll(attrs.list);
575 attrs.list = 0;
576 pool.takeAllFrom(attrs.pool);
577 }
578
clear()579 void clear() { list = 0; pool.clear(); }
getList()580 AttributeList *getList() const { return list; }
581
582 /// Returns a reference to the attribute list. Try not to introduce
583 /// dependencies on this method, it may not be long-lived.
getListRef()584 AttributeList *&getListRef() { return list; }
585
586 /// Add attribute with expression arguments.
addNew(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * parmName,SourceLocation parmLoc,Expr ** args,unsigned numArgs,AttributeList::Syntax syntax)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);
595 add(attr);
596 return attr;
597 }
598
599 /// Add availability attribute.
addNew(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,AttributeList::Syntax syntax)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);
613 add(attr);
614 return attr;
615 }
616
617 /// Add type_tag_for_datatype attribute.
addNewTypeTagForDatatype(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * argumentKindName,SourceLocation argumentKindLoc,ParsedType matchingCType,bool layoutCompatible,bool mustBeNull,AttributeList::Syntax syntax)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,
627 scopeName, scopeLoc,
628 argumentKindName, argumentKindLoc,
629 matchingCType, layoutCompatible,
630 mustBeNull, syntax);
631 add(attr);
632 return attr;
633 }
634
addNewInteger(ASTContext & C,IdentifierInfo * name,SourceLocation loc,int arg)635 AttributeList *addNewInteger(ASTContext &C, IdentifierInfo *name,
636 SourceLocation loc, int arg) {
637 AttributeList *attr =
638 pool.createIntegerAttribute(C, name, loc, arg);
639 add(attr);
640 return attr;
641 }
642
643
644 private:
645 mutable AttributePool pool;
646 AttributeList *list;
647 };
648
649 } // end namespace clang
650
651 #endif
652