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 "clang/Basic/SourceLocation.h"
19 #include "clang/Basic/VersionTuple.h"
20 #include "clang/Sema/Ownership.h"
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/Support/Allocator.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 a syntactic attribute.
48 ///
49 /// For a GNU attribute, there are four forms of this construct:
50 ///
51 /// 1: __attribute__(( const )). ParmName/Args/NumArgs will all be unused.
52 /// 2: __attribute__(( mode(byte) )). ParmName used, Args/NumArgs unused.
53 /// 3: __attribute__(( format(printf, 1, 2) )). ParmName/Args/NumArgs all used.
54 /// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used.
55 ///
56 class AttributeList { // TODO: This should really be called ParsedAttribute
57 public:
58 /// The style used to specify an attribute.
59 enum Syntax {
60 /// __attribute__((...))
61 AS_GNU,
62 /// [[...]]
63 AS_CXX11,
64 /// __declspec(...)
65 AS_Declspec,
66 /// __ptr16, alignas(...), etc.
67 AS_Keyword
68 };
69 private:
70 IdentifierInfo *AttrName;
71 IdentifierInfo *ScopeName;
72 IdentifierInfo *ParmName;
73 SourceRange AttrRange;
74 SourceLocation ScopeLoc;
75 SourceLocation ParmLoc;
76 SourceLocation EllipsisLoc;
77
78 /// The number of expression arguments this attribute has.
79 /// The expressions themselves are stored after the object.
80 unsigned NumArgs : 16;
81
82 /// Corresponds to the Syntax enum.
83 unsigned SyntaxUsed : 2;
84
85 /// True if already diagnosed as invalid.
86 mutable unsigned Invalid : 1;
87
88 /// True if this attribute was used as a type attribute.
89 mutable unsigned UsedAsTypeAttr : 1;
90
91 /// True if this has the extra information associated with an
92 /// availability attribute.
93 unsigned IsAvailability : 1;
94
95 /// True if this has extra information associated with a
96 /// type_tag_for_datatype attribute.
97 unsigned IsTypeTagForDatatype : 1;
98
99 unsigned AttrKind : 8;
100
101 /// \brief The location of the 'unavailable' keyword in an
102 /// availability attribute.
103 SourceLocation UnavailableLoc;
104
105 const Expr *MessageExpr;
106
107 /// The next attribute in the current position.
108 AttributeList *NextInPosition;
109
110 /// The next attribute allocated in the current Pool.
111 AttributeList *NextInPool;
112
getArgsBuffer()113 Expr **getArgsBuffer() {
114 return reinterpret_cast<Expr**>(this+1);
115 }
getArgsBuffer()116 Expr * const *getArgsBuffer() const {
117 return reinterpret_cast<Expr* const *>(this+1);
118 }
119
120 enum AvailabilitySlot {
121 IntroducedSlot, DeprecatedSlot, ObsoletedSlot
122 };
123
getAvailabilitySlot(AvailabilitySlot index)124 AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) {
125 return reinterpret_cast<AvailabilityChange*>(this+1)[index];
126 }
getAvailabilitySlot(AvailabilitySlot index)127 const AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) const {
128 return reinterpret_cast<const AvailabilityChange*>(this+1)[index];
129 }
130
131 public:
132 struct TypeTagForDatatypeData {
133 ParsedType *MatchingCType;
134 unsigned LayoutCompatible : 1;
135 unsigned MustBeNull : 1;
136 };
137
138 private:
getTypeTagForDatatypeDataSlot()139 TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() {
140 return *reinterpret_cast<TypeTagForDatatypeData *>(this + 1);
141 }
142
getTypeTagForDatatypeDataSlot()143 const TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const {
144 return *reinterpret_cast<const TypeTagForDatatypeData *>(this + 1);
145 }
146
getTypeBuffer()147 ParsedType &getTypeBuffer() {
148 return *reinterpret_cast<ParsedType *>(this + 1);
149 }
150
getTypeBuffer()151 const ParsedType &getTypeBuffer() const {
152 return *reinterpret_cast<const ParsedType *>(this + 1);
153 }
154
155 AttributeList(const AttributeList &) LLVM_DELETED_FUNCTION;
156 void operator=(const AttributeList &) LLVM_DELETED_FUNCTION;
157 void operator delete(void *) LLVM_DELETED_FUNCTION;
158 ~AttributeList() LLVM_DELETED_FUNCTION;
159
160 size_t allocated_size() const;
161
162 /// 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,SourceLocation ellipsisLoc)163 AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
164 IdentifierInfo *scopeName, SourceLocation scopeLoc,
165 IdentifierInfo *parmName, SourceLocation parmLoc,
166 Expr **args, unsigned numArgs,
167 Syntax syntaxUsed, SourceLocation ellipsisLoc)
168 : AttrName(attrName), ScopeName(scopeName), ParmName(parmName),
169 AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
170 EllipsisLoc(ellipsisLoc), NumArgs(numArgs), SyntaxUsed(syntaxUsed),
171 Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
172 IsTypeTagForDatatype(false), NextInPosition(0), NextInPool(0) {
173 if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(Expr*));
174 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
175 }
176
177 /// 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)178 AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
179 IdentifierInfo *scopeName, SourceLocation scopeLoc,
180 IdentifierInfo *parmName, SourceLocation parmLoc,
181 const AvailabilityChange &introduced,
182 const AvailabilityChange &deprecated,
183 const AvailabilityChange &obsoleted,
184 SourceLocation unavailable,
185 const Expr *messageExpr,
186 Syntax syntaxUsed)
187 : AttrName(attrName), ScopeName(scopeName), ParmName(parmName),
188 AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc), EllipsisLoc(),
189 NumArgs(0), SyntaxUsed(syntaxUsed),
190 Invalid(false), UsedAsTypeAttr(false), IsAvailability(true),
191 IsTypeTagForDatatype(false),
192 UnavailableLoc(unavailable), MessageExpr(messageExpr),
193 NextInPosition(0), NextInPool(0) {
194 new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced);
195 new (&getAvailabilitySlot(DeprecatedSlot)) AvailabilityChange(deprecated);
196 new (&getAvailabilitySlot(ObsoletedSlot)) AvailabilityChange(obsoleted);
197 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
198 }
199
200 /// 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)201 AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
202 IdentifierInfo *scopeName, SourceLocation scopeLoc,
203 IdentifierInfo *argumentKindName,
204 SourceLocation argumentKindLoc,
205 ParsedType matchingCType, bool layoutCompatible,
206 bool mustBeNull, Syntax syntaxUsed)
207 : AttrName(attrName), ScopeName(scopeName), ParmName(argumentKindName),
208 AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(argumentKindLoc),
209 EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed),
210 Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
211 IsTypeTagForDatatype(true), NextInPosition(NULL), NextInPool(NULL) {
212 TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot();
213 new (&ExtraData.MatchingCType) ParsedType(matchingCType);
214 ExtraData.LayoutCompatible = layoutCompatible;
215 ExtraData.MustBeNull = mustBeNull;
216 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
217 }
218
219 /// Constructor for attributes with a single type argument.
AttributeList(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * parmName,SourceLocation parmLoc,ParsedType typeArg,Syntax syntaxUsed)220 AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
221 IdentifierInfo *scopeName, SourceLocation scopeLoc,
222 IdentifierInfo *parmName, SourceLocation parmLoc,
223 ParsedType typeArg, Syntax syntaxUsed)
224 : AttrName(attrName), ScopeName(scopeName), ParmName(parmName),
225 AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
226 EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false),
227 UsedAsTypeAttr(false), IsAvailability(false),
228 IsTypeTagForDatatype(false), NextInPosition(0), NextInPool(0) {
229 new (&getTypeBuffer()) ParsedType(typeArg);
230 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
231 }
232
233 friend class AttributePool;
234 friend class AttributeFactory;
235
236 public:
237 enum Kind {
238 #define PARSED_ATTR(NAME) AT_##NAME,
239 #include "clang/Sema/AttrParsedAttrList.inc"
240 #undef PARSED_ATTR
241 IgnoredAttribute,
242 UnknownAttribute
243 };
244
getName()245 IdentifierInfo *getName() const { return AttrName; }
getLoc()246 SourceLocation getLoc() const { return AttrRange.getBegin(); }
getRange()247 SourceRange getRange() const { return AttrRange; }
248
hasScope()249 bool hasScope() const { return ScopeName; }
getScopeName()250 IdentifierInfo *getScopeName() const { return ScopeName; }
getScopeLoc()251 SourceLocation getScopeLoc() const { return ScopeLoc; }
252
getParameterName()253 IdentifierInfo *getParameterName() const { return ParmName; }
getParameterLoc()254 SourceLocation getParameterLoc() const { return ParmLoc; }
255
isAlignasAttribute()256 bool isAlignasAttribute() const {
257 // FIXME: Use a better mechanism to determine this.
258 return getKind() == AT_Aligned && SyntaxUsed == AS_Keyword;
259 }
260
isDeclspecAttribute()261 bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
isCXX11Attribute()262 bool isCXX11Attribute() const {
263 return SyntaxUsed == AS_CXX11 || isAlignasAttribute();
264 }
isKeywordAttribute()265 bool isKeywordAttribute() const { return SyntaxUsed == AS_Keyword; }
266
isInvalid()267 bool isInvalid() const { return Invalid; }
268 void setInvalid(bool b = true) const { Invalid = b; }
269
isUsedAsTypeAttr()270 bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; }
setUsedAsTypeAttr()271 void setUsedAsTypeAttr() { UsedAsTypeAttr = true; }
272
isPackExpansion()273 bool isPackExpansion() const { return EllipsisLoc.isValid(); }
getEllipsisLoc()274 SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
275
getKind()276 Kind getKind() const { return Kind(AttrKind); }
277 static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope,
278 Syntax SyntaxUsed);
279
getNext()280 AttributeList *getNext() const { return NextInPosition; }
setNext(AttributeList * N)281 void setNext(AttributeList *N) { NextInPosition = N; }
282
283 /// getNumArgs - Return the number of actual arguments to this attribute.
getNumArgs()284 unsigned getNumArgs() const { return NumArgs; }
285
286 /// hasParameterOrArguments - Return true if this attribute has a parameter,
287 /// or has a non empty argument expression list.
hasParameterOrArguments()288 bool hasParameterOrArguments() const { return ParmName || NumArgs; }
289
290 /// getArg - Return the specified argument.
getArg(unsigned Arg)291 Expr *getArg(unsigned Arg) const {
292 assert(Arg < NumArgs && "Arg access out of range!");
293 return getArgsBuffer()[Arg];
294 }
295
296 class arg_iterator {
297 Expr * const *X;
298 unsigned Idx;
299 public:
arg_iterator(Expr * const * x,unsigned idx)300 arg_iterator(Expr * const *x, unsigned idx) : X(x), Idx(idx) {}
301
302 arg_iterator& operator++() {
303 ++Idx;
304 return *this;
305 }
306
307 bool operator==(const arg_iterator& I) const {
308 assert (X == I.X &&
309 "compared arg_iterators are for different argument lists");
310 return Idx == I.Idx;
311 }
312
313 bool operator!=(const arg_iterator& I) const {
314 return !operator==(I);
315 }
316
317 Expr* operator*() const {
318 return X[Idx];
319 }
320
getArgNum()321 unsigned getArgNum() const {
322 return Idx+1;
323 }
324 };
325
arg_begin()326 arg_iterator arg_begin() const {
327 return arg_iterator(getArgsBuffer(), 0);
328 }
329
arg_end()330 arg_iterator arg_end() const {
331 return arg_iterator(getArgsBuffer(), NumArgs);
332 }
333
getAvailabilityIntroduced()334 const AvailabilityChange &getAvailabilityIntroduced() const {
335 assert(getKind() == AT_Availability && "Not an availability attribute");
336 return getAvailabilitySlot(IntroducedSlot);
337 }
338
getAvailabilityDeprecated()339 const AvailabilityChange &getAvailabilityDeprecated() const {
340 assert(getKind() == AT_Availability && "Not an availability attribute");
341 return getAvailabilitySlot(DeprecatedSlot);
342 }
343
getAvailabilityObsoleted()344 const AvailabilityChange &getAvailabilityObsoleted() const {
345 assert(getKind() == AT_Availability && "Not an availability attribute");
346 return getAvailabilitySlot(ObsoletedSlot);
347 }
348
getUnavailableLoc()349 SourceLocation getUnavailableLoc() const {
350 assert(getKind() == AT_Availability && "Not an availability attribute");
351 return UnavailableLoc;
352 }
353
getMessageExpr()354 const Expr * getMessageExpr() const {
355 assert(getKind() == AT_Availability && "Not an availability attribute");
356 return MessageExpr;
357 }
358
getMatchingCType()359 const ParsedType &getMatchingCType() const {
360 assert(getKind() == AT_TypeTagForDatatype &&
361 "Not a type_tag_for_datatype attribute");
362 return *getTypeTagForDatatypeDataSlot().MatchingCType;
363 }
364
getLayoutCompatible()365 bool getLayoutCompatible() const {
366 assert(getKind() == AT_TypeTagForDatatype &&
367 "Not a type_tag_for_datatype attribute");
368 return getTypeTagForDatatypeDataSlot().LayoutCompatible;
369 }
370
getMustBeNull()371 bool getMustBeNull() const {
372 assert(getKind() == AT_TypeTagForDatatype &&
373 "Not a type_tag_for_datatype attribute");
374 return getTypeTagForDatatypeDataSlot().MustBeNull;
375 }
376
getTypeArg()377 const ParsedType &getTypeArg() const {
378 assert(getKind() == AT_VecTypeHint && "Not a type attribute");
379 return getTypeBuffer();
380 }
381
382 /// \brief Get an index into the attribute spelling list
383 /// defined in Attr.td. This index is used by an attribute
384 /// to pretty print itself.
385 unsigned getAttributeSpellingListIndex() const;
386 };
387
388 /// A factory, from which one makes pools, from which one creates
389 /// individual attributes which are deallocated with the pool.
390 ///
391 /// Note that it's tolerably cheap to create and destroy one of
392 /// these as long as you don't actually allocate anything in it.
393 class AttributeFactory {
394 public:
395 enum {
396 /// The required allocation size of an availability attribute,
397 /// which we want to ensure is a multiple of sizeof(void*).
398 AvailabilityAllocSize =
399 sizeof(AttributeList)
400 + ((3 * sizeof(AvailabilityChange) + sizeof(void*) - 1)
401 / sizeof(void*) * sizeof(void*)),
402 TypeTagForDatatypeAllocSize =
403 sizeof(AttributeList)
404 + (sizeof(AttributeList::TypeTagForDatatypeData) + sizeof(void *) - 1)
405 / sizeof(void*) * sizeof(void*)
406 };
407
408 private:
409 enum {
410 /// The number of free lists we want to be sure to support
411 /// inline. This is just enough that availability attributes
412 /// don't surpass it. It's actually very unlikely we'll see an
413 /// attribute that needs more than that; on x86-64 you'd need 10
414 /// expression arguments, and on i386 you'd need 19.
415 InlineFreeListsCapacity =
416 1 + (AvailabilityAllocSize - sizeof(AttributeList)) / sizeof(void*)
417 };
418
419 llvm::BumpPtrAllocator Alloc;
420
421 /// Free lists. The index is determined by the following formula:
422 /// (size - sizeof(AttributeList)) / sizeof(void*)
423 SmallVector<AttributeList*, InlineFreeListsCapacity> FreeLists;
424
425 // The following are the private interface used by AttributePool.
426 friend class AttributePool;
427
428 /// Allocate an attribute of the given size.
429 void *allocate(size_t size);
430
431 /// Reclaim all the attributes in the given pool chain, which is
432 /// non-empty. Note that the current implementation is safe
433 /// against reclaiming things which were not actually allocated
434 /// with the allocator, although of course it's important to make
435 /// sure that their allocator lives at least as long as this one.
436 void reclaimPool(AttributeList *head);
437
438 public:
439 AttributeFactory();
440 ~AttributeFactory();
441 };
442
443 class AttributePool {
444 AttributeFactory &Factory;
445 AttributeList *Head;
446
allocate(size_t size)447 void *allocate(size_t size) {
448 return Factory.allocate(size);
449 }
450
add(AttributeList * attr)451 AttributeList *add(AttributeList *attr) {
452 // We don't care about the order of the pool.
453 attr->NextInPool = Head;
454 Head = attr;
455 return attr;
456 }
457
458 void takePool(AttributeList *pool);
459
460 public:
461 /// Create a new pool for a factory.
AttributePool(AttributeFactory & factory)462 AttributePool(AttributeFactory &factory) : Factory(factory), Head(0) {}
463
464 /// Move the given pool's allocations to this pool.
AttributePool(AttributePool & pool)465 AttributePool(AttributePool &pool) : Factory(pool.Factory), Head(pool.Head) {
466 pool.Head = 0;
467 }
468
getFactory()469 AttributeFactory &getFactory() const { return Factory; }
470
clear()471 void clear() {
472 if (Head) {
473 Factory.reclaimPool(Head);
474 Head = 0;
475 }
476 }
477
478 /// Take the given pool's allocations and add them to this pool.
takeAllFrom(AttributePool & pool)479 void takeAllFrom(AttributePool &pool) {
480 if (pool.Head) {
481 takePool(pool.Head);
482 pool.Head = 0;
483 }
484 }
485
~AttributePool()486 ~AttributePool() {
487 if (Head) Factory.reclaimPool(Head);
488 }
489
490 AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
491 IdentifierInfo *scopeName, SourceLocation scopeLoc,
492 IdentifierInfo *parmName, SourceLocation parmLoc,
493 Expr **args, unsigned numArgs,
494 AttributeList::Syntax syntax,
495 SourceLocation ellipsisLoc = SourceLocation()) {
496 void *memory = allocate(sizeof(AttributeList)
497 + numArgs * sizeof(Expr*));
498 return add(new (memory) AttributeList(attrName, attrRange,
499 scopeName, scopeLoc,
500 parmName, parmLoc,
501 args, numArgs, syntax,
502 ellipsisLoc));
503 }
504
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)505 AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
506 IdentifierInfo *scopeName, SourceLocation scopeLoc,
507 IdentifierInfo *parmName, SourceLocation parmLoc,
508 const AvailabilityChange &introduced,
509 const AvailabilityChange &deprecated,
510 const AvailabilityChange &obsoleted,
511 SourceLocation unavailable,
512 const Expr *MessageExpr,
513 AttributeList::Syntax syntax) {
514 void *memory = allocate(AttributeFactory::AvailabilityAllocSize);
515 return add(new (memory) AttributeList(attrName, attrRange,
516 scopeName, scopeLoc,
517 parmName, parmLoc,
518 introduced, deprecated, obsoleted,
519 unavailable, MessageExpr, syntax));
520 }
521
522 AttributeList *createIntegerAttribute(ASTContext &C, IdentifierInfo *Name,
523 SourceLocation TokLoc, int Arg);
524
createTypeTagForDatatype(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * argumentKindName,SourceLocation argumentKindLoc,ParsedType matchingCType,bool layoutCompatible,bool mustBeNull,AttributeList::Syntax syntax)525 AttributeList *createTypeTagForDatatype(
526 IdentifierInfo *attrName, SourceRange attrRange,
527 IdentifierInfo *scopeName, SourceLocation scopeLoc,
528 IdentifierInfo *argumentKindName,
529 SourceLocation argumentKindLoc,
530 ParsedType matchingCType, bool layoutCompatible,
531 bool mustBeNull, AttributeList::Syntax syntax) {
532 void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize);
533 return add(new (memory) AttributeList(attrName, attrRange,
534 scopeName, scopeLoc,
535 argumentKindName, argumentKindLoc,
536 matchingCType, layoutCompatible,
537 mustBeNull, syntax));
538 }
539
createTypeAttribute(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * parmName,SourceLocation parmLoc,ParsedType typeArg,AttributeList::Syntax syntaxUsed)540 AttributeList *createTypeAttribute(
541 IdentifierInfo *attrName, SourceRange attrRange,
542 IdentifierInfo *scopeName, SourceLocation scopeLoc,
543 IdentifierInfo *parmName, SourceLocation parmLoc,
544 ParsedType typeArg, AttributeList::Syntax syntaxUsed) {
545 void *memory = allocate(sizeof(AttributeList) + sizeof(void *));
546 return add(new (memory) AttributeList(attrName, attrRange,
547 scopeName, scopeLoc,
548 parmName, parmLoc,
549 typeArg, syntaxUsed));
550 }
551 };
552
553 /// addAttributeLists - Add two AttributeLists together
554 /// The right-hand list is appended to the left-hand list, if any
555 /// A pointer to the joined list is returned.
556 /// Note: the lists are not left unmodified.
addAttributeLists(AttributeList * Left,AttributeList * Right)557 inline AttributeList *addAttributeLists(AttributeList *Left,
558 AttributeList *Right) {
559 if (!Left)
560 return Right;
561
562 AttributeList *next = Left, *prev;
563 do {
564 prev = next;
565 next = next->getNext();
566 } while (next);
567 prev->setNext(Right);
568 return Left;
569 }
570
571 /// CXX11AttributeList - A wrapper around a C++11 attribute list.
572 /// Stores, in addition to the list proper, whether or not an actual list was
573 /// (as opposed to an empty list, which may be ill-formed in some places) and
574 /// the source range of the list.
575 struct CXX11AttributeList {
576 AttributeList *AttrList;
577 SourceRange Range;
578 bool HasAttr;
CXX11AttributeListCXX11AttributeList579 CXX11AttributeList (AttributeList *attrList, SourceRange range, bool hasAttr)
580 : AttrList(attrList), Range(range), HasAttr (hasAttr) {
581 }
CXX11AttributeListCXX11AttributeList582 CXX11AttributeList ()
583 : AttrList(0), Range(), HasAttr(false) {
584 }
585 };
586
587 /// ParsedAttributes - A collection of parsed attributes. Currently
588 /// we don't differentiate between the various attribute syntaxes,
589 /// which is basically silly.
590 ///
591 /// Right now this is a very lightweight container, but the expectation
592 /// is that this will become significantly more serious.
593 class ParsedAttributes {
594 public:
ParsedAttributes(AttributeFactory & factory)595 ParsedAttributes(AttributeFactory &factory)
596 : pool(factory), list(0) {
597 }
598
ParsedAttributes(ParsedAttributes & attrs)599 ParsedAttributes(ParsedAttributes &attrs)
600 : pool(attrs.pool), list(attrs.list) {
601 attrs.list = 0;
602 }
603
getPool()604 AttributePool &getPool() const { return pool; }
605
empty()606 bool empty() const { return list == 0; }
607
add(AttributeList * newAttr)608 void add(AttributeList *newAttr) {
609 assert(newAttr);
610 assert(newAttr->getNext() == 0);
611 newAttr->setNext(list);
612 list = newAttr;
613 }
614
addAll(AttributeList * newList)615 void addAll(AttributeList *newList) {
616 if (!newList) return;
617
618 AttributeList *lastInNewList = newList;
619 while (AttributeList *next = lastInNewList->getNext())
620 lastInNewList = next;
621
622 lastInNewList->setNext(list);
623 list = newList;
624 }
625
set(AttributeList * newList)626 void set(AttributeList *newList) {
627 list = newList;
628 }
629
takeAllFrom(ParsedAttributes & attrs)630 void takeAllFrom(ParsedAttributes &attrs) {
631 addAll(attrs.list);
632 attrs.list = 0;
633 pool.takeAllFrom(attrs.pool);
634 }
635
clear()636 void clear() { list = 0; pool.clear(); }
getList()637 AttributeList *getList() const { return list; }
638
639 /// Returns a reference to the attribute list. Try not to introduce
640 /// dependencies on this method, it may not be long-lived.
getListRef()641 AttributeList *&getListRef() { return list; }
642
643 /// Add attribute with expression arguments.
644 AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
645 IdentifierInfo *scopeName, SourceLocation scopeLoc,
646 IdentifierInfo *parmName, SourceLocation parmLoc,
647 Expr **args, unsigned numArgs,
648 AttributeList::Syntax syntax,
649 SourceLocation ellipsisLoc = SourceLocation()) {
650 AttributeList *attr =
651 pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc,
652 args, numArgs, syntax, ellipsisLoc);
653 add(attr);
654 return attr;
655 }
656
657 /// 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)658 AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
659 IdentifierInfo *scopeName, SourceLocation scopeLoc,
660 IdentifierInfo *parmName, SourceLocation parmLoc,
661 const AvailabilityChange &introduced,
662 const AvailabilityChange &deprecated,
663 const AvailabilityChange &obsoleted,
664 SourceLocation unavailable,
665 const Expr *MessageExpr,
666 AttributeList::Syntax syntax) {
667 AttributeList *attr =
668 pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc,
669 introduced, deprecated, obsoleted, unavailable,
670 MessageExpr, syntax);
671 add(attr);
672 return attr;
673 }
674
675 /// 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)676 AttributeList *addNewTypeTagForDatatype(
677 IdentifierInfo *attrName, SourceRange attrRange,
678 IdentifierInfo *scopeName, SourceLocation scopeLoc,
679 IdentifierInfo *argumentKindName,
680 SourceLocation argumentKindLoc,
681 ParsedType matchingCType, bool layoutCompatible,
682 bool mustBeNull, AttributeList::Syntax syntax) {
683 AttributeList *attr =
684 pool.createTypeTagForDatatype(attrName, attrRange,
685 scopeName, scopeLoc,
686 argumentKindName, argumentKindLoc,
687 matchingCType, layoutCompatible,
688 mustBeNull, syntax);
689 add(attr);
690 return attr;
691 }
692
693 /// Add an attribute with a single type argument.
694 AttributeList *
addNewTypeAttr(IdentifierInfo * attrName,SourceRange attrRange,IdentifierInfo * scopeName,SourceLocation scopeLoc,IdentifierInfo * parmName,SourceLocation parmLoc,ParsedType typeArg,AttributeList::Syntax syntaxUsed)695 addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange,
696 IdentifierInfo *scopeName, SourceLocation scopeLoc,
697 IdentifierInfo *parmName, SourceLocation parmLoc,
698 ParsedType typeArg, AttributeList::Syntax syntaxUsed) {
699 AttributeList *attr =
700 pool.createTypeAttribute(attrName, attrRange, scopeName, scopeLoc,
701 parmName, parmLoc, typeArg, syntaxUsed);
702 add(attr);
703 return attr;
704 }
705
addNewInteger(ASTContext & C,IdentifierInfo * name,SourceLocation loc,int arg)706 AttributeList *addNewInteger(ASTContext &C, IdentifierInfo *name,
707 SourceLocation loc, int arg) {
708 AttributeList *attr =
709 pool.createIntegerAttribute(C, name, loc, arg);
710 add(attr);
711 return attr;
712 }
713
714
715 private:
716 mutable AttributePool pool;
717 AttributeList *list;
718 };
719
720 } // end namespace clang
721
722 #endif
723