1 //======- ParsedAttr.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 ParsedAttr 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/AttrSubjectMatchRules.h"
19 #include "clang/Basic/Diagnostic.h"
20 #include "clang/Basic/SourceLocation.h"
21 #include "clang/Basic/TargetInfo.h"
22 #include "clang/Sema/Ownership.h"
23 #include "llvm/ADT/PointerUnion.h"
24 #include "llvm/ADT/SmallVector.h"
25 #include "llvm/ADT/TinyPtrVector.h"
26 #include "llvm/Support/Allocator.h"
27 #include "llvm/Support/VersionTuple.h"
41 /// Represents information about a change in availability for
42 /// an entity, which is part of the encoding of the 'availability'
44 struct AvailabilityChange {
45 /// The location of the keyword indicating the kind of change.
46 SourceLocation KeywordLoc;
48 /// The version number at which the change occurred.
51 /// The source range covering the version number.
52 SourceRange VersionRange;
54 /// Determine whether this availability change is valid.
55 bool isValid() const { return !Version.empty(); }
59 enum AvailabilitySlot {
60 IntroducedSlot, DeprecatedSlot, ObsoletedSlot, NumAvailabilitySlots
63 /// Describes the trailing object for Availability attribute in ParsedAttr.
64 struct AvailabilityData {
65 AvailabilityChange Changes[NumAvailabilitySlots];
66 SourceLocation StrictLoc;
67 const Expr *Replacement;
69 AvailabilityData(const AvailabilityChange &Introduced,
70 const AvailabilityChange &Deprecated,
71 const AvailabilityChange &Obsoleted,
72 SourceLocation Strict, const Expr *ReplaceExpr)
73 : StrictLoc(Strict), Replacement(ReplaceExpr) {
74 Changes[IntroducedSlot] = Introduced;
75 Changes[DeprecatedSlot] = Deprecated;
76 Changes[ObsoletedSlot] = Obsoleted;
80 struct TypeTagForDatatypeData {
81 ParsedType MatchingCType;
82 unsigned LayoutCompatible : 1;
83 unsigned MustBeNull : 1;
86 IdentifierInfo *GetterId, *SetterId;
88 PropertyData(IdentifierInfo *getterId, IdentifierInfo *setterId)
89 : GetterId(getterId), SetterId(setterId) {}
94 /// Wraps an identifier and optional source location for the identifier.
95 struct IdentifierLoc {
97 IdentifierInfo *Ident;
99 static IdentifierLoc *create(ASTContext &Ctx, SourceLocation Loc,
100 IdentifierInfo *Ident);
103 /// A union of the various pointer types that can be passed to an
104 /// ParsedAttr as an argument.
105 using ArgsUnion = llvm::PointerUnion<Expr *, IdentifierLoc *>;
106 using ArgsVector = llvm::SmallVector<ArgsUnion, 12U>;
108 /// ParsedAttr - Represents a syntactic attribute.
110 /// For a GNU attribute, there are four forms of this construct:
112 /// 1: __attribute__(( const )). ParmName/Args/NumArgs will all be unused.
113 /// 2: __attribute__(( mode(byte) )). ParmName used, Args/NumArgs unused.
114 /// 3: __attribute__(( format(printf, 1, 2) )). ParmName/Args/NumArgs all used.
115 /// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used.
117 class ParsedAttr final
118 : private llvm::TrailingObjects<
119 ParsedAttr, ArgsUnion, detail::AvailabilityData,
120 detail::TypeTagForDatatypeData, ParsedType, detail::PropertyData> {
121 friend TrailingObjects;
123 size_t numTrailingObjects(OverloadToken<ArgsUnion>) const { return NumArgs; }
124 size_t numTrailingObjects(OverloadToken<detail::AvailabilityData>) const {
125 return IsAvailability;
128 numTrailingObjects(OverloadToken<detail::TypeTagForDatatypeData>) const {
129 return IsTypeTagForDatatype;
131 size_t numTrailingObjects(OverloadToken<ParsedType>) const {
132 return HasParsedType;
134 size_t numTrailingObjects(OverloadToken<detail::PropertyData>) const {
139 /// The style used to specify an attribute.
141 /// __attribute__((...))
153 /// [uuid("...")] class Foo
156 /// __ptr16, alignas(...), etc.
162 // Note TableGen depends on the order above. Do not add or change the order
163 // without adding related code to TableGen/ClangAttrEmitter.cpp.
164 /// Context-sensitive version of a keyword attribute.
165 AS_ContextSensitiveKeyword,
169 IdentifierInfo *AttrName;
170 IdentifierInfo *ScopeName;
171 SourceRange AttrRange;
172 SourceLocation ScopeLoc;
173 SourceLocation EllipsisLoc;
175 unsigned AttrKind : 16;
177 /// The number of expression arguments this attribute has.
178 /// The expressions themselves are stored after the object.
179 unsigned NumArgs : 16;
181 /// Corresponds to the Syntax enum.
182 unsigned SyntaxUsed : 3;
184 /// True if already diagnosed as invalid.
185 mutable unsigned Invalid : 1;
187 /// True if this attribute was used as a type attribute.
188 mutable unsigned UsedAsTypeAttr : 1;
190 /// True if this has the extra information associated with an
191 /// availability attribute.
192 unsigned IsAvailability : 1;
194 /// True if this has extra information associated with a
195 /// type_tag_for_datatype attribute.
196 unsigned IsTypeTagForDatatype : 1;
198 /// True if this has extra information associated with a
199 /// Microsoft __delcspec(property) attribute.
200 unsigned IsProperty : 1;
202 /// True if this has a ParsedType
203 unsigned HasParsedType : 1;
205 /// True if the processing cache is valid.
206 mutable unsigned HasProcessingCache : 1;
209 mutable unsigned ProcessingCache : 8;
211 /// The location of the 'unavailable' keyword in an
212 /// availability attribute.
213 SourceLocation UnavailableLoc;
215 const Expr *MessageExpr;
217 ArgsUnion *getArgsBuffer() { return getTrailingObjects<ArgsUnion>(); }
218 ArgsUnion const *getArgsBuffer() const {
219 return getTrailingObjects<ArgsUnion>();
222 detail::AvailabilityData *getAvailabilityData() {
223 return getTrailingObjects<detail::AvailabilityData>();
225 const detail::AvailabilityData *getAvailabilityData() const {
226 return getTrailingObjects<detail::AvailabilityData>();
230 friend class AttributeFactory;
231 friend class AttributePool;
233 /// Constructor for attributes with expression arguments.
234 ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
235 IdentifierInfo *scopeName, SourceLocation scopeLoc,
236 ArgsUnion *args, unsigned numArgs, Syntax syntaxUsed,
237 SourceLocation ellipsisLoc)
238 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
239 ScopeLoc(scopeLoc), EllipsisLoc(ellipsisLoc), NumArgs(numArgs),
240 SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false),
241 IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false),
242 HasParsedType(false), HasProcessingCache(false) {
243 if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion));
244 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
247 /// Constructor for availability attributes.
248 ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
249 IdentifierInfo *scopeName, SourceLocation scopeLoc,
250 IdentifierLoc *Parm, const AvailabilityChange &introduced,
251 const AvailabilityChange &deprecated,
252 const AvailabilityChange &obsoleted, SourceLocation unavailable,
253 const Expr *messageExpr, Syntax syntaxUsed, SourceLocation strict,
254 const Expr *replacementExpr)
255 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
256 ScopeLoc(scopeLoc), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false),
257 UsedAsTypeAttr(false), IsAvailability(true),
258 IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
259 HasProcessingCache(false), UnavailableLoc(unavailable),
260 MessageExpr(messageExpr) {
261 ArgsUnion PVal(Parm);
262 memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
263 new (getAvailabilityData()) detail::AvailabilityData(
264 introduced, deprecated, obsoleted, strict, replacementExpr);
265 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
268 /// Constructor for objc_bridge_related attributes.
269 ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
270 IdentifierInfo *scopeName, SourceLocation scopeLoc,
271 IdentifierLoc *Parm1, IdentifierLoc *Parm2, IdentifierLoc *Parm3,
273 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
274 ScopeLoc(scopeLoc), NumArgs(3), SyntaxUsed(syntaxUsed), Invalid(false),
275 UsedAsTypeAttr(false), IsAvailability(false),
276 IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
277 HasProcessingCache(false) {
278 ArgsUnion *Args = getArgsBuffer();
282 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
285 /// Constructor for type_tag_for_datatype attribute.
286 ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
287 IdentifierInfo *scopeName, SourceLocation scopeLoc,
288 IdentifierLoc *ArgKind, ParsedType matchingCType,
289 bool layoutCompatible, bool mustBeNull, Syntax syntaxUsed)
290 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
291 ScopeLoc(scopeLoc), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false),
292 UsedAsTypeAttr(false), IsAvailability(false),
293 IsTypeTagForDatatype(true), IsProperty(false), HasParsedType(false),
294 HasProcessingCache(false) {
295 ArgsUnion PVal(ArgKind);
296 memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
297 detail::TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot();
298 new (&ExtraData.MatchingCType) ParsedType(matchingCType);
299 ExtraData.LayoutCompatible = layoutCompatible;
300 ExtraData.MustBeNull = mustBeNull;
301 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
304 /// Constructor for attributes with a single type argument.
305 ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
306 IdentifierInfo *scopeName, SourceLocation scopeLoc,
307 ParsedType typeArg, Syntax syntaxUsed)
308 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
309 ScopeLoc(scopeLoc), NumArgs(0), SyntaxUsed(syntaxUsed), Invalid(false),
310 UsedAsTypeAttr(false), IsAvailability(false),
311 IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(true),
312 HasProcessingCache(false) {
313 new (&getTypeBuffer()) ParsedType(typeArg);
314 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
317 /// Constructor for microsoft __declspec(property) attribute.
318 ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
319 IdentifierInfo *scopeName, SourceLocation scopeLoc,
320 IdentifierInfo *getterId, IdentifierInfo *setterId,
322 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
323 ScopeLoc(scopeLoc), NumArgs(0), SyntaxUsed(syntaxUsed), Invalid(false),
324 UsedAsTypeAttr(false), IsAvailability(false),
325 IsTypeTagForDatatype(false), IsProperty(true), HasParsedType(false),
326 HasProcessingCache(false) {
327 new (&getPropertyDataBuffer()) detail::PropertyData(getterId, setterId);
328 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
331 /// Type tag information is stored immediately following the arguments, if
332 /// any, at the end of the object. They are mutually exclusive with
333 /// availability slots.
334 detail::TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() {
335 return *getTrailingObjects<detail::TypeTagForDatatypeData>();
337 const detail::TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const {
338 return *getTrailingObjects<detail::TypeTagForDatatypeData>();
341 /// The type buffer immediately follows the object and are mutually exclusive
343 ParsedType &getTypeBuffer() { return *getTrailingObjects<ParsedType>(); }
344 const ParsedType &getTypeBuffer() const {
345 return *getTrailingObjects<ParsedType>();
348 /// The property data immediately follows the object is is mutually exclusive
350 detail::PropertyData &getPropertyDataBuffer() {
352 return *getTrailingObjects<detail::PropertyData>();
354 const detail::PropertyData &getPropertyDataBuffer() const {
356 return *getTrailingObjects<detail::PropertyData>();
359 size_t allocated_size() const;
362 ParsedAttr(const ParsedAttr &) = delete;
363 ParsedAttr(ParsedAttr &&) = delete;
364 ParsedAttr &operator=(const ParsedAttr &) = delete;
365 ParsedAttr &operator=(ParsedAttr &&) = delete;
366 ~ParsedAttr() = delete;
368 void operator delete(void *) = delete;
371 #define PARSED_ATTR(NAME) AT_##NAME,
372 #include "clang/Sema/AttrParsedAttrList.inc"
378 IdentifierInfo *getName() const { return AttrName; }
379 SourceLocation getLoc() const { return AttrRange.getBegin(); }
380 SourceRange getRange() const { return AttrRange; }
382 bool hasScope() const { return ScopeName; }
383 IdentifierInfo *getScopeName() const { return ScopeName; }
384 SourceLocation getScopeLoc() const { return ScopeLoc; }
386 bool isGNUScope() const {
388 (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"));
391 bool hasParsedType() const { return HasParsedType; }
393 /// Is this the Microsoft __declspec(property) attribute?
394 bool isDeclspecPropertyAttribute() const {
398 bool isAlignasAttribute() const {
399 // FIXME: Use a better mechanism to determine this.
400 return getKind() == AT_Aligned && isKeywordAttribute();
403 bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
404 bool isMicrosoftAttribute() const { return SyntaxUsed == AS_Microsoft; }
406 bool isCXX11Attribute() const {
407 return SyntaxUsed == AS_CXX11 || isAlignasAttribute();
410 bool isC2xAttribute() const {
411 return SyntaxUsed == AS_C2x;
414 bool isKeywordAttribute() const {
415 return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword;
418 bool isContextSensitiveKeywordAttribute() const {
419 return SyntaxUsed == AS_ContextSensitiveKeyword;
422 bool isInvalid() const { return Invalid; }
423 void setInvalid(bool b = true) const { Invalid = b; }
425 bool hasProcessingCache() const { return HasProcessingCache; }
427 unsigned getProcessingCache() const {
428 assert(hasProcessingCache());
429 return ProcessingCache;
432 void setProcessingCache(unsigned value) const {
433 ProcessingCache = value;
434 HasProcessingCache = true;
437 bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; }
438 void setUsedAsTypeAttr() { UsedAsTypeAttr = true; }
440 bool isPackExpansion() const { return EllipsisLoc.isValid(); }
441 SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
443 Kind getKind() const { return Kind(AttrKind); }
444 static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope,
447 /// getNumArgs - Return the number of actual arguments to this attribute.
448 unsigned getNumArgs() const { return NumArgs; }
450 /// getArg - Return the specified argument.
451 ArgsUnion getArg(unsigned Arg) const {
452 assert(Arg < NumArgs && "Arg access out of range!");
453 return getArgsBuffer()[Arg];
456 bool isArgExpr(unsigned Arg) const {
457 return Arg < NumArgs && getArg(Arg).is<Expr*>();
460 Expr *getArgAsExpr(unsigned Arg) const {
461 return getArg(Arg).get<Expr*>();
464 bool isArgIdent(unsigned Arg) const {
465 return Arg < NumArgs && getArg(Arg).is<IdentifierLoc*>();
468 IdentifierLoc *getArgAsIdent(unsigned Arg) const {
469 return getArg(Arg).get<IdentifierLoc*>();
472 const AvailabilityChange &getAvailabilityIntroduced() const {
473 assert(getKind() == AT_Availability && "Not an availability attribute");
474 return getAvailabilityData()->Changes[detail::IntroducedSlot];
477 const AvailabilityChange &getAvailabilityDeprecated() const {
478 assert(getKind() == AT_Availability && "Not an availability attribute");
479 return getAvailabilityData()->Changes[detail::DeprecatedSlot];
482 const AvailabilityChange &getAvailabilityObsoleted() const {
483 assert(getKind() == AT_Availability && "Not an availability attribute");
484 return getAvailabilityData()->Changes[detail::ObsoletedSlot];
487 SourceLocation getStrictLoc() const {
488 assert(getKind() == AT_Availability && "Not an availability attribute");
489 return getAvailabilityData()->StrictLoc;
492 SourceLocation getUnavailableLoc() const {
493 assert(getKind() == AT_Availability && "Not an availability attribute");
494 return UnavailableLoc;
497 const Expr * getMessageExpr() const {
498 assert(getKind() == AT_Availability && "Not an availability attribute");
502 const Expr *getReplacementExpr() const {
503 assert(getKind() == AT_Availability && "Not an availability attribute");
504 return getAvailabilityData()->Replacement;
507 const ParsedType &getMatchingCType() const {
508 assert(getKind() == AT_TypeTagForDatatype &&
509 "Not a type_tag_for_datatype attribute");
510 return getTypeTagForDatatypeDataSlot().MatchingCType;
513 bool getLayoutCompatible() const {
514 assert(getKind() == AT_TypeTagForDatatype &&
515 "Not a type_tag_for_datatype attribute");
516 return getTypeTagForDatatypeDataSlot().LayoutCompatible;
519 bool getMustBeNull() const {
520 assert(getKind() == AT_TypeTagForDatatype &&
521 "Not a type_tag_for_datatype attribute");
522 return getTypeTagForDatatypeDataSlot().MustBeNull;
525 const ParsedType &getTypeArg() const {
526 assert(HasParsedType && "Not a type attribute");
527 return getTypeBuffer();
530 IdentifierInfo *getPropertyDataGetter() const {
531 assert(isDeclspecPropertyAttribute() &&
532 "Not a __delcspec(property) attribute");
533 return getPropertyDataBuffer().GetterId;
536 IdentifierInfo *getPropertyDataSetter() const {
537 assert(isDeclspecPropertyAttribute() &&
538 "Not a __delcspec(property) attribute");
539 return getPropertyDataBuffer().SetterId;
542 /// Get an index into the attribute spelling list
543 /// defined in Attr.td. This index is used by an attribute
544 /// to pretty print itself.
545 unsigned getAttributeSpellingListIndex() const;
547 bool isTargetSpecificAttr() const;
548 bool isTypeAttr() const;
549 bool isStmtAttr() const;
551 bool hasCustomParsing() const;
552 unsigned getMinArgs() const;
553 unsigned getMaxArgs() const;
554 bool hasVariadicArg() const;
555 bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const;
556 bool appliesToDecl(const Decl *D, attr::SubjectMatchRule MatchRule) const;
557 void getMatchRules(const LangOptions &LangOpts,
558 SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>>
560 bool diagnoseLangOpts(class Sema &S) const;
561 bool existsInTarget(const TargetInfo &Target) const;
562 bool isKnownToGCC() const;
563 bool isSupportedByPragmaAttribute() const;
565 /// If the parsed attribute has a semantic equivalent, and it would
566 /// have a semantic Spelling enumeration (due to having semantically-distinct
567 /// spelling variations), return the value of that semantic spelling. If the
568 /// parsed attribute does not have a semantic equivalent, or would not have
569 /// a Spelling enumeration, the value UINT_MAX is returned.
570 unsigned getSemanticSpelling() const;
574 /// A factory, from which one makes pools, from which one creates
575 /// individual attributes which are deallocated with the pool.
577 /// Note that it's tolerably cheap to create and destroy one of
578 /// these as long as you don't actually allocate anything in it.
579 class AttributeFactory {
582 AvailabilityAllocSize =
583 ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
584 detail::TypeTagForDatatypeData, ParsedType,
585 detail::PropertyData>(1, 1, 0, 0, 0),
586 TypeTagForDatatypeAllocSize =
587 ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
588 detail::TypeTagForDatatypeData, ParsedType,
589 detail::PropertyData>(1, 0, 1, 0, 0),
591 ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
592 detail::TypeTagForDatatypeData, ParsedType,
593 detail::PropertyData>(0, 0, 0, 0, 1),
598 /// The number of free lists we want to be sure to support
599 /// inline. This is just enough that availability attributes
600 /// don't surpass it. It's actually very unlikely we'll see an
601 /// attribute that needs more than that; on x86-64 you'd need 10
602 /// expression arguments, and on i386 you'd need 19.
603 InlineFreeListsCapacity =
604 1 + (AvailabilityAllocSize - sizeof(ParsedAttr)) / sizeof(void *)
607 llvm::BumpPtrAllocator Alloc;
609 /// Free lists. The index is determined by the following formula:
610 /// (size - sizeof(ParsedAttr)) / sizeof(void*)
611 SmallVector<SmallVector<ParsedAttr *, 8>, InlineFreeListsCapacity> FreeLists;
613 // The following are the private interface used by AttributePool.
614 friend class AttributePool;
616 /// Allocate an attribute of the given size.
617 void *allocate(size_t size);
619 void deallocate(ParsedAttr *AL);
621 /// Reclaim all the attributes in the given pool chain, which is
622 /// non-empty. Note that the current implementation is safe
623 /// against reclaiming things which were not actually allocated
624 /// with the allocator, although of course it's important to make
625 /// sure that their allocator lives at least as long as this one.
626 void reclaimPool(AttributePool &head);
633 class AttributePool {
634 friend class AttributeFactory;
635 AttributeFactory &Factory;
636 llvm::TinyPtrVector<ParsedAttr *> Attrs;
638 void *allocate(size_t size) {
639 return Factory.allocate(size);
642 ParsedAttr *add(ParsedAttr *attr) {
643 Attrs.push_back(attr);
647 void remove(ParsedAttr *attr) {
648 assert(llvm::is_contained(Attrs, attr) &&
649 "Can't take attribute from a pool that doesn't own it!");
650 Attrs.erase(llvm::find(Attrs, attr));
653 void takePool(AttributePool &pool);
656 /// Create a new pool for a factory.
657 AttributePool(AttributeFactory &factory) : Factory(factory) {}
659 AttributePool(const AttributePool &) = delete;
661 ~AttributePool() { Factory.reclaimPool(*this); }
663 /// Move the given pool's allocations to this pool.
664 AttributePool(AttributePool &&pool) = default;
666 AttributeFactory &getFactory() const { return Factory; }
669 Factory.reclaimPool(*this);
673 /// Take the given pool's allocations and add them to this pool.
674 void takeAllFrom(AttributePool &pool) {
679 ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange,
680 IdentifierInfo *scopeName, SourceLocation scopeLoc,
681 ArgsUnion *args, unsigned numArgs,
682 ParsedAttr::Syntax syntax,
683 SourceLocation ellipsisLoc = SourceLocation()) {
685 ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
686 detail::TypeTagForDatatypeData, ParsedType,
687 detail::PropertyData>(numArgs, 0, 0, 0, 0);
689 void *memory = allocate(
690 ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
691 detail::TypeTagForDatatypeData, ParsedType,
692 detail::PropertyData>(numArgs, 0, 0, 0,
694 return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
695 args, numArgs, syntax, ellipsisLoc));
698 ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange,
699 IdentifierInfo *scopeName, SourceLocation scopeLoc,
700 IdentifierLoc *Param, const AvailabilityChange &introduced,
701 const AvailabilityChange &deprecated,
702 const AvailabilityChange &obsoleted,
703 SourceLocation unavailable, const Expr *MessageExpr,
704 ParsedAttr::Syntax syntax, SourceLocation strict,
705 const Expr *ReplacementExpr) {
706 void *memory = allocate(AttributeFactory::AvailabilityAllocSize);
707 return add(new (memory) ParsedAttr(
708 attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated,
709 obsoleted, unavailable, MessageExpr, syntax, strict, ReplacementExpr));
712 ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange,
713 IdentifierInfo *scopeName, SourceLocation scopeLoc,
714 IdentifierLoc *Param1, IdentifierLoc *Param2,
715 IdentifierLoc *Param3, ParsedAttr::Syntax syntax) {
716 void *memory = allocate(
717 ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
718 detail::TypeTagForDatatypeData, ParsedType,
719 detail::PropertyData>(3, 0, 0, 0, 0));
720 return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
721 Param1, Param2, Param3, syntax));
725 createTypeTagForDatatype(IdentifierInfo *attrName, SourceRange attrRange,
726 IdentifierInfo *scopeName, SourceLocation scopeLoc,
727 IdentifierLoc *argumentKind,
728 ParsedType matchingCType, bool layoutCompatible,
729 bool mustBeNull, ParsedAttr::Syntax syntax) {
730 void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize);
731 return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
732 argumentKind, matchingCType,
733 layoutCompatible, mustBeNull, syntax));
736 ParsedAttr *createTypeAttribute(IdentifierInfo *attrName,
737 SourceRange attrRange,
738 IdentifierInfo *scopeName,
739 SourceLocation scopeLoc, ParsedType typeArg,
740 ParsedAttr::Syntax syntaxUsed) {
741 void *memory = allocate(
742 ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
743 detail::TypeTagForDatatypeData, ParsedType,
744 detail::PropertyData>(0, 0, 0, 1, 0));
745 return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
746 typeArg, syntaxUsed));
750 createPropertyAttribute(IdentifierInfo *attrName, SourceRange attrRange,
751 IdentifierInfo *scopeName, SourceLocation scopeLoc,
752 IdentifierInfo *getterId, IdentifierInfo *setterId,
753 ParsedAttr::Syntax syntaxUsed) {
754 void *memory = allocate(AttributeFactory::PropertyAllocSize);
755 return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
756 getterId, setterId, syntaxUsed));
760 class ParsedAttributesView {
761 using VecTy = llvm::TinyPtrVector<ParsedAttr *>;
762 using SizeType = decltype(std::declval<VecTy>().size());
765 bool empty() const { return AttrList.empty(); }
766 SizeType size() const { return AttrList.size(); }
767 ParsedAttr &operator[](SizeType pos) { return *AttrList[pos]; }
768 const ParsedAttr &operator[](SizeType pos) const { return *AttrList[pos]; }
770 void addAtEnd(ParsedAttr *newAttr) {
772 AttrList.push_back(newAttr);
775 void remove(ParsedAttr *ToBeRemoved) {
776 assert(is_contained(AttrList, ToBeRemoved) &&
777 "Cannot remove attribute that isn't in the list");
778 AttrList.erase(llvm::find(AttrList, ToBeRemoved));
781 void clearListOnly() { AttrList.clear(); }
783 struct iterator : llvm::iterator_adaptor_base<iterator, VecTy::iterator,
784 std::random_access_iterator_tag,
786 iterator() : iterator_adaptor_base(nullptr) {}
787 iterator(VecTy::iterator I) : iterator_adaptor_base(I) {}
788 reference operator*() { return **I; }
789 friend class ParsedAttributesView;
791 struct const_iterator
792 : llvm::iterator_adaptor_base<const_iterator, VecTy::const_iterator,
793 std::random_access_iterator_tag,
795 const_iterator() : iterator_adaptor_base(nullptr) {}
796 const_iterator(VecTy::const_iterator I) : iterator_adaptor_base(I) {}
798 reference operator*() const { return **I; }
799 friend class ParsedAttributesView;
802 void addAll(iterator B, iterator E) {
803 AttrList.insert(AttrList.begin(), B.I, E.I);
806 void addAll(const_iterator B, const_iterator E) {
807 AttrList.insert(AttrList.begin(), B.I, E.I);
810 void addAllAtEnd(iterator B, iterator E) {
811 AttrList.insert(AttrList.end(), B.I, E.I);
814 void addAllAtEnd(const_iterator B, const_iterator E) {
815 AttrList.insert(AttrList.end(), B.I, E.I);
818 iterator begin() { return iterator(AttrList.begin()); }
819 const_iterator begin() const { return const_iterator(AttrList.begin()); }
820 iterator end() { return iterator(AttrList.end()); }
821 const_iterator end() const { return const_iterator(AttrList.end()); }
823 ParsedAttr &front() {
825 return *AttrList.front();
827 const ParsedAttr &front() const {
829 return *AttrList.front();
833 return *AttrList.back();
835 const ParsedAttr &back() const {
837 return *AttrList.back();
840 bool hasAttribute(ParsedAttr::Kind K) const {
842 AttrList, [K](const ParsedAttr *AL) { return AL->getKind() == K; });
849 /// ParsedAttributes - A collection of parsed attributes. Currently
850 /// we don't differentiate between the various attribute syntaxes,
851 /// which is basically silly.
853 /// Right now this is a very lightweight container, but the expectation
854 /// is that this will become significantly more serious.
855 class ParsedAttributes : public ParsedAttributesView {
857 ParsedAttributes(AttributeFactory &factory) : pool(factory) {}
858 ParsedAttributes(const ParsedAttributes &) = delete;
860 AttributePool &getPool() const { return pool; }
862 void takeAllFrom(ParsedAttributes &attrs) {
863 addAll(attrs.begin(), attrs.end());
864 attrs.clearListOnly();
865 pool.takeAllFrom(attrs.pool);
873 /// Add attribute with expression arguments.
874 ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange,
875 IdentifierInfo *scopeName, SourceLocation scopeLoc,
876 ArgsUnion *args, unsigned numArgs,
877 ParsedAttr::Syntax syntax,
878 SourceLocation ellipsisLoc = SourceLocation()) {
879 ParsedAttr *attr = pool.create(attrName, attrRange, scopeName, scopeLoc,
880 args, numArgs, syntax, ellipsisLoc);
885 /// Add availability attribute.
886 ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange,
887 IdentifierInfo *scopeName, SourceLocation scopeLoc,
888 IdentifierLoc *Param, const AvailabilityChange &introduced,
889 const AvailabilityChange &deprecated,
890 const AvailabilityChange &obsoleted,
891 SourceLocation unavailable, const Expr *MessageExpr,
892 ParsedAttr::Syntax syntax, SourceLocation strict,
893 const Expr *ReplacementExpr) {
894 ParsedAttr *attr = pool.create(
895 attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated,
896 obsoleted, unavailable, MessageExpr, syntax, strict, ReplacementExpr);
901 /// Add objc_bridge_related attribute.
902 ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange,
903 IdentifierInfo *scopeName, SourceLocation scopeLoc,
904 IdentifierLoc *Param1, IdentifierLoc *Param2,
905 IdentifierLoc *Param3, ParsedAttr::Syntax syntax) {
906 ParsedAttr *attr = pool.create(attrName, attrRange, scopeName, scopeLoc,
907 Param1, Param2, Param3, syntax);
912 /// Add type_tag_for_datatype attribute.
914 addNewTypeTagForDatatype(IdentifierInfo *attrName, SourceRange attrRange,
915 IdentifierInfo *scopeName, SourceLocation scopeLoc,
916 IdentifierLoc *argumentKind,
917 ParsedType matchingCType, bool layoutCompatible,
918 bool mustBeNull, ParsedAttr::Syntax syntax) {
919 ParsedAttr *attr = pool.createTypeTagForDatatype(
920 attrName, attrRange, scopeName, scopeLoc, argumentKind, matchingCType,
921 layoutCompatible, mustBeNull, syntax);
926 /// Add an attribute with a single type argument.
927 ParsedAttr *addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange,
928 IdentifierInfo *scopeName, SourceLocation scopeLoc,
930 ParsedAttr::Syntax syntaxUsed) {
931 ParsedAttr *attr = pool.createTypeAttribute(attrName, attrRange, scopeName,
932 scopeLoc, typeArg, syntaxUsed);
937 /// Add microsoft __delspec(property) attribute.
939 addNewPropertyAttr(IdentifierInfo *attrName, SourceRange attrRange,
940 IdentifierInfo *scopeName, SourceLocation scopeLoc,
941 IdentifierInfo *getterId, IdentifierInfo *setterId,
942 ParsedAttr::Syntax syntaxUsed) {
944 pool.createPropertyAttribute(attrName, attrRange, scopeName, scopeLoc,
945 getterId, setterId, syntaxUsed);
951 mutable AttributePool pool;
954 /// These constants match the enumerated choices of
955 /// err_attribute_argument_n_type and err_attribute_argument_type.
956 enum AttributeArgumentNType {
957 AANT_ArgumentIntOrBool,
958 AANT_ArgumentIntegerConstant,
960 AANT_ArgumentIdentifier
963 /// These constants match the enumerated choices of
964 /// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type.
965 enum AttributeDeclKind {
968 ExpectedVariableOrFunction,
969 ExpectedFunctionOrMethod,
970 ExpectedFunctionMethodOrBlock,
971 ExpectedFunctionMethodOrParameter,
973 ExpectedVariableOrField,
974 ExpectedVariableFieldOrTag,
975 ExpectedTypeOrNamespace,
976 ExpectedFunctionVariableOrClass,
977 ExpectedKernelFunction,
978 ExpectedFunctionWithProtoType,
981 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
982 const ParsedAttr &At) {
983 DB.AddTaggedVal(reinterpret_cast<intptr_t>(At.getName()),
984 DiagnosticsEngine::ak_identifierinfo);
988 inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
989 const ParsedAttr &At) {
990 PD.AddTaggedVal(reinterpret_cast<intptr_t>(At.getName()),
991 DiagnosticsEngine::ak_identifierinfo);
995 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
996 const ParsedAttr *At) {
997 DB.AddTaggedVal(reinterpret_cast<intptr_t>(At->getName()),
998 DiagnosticsEngine::ak_identifierinfo);
1002 inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
1003 const ParsedAttr *At) {
1004 PD.AddTaggedVal(reinterpret_cast<intptr_t>(At->getName()),
1005 DiagnosticsEngine::ak_identifierinfo);
1009 } // namespace clang
1011 #endif // LLVM_CLANG_SEMA_ATTRIBUTELIST_H