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_PARSEDATTR_H
15 #define LLVM_CLANG_SEMA_PARSEDATTR_H
17 #include "clang/Basic/AttrSubjectMatchRules.h"
18 #include "clang/Basic/AttributeCommonInfo.h"
19 #include "clang/Basic/Diagnostic.h"
20 #include "clang/Basic/ParsedAttrInfo.h"
21 #include "clang/Basic/SourceLocation.h"
22 #include "clang/Sema/Ownership.h"
23 #include "llvm/ADT/PointerUnion.h"
24 #include "llvm/ADT/SmallVector.h"
25 #include "llvm/Support/Allocator.h"
26 #include "llvm/Support/VersionTuple.h"
43 /// Represents information about a change in availability for
44 /// an entity, which is part of the encoding of the 'availability'
46 struct AvailabilityChange {
47 /// The location of the keyword indicating the kind of change.
48 SourceLocation KeywordLoc;
50 /// The version number at which the change occurred.
53 /// The source range covering the version number.
54 SourceRange VersionRange;
56 /// Determine whether this availability change is valid.
57 bool isValid() const { return !Version.empty(); }
61 enum AvailabilitySlot {
62 IntroducedSlot, DeprecatedSlot, ObsoletedSlot, NumAvailabilitySlots
65 /// Describes the trailing object for Availability attribute in ParsedAttr.
66 struct AvailabilityData {
67 AvailabilityChange Changes[NumAvailabilitySlots];
68 SourceLocation StrictLoc;
69 const Expr *Replacement;
71 AvailabilityData(const AvailabilityChange &Introduced,
72 const AvailabilityChange &Deprecated,
73 const AvailabilityChange &Obsoleted,
74 SourceLocation Strict, const Expr *ReplaceExpr)
75 : StrictLoc(Strict), Replacement(ReplaceExpr) {
76 Changes[IntroducedSlot] = Introduced;
77 Changes[DeprecatedSlot] = Deprecated;
78 Changes[ObsoletedSlot] = Obsoleted;
82 struct TypeTagForDatatypeData {
83 ParsedType MatchingCType;
84 unsigned LayoutCompatible : 1;
85 unsigned MustBeNull : 1;
88 IdentifierInfo *GetterId, *SetterId;
90 PropertyData(IdentifierInfo *getterId, IdentifierInfo *setterId)
91 : GetterId(getterId), SetterId(setterId) {}
96 /// Wraps an identifier and optional source location for the identifier.
97 struct IdentifierLoc {
99 IdentifierInfo *Ident;
101 static IdentifierLoc *create(ASTContext &Ctx, SourceLocation Loc,
102 IdentifierInfo *Ident);
105 /// A union of the various pointer types that can be passed to an
106 /// ParsedAttr as an argument.
107 using ArgsUnion = llvm::PointerUnion<Expr *, IdentifierLoc *>;
108 using ArgsVector = llvm::SmallVector<ArgsUnion, 12U>;
110 /// ParsedAttr - Represents a syntactic attribute.
112 /// For a GNU attribute, there are four forms of this construct:
114 /// 1: __attribute__(( const )). ParmName/Args/NumArgs will all be unused.
115 /// 2: __attribute__(( mode(byte) )). ParmName used, Args/NumArgs unused.
116 /// 3: __attribute__(( format(printf, 1, 2) )). ParmName/Args/NumArgs all used.
117 /// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used.
119 class ParsedAttr final
120 : public AttributeCommonInfo,
121 private llvm::TrailingObjects<
122 ParsedAttr, ArgsUnion, detail::AvailabilityData,
123 detail::TypeTagForDatatypeData, ParsedType, detail::PropertyData> {
124 friend TrailingObjects;
126 size_t numTrailingObjects(OverloadToken<ArgsUnion>) const { return NumArgs; }
127 size_t numTrailingObjects(OverloadToken<detail::AvailabilityData>) const {
128 return IsAvailability;
131 numTrailingObjects(OverloadToken<detail::TypeTagForDatatypeData>) const {
132 return IsTypeTagForDatatype;
134 size_t numTrailingObjects(OverloadToken<ParsedType>) const {
135 return HasParsedType;
137 size_t numTrailingObjects(OverloadToken<detail::PropertyData>) const {
142 IdentifierInfo *MacroII = nullptr;
143 SourceLocation MacroExpansionLoc;
144 SourceLocation EllipsisLoc;
146 /// The number of expression arguments this attribute has.
147 /// The expressions themselves are stored after the object.
148 unsigned NumArgs : 16;
150 /// True if already diagnosed as invalid.
151 mutable unsigned Invalid : 1;
153 /// True if this attribute was used as a type attribute.
154 mutable unsigned UsedAsTypeAttr : 1;
156 /// True if this has the extra information associated with an
157 /// availability attribute.
158 unsigned IsAvailability : 1;
160 /// True if this has extra information associated with a
161 /// type_tag_for_datatype attribute.
162 unsigned IsTypeTagForDatatype : 1;
164 /// True if this has extra information associated with a
165 /// Microsoft __delcspec(property) attribute.
166 unsigned IsProperty : 1;
168 /// True if this has a ParsedType
169 unsigned HasParsedType : 1;
171 /// True if the processing cache is valid.
172 mutable unsigned HasProcessingCache : 1;
175 mutable unsigned ProcessingCache : 8;
177 /// True if the attribute is specified using '#pragma clang attribute'.
178 mutable unsigned IsPragmaClangAttribute : 1;
180 /// The location of the 'unavailable' keyword in an
181 /// availability attribute.
182 SourceLocation UnavailableLoc;
184 const Expr *MessageExpr;
186 const ParsedAttrInfo &Info;
188 ArgsUnion *getArgsBuffer() { return getTrailingObjects<ArgsUnion>(); }
189 ArgsUnion const *getArgsBuffer() const {
190 return getTrailingObjects<ArgsUnion>();
193 detail::AvailabilityData *getAvailabilityData() {
194 return getTrailingObjects<detail::AvailabilityData>();
196 const detail::AvailabilityData *getAvailabilityData() const {
197 return getTrailingObjects<detail::AvailabilityData>();
201 friend class AttributeFactory;
202 friend class AttributePool;
204 /// Constructor for attributes with expression arguments.
205 ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
206 IdentifierInfo *scopeName, SourceLocation scopeLoc,
207 ArgsUnion *args, unsigned numArgs, Form formUsed,
208 SourceLocation ellipsisLoc)
209 : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, formUsed),
210 EllipsisLoc(ellipsisLoc), NumArgs(numArgs), Invalid(false),
211 UsedAsTypeAttr(false), IsAvailability(false),
212 IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
213 HasProcessingCache(false), IsPragmaClangAttribute(false),
214 Info(ParsedAttrInfo::get(*this)) {
216 memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion));
219 /// Constructor for availability attributes.
220 ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
221 IdentifierInfo *scopeName, SourceLocation scopeLoc,
222 IdentifierLoc *Parm, const AvailabilityChange &introduced,
223 const AvailabilityChange &deprecated,
224 const AvailabilityChange &obsoleted, SourceLocation unavailable,
225 const Expr *messageExpr, Form formUsed, SourceLocation strict,
226 const Expr *replacementExpr)
227 : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, formUsed),
228 NumArgs(1), Invalid(false), UsedAsTypeAttr(false), IsAvailability(true),
229 IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
230 HasProcessingCache(false), IsPragmaClangAttribute(false),
231 UnavailableLoc(unavailable), MessageExpr(messageExpr),
232 Info(ParsedAttrInfo::get(*this)) {
233 ArgsUnion PVal(Parm);
234 memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
235 new (getAvailabilityData()) detail::AvailabilityData(
236 introduced, deprecated, obsoleted, strict, replacementExpr);
239 /// Constructor for objc_bridge_related attributes.
240 ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
241 IdentifierInfo *scopeName, SourceLocation scopeLoc,
242 IdentifierLoc *Parm1, IdentifierLoc *Parm2, IdentifierLoc *Parm3,
244 : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, formUsed),
245 NumArgs(3), Invalid(false), UsedAsTypeAttr(false),
246 IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false),
247 HasParsedType(false), HasProcessingCache(false),
248 IsPragmaClangAttribute(false), Info(ParsedAttrInfo::get(*this)) {
249 ArgsUnion *Args = getArgsBuffer();
255 /// Constructor for type_tag_for_datatype attribute.
256 ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
257 IdentifierInfo *scopeName, SourceLocation scopeLoc,
258 IdentifierLoc *ArgKind, ParsedType matchingCType,
259 bool layoutCompatible, bool mustBeNull, Form formUsed)
260 : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, formUsed),
261 NumArgs(1), Invalid(false), UsedAsTypeAttr(false),
262 IsAvailability(false), IsTypeTagForDatatype(true), IsProperty(false),
263 HasParsedType(false), HasProcessingCache(false),
264 IsPragmaClangAttribute(false), Info(ParsedAttrInfo::get(*this)) {
265 ArgsUnion PVal(ArgKind);
266 memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
267 detail::TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot();
268 new (&ExtraData.MatchingCType) ParsedType(matchingCType);
269 ExtraData.LayoutCompatible = layoutCompatible;
270 ExtraData.MustBeNull = mustBeNull;
273 /// Constructor for attributes with a single type argument.
274 ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
275 IdentifierInfo *scopeName, SourceLocation scopeLoc,
276 ParsedType typeArg, Form formUsed, SourceLocation ellipsisLoc)
277 : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, formUsed),
278 EllipsisLoc(ellipsisLoc), NumArgs(0), Invalid(false),
279 UsedAsTypeAttr(false), IsAvailability(false),
280 IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(true),
281 HasProcessingCache(false), IsPragmaClangAttribute(false),
282 Info(ParsedAttrInfo::get(*this)) {
283 new (&getTypeBuffer()) ParsedType(typeArg);
286 /// Constructor for microsoft __declspec(property) attribute.
287 ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
288 IdentifierInfo *scopeName, SourceLocation scopeLoc,
289 IdentifierInfo *getterId, IdentifierInfo *setterId, Form formUsed)
290 : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, formUsed),
291 NumArgs(0), Invalid(false), UsedAsTypeAttr(false),
292 IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(true),
293 HasParsedType(false), HasProcessingCache(false),
294 IsPragmaClangAttribute(false), Info(ParsedAttrInfo::get(*this)) {
295 new (&getPropertyDataBuffer()) detail::PropertyData(getterId, setterId);
298 /// Type tag information is stored immediately following the arguments, if
299 /// any, at the end of the object. They are mutually exclusive with
300 /// availability slots.
301 detail::TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() {
302 return *getTrailingObjects<detail::TypeTagForDatatypeData>();
304 const detail::TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const {
305 return *getTrailingObjects<detail::TypeTagForDatatypeData>();
308 /// The type buffer immediately follows the object and are mutually exclusive
310 ParsedType &getTypeBuffer() { return *getTrailingObjects<ParsedType>(); }
311 const ParsedType &getTypeBuffer() const {
312 return *getTrailingObjects<ParsedType>();
315 /// The property data immediately follows the object is mutually exclusive
317 detail::PropertyData &getPropertyDataBuffer() {
319 return *getTrailingObjects<detail::PropertyData>();
321 const detail::PropertyData &getPropertyDataBuffer() const {
323 return *getTrailingObjects<detail::PropertyData>();
326 size_t allocated_size() const;
329 ParsedAttr(const ParsedAttr &) = delete;
330 ParsedAttr(ParsedAttr &&) = delete;
331 ParsedAttr &operator=(const ParsedAttr &) = delete;
332 ParsedAttr &operator=(ParsedAttr &&) = delete;
333 ~ParsedAttr() = delete;
335 void operator delete(void *) = delete;
337 bool hasParsedType() const { return HasParsedType; }
339 /// Is this the Microsoft __declspec(property) attribute?
340 bool isDeclspecPropertyAttribute() const {
344 bool isInvalid() const { return Invalid; }
345 void setInvalid(bool b = true) const { Invalid = b; }
347 bool hasProcessingCache() const { return HasProcessingCache; }
349 unsigned getProcessingCache() const {
350 assert(hasProcessingCache());
351 return ProcessingCache;
354 void setProcessingCache(unsigned value) const {
355 ProcessingCache = value;
356 HasProcessingCache = true;
359 bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; }
360 void setUsedAsTypeAttr(bool Used = true) { UsedAsTypeAttr = Used; }
362 /// True if the attribute is specified using '#pragma clang attribute'.
363 bool isPragmaClangAttribute() const { return IsPragmaClangAttribute; }
365 void setIsPragmaClangAttribute() { IsPragmaClangAttribute = true; }
367 bool isPackExpansion() const { return EllipsisLoc.isValid(); }
368 SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
370 /// getNumArgs - Return the number of actual arguments to this attribute.
371 unsigned getNumArgs() const { return NumArgs; }
373 /// getArg - Return the specified argument.
374 ArgsUnion getArg(unsigned Arg) const {
375 assert(Arg < NumArgs && "Arg access out of range!");
376 return getArgsBuffer()[Arg];
379 bool isArgExpr(unsigned Arg) const {
380 return Arg < NumArgs && getArg(Arg).is<Expr*>();
383 Expr *getArgAsExpr(unsigned Arg) const {
384 return getArg(Arg).get<Expr*>();
387 bool isArgIdent(unsigned Arg) const {
388 return Arg < NumArgs && getArg(Arg).is<IdentifierLoc*>();
391 IdentifierLoc *getArgAsIdent(unsigned Arg) const {
392 return getArg(Arg).get<IdentifierLoc*>();
395 const AvailabilityChange &getAvailabilityIntroduced() const {
396 assert(getParsedKind() == AT_Availability &&
397 "Not an availability attribute");
398 return getAvailabilityData()->Changes[detail::IntroducedSlot];
401 const AvailabilityChange &getAvailabilityDeprecated() const {
402 assert(getParsedKind() == AT_Availability &&
403 "Not an availability attribute");
404 return getAvailabilityData()->Changes[detail::DeprecatedSlot];
407 const AvailabilityChange &getAvailabilityObsoleted() const {
408 assert(getParsedKind() == AT_Availability &&
409 "Not an availability attribute");
410 return getAvailabilityData()->Changes[detail::ObsoletedSlot];
413 SourceLocation getStrictLoc() const {
414 assert(getParsedKind() == AT_Availability &&
415 "Not an availability attribute");
416 return getAvailabilityData()->StrictLoc;
419 SourceLocation getUnavailableLoc() const {
420 assert(getParsedKind() == AT_Availability &&
421 "Not an availability attribute");
422 return UnavailableLoc;
425 const Expr * getMessageExpr() const {
426 assert(getParsedKind() == AT_Availability &&
427 "Not an availability attribute");
431 const Expr *getReplacementExpr() const {
432 assert(getParsedKind() == AT_Availability &&
433 "Not an availability attribute");
434 return getAvailabilityData()->Replacement;
437 const ParsedType &getMatchingCType() const {
438 assert(getParsedKind() == AT_TypeTagForDatatype &&
439 "Not a type_tag_for_datatype attribute");
440 return getTypeTagForDatatypeDataSlot().MatchingCType;
443 bool getLayoutCompatible() const {
444 assert(getParsedKind() == AT_TypeTagForDatatype &&
445 "Not a type_tag_for_datatype attribute");
446 return getTypeTagForDatatypeDataSlot().LayoutCompatible;
449 bool getMustBeNull() const {
450 assert(getParsedKind() == AT_TypeTagForDatatype &&
451 "Not a type_tag_for_datatype attribute");
452 return getTypeTagForDatatypeDataSlot().MustBeNull;
455 const ParsedType &getTypeArg() const {
456 assert(HasParsedType && "Not a type attribute");
457 return getTypeBuffer();
460 IdentifierInfo *getPropertyDataGetter() const {
461 assert(isDeclspecPropertyAttribute() &&
462 "Not a __delcspec(property) attribute");
463 return getPropertyDataBuffer().GetterId;
466 IdentifierInfo *getPropertyDataSetter() const {
467 assert(isDeclspecPropertyAttribute() &&
468 "Not a __delcspec(property) attribute");
469 return getPropertyDataBuffer().SetterId;
472 /// Set the macro identifier info object that this parsed attribute was
473 /// declared in if it was declared in a macro. Also set the expansion location
475 void setMacroIdentifier(IdentifierInfo *MacroName, SourceLocation Loc) {
477 MacroExpansionLoc = Loc;
480 /// Returns true if this attribute was declared in a macro.
481 bool hasMacroIdentifier() const { return MacroII != nullptr; }
483 /// Return the macro identifier if this attribute was declared in a macro.
484 /// nullptr is returned if it was not declared in a macro.
485 IdentifierInfo *getMacroIdentifier() const { return MacroII; }
487 SourceLocation getMacroExpansionLoc() const {
488 assert(hasMacroIdentifier() && "Can only get the macro expansion location "
489 "if this attribute has a macro identifier.");
490 return MacroExpansionLoc;
493 /// Check if the attribute has exactly as many args as Num. May output an
494 /// error. Returns false if a diagnostic is produced.
495 bool checkExactlyNumArgs(class Sema &S, unsigned Num) const;
496 /// Check if the attribute has at least as many args as Num. May output an
497 /// error. Returns false if a diagnostic is produced.
498 bool checkAtLeastNumArgs(class Sema &S, unsigned Num) const;
499 /// Check if the attribute has at most as many args as Num. May output an
500 /// error. Returns false if a diagnostic is produced.
501 bool checkAtMostNumArgs(class Sema &S, unsigned Num) const;
503 bool isTargetSpecificAttr() const;
504 bool isTypeAttr() const;
505 bool isStmtAttr() const;
507 bool hasCustomParsing() const;
508 bool acceptsExprPack() const;
509 bool isParamExpr(size_t N) const;
510 unsigned getMinArgs() const;
511 unsigned getMaxArgs() const;
512 unsigned getNumArgMembers() const;
513 bool hasVariadicArg() const;
514 void handleAttrWithDelayedArgs(Sema &S, Decl *D) const;
515 bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const;
516 bool diagnoseAppertainsTo(class Sema &S, const Stmt *St) const;
517 bool diagnoseMutualExclusion(class Sema &S, const Decl *D) const;
518 // This function stub exists for parity with the declaration checking code so
519 // that checkCommonAttributeFeatures() can work generically on declarations
521 bool diagnoseMutualExclusion(class Sema &S, const Stmt *St) const {
524 bool appliesToDecl(const Decl *D, attr::SubjectMatchRule MatchRule) const;
525 void getMatchRules(const LangOptions &LangOpts,
526 SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>>
528 bool diagnoseLangOpts(class Sema &S) const;
529 bool existsInTarget(const TargetInfo &Target) const;
530 bool isKnownToGCC() const;
531 bool isSupportedByPragmaAttribute() const;
533 /// Returns whether a [[]] attribute, if specified ahead of a declaration,
534 /// should be applied to the decl-specifier-seq instead (i.e. whether it
535 /// "slides" to the decl-specifier-seq).
537 /// By the standard, attributes specified before the declaration always
538 /// appertain to the declaration, but historically we have allowed some of
539 /// these attributes to slide to the decl-specifier-seq, so we need to keep
540 /// supporting this behavior.
542 /// This may only be called if isStandardAttributeSyntax() returns true.
543 bool slidesFromDeclToDeclSpecLegacyBehavior() const;
545 /// If the parsed attribute has a semantic equivalent, and it would
546 /// have a semantic Spelling enumeration (due to having semantically-distinct
547 /// spelling variations), return the value of that semantic spelling. If the
548 /// parsed attribute does not have a semantic equivalent, or would not have
549 /// a Spelling enumeration, the value UINT_MAX is returned.
550 unsigned getSemanticSpelling() const;
552 /// If this is an OpenCL address space attribute, returns its representation
553 /// in LangAS, otherwise returns default address space.
554 LangAS asOpenCLLangAS() const {
555 switch (getParsedKind()) {
556 case ParsedAttr::AT_OpenCLConstantAddressSpace:
557 return LangAS::opencl_constant;
558 case ParsedAttr::AT_OpenCLGlobalAddressSpace:
559 return LangAS::opencl_global;
560 case ParsedAttr::AT_OpenCLGlobalDeviceAddressSpace:
561 return LangAS::opencl_global_device;
562 case ParsedAttr::AT_OpenCLGlobalHostAddressSpace:
563 return LangAS::opencl_global_host;
564 case ParsedAttr::AT_OpenCLLocalAddressSpace:
565 return LangAS::opencl_local;
566 case ParsedAttr::AT_OpenCLPrivateAddressSpace:
567 return LangAS::opencl_private;
568 case ParsedAttr::AT_OpenCLGenericAddressSpace:
569 return LangAS::opencl_generic;
571 return LangAS::Default;
575 /// If this is an OpenCL address space attribute, returns its SYCL
576 /// representation in LangAS, otherwise returns default address space.
577 LangAS asSYCLLangAS() const {
579 case ParsedAttr::AT_OpenCLGlobalAddressSpace:
580 return LangAS::sycl_global;
581 case ParsedAttr::AT_OpenCLGlobalDeviceAddressSpace:
582 return LangAS::sycl_global_device;
583 case ParsedAttr::AT_OpenCLGlobalHostAddressSpace:
584 return LangAS::sycl_global_host;
585 case ParsedAttr::AT_OpenCLLocalAddressSpace:
586 return LangAS::sycl_local;
587 case ParsedAttr::AT_OpenCLPrivateAddressSpace:
588 return LangAS::sycl_private;
589 case ParsedAttr::AT_OpenCLGenericAddressSpace:
591 return LangAS::Default;
595 /// If this is an HLSL address space attribute, returns its representation
596 /// in LangAS, otherwise returns default address space.
597 LangAS asHLSLLangAS() const {
598 switch (getParsedKind()) {
599 case ParsedAttr::AT_HLSLGroupSharedAddressSpace:
600 return LangAS::hlsl_groupshared;
602 return LangAS::Default;
606 AttributeCommonInfo::Kind getKind() const {
607 return AttributeCommonInfo::Kind(Info.AttrKind);
609 const ParsedAttrInfo &getInfo() const { return Info; }
613 /// A factory, from which one makes pools, from which one creates
614 /// individual attributes which are deallocated with the pool.
616 /// Note that it's tolerably cheap to create and destroy one of
617 /// these as long as you don't actually allocate anything in it.
618 class AttributeFactory {
621 AvailabilityAllocSize =
622 ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
623 detail::TypeTagForDatatypeData, ParsedType,
624 detail::PropertyData>(1, 1, 0, 0, 0),
625 TypeTagForDatatypeAllocSize =
626 ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
627 detail::TypeTagForDatatypeData, ParsedType,
628 detail::PropertyData>(1, 0, 1, 0, 0),
630 ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
631 detail::TypeTagForDatatypeData, ParsedType,
632 detail::PropertyData>(0, 0, 0, 0, 1),
637 /// The number of free lists we want to be sure to support
638 /// inline. This is just enough that availability attributes
639 /// don't surpass it. It's actually very unlikely we'll see an
640 /// attribute that needs more than that; on x86-64 you'd need 10
641 /// expression arguments, and on i386 you'd need 19.
642 InlineFreeListsCapacity =
643 1 + (AvailabilityAllocSize - sizeof(ParsedAttr)) / sizeof(void *)
646 llvm::BumpPtrAllocator Alloc;
648 /// Free lists. The index is determined by the following formula:
649 /// (size - sizeof(ParsedAttr)) / sizeof(void*)
650 SmallVector<SmallVector<ParsedAttr *, 8>, InlineFreeListsCapacity> FreeLists;
652 // The following are the private interface used by AttributePool.
653 friend class AttributePool;
655 /// Allocate an attribute of the given size.
656 void *allocate(size_t size);
658 void deallocate(ParsedAttr *AL);
660 /// Reclaim all the attributes in the given pool chain, which is
661 /// non-empty. Note that the current implementation is safe
662 /// against reclaiming things which were not actually allocated
663 /// with the allocator, although of course it's important to make
664 /// sure that their allocator lives at least as long as this one.
665 void reclaimPool(AttributePool &head);
672 class AttributePool {
673 friend class AttributeFactory;
674 friend class ParsedAttributes;
675 AttributeFactory &Factory;
676 llvm::SmallVector<ParsedAttr *> Attrs;
678 void *allocate(size_t size) {
679 return Factory.allocate(size);
682 ParsedAttr *add(ParsedAttr *attr) {
683 Attrs.push_back(attr);
687 void remove(ParsedAttr *attr) {
688 assert(llvm::is_contained(Attrs, attr) &&
689 "Can't take attribute from a pool that doesn't own it!");
690 Attrs.erase(llvm::find(Attrs, attr));
693 void takePool(AttributePool &pool);
696 /// Create a new pool for a factory.
697 AttributePool(AttributeFactory &factory) : Factory(factory) {}
699 AttributePool(const AttributePool &) = delete;
700 // The copy assignment operator is defined as deleted pending further
702 AttributePool &operator=(const AttributePool &) = delete;
704 ~AttributePool() { Factory.reclaimPool(*this); }
706 /// Move the given pool's allocations to this pool.
707 AttributePool(AttributePool &&pool) = default;
709 // The move assignment operator is defined as deleted pending further
711 AttributePool &operator=(AttributePool &&pool) = delete;
713 AttributeFactory &getFactory() const { return Factory; }
716 Factory.reclaimPool(*this);
720 /// Take the given pool's allocations and add them to this pool.
721 void takeAllFrom(AttributePool &pool) {
726 ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange,
727 IdentifierInfo *scopeName, SourceLocation scopeLoc,
728 ArgsUnion *args, unsigned numArgs, ParsedAttr::Form form,
729 SourceLocation ellipsisLoc = SourceLocation()) {
731 ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
732 detail::TypeTagForDatatypeData, ParsedType,
733 detail::PropertyData>(numArgs, 0, 0, 0, 0);
735 void *memory = allocate(
736 ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
737 detail::TypeTagForDatatypeData, ParsedType,
738 detail::PropertyData>(numArgs, 0, 0, 0,
740 return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
741 args, numArgs, form, ellipsisLoc));
744 ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange,
745 IdentifierInfo *scopeName, SourceLocation scopeLoc,
746 IdentifierLoc *Param, const AvailabilityChange &introduced,
747 const AvailabilityChange &deprecated,
748 const AvailabilityChange &obsoleted,
749 SourceLocation unavailable, const Expr *MessageExpr,
750 ParsedAttr::Form form, SourceLocation strict,
751 const Expr *ReplacementExpr) {
752 void *memory = allocate(AttributeFactory::AvailabilityAllocSize);
753 return add(new (memory) ParsedAttr(
754 attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated,
755 obsoleted, unavailable, MessageExpr, form, strict, ReplacementExpr));
758 ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange,
759 IdentifierInfo *scopeName, SourceLocation scopeLoc,
760 IdentifierLoc *Param1, IdentifierLoc *Param2,
761 IdentifierLoc *Param3, ParsedAttr::Form form) {
762 void *memory = allocate(
763 ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
764 detail::TypeTagForDatatypeData, ParsedType,
765 detail::PropertyData>(3, 0, 0, 0, 0));
766 return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
767 Param1, Param2, Param3, form));
771 createTypeTagForDatatype(IdentifierInfo *attrName, SourceRange attrRange,
772 IdentifierInfo *scopeName, SourceLocation scopeLoc,
773 IdentifierLoc *argumentKind,
774 ParsedType matchingCType, bool layoutCompatible,
775 bool mustBeNull, ParsedAttr::Form form) {
776 void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize);
777 return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
778 argumentKind, matchingCType,
779 layoutCompatible, mustBeNull, form));
782 ParsedAttr *createTypeAttribute(IdentifierInfo *attrName,
783 SourceRange attrRange,
784 IdentifierInfo *scopeName,
785 SourceLocation scopeLoc, ParsedType typeArg,
786 ParsedAttr::Form formUsed,
787 SourceLocation ellipsisLoc) {
788 void *memory = allocate(
789 ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
790 detail::TypeTagForDatatypeData, ParsedType,
791 detail::PropertyData>(0, 0, 0, 1, 0));
792 return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
793 typeArg, formUsed, ellipsisLoc));
797 createPropertyAttribute(IdentifierInfo *attrName, SourceRange attrRange,
798 IdentifierInfo *scopeName, SourceLocation scopeLoc,
799 IdentifierInfo *getterId, IdentifierInfo *setterId,
800 ParsedAttr::Form formUsed) {
801 void *memory = allocate(AttributeFactory::PropertyAllocSize);
802 return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
803 getterId, setterId, formUsed));
807 class ParsedAttributesView {
808 using VecTy = llvm::SmallVector<ParsedAttr *>;
809 using SizeType = decltype(std::declval<VecTy>().size());
814 static const ParsedAttributesView &none() {
815 static const ParsedAttributesView Attrs;
819 bool empty() const { return AttrList.empty(); }
820 SizeType size() const { return AttrList.size(); }
821 ParsedAttr &operator[](SizeType pos) { return *AttrList[pos]; }
822 const ParsedAttr &operator[](SizeType pos) const { return *AttrList[pos]; }
824 void addAtEnd(ParsedAttr *newAttr) {
826 AttrList.push_back(newAttr);
829 void remove(ParsedAttr *ToBeRemoved) {
830 assert(is_contained(AttrList, ToBeRemoved) &&
831 "Cannot remove attribute that isn't in the list");
832 AttrList.erase(llvm::find(AttrList, ToBeRemoved));
835 void clearListOnly() { AttrList.clear(); }
837 struct iterator : llvm::iterator_adaptor_base<iterator, VecTy::iterator,
838 std::random_access_iterator_tag,
840 iterator() : iterator_adaptor_base(nullptr) {}
841 iterator(VecTy::iterator I) : iterator_adaptor_base(I) {}
842 reference operator*() const { return **I; }
843 friend class ParsedAttributesView;
845 struct const_iterator
846 : llvm::iterator_adaptor_base<const_iterator, VecTy::const_iterator,
847 std::random_access_iterator_tag,
849 const_iterator() : iterator_adaptor_base(nullptr) {}
850 const_iterator(VecTy::const_iterator I) : iterator_adaptor_base(I) {}
852 reference operator*() const { return **I; }
853 friend class ParsedAttributesView;
856 void addAll(iterator B, iterator E) {
857 AttrList.insert(AttrList.begin(), B.I, E.I);
860 void addAll(const_iterator B, const_iterator E) {
861 AttrList.insert(AttrList.begin(), B.I, E.I);
864 void addAllAtEnd(iterator B, iterator E) {
865 AttrList.insert(AttrList.end(), B.I, E.I);
868 void addAllAtEnd(const_iterator B, const_iterator E) {
869 AttrList.insert(AttrList.end(), B.I, E.I);
872 iterator begin() { return iterator(AttrList.begin()); }
873 const_iterator begin() const { return const_iterator(AttrList.begin()); }
874 iterator end() { return iterator(AttrList.end()); }
875 const_iterator end() const { return const_iterator(AttrList.end()); }
877 ParsedAttr &front() {
879 return *AttrList.front();
881 const ParsedAttr &front() const {
883 return *AttrList.front();
887 return *AttrList.back();
889 const ParsedAttr &back() const {
891 return *AttrList.back();
894 bool hasAttribute(ParsedAttr::Kind K) const {
895 return llvm::any_of(AttrList, [K](const ParsedAttr *AL) {
896 return AL->getParsedKind() == K;
900 const ParsedAttr *getMSPropertyAttr() const {
901 auto It = llvm::find_if(AttrList, [](const ParsedAttr *AL) {
902 return AL->isDeclspecPropertyAttribute();
904 if (It != AttrList.end())
908 bool hasMSPropertyAttr() const { return getMSPropertyAttr(); }
914 /// ParsedAttributes - A collection of parsed attributes. Currently
915 /// we don't differentiate between the various attribute syntaxes,
916 /// which is basically silly.
918 /// Right now this is a very lightweight container, but the expectation
919 /// is that this will become significantly more serious.
920 class ParsedAttributes : public ParsedAttributesView {
922 ParsedAttributes(AttributeFactory &factory) : pool(factory) {}
923 ParsedAttributes(const ParsedAttributes &) = delete;
924 ParsedAttributes &operator=(const ParsedAttributes &) = delete;
926 AttributePool &getPool() const { return pool; }
928 void takeAllFrom(ParsedAttributes &Other) {
929 assert(&Other != this &&
930 "ParsedAttributes can't take attributes from itself");
931 addAll(Other.begin(), Other.end());
932 Other.clearListOnly();
933 pool.takeAllFrom(Other.pool);
936 void takeOneFrom(ParsedAttributes &Other, ParsedAttr *PA) {
937 assert(&Other != this &&
938 "ParsedAttributes can't take attribute from itself");
939 Other.getPool().remove(PA);
948 Range = SourceRange();
951 /// Add attribute with expression arguments.
952 ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange,
953 IdentifierInfo *scopeName, SourceLocation scopeLoc,
954 ArgsUnion *args, unsigned numArgs, ParsedAttr::Form form,
955 SourceLocation ellipsisLoc = SourceLocation()) {
956 ParsedAttr *attr = pool.create(attrName, attrRange, scopeName, scopeLoc,
957 args, numArgs, form, ellipsisLoc);
962 /// Add availability attribute.
963 ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange,
964 IdentifierInfo *scopeName, SourceLocation scopeLoc,
965 IdentifierLoc *Param, const AvailabilityChange &introduced,
966 const AvailabilityChange &deprecated,
967 const AvailabilityChange &obsoleted,
968 SourceLocation unavailable, const Expr *MessageExpr,
969 ParsedAttr::Form form, SourceLocation strict,
970 const Expr *ReplacementExpr) {
971 ParsedAttr *attr = pool.create(
972 attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated,
973 obsoleted, unavailable, MessageExpr, form, strict, ReplacementExpr);
978 /// Add objc_bridge_related attribute.
979 ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange,
980 IdentifierInfo *scopeName, SourceLocation scopeLoc,
981 IdentifierLoc *Param1, IdentifierLoc *Param2,
982 IdentifierLoc *Param3, ParsedAttr::Form form) {
983 ParsedAttr *attr = pool.create(attrName, attrRange, scopeName, scopeLoc,
984 Param1, Param2, Param3, form);
989 /// Add type_tag_for_datatype attribute.
991 addNewTypeTagForDatatype(IdentifierInfo *attrName, SourceRange attrRange,
992 IdentifierInfo *scopeName, SourceLocation scopeLoc,
993 IdentifierLoc *argumentKind,
994 ParsedType matchingCType, bool layoutCompatible,
995 bool mustBeNull, ParsedAttr::Form form) {
996 ParsedAttr *attr = pool.createTypeTagForDatatype(
997 attrName, attrRange, scopeName, scopeLoc, argumentKind, matchingCType,
998 layoutCompatible, mustBeNull, form);
1003 /// Add an attribute with a single type argument.
1004 ParsedAttr *addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange,
1005 IdentifierInfo *scopeName, SourceLocation scopeLoc,
1006 ParsedType typeArg, ParsedAttr::Form formUsed,
1007 SourceLocation ellipsisLoc = SourceLocation()) {
1009 pool.createTypeAttribute(attrName, attrRange, scopeName, scopeLoc,
1010 typeArg, formUsed, ellipsisLoc);
1015 /// Add microsoft __delspec(property) attribute.
1017 addNewPropertyAttr(IdentifierInfo *attrName, SourceRange attrRange,
1018 IdentifierInfo *scopeName, SourceLocation scopeLoc,
1019 IdentifierInfo *getterId, IdentifierInfo *setterId,
1020 ParsedAttr::Form formUsed) {
1021 ParsedAttr *attr = pool.createPropertyAttribute(
1022 attrName, attrRange, scopeName, scopeLoc, getterId, setterId, formUsed);
1028 mutable AttributePool pool;
1031 /// Consumes the attributes from `First` and `Second` and concatenates them into
1032 /// `Result`. Sets `Result.Range` to the combined range of `First` and `Second`.
1033 void takeAndConcatenateAttrs(ParsedAttributes &First, ParsedAttributes &Second,
1034 ParsedAttributes &Result);
1036 /// These constants match the enumerated choices of
1037 /// err_attribute_argument_n_type and err_attribute_argument_type.
1038 enum AttributeArgumentNType {
1039 AANT_ArgumentIntOrBool,
1040 AANT_ArgumentIntegerConstant,
1041 AANT_ArgumentString,
1042 AANT_ArgumentIdentifier,
1043 AANT_ArgumentConstantExpr,
1044 AANT_ArgumentBuiltinFunction,
1047 /// These constants match the enumerated choices of
1048 /// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type.
1049 enum AttributeDeclKind {
1052 ExpectedVariableOrFunction,
1053 ExpectedFunctionOrMethod,
1054 ExpectedFunctionMethodOrBlock,
1055 ExpectedFunctionMethodOrParameter,
1057 ExpectedVariableOrField,
1058 ExpectedVariableFieldOrTag,
1059 ExpectedTypeOrNamespace,
1060 ExpectedFunctionVariableOrClass,
1061 ExpectedKernelFunction,
1062 ExpectedFunctionWithProtoType,
1065 inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
1066 const ParsedAttr &At) {
1067 DB.AddTaggedVal(reinterpret_cast<uint64_t>(At.getAttrName()),
1068 DiagnosticsEngine::ak_identifierinfo);
1072 inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
1073 const ParsedAttr *At) {
1074 DB.AddTaggedVal(reinterpret_cast<uint64_t>(At->getAttrName()),
1075 DiagnosticsEngine::ak_identifierinfo);
1079 /// AttributeCommonInfo has a non-explicit constructor which takes an
1080 /// SourceRange as its only argument, this constructor has many uses so making
1081 /// it explicit is hard. This constructor causes ambiguity with
1082 /// DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, SourceRange R).
1083 /// We use SFINAE to disable any conversion and remove any ambiguity.
1086 std::enable_if_t<std::is_same<ACI, AttributeCommonInfo>::value, int> = 0>
1087 inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
1089 DB.AddTaggedVal(reinterpret_cast<uint64_t>(CI.getAttrName()),
1090 DiagnosticsEngine::ak_identifierinfo);
1096 std::enable_if_t<std::is_same<ACI, AttributeCommonInfo>::value, int> = 0>
1097 inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
1099 DB.AddTaggedVal(reinterpret_cast<uint64_t>(CI->getAttrName()),
1100 DiagnosticsEngine::ak_identifierinfo);
1104 } // namespace clang
1106 #endif // LLVM_CLANG_SEMA_PARSEDATTR_H