1 //===--- AttributeList.h - Parsed attribute sets ----------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the AttributeList class, which is used to collect
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CLANG_SEMA_ATTRIBUTELIST_H
16 #define LLVM_CLANG_SEMA_ATTRIBUTELIST_H
18 #include "clang/Basic/SourceLocation.h"
19 #include "clang/Basic/TargetInfo.h"
20 #include "clang/Basic/VersionTuple.h"
21 #include "clang/Sema/Ownership.h"
22 #include "llvm/ADT/PointerUnion.h"
23 #include "llvm/ADT/SmallVector.h"
24 #include "llvm/Support/Allocator.h"
32 /// \brief Represents information about a change in availability for
33 /// an entity, which is part of the encoding of the 'availability'
35 struct AvailabilityChange {
36 /// \brief The location of the keyword indicating the kind of change.
37 SourceLocation KeywordLoc;
39 /// \brief The version number at which the change occurred.
42 /// \brief The source range covering the version number.
43 SourceRange VersionRange;
45 /// \brief Determine whether this availability change is valid.
46 bool isValid() const { return !Version.empty(); }
49 /// \brief Wraps an identifier and optional source location for the identifier.
50 struct IdentifierLoc {
52 IdentifierInfo *Ident;
54 static IdentifierLoc *create(ASTContext &Ctx, SourceLocation Loc,
55 IdentifierInfo *Ident);
58 /// \brief A union of the various pointer types that can be passed to an
59 /// AttributeList as an argument.
60 typedef llvm::PointerUnion<Expr*, IdentifierLoc*> ArgsUnion;
61 typedef llvm::SmallVector<ArgsUnion, 12U> ArgsVector;
63 /// AttributeList - Represents a syntactic attribute.
65 /// For a GNU attribute, there are four forms of this construct:
67 /// 1: __attribute__(( const )). ParmName/Args/NumArgs will all be unused.
68 /// 2: __attribute__(( mode(byte) )). ParmName used, Args/NumArgs unused.
69 /// 3: __attribute__(( format(printf, 1, 2) )). ParmName/Args/NumArgs all used.
70 /// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used.
72 class AttributeList { // TODO: This should really be called ParsedAttribute
74 /// The style used to specify an attribute.
76 /// __attribute__((...))
82 /// __ptr16, alignas(...), etc.
84 /// Context-sensitive version of a keyword attribute.
85 AS_ContextSensitiveKeyword,
91 IdentifierInfo *AttrName;
92 IdentifierInfo *ScopeName;
93 SourceRange AttrRange;
94 SourceLocation ScopeLoc;
95 SourceLocation EllipsisLoc;
97 /// The number of expression arguments this attribute has.
98 /// The expressions themselves are stored after the object.
99 unsigned NumArgs : 15;
101 /// Corresponds to the Syntax enum.
102 unsigned SyntaxUsed : 3;
104 /// True if already diagnosed as invalid.
105 mutable unsigned Invalid : 1;
107 /// True if this attribute was used as a type attribute.
108 mutable unsigned UsedAsTypeAttr : 1;
110 /// True if this has the extra information associated with an
111 /// availability attribute.
112 unsigned IsAvailability : 1;
114 /// True if this has extra information associated with a
115 /// type_tag_for_datatype attribute.
116 unsigned IsTypeTagForDatatype : 1;
118 /// True if this has extra information associated with a
119 /// Microsoft __delcspec(property) attribute.
120 unsigned IsProperty : 1;
122 /// True if this has a ParsedType
123 unsigned HasParsedType : 1;
125 unsigned AttrKind : 8;
127 /// \brief The location of the 'unavailable' keyword in an
128 /// availability attribute.
129 SourceLocation UnavailableLoc;
131 const Expr *MessageExpr;
133 /// The next attribute in the current position.
134 AttributeList *NextInPosition;
136 /// The next attribute allocated in the current Pool.
137 AttributeList *NextInPool;
139 /// Arguments, if any, are stored immediately following the object.
140 ArgsUnion *getArgsBuffer() { return reinterpret_cast<ArgsUnion *>(this + 1); }
141 ArgsUnion const *getArgsBuffer() const {
142 return reinterpret_cast<ArgsUnion const *>(this + 1);
145 enum AvailabilitySlot {
146 IntroducedSlot, DeprecatedSlot, ObsoletedSlot
149 /// Availability information is stored immediately following the arguments,
150 /// if any, at the end of the object.
151 AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) {
152 return reinterpret_cast<AvailabilityChange*>(getArgsBuffer()
155 const AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) const {
156 return reinterpret_cast<const AvailabilityChange*>(getArgsBuffer()
161 struct TypeTagForDatatypeData {
162 ParsedType *MatchingCType;
163 unsigned LayoutCompatible : 1;
164 unsigned MustBeNull : 1;
166 struct PropertyData {
167 IdentifierInfo *GetterId, *SetterId;
168 PropertyData(IdentifierInfo *getterId, IdentifierInfo *setterId)
169 : GetterId(getterId), SetterId(setterId) {}
173 /// Type tag information is stored immediately following the arguments, if
174 /// any, at the end of the object. They are mutually exlusive with
175 /// availability slots.
176 TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() {
177 return *reinterpret_cast<TypeTagForDatatypeData*>(getArgsBuffer()+NumArgs);
180 const TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const {
181 return *reinterpret_cast<const TypeTagForDatatypeData*>(getArgsBuffer()
185 /// The type buffer immediately follows the object and are mutually exclusive
187 ParsedType &getTypeBuffer() {
188 return *reinterpret_cast<ParsedType *>(this + 1);
191 const ParsedType &getTypeBuffer() const {
192 return *reinterpret_cast<const ParsedType *>(this + 1);
195 /// The property data immediately follows the object is is mutually exclusive
197 PropertyData &getPropertyDataBuffer() {
199 return *reinterpret_cast<PropertyData*>(this + 1);
202 const PropertyData &getPropertyDataBuffer() const {
204 return *reinterpret_cast<const PropertyData*>(this + 1);
207 AttributeList(const AttributeList &) = delete;
208 void operator=(const AttributeList &) = delete;
209 void operator delete(void *) = delete;
210 ~AttributeList() = delete;
212 size_t allocated_size() const;
214 /// Constructor for attributes with expression arguments.
215 AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
216 IdentifierInfo *scopeName, SourceLocation scopeLoc,
217 ArgsUnion *args, unsigned numArgs,
218 Syntax syntaxUsed, SourceLocation ellipsisLoc)
219 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
220 ScopeLoc(scopeLoc), EllipsisLoc(ellipsisLoc), NumArgs(numArgs),
221 SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false),
222 IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false),
223 HasParsedType(false), NextInPosition(nullptr), NextInPool(nullptr) {
224 if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion));
225 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
228 /// Constructor for availability attributes.
229 AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
230 IdentifierInfo *scopeName, SourceLocation scopeLoc,
231 IdentifierLoc *Parm, const AvailabilityChange &introduced,
232 const AvailabilityChange &deprecated,
233 const AvailabilityChange &obsoleted,
234 SourceLocation unavailable,
235 const Expr *messageExpr,
237 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
238 ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed),
239 Invalid(false), UsedAsTypeAttr(false), IsAvailability(true),
240 IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
241 UnavailableLoc(unavailable), MessageExpr(messageExpr),
242 NextInPosition(nullptr), NextInPool(nullptr) {
243 ArgsUnion PVal(Parm);
244 memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
245 new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced);
246 new (&getAvailabilitySlot(DeprecatedSlot)) AvailabilityChange(deprecated);
247 new (&getAvailabilitySlot(ObsoletedSlot)) AvailabilityChange(obsoleted);
248 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
251 /// Constructor for objc_bridge_related attributes.
252 AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
253 IdentifierInfo *scopeName, SourceLocation scopeLoc,
254 IdentifierLoc *Parm1,
255 IdentifierLoc *Parm2,
256 IdentifierLoc *Parm3,
258 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
259 ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(3), SyntaxUsed(syntaxUsed),
260 Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
261 IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
262 NextInPosition(nullptr), NextInPool(nullptr) {
264 Args.push_back(Parm1);
265 Args.push_back(Parm2);
266 Args.push_back(Parm3);
267 memcpy(getArgsBuffer(), &Args[0], 3 * sizeof(ArgsUnion));
268 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
271 /// Constructor for type_tag_for_datatype attribute.
272 AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
273 IdentifierInfo *scopeName, SourceLocation scopeLoc,
274 IdentifierLoc *ArgKind, ParsedType matchingCType,
275 bool layoutCompatible, bool mustBeNull, Syntax syntaxUsed)
276 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
277 ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed),
278 Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
279 IsTypeTagForDatatype(true), IsProperty(false), HasParsedType(false),
280 NextInPosition(nullptr), NextInPool(nullptr) {
281 ArgsUnion PVal(ArgKind);
282 memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
283 TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot();
284 new (&ExtraData.MatchingCType) ParsedType(matchingCType);
285 ExtraData.LayoutCompatible = layoutCompatible;
286 ExtraData.MustBeNull = mustBeNull;
287 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
290 /// Constructor for attributes with a single type argument.
291 AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
292 IdentifierInfo *scopeName, SourceLocation scopeLoc,
293 ParsedType typeArg, Syntax syntaxUsed)
294 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
295 ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed),
296 Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
297 IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(true),
298 NextInPosition(nullptr), NextInPool(nullptr) {
299 new (&getTypeBuffer()) ParsedType(typeArg);
300 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
303 /// Constructor for microsoft __declspec(property) attribute.
304 AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
305 IdentifierInfo *scopeName, SourceLocation scopeLoc,
306 IdentifierInfo *getterId, IdentifierInfo *setterId,
308 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
309 ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed),
310 Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
311 IsTypeTagForDatatype(false), IsProperty(true), HasParsedType(false),
312 NextInPosition(nullptr), NextInPool(nullptr) {
313 new (&getPropertyDataBuffer()) PropertyData(getterId, setterId);
314 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
317 friend class AttributePool;
318 friend class AttributeFactory;
322 #define PARSED_ATTR(NAME) AT_##NAME,
323 #include "clang/Sema/AttrParsedAttrList.inc"
329 IdentifierInfo *getName() const { return AttrName; }
330 SourceLocation getLoc() const { return AttrRange.getBegin(); }
331 SourceRange getRange() const { return AttrRange; }
333 bool hasScope() const { return ScopeName; }
334 IdentifierInfo *getScopeName() const { return ScopeName; }
335 SourceLocation getScopeLoc() const { return ScopeLoc; }
337 bool hasParsedType() const { return HasParsedType; }
339 /// Is this the Microsoft __declspec(property) attribute?
340 bool isDeclspecPropertyAttribute() const {
344 bool isAlignasAttribute() const {
345 // FIXME: Use a better mechanism to determine this.
346 return getKind() == AT_Aligned && isKeywordAttribute();
349 bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
350 bool isCXX11Attribute() const {
351 return SyntaxUsed == AS_CXX11 || isAlignasAttribute();
353 bool isKeywordAttribute() const {
354 return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword;
357 bool isContextSensitiveKeywordAttribute() const {
358 return SyntaxUsed == AS_ContextSensitiveKeyword;
361 bool isInvalid() const { return Invalid; }
362 void setInvalid(bool b = true) const { Invalid = b; }
364 bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; }
365 void setUsedAsTypeAttr() { UsedAsTypeAttr = true; }
367 bool isPackExpansion() const { return EllipsisLoc.isValid(); }
368 SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
370 Kind getKind() const { return Kind(AttrKind); }
371 static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope,
374 AttributeList *getNext() const { return NextInPosition; }
375 void setNext(AttributeList *N) { NextInPosition = N; }
377 /// getNumArgs - Return the number of actual arguments to this attribute.
378 unsigned getNumArgs() const { return NumArgs; }
380 /// getArg - Return the specified argument.
381 ArgsUnion getArg(unsigned Arg) const {
382 assert(Arg < NumArgs && "Arg access out of range!");
383 return getArgsBuffer()[Arg];
386 bool isArgExpr(unsigned Arg) const {
387 return Arg < NumArgs && getArg(Arg).is<Expr*>();
389 Expr *getArgAsExpr(unsigned Arg) const {
390 return getArg(Arg).get<Expr*>();
393 bool isArgIdent(unsigned Arg) const {
394 return Arg < NumArgs && getArg(Arg).is<IdentifierLoc*>();
396 IdentifierLoc *getArgAsIdent(unsigned Arg) const {
397 return getArg(Arg).get<IdentifierLoc*>();
400 const AvailabilityChange &getAvailabilityIntroduced() const {
401 assert(getKind() == AT_Availability && "Not an availability attribute");
402 return getAvailabilitySlot(IntroducedSlot);
405 const AvailabilityChange &getAvailabilityDeprecated() const {
406 assert(getKind() == AT_Availability && "Not an availability attribute");
407 return getAvailabilitySlot(DeprecatedSlot);
410 const AvailabilityChange &getAvailabilityObsoleted() const {
411 assert(getKind() == AT_Availability && "Not an availability attribute");
412 return getAvailabilitySlot(ObsoletedSlot);
415 SourceLocation getUnavailableLoc() const {
416 assert(getKind() == AT_Availability && "Not an availability attribute");
417 return UnavailableLoc;
420 const Expr * getMessageExpr() const {
421 assert(getKind() == AT_Availability && "Not an availability attribute");
425 const ParsedType &getMatchingCType() const {
426 assert(getKind() == AT_TypeTagForDatatype &&
427 "Not a type_tag_for_datatype attribute");
428 return *getTypeTagForDatatypeDataSlot().MatchingCType;
431 bool getLayoutCompatible() const {
432 assert(getKind() == AT_TypeTagForDatatype &&
433 "Not a type_tag_for_datatype attribute");
434 return getTypeTagForDatatypeDataSlot().LayoutCompatible;
437 bool getMustBeNull() const {
438 assert(getKind() == AT_TypeTagForDatatype &&
439 "Not a type_tag_for_datatype attribute");
440 return getTypeTagForDatatypeDataSlot().MustBeNull;
443 const ParsedType &getTypeArg() const {
444 assert(HasParsedType && "Not a type attribute");
445 return getTypeBuffer();
448 const PropertyData &getPropertyData() const {
449 assert(isDeclspecPropertyAttribute() && "Not a __delcspec(property) attribute");
450 return getPropertyDataBuffer();
453 /// \brief Get an index into the attribute spelling list
454 /// defined in Attr.td. This index is used by an attribute
455 /// to pretty print itself.
456 unsigned getAttributeSpellingListIndex() const;
458 bool isTargetSpecificAttr() const;
459 bool isTypeAttr() const;
461 bool hasCustomParsing() const;
462 unsigned getMinArgs() const;
463 unsigned getMaxArgs() const;
464 bool hasVariadicArg() const;
465 bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const;
466 bool diagnoseLangOpts(class Sema &S) const;
467 bool existsInTarget(const TargetInfo &Target) const;
468 bool isKnownToGCC() const;
470 /// \brief If the parsed attribute has a semantic equivalent, and it would
471 /// have a semantic Spelling enumeration (due to having semantically-distinct
472 /// spelling variations), return the value of that semantic spelling. If the
473 /// parsed attribute does not have a semantic equivalent, or would not have
474 /// a Spelling enumeration, the value UINT_MAX is returned.
475 unsigned getSemanticSpelling() const;
478 /// A factory, from which one makes pools, from which one creates
479 /// individual attributes which are deallocated with the pool.
481 /// Note that it's tolerably cheap to create and destroy one of
482 /// these as long as you don't actually allocate anything in it.
483 class AttributeFactory {
486 /// The required allocation size of an availability attribute,
487 /// which we want to ensure is a multiple of sizeof(void*).
488 AvailabilityAllocSize =
489 sizeof(AttributeList)
490 + ((3 * sizeof(AvailabilityChange) + sizeof(void*) +
491 sizeof(ArgsUnion) - 1)
492 / sizeof(void*) * sizeof(void*)),
493 TypeTagForDatatypeAllocSize =
494 sizeof(AttributeList)
495 + (sizeof(AttributeList::TypeTagForDatatypeData) + sizeof(void *) +
496 sizeof(ArgsUnion) - 1)
497 / sizeof(void*) * sizeof(void*),
499 sizeof(AttributeList)
500 + (sizeof(AttributeList::PropertyData) + sizeof(void *) - 1)
501 / sizeof(void*) * sizeof(void*)
506 /// The number of free lists we want to be sure to support
507 /// inline. This is just enough that availability attributes
508 /// don't surpass it. It's actually very unlikely we'll see an
509 /// attribute that needs more than that; on x86-64 you'd need 10
510 /// expression arguments, and on i386 you'd need 19.
511 InlineFreeListsCapacity =
512 1 + (AvailabilityAllocSize - sizeof(AttributeList)) / sizeof(void*)
515 llvm::BumpPtrAllocator Alloc;
517 /// Free lists. The index is determined by the following formula:
518 /// (size - sizeof(AttributeList)) / sizeof(void*)
519 SmallVector<AttributeList*, InlineFreeListsCapacity> FreeLists;
521 // The following are the private interface used by AttributePool.
522 friend class AttributePool;
524 /// Allocate an attribute of the given size.
525 void *allocate(size_t size);
527 /// Reclaim all the attributes in the given pool chain, which is
528 /// non-empty. Note that the current implementation is safe
529 /// against reclaiming things which were not actually allocated
530 /// with the allocator, although of course it's important to make
531 /// sure that their allocator lives at least as long as this one.
532 void reclaimPool(AttributeList *head);
539 class AttributePool {
540 AttributeFactory &Factory;
543 void *allocate(size_t size) {
544 return Factory.allocate(size);
547 AttributeList *add(AttributeList *attr) {
548 // We don't care about the order of the pool.
549 attr->NextInPool = Head;
554 void takePool(AttributeList *pool);
557 /// Create a new pool for a factory.
558 AttributePool(AttributeFactory &factory) : Factory(factory), Head(nullptr) {}
560 AttributePool(const AttributePool &) = delete;
562 /// Move the given pool's allocations to this pool.
563 AttributePool(AttributePool &&pool) : Factory(pool.Factory), Head(pool.Head) {
567 AttributeFactory &getFactory() const { return Factory; }
571 Factory.reclaimPool(Head);
576 /// Take the given pool's allocations and add them to this pool.
577 void takeAllFrom(AttributePool &pool) {
585 if (Head) Factory.reclaimPool(Head);
588 AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
589 IdentifierInfo *scopeName, SourceLocation scopeLoc,
590 ArgsUnion *args, unsigned numArgs,
591 AttributeList::Syntax syntax,
592 SourceLocation ellipsisLoc = SourceLocation()) {
593 void *memory = allocate(sizeof(AttributeList)
594 + numArgs * sizeof(ArgsUnion));
595 return add(new (memory) AttributeList(attrName, attrRange,
597 args, numArgs, syntax,
601 AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
602 IdentifierInfo *scopeName, SourceLocation scopeLoc,
603 IdentifierLoc *Param,
604 const AvailabilityChange &introduced,
605 const AvailabilityChange &deprecated,
606 const AvailabilityChange &obsoleted,
607 SourceLocation unavailable,
608 const Expr *MessageExpr,
609 AttributeList::Syntax syntax) {
610 void *memory = allocate(AttributeFactory::AvailabilityAllocSize);
611 return add(new (memory) AttributeList(attrName, attrRange,
613 Param, introduced, deprecated,
614 obsoleted, unavailable, MessageExpr,
618 AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
619 IdentifierInfo *scopeName, SourceLocation scopeLoc,
620 IdentifierLoc *Param1,
621 IdentifierLoc *Param2,
622 IdentifierLoc *Param3,
623 AttributeList::Syntax syntax) {
624 size_t size = sizeof(AttributeList) + 3 * sizeof(ArgsUnion);
625 void *memory = allocate(size);
626 return add(new (memory) AttributeList(attrName, attrRange,
628 Param1, Param2, Param3,
632 AttributeList *createTypeTagForDatatype(
633 IdentifierInfo *attrName, SourceRange attrRange,
634 IdentifierInfo *scopeName, SourceLocation scopeLoc,
635 IdentifierLoc *argumentKind, ParsedType matchingCType,
636 bool layoutCompatible, bool mustBeNull,
637 AttributeList::Syntax syntax) {
638 void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize);
639 return add(new (memory) AttributeList(attrName, attrRange,
641 argumentKind, matchingCType,
642 layoutCompatible, mustBeNull,
646 AttributeList *createTypeAttribute(
647 IdentifierInfo *attrName, SourceRange attrRange,
648 IdentifierInfo *scopeName, SourceLocation scopeLoc,
649 ParsedType typeArg, AttributeList::Syntax syntaxUsed) {
650 void *memory = allocate(sizeof(AttributeList) + sizeof(void *));
651 return add(new (memory) AttributeList(attrName, attrRange,
653 typeArg, syntaxUsed));
656 AttributeList *createPropertyAttribute(
657 IdentifierInfo *attrName, SourceRange attrRange,
658 IdentifierInfo *scopeName, SourceLocation scopeLoc,
659 IdentifierInfo *getterId, IdentifierInfo *setterId,
660 AttributeList::Syntax syntaxUsed) {
661 void *memory = allocate(AttributeFactory::PropertyAllocSize);
662 return add(new (memory) AttributeList(attrName, attrRange,
669 /// ParsedAttributes - A collection of parsed attributes. Currently
670 /// we don't differentiate between the various attribute syntaxes,
671 /// which is basically silly.
673 /// Right now this is a very lightweight container, but the expectation
674 /// is that this will become significantly more serious.
675 class ParsedAttributes {
677 ParsedAttributes(AttributeFactory &factory)
678 : pool(factory), list(nullptr) {
681 ParsedAttributes(const ParsedAttributes &) = delete;
683 AttributePool &getPool() const { return pool; }
685 bool empty() const { return list == nullptr; }
687 void add(AttributeList *newAttr) {
689 assert(newAttr->getNext() == nullptr);
690 newAttr->setNext(list);
694 void addAll(AttributeList *newList) {
695 if (!newList) return;
697 AttributeList *lastInNewList = newList;
698 while (AttributeList *next = lastInNewList->getNext())
699 lastInNewList = next;
701 lastInNewList->setNext(list);
705 void set(AttributeList *newList) {
709 void takeAllFrom(ParsedAttributes &attrs) {
711 attrs.list = nullptr;
712 pool.takeAllFrom(attrs.pool);
715 void clear() { list = nullptr; pool.clear(); }
716 AttributeList *getList() const { return list; }
718 /// Returns a reference to the attribute list. Try not to introduce
719 /// dependencies on this method, it may not be long-lived.
720 AttributeList *&getListRef() { return list; }
722 /// Add attribute with expression arguments.
723 AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
724 IdentifierInfo *scopeName, SourceLocation scopeLoc,
725 ArgsUnion *args, unsigned numArgs,
726 AttributeList::Syntax syntax,
727 SourceLocation ellipsisLoc = SourceLocation()) {
728 AttributeList *attr =
729 pool.create(attrName, attrRange, scopeName, scopeLoc, args, numArgs,
730 syntax, ellipsisLoc);
735 /// Add availability attribute.
736 AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
737 IdentifierInfo *scopeName, SourceLocation scopeLoc,
738 IdentifierLoc *Param,
739 const AvailabilityChange &introduced,
740 const AvailabilityChange &deprecated,
741 const AvailabilityChange &obsoleted,
742 SourceLocation unavailable,
743 const Expr *MessageExpr,
744 AttributeList::Syntax syntax) {
745 AttributeList *attr =
746 pool.create(attrName, attrRange, scopeName, scopeLoc, Param, introduced,
747 deprecated, obsoleted, unavailable, MessageExpr, syntax);
752 /// Add objc_bridge_related attribute.
753 AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
754 IdentifierInfo *scopeName, SourceLocation scopeLoc,
755 IdentifierLoc *Param1,
756 IdentifierLoc *Param2,
757 IdentifierLoc *Param3,
758 AttributeList::Syntax syntax) {
759 AttributeList *attr =
760 pool.create(attrName, attrRange, scopeName, scopeLoc,
761 Param1, Param2, Param3, syntax);
766 /// Add type_tag_for_datatype attribute.
767 AttributeList *addNewTypeTagForDatatype(
768 IdentifierInfo *attrName, SourceRange attrRange,
769 IdentifierInfo *scopeName, SourceLocation scopeLoc,
770 IdentifierLoc *argumentKind, ParsedType matchingCType,
771 bool layoutCompatible, bool mustBeNull,
772 AttributeList::Syntax syntax) {
773 AttributeList *attr =
774 pool.createTypeTagForDatatype(attrName, attrRange,
776 argumentKind, matchingCType,
777 layoutCompatible, mustBeNull, syntax);
782 /// Add an attribute with a single type argument.
784 addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange,
785 IdentifierInfo *scopeName, SourceLocation scopeLoc,
786 ParsedType typeArg, AttributeList::Syntax syntaxUsed) {
787 AttributeList *attr =
788 pool.createTypeAttribute(attrName, attrRange, scopeName, scopeLoc,
789 typeArg, syntaxUsed);
794 /// Add microsoft __delspec(property) attribute.
796 addNewPropertyAttr(IdentifierInfo *attrName, SourceRange attrRange,
797 IdentifierInfo *scopeName, SourceLocation scopeLoc,
798 IdentifierInfo *getterId, IdentifierInfo *setterId,
799 AttributeList::Syntax syntaxUsed) {
800 AttributeList *attr =
801 pool.createPropertyAttribute(attrName, attrRange, scopeName, scopeLoc,
802 getterId, setterId, syntaxUsed);
808 mutable AttributePool pool;
812 /// These constants match the enumerated choices of
813 /// err_attribute_argument_n_type and err_attribute_argument_type.
814 enum AttributeArgumentNType {
815 AANT_ArgumentIntOrBool,
816 AANT_ArgumentIntegerConstant,
818 AANT_ArgumentIdentifier
821 /// These constants match the enumerated choices of
822 /// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type.
823 enum AttributeDeclKind {
826 ExpectedVariableOrFunction,
827 ExpectedFunctionOrMethod,
829 ExpectedFunctionMethodOrBlock,
830 ExpectedFunctionMethodOrClass,
831 ExpectedFunctionMethodOrParameter,
836 ExpectedVariableFunctionOrLabel,
837 ExpectedFieldOrGlobalVar,
839 ExpectedVariableOrTypedef,
841 ExpectedVariableOrField,
842 ExpectedVariableFieldOrTag,
843 ExpectedTypeOrNamespace,
844 ExpectedObjectiveCInterface,
845 ExpectedMethodOrProperty,
846 ExpectedStructOrUnion,
847 ExpectedStructOrUnionOrClass,
849 ExpectedObjCInstanceMethod,
850 ExpectedObjCInterfaceDeclInitMethod,
851 ExpectedFunctionVariableOrClass,
852 ExpectedObjectiveCProtocol,
853 ExpectedFunctionGlobalVarMethodOrProperty,
854 ExpectedStructOrUnionOrTypedef,
855 ExpectedStructOrTypedef,
856 ExpectedObjectiveCInterfaceOrProtocol,
857 ExpectedKernelFunction,
858 ExpectedFunctionWithProtoType
861 } // end namespace clang