r340215 - Model type attributes as regular Attrs.

Mikael Holmén via cfe-commits cfe-commits at lists.llvm.org
Tue Aug 21 00:23:51 PDT 2018



On 08/21/2018 08:11 AM, Mikael Holmén wrote:
> Hi,
> 
> I get a warning with this:
> 
> [1/16] Building CXX object 
> tools/clang/lib/Sema/CMakeFiles/clangSema.dir/SemaType.cpp.o
> ../tools/clang/lib/Sema/SemaType.cpp: In function 'bool 
> handleFunctionTypeAttr({anonymous}::TypeProcessingState&, 
> clang::ParsedAttr&, clang::QualType&)':
> ../tools/clang/lib/Sema/SemaType.cpp:6788:31: warning: unused variable 
> 'AT' [-Wunused-variable]
>       if (const AttributedType *AT = 
> S.getCallingConvAttributedType(type)) {
>                                 ^

I fixed in r340251.

/Mikael
> /Mikael
> 
> On 08/20/2018 11:47 PM, Richard Smith via cfe-commits wrote:
>> Author: rsmith
>> Date: Mon Aug 20 14:47:29 2018
>> New Revision: 340215
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=340215&view=rev
>> Log:
>> Model type attributes as regular Attrs.
>>
>> Specifically, AttributedType now tracks a regular attr::Kind rather than
>> having its own parallel Kind enumeration, and AttributedTypeLoc now
>> holds an Attr* instead of holding an ad-hoc collection of Attr fields.
>>
>> Differential Revision: https://reviews.llvm.org/D50526
>>
>> This reinstates r339623, reverted in r339638, with a fix to not fail
>> template instantiation if we instantiate a QualType with no associated
>> type source information and we encounter an AttributedType.
>>
>> Modified:
>>      cfe/trunk/include/clang/AST/ASTContext.h
>>      cfe/trunk/include/clang/AST/Attr.h
>>      cfe/trunk/include/clang/AST/Type.h
>>      cfe/trunk/include/clang/AST/TypeLoc.h
>>      cfe/trunk/include/clang/Basic/Attr.td
>>      cfe/trunk/include/clang/Sema/Sema.h
>>      cfe/trunk/include/clang/Serialization/ASTReader.h
>>      cfe/trunk/include/clang/Serialization/ASTWriter.h
>>      cfe/trunk/lib/ARCMigrate/TransGCAttrs.cpp
>>      cfe/trunk/lib/ARCMigrate/Transforms.cpp
>>      cfe/trunk/lib/AST/ASTContext.cpp
>>      cfe/trunk/lib/AST/Type.cpp
>>      cfe/trunk/lib/AST/TypeLoc.cpp
>>      cfe/trunk/lib/AST/TypePrinter.cpp
>>      cfe/trunk/lib/Sema/SemaDecl.cpp
>>      cfe/trunk/lib/Sema/SemaExpr.cpp
>>      cfe/trunk/lib/Sema/SemaInit.cpp
>>      cfe/trunk/lib/Sema/SemaObjCProperty.cpp
>>      cfe/trunk/lib/Sema/SemaType.cpp
>>      cfe/trunk/lib/Sema/TreeTransform.h
>>      cfe/trunk/lib/Serialization/ASTReader.cpp
>>      cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
>>      cfe/trunk/lib/Serialization/ASTWriter.cpp
>>      cfe/trunk/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
>>      cfe/trunk/test/SemaCXX/calling-conv-compat.cpp
>>      cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
>>
>> Modified: cfe/trunk/include/clang/AST/ASTContext.h
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=340215&r1=340214&r2=340215&view=diff 
>>
>> ============================================================================== 
>>
>> --- cfe/trunk/include/clang/AST/ASTContext.h (original)
>> +++ cfe/trunk/include/clang/AST/ASTContext.h Mon Aug 20 14:47:29 2018
>> @@ -31,6 +31,7 @@
>>   #include "clang/AST/TemplateName.h"
>>   #include "clang/AST/Type.h"
>>   #include "clang/Basic/AddressSpaces.h"
>> +#include "clang/Basic/AttrKinds.h"
>>   #include "clang/Basic/IdentifierTable.h"
>>   #include "clang/Basic/LLVM.h"
>>   #include "clang/Basic/LangOptions.h"
>> @@ -1422,7 +1423,7 @@ public:
>>     QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType 
>> TST) const;
>> -  QualType getAttributedType(AttributedType::Kind attrKind,
>> +  QualType getAttributedType(attr::Kind attrKind,
>>                                QualType modifiedType,
>>                                QualType equivalentType);
>>
>> Modified: cfe/trunk/include/clang/AST/Attr.h
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Attr.h?rev=340215&r1=340214&r2=340215&view=diff 
>>
>> ============================================================================== 
>>
>> --- cfe/trunk/include/clang/AST/Attr.h (original)
>> +++ cfe/trunk/include/clang/AST/Attr.h Mon Aug 20 14:47:29 2018
>> @@ -113,6 +113,19 @@ public:
>>     void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) 
>> const;
>>   };
>> +class TypeAttr : public Attr {
>> +protected:
>> +  TypeAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
>> +           bool IsLateParsed)
>> +      : Attr(AK, R, SpellingListIndex, IsLateParsed) {}
>> +
>> +public:
>> +  static bool classof(const Attr *A) {
>> +    return A->getKind() >= attr::FirstTypeAttr &&
>> +           A->getKind() <= attr::LastTypeAttr;
>> +  }
>> +};
>> +
>>   class StmtAttr : public Attr {
>>   protected:
>>     StmtAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
>>
>> Modified: cfe/trunk/include/clang/AST/Type.h
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=340215&r1=340214&r2=340215&view=diff 
>>
>> ============================================================================== 
>>
>> --- cfe/trunk/include/clang/AST/Type.h (original)
>> +++ cfe/trunk/include/clang/AST/Type.h Mon Aug 20 14:47:29 2018
>> @@ -21,6 +21,7 @@
>>   #include "clang/AST/NestedNameSpecifier.h"
>>   #include "clang/AST/TemplateName.h"
>>   #include "clang/Basic/AddressSpaces.h"
>> +#include "clang/Basic/AttrKinds.h"
>>   #include "clang/Basic/Diagnostic.h"
>>   #include "clang/Basic/ExceptionSpecificationType.h"
>>   #include "clang/Basic/LLVM.h"
>> @@ -1970,7 +1971,16 @@ public:
>>     bool isObjCQualifiedClassType() const;        // Class<foo>
>>     bool isObjCObjectOrInterfaceType() const;
>>     bool isObjCIdType() const;                    // id
>> -  bool isObjCInertUnsafeUnretainedType() const;
>> +
>> +  /// Was this type written with the special inert-in-ARC 
>> __unsafe_unretained
>> +  /// qualifier?
>> +  ///
>> +  /// This approximates the answer to the following question: if this
>> +  /// translation unit were compiled in ARC, would this type be 
>> qualified
>> +  /// with __unsafe_unretained?
>> +  bool isObjCInertUnsafeUnretainedType() const {
>> +    return hasAttr(attr::ObjCInertUnsafeUnretained);
>> +  }
>>     /// Whether the type is Objective-C 'id' or a __kindof type of an
>>     /// object type, e.g., __kindof NSView * or __kindof id
>> @@ -2184,6 +2194,10 @@ public:
>>     /// qualifiers from the outermost type.
>>     const ArrayType *castAsArrayTypeUnsafe() const;
>> +  /// Determine whether this type had the specified attribute applied 
>> to it
>> +  /// (looking through top-level type sugar).
>> +  bool hasAttr(attr::Kind AK) const;
>> +
>>     /// Get the base element type of this type, potentially discarding 
>> type
>>     /// qualifiers.  This should never be used when type qualifiers
>>     /// are meaningful.
>> @@ -4293,56 +4307,7 @@ public:
>>   ///   - the canonical type is VectorType(16, int)
>>   class AttributedType : public Type, public llvm::FoldingSetNode {
>>   public:
>> -  // It is really silly to have yet another attribute-kind enum, but
>> -  // clang::attr::Kind doesn't currently cover the pure type attrs.
>> -  enum Kind {
>> -    // Expression operand.
>> -    attr_address_space,
>> -    attr_regparm,
>> -    attr_vector_size,
>> -    attr_neon_vector_type,
>> -    attr_neon_polyvector_type,
>> -
>> -    FirstExprOperandKind = attr_address_space,
>> -    LastExprOperandKind = attr_neon_polyvector_type,
>> -
>> -    // Enumerated operand (string or keyword).
>> -    attr_objc_gc,
>> -    attr_objc_ownership,
>> -    attr_pcs,
>> -    attr_pcs_vfp,
>> -
>> -    FirstEnumOperandKind = attr_objc_gc,
>> -    LastEnumOperandKind = attr_pcs_vfp,
>> -
>> -    // No operand.
>> -    attr_noreturn,
>> -    attr_nocf_check,
>> -    attr_cdecl,
>> -    attr_fastcall,
>> -    attr_stdcall,
>> -    attr_thiscall,
>> -    attr_regcall,
>> -    attr_pascal,
>> -    attr_swiftcall,
>> -    attr_vectorcall,
>> -    attr_inteloclbicc,
>> -    attr_ms_abi,
>> -    attr_sysv_abi,
>> -    attr_preserve_most,
>> -    attr_preserve_all,
>> -    attr_ptr32,
>> -    attr_ptr64,
>> -    attr_sptr,
>> -    attr_uptr,
>> -    attr_nonnull,
>> -    attr_ns_returns_retained,
>> -    attr_nullable,
>> -    attr_null_unspecified,
>> -    attr_objc_kindof,
>> -    attr_objc_inert_unsafe_unretained,
>> -    attr_lifetimebound,
>> -  };
>> +  using Kind = attr::Kind;
>>   private:
>>     friend class ASTContext; // ASTContext creates these
>> @@ -4350,7 +4315,7 @@ private:
>>     QualType ModifiedType;
>>     QualType EquivalentType;
>> -  AttributedType(QualType canon, Kind attrKind, QualType modified,
>> +  AttributedType(QualType canon, attr::Kind attrKind, QualType modified,
>>                    QualType equivalent)
>>         : Type(Attributed, canon, equivalent->isDependentType(),
>>                equivalent->isInstantiationDependentType(),
>> @@ -4399,13 +4364,13 @@ public:
>>     static Kind getNullabilityAttrKind(NullabilityKind kind) {
>>       switch (kind) {
>>       case NullabilityKind::NonNull:
>> -      return attr_nonnull;
>> +      return attr::TypeNonNull;
>>       case NullabilityKind::Nullable:
>> -      return attr_nullable;
>> +      return attr::TypeNullable;
>>       case NullabilityKind::Unspecified:
>> -      return attr_null_unspecified;
>> +      return attr::TypeNullUnspecified;
>>       }
>>       llvm_unreachable("Unknown nullability kind.");
>>     }
>>
>> Modified: cfe/trunk/include/clang/AST/TypeLoc.h
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeLoc.h?rev=340215&r1=340214&r2=340215&view=diff 
>>
>> ============================================================================== 
>>
>> --- cfe/trunk/include/clang/AST/TypeLoc.h (original)
>> +++ cfe/trunk/include/clang/AST/TypeLoc.h Mon Aug 20 14:47:29 2018
>> @@ -15,6 +15,7 @@
>>   #ifndef LLVM_CLANG_AST_TYPELOC_H
>>   #define LLVM_CLANG_AST_TYPELOC_H
>> +#include "clang/AST/Attr.h"
>>   #include "clang/AST/Decl.h"
>>   #include "clang/AST/NestedNameSpecifier.h"
>>   #include "clang/AST/TemplateBase.h"
>> @@ -849,16 +850,7 @@ class SubstTemplateTypeParmPackTypeLoc :
>>   };
>>   struct AttributedLocInfo {
>> -  union {
>> -    Expr *ExprOperand;
>> -
>> -    /// A raw SourceLocation.
>> -    unsigned EnumOperandLoc;
>> -  };
>> -
>> -  SourceRange OperandParens;
>> -
>> -  SourceLocation AttrLoc;
>> +  const Attr *TypeAttr;
>>   };
>>   /// Type source information for an attributed type.
>> @@ -867,24 +859,10 @@ class AttributedTypeLoc : public Concret
>>                                                    AttributedType,
>>                                                    AttributedLocInfo> {
>>   public:
>> -  AttributedType::Kind getAttrKind() const {
>> +  attr::Kind getAttrKind() const {
>>       return getTypePtr()->getAttrKind();
>>     }
>> -  bool hasAttrExprOperand() const {
>> -    return (getAttrKind() >= AttributedType::FirstExprOperandKind &&
>> -            getAttrKind() <= AttributedType::LastExprOperandKind);
>> -  }
>> -
>> -  bool hasAttrEnumOperand() const {
>> -    return (getAttrKind() >= AttributedType::FirstEnumOperandKind &&
>> -            getAttrKind() <= AttributedType::LastEnumOperandKind);
>> -  }
>> -
>> -  bool hasAttrOperand() const {
>> -    return hasAttrExprOperand() || hasAttrEnumOperand();
>> -  }
>> -
>>     bool isQualifier() const {
>>       return getTypePtr()->isQualifier();
>>     }
>> @@ -897,51 +875,16 @@ public:
>>       return getInnerTypeLoc();
>>     }
>> -  /// The location of the attribute name, i.e.
>> -  ///    __attribute__((regparm(1000)))
>> -  ///                   ^~~~~~~
>> -  SourceLocation getAttrNameLoc() const {
>> -    return getLocalData()->AttrLoc;
>> -  }
>> -  void setAttrNameLoc(SourceLocation loc) {
>> -    getLocalData()->AttrLoc = loc;
>> -  }
>> -
>> -  /// The attribute's expression operand, if it has one.
>> -  ///    void *cur_thread __attribute__((address_space(21)))
>> -  ///                                                  ^~
>> -  Expr *getAttrExprOperand() const {
>> -    assert(hasAttrExprOperand());
>> -    return getLocalData()->ExprOperand;
>> -  }
>> -  void setAttrExprOperand(Expr *e) {
>> -    assert(hasAttrExprOperand());
>> -    getLocalData()->ExprOperand = e;
>> -  }
>> -
>> -  /// The location of the attribute's enumerated operand, if it has one.
>> -  ///    void * __attribute__((objc_gc(weak)))
>> -  ///                                  ^~~~
>> -  SourceLocation getAttrEnumOperandLoc() const {
>> -    assert(hasAttrEnumOperand());
>> -    return 
>> SourceLocation::getFromRawEncoding(getLocalData()->EnumOperandLoc);
>> -  }
>> -  void setAttrEnumOperandLoc(SourceLocation loc) {
>> -    assert(hasAttrEnumOperand());
>> -    getLocalData()->EnumOperandLoc = loc.getRawEncoding();
>> -  }
>> -
>> -  /// The location of the parentheses around the operand, if there is
>> -  /// an operand.
>> -  ///    void * __attribute__((objc_gc(weak)))
>> -  ///                                 ^    ^
>> -  SourceRange getAttrOperandParensRange() const {
>> -    assert(hasAttrOperand());
>> -    return getLocalData()->OperandParens;
>> -  }
>> -  void setAttrOperandParensRange(SourceRange range) {
>> -    assert(hasAttrOperand());
>> -    getLocalData()->OperandParens = range;
>> +  /// The type attribute.
>> +  const Attr *getAttr() const {
>> +    return getLocalData()->TypeAttr;
>> +  }
>> +  void setAttr(const Attr *A) {
>> +    getLocalData()->TypeAttr = A;
>> +  }
>> +
>> +  template<typename T> const T *getAttrAs() {
>> +    return dyn_cast_or_null<T>(getAttr());
>>     }
>>     SourceRange getLocalSourceRange() const {
>> @@ -954,21 +897,11 @@ public:
>>       //    ^~        ~~
>>       // That enclosure doesn't necessarily belong to a single attribute
>>       // anyway.
>> -    SourceRange range(getAttrNameLoc());
>> -    if (hasAttrOperand())
>> -      range.setEnd(getAttrOperandParensRange().getEnd());
>> -    return range;
>> +    return getAttr() ? getAttr()->getRange() : SourceRange();
>>     }
>>     void initializeLocal(ASTContext &Context, SourceLocation loc) {
>> -    setAttrNameLoc(loc);
>> -    if (hasAttrExprOperand()) {
>> -      setAttrOperandParensRange(SourceRange(loc));
>> -      setAttrExprOperand(nullptr);
>> -    } else if (hasAttrEnumOperand()) {
>> -      setAttrOperandParensRange(SourceRange(loc));
>> -      setAttrEnumOperandLoc(loc);
>> -    }
>> +    setAttr(nullptr);
>>     }
>>     QualType getInnerType() const {
>>
>> Modified: cfe/trunk/include/clang/Basic/Attr.td
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=340215&r1=340214&r2=340215&view=diff 
>>
>> ============================================================================== 
>>
>> --- cfe/trunk/include/clang/Basic/Attr.td (original)
>> +++ cfe/trunk/include/clang/Basic/Attr.td Mon Aug 20 14:47:29 2018
>> @@ -494,10 +494,7 @@ class Attr {
>>   }
>>   /// A type attribute is not processed on a declaration or a statement.
>> -class TypeAttr : Attr {
>> -  // By default, type attributes do not get an AST node.
>> -  let ASTNode = 0;
>> -}
>> +class TypeAttr : Attr;
>>   /// A stmt attribute is not processed on a declaration or a type.
>>   class StmtAttr : Attr;
>> @@ -567,6 +564,8 @@ def AddressSpace : TypeAttr {
>>     let Spellings = [Clang<"address_space">];
>>     let Args = [IntArgument<"AddressSpace">];
>>     let Documentation = [Undocumented];
>> +  // Represented as a qualifier or DependentAddressSpaceType instead.
>> +  let ASTNode = 0;
>>   }
>>   def Alias : Attr {
>> @@ -1224,7 +1223,7 @@ def LayoutVersion : InheritableAttr, Tar
>>     let Documentation = [LayoutVersionDocs];
>>   }
>> -def LifetimeBound : InheritableAttr {
>> +def LifetimeBound : DeclOrTypeAttr {
>>     let Spellings = [Clang<"lifetimebound", 0>];
>>     let Subjects = SubjectList<[ParmVar, ImplicitObjectParameter], 
>> ErrorDiag>;
>>     let Documentation = [LifetimeBoundDocs];
>> @@ -1327,12 +1326,16 @@ def NeonPolyVectorType : TypeAttr {
>>     let Spellings = [Clang<"neon_polyvector_type">];
>>     let Args = [IntArgument<"NumElements">];
>>     let Documentation = [Undocumented];
>> +  // Represented as VectorType instead.
>> +  let ASTNode = 0;
>>   }
>>   def NeonVectorType : TypeAttr {
>>     let Spellings = [Clang<"neon_vector_type">];
>>     let Args = [IntArgument<"NumElements">];
>>     let Documentation = [Undocumented];
>> +  // Represented as VectorType instead.
>> +  let ASTNode = 0;
>>   }
>>   def ReturnsTwice : InheritableAttr {
>> @@ -1507,6 +1510,14 @@ def TypeNullUnspecified : TypeAttr {
>>     let Documentation = [TypeNullUnspecifiedDocs];
>>   }
>> +// This is a marker used to indicate that an __unsafe_unretained 
>> qualifier was
>> +// ignored because ARC is not enabled. The usual representation for this
>> +// qualifier is as an ObjCOwnership attribute with Kind == "none".
>> +def ObjCInertUnsafeUnretained : TypeAttr {
>> +  let Spellings = [Keyword<"__unsafe_unretained">];
>> +  let Documentation = [Undocumented];
>> +}
>> +
>>   def ObjCKindOf : TypeAttr {
>>     let Spellings = [Keyword<"__kindof">];
>>     let Documentation = [Undocumented];
>> @@ -1594,7 +1605,7 @@ def ObjCBridgeRelated : InheritableAttr
>>     let Documentation = [Undocumented];
>>   }
>> -def NSReturnsRetained : InheritableAttr {
>> +def NSReturnsRetained : DeclOrTypeAttr {
>>     let Spellings = [Clang<"ns_returns_retained">];
>>   //  let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
>>     let Documentation = [Undocumented];
>> @@ -1779,6 +1790,8 @@ def Regparm : TypeAttr {
>>     let Spellings = [GCC<"regparm">];
>>     let Args = [UnsignedArgument<"NumParams">];
>>     let Documentation = [RegparmDocs];
>> +  // Represented as part of the enclosing function type.
>> +  let ASTNode = 0;
>>   }
>>   def ReqdWorkGroupSize : InheritableAttr {
>> @@ -2067,10 +2080,9 @@ def ObjCGC : TypeAttr {
>>     let Documentation = [Undocumented];
>>   }
>> -def ObjCOwnership : InheritableAttr {
>> +def ObjCOwnership : DeclOrTypeAttr {
>>     let Spellings = [Clang<"objc_ownership">];
>>     let Args = [IdentifierArgument<"Kind">];
>> -  let ASTNode = 0;
>>     let Documentation = [Undocumented];
>>   }
>> @@ -2108,6 +2120,8 @@ def VectorSize : TypeAttr {
>>     let Spellings = [GCC<"vector_size">];
>>     let Args = [ExprArgument<"NumBytes">];
>>     let Documentation = [Undocumented];
>> +  // Represented as VectorType instead.
>> +  let ASTNode = 0;
>>   }
>>   def VecTypeHint : InheritableAttr {
>> @@ -2202,7 +2216,7 @@ def AnyX86NoCallerSavedRegisters : Inher
>>     let Documentation = [AnyX86NoCallerSavedRegistersDocs];
>>   }
>> -def AnyX86NoCfCheck : InheritableAttr, TargetSpecificAttr<TargetAnyX86>{
>> +def AnyX86NoCfCheck : DeclOrTypeAttr, TargetSpecificAttr<TargetAnyX86>{
>>     let Spellings = [GCC<"nocf_check">];
>>     let Subjects = SubjectList<[FunctionLike]>;
>>     let Documentation = [AnyX86NoCfCheckDocs];
>>
>> Modified: cfe/trunk/include/clang/Sema/Sema.h
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=340215&r1=340214&r2=340215&view=diff 
>>
>> ============================================================================== 
>>
>> --- cfe/trunk/include/clang/Sema/Sema.h (original)
>> +++ cfe/trunk/include/clang/Sema/Sema.h Mon Aug 20 14:47:29 2018
>> @@ -1435,8 +1435,6 @@ public:
>>     TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S);
>>     TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType 
>> FromTy);
>> -  TypeSourceInfo *GetTypeSourceInfoForDeclarator(Declarator &D, 
>> QualType T,
>> -                                               TypeSourceInfo 
>> *ReturnTypeInfo);
>>     /// Package the given type and TSI into a ParsedType.
>>     ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo);
>> @@ -3378,30 +3376,6 @@ public:
>>     /// Valid types should not have multiple attributes with different 
>> CCs.
>>     const AttributedType *getCallingConvAttributedType(QualType T) const;
>> -  /// Check whether a nullability type specifier can be added to the 
>> given
>> -  /// type.
>> -  ///
>> -  /// \param type The type to which the nullability specifier will be
>> -  /// added. On success, this type will be updated appropriately.
>> -  ///
>> -  /// \param nullability The nullability specifier to add.
>> -  ///
>> -  /// \param nullabilityLoc The location of the nullability specifier.
>> -  ///
>> -  /// \param isContextSensitive Whether this nullability specifier was
>> -  /// written as a context-sensitive keyword (in an Objective-C
>> -  /// method) or an Objective-C property attribute, rather than as an
>> -  /// underscored type specifier.
>> -  ///
>> -  /// \param allowArrayTypes Whether to accept nullability specifiers 
>> on an
>> -  /// array type (e.g., because it will decay to a pointer).
>> -  ///
>> -  /// \returns true if nullability cannot be applied, false otherwise.
>> -  bool checkNullabilityTypeSpecifier(QualType &type, NullabilityKind 
>> nullability,
>> -                                     SourceLocation nullabilityLoc,
>> -                                     bool isContextSensitive,
>> -                                     bool allowArrayTypes);
>> -
>>     /// Stmt attributes - this routine is the top level dispatcher.
>>     StmtResult ProcessStmtAttributes(Stmt *Stmt,
>>                                      const ParsedAttributesView &Attrs,
>> @@ -8071,10 +8045,6 @@ public:
>>                                  SourceLocation ProtocolRAngleLoc,
>>                                  bool FailOnError = false);
>> -  /// Check the application of the Objective-C '__kindof' qualifier to
>> -  /// the given type.
>> -  bool checkObjCKindOfType(QualType &type, SourceLocation loc);
>> -
>>     /// Ensure attributes are consistent with type.
>>     /// \param [in, out] Attributes The attributes to check; they will
>>     /// be modified to be consistent with \p PropertyTy.
>>
>> Modified: cfe/trunk/include/clang/Serialization/ASTReader.h
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=340215&r1=340214&r2=340215&view=diff 
>>
>> ============================================================================== 
>>
>> --- cfe/trunk/include/clang/Serialization/ASTReader.h (original)
>> +++ cfe/trunk/include/clang/Serialization/ASTReader.h Mon Aug 20 
>> 14:47:29 2018
>> @@ -2245,6 +2245,9 @@ public:
>>     CXXTemporary *ReadCXXTemporary(ModuleFile &F, const RecordData 
>> &Record,
>>                                    unsigned &Idx);
>> +  /// Reads one attribute from the current stream position.
>> +  Attr *ReadAttr(ModuleFile &M, const RecordData &Record, unsigned 
>> &Idx);
>> +
>>     /// Reads attributes from the current stream position.
>>     void ReadAttributes(ASTRecordReader &Record, AttrVec &Attrs);
>> @@ -2630,6 +2633,11 @@ public:
>>       return ASTReader::ReadVersionTuple(Record, Idx);
>>     }
>> +  /// Reads one attribute from the current stream position, advancing 
>> Idx.
>> +  Attr *readAttr() {
>> +    return Reader->ReadAttr(*F, Record, Idx);
>> +  }
>> +
>>     /// Reads attributes from the current stream position, advancing Idx.
>>     void readAttributes(AttrVec &Attrs) {
>>       return Reader->ReadAttributes(*this, Attrs);
>>
>> Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=340215&r1=340214&r2=340215&view=diff 
>>
>> ============================================================================== 
>>
>> --- cfe/trunk/include/clang/Serialization/ASTWriter.h (original)
>> +++ cfe/trunk/include/clang/Serialization/ASTWriter.h Mon Aug 20 
>> 14:47:29 2018
>> @@ -955,6 +955,9 @@ public:
>>       return Writer->AddVersionTuple(Version, *Record);
>>     }
>> +  // Emit an attribute.
>> +  void AddAttr(const Attr *A);
>> +
>>     /// Emit a list of attributes.
>>     void AddAttributes(ArrayRef<const Attr*> Attrs);
>>   };
>>
>> Modified: cfe/trunk/lib/ARCMigrate/TransGCAttrs.cpp
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/TransGCAttrs.cpp?rev=340215&r1=340214&r2=340215&view=diff 
>>
>> ============================================================================== 
>>
>> --- cfe/trunk/lib/ARCMigrate/TransGCAttrs.cpp (original)
>> +++ cfe/trunk/lib/ARCMigrate/TransGCAttrs.cpp Mon Aug 20 14:47:29 2018
>> @@ -81,10 +81,11 @@ public:
>>     }
>>     bool handleAttr(AttributedTypeLoc TL, Decl *D = nullptr) {
>> -    if (TL.getAttrKind() != AttributedType::attr_objc_ownership)
>> +    auto *OwnershipAttr = TL.getAttrAs<ObjCOwnershipAttr>();
>> +    if (!OwnershipAttr)
>>         return false;
>> -    SourceLocation Loc = TL.getAttrNameLoc();
>> +    SourceLocation Loc = OwnershipAttr->getLocation();
>>       unsigned RawLoc = Loc.getRawEncoding();
>>       if (MigrateCtx.AttrSet.count(RawLoc))
>>         return true;
>> @@ -93,13 +94,7 @@ public:
>>       SourceManager &SM = Ctx.getSourceManager();
>>       if (Loc.isMacroID())
>>         Loc = SM.getImmediateExpansionRange(Loc).getBegin();
>> -    SmallString<32> Buf;
>> -    bool Invalid = false;
>> -    StringRef Spell = Lexer::getSpelling(
>> -                                  
>> SM.getSpellingLoc(TL.getAttrEnumOperandLoc()),
>> -                                  Buf, SM, Ctx.getLangOpts(), &Invalid);
>> -    if (Invalid)
>> -      return false;
>> +    StringRef Spell = OwnershipAttr->getKind()->getName();
>>       MigrationContext::GCAttrOccurrence::AttrKind Kind;
>>       if (Spell == "strong")
>>         Kind = MigrationContext::GCAttrOccurrence::Strong;
>> @@ -284,7 +279,7 @@ static void checkAllAtProps(MigrationCon
>>     }
>>     for (unsigned i = 0, e = ATLs.size(); i != e; ++i) {
>> -    SourceLocation Loc = ATLs[i].first.getAttrNameLoc();
>> +    SourceLocation Loc = ATLs[i].first.getAttr()->getLocation();
>>       if (Loc.isMacroID())
>>         Loc = MigrateCtx.Pass.Ctx.getSourceManager()
>>                   .getImmediateExpansionRange(Loc)
>>
>> Modified: cfe/trunk/lib/ARCMigrate/Transforms.cpp
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/Transforms.cpp?rev=340215&r1=340214&r2=340215&view=diff 
>>
>> ============================================================================== 
>>
>> --- cfe/trunk/lib/ARCMigrate/Transforms.cpp (original)
>> +++ cfe/trunk/lib/ARCMigrate/Transforms.cpp Mon Aug 20 14:47:29 2018
>> @@ -359,7 +359,7 @@ MigrationContext::~MigrationContext() {
>>   bool MigrationContext::isGCOwnedNonObjC(QualType T) {
>>     while (!T.isNull()) {
>>       if (const AttributedType *AttrT = T->getAs<AttributedType>()) {
>> -      if (AttrT->getAttrKind() == AttributedType::attr_objc_ownership)
>> +      if (AttrT->getAttrKind() == attr::ObjCOwnership)
>>           return !AttrT->getModifiedType()->isObjCRetainableType();
>>       }
>>
>> Modified: cfe/trunk/lib/AST/ASTContext.cpp
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=340215&r1=340214&r2=340215&view=diff 
>>
>> ============================================================================== 
>>
>> --- cfe/trunk/lib/AST/ASTContext.cpp (original)
>> +++ cfe/trunk/lib/AST/ASTContext.cpp Mon Aug 20 14:47:29 2018
>> @@ -3876,7 +3876,7 @@ QualType ASTContext::getEnumType(const E
>>     return QualType(newType, 0);
>>   }
>> -QualType ASTContext::getAttributedType(AttributedType::Kind attrKind,
>> +QualType ASTContext::getAttributedType(attr::Kind attrKind,
>>                                          QualType modifiedType,
>>                                          QualType equivalentType) {
>>     llvm::FoldingSetNodeID id;
>>
>> Modified: cfe/trunk/lib/AST/Type.cpp
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=340215&r1=340214&r2=340215&view=diff 
>>
>> ============================================================================== 
>>
>> --- cfe/trunk/lib/AST/Type.cpp (original)
>> +++ cfe/trunk/lib/AST/Type.cpp Mon Aug 20 14:47:29 2018
>> @@ -592,28 +592,6 @@ bool Type::isObjCClassOrClassKindOfType(
>>     return OPT->isObjCClassType() || OPT->isObjCQualifiedClassType();
>>   }
>> -/// Was this type written with the special inert-in-MRC 
>> __unsafe_unretained
>> -/// qualifier?
>> -///
>> -/// This approximates the answer to the following question: if this
>> -/// translation unit were compiled in ARC, would this type be qualified
>> -/// with __unsafe_unretained?
>> -bool Type::isObjCInertUnsafeUnretainedType() const {
>> -  const Type *cur = this;
>> -  while (true) {
>> -    if (const auto attributed = dyn_cast<AttributedType>(cur)) {
>> -      if (attributed->getAttrKind() ==
>> -            AttributedType::attr_objc_inert_unsafe_unretained)
>> -        return true;
>> -    }
>> -
>> -    // Single-step desugar until we run out of sugar.
>> -    QualType next = cur->getLocallyUnqualifiedSingleStepDesugaredType();
>> -    if (next.getTypePtr() == cur) return false;
>> -    cur = next.getTypePtr();
>> -  }
>> -}
>> -
>>   ObjCTypeParamType::ObjCTypeParamType(const ObjCTypeParamDecl *D,
>>                                        QualType can,
>>                                        ArrayRef<ObjCProtocolDecl *> 
>> protocols)
>> @@ -1641,6 +1619,16 @@ TagDecl *Type::getAsTagDecl() const {
>>     return nullptr;
>>   }
>> +bool Type::hasAttr(attr::Kind AK) const {
>> +  const Type *Cur = this;
>> +  while (const auto *AT = Cur->getAs<AttributedType>()) {
>> +    if (AT->getAttrKind() == AK)
>> +      return true;
>> +    Cur = AT->getEquivalentType().getTypePtr();
>> +  }
>> +  return false;
>> +}
>> +
>>   namespace {
>>     class GetContainedDeducedTypeVisitor :
>> @@ -3168,105 +3156,58 @@ bool RecordType::hasConstFields() const
>>   }
>>   bool AttributedType::isQualifier() const {
>> +  // FIXME: Generate this with TableGen.
>>     switch (getAttrKind()) {
>>     // These are type qualifiers in the traditional C sense: they 
>> annotate
>>     // something about a specific value/variable of a type.  (They aren't
>>     // always part of the canonical type, though.)
>> -  case AttributedType::attr_address_space:
>> -  case AttributedType::attr_objc_gc:
>> -  case AttributedType::attr_objc_ownership:
>> -  case AttributedType::attr_objc_inert_unsafe_unretained:
>> -  case AttributedType::attr_nonnull:
>> -  case AttributedType::attr_nullable:
>> -  case AttributedType::attr_null_unspecified:
>> -  case AttributedType::attr_lifetimebound:
>> -    return true;
>> -
>> -  // These aren't qualifiers; they rewrite the modified type to be a
>> -  // semantically different type.
>> -  case AttributedType::attr_regparm:
>> -  case AttributedType::attr_vector_size:
>> -  case AttributedType::attr_neon_vector_type:
>> -  case AttributedType::attr_neon_polyvector_type:
>> -  case AttributedType::attr_pcs:
>> -  case AttributedType::attr_pcs_vfp:
>> -  case AttributedType::attr_noreturn:
>> -  case AttributedType::attr_cdecl:
>> -  case AttributedType::attr_fastcall:
>> -  case AttributedType::attr_stdcall:
>> -  case AttributedType::attr_thiscall:
>> -  case AttributedType::attr_regcall:
>> -  case AttributedType::attr_pascal:
>> -  case AttributedType::attr_swiftcall:
>> -  case AttributedType::attr_vectorcall:
>> -  case AttributedType::attr_inteloclbicc:
>> -  case AttributedType::attr_preserve_most:
>> -  case AttributedType::attr_preserve_all:
>> -  case AttributedType::attr_ms_abi:
>> -  case AttributedType::attr_sysv_abi:
>> -  case AttributedType::attr_ptr32:
>> -  case AttributedType::attr_ptr64:
>> -  case AttributedType::attr_sptr:
>> -  case AttributedType::attr_uptr:
>> -  case AttributedType::attr_objc_kindof:
>> -  case AttributedType::attr_ns_returns_retained:
>> -  case AttributedType::attr_nocf_check:
>> +  case attr::ObjCGC:
>> +  case attr::ObjCOwnership:
>> +  case attr::ObjCInertUnsafeUnretained:
>> +  case attr::TypeNonNull:
>> +  case attr::TypeNullable:
>> +  case attr::TypeNullUnspecified:
>> +  case attr::LifetimeBound:
>> +    return true;
>> +
>> +  // All other type attributes aren't qualifiers; they rewrite the 
>> modified
>> +  // type to be a semantically different type.
>> +  default:
>>       return false;
>>     }
>> -  llvm_unreachable("bad attributed type kind");
>>   }
>>   bool AttributedType::isMSTypeSpec() const {
>> +  // FIXME: Generate this with TableGen?
>>     switch (getAttrKind()) {
>> -  default:  return false;
>> -  case attr_ptr32:
>> -  case attr_ptr64:
>> -  case attr_sptr:
>> -  case attr_uptr:
>> +  default: return false;
>> +  case attr::Ptr32:
>> +  case attr::Ptr64:
>> +  case attr::SPtr:
>> +  case attr::UPtr:
>>       return true;
>>     }
>>     llvm_unreachable("invalid attr kind");
>>   }
>>   bool AttributedType::isCallingConv() const {
>> +  // FIXME: Generate this with TableGen.
>>     switch (getAttrKind()) {
>> -  case attr_ptr32:
>> -  case attr_ptr64:
>> -  case attr_sptr:
>> -  case attr_uptr:
>> -  case attr_address_space:
>> -  case attr_regparm:
>> -  case attr_vector_size:
>> -  case attr_neon_vector_type:
>> -  case attr_neon_polyvector_type:
>> -  case attr_objc_gc:
>> -  case attr_objc_ownership:
>> -  case attr_objc_inert_unsafe_unretained:
>> -  case attr_noreturn:
>> -  case attr_nonnull:
>> -  case attr_ns_returns_retained:
>> -  case attr_nullable:
>> -  case attr_null_unspecified:
>> -  case attr_objc_kindof:
>> -  case attr_nocf_check:
>> -  case attr_lifetimebound:
>> -    return false;
>> -
>> -  case attr_pcs:
>> -  case attr_pcs_vfp:
>> -  case attr_cdecl:
>> -  case attr_fastcall:
>> -  case attr_stdcall:
>> -  case attr_thiscall:
>> -  case attr_regcall:
>> -  case attr_swiftcall:
>> -  case attr_vectorcall:
>> -  case attr_pascal:
>> -  case attr_ms_abi:
>> -  case attr_sysv_abi:
>> -  case attr_inteloclbicc:
>> -  case attr_preserve_most:
>> -  case attr_preserve_all:
>> +  default: return false;
>> +  case attr::Pcs:
>> +  case attr::CDecl:
>> +  case attr::FastCall:
>> +  case attr::StdCall:
>> +  case attr::ThisCall:
>> +  case attr::RegCall:
>> +  case attr::SwiftCall:
>> +  case attr::VectorCall:
>> +  case attr::Pascal:
>> +  case attr::MSABI:
>> +  case attr::SysVABI:
>> +  case attr::IntelOclBicc:
>> +  case attr::PreserveMost:
>> +  case attr::PreserveAll:
>>       return true;
>>     }
>>     llvm_unreachable("invalid attr kind");
>> @@ -3712,23 +3653,18 @@ LinkageInfo Type::getLinkageAndVisibilit
>>     return LinkageComputer{}.getTypeLinkageAndVisibility(this);
>>   }
>> -Optional<NullabilityKind> Type::getNullability(const ASTContext 
>> &context) const {
>> -  QualType type(this, 0);
>> -  do {
>> +Optional<NullabilityKind>
>> +Type::getNullability(const ASTContext &Context) const {
>> +  QualType Type(this, 0);
>> +  while (const auto *AT = Type->getAs<AttributedType>()) {
>>       // Check whether this is an attributed type with nullability
>>       // information.
>> -    if (auto attributed = dyn_cast<AttributedType>(type.getTypePtr())) {
>> -      if (auto nullability = attributed->getImmediateNullability())
>> -        return nullability;
>> -    }
>> -
>> -    // Desugar the type. If desugaring does nothing, we're done.
>> -    QualType desugared = type.getSingleStepDesugaredType(context);
>> -    if (desugared.getTypePtr() == type.getTypePtr())
>> -      return None;
>> +    if (auto Nullability = AT->getImmediateNullability())
>> +      return Nullability;
>> -    type = desugared;
>> -  } while (true);
>> +    Type = AT->getEquivalentType();
>> +  }
>> +  return None;
>>   }
>>   bool Type::canHaveNullability(bool ResultIfUnknown) const {
>> @@ -3841,12 +3777,13 @@ bool Type::canHaveNullability(bool Resul
>>     llvm_unreachable("bad type kind!");
>>   }
>> -llvm::Optional<NullabilityKind> 
>> AttributedType::getImmediateNullability() const {
>> -  if (getAttrKind() == AttributedType::attr_nonnull)
>> +llvm::Optional<NullabilityKind>
>> +AttributedType::getImmediateNullability() const {
>> +  if (getAttrKind() == attr::TypeNonNull)
>>       return NullabilityKind::NonNull;
>> -  if (getAttrKind() == AttributedType::attr_nullable)
>> +  if (getAttrKind() == attr::TypeNullable)
>>       return NullabilityKind::Nullable;
>> -  if (getAttrKind() == AttributedType::attr_null_unspecified)
>> +  if (getAttrKind() == attr::TypeNullUnspecified)
>>       return NullabilityKind::Unspecified;
>>     return None;
>>   }
>>
>> Modified: cfe/trunk/lib/AST/TypeLoc.cpp
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypeLoc.cpp?rev=340215&r1=340214&r2=340215&view=diff 
>>
>> ============================================================================== 
>>
>> --- cfe/trunk/lib/AST/TypeLoc.cpp (original)
>> +++ cfe/trunk/lib/AST/TypeLoc.cpp Mon Aug 20 14:47:29 2018
>> @@ -404,11 +404,11 @@ TypeLoc TypeLoc::IgnoreParensImpl(TypeLo
>>   }
>>   SourceLocation TypeLoc::findNullabilityLoc() const {
>> -  if (auto attributedLoc = getAs<AttributedTypeLoc>()) {
>> -    if (attributedLoc.getAttrKind() == AttributedType::attr_nullable ||
>> -        attributedLoc.getAttrKind() == AttributedType::attr_nonnull ||
>> -        attributedLoc.getAttrKind() == 
>> AttributedType::attr_null_unspecified)
>> -      return attributedLoc.getAttrNameLoc();
>> +  if (auto ATL = getAs<AttributedTypeLoc>()) {
>> +    const Attr *A = ATL.getAttr();
>> +    if (A && (isa<TypeNullableAttr>(A) || isa<TypeNonNullAttr>(A) ||
>> +              isa<TypeNullUnspecifiedAttr>(A)))
>> +      return A->getLocation();
>>     }
>>     return {};
>>
>> Modified: cfe/trunk/lib/AST/TypePrinter.cpp
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypePrinter.cpp?rev=340215&r1=340214&r2=340215&view=diff 
>>
>> ============================================================================== 
>>
>> --- cfe/trunk/lib/AST/TypePrinter.cpp (original)
>> +++ cfe/trunk/lib/AST/TypePrinter.cpp Mon Aug 20 14:47:29 2018
>> @@ -1354,12 +1354,14 @@ void TypePrinter::printPackExpansionAfte
>>   void TypePrinter::printAttributedBefore(const AttributedType *T,
>>                                           raw_ostream &OS) {
>> +  // FIXME: Generate this with TableGen.
>> +
>>     // Prefer the macro forms of the GC and ownership qualifiers.
>> -  if (T->getAttrKind() == AttributedType::attr_objc_gc ||
>> -      T->getAttrKind() == AttributedType::attr_objc_ownership)
>> +  if (T->getAttrKind() == attr::ObjCGC ||
>> +      T->getAttrKind() == attr::ObjCOwnership)
>>       return printBefore(T->getEquivalentType(), OS);
>> -  if (T->getAttrKind() == AttributedType::attr_objc_kindof)
>> +  if (T->getAttrKind() == attr::ObjCKindOf)
>>       OS << "__kindof ";
>>     printBefore(T->getModifiedType(), OS);
>> @@ -1367,23 +1369,21 @@ void TypePrinter::printAttributedBefore(
>>     if (T->isMSTypeSpec()) {
>>       switch (T->getAttrKind()) {
>>       default: return;
>> -    case AttributedType::attr_ptr32: OS << " __ptr32"; break;
>> -    case AttributedType::attr_ptr64: OS << " __ptr64"; break;
>> -    case AttributedType::attr_sptr: OS << " __sptr"; break;
>> -    case AttributedType::attr_uptr: OS << " __uptr"; break;
>> +    case attr::Ptr32: OS << " __ptr32"; break;
>> +    case attr::Ptr64: OS << " __ptr64"; break;
>> +    case attr::SPtr: OS << " __sptr"; break;
>> +    case attr::UPtr: OS << " __uptr"; break;
>>       }
>>       spaceBeforePlaceHolder(OS);
>>     }
>>     // Print nullability type specifiers.
>> -  if (T->getAttrKind() == AttributedType::attr_nonnull ||
>> -      T->getAttrKind() == AttributedType::attr_nullable ||
>> -      T->getAttrKind() == AttributedType::attr_null_unspecified) {
>> -    if (T->getAttrKind() == AttributedType::attr_nonnull)
>> +  if (T->getImmediateNullability()) {
>> +    if (T->getAttrKind() == attr::TypeNonNull)
>>         OS << " _Nonnull";
>> -    else if (T->getAttrKind() == AttributedType::attr_nullable)
>> +    else if (T->getAttrKind() == attr::TypeNullable)
>>         OS << " _Nullable";
>> -    else if (T->getAttrKind() == AttributedType::attr_null_unspecified)
>> +    else if (T->getAttrKind() == attr::TypeNullUnspecified)
>>         OS << " _Null_unspecified";
>>       else
>>         llvm_unreachable("unhandled nullability");
>> @@ -1393,9 +1393,11 @@ void TypePrinter::printAttributedBefore(
>>   void TypePrinter::printAttributedAfter(const AttributedType *T,
>>                                          raw_ostream &OS) {
>> +  // FIXME: Generate this with TableGen.
>> +
>>     // Prefer the macro forms of the GC and ownership qualifiers.
>> -  if (T->getAttrKind() == AttributedType::attr_objc_gc ||
>> -      T->getAttrKind() == AttributedType::attr_objc_ownership)
>> +  if (T->getAttrKind() == attr::ObjCGC ||
>> +      T->getAttrKind() == attr::ObjCOwnership)
>>       return printAfter(T->getEquivalentType(), OS);
>>     // If this is a calling convention attribute, don't print the 
>> implicit CC from
>> @@ -1406,107 +1408,74 @@ void TypePrinter::printAttributedAfter(c
>>     // Some attributes are printed as qualifiers before the type, so 
>> we have
>>     // nothing left to do.
>> -  if (T->getAttrKind() == AttributedType::attr_objc_kindof ||
>> -      T->isMSTypeSpec() ||
>> -      T->getAttrKind() == AttributedType::attr_nonnull ||
>> -      T->getAttrKind() == AttributedType::attr_nullable ||
>> -      T->getAttrKind() == AttributedType::attr_null_unspecified)
>> +  if (T->getAttrKind() == attr::ObjCKindOf ||
>> +      T->isMSTypeSpec() || T->getImmediateNullability())
>>       return;
>>     // Don't print the inert __unsafe_unretained attribute at all.
>> -  if (T->getAttrKind() == 
>> AttributedType::attr_objc_inert_unsafe_unretained)
>> +  if (T->getAttrKind() == attr::ObjCInertUnsafeUnretained)
>>       return;
>>     // Don't print ns_returns_retained unless it had an effect.
>> -  if (T->getAttrKind() == AttributedType::attr_ns_returns_retained &&
>> +  if (T->getAttrKind() == attr::NSReturnsRetained &&
>>         !T->getEquivalentType()->castAs<FunctionType>()
>>                                ->getExtInfo().getProducesResult())
>>       return;
>> -  if (T->getAttrKind() == AttributedType::attr_lifetimebound) {
>> +  if (T->getAttrKind() == attr::LifetimeBound) {
>>       OS << " [[clang::lifetimebound]]";
>>       return;
>>     }
>>     OS << " __attribute__((";
>>     switch (T->getAttrKind()) {
>> -  case AttributedType::attr_lifetimebound:
>> -  case AttributedType::attr_nonnull:
>> -  case AttributedType::attr_nullable:
>> -  case AttributedType::attr_null_unspecified:
>> -  case AttributedType::attr_objc_gc:
>> -  case AttributedType::attr_objc_inert_unsafe_unretained:
>> -  case AttributedType::attr_objc_kindof:
>> -  case AttributedType::attr_objc_ownership:
>> -  case AttributedType::attr_ptr32:
>> -  case AttributedType::attr_ptr64:
>> -  case AttributedType::attr_sptr:
>> -  case AttributedType::attr_uptr:
>> +#define TYPE_ATTR(NAME)
>> +#define DECL_OR_TYPE_ATTR(NAME)
>> +#define ATTR(NAME) case attr::NAME:
>> +#include "clang/Basic/AttrList.inc"
>> +    llvm_unreachable("non-type attribute attached to type");
>> +
>> +  case attr::OpenCLPrivateAddressSpace:
>> +  case attr::OpenCLGlobalAddressSpace:
>> +  case attr::OpenCLLocalAddressSpace:
>> +  case attr::OpenCLConstantAddressSpace:
>> +  case attr::OpenCLGenericAddressSpace:
>> +    // FIXME: Update printAttributedBefore to print these once we 
>> generate
>> +    // AttributedType nodes for them.
>> +    break;
>> +
>> +  case attr::LifetimeBound:
>> +  case attr::TypeNonNull:
>> +  case attr::TypeNullable:
>> +  case attr::TypeNullUnspecified:
>> +  case attr::ObjCGC:
>> +  case attr::ObjCInertUnsafeUnretained:
>> +  case attr::ObjCKindOf:
>> +  case attr::ObjCOwnership:
>> +  case attr::Ptr32:
>> +  case attr::Ptr64:
>> +  case attr::SPtr:
>> +  case attr::UPtr:
>>       llvm_unreachable("This attribute should have been handled 
>> already");
>> -  case AttributedType::attr_address_space:
>> -    OS << "address_space(";
>> -    // FIXME: printing the raw LangAS value is wrong. This should 
>> probably
>> -    // use the same code as Qualifiers::print()
>> -    OS << (unsigned)T->getEquivalentType().getAddressSpace();
>> -    OS << ')';
>> -    break;
>> -
>> -  case AttributedType::attr_vector_size:
>> -    OS << "__vector_size__(";
>> -    if (const auto *vector = 
>> T->getEquivalentType()->getAs<VectorType>()) {
>> -      OS << vector->getNumElements();
>> -      OS << " * sizeof(";
>> -      print(vector->getElementType(), OS, StringRef());
>> -      OS << ')';
>> -    }
>> -    OS << ')';
>> -    break;
>> -
>> -  case AttributedType::attr_neon_vector_type:
>> -  case AttributedType::attr_neon_polyvector_type: {
>> -    if (T->getAttrKind() == AttributedType::attr_neon_vector_type)
>> -      OS << "neon_vector_type(";
>> -    else
>> -      OS << "neon_polyvector_type(";
>> -    const auto *vector = T->getEquivalentType()->getAs<VectorType>();
>> -    OS << vector->getNumElements();
>> -    OS << ')';
>> -    break;
>> -  }
>> -
>> -  case AttributedType::attr_regparm: {
>> -    // FIXME: When Sema learns to form this AttributedType, avoid 
>> printing the
>> -    // attribute again in printFunctionProtoAfter.
>> -    OS << "regparm(";
>> -    QualType t = T->getEquivalentType();
>> -    while (!t->isFunctionType())
>> -      t = t->getPointeeType();
>> -    OS << t->getAs<FunctionType>()->getRegParmType();
>> -    OS << ')';
>> -    break;
>> -  }
>> -
>> -  case AttributedType::attr_ns_returns_retained:
>> +  case attr::NSReturnsRetained:
>>       OS << "ns_returns_retained";
>>       break;
>>     // FIXME: When Sema learns to form this AttributedType, avoid 
>> printing the
>>     // attribute again in printFunctionProtoAfter.
>> -  case AttributedType::attr_noreturn: OS << "noreturn"; break;
>> -  case AttributedType::attr_nocf_check: OS << "nocf_check"; break;
>> -  case AttributedType::attr_cdecl: OS << "cdecl"; break;
>> -  case AttributedType::attr_fastcall: OS << "fastcall"; break;
>> -  case AttributedType::attr_stdcall: OS << "stdcall"; break;
>> -  case AttributedType::attr_thiscall: OS << "thiscall"; break;
>> -  case AttributedType::attr_swiftcall: OS << "swiftcall"; break;
>> -  case AttributedType::attr_vectorcall: OS << "vectorcall"; break;
>> -  case AttributedType::attr_pascal: OS << "pascal"; break;
>> -  case AttributedType::attr_ms_abi: OS << "ms_abi"; break;
>> -  case AttributedType::attr_sysv_abi: OS << "sysv_abi"; break;
>> -  case AttributedType::attr_regcall: OS << "regcall"; break;
>> -  case AttributedType::attr_pcs:
>> -  case AttributedType::attr_pcs_vfp: {
>> +  case attr::AnyX86NoCfCheck: OS << "nocf_check"; break;
>> +  case attr::CDecl: OS << "cdecl"; break;
>> +  case attr::FastCall: OS << "fastcall"; break;
>> +  case attr::StdCall: OS << "stdcall"; break;
>> +  case attr::ThisCall: OS << "thiscall"; break;
>> +  case attr::SwiftCall: OS << "swiftcall"; break;
>> +  case attr::VectorCall: OS << "vectorcall"; break;
>> +  case attr::Pascal: OS << "pascal"; break;
>> +  case attr::MSABI: OS << "ms_abi"; break;
>> +  case attr::SysVABI: OS << "sysv_abi"; break;
>> +  case attr::RegCall: OS << "regcall"; break;
>> +  case attr::Pcs: {
>>       OS << "pcs(";
>>      QualType t = T->getEquivalentType();
>>      while (!t->isFunctionType())
>> @@ -1517,12 +1486,12 @@ void TypePrinter::printAttributedAfter(c
>>      break;
>>     }
>> -  case AttributedType::attr_inteloclbicc: OS << "inteloclbicc"; break;
>> -  case AttributedType::attr_preserve_most:
>> +  case attr::IntelOclBicc: OS << "inteloclbicc"; break;
>> +  case attr::PreserveMost:
>>       OS << "preserve_most";
>>       break;
>> -  case AttributedType::attr_preserve_all:
>> +  case attr::PreserveAll:
>>       OS << "preserve_all";
>>       break;
>>     }
>>
>> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=340215&r1=340214&r2=340215&view=diff 
>>
>> ============================================================================== 
>>
>> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Aug 20 14:47:29 2018
>> @@ -5999,14 +5999,14 @@ static void checkAttributesAfterMerging(
>>         // The [[lifetimebound]] attribute can be applied to the 
>> implicit object
>>         // parameter of a non-static member function (other than a 
>> ctor or dtor)
>>         // by applying it to the function type.
>> -      if (ATL.getAttrKind() == AttributedType::attr_lifetimebound) {
>> +      if (const auto *A = ATL.getAttrAs<LifetimeBoundAttr>()) {
>>           const auto *MD = dyn_cast<CXXMethodDecl>(FD);
>>           if (!MD || MD->isStatic()) {
>> -          S.Diag(ATL.getAttrNameLoc(), 
>> diag::err_lifetimebound_no_object_param)
>> -              << !MD << ATL.getLocalSourceRange();
>> +          S.Diag(A->getLocation(), 
>> diag::err_lifetimebound_no_object_param)
>> +              << !MD << A->getRange();
>>           } else if (isa<CXXConstructorDecl>(MD) || 
>> isa<CXXDestructorDecl>(MD)) {
>> -          S.Diag(ATL.getAttrNameLoc(), 
>> diag::err_lifetimebound_ctor_dtor)
>> -              << isa<CXXDestructorDecl>(MD) << 
>> ATL.getLocalSourceRange();
>> +          S.Diag(A->getLocation(), diag::err_lifetimebound_ctor_dtor)
>> +              << isa<CXXDestructorDecl>(MD) << A->getRange();
>>           }
>>         }
>>       }
>>
>> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=340215&r1=340214&r2=340215&view=diff 
>>
>> ============================================================================== 
>>
>> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Aug 20 14:47:29 2018
>> @@ -14648,15 +14648,15 @@ static bool captureInBlock(BlockScopeInf
>>     // Warn about implicitly autoreleasing indirect parameters 
>> captured by blocks.
>>     if (const auto *PT = CaptureType->getAs<PointerType>()) {
>>       // This function finds out whether there is an AttributedType of 
>> kind
>> -    // attr_objc_ownership in Ty. The existence of AttributedType of 
>> kind
>> -    // attr_objc_ownership implies __autoreleasing was explicitly 
>> specified
>> +    // attr::ObjCOwnership in Ty. The existence of AttributedType of 
>> kind
>> +    // attr::ObjCOwnership implies __autoreleasing was explicitly 
>> specified
>>       // rather than being added implicitly by the compiler.
>>       auto IsObjCOwnershipAttributedType = [](QualType Ty) {
>>         while (const auto *AttrTy = Ty->getAs<AttributedType>()) {
>> -        if (AttrTy->getAttrKind() == 
>> AttributedType::attr_objc_ownership)
>> +        if (AttrTy->getAttrKind() == attr::ObjCOwnership)
>>             return true;
>> -        // Peel off AttributedTypes that are not of kind objc_ownership.
>> +        // Peel off AttributedTypes that are not of kind ObjCOwnership.
>>           Ty = AttrTy->getModifiedType();
>>         }
>>
>> Modified: cfe/trunk/lib/Sema/SemaInit.cpp
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=340215&r1=340214&r2=340215&view=diff 
>>
>> ============================================================================== 
>>
>> --- cfe/trunk/lib/Sema/SemaInit.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaInit.cpp Mon Aug 20 14:47:29 2018
>> @@ -6360,7 +6360,7 @@ static bool implicitObjectParamIsLifetim
>>     for (TypeLoc TL = TSI->getTypeLoc();
>>          (ATL = TL.getAsAdjusted<AttributedTypeLoc>());
>>          TL = ATL.getModifiedLoc()) {
>> -    if (ATL.getAttrKind() == AttributedType::attr_lifetimebound)
>> +    if (ATL.getAttrAs<LifetimeBoundAttr>())
>>         return true;
>>     }
>>     return false;
>>
>> Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=340215&r1=340214&r2=340215&view=diff 
>>
>> ============================================================================== 
>>
>> --- cfe/trunk/lib/Sema/SemaObjCProperty.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaObjCProperty.cpp Mon Aug 20 14:47:29 2018
>> @@ -2384,7 +2384,7 @@ void Sema::ProcessPropertyDecl(ObjCPrope
>>         QualType modifiedTy = resultTy;
>>         if (auto nullability = 
>> AttributedType::stripOuterNullability(modifiedTy)) {
>>           if (*nullability == NullabilityKind::Unspecified)
>> -          resultTy = 
>> Context.getAttributedType(AttributedType::attr_nonnull,
>> +          resultTy = Context.getAttributedType(attr::TypeNonNull,
>>                                                  modifiedTy, modifiedTy);
>>         }
>>       }
>> @@ -2458,7 +2458,7 @@ void Sema::ProcessPropertyDecl(ObjCPrope
>>           QualType modifiedTy = paramTy;
>>           if (auto nullability = 
>> AttributedType::stripOuterNullability(modifiedTy)){
>>             if (*nullability == NullabilityKind::Unspecified)
>> -            paramTy = 
>> Context.getAttributedType(AttributedType::attr_nullable,
>> +            paramTy = Context.getAttributedType(attr::TypeNullable,
>>                                                   modifiedTy, 
>> modifiedTy);
>>           }
>>         }
>>
>> Modified: cfe/trunk/lib/Sema/SemaType.cpp
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=340215&r1=340214&r2=340215&view=diff 
>>
>> ============================================================================== 
>>
>> --- cfe/trunk/lib/Sema/SemaType.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaType.cpp Mon Aug 20 14:47:29 2018
>> @@ -172,6 +172,16 @@ namespace {
>>       /// processing is complete.
>>       SmallVector<ParsedAttr *, 2> ignoredTypeAttrs;
>> +    /// Attributes corresponding to AttributedTypeLocs that we have 
>> not yet
>> +    /// populated.
>> +    // FIXME: The two-phase mechanism by which we construct Types and 
>> fill
>> +    // their TypeLocs makes it hard to correctly assign these. We 
>> keep the
>> +    // attributes in creation order as an attempt to make them line up
>> +    // properly.
>> +    using TypeAttrPair = std::pair<const AttributedType*, const Attr*>;
>> +    SmallVector<TypeAttrPair, 8> AttrsForTypes;
>> +    bool AttrsForTypesSorted = true;
>> +
>>     public:
>>       TypeProcessingState(Sema &sema, Declarator &declarator)
>>         : sema(sema), declarator(declarator),
>> @@ -230,6 +240,43 @@ namespace {
>>           diagnoseBadTypeAttribute(getSema(), *Attr, type);
>>       }
>> +    /// Get an attributed type for the given attribute, and remember 
>> the Attr
>> +    /// object so that we can attach it to the AttributedTypeLoc.
>> +    QualType getAttributedType(Attr *A, QualType ModifiedType,
>> +                               QualType EquivType) {
>> +      QualType T =
>> +          sema.Context.getAttributedType(A->getKind(), ModifiedType, 
>> EquivType);
>> +      AttrsForTypes.push_back({cast<AttributedType>(T.getTypePtr()), 
>> A});
>> +      AttrsForTypesSorted = false;
>> +      return T;
>> +    }
>> +
>> +    /// Extract and remove the Attr* for a given attributed type.
>> +    const Attr *takeAttrForAttributedType(const AttributedType *AT) {
>> +      if (!AttrsForTypesSorted) {
>> +        std::stable_sort(AttrsForTypes.begin(), AttrsForTypes.end(),
>> +                         [](const TypeAttrPair &A, const TypeAttrPair 
>> &B) {
>> +                           return A.first < B.first;
>> +                         });
>> +        AttrsForTypesSorted = true;
>> +      }
>> +
>> +      // FIXME: This is quadratic if we have lots of reuses of the same
>> +      // attributed type.
>> +      for (auto It = std::partition_point(
>> +               AttrsForTypes.begin(), AttrsForTypes.end(),
>> +               [=](const TypeAttrPair &A) { return A.first < AT; });
>> +           It != AttrsForTypes.end() && It->first == AT; ++It) {
>> +        if (It->second) {
>> +          const Attr *Result = It->second;
>> +          It->second = nullptr;
>> +          return Result;
>> +        }
>> +      }
>> +
>> +      llvm_unreachable("no Attr* for AttributedType*");
>> +    }
>> +
>>       ~TypeProcessingState() {
>>         if (trivial) return;
>> @@ -3832,6 +3879,32 @@ static bool hasOuterPointerLikeChunk(con
>>     return false;
>>   }
>> +template<typename AttrT>
>> +static AttrT *createSimpleAttr(ASTContext &Ctx, ParsedAttr &Attr) {
>> +  Attr.setUsedAsTypeAttr();
>> +  return ::new (Ctx)
>> +      AttrT(Attr.getRange(), Ctx, Attr.getAttributeSpellingListIndex());
>> +}
>> +
>> +static Attr *createNullabilityAttr(ASTContext &Ctx, ParsedAttr &Attr,
>> +                                   NullabilityKind NK) {
>> +  switch (NK) {
>> +  case NullabilityKind::NonNull:
>> +    return createSimpleAttr<TypeNonNullAttr>(Ctx, Attr);
>> +
>> +  case NullabilityKind::Nullable:
>> +    return createSimpleAttr<TypeNullableAttr>(Ctx, Attr);
>> +
>> +  case NullabilityKind::Unspecified:
>> +    return createSimpleAttr<TypeNullUnspecifiedAttr>(Ctx, Attr);
>> +  }
>> +  llvm_unreachable("unknown NullabilityKind");
>> +}
>> +
>> +static TypeSourceInfo *
>> +GetTypeSourceInfoForDeclarator(TypeProcessingState &State,
>> +                               QualType T, TypeSourceInfo 
>> *ReturnTypeInfo);
>> +
>>   static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState 
>> &state,
>>                                                   QualType declSpecType,
>>                                                   TypeSourceInfo 
>> *TInfo) {
>> @@ -4184,9 +4257,8 @@ static TypeSourceInfo *GetFullTypeForDec
>>                   pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(),
>>                   D.getDeclSpec().getEndLoc(),
>>                   D.getMutableDeclSpec().getAttributes())) {
>> -          T = Context.getAttributedType(
>> -                
>> AttributedType::getNullabilityAttrKind(*inferNullability),T,T);
>> -          attr->setUsedAsTypeAttr();
>> +          T = state.getAttributedType(
>> +              createNullabilityAttr(Context, *attr, 
>> *inferNullability), T, T);
>>           }
>>         }
>>       }
>> @@ -5025,7 +5097,7 @@ static TypeSourceInfo *GetFullTypeForDec
>>     if (D.isInvalidType())
>>       return Context.getTrivialTypeSourceInfo(T);
>> -  return S.GetTypeSourceInfoForDeclarator(D, T, TInfo);
>> +  return GetTypeSourceInfoForDeclarator(state, T, TInfo);
>>   }
>>   /// GetTypeForDeclarator - Convert the type for the specified
>> @@ -5161,131 +5233,25 @@ TypeSourceInfo *Sema::GetTypeForDeclarat
>>     return GetFullTypeForDeclarator(state, declSpecTy, ReturnTypeInfo);
>>   }
>> -/// Map an AttributedType::Kind to an ParsedAttr::Kind.
>> -static ParsedAttr::Kind getAttrListKind(AttributedType::Kind kind) {
>> -  switch (kind) {
>> -  case AttributedType::attr_address_space:
>> -    return ParsedAttr::AT_AddressSpace;
>> -  case AttributedType::attr_regparm:
>> -    return ParsedAttr::AT_Regparm;
>> -  case AttributedType::attr_vector_size:
>> -    return ParsedAttr::AT_VectorSize;
>> -  case AttributedType::attr_neon_vector_type:
>> -    return ParsedAttr::AT_NeonVectorType;
>> -  case AttributedType::attr_neon_polyvector_type:
>> -    return ParsedAttr::AT_NeonPolyVectorType;
>> -  case AttributedType::attr_objc_gc:
>> -    return ParsedAttr::AT_ObjCGC;
>> -  case AttributedType::attr_objc_ownership:
>> -  case AttributedType::attr_objc_inert_unsafe_unretained:
>> -    return ParsedAttr::AT_ObjCOwnership;
>> -  case AttributedType::attr_noreturn:
>> -    return ParsedAttr::AT_NoReturn;
>> -  case AttributedType::attr_nocf_check:
>> -    return ParsedAttr::AT_AnyX86NoCfCheck;
>> -  case AttributedType::attr_cdecl:
>> -    return ParsedAttr::AT_CDecl;
>> -  case AttributedType::attr_fastcall:
>> -    return ParsedAttr::AT_FastCall;
>> -  case AttributedType::attr_stdcall:
>> -    return ParsedAttr::AT_StdCall;
>> -  case AttributedType::attr_thiscall:
>> -    return ParsedAttr::AT_ThisCall;
>> -  case AttributedType::attr_regcall:
>> -    return ParsedAttr::AT_RegCall;
>> -  case AttributedType::attr_pascal:
>> -    return ParsedAttr::AT_Pascal;
>> -  case AttributedType::attr_swiftcall:
>> -    return ParsedAttr::AT_SwiftCall;
>> -  case AttributedType::attr_vectorcall:
>> -    return ParsedAttr::AT_VectorCall;
>> -  case AttributedType::attr_pcs:
>> -  case AttributedType::attr_pcs_vfp:
>> -    return ParsedAttr::AT_Pcs;
>> -  case AttributedType::attr_inteloclbicc:
>> -    return ParsedAttr::AT_IntelOclBicc;
>> -  case AttributedType::attr_ms_abi:
>> -    return ParsedAttr::AT_MSABI;
>> -  case AttributedType::attr_sysv_abi:
>> -    return ParsedAttr::AT_SysVABI;
>> -  case AttributedType::attr_preserve_most:
>> -    return ParsedAttr::AT_PreserveMost;
>> -  case AttributedType::attr_preserve_all:
>> -    return ParsedAttr::AT_PreserveAll;
>> -  case AttributedType::attr_ptr32:
>> -    return ParsedAttr::AT_Ptr32;
>> -  case AttributedType::attr_ptr64:
>> -    return ParsedAttr::AT_Ptr64;
>> -  case AttributedType::attr_sptr:
>> -    return ParsedAttr::AT_SPtr;
>> -  case AttributedType::attr_uptr:
>> -    return ParsedAttr::AT_UPtr;
>> -  case AttributedType::attr_nonnull:
>> -    return ParsedAttr::AT_TypeNonNull;
>> -  case AttributedType::attr_nullable:
>> -    return ParsedAttr::AT_TypeNullable;
>> -  case AttributedType::attr_null_unspecified:
>> -    return ParsedAttr::AT_TypeNullUnspecified;
>> -  case AttributedType::attr_objc_kindof:
>> -    return ParsedAttr::AT_ObjCKindOf;
>> -  case AttributedType::attr_ns_returns_retained:
>> -    return ParsedAttr::AT_NSReturnsRetained;
>> -  case AttributedType::attr_lifetimebound:
>> -    return ParsedAttr::AT_LifetimeBound;
>> -  }
>> -  llvm_unreachable("unexpected attribute kind!");
>> -}
>> -
>> -static void setAttributedTypeLoc(AttributedTypeLoc TL, const 
>> ParsedAttr &attr) {
>> -  TL.setAttrNameLoc(attr.getLoc());
>> -  if (TL.hasAttrExprOperand()) {
>> -    assert(attr.isArgExpr(0) && "mismatched attribute operand kind");
>> -    TL.setAttrExprOperand(attr.getArgAsExpr(0));
>> -  } else if (TL.hasAttrEnumOperand()) {
>> -    assert((attr.isArgIdent(0) || attr.isArgExpr(0)) &&
>> -           "unexpected attribute operand kind");
>> -    if (attr.isArgIdent(0))
>> -      TL.setAttrEnumOperandLoc(attr.getArgAsIdent(0)->Loc);
>> -    else
>> -      TL.setAttrEnumOperandLoc(attr.getArgAsExpr(0)->getExprLoc());
>> -  }
>> -
>> -  // FIXME: preserve this information to here.
>> -  if (TL.hasAttrOperand())
>> -    TL.setAttrOperandParensRange(SourceRange());
>> -}
>> -
>>   static void fillAttributedTypeLoc(AttributedTypeLoc TL,
>> -                                  const ParsedAttributesView &Attrs,
>> -                                  const ParsedAttributesView 
>> &DeclAttrs) {
>> -  // DeclAttrs and Attrs cannot be both empty.
>> -  assert((!Attrs.empty() || !DeclAttrs.empty()) &&
>> -         "no type attributes in the expected location!");
>> -
>> -  ParsedAttr::Kind parsedKind = getAttrListKind(TL.getAttrKind());
>> -  // Try to search for an attribute of matching kind in Attrs list.
>> -  for (const ParsedAttr &AL : Attrs)
>> -    if (AL.getKind() == parsedKind)
>> -      return setAttributedTypeLoc(TL, AL);
>> -
>> -  for (const ParsedAttr &AL : DeclAttrs)
>> -    if (AL.isCXX11Attribute() || AL.getKind() == parsedKind)
>> -      return setAttributedTypeLoc(TL, AL);
>> -  llvm_unreachable("no matching type attribute in expected location!");
>> +                                  TypeProcessingState &State) {
>> +  TL.setAttr(State.takeAttrForAttributedType(TL.getTypePtr()));
>>   }
>>   namespace {
>>     class TypeSpecLocFiller : public TypeLocVisitor<TypeSpecLocFiller> {
>>       ASTContext &Context;
>> +    TypeProcessingState &State;
>>       const DeclSpec &DS;
>>     public:
>> -    TypeSpecLocFiller(ASTContext &Context, const DeclSpec &DS)
>> -      : Context(Context), DS(DS) {}
>> +    TypeSpecLocFiller(ASTContext &Context, TypeProcessingState &State,
>> +                      const DeclSpec &DS)
>> +        : Context(Context), State(State), DS(DS) {}
>>       void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
>> -      fillAttributedTypeLoc(TL, DS.getAttributes(), 
>> ParsedAttributesView{});
>>         Visit(TL.getModifiedLoc());
>> +      fillAttributedTypeLoc(TL, State);
>>       }
>>       void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
>>         Visit(TL.getUnqualifiedLoc());
>> @@ -5442,11 +5408,13 @@ namespace {
>>     class DeclaratorLocFiller : public 
>> TypeLocVisitor<DeclaratorLocFiller> {
>>       ASTContext &Context;
>> +    TypeProcessingState &State;
>>       const DeclaratorChunk &Chunk;
>>     public:
>> -    DeclaratorLocFiller(ASTContext &Context, const DeclaratorChunk 
>> &Chunk)
>> -      : Context(Context), Chunk(Chunk) {}
>> +    DeclaratorLocFiller(ASTContext &Context, TypeProcessingState &State,
>> +                        const DeclaratorChunk &Chunk)
>> +        : Context(Context), State(State), Chunk(Chunk) {}
>>       void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
>>         llvm_unreachable("qualified type locs not expected here!");
>> @@ -5456,7 +5424,7 @@ namespace {
>>       }
>>       void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
>> -      fillAttributedTypeLoc(TL, Chunk.getAttrs(), 
>> ParsedAttributesView{});
>> +      fillAttributedTypeLoc(TL, State);
>>       }
>>       void VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {
>>         // nothing
>> @@ -5613,10 +5581,13 @@ fillDependentAddressSpaceTypeLoc(Depende
>>   /// up in the normal place in the declaration specifiers (such as a C++
>>   /// conversion function), this pointer will refer to a type source 
>> information
>>   /// for that return type.
>> -TypeSourceInfo *
>> -Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
>> -                                     TypeSourceInfo *ReturnTypeInfo) {
>> -  TypeSourceInfo *TInfo = Context.CreateTypeSourceInfo(T);
>> +static TypeSourceInfo *
>> +GetTypeSourceInfoForDeclarator(TypeProcessingState &State,
>> +                               QualType T, TypeSourceInfo 
>> *ReturnTypeInfo) {
>> +  Sema &S = State.getSema();
>> +  Declarator &D = State.getDeclarator();
>> +
>> +  TypeSourceInfo *TInfo = S.Context.CreateTypeSourceInfo(T);
>>     UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc();
>>     // Handle parameter packs whose type is a pack expansion.
>> @@ -5626,7 +5597,6 @@ Sema::GetTypeSourceInfoForDeclarator(Dec
>>     }
>>     for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
>> -
>>       if (DependentAddressSpaceTypeLoc DASTL =
>>           CurrTL.getAs<DependentAddressSpaceTypeLoc>()) {
>>         fillDependentAddressSpaceTypeLoc(DASTL, 
>> D.getTypeObject(i).getAttrs());
>> @@ -5641,8 +5611,7 @@ Sema::GetTypeSourceInfoForDeclarator(Dec
>>       }
>>       while (AttributedTypeLoc TL = CurrTL.getAs<AttributedTypeLoc>()) {
>> -      fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs(),
>> -                            D.getAttributes());
>> +      fillAttributedTypeLoc(TL, State);
>>         CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
>>       }
>> @@ -5650,7 +5619,7 @@ Sema::GetTypeSourceInfoForDeclarator(Dec
>>       while (AdjustedTypeLoc TL = CurrTL.getAs<AdjustedTypeLoc>())
>>         CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
>> -    DeclaratorLocFiller(Context, D.getTypeObject(i)).Visit(CurrTL);
>> +    DeclaratorLocFiller(S.Context, State, 
>> D.getTypeObject(i)).Visit(CurrTL);
>>       CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
>>     }
>> @@ -5661,7 +5630,7 @@ Sema::GetTypeSourceInfoForDeclarator(Dec
>>       assert(TL.getFullDataSize() == CurrTL.getFullDataSize());
>>       memcpy(CurrTL.getOpaqueData(), TL.getOpaqueData(), 
>> TL.getFullDataSize());
>>     } else {
>> -    TypeSpecLocFiller(Context, D.getDeclSpec()).Visit(CurrTL);
>> +    TypeSpecLocFiller(S.Context, State, D.getDeclSpec()).Visit(CurrTL);
>>     }
>>     return TInfo;
>> @@ -5890,7 +5859,7 @@ static bool hasDirectOwnershipQualifier(
>>     while (true) {
>>       // __strong id
>>       if (const AttributedType *attr = dyn_cast<AttributedType>(type)) {
>> -      if (attr->getAttrKind() == AttributedType::attr_objc_ownership)
>> +      if (attr->getAttrKind() == attr::ObjCOwnership)
>>           return true;
>>         type = attr->getModifiedType();
>> @@ -6034,9 +6003,9 @@ static bool handleObjCOwnershipTypeAttr(
>>     // the coexistence problems with __unsafe_unretained.
>>     if (!S.getLangOpts().ObjCAutoRefCount &&
>>         lifetime == Qualifiers::OCL_ExplicitNone) {
>> -    type = S.Context.getAttributedType(
>> -                             
>> AttributedType::attr_objc_inert_unsafe_unretained,
>> -                                       type, type);
>> +    type = state.getAttributedType(
>> +        createSimpleAttr<ObjCInertUnsafeUnretainedAttr>(S.Context, 
>> attr),
>> +        type, type);
>>       return true;
>>     }
>> @@ -6046,9 +6015,12 @@ static bool handleObjCOwnershipTypeAttr(
>>     // If we have a valid source location for the attribute, use an
>>     // AttributedType instead.
>> -  if (AttrLoc.isValid())
>> -    type = 
>> S.Context.getAttributedType(AttributedType::attr_objc_ownership,
>> -                                       origType, type);
>> +  if (AttrLoc.isValid()) {
>> +    type = state.getAttributedType(::new (S.Context) ObjCOwnershipAttr(
>> +                                       attr.getRange(), S.Context, II,
>> +                                       
>> attr.getAttributeSpellingListIndex()),
>> +                                   origType, type);
>> +  }
>>     auto diagnoseOrDelay = [](Sema &S, SourceLocation loc,
>>                               unsigned diagnostic, QualType type) {
>> @@ -6148,8 +6120,10 @@ static bool handleObjCGCTypeAttr(TypePro
>>     // Make an attributed type to preserve the source information.
>>     if (attr.getLoc().isValid())
>> -    type = S.Context.getAttributedType(AttributedType::attr_objc_gc,
>> -                                       origType, type);
>> +    type = state.getAttributedType(
>> +        ::new (S.Context) ObjCGCAttr(attr.getRange(), S.Context, II,
>> +                                     
>> attr.getAttributeSpellingListIndex()),
>> +        origType, type);
>>     return true;
>>   }
>> @@ -6292,37 +6266,50 @@ namespace {
>>   } // end anonymous namespace
>>   static bool handleMSPointerTypeQualifierAttr(TypeProcessingState 
>> &State,
>> -                                             ParsedAttr &Attr, 
>> QualType &Type) {
>> +                                             ParsedAttr &PAttr, 
>> QualType &Type) {
>>     Sema &S = State.getSema();
>> -  ParsedAttr::Kind Kind = Attr.getKind();
>> +  Attr *A;
>> +  switch (PAttr.getKind()) {
>> +  default: llvm_unreachable("Unknown attribute kind");
>> +  case ParsedAttr::AT_Ptr32:
>> +    A = createSimpleAttr<Ptr32Attr>(S.Context, PAttr);
>> +    break;
>> +  case ParsedAttr::AT_Ptr64:
>> +    A = createSimpleAttr<Ptr64Attr>(S.Context, PAttr);
>> +    break;
>> +  case ParsedAttr::AT_SPtr:
>> +    A = createSimpleAttr<SPtrAttr>(S.Context, PAttr);
>> +    break;
>> +  case ParsedAttr::AT_UPtr:
>> +    A = createSimpleAttr<UPtrAttr>(S.Context, PAttr);
>> +    break;
>> +  }
>> +
>> +  attr::Kind NewAttrKind = A->getKind();
>>     QualType Desugared = Type;
>>     const AttributedType *AT = dyn_cast<AttributedType>(Type);
>>     while (AT) {
>> -    AttributedType::Kind CurAttrKind = AT->getAttrKind();
>> +    attr::Kind CurAttrKind = AT->getAttrKind();
>>       // You cannot specify duplicate type attributes, so if the 
>> attribute has
>>       // already been applied, flag it.
>> -    if (getAttrListKind(CurAttrKind) == Kind) {
>> -      S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute_exact)
>> -        << Attr.getName();
>> +    if (NewAttrKind == CurAttrKind) {
>> +      S.Diag(PAttr.getLoc(), diag::warn_duplicate_attribute_exact)
>> +        << PAttr.getName();
>>         return true;
>>       }
>>       // You cannot have both __sptr and __uptr on the same type, nor 
>> can you
>>       // have __ptr32 and __ptr64.
>> -    if ((CurAttrKind == AttributedType::attr_ptr32 &&
>> -         Kind == ParsedAttr::AT_Ptr64) ||
>> -        (CurAttrKind == AttributedType::attr_ptr64 &&
>> -         Kind == ParsedAttr::AT_Ptr32)) {
>> -      S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
>> +    if ((CurAttrKind == attr::Ptr32 && NewAttrKind == attr::Ptr64) ||
>> +        (CurAttrKind == attr::Ptr64 && NewAttrKind == attr::Ptr32)) {
>> +      S.Diag(PAttr.getLoc(), diag::err_attributes_are_not_compatible)
>>           << "'__ptr32'" << "'__ptr64'";
>>         return true;
>> -    } else if ((CurAttrKind == AttributedType::attr_sptr &&
>> -                Kind == ParsedAttr::AT_UPtr) ||
>> -               (CurAttrKind == AttributedType::attr_uptr &&
>> -                Kind == ParsedAttr::AT_SPtr)) {
>> -      S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
>> +    } else if ((CurAttrKind == attr::SPtr && NewAttrKind == 
>> attr::UPtr) ||
>> +               (CurAttrKind == attr::UPtr && NewAttrKind == 
>> attr::SPtr)) {
>> +      S.Diag(PAttr.getLoc(), diag::err_attributes_are_not_compatible)
>>           << "'__sptr'" << "'__uptr'";
>>         return true;
>>       }
>> @@ -6333,41 +6320,64 @@ static bool handleMSPointerTypeQualifier
>>     // Pointer type qualifiers can only operate on pointer types, but not
>>     // pointer-to-member types.
>> +  //
>> +  // FIXME: Should we really be disallowing this attribute if there 
>> is any
>> +  // type sugar between it and the pointer (other than attributes)? 
>> Eg, this
>> +  // disallows the attribute on a parenthesized pointer.
>> +  // And if so, should we really allow *any* type attribute?
>>     if (!isa<PointerType>(Desugared)) {
>>       if (Type->isMemberPointerType())
>> -      S.Diag(Attr.getLoc(), diag::err_attribute_no_member_pointers) 
>> << Attr;
>> +      S.Diag(PAttr.getLoc(), diag::err_attribute_no_member_pointers) 
>> << PAttr;
>>       else
>> -      S.Diag(Attr.getLoc(), diag::err_attribute_pointers_only) << 
>> Attr << 0;
>> +      S.Diag(PAttr.getLoc(), diag::err_attribute_pointers_only) << 
>> PAttr << 0;
>>       return true;
>>     }
>> -  AttributedType::Kind TAK;
>> -  switch (Kind) {
>> -  default: llvm_unreachable("Unknown attribute kind");
>> -  case ParsedAttr::AT_Ptr32:
>> -    TAK = AttributedType::attr_ptr32;
>> -    break;
>> -  case ParsedAttr::AT_Ptr64:
>> -    TAK = AttributedType::attr_ptr64;
>> -    break;
>> -  case ParsedAttr::AT_SPtr:
>> -    TAK = AttributedType::attr_sptr;
>> -    break;
>> -  case ParsedAttr::AT_UPtr:
>> -    TAK = AttributedType::attr_uptr;
>> -    break;
>> -  }
>> -
>> -  Type = S.Context.getAttributedType(TAK, Type, Type);
>> +  Type = State.getAttributedType(A, Type, Type);
>>     return false;
>>   }
>> -bool Sema::checkNullabilityTypeSpecifier(QualType &type,
>> -                                         NullabilityKind nullability,
>> -                                         SourceLocation nullabilityLoc,
>> -                                         bool isContextSensitive,
>> -                                         bool allowOnArrayType) {
>> -  recordNullabilitySeen(*this, nullabilityLoc);
>> +/// Map a nullability attribute kind to a nullability kind.
>> +static NullabilityKind mapNullabilityAttrKind(ParsedAttr::Kind kind) {
>> +  switch (kind) {
>> +  case ParsedAttr::AT_TypeNonNull:
>> +    return NullabilityKind::NonNull;
>> +
>> +  case ParsedAttr::AT_TypeNullable:
>> +    return NullabilityKind::Nullable;
>> +
>> +  case ParsedAttr::AT_TypeNullUnspecified:
>> +    return NullabilityKind::Unspecified;
>> +
>> +  default:
>> +    llvm_unreachable("not a nullability attribute kind");
>> +  }
>> +}
>> +
>> +/// Applies a nullability type specifier to the given type, if possible.
>> +///
>> +/// \param state The type processing state.
>> +///
>> +/// \param type The type to which the nullability specifier will be
>> +/// added. On success, this type will be updated appropriately.
>> +///
>> +/// \param attr The attribute as written on the type.
>> +///
>> +/// \param allowArrayTypes Whether to accept nullability specifiers 
>> on an
>> +/// array type (e.g., because it will decay to a pointer).
>> +///
>> +/// \returns true if a problem has been diagnosed, false on success.
>> +static bool checkNullabilityTypeSpecifier(TypeProcessingState &state,
>> +                                          QualType &type,
>> +                                          ParsedAttr &attr,
>> +                                          bool allowOnArrayType) {
>> +  Sema &S = state.getSema();
>> +
>> +  NullabilityKind nullability = mapNullabilityAttrKind(attr.getKind());
>> +  SourceLocation nullabilityLoc = attr.getLoc();
>> +  bool isContextSensitive = attr.isContextSensitiveKeywordAttribute();
>> +
>> +  recordNullabilitySeen(S, nullabilityLoc);
>>     // Check for existing nullability attributes on the type.
>>     QualType desugared = type;
>> @@ -6376,7 +6386,7 @@ bool Sema::checkNullabilityTypeSpecifier
>>       if (auto existingNullability = 
>> attributed->getImmediateNullability()) {
>>         // Duplicated nullability.
>>         if (nullability == *existingNullability) {
>> -        Diag(nullabilityLoc, diag::warn_nullability_duplicate)
>> +        S.Diag(nullabilityLoc, diag::warn_nullability_duplicate)
>>             << DiagNullabilityKind(nullability, isContextSensitive)
>>             << FixItHint::CreateRemoval(nullabilityLoc);
>> @@ -6384,7 +6394,7 @@ bool Sema::checkNullabilityTypeSpecifier
>>         }
>>         // Conflicting nullability.
>> -      Diag(nullabilityLoc, diag::err_nullability_conflicting)
>> +      S.Diag(nullabilityLoc, diag::err_nullability_conflicting)
>>           << DiagNullabilityKind(nullability, isContextSensitive)
>>           << DiagNullabilityKind(*existingNullability, false);
>>         return true;
>> @@ -6397,9 +6407,9 @@ bool Sema::checkNullabilityTypeSpecifier
>>     // This (unlike the code above) looks through typedefs that might
>>     // have nullability specifiers on them, which means we cannot
>>     // provide a useful Fix-It.
>> -  if (auto existingNullability = desugared->getNullability(Context)) {
>> +  if (auto existingNullability = desugared->getNullability(S.Context)) {
>>       if (nullability != *existingNullability) {
>> -      Diag(nullabilityLoc, diag::err_nullability_conflicting)
>> +      S.Diag(nullabilityLoc, diag::err_nullability_conflicting)
>>           << DiagNullabilityKind(nullability, isContextSensitive)
>>           << DiagNullabilityKind(*existingNullability, false);
>> @@ -6410,7 +6420,7 @@ bool Sema::checkNullabilityTypeSpecifier
>>           if (auto typedefNullability
>>                 = 
>> AttributedType::stripOuterNullability(underlyingType)) {
>>             if (*typedefNullability == *existingNullability) {
>> -            Diag(typedefDecl->getLocation(), 
>> diag::note_nullability_here)
>> +            S.Diag(typedefDecl->getLocation(), 
>> diag::note_nullability_here)
>>                 << DiagNullabilityKind(*existingNullability, false);
>>             }
>>           }
>> @@ -6423,7 +6433,7 @@ bool Sema::checkNullabilityTypeSpecifier
>>     // If this definitely isn't a pointer type, reject the specifier.
>>     if (!desugared->canHaveNullability() &&
>>         !(allowOnArrayType && desugared->isArrayType())) {
>> -    Diag(nullabilityLoc, diag::err_nullability_nonpointer)
>> +    S.Diag(nullabilityLoc, diag::err_nullability_nonpointer)
>>         << DiagNullabilityKind(nullability, isContextSensitive) << type;
>>       return true;
>>     }
>> @@ -6441,10 +6451,10 @@ bool Sema::checkNullabilityTypeSpecifier
>>       if (pointeeType->isAnyPointerType() ||
>>           pointeeType->isObjCObjectPointerType() ||
>>           pointeeType->isMemberPointerType()) {
>> -      Diag(nullabilityLoc, diag::err_nullability_cs_multilevel)
>> +      S.Diag(nullabilityLoc, diag::err_nullability_cs_multilevel)
>>           << DiagNullabilityKind(nullability, true)
>>           << type;
>> -      Diag(nullabilityLoc, diag::note_nullability_type_specifier)
>> +      S.Diag(nullabilityLoc, diag::note_nullability_type_specifier)
>>           << DiagNullabilityKind(nullability, false)
>>           << type
>>           << FixItHint::CreateReplacement(nullabilityLoc,
>> @@ -6454,16 +6464,21 @@ bool Sema::checkNullabilityTypeSpecifier
>>     }
>>     // Form the attributed type.
>> -  type = Context.getAttributedType(
>> -           AttributedType::getNullabilityAttrKind(nullability), type, 
>> type);
>> +  type = state.getAttributedType(
>> +      createNullabilityAttr(S.Context, attr, nullability), type, type);
>>     return false;
>>   }
>> -bool Sema::checkObjCKindOfType(QualType &type, SourceLocation loc) {
>> +/// Check the application of the Objective-C '__kindof' qualifier to
>> +/// the given type.
>> +static bool checkObjCKindOfType(TypeProcessingState &state, QualType 
>> &type,
>> +                                ParsedAttr &attr) {
>> +  Sema &S = state.getSema();
>> +
>>     if (isa<ObjCTypeParamType>(type)) {
>>       // Build the attributed type to record where __kindof occurred.
>> -    type = Context.getAttributedType(AttributedType::attr_objc_kindof,
>> -                                     type, type);
>> +    type = state.getAttributedType(
>> +        createSimpleAttr<ObjCKindOfAttr>(S.Context, attr), type, type);
>>       return false;
>>     }
>> @@ -6475,7 +6490,7 @@ bool Sema::checkObjCKindOfType(QualType
>>     // If not, we can't apply __kindof.
>>     if (!objType) {
>>       // FIXME: Handle dependent types that aren't yet object types.
>> -    Diag(loc, diag::err_objc_kindof_nonobject)
>> +    S.Diag(attr.getLoc(), diag::err_objc_kindof_nonobject)
>>         << type;
>>       return true;
>>     }
>> @@ -6483,45 +6498,31 @@ bool Sema::checkObjCKindOfType(QualType
>>     // Rebuild the "equivalent" type, which pushes __kindof down into
>>     // the object type.
>>     // There is no need to apply kindof on an unqualified id type.
>> -  QualType equivType = Context.getObjCObjectType(
>> +  QualType equivType = S.Context.getObjCObjectType(
>>         objType->getBaseType(), objType->getTypeArgsAsWritten(),
>>         objType->getProtocols(),
>>         /*isKindOf=*/objType->isObjCUnqualifiedId() ? false : true);
>>     // If we started with an object pointer type, rebuild it.
>>     if (ptrType) {
>> -    equivType = Context.getObjCObjectPointerType(equivType);
>> -    if (auto nullability = type->getNullability(Context)) {
>> -      auto attrKind = 
>> AttributedType::getNullabilityAttrKind(*nullability);
>> -      equivType = Context.getAttributedType(attrKind, equivType, 
>> equivType);
>> +    equivType = S.Context.getObjCObjectPointerType(equivType);
>> +    if (auto nullability = type->getNullability(S.Context)) {
>> +      // We create a nullability attribute from the __kindof attribute.
>> +      // Make sure that will make sense.
>> +      assert(attr.getAttributeSpellingListIndex() == 0 &&
>> +             "multiple spellings for __kindof?");
>> +      Attr *A = createNullabilityAttr(S.Context, attr, *nullability);
>> +      A->setImplicit(true);
>> +      equivType = state.getAttributedType(A, equivType, equivType);
>>       }
>>     }
>>     // Build the attributed type to record where __kindof occurred.
>> -  type = Context.getAttributedType(AttributedType::attr_objc_kindof,
>> -                                   type,
>> -                                   equivType);
>> -
>> +  type = state.getAttributedType(
>> +      createSimpleAttr<ObjCKindOfAttr>(S.Context, attr), type, 
>> equivType);
>>     return false;
>>   }
>> -/// Map a nullability attribute kind to a nullability kind.
>> -static NullabilityKind mapNullabilityAttrKind(ParsedAttr::Kind kind) {
>> -  switch (kind) {
>> -  case ParsedAttr::AT_TypeNonNull:
>> -    return NullabilityKind::NonNull;
>> -
>> -  case ParsedAttr::AT_TypeNullable:
>> -    return NullabilityKind::Nullable;
>> -
>> -  case ParsedAttr::AT_TypeNullUnspecified:
>> -    return NullabilityKind::Unspecified;
>> -
>> -  default:
>> -    llvm_unreachable("not a nullability attribute kind");
>> -  }
>> -}
>> -
>>   /// Distribute a nullability type attribute that cannot be applied to
>>   /// the type specifier to a pointer, block pointer, or member pointer
>>   /// declarator, complaining if necessary.
>> @@ -6609,27 +6610,27 @@ static bool distributeNullabilityTypeAtt
>>     return false;
>>   }
>> -static AttributedType::Kind getCCTypeAttrKind(ParsedAttr &Attr) {
>> +static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) {
>>     assert(!Attr.isInvalid());
>>     switch (Attr.getKind()) {
>>     default:
>>       llvm_unreachable("not a calling convention attribute");
>>     case ParsedAttr::AT_CDecl:
>> -    return AttributedType::attr_cdecl;
>> +    return createSimpleAttr<CDeclAttr>(Ctx, Attr);
>>     case ParsedAttr::AT_FastCall:
>> -    return AttributedType::attr_fastcall;
>> +    return createSimpleAttr<FastCallAttr>(Ctx, Attr);
>>     case ParsedAttr::AT_StdCall:
>> -    return AttributedType::attr_stdcall;
>> +    return createSimpleAttr<StdCallAttr>(Ctx, Attr);
>>     case ParsedAttr::AT_ThisCall:
>> -    return AttributedType::attr_thiscall;
>> +    return createSimpleAttr<ThisCallAttr>(Ctx, Attr);
>>     case ParsedAttr::AT_RegCall:
>> -    return AttributedType::attr_regcall;
>> +    return createSimpleAttr<RegCallAttr>(Ctx, Attr);
>>     case ParsedAttr::AT_Pascal:
>> -    return AttributedType::attr_pascal;
>> +    return createSimpleAttr<PascalAttr>(Ctx, Attr);
>>     case ParsedAttr::AT_SwiftCall:
>> -    return AttributedType::attr_swiftcall;
>> +    return createSimpleAttr<SwiftCallAttr>(Ctx, Attr);
>>     case ParsedAttr::AT_VectorCall:
>> -    return AttributedType::attr_vectorcall;
>> +    return createSimpleAttr<VectorCallAttr>(Ctx, Attr);
>>     case ParsedAttr::AT_Pcs: {
>>       // The attribute may have had a fixit applied where we treated an
>>       // identifier as a string literal.  The contents of the string 
>> are valid,
>> @@ -6639,20 +6640,22 @@ static AttributedType::Kind getCCTypeAtt
>>         Str = cast<StringLiteral>(Attr.getArgAsExpr(0))->getString();
>>       else
>>         Str = Attr.getArgAsIdent(0)->Ident->getName();
>> -    return llvm::StringSwitch<AttributedType::Kind>(Str)
>> -        .Case("aapcs", AttributedType::attr_pcs)
>> -        .Case("aapcs-vfp", AttributedType::attr_pcs_vfp);
>> +    PcsAttr::PCSType Type;
>> +    if (!PcsAttr::ConvertStrToPCSType(Str, Type))
>> +      llvm_unreachable("already validated the attribute");
>> +    return ::new (Ctx) PcsAttr(Attr.getRange(), Ctx, Type,
>> +                               Attr.getAttributeSpellingListIndex());
>>     }
>>     case ParsedAttr::AT_IntelOclBicc:
>> -    return AttributedType::attr_inteloclbicc;
>> +    return createSimpleAttr<IntelOclBiccAttr>(Ctx, Attr);
>>     case ParsedAttr::AT_MSABI:
>> -    return AttributedType::attr_ms_abi;
>> +    return createSimpleAttr<MSABIAttr>(Ctx, Attr);
>>     case ParsedAttr::AT_SysVABI:
>> -    return AttributedType::attr_sysv_abi;
>> +    return createSimpleAttr<SysVABIAttr>(Ctx, Attr);
>>     case ParsedAttr::AT_PreserveMost:
>> -    return AttributedType::attr_preserve_most;
>> +    return createSimpleAttr<PreserveMostAttr>(Ctx, Attr);
>>     case ParsedAttr::AT_PreserveAll:
>> -    return AttributedType::attr_preserve_all;
>> +    return createSimpleAttr<PreserveAllAttr>(Ctx, Attr);
>>     }
>>     llvm_unreachable("unexpected attribute kind!");
>>   }
>> @@ -6700,8 +6703,9 @@ static bool handleFunctionTypeAttr(TypeP
>>           = unwrapped.get()->getExtInfo().withProducesResult(true);
>>         type = unwrapped.wrap(S, 
>> S.Context.adjustFunctionType(unwrapped.get(), EI));
>>       }
>> -    type = 
>> S.Context.getAttributedType(AttributedType::attr_ns_returns_retained,
>> -                                       origType, type);
>> +    type = state.getAttributedType(
>> +        createSimpleAttr<NSReturnsRetainedAttr>(S.Context, attr),
>> +        origType, type);
>>       return true;
>>     }
>> @@ -6776,13 +6780,12 @@ static bool handleFunctionTypeAttr(TypeP
>>     const FunctionType *fn = unwrapped.get();
>>     CallingConv CCOld = fn->getCallConv();
>> -  AttributedType::Kind CCAttrKind = getCCTypeAttrKind(attr);
>> +  Attr *CCAttr = getCCTypeAttr(S.Context, attr);
>>     if (CCOld != CC) {
>>       // Error out on when there's already an attribute on the type
>>       // and the CCs don't match.
>> -    const AttributedType *AT = S.getCallingConvAttributedType(type);
>> -    if (AT && AT->getAttrKind() != CCAttrKind) {
>> +    if (const AttributedType *AT = 
>> S.getCallingConvAttributedType(type)) {
>>         S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
>>           << FunctionType::getNameForCallConv(CC)
>>           << FunctionType::getNameForCallConv(CCOld);
>> @@ -6836,7 +6839,7 @@ static bool handleFunctionTypeAttr(TypeP
>>       Equivalent =
>>         unwrapped.wrap(S, 
>> S.Context.adjustFunctionType(unwrapped.get(), EI));
>>     }
>> -  type = S.Context.getAttributedType(CCAttrKind, type, Equivalent);
>> +  type = state.getAttributedType(CCAttr, type, Equivalent);
>>     return true;
>>   }
>> @@ -7192,14 +7195,15 @@ static void deduceOpenCLImplicitAddrSpac
>>     T = State.getSema().Context.getAddrSpaceQualType(T, ImpAddr);
>>   }
>> -static void HandleLifetimeBoundAttr(QualType &CurType,
>> -                                    const ParsedAttr &Attr,
>> -                                    Sema &S, Declarator &D) {
>> -  if (D.isDeclarationOfFunction()) {
>> -    CurType = 
>> S.Context.getAttributedType(AttributedType::attr_lifetimebound,
>> -                                          CurType, CurType);
>> +static void HandleLifetimeBoundAttr(TypeProcessingState &State,
>> +                                    QualType &CurType,
>> +                                    ParsedAttr &Attr) {
>> +  if (State.getDeclarator().isDeclarationOfFunction()) {
>> +    CurType = State.getAttributedType(
>> +        createSimpleAttr<LifetimeBoundAttr>(State.getSema().Context, 
>> Attr),
>> +        CurType, CurType);
>>     } else {
>> -    Attr.diagnoseAppertainsTo(S, nullptr);
>> +    Attr.diagnoseAppertainsTo(State.getSema(), nullptr);
>>     }
>>   }
>> @@ -7309,11 +7313,8 @@ static void processTypeAttrs(TypeProcess
>>         attr.setUsedAsTypeAttr();
>>         break;
>>       case ParsedAttr::AT_LifetimeBound:
>> -      if (TAL == TAL_DeclChunk) {
>> -        HandleLifetimeBoundAttr(type, attr, state.getSema(),
>> -                                state.getDeclarator());
>> -        attr.setUsedAsTypeAttr();
>> -      }
>> +      if (TAL == TAL_DeclChunk)
>> +        HandleLifetimeBoundAttr(state, type, attr);
>>         break;
>>       MS_TYPE_ATTRS_CASELIST:
>> @@ -7337,11 +7338,10 @@ static void processTypeAttrs(TypeProcess
>>           bool allowOnArrayType =
>>               state.getDeclarator().isPrototypeContext() &&
>>               !hasOuterPointerLikeChunk(state.getDeclarator(), endIndex);
>> -        if (state.getSema().checkNullabilityTypeSpecifier(
>> +        if (checkNullabilityTypeSpecifier(
>> +              state,
>>                 type,
>> -              mapNullabilityAttrKind(attr.getKind()),
>> -              attr.getLoc(),
>> -              attr.isContextSensitiveKeywordAttribute(),
>> +              attr,
>>                 allowOnArrayType)) {
>>             attr.setInvalid();
>>           }
>> @@ -7368,9 +7368,8 @@ static void processTypeAttrs(TypeProcess
>>         }
>>         // Apply it regardless.
>> -      if (state.getSema().checkObjCKindOfType(type, attr.getLoc()))
>> +      if (checkObjCKindOfType(state, type, attr))
>>           attr.setInvalid();
>> -      attr.setUsedAsTypeAttr();
>>         break;
>>       FUNCTION_TYPE_ATTRS_CASELIST:
>>
>> Modified: cfe/trunk/lib/Sema/TreeTransform.h
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=340215&r1=340214&r2=340215&view=diff 
>>
>> ============================================================================== 
>>
>> --- cfe/trunk/lib/Sema/TreeTransform.h (original)
>> +++ cfe/trunk/lib/Sema/TreeTransform.h Mon Aug 20 14:47:29 2018
>> @@ -6058,6 +6058,12 @@ QualType TreeTransform<Derived>::Transfo
>>     if (modifiedType.isNull())
>>       return QualType();
>> +  // oldAttr can be null if we started with a QualType rather than a 
>> TypeLoc.
>> +  const Attr *oldAttr = TL.getAttr();
>> +  const Attr *newAttr = oldAttr ? getDerived().TransformAttr(oldAttr) 
>> : nullptr;
>> +  if (oldAttr && !newAttr)
>> +    return QualType();
>> +
>>     QualType result = TL.getType();
>>     // FIXME: dependent operand expressions?
>> @@ -6074,26 +6080,20 @@ QualType TreeTransform<Derived>::Transfo
>>       // type sugar, and therefore cannot be diagnosed in any other way.
>>       if (auto nullability = oldType->getImmediateNullability()) {
>>         if (!modifiedType->canHaveNullability()) {
>> -        SemaRef.Diag(TL.getAttrNameLoc(), 
>> diag::err_nullability_nonpointer)
>> -          << DiagNullabilityKind(*nullability, false) << modifiedType;
>> +        SemaRef.Diag(TL.getAttr()->getLocation(),
>> +                     diag::err_nullability_nonpointer)
>> +            << DiagNullabilityKind(*nullability, false) << modifiedType;
>>           return QualType();
>>         }
>>       }
>> -    result = SemaRef.Context.getAttributedType(oldType->getAttrKind(),
>> +    result = SemaRef.Context.getAttributedType(TL.getAttrKind(),
>>                                                  modifiedType,
>>                                                  equivalentType);
>>     }
>>     AttributedTypeLoc newTL = TLB.push<AttributedTypeLoc>(result);
>> -  newTL.setAttrNameLoc(TL.getAttrNameLoc());
>> -  if (TL.hasAttrOperand())
>> -    newTL.setAttrOperandParensRange(TL.getAttrOperandParensRange());
>> -  if (TL.hasAttrExprOperand())
>> -    newTL.setAttrExprOperand(TL.getAttrExprOperand());
>> -  else if (TL.hasAttrEnumOperand())
>> -    newTL.setAttrEnumOperandLoc(TL.getAttrEnumOperandLoc());
>> -
>> +  newTL.setAttr(newAttr);
>>     return result;
>>   }
>>
>> Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=340215&r1=340214&r2=340215&view=diff 
>>
>> ============================================================================== 
>>
>> --- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
>> +++ cfe/trunk/lib/Serialization/ASTReader.cpp Mon Aug 20 14:47:29 2018
>> @@ -6455,6 +6455,10 @@ class TypeLocReader : public TypeLocVisi
>>       return Reader->ReadNestedNameSpecifierLoc(*F, Record, Idx);
>>     }
>> +  Attr *ReadAttr() {
>> +    return Reader->ReadAttr(*F, Record, Idx);
>> +  }
>> +
>>   public:
>>     TypeLocReader(ModuleFile &F, ASTReader &Reader,
>>                   const ASTReader::RecordData &Record, unsigned &Idx)
>> @@ -6646,20 +6650,7 @@ void TypeLocReader::VisitEnumTypeLoc(Enu
>>   }
>>   void TypeLocReader::VisitAttributedTypeLoc(AttributedTypeLoc TL) {
>> -  TL.setAttrNameLoc(ReadSourceLocation());
>> -  if (TL.hasAttrOperand()) {
>> -    SourceRange range;
>> -    range.setBegin(ReadSourceLocation());
>> -    range.setEnd(ReadSourceLocation());
>> -    TL.setAttrOperandParensRange(range);
>> -  }
>> -  if (TL.hasAttrExprOperand()) {
>> -    if (Record[Idx++])
>> -      TL.setAttrExprOperand(Reader->ReadExpr(*F));
>> -    else
>> -      TL.setAttrExprOperand(nullptr);
>> -  } else if (TL.hasAttrEnumOperand())
>> -    TL.setAttrEnumOperandLoc(ReadSourceLocation());
>> +  TL.setAttr(ReadAttr());
>>   }
>>   void 
>> TypeLocReader::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
>>
>> Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=340215&r1=340214&r2=340215&view=diff 
>>
>> ============================================================================== 
>>
>> --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
>> +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Mon Aug 20 14:47:29 
>> 2018
>> @@ -2648,19 +2648,72 @@ void ASTDeclReader::VisitOMPCapturedExpr
>>   // Attribute Reading
>>   
>> //===----------------------------------------------------------------------===// 
>>
>> -/// Reads attributes from the current stream position.
>> -void ASTReader::ReadAttributes(ASTRecordReader &Record, AttrVec 
>> &Attrs) {
>> -  for (unsigned i = 0, e = Record.readInt(); i != e; ++i) {
>> -    Attr *New = nullptr;
>> -    auto Kind = (attr::Kind)Record.readInt();
>> -    SourceRange Range = Record.readSourceRange();
>> -    ASTContext &Context = getContext();
>> +namespace {
>> +class AttrReader {
>> +  ModuleFile *F;
>> +  ASTReader *Reader;
>> +  const ASTReader::RecordData &Record;
>> +  unsigned &Idx;
>> -#include "clang/Serialization/AttrPCHRead.inc"
>> +public:
>> +  AttrReader(ModuleFile &F, ASTReader &Reader,
>> +             const ASTReader::RecordData &Record, unsigned &Idx)
>> +      : F(&F), Reader(&Reader), Record(Record), Idx(Idx) {}
>> +
>> +  const uint64_t &readInt() { return Record[Idx++]; }
>> +
>> +  SourceRange readSourceRange() {
>> +    return Reader->ReadSourceRange(*F, Record, Idx);
>> +  }
>> +
>> +  Expr *readExpr() { return Reader->ReadExpr(*F); }
>> +
>> +  std::string readString() {
>> +    return Reader->ReadString(Record, Idx);
>> +  }
>> +
>> +  TypeSourceInfo *getTypeSourceInfo() {
>> +    return Reader->GetTypeSourceInfo(*F, Record, Idx);
>> +  }
>> +
>> +  IdentifierInfo *getIdentifierInfo() {
>> +    return Reader->GetIdentifierInfo(*F, Record, Idx);
>> +  }
>> -    assert(New && "Unable to decode attribute?");
>> -    Attrs.push_back(New);
>> +  VersionTuple readVersionTuple() {
>> +    return ASTReader::ReadVersionTuple(Record, Idx);
>>     }
>> +
>> +  template <typename T> T *GetLocalDeclAs(uint32_t LocalID) {
>> +    return cast_or_null<T>(Reader->GetLocalDecl(*F, LocalID));
>> +  }
>> +};
>> +}
>> +
>> +Attr *ASTReader::ReadAttr(ModuleFile &M, const RecordData &Rec,
>> +                          unsigned &Idx) {
>> +  AttrReader Record(M, *this, Rec, Idx);
>> +  auto V = Record.readInt();
>> +  if (!V)
>> +    return nullptr;
>> +
>> +  Attr *New = nullptr;
>> +  // Kind is stored as a 1-based integer because 0 is used to 
>> indicate a null
>> +  // Attr pointer.
>> +  auto Kind = static_cast<attr::Kind>(V - 1);
>> +  SourceRange Range = Record.readSourceRange();
>> +  ASTContext &Context = getContext();
>> +
>> +#include "clang/Serialization/AttrPCHRead.inc"
>> +
>> +  assert(New && "Unable to decode attribute?");
>> +  return New;
>> +}
>> +
>> +/// Reads attributes from the current stream position.
>> +void ASTReader::ReadAttributes(ASTRecordReader &Record, AttrVec 
>> &Attrs) {
>> +  for (unsigned I = 0, E = Record.readInt(); I != E; ++I)
>> +    Attrs.push_back(Record.readAttr());
>>   }
>>   
>> //===----------------------------------------------------------------------===// 
>>
>>
>> Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=340215&r1=340214&r2=340215&view=diff 
>>
>> ============================================================================== 
>>
>> --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
>> +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Mon Aug 20 14:47:29 2018
>> @@ -770,19 +770,7 @@ void TypeLocWriter::VisitEnumTypeLoc(Enu
>>   }
>>   void TypeLocWriter::VisitAttributedTypeLoc(AttributedTypeLoc TL) {
>> -  Record.AddSourceLocation(TL.getAttrNameLoc());
>> -  if (TL.hasAttrOperand()) {
>> -    SourceRange range = TL.getAttrOperandParensRange();
>> -    Record.AddSourceLocation(range.getBegin());
>> -    Record.AddSourceLocation(range.getEnd());
>> -  }
>> -  if (TL.hasAttrExprOperand()) {
>> -    Expr *operand = TL.getAttrExprOperand();
>> -    Record.push_back(operand ? 1 : 0);
>> -    if (operand) Record.AddStmt(operand);
>> -  } else if (TL.hasAttrEnumOperand()) {
>> -    Record.AddSourceLocation(TL.getAttrEnumOperandLoc());
>> -  }
>> +  Record.AddAttr(TL.getAttr());
>>   }
>>   void 
>> TypeLocWriter::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
>> @@ -4481,16 +4469,21 @@ void ASTWriter::WriteModuleFileExtension
>>   // General Serialization Routines
>>   
>> //===----------------------------------------------------------------------===// 
>>
>> -/// Emit the list of attributes to the specified record.
>> -void ASTRecordWriter::AddAttributes(ArrayRef<const Attr *> Attrs) {
>> +void ASTRecordWriter::AddAttr(const Attr *A) {
>>     auto &Record = *this;
>> -  Record.push_back(Attrs.size());
>> -  for (const auto *A : Attrs) {
>> -    Record.push_back(A->getKind()); // FIXME: stable encoding, target 
>> attrs
>> -    Record.AddSourceRange(A->getRange());
>> +  if (!A)
>> +    return Record.push_back(0);
>> +  Record.push_back(A->getKind() + 1); // FIXME: stable encoding, 
>> target attrs
>> +  Record.AddSourceRange(A->getRange());
>>   #include "clang/Serialization/AttrPCHWrite.inc"
>> -  }
>> +}
>> +
>> +/// Emit the list of attributes to the specified record.
>> +void ASTRecordWriter::AddAttributes(ArrayRef<const Attr *> Attrs) {
>> +  push_back(Attrs.size());
>> +  for (const auto *A : Attrs)
>> +    AddAttr(A);
>>   }
>>   void ASTWriter::AddToken(const Token &Tok, RecordDataImpl &Record) {
>>
>> Modified: cfe/trunk/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CheckerHelpers.cpp?rev=340215&r1=340214&r2=340215&view=diff 
>>
>> ============================================================================== 
>>
>> --- cfe/trunk/lib/StaticAnalyzer/Core/CheckerHelpers.cpp (original)
>> +++ cfe/trunk/lib/StaticAnalyzer/Core/CheckerHelpers.cpp Mon Aug 20 
>> 14:47:29 2018
>> @@ -103,9 +103,9 @@ Nullability getNullabilityAnnotation(Qua
>>     const auto *AttrType = Type->getAs<AttributedType>();
>>     if (!AttrType)
>>       return Nullability::Unspecified;
>> -  if (AttrType->getAttrKind() == AttributedType::attr_nullable)
>> +  if (AttrType->getAttrKind() == attr::TypeNullable)
>>       return Nullability::Nullable;
>> -  else if (AttrType->getAttrKind() == AttributedType::attr_nonnull)
>> +  else if (AttrType->getAttrKind() == attr::TypeNonNull)
>>       return Nullability::Nonnull;
>>     return Nullability::Unspecified;
>>   }
>>
>> Modified: cfe/trunk/test/SemaCXX/calling-conv-compat.cpp
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/calling-conv-compat.cpp?rev=340215&r1=340214&r2=340215&view=diff 
>>
>> ============================================================================== 
>>
>> --- cfe/trunk/test/SemaCXX/calling-conv-compat.cpp (original)
>> +++ cfe/trunk/test/SemaCXX/calling-conv-compat.cpp Mon Aug 20 14:47:29 
>> 2018
>> @@ -1,4 +1,8 @@
>>   // RUN: %clang_cc1 -fsyntax-only -std=c++11 -fms-extensions -verify 
>> -triple i686-pc-win32 %s
>> +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -fms-extensions -verify 
>> -triple x86_64-pc-win32 %s
>> +
>> +// FIXME: Extend this portion of the test to cover the 64-bit case.
>> +#if !_M_X64
>>   // Pointers to free functions
>>   void            free_func_default();
>> @@ -244,11 +248,16 @@ void call_member_inheritance() {
>>   }
>>   } // end namespace NonVariadic
>> +#endif  // !_M_X64
>> +
>>   namespace Variadic {
>>   struct A {
>>     void            member_default(int, ...);
>>     void __cdecl    member_cdecl(int, ...);
>> -  void __thiscall member_thiscall(int, ...); // expected-error 
>> {{variadic function cannot use thiscall calling convention}}
>> +  void __thiscall member_thiscall(int, ...);
>> +#if !_M_X64
>> +  // expected-error at -2 {{variadic function cannot use thiscall 
>> calling convention}}
>> +#endif
>>   };
>>   struct B : public A {
>> @@ -319,7 +328,10 @@ mptr_t __stdcall return_mptr_std(short)
>>   }
>>   void (A::*(*return_fptr_std_mptr(char))(short))(int) {
>> -  return return_mptr_std; // expected-error {{cannot initialize 
>> return object of type 'void (MultiChunkDecls::A::*(*)(short))(int) 
>> __attribute__((thiscall))' with an lvalue of type 
>> 'MultiChunkDecls::mptr_t (short) __attribute__((stdcall))'}}
>> +  return return_mptr_std;
>> +#if !_M_X64
>> +  // expected-error at -2 {{cannot initialize return object of type 
>> 'void (MultiChunkDecls::A::*(*)(short))(int) 
>> __attribute__((thiscall))' with an lvalue of type 
>> 'MultiChunkDecls::mptr_t (short) __attribute__((stdcall))'}}
>> +#endif
>>   }
>>   void call_return() {
>> @@ -387,15 +399,32 @@ Y<decltype(&A::method_thiscall)>::p tmpl
>>   // Test that lambdas that capture nothing convert to cdecl function 
>> pointers.
>>   namespace Lambdas {
>> -
>>   void pass_fptr_cdecl   (void (__cdecl    *fp)());
>> -void pass_fptr_stdcall (void (__stdcall  *fp)()); // expected-note 
>> {{candidate function not viable}}
>> -void pass_fptr_fastcall(void (__fastcall *fp)()); // expected-note 
>> {{candidate function not viable}}
>> +void pass_fptr_stdcall (void (__stdcall  *fp)());
>> +void pass_fptr_fastcall(void (__fastcall *fp)());
>>   void conversion_to_fptr() {
>>     pass_fptr_cdecl   ([]() { } );
>> -  pass_fptr_stdcall ([]() { } ); // expected-error {{no matching 
>> function for call}}
>> -  pass_fptr_fastcall([]() { } ); // expected-error {{no matching 
>> function for call}}
>> +
>> +  pass_fptr_stdcall ([]() { } );
>> +#if !_M_X64
>> +  // expected-error at -2 {{no matching function for call}}
>> +  // expected-note at -9 {{candidate function not viable}}
>> +#endif
>> +
>> +  pass_fptr_fastcall([]() { } );
>> +#if !_M_X64
>> +  // expected-error at -2 {{no matching function for call}}
>> +  // expected-note at -14 {{candidate function not viable}}
>> +#endif
>> +}
>>   }
>> +namespace D50526 {
>> +  template<typename T, T (__stdcall f)()> void g();
>> +  void h() { g<void, h>(); }
>> +#if !_M_X64
>> +  // expected-error at -2 {{no matching function for call to}}
>> +  // expected-note at -4 {{invalid explicitly-specified argument}}
>> +#endif
>>   }
>>
>> Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
>> URL: 
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=340215&r1=340214&r2=340215&view=diff 
>>
>> ============================================================================== 
>>
>> --- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original)
>> +++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Mon Aug 20 14:47:29 
>> 2018
>> @@ -2470,8 +2470,10 @@ namespace {
>>   static const AttrClassDescriptor AttrClassDescriptors[] = {
>>     { "ATTR", "Attr" },
>> +  { "TYPE_ATTR", "TypeAttr" },
>>     { "STMT_ATTR", "StmtAttr" },
>>     { "INHERITABLE_ATTR", "InheritableAttr" },
>> +  { "DECL_OR_TYPE_ATTR", "DeclOrTypeAttr" },
>>     { "INHERITABLE_PARAM_ATTR", "InheritableParamAttr" },
>>     { "PARAMETER_ABI_ATTR", "ParameterABIAttr" }
>>   };
>>
>>
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>>



More information about the cfe-commits mailing list