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