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(); }
50 enum AvailabilitySlot {
51 IntroducedSlot, DeprecatedSlot, ObsoletedSlot, NumAvailabilitySlots
54 /// Describes the trailing object for Availability attribute in AttributeList.
55 struct AvailabilityData {
56 AvailabilityChange Changes[NumAvailabilitySlots];
57 SourceLocation StrictLoc;
58 const Expr *Replacement;
59 AvailabilityData(const AvailabilityChange &Introduced,
60 const AvailabilityChange &Deprecated,
61 const AvailabilityChange &Obsoleted,
62 SourceLocation Strict, const Expr *ReplaceExpr)
63 : StrictLoc(Strict), Replacement(ReplaceExpr) {
64 Changes[IntroducedSlot] = Introduced;
65 Changes[DeprecatedSlot] = Deprecated;
66 Changes[ObsoletedSlot] = Obsoleted;
71 /// \brief Wraps an identifier and optional source location for the identifier.
72 struct IdentifierLoc {
74 IdentifierInfo *Ident;
76 static IdentifierLoc *create(ASTContext &Ctx, SourceLocation Loc,
77 IdentifierInfo *Ident);
80 /// \brief A union of the various pointer types that can be passed to an
81 /// AttributeList as an argument.
82 typedef llvm::PointerUnion<Expr*, IdentifierLoc*> ArgsUnion;
83 typedef llvm::SmallVector<ArgsUnion, 12U> ArgsVector;
85 /// AttributeList - Represents a syntactic attribute.
87 /// For a GNU attribute, there are four forms of this construct:
89 /// 1: __attribute__(( const )). ParmName/Args/NumArgs will all be unused.
90 /// 2: __attribute__(( mode(byte) )). ParmName used, Args/NumArgs unused.
91 /// 3: __attribute__(( format(printf, 1, 2) )). ParmName/Args/NumArgs all used.
92 /// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used.
94 class AttributeList { // TODO: This should really be called ParsedAttribute
96 /// The style used to specify an attribute.
98 /// __attribute__((...))
104 /// [uuid("...")] class Foo
106 /// __ptr16, alignas(...), etc.
108 /// Context-sensitive version of a keyword attribute.
109 AS_ContextSensitiveKeyword,
115 IdentifierInfo *AttrName;
116 IdentifierInfo *ScopeName;
117 SourceRange AttrRange;
118 SourceLocation ScopeLoc;
119 SourceLocation EllipsisLoc;
121 unsigned AttrKind : 16;
123 /// The number of expression arguments this attribute has.
124 /// The expressions themselves are stored after the object.
125 unsigned NumArgs : 16;
127 /// Corresponds to the Syntax enum.
128 unsigned SyntaxUsed : 3;
130 /// True if already diagnosed as invalid.
131 mutable unsigned Invalid : 1;
133 /// True if this attribute was used as a type attribute.
134 mutable unsigned UsedAsTypeAttr : 1;
136 /// True if this has the extra information associated with an
137 /// availability attribute.
138 unsigned IsAvailability : 1;
140 /// True if this has extra information associated with a
141 /// type_tag_for_datatype attribute.
142 unsigned IsTypeTagForDatatype : 1;
144 /// True if this has extra information associated with a
145 /// Microsoft __delcspec(property) attribute.
146 unsigned IsProperty : 1;
148 /// True if this has a ParsedType
149 unsigned HasParsedType : 1;
151 /// True if the processing cache is valid.
152 mutable unsigned HasProcessingCache : 1;
155 mutable unsigned ProcessingCache : 8;
157 /// \brief The location of the 'unavailable' keyword in an
158 /// availability attribute.
159 SourceLocation UnavailableLoc;
161 const Expr *MessageExpr;
163 /// The next attribute in the current position.
164 AttributeList *NextInPosition;
166 /// The next attribute allocated in the current Pool.
167 AttributeList *NextInPool;
169 /// Arguments, if any, are stored immediately following the object.
170 ArgsUnion *getArgsBuffer() { return reinterpret_cast<ArgsUnion *>(this + 1); }
171 ArgsUnion const *getArgsBuffer() const {
172 return reinterpret_cast<ArgsUnion const *>(this + 1);
175 /// Availability information is stored immediately following the arguments,
176 /// if any, at the end of the object.
177 AvailabilityData *getAvailabilityData() {
178 return reinterpret_cast<AvailabilityData*>(getArgsBuffer() + NumArgs);
180 const AvailabilityData *getAvailabilityData() const {
181 return reinterpret_cast<const AvailabilityData*>(getArgsBuffer() + NumArgs);
185 struct TypeTagForDatatypeData {
186 ParsedType *MatchingCType;
187 unsigned LayoutCompatible : 1;
188 unsigned MustBeNull : 1;
190 struct PropertyData {
191 IdentifierInfo *GetterId, *SetterId;
192 PropertyData(IdentifierInfo *getterId, IdentifierInfo *setterId)
193 : GetterId(getterId), SetterId(setterId) {}
197 /// Type tag information is stored immediately following the arguments, if
198 /// any, at the end of the object. They are mutually exlusive with
199 /// availability slots.
200 TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() {
201 return *reinterpret_cast<TypeTagForDatatypeData*>(getArgsBuffer()+NumArgs);
204 const TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const {
205 return *reinterpret_cast<const TypeTagForDatatypeData*>(getArgsBuffer()
209 /// The type buffer immediately follows the object and are mutually exclusive
211 ParsedType &getTypeBuffer() {
212 return *reinterpret_cast<ParsedType *>(this + 1);
215 const ParsedType &getTypeBuffer() const {
216 return *reinterpret_cast<const ParsedType *>(this + 1);
219 /// The property data immediately follows the object is is mutually exclusive
221 PropertyData &getPropertyDataBuffer() {
223 return *reinterpret_cast<PropertyData*>(this + 1);
226 const PropertyData &getPropertyDataBuffer() const {
228 return *reinterpret_cast<const PropertyData*>(this + 1);
231 AttributeList(const AttributeList &) = delete;
232 void operator=(const AttributeList &) = delete;
233 void operator delete(void *) = delete;
234 ~AttributeList() = delete;
236 size_t allocated_size() const;
238 /// Constructor for attributes with expression arguments.
239 AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
240 IdentifierInfo *scopeName, SourceLocation scopeLoc,
241 ArgsUnion *args, unsigned numArgs,
242 Syntax syntaxUsed, SourceLocation ellipsisLoc)
243 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
244 ScopeLoc(scopeLoc), EllipsisLoc(ellipsisLoc), NumArgs(numArgs),
245 SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false),
246 IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false),
247 HasParsedType(false), HasProcessingCache(false),
248 NextInPosition(nullptr), NextInPool(nullptr) {
249 if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion));
250 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
253 /// Constructor for availability attributes.
254 AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
255 IdentifierInfo *scopeName, SourceLocation scopeLoc,
256 IdentifierLoc *Parm, const AvailabilityChange &introduced,
257 const AvailabilityChange &deprecated,
258 const AvailabilityChange &obsoleted,
259 SourceLocation unavailable,
260 const Expr *messageExpr,
261 Syntax syntaxUsed, SourceLocation strict,
262 const Expr *replacementExpr)
263 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
264 ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed),
265 Invalid(false), UsedAsTypeAttr(false), IsAvailability(true),
266 IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
267 HasProcessingCache(false), UnavailableLoc(unavailable),
268 MessageExpr(messageExpr), NextInPosition(nullptr), NextInPool(nullptr) {
269 ArgsUnion PVal(Parm);
270 memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
271 new (getAvailabilityData()) AvailabilityData(
272 introduced, deprecated, obsoleted, strict, replacementExpr);
273 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
276 /// Constructor for objc_bridge_related attributes.
277 AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
278 IdentifierInfo *scopeName, SourceLocation scopeLoc,
279 IdentifierLoc *Parm1,
280 IdentifierLoc *Parm2,
281 IdentifierLoc *Parm3,
283 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
284 ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(3), SyntaxUsed(syntaxUsed),
285 Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
286 IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
287 HasProcessingCache(false), NextInPosition(nullptr), NextInPool(nullptr) {
288 ArgsUnion *Args = getArgsBuffer();
292 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
295 /// Constructor for type_tag_for_datatype attribute.
296 AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
297 IdentifierInfo *scopeName, SourceLocation scopeLoc,
298 IdentifierLoc *ArgKind, ParsedType matchingCType,
299 bool layoutCompatible, bool mustBeNull, Syntax syntaxUsed)
300 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
301 ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed),
302 Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
303 IsTypeTagForDatatype(true), IsProperty(false), HasParsedType(false),
304 HasProcessingCache(false), NextInPosition(nullptr), NextInPool(nullptr) {
305 ArgsUnion PVal(ArgKind);
306 memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
307 TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot();
308 new (&ExtraData.MatchingCType) ParsedType(matchingCType);
309 ExtraData.LayoutCompatible = layoutCompatible;
310 ExtraData.MustBeNull = mustBeNull;
311 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
314 /// Constructor for attributes with a single type argument.
315 AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
316 IdentifierInfo *scopeName, SourceLocation scopeLoc,
317 ParsedType typeArg, Syntax syntaxUsed)
318 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
319 ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed),
320 Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
321 IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(true),
322 HasProcessingCache(false), NextInPosition(nullptr), NextInPool(nullptr){
323 new (&getTypeBuffer()) ParsedType(typeArg);
324 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
327 /// Constructor for microsoft __declspec(property) attribute.
328 AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
329 IdentifierInfo *scopeName, SourceLocation scopeLoc,
330 IdentifierInfo *getterId, IdentifierInfo *setterId,
332 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
333 ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed),
334 Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
335 IsTypeTagForDatatype(false), IsProperty(true), HasParsedType(false),
336 HasProcessingCache(false), NextInPosition(nullptr), NextInPool(nullptr) {
337 new (&getPropertyDataBuffer()) PropertyData(getterId, setterId);
338 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
341 friend class AttributePool;
342 friend class AttributeFactory;
346 #define PARSED_ATTR(NAME) AT_##NAME,
347 #include "clang/Sema/AttrParsedAttrList.inc"
353 IdentifierInfo *getName() const { return AttrName; }
354 SourceLocation getLoc() const { return AttrRange.getBegin(); }
355 SourceRange getRange() const { return AttrRange; }
357 bool hasScope() const { return ScopeName; }
358 IdentifierInfo *getScopeName() const { return ScopeName; }
359 SourceLocation getScopeLoc() const { return ScopeLoc; }
361 bool hasParsedType() const { return HasParsedType; }
363 /// Is this the Microsoft __declspec(property) attribute?
364 bool isDeclspecPropertyAttribute() const {
368 bool isAlignasAttribute() const {
369 // FIXME: Use a better mechanism to determine this.
370 return getKind() == AT_Aligned && isKeywordAttribute();
373 bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
374 bool isMicrosoftAttribute() const { return SyntaxUsed == AS_Microsoft; }
375 bool isCXX11Attribute() const {
376 return SyntaxUsed == AS_CXX11 || isAlignasAttribute();
378 bool isKeywordAttribute() const {
379 return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword;
382 bool isContextSensitiveKeywordAttribute() const {
383 return SyntaxUsed == AS_ContextSensitiveKeyword;
386 bool isInvalid() const { return Invalid; }
387 void setInvalid(bool b = true) const { Invalid = b; }
389 bool hasProcessingCache() const { return HasProcessingCache; }
390 unsigned getProcessingCache() const {
391 assert(hasProcessingCache());
392 return ProcessingCache;
394 void setProcessingCache(unsigned value) const {
395 ProcessingCache = value;
396 HasProcessingCache = true;
399 bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; }
400 void setUsedAsTypeAttr() { UsedAsTypeAttr = true; }
402 bool isPackExpansion() const { return EllipsisLoc.isValid(); }
403 SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
405 Kind getKind() const { return Kind(AttrKind); }
406 static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope,
409 AttributeList *getNext() const { return NextInPosition; }
410 void setNext(AttributeList *N) { NextInPosition = N; }
412 /// getNumArgs - Return the number of actual arguments to this attribute.
413 unsigned getNumArgs() const { return NumArgs; }
415 /// getArg - Return the specified argument.
416 ArgsUnion getArg(unsigned Arg) const {
417 assert(Arg < NumArgs && "Arg access out of range!");
418 return getArgsBuffer()[Arg];
421 bool isArgExpr(unsigned Arg) const {
422 return Arg < NumArgs && getArg(Arg).is<Expr*>();
424 Expr *getArgAsExpr(unsigned Arg) const {
425 return getArg(Arg).get<Expr*>();
428 bool isArgIdent(unsigned Arg) const {
429 return Arg < NumArgs && getArg(Arg).is<IdentifierLoc*>();
431 IdentifierLoc *getArgAsIdent(unsigned Arg) const {
432 return getArg(Arg).get<IdentifierLoc*>();
435 const AvailabilityChange &getAvailabilityIntroduced() const {
436 assert(getKind() == AT_Availability && "Not an availability attribute");
437 return getAvailabilityData()->Changes[IntroducedSlot];
440 const AvailabilityChange &getAvailabilityDeprecated() const {
441 assert(getKind() == AT_Availability && "Not an availability attribute");
442 return getAvailabilityData()->Changes[DeprecatedSlot];
445 const AvailabilityChange &getAvailabilityObsoleted() const {
446 assert(getKind() == AT_Availability && "Not an availability attribute");
447 return getAvailabilityData()->Changes[ObsoletedSlot];
450 SourceLocation getStrictLoc() const {
451 assert(getKind() == AT_Availability && "Not an availability attribute");
452 return getAvailabilityData()->StrictLoc;
455 SourceLocation getUnavailableLoc() const {
456 assert(getKind() == AT_Availability && "Not an availability attribute");
457 return UnavailableLoc;
460 const Expr * getMessageExpr() const {
461 assert(getKind() == AT_Availability && "Not an availability attribute");
465 const Expr *getReplacementExpr() const {
466 assert(getKind() == AT_Availability && "Not an availability attribute");
467 return getAvailabilityData()->Replacement;
470 const ParsedType &getMatchingCType() const {
471 assert(getKind() == AT_TypeTagForDatatype &&
472 "Not a type_tag_for_datatype attribute");
473 return *getTypeTagForDatatypeDataSlot().MatchingCType;
476 bool getLayoutCompatible() const {
477 assert(getKind() == AT_TypeTagForDatatype &&
478 "Not a type_tag_for_datatype attribute");
479 return getTypeTagForDatatypeDataSlot().LayoutCompatible;
482 bool getMustBeNull() const {
483 assert(getKind() == AT_TypeTagForDatatype &&
484 "Not a type_tag_for_datatype attribute");
485 return getTypeTagForDatatypeDataSlot().MustBeNull;
488 const ParsedType &getTypeArg() const {
489 assert(HasParsedType && "Not a type attribute");
490 return getTypeBuffer();
493 const PropertyData &getPropertyData() const {
494 assert(isDeclspecPropertyAttribute() && "Not a __delcspec(property) attribute");
495 return getPropertyDataBuffer();
498 /// \brief Get an index into the attribute spelling list
499 /// defined in Attr.td. This index is used by an attribute
500 /// to pretty print itself.
501 unsigned getAttributeSpellingListIndex() const;
503 bool isTargetSpecificAttr() const;
504 bool isTypeAttr() const;
505 bool isStmtAttr() const;
507 bool hasCustomParsing() const;
508 unsigned getMinArgs() const;
509 unsigned getMaxArgs() const;
510 bool hasVariadicArg() const;
511 bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const;
512 bool diagnoseLangOpts(class Sema &S) const;
513 bool existsInTarget(const TargetInfo &Target) const;
514 bool isKnownToGCC() const;
516 /// \brief If the parsed attribute has a semantic equivalent, and it would
517 /// have a semantic Spelling enumeration (due to having semantically-distinct
518 /// spelling variations), return the value of that semantic spelling. If the
519 /// parsed attribute does not have a semantic equivalent, or would not have
520 /// a Spelling enumeration, the value UINT_MAX is returned.
521 unsigned getSemanticSpelling() const;
524 /// A factory, from which one makes pools, from which one creates
525 /// individual attributes which are deallocated with the pool.
527 /// Note that it's tolerably cheap to create and destroy one of
528 /// these as long as you don't actually allocate anything in it.
529 class AttributeFactory {
532 /// The required allocation size of an availability attribute,
533 /// which we want to ensure is a multiple of sizeof(void*).
534 AvailabilityAllocSize =
535 sizeof(AttributeList)
536 + ((sizeof(AvailabilityData) + sizeof(void*) + sizeof(ArgsUnion) - 1)
537 / sizeof(void*) * sizeof(void*)),
538 TypeTagForDatatypeAllocSize =
539 sizeof(AttributeList)
540 + (sizeof(AttributeList::TypeTagForDatatypeData) + sizeof(void *) +
541 sizeof(ArgsUnion) - 1)
542 / sizeof(void*) * sizeof(void*),
544 sizeof(AttributeList)
545 + (sizeof(AttributeList::PropertyData) + sizeof(void *) - 1)
546 / sizeof(void*) * sizeof(void*)
551 /// The number of free lists we want to be sure to support
552 /// inline. This is just enough that availability attributes
553 /// don't surpass it. It's actually very unlikely we'll see an
554 /// attribute that needs more than that; on x86-64 you'd need 10
555 /// expression arguments, and on i386 you'd need 19.
556 InlineFreeListsCapacity =
557 1 + (AvailabilityAllocSize - sizeof(AttributeList)) / sizeof(void*)
560 llvm::BumpPtrAllocator Alloc;
562 /// Free lists. The index is determined by the following formula:
563 /// (size - sizeof(AttributeList)) / sizeof(void*)
564 SmallVector<AttributeList*, InlineFreeListsCapacity> FreeLists;
566 // The following are the private interface used by AttributePool.
567 friend class AttributePool;
569 /// Allocate an attribute of the given size.
570 void *allocate(size_t size);
572 /// Reclaim all the attributes in the given pool chain, which is
573 /// non-empty. Note that the current implementation is safe
574 /// against reclaiming things which were not actually allocated
575 /// with the allocator, although of course it's important to make
576 /// sure that their allocator lives at least as long as this one.
577 void reclaimPool(AttributeList *head);
584 class AttributePool {
585 AttributeFactory &Factory;
588 void *allocate(size_t size) {
589 return Factory.allocate(size);
592 AttributeList *add(AttributeList *attr) {
593 // We don't care about the order of the pool.
594 attr->NextInPool = Head;
599 void takePool(AttributeList *pool);
602 /// Create a new pool for a factory.
603 AttributePool(AttributeFactory &factory) : Factory(factory), Head(nullptr) {}
605 AttributePool(const AttributePool &) = delete;
607 /// Move the given pool's allocations to this pool.
608 AttributePool(AttributePool &&pool) : Factory(pool.Factory), Head(pool.Head) {
612 AttributeFactory &getFactory() const { return Factory; }
616 Factory.reclaimPool(Head);
621 /// Take the given pool's allocations and add them to this pool.
622 void takeAllFrom(AttributePool &pool) {
630 if (Head) Factory.reclaimPool(Head);
633 AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
634 IdentifierInfo *scopeName, SourceLocation scopeLoc,
635 ArgsUnion *args, unsigned numArgs,
636 AttributeList::Syntax syntax,
637 SourceLocation ellipsisLoc = SourceLocation()) {
638 void *memory = allocate(sizeof(AttributeList)
639 + numArgs * sizeof(ArgsUnion));
640 return add(new (memory) AttributeList(attrName, attrRange,
642 args, numArgs, syntax,
646 AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
647 IdentifierInfo *scopeName, SourceLocation scopeLoc,
648 IdentifierLoc *Param,
649 const AvailabilityChange &introduced,
650 const AvailabilityChange &deprecated,
651 const AvailabilityChange &obsoleted,
652 SourceLocation unavailable,
653 const Expr *MessageExpr,
654 AttributeList::Syntax syntax,
655 SourceLocation strict, const Expr *ReplacementExpr) {
656 void *memory = allocate(AttributeFactory::AvailabilityAllocSize);
657 return add(new (memory) AttributeList(attrName, attrRange,
659 Param, introduced, deprecated,
660 obsoleted, unavailable, MessageExpr,
661 syntax, strict, ReplacementExpr));
664 AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
665 IdentifierInfo *scopeName, SourceLocation scopeLoc,
666 IdentifierLoc *Param1,
667 IdentifierLoc *Param2,
668 IdentifierLoc *Param3,
669 AttributeList::Syntax syntax) {
670 size_t size = sizeof(AttributeList) + 3 * sizeof(ArgsUnion);
671 void *memory = allocate(size);
672 return add(new (memory) AttributeList(attrName, attrRange,
674 Param1, Param2, Param3,
678 AttributeList *createTypeTagForDatatype(
679 IdentifierInfo *attrName, SourceRange attrRange,
680 IdentifierInfo *scopeName, SourceLocation scopeLoc,
681 IdentifierLoc *argumentKind, ParsedType matchingCType,
682 bool layoutCompatible, bool mustBeNull,
683 AttributeList::Syntax syntax) {
684 void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize);
685 return add(new (memory) AttributeList(attrName, attrRange,
687 argumentKind, matchingCType,
688 layoutCompatible, mustBeNull,
692 AttributeList *createTypeAttribute(
693 IdentifierInfo *attrName, SourceRange attrRange,
694 IdentifierInfo *scopeName, SourceLocation scopeLoc,
695 ParsedType typeArg, AttributeList::Syntax syntaxUsed) {
696 void *memory = allocate(sizeof(AttributeList) + sizeof(void *));
697 return add(new (memory) AttributeList(attrName, attrRange,
699 typeArg, syntaxUsed));
702 AttributeList *createPropertyAttribute(
703 IdentifierInfo *attrName, SourceRange attrRange,
704 IdentifierInfo *scopeName, SourceLocation scopeLoc,
705 IdentifierInfo *getterId, IdentifierInfo *setterId,
706 AttributeList::Syntax syntaxUsed) {
707 void *memory = allocate(AttributeFactory::PropertyAllocSize);
708 return add(new (memory) AttributeList(attrName, attrRange,
715 /// ParsedAttributes - A collection of parsed attributes. Currently
716 /// we don't differentiate between the various attribute syntaxes,
717 /// which is basically silly.
719 /// Right now this is a very lightweight container, but the expectation
720 /// is that this will become significantly more serious.
721 class ParsedAttributes {
723 ParsedAttributes(AttributeFactory &factory)
724 : pool(factory), list(nullptr) {
727 ParsedAttributes(const ParsedAttributes &) = delete;
729 AttributePool &getPool() const { return pool; }
731 bool empty() const { return list == nullptr; }
733 void add(AttributeList *newAttr) {
735 assert(newAttr->getNext() == nullptr);
736 newAttr->setNext(list);
740 void addAll(AttributeList *newList) {
741 if (!newList) return;
743 AttributeList *lastInNewList = newList;
744 while (AttributeList *next = lastInNewList->getNext())
745 lastInNewList = next;
747 lastInNewList->setNext(list);
751 void addAllAtEnd(AttributeList *newList) {
757 AttributeList *lastInList = list;
758 while (AttributeList *next = lastInList->getNext())
761 lastInList->setNext(newList);
764 void set(AttributeList *newList) {
768 void takeAllFrom(ParsedAttributes &attrs) {
770 attrs.list = nullptr;
771 pool.takeAllFrom(attrs.pool);
774 void clear() { list = nullptr; pool.clear(); }
775 AttributeList *getList() const { return list; }
777 /// Returns a reference to the attribute list. Try not to introduce
778 /// dependencies on this method, it may not be long-lived.
779 AttributeList *&getListRef() { return list; }
781 /// Add attribute with expression arguments.
782 AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
783 IdentifierInfo *scopeName, SourceLocation scopeLoc,
784 ArgsUnion *args, unsigned numArgs,
785 AttributeList::Syntax syntax,
786 SourceLocation ellipsisLoc = SourceLocation()) {
787 AttributeList *attr =
788 pool.create(attrName, attrRange, scopeName, scopeLoc, args, numArgs,
789 syntax, ellipsisLoc);
794 /// Add availability attribute.
795 AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
796 IdentifierInfo *scopeName, SourceLocation scopeLoc,
797 IdentifierLoc *Param,
798 const AvailabilityChange &introduced,
799 const AvailabilityChange &deprecated,
800 const AvailabilityChange &obsoleted,
801 SourceLocation unavailable,
802 const Expr *MessageExpr,
803 AttributeList::Syntax syntax,
804 SourceLocation strict, const Expr *ReplacementExpr) {
805 AttributeList *attr =
806 pool.create(attrName, attrRange, scopeName, scopeLoc, Param, introduced,
807 deprecated, obsoleted, unavailable, MessageExpr, syntax,
808 strict, ReplacementExpr);
813 /// Add objc_bridge_related attribute.
814 AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
815 IdentifierInfo *scopeName, SourceLocation scopeLoc,
816 IdentifierLoc *Param1,
817 IdentifierLoc *Param2,
818 IdentifierLoc *Param3,
819 AttributeList::Syntax syntax) {
820 AttributeList *attr =
821 pool.create(attrName, attrRange, scopeName, scopeLoc,
822 Param1, Param2, Param3, syntax);
827 /// Add type_tag_for_datatype attribute.
828 AttributeList *addNewTypeTagForDatatype(
829 IdentifierInfo *attrName, SourceRange attrRange,
830 IdentifierInfo *scopeName, SourceLocation scopeLoc,
831 IdentifierLoc *argumentKind, ParsedType matchingCType,
832 bool layoutCompatible, bool mustBeNull,
833 AttributeList::Syntax syntax) {
834 AttributeList *attr =
835 pool.createTypeTagForDatatype(attrName, attrRange,
837 argumentKind, matchingCType,
838 layoutCompatible, mustBeNull, syntax);
843 /// Add an attribute with a single type argument.
845 addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange,
846 IdentifierInfo *scopeName, SourceLocation scopeLoc,
847 ParsedType typeArg, AttributeList::Syntax syntaxUsed) {
848 AttributeList *attr =
849 pool.createTypeAttribute(attrName, attrRange, scopeName, scopeLoc,
850 typeArg, syntaxUsed);
855 /// Add microsoft __delspec(property) attribute.
857 addNewPropertyAttr(IdentifierInfo *attrName, SourceRange attrRange,
858 IdentifierInfo *scopeName, SourceLocation scopeLoc,
859 IdentifierInfo *getterId, IdentifierInfo *setterId,
860 AttributeList::Syntax syntaxUsed) {
861 AttributeList *attr =
862 pool.createPropertyAttribute(attrName, attrRange, scopeName, scopeLoc,
863 getterId, setterId, syntaxUsed);
869 mutable AttributePool pool;
873 /// These constants match the enumerated choices of
874 /// err_attribute_argument_n_type and err_attribute_argument_type.
875 enum AttributeArgumentNType {
876 AANT_ArgumentIntOrBool,
877 AANT_ArgumentIntegerConstant,
879 AANT_ArgumentIdentifier
882 /// These constants match the enumerated choices of
883 /// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type.
884 enum AttributeDeclKind {
887 ExpectedVariableOrFunction,
888 ExpectedFunctionOrGlobalVar,
889 ExpectedFunctionVariableOrObjCInterface,
890 ExpectedFunctionOrMethod,
892 ExpectedFunctionMethodOrBlock,
893 ExpectedFunctionMethodOrClass,
894 ExpectedFunctionMethodOrParameter,
895 ExpectedFunctionMethodOrGlobalVar,
900 ExpectedFieldOrGlobalVar,
902 ExpectedParameterOrTypedef,
903 ExpectedVariableOrTypedef,
905 ExpectedVariableOrField,
906 ExpectedVariableFieldOrTag,
907 ExpectedTypeOrNamespace,
908 ExpectedObjectiveCInterface,
909 ExpectedMethodOrProperty,
910 ExpectedStructOrUnion,
911 ExpectedStructOrUnionOrClass,
913 ExpectedObjCInstanceMethod,
914 ExpectedObjCInterfaceDeclInitMethod,
915 ExpectedFunctionVariableOrClass,
916 ExpectedFunctionVariableClassOrObjCInterface,
917 ExpectedObjectiveCProtocol,
918 ExpectedStaticOrTLSVar,
919 ExpectedFunctionGlobalVarMethodOrProperty,
920 ExpectedStructOrUnionOrTypedef,
921 ExpectedStructOrTypedef,
922 ExpectedObjectiveCInterfaceOrProtocol,
923 ExpectedKernelFunction,
924 ExpectedFunctionWithProtoType,
925 ExpectedVariableEnumFieldOrTypedef,
926 ExpectedFunctionMethodEnumOrClass,
927 ExpectedStructClassVariableFunctionOrInlineNamespace,
928 ExpectedForMaybeUnused,
933 } // end namespace clang