1 //======- ParsedAttr.h - Parsed attribute sets ------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file defines the ParsedAttr class, which is used to collect
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_CLANG_SEMA_ATTRIBUTELIST_H
15 #define LLVM_CLANG_SEMA_ATTRIBUTELIST_H
17 #include "clang/Basic/AttrSubjectMatchRules.h"
18 #include "clang/Basic/Diagnostic.h"
19 #include "clang/Basic/SourceLocation.h"
20 #include "clang/Basic/TargetInfo.h"
21 #include "clang/Sema/Ownership.h"
22 #include "llvm/ADT/PointerUnion.h"
23 #include "llvm/ADT/SmallVector.h"
24 #include "llvm/ADT/TinyPtrVector.h"
25 #include "llvm/Support/Allocator.h"
26 #include "llvm/Support/VersionTuple.h"
40 /// Represents information about a change in availability for
41 /// an entity, which is part of the encoding of the 'availability'
43 struct AvailabilityChange {
44 /// The location of the keyword indicating the kind of change.
45 SourceLocation KeywordLoc;
47 /// The version number at which the change occurred.
50 /// The source range covering the version number.
51 SourceRange VersionRange;
53 /// Determine whether this availability change is valid.
54 bool isValid() const { return !Version.empty(); }
58 enum AvailabilitySlot {
59 IntroducedSlot, DeprecatedSlot, ObsoletedSlot, NumAvailabilitySlots
62 /// Describes the trailing object for Availability attribute in ParsedAttr.
63 struct AvailabilityData {
64 AvailabilityChange Changes[NumAvailabilitySlots];
65 SourceLocation StrictLoc;
66 const Expr *Replacement;
68 AvailabilityData(const AvailabilityChange &Introduced,
69 const AvailabilityChange &Deprecated,
70 const AvailabilityChange &Obsoleted,
71 SourceLocation Strict, const Expr *ReplaceExpr)
72 : StrictLoc(Strict), Replacement(ReplaceExpr) {
73 Changes[IntroducedSlot] = Introduced;
74 Changes[DeprecatedSlot] = Deprecated;
75 Changes[ObsoletedSlot] = Obsoleted;
79 struct TypeTagForDatatypeData {
80 ParsedType MatchingCType;
81 unsigned LayoutCompatible : 1;
82 unsigned MustBeNull : 1;
85 IdentifierInfo *GetterId, *SetterId;
87 PropertyData(IdentifierInfo *getterId, IdentifierInfo *setterId)
88 : GetterId(getterId), SetterId(setterId) {}
93 /// Wraps an identifier and optional source location for the identifier.
94 struct IdentifierLoc {
96 IdentifierInfo *Ident;
98 static IdentifierLoc *create(ASTContext &Ctx, SourceLocation Loc,
99 IdentifierInfo *Ident);
102 /// A union of the various pointer types that can be passed to an
103 /// ParsedAttr as an argument.
104 using ArgsUnion = llvm::PointerUnion<Expr *, IdentifierLoc *>;
105 using ArgsVector = llvm::SmallVector<ArgsUnion, 12U>;
107 /// ParsedAttr - Represents a syntactic attribute.
109 /// For a GNU attribute, there are four forms of this construct:
111 /// 1: __attribute__(( const )). ParmName/Args/NumArgs will all be unused.
112 /// 2: __attribute__(( mode(byte) )). ParmName used, Args/NumArgs unused.
113 /// 3: __attribute__(( format(printf, 1, 2) )). ParmName/Args/NumArgs all used.
114 /// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used.
116 class ParsedAttr final
117 : private llvm::TrailingObjects<
118 ParsedAttr, ArgsUnion, detail::AvailabilityData,
119 detail::TypeTagForDatatypeData, ParsedType, detail::PropertyData> {
120 friend TrailingObjects;
122 size_t numTrailingObjects(OverloadToken<ArgsUnion>) const { return NumArgs; }
123 size_t numTrailingObjects(OverloadToken<detail::AvailabilityData>) const {
124 return IsAvailability;
127 numTrailingObjects(OverloadToken<detail::TypeTagForDatatypeData>) const {
128 return IsTypeTagForDatatype;
130 size_t numTrailingObjects(OverloadToken<ParsedType>) const {
131 return HasParsedType;
133 size_t numTrailingObjects(OverloadToken<detail::PropertyData>) const {
138 /// The style used to specify an attribute.
140 /// __attribute__((...))
152 /// [uuid("...")] class Foo
155 /// __ptr16, alignas(...), etc.
161 // Note TableGen depends on the order above. Do not add or change the order
162 // without adding related code to TableGen/ClangAttrEmitter.cpp.
163 /// Context-sensitive version of a keyword attribute.
164 AS_ContextSensitiveKeyword,
168 IdentifierInfo *AttrName;
169 IdentifierInfo *ScopeName;
170 IdentifierInfo *MacroII = nullptr;
171 SourceLocation MacroExpansionLoc;
172 SourceRange AttrRange;
173 SourceLocation ScopeLoc;
174 SourceLocation EllipsisLoc;
176 unsigned AttrKind : 16;
178 /// The number of expression arguments this attribute has.
179 /// The expressions themselves are stored after the object.
180 unsigned NumArgs : 16;
182 /// Corresponds to the Syntax enum.
183 unsigned SyntaxUsed : 3;
185 /// True if already diagnosed as invalid.
186 mutable unsigned Invalid : 1;
188 /// True if this attribute was used as a type attribute.
189 mutable unsigned UsedAsTypeAttr : 1;
191 /// True if this has the extra information associated with an
192 /// availability attribute.
193 unsigned IsAvailability : 1;
195 /// True if this has extra information associated with a
196 /// type_tag_for_datatype attribute.
197 unsigned IsTypeTagForDatatype : 1;
199 /// True if this has extra information associated with a
200 /// Microsoft __delcspec(property) attribute.
201 unsigned IsProperty : 1;
203 /// True if this has a ParsedType
204 unsigned HasParsedType : 1;
206 /// True if the processing cache is valid.
207 mutable unsigned HasProcessingCache : 1;
210 mutable unsigned ProcessingCache : 8;
212 /// True if the attribute is specified using '#pragma clang attribute'.
213 mutable unsigned IsPragmaClangAttribute : 1;
215 /// The location of the 'unavailable' keyword in an
216 /// availability attribute.
217 SourceLocation UnavailableLoc;
219 const Expr *MessageExpr;
221 ArgsUnion *getArgsBuffer() { return getTrailingObjects<ArgsUnion>(); }
222 ArgsUnion const *getArgsBuffer() const {
223 return getTrailingObjects<ArgsUnion>();
226 detail::AvailabilityData *getAvailabilityData() {
227 return getTrailingObjects<detail::AvailabilityData>();
229 const detail::AvailabilityData *getAvailabilityData() const {
230 return getTrailingObjects<detail::AvailabilityData>();
234 friend class AttributeFactory;
235 friend class AttributePool;
237 /// Constructor for attributes with expression arguments.
238 ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
239 IdentifierInfo *scopeName, SourceLocation scopeLoc,
240 ArgsUnion *args, unsigned numArgs, Syntax syntaxUsed,
241 SourceLocation ellipsisLoc)
242 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
243 ScopeLoc(scopeLoc), EllipsisLoc(ellipsisLoc), NumArgs(numArgs),
244 SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false),
245 IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false),
246 HasParsedType(false), HasProcessingCache(false),
247 IsPragmaClangAttribute(false) {
248 if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion));
249 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
252 /// Constructor for availability attributes.
253 ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
254 IdentifierInfo *scopeName, SourceLocation scopeLoc,
255 IdentifierLoc *Parm, const AvailabilityChange &introduced,
256 const AvailabilityChange &deprecated,
257 const AvailabilityChange &obsoleted, SourceLocation unavailable,
258 const Expr *messageExpr, Syntax syntaxUsed, SourceLocation strict,
259 const Expr *replacementExpr)
260 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
261 ScopeLoc(scopeLoc), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false),
262 UsedAsTypeAttr(false), IsAvailability(true),
263 IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
264 HasProcessingCache(false), IsPragmaClangAttribute(false),
265 UnavailableLoc(unavailable), MessageExpr(messageExpr) {
266 ArgsUnion PVal(Parm);
267 memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
268 new (getAvailabilityData()) detail::AvailabilityData(
269 introduced, deprecated, obsoleted, strict, replacementExpr);
270 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
273 /// Constructor for objc_bridge_related attributes.
274 ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
275 IdentifierInfo *scopeName, SourceLocation scopeLoc,
276 IdentifierLoc *Parm1, IdentifierLoc *Parm2, IdentifierLoc *Parm3,
278 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
279 ScopeLoc(scopeLoc), NumArgs(3), SyntaxUsed(syntaxUsed), Invalid(false),
280 UsedAsTypeAttr(false), IsAvailability(false),
281 IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
282 HasProcessingCache(false), IsPragmaClangAttribute(false) {
283 ArgsUnion *Args = getArgsBuffer();
287 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
290 /// Constructor for type_tag_for_datatype attribute.
291 ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
292 IdentifierInfo *scopeName, SourceLocation scopeLoc,
293 IdentifierLoc *ArgKind, ParsedType matchingCType,
294 bool layoutCompatible, bool mustBeNull, Syntax syntaxUsed)
295 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
296 ScopeLoc(scopeLoc), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false),
297 UsedAsTypeAttr(false), IsAvailability(false),
298 IsTypeTagForDatatype(true), IsProperty(false), HasParsedType(false),
299 HasProcessingCache(false), IsPragmaClangAttribute(false) {
300 ArgsUnion PVal(ArgKind);
301 memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
302 detail::TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot();
303 new (&ExtraData.MatchingCType) ParsedType(matchingCType);
304 ExtraData.LayoutCompatible = layoutCompatible;
305 ExtraData.MustBeNull = mustBeNull;
306 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
309 /// Constructor for attributes with a single type argument.
310 ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
311 IdentifierInfo *scopeName, SourceLocation scopeLoc,
312 ParsedType typeArg, Syntax syntaxUsed)
313 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
314 ScopeLoc(scopeLoc), NumArgs(0), SyntaxUsed(syntaxUsed), Invalid(false),
315 UsedAsTypeAttr(false), IsAvailability(false),
316 IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(true),
317 HasProcessingCache(false), IsPragmaClangAttribute(false) {
318 new (&getTypeBuffer()) ParsedType(typeArg);
319 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
322 /// Constructor for microsoft __declspec(property) attribute.
323 ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
324 IdentifierInfo *scopeName, SourceLocation scopeLoc,
325 IdentifierInfo *getterId, IdentifierInfo *setterId,
327 : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
328 ScopeLoc(scopeLoc), NumArgs(0), SyntaxUsed(syntaxUsed), Invalid(false),
329 UsedAsTypeAttr(false), IsAvailability(false),
330 IsTypeTagForDatatype(false), IsProperty(true), HasParsedType(false),
331 HasProcessingCache(false), IsPragmaClangAttribute(false) {
332 new (&getPropertyDataBuffer()) detail::PropertyData(getterId, setterId);
333 AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
336 /// Type tag information is stored immediately following the arguments, if
337 /// any, at the end of the object. They are mutually exclusive with
338 /// availability slots.
339 detail::TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() {
340 return *getTrailingObjects<detail::TypeTagForDatatypeData>();
342 const detail::TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const {
343 return *getTrailingObjects<detail::TypeTagForDatatypeData>();
346 /// The type buffer immediately follows the object and are mutually exclusive
348 ParsedType &getTypeBuffer() { return *getTrailingObjects<ParsedType>(); }
349 const ParsedType &getTypeBuffer() const {
350 return *getTrailingObjects<ParsedType>();
353 /// The property data immediately follows the object is is mutually exclusive
355 detail::PropertyData &getPropertyDataBuffer() {
357 return *getTrailingObjects<detail::PropertyData>();
359 const detail::PropertyData &getPropertyDataBuffer() const {
361 return *getTrailingObjects<detail::PropertyData>();
364 size_t allocated_size() const;
367 ParsedAttr(const ParsedAttr &) = delete;
368 ParsedAttr(ParsedAttr &&) = delete;
369 ParsedAttr &operator=(const ParsedAttr &) = delete;
370 ParsedAttr &operator=(ParsedAttr &&) = delete;
371 ~ParsedAttr() = delete;
373 void operator delete(void *) = delete;
376 #define PARSED_ATTR(NAME) AT_##NAME,
377 #include "clang/Sema/AttrParsedAttrList.inc"
383 IdentifierInfo *getName() const { return AttrName; }
384 SourceLocation getLoc() const { return AttrRange.getBegin(); }
385 SourceRange getRange() const { return AttrRange; }
387 bool hasScope() const { return ScopeName; }
388 IdentifierInfo *getScopeName() const { return ScopeName; }
389 SourceLocation getScopeLoc() const { return ScopeLoc; }
391 bool isGNUScope() const {
393 (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"));
396 bool hasParsedType() const { return HasParsedType; }
398 /// Is this the Microsoft __declspec(property) attribute?
399 bool isDeclspecPropertyAttribute() const {
403 bool isAlignasAttribute() const {
404 // FIXME: Use a better mechanism to determine this.
405 return getKind() == AT_Aligned && isKeywordAttribute();
408 bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
409 bool isMicrosoftAttribute() const { return SyntaxUsed == AS_Microsoft; }
411 bool isCXX11Attribute() const {
412 return SyntaxUsed == AS_CXX11 || isAlignasAttribute();
415 bool isC2xAttribute() const {
416 return SyntaxUsed == AS_C2x;
419 bool isKeywordAttribute() const {
420 return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword;
423 bool isContextSensitiveKeywordAttribute() const {
424 return SyntaxUsed == AS_ContextSensitiveKeyword;
427 bool isInvalid() const { return Invalid; }
428 void setInvalid(bool b = true) const { Invalid = b; }
430 bool hasProcessingCache() const { return HasProcessingCache; }
432 unsigned getProcessingCache() const {
433 assert(hasProcessingCache());
434 return ProcessingCache;
437 void setProcessingCache(unsigned value) const {
438 ProcessingCache = value;
439 HasProcessingCache = true;
442 bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; }
443 void setUsedAsTypeAttr(bool Used = true) { UsedAsTypeAttr = Used; }
445 /// True if the attribute is specified using '#pragma clang attribute'.
446 bool isPragmaClangAttribute() const { return IsPragmaClangAttribute; }
448 void setIsPragmaClangAttribute() { IsPragmaClangAttribute = true; }
450 bool isPackExpansion() const { return EllipsisLoc.isValid(); }
451 SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
453 Kind getKind() const { return Kind(AttrKind); }
454 static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope,
457 /// getNumArgs - Return the number of actual arguments to this attribute.
458 unsigned getNumArgs() const { return NumArgs; }
460 /// getArg - Return the specified argument.
461 ArgsUnion getArg(unsigned Arg) const {
462 assert(Arg < NumArgs && "Arg access out of range!");
463 return getArgsBuffer()[Arg];
466 bool isArgExpr(unsigned Arg) const {
467 return Arg < NumArgs && getArg(Arg).is<Expr*>();
470 Expr *getArgAsExpr(unsigned Arg) const {
471 return getArg(Arg).get<Expr*>();
474 bool isArgIdent(unsigned Arg) const {
475 return Arg < NumArgs && getArg(Arg).is<IdentifierLoc*>();
478 IdentifierLoc *getArgAsIdent(unsigned Arg) const {
479 return getArg(Arg).get<IdentifierLoc*>();
482 const AvailabilityChange &getAvailabilityIntroduced() const {
483 assert(getKind() == AT_Availability && "Not an availability attribute");
484 return getAvailabilityData()->Changes[detail::IntroducedSlot];
487 const AvailabilityChange &getAvailabilityDeprecated() const {
488 assert(getKind() == AT_Availability && "Not an availability attribute");
489 return getAvailabilityData()->Changes[detail::DeprecatedSlot];
492 const AvailabilityChange &getAvailabilityObsoleted() const {
493 assert(getKind() == AT_Availability && "Not an availability attribute");
494 return getAvailabilityData()->Changes[detail::ObsoletedSlot];
497 SourceLocation getStrictLoc() const {
498 assert(getKind() == AT_Availability && "Not an availability attribute");
499 return getAvailabilityData()->StrictLoc;
502 SourceLocation getUnavailableLoc() const {
503 assert(getKind() == AT_Availability && "Not an availability attribute");
504 return UnavailableLoc;
507 const Expr * getMessageExpr() const {
508 assert(getKind() == AT_Availability && "Not an availability attribute");
512 const Expr *getReplacementExpr() const {
513 assert(getKind() == AT_Availability && "Not an availability attribute");
514 return getAvailabilityData()->Replacement;
517 const ParsedType &getMatchingCType() const {
518 assert(getKind() == AT_TypeTagForDatatype &&
519 "Not a type_tag_for_datatype attribute");
520 return getTypeTagForDatatypeDataSlot().MatchingCType;
523 bool getLayoutCompatible() const {
524 assert(getKind() == AT_TypeTagForDatatype &&
525 "Not a type_tag_for_datatype attribute");
526 return getTypeTagForDatatypeDataSlot().LayoutCompatible;
529 bool getMustBeNull() const {
530 assert(getKind() == AT_TypeTagForDatatype &&
531 "Not a type_tag_for_datatype attribute");
532 return getTypeTagForDatatypeDataSlot().MustBeNull;
535 const ParsedType &getTypeArg() const {
536 assert(HasParsedType && "Not a type attribute");
537 return getTypeBuffer();
540 IdentifierInfo *getPropertyDataGetter() const {
541 assert(isDeclspecPropertyAttribute() &&
542 "Not a __delcspec(property) attribute");
543 return getPropertyDataBuffer().GetterId;
546 IdentifierInfo *getPropertyDataSetter() const {
547 assert(isDeclspecPropertyAttribute() &&
548 "Not a __delcspec(property) attribute");
549 return getPropertyDataBuffer().SetterId;
552 /// Set the macro identifier info object that this parsed attribute was
553 /// declared in if it was declared in a macro. Also set the expansion location
555 void setMacroIdentifier(IdentifierInfo *MacroName, SourceLocation Loc) {
557 MacroExpansionLoc = Loc;
560 /// Returns true if this attribute was declared in a macro.
561 bool hasMacroIdentifier() const { return MacroII != nullptr; }
563 /// Return the macro identifier if this attribute was declared in a macro.
564 /// nullptr is returned if it was not declared in a macro.
565 IdentifierInfo *getMacroIdentifier() const { return MacroII; }
567 SourceLocation getMacroExpansionLoc() const {
568 assert(hasMacroIdentifier() && "Can only get the macro expansion location "
569 "if this attribute has a macro identifier.");
570 return MacroExpansionLoc;
573 /// Get an index into the attribute spelling list
574 /// defined in Attr.td. This index is used by an attribute
575 /// to pretty print itself.
576 unsigned getAttributeSpellingListIndex() const;
578 bool isTargetSpecificAttr() const;
579 bool isTypeAttr() const;
580 bool isStmtAttr() const;
582 bool hasCustomParsing() const;
583 unsigned getMinArgs() const;
584 unsigned getMaxArgs() const;
585 bool hasVariadicArg() const;
586 bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const;
587 bool appliesToDecl(const Decl *D, attr::SubjectMatchRule MatchRule) const;
588 void getMatchRules(const LangOptions &LangOpts,
589 SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>>
591 bool diagnoseLangOpts(class Sema &S) const;
592 bool existsInTarget(const TargetInfo &Target) const;
593 bool isKnownToGCC() const;
594 bool isSupportedByPragmaAttribute() const;
596 /// If the parsed attribute has a semantic equivalent, and it would
597 /// have a semantic Spelling enumeration (due to having semantically-distinct
598 /// spelling variations), return the value of that semantic spelling. If the
599 /// parsed attribute does not have a semantic equivalent, or would not have
600 /// a Spelling enumeration, the value UINT_MAX is returned.
601 unsigned getSemanticSpelling() const;
603 /// If this is an OpenCL addr space attribute returns its representation
604 /// in LangAS, otherwise returns default addr space.
605 LangAS asOpenCLLangAS() const {
607 case ParsedAttr::AT_OpenCLConstantAddressSpace:
608 return LangAS::opencl_constant;
609 case ParsedAttr::AT_OpenCLGlobalAddressSpace:
610 return LangAS::opencl_global;
611 case ParsedAttr::AT_OpenCLLocalAddressSpace:
612 return LangAS::opencl_local;
613 case ParsedAttr::AT_OpenCLPrivateAddressSpace:
614 return LangAS::opencl_private;
615 case ParsedAttr::AT_OpenCLGenericAddressSpace:
616 return LangAS::opencl_generic;
618 return LangAS::Default;
624 /// A factory, from which one makes pools, from which one creates
625 /// individual attributes which are deallocated with the pool.
627 /// Note that it's tolerably cheap to create and destroy one of
628 /// these as long as you don't actually allocate anything in it.
629 class AttributeFactory {
632 AvailabilityAllocSize =
633 ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
634 detail::TypeTagForDatatypeData, ParsedType,
635 detail::PropertyData>(1, 1, 0, 0, 0),
636 TypeTagForDatatypeAllocSize =
637 ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
638 detail::TypeTagForDatatypeData, ParsedType,
639 detail::PropertyData>(1, 0, 1, 0, 0),
641 ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
642 detail::TypeTagForDatatypeData, ParsedType,
643 detail::PropertyData>(0, 0, 0, 0, 1),
648 /// The number of free lists we want to be sure to support
649 /// inline. This is just enough that availability attributes
650 /// don't surpass it. It's actually very unlikely we'll see an
651 /// attribute that needs more than that; on x86-64 you'd need 10
652 /// expression arguments, and on i386 you'd need 19.
653 InlineFreeListsCapacity =
654 1 + (AvailabilityAllocSize - sizeof(ParsedAttr)) / sizeof(void *)
657 llvm::BumpPtrAllocator Alloc;
659 /// Free lists. The index is determined by the following formula:
660 /// (size - sizeof(ParsedAttr)) / sizeof(void*)
661 SmallVector<SmallVector<ParsedAttr *, 8>, InlineFreeListsCapacity> FreeLists;
663 // The following are the private interface used by AttributePool.
664 friend class AttributePool;
666 /// Allocate an attribute of the given size.
667 void *allocate(size_t size);
669 void deallocate(ParsedAttr *AL);
671 /// Reclaim all the attributes in the given pool chain, which is
672 /// non-empty. Note that the current implementation is safe
673 /// against reclaiming things which were not actually allocated
674 /// with the allocator, although of course it's important to make
675 /// sure that their allocator lives at least as long as this one.
676 void reclaimPool(AttributePool &head);
683 class AttributePool {
684 friend class AttributeFactory;
685 friend class ParsedAttributes;
686 AttributeFactory &Factory;
687 llvm::TinyPtrVector<ParsedAttr *> Attrs;
689 void *allocate(size_t size) {
690 return Factory.allocate(size);
693 ParsedAttr *add(ParsedAttr *attr) {
694 Attrs.push_back(attr);
698 void remove(ParsedAttr *attr) {
699 assert(llvm::is_contained(Attrs, attr) &&
700 "Can't take attribute from a pool that doesn't own it!");
701 Attrs.erase(llvm::find(Attrs, attr));
704 void takePool(AttributePool &pool);
707 /// Create a new pool for a factory.
708 AttributePool(AttributeFactory &factory) : Factory(factory) {}
710 AttributePool(const AttributePool &) = delete;
712 ~AttributePool() { Factory.reclaimPool(*this); }
714 /// Move the given pool's allocations to this pool.
715 AttributePool(AttributePool &&pool) = default;
717 AttributeFactory &getFactory() const { return Factory; }
720 Factory.reclaimPool(*this);
724 /// Take the given pool's allocations and add them to this pool.
725 void takeAllFrom(AttributePool &pool) {
730 ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange,
731 IdentifierInfo *scopeName, SourceLocation scopeLoc,
732 ArgsUnion *args, unsigned numArgs,
733 ParsedAttr::Syntax syntax,
734 SourceLocation ellipsisLoc = SourceLocation()) {
736 ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
737 detail::TypeTagForDatatypeData, ParsedType,
738 detail::PropertyData>(numArgs, 0, 0, 0, 0);
740 void *memory = allocate(
741 ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
742 detail::TypeTagForDatatypeData, ParsedType,
743 detail::PropertyData>(numArgs, 0, 0, 0,
745 return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
746 args, numArgs, syntax, ellipsisLoc));
749 ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange,
750 IdentifierInfo *scopeName, SourceLocation scopeLoc,
751 IdentifierLoc *Param, const AvailabilityChange &introduced,
752 const AvailabilityChange &deprecated,
753 const AvailabilityChange &obsoleted,
754 SourceLocation unavailable, const Expr *MessageExpr,
755 ParsedAttr::Syntax syntax, SourceLocation strict,
756 const Expr *ReplacementExpr) {
757 void *memory = allocate(AttributeFactory::AvailabilityAllocSize);
758 return add(new (memory) ParsedAttr(
759 attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated,
760 obsoleted, unavailable, MessageExpr, syntax, strict, ReplacementExpr));
763 ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange,
764 IdentifierInfo *scopeName, SourceLocation scopeLoc,
765 IdentifierLoc *Param1, IdentifierLoc *Param2,
766 IdentifierLoc *Param3, ParsedAttr::Syntax syntax) {
767 void *memory = allocate(
768 ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
769 detail::TypeTagForDatatypeData, ParsedType,
770 detail::PropertyData>(3, 0, 0, 0, 0));
771 return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
772 Param1, Param2, Param3, syntax));
776 createTypeTagForDatatype(IdentifierInfo *attrName, SourceRange attrRange,
777 IdentifierInfo *scopeName, SourceLocation scopeLoc,
778 IdentifierLoc *argumentKind,
779 ParsedType matchingCType, bool layoutCompatible,
780 bool mustBeNull, ParsedAttr::Syntax syntax) {
781 void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize);
782 return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
783 argumentKind, matchingCType,
784 layoutCompatible, mustBeNull, syntax));
787 ParsedAttr *createTypeAttribute(IdentifierInfo *attrName,
788 SourceRange attrRange,
789 IdentifierInfo *scopeName,
790 SourceLocation scopeLoc, ParsedType typeArg,
791 ParsedAttr::Syntax syntaxUsed) {
792 void *memory = allocate(
793 ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
794 detail::TypeTagForDatatypeData, ParsedType,
795 detail::PropertyData>(0, 0, 0, 1, 0));
796 return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
797 typeArg, syntaxUsed));
801 createPropertyAttribute(IdentifierInfo *attrName, SourceRange attrRange,
802 IdentifierInfo *scopeName, SourceLocation scopeLoc,
803 IdentifierInfo *getterId, IdentifierInfo *setterId,
804 ParsedAttr::Syntax syntaxUsed) {
805 void *memory = allocate(AttributeFactory::PropertyAllocSize);
806 return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
807 getterId, setterId, syntaxUsed));
811 class ParsedAttributesView {
812 using VecTy = llvm::TinyPtrVector<ParsedAttr *>;
813 using SizeType = decltype(std::declval<VecTy>().size());
816 bool empty() const { return AttrList.empty(); }
817 SizeType size() const { return AttrList.size(); }
818 ParsedAttr &operator[](SizeType pos) { return *AttrList[pos]; }
819 const ParsedAttr &operator[](SizeType pos) const { return *AttrList[pos]; }
821 void addAtEnd(ParsedAttr *newAttr) {
823 AttrList.push_back(newAttr);
826 void remove(ParsedAttr *ToBeRemoved) {
827 assert(is_contained(AttrList, ToBeRemoved) &&
828 "Cannot remove attribute that isn't in the list");
829 AttrList.erase(llvm::find(AttrList, ToBeRemoved));
832 void clearListOnly() { AttrList.clear(); }
834 struct iterator : llvm::iterator_adaptor_base<iterator, VecTy::iterator,
835 std::random_access_iterator_tag,
837 iterator() : iterator_adaptor_base(nullptr) {}
838 iterator(VecTy::iterator I) : iterator_adaptor_base(I) {}
839 reference operator*() { return **I; }
840 friend class ParsedAttributesView;
842 struct const_iterator
843 : llvm::iterator_adaptor_base<const_iterator, VecTy::const_iterator,
844 std::random_access_iterator_tag,
846 const_iterator() : iterator_adaptor_base(nullptr) {}
847 const_iterator(VecTy::const_iterator I) : iterator_adaptor_base(I) {}
849 reference operator*() const { return **I; }
850 friend class ParsedAttributesView;
853 void addAll(iterator B, iterator E) {
854 AttrList.insert(AttrList.begin(), B.I, E.I);
857 void addAll(const_iterator B, const_iterator E) {
858 AttrList.insert(AttrList.begin(), B.I, E.I);
861 void addAllAtEnd(iterator B, iterator E) {
862 AttrList.insert(AttrList.end(), B.I, E.I);
865 void addAllAtEnd(const_iterator B, const_iterator E) {
866 AttrList.insert(AttrList.end(), B.I, E.I);
869 iterator begin() { return iterator(AttrList.begin()); }
870 const_iterator begin() const { return const_iterator(AttrList.begin()); }
871 iterator end() { return iterator(AttrList.end()); }
872 const_iterator end() const { return const_iterator(AttrList.end()); }
874 ParsedAttr &front() {
876 return *AttrList.front();
878 const ParsedAttr &front() const {
880 return *AttrList.front();
884 return *AttrList.back();
886 const ParsedAttr &back() const {
888 return *AttrList.back();
891 bool hasAttribute(ParsedAttr::Kind K) const {
893 AttrList, [K](const ParsedAttr *AL) { return AL->getKind() == K; });
900 /// ParsedAttributes - A collection of parsed attributes. Currently
901 /// we don't differentiate between the various attribute syntaxes,
902 /// which is basically silly.
904 /// Right now this is a very lightweight container, but the expectation
905 /// is that this will become significantly more serious.
906 class ParsedAttributes : public ParsedAttributesView {
908 ParsedAttributes(AttributeFactory &factory) : pool(factory) {}
909 ParsedAttributes(const ParsedAttributes &) = delete;
911 AttributePool &getPool() const { return pool; }
913 void takeAllFrom(ParsedAttributes &attrs) {
914 addAll(attrs.begin(), attrs.end());
915 attrs.clearListOnly();
916 pool.takeAllFrom(attrs.pool);
919 void takeOneFrom(ParsedAttributes &Attrs, ParsedAttr *PA) {
920 Attrs.getPool().remove(PA);
931 /// Add attribute with expression arguments.
932 ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange,
933 IdentifierInfo *scopeName, SourceLocation scopeLoc,
934 ArgsUnion *args, unsigned numArgs,
935 ParsedAttr::Syntax syntax,
936 SourceLocation ellipsisLoc = SourceLocation()) {
937 ParsedAttr *attr = pool.create(attrName, attrRange, scopeName, scopeLoc,
938 args, numArgs, syntax, ellipsisLoc);
943 /// Add availability attribute.
944 ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange,
945 IdentifierInfo *scopeName, SourceLocation scopeLoc,
946 IdentifierLoc *Param, const AvailabilityChange &introduced,
947 const AvailabilityChange &deprecated,
948 const AvailabilityChange &obsoleted,
949 SourceLocation unavailable, const Expr *MessageExpr,
950 ParsedAttr::Syntax syntax, SourceLocation strict,
951 const Expr *ReplacementExpr) {
952 ParsedAttr *attr = pool.create(
953 attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated,
954 obsoleted, unavailable, MessageExpr, syntax, strict, ReplacementExpr);
959 /// Add objc_bridge_related attribute.
960 ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange,
961 IdentifierInfo *scopeName, SourceLocation scopeLoc,
962 IdentifierLoc *Param1, IdentifierLoc *Param2,
963 IdentifierLoc *Param3, ParsedAttr::Syntax syntax) {
964 ParsedAttr *attr = pool.create(attrName, attrRange, scopeName, scopeLoc,
965 Param1, Param2, Param3, syntax);
970 /// Add type_tag_for_datatype attribute.
972 addNewTypeTagForDatatype(IdentifierInfo *attrName, SourceRange attrRange,
973 IdentifierInfo *scopeName, SourceLocation scopeLoc,
974 IdentifierLoc *argumentKind,
975 ParsedType matchingCType, bool layoutCompatible,
976 bool mustBeNull, ParsedAttr::Syntax syntax) {
977 ParsedAttr *attr = pool.createTypeTagForDatatype(
978 attrName, attrRange, scopeName, scopeLoc, argumentKind, matchingCType,
979 layoutCompatible, mustBeNull, syntax);
984 /// Add an attribute with a single type argument.
985 ParsedAttr *addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange,
986 IdentifierInfo *scopeName, SourceLocation scopeLoc,
988 ParsedAttr::Syntax syntaxUsed) {
989 ParsedAttr *attr = pool.createTypeAttribute(attrName, attrRange, scopeName,
990 scopeLoc, typeArg, syntaxUsed);
995 /// Add microsoft __delspec(property) attribute.
997 addNewPropertyAttr(IdentifierInfo *attrName, SourceRange attrRange,
998 IdentifierInfo *scopeName, SourceLocation scopeLoc,
999 IdentifierInfo *getterId, IdentifierInfo *setterId,
1000 ParsedAttr::Syntax syntaxUsed) {
1002 pool.createPropertyAttribute(attrName, attrRange, scopeName, scopeLoc,
1003 getterId, setterId, syntaxUsed);
1009 mutable AttributePool pool;
1012 /// These constants match the enumerated choices of
1013 /// err_attribute_argument_n_type and err_attribute_argument_type.
1014 enum AttributeArgumentNType {
1015 AANT_ArgumentIntOrBool,
1016 AANT_ArgumentIntegerConstant,
1017 AANT_ArgumentString,
1018 AANT_ArgumentIdentifier
1021 /// These constants match the enumerated choices of
1022 /// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type.
1023 enum AttributeDeclKind {
1026 ExpectedVariableOrFunction,
1027 ExpectedFunctionOrMethod,
1028 ExpectedFunctionMethodOrBlock,
1029 ExpectedFunctionMethodOrParameter,
1031 ExpectedVariableOrField,
1032 ExpectedVariableFieldOrTag,
1033 ExpectedTypeOrNamespace,
1034 ExpectedFunctionVariableOrClass,
1035 ExpectedKernelFunction,
1036 ExpectedFunctionWithProtoType,
1039 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
1040 const ParsedAttr &At) {
1041 DB.AddTaggedVal(reinterpret_cast<intptr_t>(At.getName()),
1042 DiagnosticsEngine::ak_identifierinfo);
1046 inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
1047 const ParsedAttr &At) {
1048 PD.AddTaggedVal(reinterpret_cast<intptr_t>(At.getName()),
1049 DiagnosticsEngine::ak_identifierinfo);
1053 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
1054 const ParsedAttr *At) {
1055 DB.AddTaggedVal(reinterpret_cast<intptr_t>(At->getName()),
1056 DiagnosticsEngine::ak_identifierinfo);
1060 inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
1061 const ParsedAttr *At) {
1062 PD.AddTaggedVal(reinterpret_cast<intptr_t>(At->getName()),
1063 DiagnosticsEngine::ak_identifierinfo);
1067 } // namespace clang
1069 #endif // LLVM_CLANG_SEMA_ATTRIBUTELIST_H