- //======- ParsedAttr.h - Parsed attribute sets ------------------*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- // 
- // This file defines the ParsedAttr class, which is used to collect 
- // parsed attributes. 
- // 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_CLANG_SEMA_PARSEDATTR_H 
- #define LLVM_CLANG_SEMA_PARSEDATTR_H 
-   
- #include "clang/Basic/AttrSubjectMatchRules.h" 
- #include "clang/Basic/AttributeCommonInfo.h" 
- #include "clang/Basic/Diagnostic.h" 
- #include "clang/Basic/SourceLocation.h" 
- #include "clang/Sema/Ownership.h" 
- #include "llvm/ADT/PointerUnion.h" 
- #include "llvm/ADT/SmallVector.h" 
- #include "llvm/Support/Allocator.h" 
- #include "llvm/Support/Registry.h" 
- #include "llvm/Support/VersionTuple.h" 
- #include <cassert> 
- #include <cstddef> 
- #include <cstring> 
- #include <utility> 
-   
- namespace clang { 
-   
- class ASTContext; 
- class Decl; 
- class Expr; 
- class IdentifierInfo; 
- class LangOptions; 
- class ParsedAttr; 
- class Sema; 
- class Stmt; 
- class TargetInfo; 
-   
- struct ParsedAttrInfo { 
-   /// Corresponds to the Kind enum. 
-   unsigned AttrKind : 16; 
-   /// The number of required arguments of this attribute. 
-   unsigned NumArgs : 4; 
-   /// The number of optional arguments of this attributes. 
-   unsigned OptArgs : 4; 
-   /// The number of non-fake arguments specified in the attribute definition. 
-   unsigned NumArgMembers : 4; 
-   /// True if the parsing does not match the semantic content. 
-   unsigned HasCustomParsing : 1; 
-   // True if this attribute accepts expression parameter pack expansions. 
-   unsigned AcceptsExprPack : 1; 
-   /// True if this attribute is only available for certain targets. 
-   unsigned IsTargetSpecific : 1; 
-   /// True if this attribute applies to types. 
-   unsigned IsType : 1; 
-   /// True if this attribute applies to statements. 
-   unsigned IsStmt : 1; 
-   /// True if this attribute has any spellings that are known to gcc. 
-   unsigned IsKnownToGCC : 1; 
-   /// True if this attribute is supported by #pragma clang attribute. 
-   unsigned IsSupportedByPragmaAttribute : 1; 
-   /// The syntaxes supported by this attribute and how they're spelled. 
-   struct Spelling { 
-     AttributeCommonInfo::Syntax Syntax; 
-     const char *NormalizedFullName; 
-   }; 
-   ArrayRef<Spelling> Spellings; 
-   // The names of the known arguments of this attribute. 
-   ArrayRef<const char *> ArgNames; 
-   
- protected: 
-   constexpr ParsedAttrInfo(AttributeCommonInfo::Kind AttrKind = 
-                                AttributeCommonInfo::NoSemaHandlerAttribute) 
-       : AttrKind(AttrKind), NumArgs(0), OptArgs(0), NumArgMembers(0), 
-         HasCustomParsing(0), AcceptsExprPack(0), IsTargetSpecific(0), IsType(0), 
-         IsStmt(0), IsKnownToGCC(0), IsSupportedByPragmaAttribute(0) {} 
-   
-   constexpr ParsedAttrInfo(AttributeCommonInfo::Kind AttrKind, unsigned NumArgs, 
-                            unsigned OptArgs, unsigned NumArgMembers, 
-                            unsigned HasCustomParsing, unsigned AcceptsExprPack, 
-                            unsigned IsTargetSpecific, unsigned IsType, 
-                            unsigned IsStmt, unsigned IsKnownToGCC, 
-                            unsigned IsSupportedByPragmaAttribute, 
-                            ArrayRef<Spelling> Spellings, 
-                            ArrayRef<const char *> ArgNames) 
-       : AttrKind(AttrKind), NumArgs(NumArgs), OptArgs(OptArgs), 
-         NumArgMembers(NumArgMembers), HasCustomParsing(HasCustomParsing), 
-         AcceptsExprPack(AcceptsExprPack), IsTargetSpecific(IsTargetSpecific), 
-         IsType(IsType), IsStmt(IsStmt), IsKnownToGCC(IsKnownToGCC), 
-         IsSupportedByPragmaAttribute(IsSupportedByPragmaAttribute), 
-         Spellings(Spellings), ArgNames(ArgNames) {} 
-   
- public: 
-   virtual ~ParsedAttrInfo() = default; 
-   
-   /// Check if this attribute appertains to D, and issue a diagnostic if not. 
-   virtual bool diagAppertainsToDecl(Sema &S, const ParsedAttr &Attr, 
-                                     const Decl *D) const { 
-     return true; 
-   } 
-   /// Check if this attribute appertains to St, and issue a diagnostic if not. 
-   virtual bool diagAppertainsToStmt(Sema &S, const ParsedAttr &Attr, 
-                                     const Stmt *St) const { 
-     return true; 
-   } 
-   /// Check if the given attribute is mutually exclusive with other attributes 
-   /// already applied to the given declaration. 
-   virtual bool diagMutualExclusion(Sema &S, const ParsedAttr &A, 
-                                    const Decl *D) const { 
-     return true; 
-   } 
-   /// Check if this attribute is allowed by the language we are compiling. 
-   virtual bool acceptsLangOpts(const LangOptions &LO) const { return true; } 
-   
-   /// Check if this attribute is allowed when compiling for the given target. 
-   virtual bool existsInTarget(const TargetInfo &Target) const { 
-     return true; 
-   } 
-   /// Convert the spelling index of Attr to a semantic spelling enum value. 
-   virtual unsigned 
-   spellingIndexToSemanticSpelling(const ParsedAttr &Attr) const { 
-     return UINT_MAX; 
-   } 
-   /// Returns true if the specified parameter index for this attribute in 
-   /// Attr.td is an ExprArgument or VariadicExprArgument, or a subclass thereof; 
-   /// returns false otherwise. 
-   virtual bool isParamExpr(size_t N) const { return false; } 
-   /// Populate Rules with the match rules of this attribute. 
-   virtual void getPragmaAttributeMatchRules( 
-       llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &Rules, 
-       const LangOptions &LangOpts) const { 
-   } 
-   enum AttrHandling { 
-     NotHandled, 
-     AttributeApplied, 
-     AttributeNotApplied 
-   }; 
-   /// If this ParsedAttrInfo knows how to handle this ParsedAttr applied to this 
-   /// Decl then do so and return either AttributeApplied if it was applied or 
-   /// AttributeNotApplied if it wasn't. Otherwise return NotHandled. 
-   virtual AttrHandling handleDeclAttribute(Sema &S, Decl *D, 
-                                            const ParsedAttr &Attr) const { 
-     return NotHandled; 
-   } 
-   
-   static const ParsedAttrInfo &get(const AttributeCommonInfo &A); 
-   static ArrayRef<const ParsedAttrInfo *> getAllBuiltin(); 
- }; 
-   
- typedef llvm::Registry<ParsedAttrInfo> ParsedAttrInfoRegistry; 
-   
- /// Represents information about a change in availability for 
- /// an entity, which is part of the encoding of the 'availability' 
- /// attribute. 
- struct AvailabilityChange { 
-   /// The location of the keyword indicating the kind of change. 
-   SourceLocation KeywordLoc; 
-   
-   /// The version number at which the change occurred. 
-   VersionTuple Version; 
-   
-   /// The source range covering the version number. 
-   SourceRange VersionRange; 
-   
-   /// Determine whether this availability change is valid. 
-   bool isValid() const { return !Version.empty(); } 
- }; 
-   
- namespace detail { 
- enum AvailabilitySlot { 
-   IntroducedSlot, DeprecatedSlot, ObsoletedSlot, NumAvailabilitySlots 
- }; 
-   
- /// Describes the trailing object for Availability attribute in ParsedAttr. 
- struct AvailabilityData { 
-   AvailabilityChange Changes[NumAvailabilitySlots]; 
-   SourceLocation StrictLoc; 
-   const Expr *Replacement; 
-   
-   AvailabilityData(const AvailabilityChange &Introduced, 
-                    const AvailabilityChange &Deprecated, 
-                    const AvailabilityChange &Obsoleted, 
-                    SourceLocation Strict, const Expr *ReplaceExpr) 
-     : StrictLoc(Strict), Replacement(ReplaceExpr) { 
-     Changes[IntroducedSlot] = Introduced; 
-     Changes[DeprecatedSlot] = Deprecated; 
-     Changes[ObsoletedSlot] = Obsoleted; 
-   } 
- }; 
-   
- struct TypeTagForDatatypeData { 
-   ParsedType MatchingCType; 
-   unsigned LayoutCompatible : 1; 
-   unsigned MustBeNull : 1; 
- }; 
- struct PropertyData { 
-   IdentifierInfo *GetterId, *SetterId; 
-   
-   PropertyData(IdentifierInfo *getterId, IdentifierInfo *setterId) 
-       : GetterId(getterId), SetterId(setterId) {} 
- }; 
-   
- } // namespace 
-   
- /// Wraps an identifier and optional source location for the identifier. 
- struct IdentifierLoc { 
-   SourceLocation Loc; 
-   IdentifierInfo *Ident; 
-   
-   static IdentifierLoc *create(ASTContext &Ctx, SourceLocation Loc, 
-                                IdentifierInfo *Ident); 
- }; 
-   
- /// A union of the various pointer types that can be passed to an 
- /// ParsedAttr as an argument. 
- using ArgsUnion = llvm::PointerUnion<Expr *, IdentifierLoc *>; 
- using ArgsVector = llvm::SmallVector<ArgsUnion, 12U>; 
-   
- /// ParsedAttr - Represents a syntactic attribute. 
- /// 
- /// For a GNU attribute, there are four forms of this construct: 
- /// 
- /// 1: __attribute__(( const )). ParmName/Args/NumArgs will all be unused. 
- /// 2: __attribute__(( mode(byte) )). ParmName used, Args/NumArgs unused. 
- /// 3: __attribute__(( format(printf, 1, 2) )). ParmName/Args/NumArgs all used. 
- /// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used. 
- /// 
- class ParsedAttr final 
-     : public AttributeCommonInfo, 
-       private llvm::TrailingObjects< 
-           ParsedAttr, ArgsUnion, detail::AvailabilityData, 
-           detail::TypeTagForDatatypeData, ParsedType, detail::PropertyData> { 
-   friend TrailingObjects; 
-   
-   size_t numTrailingObjects(OverloadToken<ArgsUnion>) const { return NumArgs; } 
-   size_t numTrailingObjects(OverloadToken<detail::AvailabilityData>) const { 
-     return IsAvailability; 
-   } 
-   size_t 
-       numTrailingObjects(OverloadToken<detail::TypeTagForDatatypeData>) const { 
-     return IsTypeTagForDatatype; 
-   } 
-   size_t numTrailingObjects(OverloadToken<ParsedType>) const { 
-     return HasParsedType; 
-   } 
-   size_t numTrailingObjects(OverloadToken<detail::PropertyData>) const { 
-     return IsProperty; 
-   } 
-   
- private: 
-   IdentifierInfo *MacroII = nullptr; 
-   SourceLocation MacroExpansionLoc; 
-   SourceLocation EllipsisLoc; 
-   
-   /// The number of expression arguments this attribute has. 
-   /// The expressions themselves are stored after the object. 
-   unsigned NumArgs : 16; 
-   
-   /// True if already diagnosed as invalid. 
-   mutable unsigned Invalid : 1; 
-   
-   /// True if this attribute was used as a type attribute. 
-   mutable unsigned UsedAsTypeAttr : 1; 
-   
-   /// True if this has the extra information associated with an 
-   /// availability attribute. 
-   unsigned IsAvailability : 1; 
-   
-   /// True if this has extra information associated with a 
-   /// type_tag_for_datatype attribute. 
-   unsigned IsTypeTagForDatatype : 1; 
-   
-   /// True if this has extra information associated with a 
-   /// Microsoft __delcspec(property) attribute. 
-   unsigned IsProperty : 1; 
-   
-   /// True if this has a ParsedType 
-   unsigned HasParsedType : 1; 
-   
-   /// True if the processing cache is valid. 
-   mutable unsigned HasProcessingCache : 1; 
-   
-   /// A cached value. 
-   mutable unsigned ProcessingCache : 8; 
-   
-   /// True if the attribute is specified using '#pragma clang attribute'. 
-   mutable unsigned IsPragmaClangAttribute : 1; 
-   
-   /// The location of the 'unavailable' keyword in an 
-   /// availability attribute. 
-   SourceLocation UnavailableLoc; 
-   
-   const Expr *MessageExpr; 
-   
-   const ParsedAttrInfo &Info; 
-   
-   ArgsUnion *getArgsBuffer() { return getTrailingObjects<ArgsUnion>(); } 
-   ArgsUnion const *getArgsBuffer() const { 
-     return getTrailingObjects<ArgsUnion>(); 
-   } 
-   
-   detail::AvailabilityData *getAvailabilityData() { 
-     return getTrailingObjects<detail::AvailabilityData>(); 
-   } 
-   const detail::AvailabilityData *getAvailabilityData() const { 
-     return getTrailingObjects<detail::AvailabilityData>(); 
-   } 
-   
- private: 
-   friend class AttributeFactory; 
-   friend class AttributePool; 
-   
-   /// Constructor for attributes with expression arguments. 
-   ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, 
-              IdentifierInfo *scopeName, SourceLocation scopeLoc, 
-              ArgsUnion *args, unsigned numArgs, Syntax syntaxUsed, 
-              SourceLocation ellipsisLoc) 
-       : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, 
-                             syntaxUsed), 
-         EllipsisLoc(ellipsisLoc), NumArgs(numArgs), Invalid(false), 
-         UsedAsTypeAttr(false), IsAvailability(false), 
-         IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false), 
-         HasProcessingCache(false), IsPragmaClangAttribute(false), 
-         Info(ParsedAttrInfo::get(*this)) { 
-     if (numArgs) 
-       memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion)); 
-   } 
-   
-   /// Constructor for availability attributes. 
-   ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, 
-              IdentifierInfo *scopeName, SourceLocation scopeLoc, 
-              IdentifierLoc *Parm, const AvailabilityChange &introduced, 
-              const AvailabilityChange &deprecated, 
-              const AvailabilityChange &obsoleted, SourceLocation unavailable, 
-              const Expr *messageExpr, Syntax syntaxUsed, SourceLocation strict, 
-              const Expr *replacementExpr) 
-       : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, 
-                             syntaxUsed), 
-         NumArgs(1), Invalid(false), UsedAsTypeAttr(false), IsAvailability(true), 
-         IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false), 
-         HasProcessingCache(false), IsPragmaClangAttribute(false), 
-         UnavailableLoc(unavailable), MessageExpr(messageExpr), 
-         Info(ParsedAttrInfo::get(*this)) { 
-     ArgsUnion PVal(Parm); 
-     memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion)); 
-     new (getAvailabilityData()) detail::AvailabilityData( 
-         introduced, deprecated, obsoleted, strict, replacementExpr); 
-   } 
-   
-   /// Constructor for objc_bridge_related attributes. 
-   ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, 
-              IdentifierInfo *scopeName, SourceLocation scopeLoc, 
-              IdentifierLoc *Parm1, IdentifierLoc *Parm2, IdentifierLoc *Parm3, 
-              Syntax syntaxUsed) 
-       : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, 
-                             syntaxUsed), 
-         NumArgs(3), Invalid(false), UsedAsTypeAttr(false), 
-         IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false), 
-         HasParsedType(false), HasProcessingCache(false), 
-         IsPragmaClangAttribute(false), Info(ParsedAttrInfo::get(*this)) { 
-     ArgsUnion *Args = getArgsBuffer(); 
-     Args[0] = Parm1; 
-     Args[1] = Parm2; 
-     Args[2] = Parm3; 
-   } 
-   
-   /// Constructor for type_tag_for_datatype attribute. 
-   ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, 
-              IdentifierInfo *scopeName, SourceLocation scopeLoc, 
-              IdentifierLoc *ArgKind, ParsedType matchingCType, 
-              bool layoutCompatible, bool mustBeNull, Syntax syntaxUsed) 
-       : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, 
-                             syntaxUsed), 
-         NumArgs(1), Invalid(false), UsedAsTypeAttr(false), 
-         IsAvailability(false), IsTypeTagForDatatype(true), IsProperty(false), 
-         HasParsedType(false), HasProcessingCache(false), 
-         IsPragmaClangAttribute(false), Info(ParsedAttrInfo::get(*this)) { 
-     ArgsUnion PVal(ArgKind); 
-     memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion)); 
-     detail::TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot(); 
-     new (&ExtraData.MatchingCType) ParsedType(matchingCType); 
-     ExtraData.LayoutCompatible = layoutCompatible; 
-     ExtraData.MustBeNull = mustBeNull; 
-   } 
-   
-   /// Constructor for attributes with a single type argument. 
-   ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, 
-              IdentifierInfo *scopeName, SourceLocation scopeLoc, 
-              ParsedType typeArg, Syntax syntaxUsed) 
-       : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, 
-                             syntaxUsed), 
-         NumArgs(0), Invalid(false), UsedAsTypeAttr(false), 
-         IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false), 
-         HasParsedType(true), HasProcessingCache(false), 
-         IsPragmaClangAttribute(false), Info(ParsedAttrInfo::get(*this)) { 
-     new (&getTypeBuffer()) ParsedType(typeArg); 
-   } 
-   
-   /// Constructor for microsoft __declspec(property) attribute. 
-   ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, 
-              IdentifierInfo *scopeName, SourceLocation scopeLoc, 
-              IdentifierInfo *getterId, IdentifierInfo *setterId, 
-              Syntax syntaxUsed) 
-       : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, 
-                             syntaxUsed), 
-         NumArgs(0), Invalid(false), UsedAsTypeAttr(false), 
-         IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(true), 
-         HasParsedType(false), HasProcessingCache(false), 
-         IsPragmaClangAttribute(false), Info(ParsedAttrInfo::get(*this)) { 
-     new (&getPropertyDataBuffer()) detail::PropertyData(getterId, setterId); 
-   } 
-   
-   /// Type tag information is stored immediately following the arguments, if 
-   /// any, at the end of the object.  They are mutually exclusive with 
-   /// availability slots. 
-   detail::TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() { 
-     return *getTrailingObjects<detail::TypeTagForDatatypeData>(); 
-   } 
-   const detail::TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const { 
-     return *getTrailingObjects<detail::TypeTagForDatatypeData>(); 
-   } 
-   
-   /// The type buffer immediately follows the object and are mutually exclusive 
-   /// with arguments. 
-   ParsedType &getTypeBuffer() { return *getTrailingObjects<ParsedType>(); } 
-   const ParsedType &getTypeBuffer() const { 
-     return *getTrailingObjects<ParsedType>(); 
-   } 
-   
-   /// The property data immediately follows the object is mutually exclusive 
-   /// with arguments. 
-   detail::PropertyData &getPropertyDataBuffer() { 
-     assert(IsProperty); 
-     return *getTrailingObjects<detail::PropertyData>(); 
-   } 
-   const detail::PropertyData &getPropertyDataBuffer() const { 
-     assert(IsProperty); 
-     return *getTrailingObjects<detail::PropertyData>(); 
-   } 
-   
-   size_t allocated_size() const; 
-   
- public: 
-   ParsedAttr(const ParsedAttr &) = delete; 
-   ParsedAttr(ParsedAttr &&) = delete; 
-   ParsedAttr &operator=(const ParsedAttr &) = delete; 
-   ParsedAttr &operator=(ParsedAttr &&) = delete; 
-   ~ParsedAttr() = delete; 
-   
-   void operator delete(void *) = delete; 
-   
-   bool hasParsedType() const { return HasParsedType; } 
-   
-   /// Is this the Microsoft __declspec(property) attribute? 
-   bool isDeclspecPropertyAttribute() const  { 
-     return IsProperty; 
-   } 
-   
-   bool isInvalid() const { return Invalid; } 
-   void setInvalid(bool b = true) const { Invalid = b; } 
-   
-   bool hasProcessingCache() const { return HasProcessingCache; } 
-   
-   unsigned getProcessingCache() const { 
-     assert(hasProcessingCache()); 
-     return ProcessingCache; 
-   } 
-   
-   void setProcessingCache(unsigned value) const { 
-     ProcessingCache = value; 
-     HasProcessingCache = true; 
-   } 
-   
-   bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; } 
-   void setUsedAsTypeAttr(bool Used = true) { UsedAsTypeAttr = Used; } 
-   
-   /// True if the attribute is specified using '#pragma clang attribute'. 
-   bool isPragmaClangAttribute() const { return IsPragmaClangAttribute; } 
-   
-   void setIsPragmaClangAttribute() { IsPragmaClangAttribute = true; } 
-   
-   bool isPackExpansion() const { return EllipsisLoc.isValid(); } 
-   SourceLocation getEllipsisLoc() const { return EllipsisLoc; } 
-   
-   /// getNumArgs - Return the number of actual arguments to this attribute. 
-   unsigned getNumArgs() const { return NumArgs; } 
-   
-   /// getArg - Return the specified argument. 
-   ArgsUnion getArg(unsigned Arg) const { 
-     assert(Arg < NumArgs && "Arg access out of range!"); 
-     return getArgsBuffer()[Arg]; 
-   } 
-   
-   bool isArgExpr(unsigned Arg) const { 
-     return Arg < NumArgs && getArg(Arg).is<Expr*>(); 
-   } 
-   
-   Expr *getArgAsExpr(unsigned Arg) const { 
-     return getArg(Arg).get<Expr*>(); 
-   } 
-   
-   bool isArgIdent(unsigned Arg) const { 
-     return Arg < NumArgs && getArg(Arg).is<IdentifierLoc*>(); 
-   } 
-   
-   IdentifierLoc *getArgAsIdent(unsigned Arg) const { 
-     return getArg(Arg).get<IdentifierLoc*>(); 
-   } 
-   
-   const AvailabilityChange &getAvailabilityIntroduced() const { 
-     assert(getParsedKind() == AT_Availability && 
-            "Not an availability attribute"); 
-     return getAvailabilityData()->Changes[detail::IntroducedSlot]; 
-   } 
-   
-   const AvailabilityChange &getAvailabilityDeprecated() const { 
-     assert(getParsedKind() == AT_Availability && 
-            "Not an availability attribute"); 
-     return getAvailabilityData()->Changes[detail::DeprecatedSlot]; 
-   } 
-   
-   const AvailabilityChange &getAvailabilityObsoleted() const { 
-     assert(getParsedKind() == AT_Availability && 
-            "Not an availability attribute"); 
-     return getAvailabilityData()->Changes[detail::ObsoletedSlot]; 
-   } 
-   
-   SourceLocation getStrictLoc() const { 
-     assert(getParsedKind() == AT_Availability && 
-            "Not an availability attribute"); 
-     return getAvailabilityData()->StrictLoc; 
-   } 
-   
-   SourceLocation getUnavailableLoc() const { 
-     assert(getParsedKind() == AT_Availability && 
-            "Not an availability attribute"); 
-     return UnavailableLoc; 
-   } 
-   
-   const Expr * getMessageExpr() const { 
-     assert(getParsedKind() == AT_Availability && 
-            "Not an availability attribute"); 
-     return MessageExpr; 
-   } 
-   
-   const Expr *getReplacementExpr() const { 
-     assert(getParsedKind() == AT_Availability && 
-            "Not an availability attribute"); 
-     return getAvailabilityData()->Replacement; 
-   } 
-   
-   const ParsedType &getMatchingCType() const { 
-     assert(getParsedKind() == AT_TypeTagForDatatype && 
-            "Not a type_tag_for_datatype attribute"); 
-     return getTypeTagForDatatypeDataSlot().MatchingCType; 
-   } 
-   
-   bool getLayoutCompatible() const { 
-     assert(getParsedKind() == AT_TypeTagForDatatype && 
-            "Not a type_tag_for_datatype attribute"); 
-     return getTypeTagForDatatypeDataSlot().LayoutCompatible; 
-   } 
-   
-   bool getMustBeNull() const { 
-     assert(getParsedKind() == AT_TypeTagForDatatype && 
-            "Not a type_tag_for_datatype attribute"); 
-     return getTypeTagForDatatypeDataSlot().MustBeNull; 
-   } 
-   
-   const ParsedType &getTypeArg() const { 
-     assert(HasParsedType && "Not a type attribute"); 
-     return getTypeBuffer(); 
-   } 
-   
-   IdentifierInfo *getPropertyDataGetter() const { 
-     assert(isDeclspecPropertyAttribute() && 
-            "Not a __delcspec(property) attribute"); 
-     return getPropertyDataBuffer().GetterId; 
-   } 
-   
-   IdentifierInfo *getPropertyDataSetter() const { 
-     assert(isDeclspecPropertyAttribute() && 
-            "Not a __delcspec(property) attribute"); 
-     return getPropertyDataBuffer().SetterId; 
-   } 
-   
-   /// Set the macro identifier info object that this parsed attribute was 
-   /// declared in if it was declared in a macro. Also set the expansion location 
-   /// of the macro. 
-   void setMacroIdentifier(IdentifierInfo *MacroName, SourceLocation Loc) { 
-     MacroII = MacroName; 
-     MacroExpansionLoc = Loc; 
-   } 
-   
-   /// Returns true if this attribute was declared in a macro. 
-   bool hasMacroIdentifier() const { return MacroII != nullptr; } 
-   
-   /// Return the macro identifier if this attribute was declared in a macro. 
-   /// nullptr is returned if it was not declared in a macro. 
-   IdentifierInfo *getMacroIdentifier() const { return MacroII; } 
-   
-   SourceLocation getMacroExpansionLoc() const { 
-     assert(hasMacroIdentifier() && "Can only get the macro expansion location " 
-                                    "if this attribute has a macro identifier."); 
-     return MacroExpansionLoc; 
-   } 
-   
-   /// Check if the attribute has exactly as many args as Num. May output an 
-   /// error. Returns false if a diagnostic is produced. 
-   bool checkExactlyNumArgs(class Sema &S, unsigned Num) const; 
-   /// Check if the attribute has at least as many args as Num. May output an 
-   /// error. Returns false if a diagnostic is produced. 
-   bool checkAtLeastNumArgs(class Sema &S, unsigned Num) const; 
-   /// Check if the attribute has at most as many args as Num. May output an 
-   /// error. Returns false if a diagnostic is produced. 
-   bool checkAtMostNumArgs(class Sema &S, unsigned Num) const; 
-   
-   bool isTargetSpecificAttr() const; 
-   bool isTypeAttr() const; 
-   bool isStmtAttr() const; 
-   
-   bool hasCustomParsing() const; 
-   bool acceptsExprPack() const; 
-   bool isParamExpr(size_t N) const; 
-   unsigned getMinArgs() const; 
-   unsigned getMaxArgs() const; 
-   unsigned getNumArgMembers() const; 
-   bool hasVariadicArg() const; 
-   void handleAttrWithDelayedArgs(Sema &S, Decl *D) const; 
-   bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const; 
-   bool diagnoseAppertainsTo(class Sema &S, const Stmt *St) const; 
-   bool diagnoseMutualExclusion(class Sema &S, const Decl *D) const; 
-   // This function stub exists for parity with the declaration checking code so 
-   // that checkCommonAttributeFeatures() can work generically on declarations 
-   // or statements. 
-   bool diagnoseMutualExclusion(class Sema &S, const Stmt *St) const { 
-     return true; 
-   } 
-   bool appliesToDecl(const Decl *D, attr::SubjectMatchRule MatchRule) const; 
-   void getMatchRules(const LangOptions &LangOpts, 
-                      SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> 
-                          &MatchRules) const; 
-   bool diagnoseLangOpts(class Sema &S) const; 
-   bool existsInTarget(const TargetInfo &Target) const; 
-   bool isKnownToGCC() const; 
-   bool isSupportedByPragmaAttribute() const; 
-   
-   /// Returns whether a [[]] attribute, if specified ahead of a declaration, 
-   /// should be applied to the decl-specifier-seq instead (i.e. whether it 
-   /// "slides" to the decl-specifier-seq). 
-   /// 
-   /// By the standard, attributes specified before the declaration always 
-   /// appertain to the declaration, but historically we have allowed some of 
-   /// these attributes to slide to the decl-specifier-seq, so we need to keep 
-   /// supporting this behavior. 
-   /// 
-   /// This may only be called if isStandardAttributeSyntax() returns true. 
-   bool slidesFromDeclToDeclSpecLegacyBehavior() const; 
-   
-   /// If the parsed attribute has a semantic equivalent, and it would 
-   /// have a semantic Spelling enumeration (due to having semantically-distinct 
-   /// spelling variations), return the value of that semantic spelling. If the 
-   /// parsed attribute does not have a semantic equivalent, or would not have 
-   /// a Spelling enumeration, the value UINT_MAX is returned. 
-   unsigned getSemanticSpelling() const; 
-   
-   /// If this is an OpenCL address space attribute, returns its representation 
-   /// in LangAS, otherwise returns default address space. 
-   LangAS asOpenCLLangAS() const { 
-     switch (getParsedKind()) { 
-     case ParsedAttr::AT_OpenCLConstantAddressSpace: 
-       return LangAS::opencl_constant; 
-     case ParsedAttr::AT_OpenCLGlobalAddressSpace: 
-       return LangAS::opencl_global; 
-     case ParsedAttr::AT_OpenCLGlobalDeviceAddressSpace: 
-       return LangAS::opencl_global_device; 
-     case ParsedAttr::AT_OpenCLGlobalHostAddressSpace: 
-       return LangAS::opencl_global_host; 
-     case ParsedAttr::AT_OpenCLLocalAddressSpace: 
-       return LangAS::opencl_local; 
-     case ParsedAttr::AT_OpenCLPrivateAddressSpace: 
-       return LangAS::opencl_private; 
-     case ParsedAttr::AT_OpenCLGenericAddressSpace: 
-       return LangAS::opencl_generic; 
-     default: 
-       return LangAS::Default; 
-     } 
-   } 
-   
-   /// If this is an OpenCL address space attribute, returns its SYCL 
-   /// representation in LangAS, otherwise returns default address space. 
-   LangAS asSYCLLangAS() const { 
-     switch (getKind()) { 
-     case ParsedAttr::AT_OpenCLGlobalAddressSpace: 
-       return LangAS::sycl_global; 
-     case ParsedAttr::AT_OpenCLGlobalDeviceAddressSpace: 
-       return LangAS::sycl_global_device; 
-     case ParsedAttr::AT_OpenCLGlobalHostAddressSpace: 
-       return LangAS::sycl_global_host; 
-     case ParsedAttr::AT_OpenCLLocalAddressSpace: 
-       return LangAS::sycl_local; 
-     case ParsedAttr::AT_OpenCLPrivateAddressSpace: 
-       return LangAS::sycl_private; 
-     case ParsedAttr::AT_OpenCLGenericAddressSpace: 
-     default: 
-       return LangAS::Default; 
-     } 
-   } 
-   
-   /// If this is an HLSL address space attribute, returns its representation 
-   /// in LangAS, otherwise returns default address space. 
-   LangAS asHLSLLangAS() const { 
-     switch (getParsedKind()) { 
-     case ParsedAttr::AT_HLSLGroupSharedAddressSpace: 
-       return LangAS::hlsl_groupshared; 
-     default: 
-       return LangAS::Default; 
-     } 
-   } 
-   
-   AttributeCommonInfo::Kind getKind() const { 
-     return AttributeCommonInfo::Kind(Info.AttrKind); 
-   } 
-   const ParsedAttrInfo &getInfo() const { return Info; } 
- }; 
-   
- class AttributePool; 
- /// A factory, from which one makes pools, from which one creates 
- /// individual attributes which are deallocated with the pool. 
- /// 
- /// Note that it's tolerably cheap to create and destroy one of 
- /// these as long as you don't actually allocate anything in it. 
- class AttributeFactory { 
- public: 
-   enum { 
-     AvailabilityAllocSize = 
-         ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, 
-                                      detail::TypeTagForDatatypeData, ParsedType, 
-                                      detail::PropertyData>(1, 1, 0, 0, 0), 
-     TypeTagForDatatypeAllocSize = 
-         ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, 
-                                      detail::TypeTagForDatatypeData, ParsedType, 
-                                      detail::PropertyData>(1, 0, 1, 0, 0), 
-     PropertyAllocSize = 
-         ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, 
-                                      detail::TypeTagForDatatypeData, ParsedType, 
-                                      detail::PropertyData>(0, 0, 0, 0, 1), 
-   }; 
-   
- private: 
-   enum { 
-     /// The number of free lists we want to be sure to support 
-     /// inline.  This is just enough that availability attributes 
-     /// don't surpass it.  It's actually very unlikely we'll see an 
-     /// attribute that needs more than that; on x86-64 you'd need 10 
-     /// expression arguments, and on i386 you'd need 19. 
-     InlineFreeListsCapacity = 
-         1 + (AvailabilityAllocSize - sizeof(ParsedAttr)) / sizeof(void *) 
-   }; 
-   
-   llvm::BumpPtrAllocator Alloc; 
-   
-   /// Free lists.  The index is determined by the following formula: 
-   ///   (size - sizeof(ParsedAttr)) / sizeof(void*) 
-   SmallVector<SmallVector<ParsedAttr *, 8>, InlineFreeListsCapacity> FreeLists; 
-   
-   // The following are the private interface used by AttributePool. 
-   friend class AttributePool; 
-   
-   /// Allocate an attribute of the given size. 
-   void *allocate(size_t size); 
-   
-   void deallocate(ParsedAttr *AL); 
-   
-   /// Reclaim all the attributes in the given pool chain, which is 
-   /// non-empty.  Note that the current implementation is safe 
-   /// against reclaiming things which were not actually allocated 
-   /// with the allocator, although of course it's important to make 
-   /// sure that their allocator lives at least as long as this one. 
-   void reclaimPool(AttributePool &head); 
-   
- public: 
-   AttributeFactory(); 
-   ~AttributeFactory(); 
- }; 
-   
- class AttributePool { 
-   friend class AttributeFactory; 
-   friend class ParsedAttributes; 
-   AttributeFactory &Factory; 
-   llvm::SmallVector<ParsedAttr *> Attrs; 
-   
-   void *allocate(size_t size) { 
-     return Factory.allocate(size); 
-   } 
-   
-   ParsedAttr *add(ParsedAttr *attr) { 
-     Attrs.push_back(attr); 
-     return attr; 
-   } 
-   
-   void remove(ParsedAttr *attr) { 
-     assert(llvm::is_contained(Attrs, attr) && 
-            "Can't take attribute from a pool that doesn't own it!"); 
-     Attrs.erase(llvm::find(Attrs, attr)); 
-   } 
-   
-   void takePool(AttributePool &pool); 
-   
- public: 
-   /// Create a new pool for a factory. 
-   AttributePool(AttributeFactory &factory) : Factory(factory) {} 
-   
-   AttributePool(const AttributePool &) = delete; 
-   
-   ~AttributePool() { Factory.reclaimPool(*this); } 
-   
-   /// Move the given pool's allocations to this pool. 
-   AttributePool(AttributePool &&pool) = default; 
-   
-   AttributeFactory &getFactory() const { return Factory; } 
-   
-   void clear() { 
-     Factory.reclaimPool(*this); 
-     Attrs.clear(); 
-   } 
-   
-   /// Take the given pool's allocations and add them to this pool. 
-   void takeAllFrom(AttributePool &pool) { 
-     takePool(pool); 
-     pool.Attrs.clear(); 
-   } 
-   
-   ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange, 
-                      IdentifierInfo *scopeName, SourceLocation scopeLoc, 
-                      ArgsUnion *args, unsigned numArgs, 
-                      ParsedAttr::Syntax syntax, 
-                      SourceLocation ellipsisLoc = SourceLocation()) { 
-     size_t temp = 
-         ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, 
-                                      detail::TypeTagForDatatypeData, ParsedType, 
-                                      detail::PropertyData>(numArgs, 0, 0, 0, 0); 
-     (void)temp; 
-     void *memory = allocate( 
-         ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, 
-                                      detail::TypeTagForDatatypeData, ParsedType, 
-                                      detail::PropertyData>(numArgs, 0, 0, 0, 
-                                                            0)); 
-     return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, 
-                                        args, numArgs, syntax, ellipsisLoc)); 
-   } 
-   
-   ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange, 
-                      IdentifierInfo *scopeName, SourceLocation scopeLoc, 
-                      IdentifierLoc *Param, const AvailabilityChange &introduced, 
-                      const AvailabilityChange &deprecated, 
-                      const AvailabilityChange &obsoleted, 
-                      SourceLocation unavailable, const Expr *MessageExpr, 
-                      ParsedAttr::Syntax syntax, SourceLocation strict, 
-                      const Expr *ReplacementExpr) { 
-     void *memory = allocate(AttributeFactory::AvailabilityAllocSize); 
-     return add(new (memory) ParsedAttr( 
-         attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated, 
-         obsoleted, unavailable, MessageExpr, syntax, strict, ReplacementExpr)); 
-   } 
-   
-   ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange, 
-                      IdentifierInfo *scopeName, SourceLocation scopeLoc, 
-                      IdentifierLoc *Param1, IdentifierLoc *Param2, 
-                      IdentifierLoc *Param3, ParsedAttr::Syntax syntax) { 
-     void *memory = allocate( 
-         ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, 
-                                      detail::TypeTagForDatatypeData, ParsedType, 
-                                      detail::PropertyData>(3, 0, 0, 0, 0)); 
-     return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, 
-                                        Param1, Param2, Param3, syntax)); 
-   } 
-   
-   ParsedAttr * 
-   createTypeTagForDatatype(IdentifierInfo *attrName, SourceRange attrRange, 
-                            IdentifierInfo *scopeName, SourceLocation scopeLoc, 
-                            IdentifierLoc *argumentKind, 
-                            ParsedType matchingCType, bool layoutCompatible, 
-                            bool mustBeNull, ParsedAttr::Syntax syntax) { 
-     void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize); 
-     return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, 
-                                        argumentKind, matchingCType, 
-                                        layoutCompatible, mustBeNull, syntax)); 
-   } 
-   
-   ParsedAttr *createTypeAttribute(IdentifierInfo *attrName, 
-                                   SourceRange attrRange, 
-                                   IdentifierInfo *scopeName, 
-                                   SourceLocation scopeLoc, ParsedType typeArg, 
-                                   ParsedAttr::Syntax syntaxUsed) { 
-     void *memory = allocate( 
-         ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, 
-                                      detail::TypeTagForDatatypeData, ParsedType, 
-                                      detail::PropertyData>(0, 0, 0, 1, 0)); 
-     return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, 
-                                        typeArg, syntaxUsed)); 
-   } 
-   
-   ParsedAttr * 
-   createPropertyAttribute(IdentifierInfo *attrName, SourceRange attrRange, 
-                           IdentifierInfo *scopeName, SourceLocation scopeLoc, 
-                           IdentifierInfo *getterId, IdentifierInfo *setterId, 
-                           ParsedAttr::Syntax syntaxUsed) { 
-     void *memory = allocate(AttributeFactory::PropertyAllocSize); 
-     return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, 
-                                        getterId, setterId, syntaxUsed)); 
-   } 
- }; 
-   
- class ParsedAttributesView { 
-   using VecTy = llvm::SmallVector<ParsedAttr *>; 
-   using SizeType = decltype(std::declval<VecTy>().size()); 
-   
- public: 
-   SourceRange Range; 
-   
-   static const ParsedAttributesView &none() { 
-     static const ParsedAttributesView Attrs; 
-     return Attrs; 
-   } 
-   
-   bool empty() const { return AttrList.empty(); } 
-   SizeType size() const { return AttrList.size(); } 
-   ParsedAttr &operator[](SizeType pos) { return *AttrList[pos]; } 
-   const ParsedAttr &operator[](SizeType pos) const { return *AttrList[pos]; } 
-   
-   void addAtEnd(ParsedAttr *newAttr) { 
-     assert(newAttr); 
-     AttrList.push_back(newAttr); 
-   } 
-   
-   void remove(ParsedAttr *ToBeRemoved) { 
-     assert(is_contained(AttrList, ToBeRemoved) && 
-            "Cannot remove attribute that isn't in the list"); 
-     AttrList.erase(llvm::find(AttrList, ToBeRemoved)); 
-   } 
-   
-   void clearListOnly() { AttrList.clear(); } 
-   
-   struct iterator : llvm::iterator_adaptor_base<iterator, VecTy::iterator, 
-                                                 std::random_access_iterator_tag, 
-                                                 ParsedAttr> { 
-     iterator() : iterator_adaptor_base(nullptr) {} 
-     iterator(VecTy::iterator I) : iterator_adaptor_base(I) {} 
-     reference operator*() const { return **I; } 
-     friend class ParsedAttributesView; 
-   }; 
-   struct const_iterator 
-       : llvm::iterator_adaptor_base<const_iterator, VecTy::const_iterator, 
-                                     std::random_access_iterator_tag, 
-                                     ParsedAttr> { 
-     const_iterator() : iterator_adaptor_base(nullptr) {} 
-     const_iterator(VecTy::const_iterator I) : iterator_adaptor_base(I) {} 
-   
-     reference operator*() const { return **I; } 
-     friend class ParsedAttributesView; 
-   }; 
-   
-   void addAll(iterator B, iterator E) { 
-     AttrList.insert(AttrList.begin(), B.I, E.I); 
-   } 
-   
-   void addAll(const_iterator B, const_iterator E) { 
-     AttrList.insert(AttrList.begin(), B.I, E.I); 
-   } 
-   
-   void addAllAtEnd(iterator B, iterator E) { 
-     AttrList.insert(AttrList.end(), B.I, E.I); 
-   } 
-   
-   void addAllAtEnd(const_iterator B, const_iterator E) { 
-     AttrList.insert(AttrList.end(), B.I, E.I); 
-   } 
-   
-   iterator begin() { return iterator(AttrList.begin()); } 
-   const_iterator begin() const { return const_iterator(AttrList.begin()); } 
-   iterator end() { return iterator(AttrList.end()); } 
-   const_iterator end() const { return const_iterator(AttrList.end()); } 
-   
-   ParsedAttr &front() { 
-     assert(!empty()); 
-     return *AttrList.front(); 
-   } 
-   const ParsedAttr &front() const { 
-     assert(!empty()); 
-     return *AttrList.front(); 
-   } 
-   ParsedAttr &back() { 
-     assert(!empty()); 
-     return *AttrList.back(); 
-   } 
-   const ParsedAttr &back() const { 
-     assert(!empty()); 
-     return *AttrList.back(); 
-   } 
-   
-   bool hasAttribute(ParsedAttr::Kind K) const { 
-     return llvm::any_of(AttrList, [K](const ParsedAttr *AL) { 
-       return AL->getParsedKind() == K; 
-     }); 
-   } 
-   
- private: 
-   VecTy AttrList; 
- }; 
-   
- /// ParsedAttributes - A collection of parsed attributes.  Currently 
- /// we don't differentiate between the various attribute syntaxes, 
- /// which is basically silly. 
- /// 
- /// Right now this is a very lightweight container, but the expectation 
- /// is that this will become significantly more serious. 
- class ParsedAttributes : public ParsedAttributesView { 
- public: 
-   ParsedAttributes(AttributeFactory &factory) : pool(factory) {} 
-   ParsedAttributes(const ParsedAttributes &) = delete; 
-   
-   AttributePool &getPool() const { return pool; } 
-   
-   void takeAllFrom(ParsedAttributes &Other) { 
-     assert(&Other != this && 
-            "ParsedAttributes can't take attributes from itself"); 
-     addAll(Other.begin(), Other.end()); 
-     Other.clearListOnly(); 
-     pool.takeAllFrom(Other.pool); 
-   } 
-   
-   void takeOneFrom(ParsedAttributes &Other, ParsedAttr *PA) { 
-     assert(&Other != this && 
-            "ParsedAttributes can't take attribute from itself"); 
-     Other.getPool().remove(PA); 
-     Other.remove(PA); 
-     getPool().add(PA); 
-     addAtEnd(PA); 
-   } 
-   
-   void clear() { 
-     clearListOnly(); 
-     pool.clear(); 
-     Range = SourceRange(); 
-   } 
-   
-   /// Add attribute with expression arguments. 
-   ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange, 
-                      IdentifierInfo *scopeName, SourceLocation scopeLoc, 
-                      ArgsUnion *args, unsigned numArgs, 
-                      ParsedAttr::Syntax syntax, 
-                      SourceLocation ellipsisLoc = SourceLocation()) { 
-     ParsedAttr *attr = pool.create(attrName, attrRange, scopeName, scopeLoc, 
-                                    args, numArgs, syntax, ellipsisLoc); 
-     addAtEnd(attr); 
-     return attr; 
-   } 
-   
-   /// Add availability attribute. 
-   ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange, 
-                      IdentifierInfo *scopeName, SourceLocation scopeLoc, 
-                      IdentifierLoc *Param, const AvailabilityChange &introduced, 
-                      const AvailabilityChange &deprecated, 
-                      const AvailabilityChange &obsoleted, 
-                      SourceLocation unavailable, const Expr *MessageExpr, 
-                      ParsedAttr::Syntax syntax, SourceLocation strict, 
-                      const Expr *ReplacementExpr) { 
-     ParsedAttr *attr = pool.create( 
-         attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated, 
-         obsoleted, unavailable, MessageExpr, syntax, strict, ReplacementExpr); 
-     addAtEnd(attr); 
-     return attr; 
-   } 
-   
-   /// Add objc_bridge_related attribute. 
-   ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange, 
-                      IdentifierInfo *scopeName, SourceLocation scopeLoc, 
-                      IdentifierLoc *Param1, IdentifierLoc *Param2, 
-                      IdentifierLoc *Param3, ParsedAttr::Syntax syntax) { 
-     ParsedAttr *attr = pool.create(attrName, attrRange, scopeName, scopeLoc, 
-                                    Param1, Param2, Param3, syntax); 
-     addAtEnd(attr); 
-     return attr; 
-   } 
-   
-   /// Add type_tag_for_datatype attribute. 
-   ParsedAttr * 
-   addNewTypeTagForDatatype(IdentifierInfo *attrName, SourceRange attrRange, 
-                            IdentifierInfo *scopeName, SourceLocation scopeLoc, 
-                            IdentifierLoc *argumentKind, 
-                            ParsedType matchingCType, bool layoutCompatible, 
-                            bool mustBeNull, ParsedAttr::Syntax syntax) { 
-     ParsedAttr *attr = pool.createTypeTagForDatatype( 
-         attrName, attrRange, scopeName, scopeLoc, argumentKind, matchingCType, 
-         layoutCompatible, mustBeNull, syntax); 
-     addAtEnd(attr); 
-     return attr; 
-   } 
-   
-   /// Add an attribute with a single type argument. 
-   ParsedAttr *addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange, 
-                              IdentifierInfo *scopeName, SourceLocation scopeLoc, 
-                              ParsedType typeArg, 
-                              ParsedAttr::Syntax syntaxUsed) { 
-     ParsedAttr *attr = pool.createTypeAttribute(attrName, attrRange, scopeName, 
-                                                 scopeLoc, typeArg, syntaxUsed); 
-     addAtEnd(attr); 
-     return attr; 
-   } 
-   
-   /// Add microsoft __delspec(property) attribute. 
-   ParsedAttr * 
-   addNewPropertyAttr(IdentifierInfo *attrName, SourceRange attrRange, 
-                      IdentifierInfo *scopeName, SourceLocation scopeLoc, 
-                      IdentifierInfo *getterId, IdentifierInfo *setterId, 
-                      ParsedAttr::Syntax syntaxUsed) { 
-     ParsedAttr *attr = 
-         pool.createPropertyAttribute(attrName, attrRange, scopeName, scopeLoc, 
-                                      getterId, setterId, syntaxUsed); 
-     addAtEnd(attr); 
-     return attr; 
-   } 
-   
- private: 
-   mutable AttributePool pool; 
- }; 
-   
- /// Consumes the attributes from `First` and `Second` and concatenates them into 
- /// `Result`. Sets `Result.Range` to the combined range of `First` and `Second`. 
- void takeAndConcatenateAttrs(ParsedAttributes &First, ParsedAttributes &Second, 
-                              ParsedAttributes &Result); 
-   
- /// These constants match the enumerated choices of 
- /// err_attribute_argument_n_type and err_attribute_argument_type. 
- enum AttributeArgumentNType { 
-   AANT_ArgumentIntOrBool, 
-   AANT_ArgumentIntegerConstant, 
-   AANT_ArgumentString, 
-   AANT_ArgumentIdentifier, 
-   AANT_ArgumentConstantExpr, 
-   AANT_ArgumentBuiltinFunction, 
- }; 
-   
- /// These constants match the enumerated choices of 
- /// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type. 
- enum AttributeDeclKind { 
-   ExpectedFunction, 
-   ExpectedUnion, 
-   ExpectedVariableOrFunction, 
-   ExpectedFunctionOrMethod, 
-   ExpectedFunctionMethodOrBlock, 
-   ExpectedFunctionMethodOrParameter, 
-   ExpectedVariable, 
-   ExpectedVariableOrField, 
-   ExpectedVariableFieldOrTag, 
-   ExpectedTypeOrNamespace, 
-   ExpectedFunctionVariableOrClass, 
-   ExpectedKernelFunction, 
-   ExpectedFunctionWithProtoType, 
- }; 
-   
- inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, 
-                                              const ParsedAttr &At) { 
-   DB.AddTaggedVal(reinterpret_cast<uint64_t>(At.getAttrName()), 
-                   DiagnosticsEngine::ak_identifierinfo); 
-   return DB; 
- } 
-   
- inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, 
-                                              const ParsedAttr *At) { 
-   DB.AddTaggedVal(reinterpret_cast<uint64_t>(At->getAttrName()), 
-                   DiagnosticsEngine::ak_identifierinfo); 
-   return DB; 
- } 
-   
- /// AttributeCommonInfo has a non-explicit constructor which takes an 
- /// SourceRange as its only argument, this constructor has many uses so making 
- /// it explicit is hard. This constructor causes ambiguity with 
- /// DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, SourceRange R). 
- /// We use SFINAE to disable any conversion and remove any ambiguity. 
- template < 
-     typename ACI, 
-     std::enable_if_t<std::is_same<ACI, AttributeCommonInfo>::value, int> = 0> 
- inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, 
-                                              const ACI &CI) { 
-   DB.AddTaggedVal(reinterpret_cast<uint64_t>(CI.getAttrName()), 
-                   DiagnosticsEngine::ak_identifierinfo); 
-   return DB; 
- } 
-   
- template < 
-     typename ACI, 
-     std::enable_if_t<std::is_same<ACI, AttributeCommonInfo>::value, int> = 0> 
- inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, 
-                                              const ACI *CI) { 
-   DB.AddTaggedVal(reinterpret_cast<uint64_t>(CI->getAttrName()), 
-                   DiagnosticsEngine::ak_identifierinfo); 
-   return DB; 
- } 
-   
- } // namespace clang 
-   
- #endif // LLVM_CLANG_SEMA_PARSEDATTR_H 
-