<div dir="ltr">Thanks, fixed and re-committed as r340215.</div><br><div class="gmail_quote"><div dir="ltr">On Mon, 13 Aug 2018 at 18:56, Reid Kleckner via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rnk<br>
Date: Mon Aug 13 18:55:37 2018<br>
New Revision: 339638<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=339638&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=339638&view=rev</a><br>
Log:<br>
Revert r339623 "Model type attributes as regular Attrs."<br>
<br>
This breaks compiling atlwin.h in Chromium. I'm sure the code is invalid<br>
in some way, but we put a lot of work into accepting it, and I'm sure<br>
rejecting it was not an intended consequence of this refactoring. :)<br>
<br>
Modified:<br>
    cfe/trunk/include/clang/AST/ASTContext.h<br>
    cfe/trunk/include/clang/AST/Attr.h<br>
    cfe/trunk/include/clang/AST/Type.h<br>
    cfe/trunk/include/clang/AST/TypeLoc.h<br>
    cfe/trunk/include/clang/Basic/Attr.td<br>
    cfe/trunk/include/clang/Sema/Sema.h<br>
    cfe/trunk/include/clang/Serialization/ASTReader.h<br>
    cfe/trunk/include/clang/Serialization/ASTWriter.h<br>
    cfe/trunk/lib/ARCMigrate/TransGCAttrs.cpp<br>
    cfe/trunk/lib/ARCMigrate/Transforms.cpp<br>
    cfe/trunk/lib/AST/ASTContext.cpp<br>
    cfe/trunk/lib/AST/Type.cpp<br>
    cfe/trunk/lib/AST/TypeLoc.cpp<br>
    cfe/trunk/lib/AST/TypePrinter.cpp<br>
    cfe/trunk/lib/Sema/SemaDecl.cpp<br>
    cfe/trunk/lib/Sema/SemaExpr.cpp<br>
    cfe/trunk/lib/Sema/SemaInit.cpp<br>
    cfe/trunk/lib/Sema/SemaObjCProperty.cpp<br>
    cfe/trunk/lib/Sema/SemaType.cpp<br>
    cfe/trunk/lib/Sema/TreeTransform.h<br>
    cfe/trunk/lib/Serialization/ASTReader.cpp<br>
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp<br>
    cfe/trunk/lib/Serialization/ASTWriter.cpp<br>
    cfe/trunk/lib/StaticAnalyzer/Core/CheckerHelpers.cpp<br>
    cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp<br>
<br>
Modified: cfe/trunk/include/clang/AST/ASTContext.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=339638&r1=339637&r2=339638&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=339638&r1=339637&r2=339638&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/ASTContext.h (original)<br>
+++ cfe/trunk/include/clang/AST/ASTContext.h Mon Aug 13 18:55:37 2018<br>
@@ -31,7 +31,6 @@<br>
 #include "clang/AST/TemplateName.h"<br>
 #include "clang/AST/Type.h"<br>
 #include "clang/Basic/AddressSpaces.h"<br>
-#include "clang/Basic/AttrKinds.h"<br>
 #include "clang/Basic/IdentifierTable.h"<br>
 #include "clang/Basic/LLVM.h"<br>
 #include "clang/Basic/LangOptions.h"<br>
@@ -1423,7 +1422,7 @@ public:<br>
<br>
   QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST) const;<br>
<br>
-  QualType getAttributedType(attr::Kind attrKind,<br>
+  QualType getAttributedType(AttributedType::Kind attrKind,<br>
                              QualType modifiedType,<br>
                              QualType equivalentType);<br>
<br>
<br>
Modified: cfe/trunk/include/clang/AST/Attr.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Attr.h?rev=339638&r1=339637&r2=339638&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Attr.h?rev=339638&r1=339637&r2=339638&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/Attr.h (original)<br>
+++ cfe/trunk/include/clang/AST/Attr.h Mon Aug 13 18:55:37 2018<br>
@@ -113,19 +113,6 @@ public:<br>
   void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const;<br>
 };<br>
<br>
-class TypeAttr : public Attr {<br>
-protected:<br>
-  TypeAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,<br>
-           bool IsLateParsed)<br>
-      : Attr(AK, R, SpellingListIndex, IsLateParsed) {}<br>
-<br>
-public:<br>
-  static bool classof(const Attr *A) {<br>
-    return A->getKind() >= attr::FirstTypeAttr &&<br>
-           A->getKind() <= attr::LastTypeAttr;<br>
-  }<br>
-};<br>
-<br>
 class StmtAttr : public Attr {<br>
 protected:<br>
   StmtAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,<br>
<br>
Modified: cfe/trunk/include/clang/AST/Type.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=339638&r1=339637&r2=339638&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=339638&r1=339637&r2=339638&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/Type.h (original)<br>
+++ cfe/trunk/include/clang/AST/Type.h Mon Aug 13 18:55:37 2018<br>
@@ -21,7 +21,6 @@<br>
 #include "clang/AST/NestedNameSpecifier.h"<br>
 #include "clang/AST/TemplateName.h"<br>
 #include "clang/Basic/AddressSpaces.h"<br>
-#include "clang/Basic/AttrKinds.h"<br>
 #include "clang/Basic/Diagnostic.h"<br>
 #include "clang/Basic/ExceptionSpecificationType.h"<br>
 #include "clang/Basic/LLVM.h"<br>
@@ -1871,16 +1870,7 @@ public:<br>
   bool isObjCQualifiedClassType() const;        // Class<foo><br>
   bool isObjCObjectOrInterfaceType() const;<br>
   bool isObjCIdType() const;                    // id<br>
-<br>
-  /// Was this type written with the special inert-in-ARC __unsafe_unretained<br>
-  /// qualifier?<br>
-  ///<br>
-  /// This approximates the answer to the following question: if this<br>
-  /// translation unit were compiled in ARC, would this type be qualified<br>
-  /// with __unsafe_unretained?<br>
-  bool isObjCInertUnsafeUnretainedType() const {<br>
-    return hasAttr(attr::ObjCInertUnsafeUnretained);<br>
-  }<br>
+  bool isObjCInertUnsafeUnretainedType() const;<br>
<br>
   /// Whether the type is Objective-C 'id' or a __kindof type of an<br>
   /// object type, e.g., __kindof NSView * or __kindof id<br>
@@ -2094,10 +2084,6 @@ public:<br>
   /// qualifiers from the outermost type.<br>
   const ArrayType *castAsArrayTypeUnsafe() const;<br>
<br>
-  /// Determine whether this type had the specified attribute applied to it<br>
-  /// (looking through top-level type sugar).<br>
-  bool hasAttr(attr::Kind AK) const;<br>
-<br>
   /// Get the base element type of this type, potentially discarding type<br>
   /// qualifiers.  This should never be used when type qualifiers<br>
   /// are meaningful.<br>
@@ -4207,7 +4193,56 @@ public:<br>
 ///   - the canonical type is VectorType(16, int)<br>
 class AttributedType : public Type, public llvm::FoldingSetNode {<br>
 public:<br>
-  using Kind = attr::Kind;<br>
+  // It is really silly to have yet another attribute-kind enum, but<br>
+  // clang::attr::Kind doesn't currently cover the pure type attrs.<br>
+  enum Kind {<br>
+    // Expression operand.<br>
+    attr_address_space,<br>
+    attr_regparm,<br>
+    attr_vector_size,<br>
+    attr_neon_vector_type,<br>
+    attr_neon_polyvector_type,<br>
+<br>
+    FirstExprOperandKind = attr_address_space,<br>
+    LastExprOperandKind = attr_neon_polyvector_type,<br>
+<br>
+    // Enumerated operand (string or keyword).<br>
+    attr_objc_gc,<br>
+    attr_objc_ownership,<br>
+    attr_pcs,<br>
+    attr_pcs_vfp,<br>
+<br>
+    FirstEnumOperandKind = attr_objc_gc,<br>
+    LastEnumOperandKind = attr_pcs_vfp,<br>
+<br>
+    // No operand.<br>
+    attr_noreturn,<br>
+    attr_nocf_check,<br>
+    attr_cdecl,<br>
+    attr_fastcall,<br>
+    attr_stdcall,<br>
+    attr_thiscall,<br>
+    attr_regcall,<br>
+    attr_pascal,<br>
+    attr_swiftcall,<br>
+    attr_vectorcall,<br>
+    attr_inteloclbicc,<br>
+    attr_ms_abi,<br>
+    attr_sysv_abi,<br>
+    attr_preserve_most,<br>
+    attr_preserve_all,<br>
+    attr_ptr32,<br>
+    attr_ptr64,<br>
+    attr_sptr,<br>
+    attr_uptr,<br>
+    attr_nonnull,<br>
+    attr_ns_returns_retained,<br>
+    attr_nullable,<br>
+    attr_null_unspecified,<br>
+    attr_objc_kindof,<br>
+    attr_objc_inert_unsafe_unretained,<br>
+    attr_lifetimebound,<br>
+  };<br>
<br>
 private:<br>
   friend class ASTContext; // ASTContext creates these<br>
@@ -4215,7 +4250,7 @@ private:<br>
   QualType ModifiedType;<br>
   QualType EquivalentType;<br>
<br>
-  AttributedType(QualType canon, attr::Kind attrKind, QualType modified,<br>
+  AttributedType(QualType canon, Kind attrKind, QualType modified,<br>
                  QualType equivalent)<br>
       : Type(Attributed, canon, equivalent->isDependentType(),<br>
              equivalent->isInstantiationDependentType(),<br>
@@ -4264,13 +4299,13 @@ public:<br>
   static Kind getNullabilityAttrKind(NullabilityKind kind) {<br>
     switch (kind) {<br>
     case NullabilityKind::NonNull:<br>
-      return attr::TypeNonNull;<br>
+      return attr_nonnull;<br>
<br>
     case NullabilityKind::Nullable:<br>
-      return attr::TypeNullable;<br>
+      return attr_nullable;<br>
<br>
     case NullabilityKind::Unspecified:<br>
-      return attr::TypeNullUnspecified;<br>
+      return attr_null_unspecified;<br>
     }<br>
     llvm_unreachable("Unknown nullability kind.");<br>
   }<br>
<br>
Modified: cfe/trunk/include/clang/AST/TypeLoc.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeLoc.h?rev=339638&r1=339637&r2=339638&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeLoc.h?rev=339638&r1=339637&r2=339638&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/TypeLoc.h (original)<br>
+++ cfe/trunk/include/clang/AST/TypeLoc.h Mon Aug 13 18:55:37 2018<br>
@@ -15,7 +15,6 @@<br>
 #ifndef LLVM_CLANG_AST_TYPELOC_H<br>
 #define LLVM_CLANG_AST_TYPELOC_H<br>
<br>
-#include "clang/AST/Attr.h"<br>
 #include "clang/AST/Decl.h"<br>
 #include "clang/AST/NestedNameSpecifier.h"<br>
 #include "clang/AST/TemplateBase.h"<br>
@@ -850,7 +849,16 @@ class SubstTemplateTypeParmPackTypeLoc :<br>
 };<br>
<br>
 struct AttributedLocInfo {<br>
-  const Attr *TypeAttr;<br>
+  union {<br>
+    Expr *ExprOperand;<br>
+<br>
+    /// A raw SourceLocation.<br>
+    unsigned EnumOperandLoc;<br>
+  };<br>
+<br>
+  SourceRange OperandParens;<br>
+<br>
+  SourceLocation AttrLoc;<br>
 };<br>
<br>
 /// Type source information for an attributed type.<br>
@@ -859,10 +867,24 @@ class AttributedTypeLoc : public Concret<br>
                                                  AttributedType,<br>
                                                  AttributedLocInfo> {<br>
 public:<br>
-  attr::Kind getAttrKind() const {<br>
+  AttributedType::Kind getAttrKind() const {<br>
     return getTypePtr()->getAttrKind();<br>
   }<br>
<br>
+  bool hasAttrExprOperand() const {<br>
+    return (getAttrKind() >= AttributedType::FirstExprOperandKind &&<br>
+            getAttrKind() <= AttributedType::LastExprOperandKind);<br>
+  }<br>
+<br>
+  bool hasAttrEnumOperand() const {<br>
+    return (getAttrKind() >= AttributedType::FirstEnumOperandKind &&<br>
+            getAttrKind() <= AttributedType::LastEnumOperandKind);<br>
+  }<br>
+<br>
+  bool hasAttrOperand() const {<br>
+    return hasAttrExprOperand() || hasAttrEnumOperand();<br>
+  }<br>
+<br>
   bool isQualifier() const {<br>
     return getTypePtr()->isQualifier();<br>
   }<br>
@@ -875,16 +897,51 @@ public:<br>
     return getInnerTypeLoc();<br>
   }<br>
<br>
-  /// The type attribute.<br>
-  const Attr *getAttr() const {<br>
-    return getLocalData()->TypeAttr;<br>
-  }<br>
-  void setAttr(const Attr *A) {<br>
-    getLocalData()->TypeAttr = A;<br>
-  }<br>
-<br>
-  template<typename T> const T *getAttrAs() {<br>
-    return dyn_cast_or_null<T>(getAttr());<br>
+  /// The location of the attribute name, i.e.<br>
+  ///    __attribute__((regparm(1000)))<br>
+  ///                   ^~~~~~~<br>
+  SourceLocation getAttrNameLoc() const {<br>
+    return getLocalData()->AttrLoc;<br>
+  }<br>
+  void setAttrNameLoc(SourceLocation loc) {<br>
+    getLocalData()->AttrLoc = loc;<br>
+  }<br>
+<br>
+  /// The attribute's expression operand, if it has one.<br>
+  ///    void *cur_thread __attribute__((address_space(21)))<br>
+  ///                                                  ^~<br>
+  Expr *getAttrExprOperand() const {<br>
+    assert(hasAttrExprOperand());<br>
+    return getLocalData()->ExprOperand;<br>
+  }<br>
+  void setAttrExprOperand(Expr *e) {<br>
+    assert(hasAttrExprOperand());<br>
+    getLocalData()->ExprOperand = e;<br>
+  }<br>
+<br>
+  /// The location of the attribute's enumerated operand, if it has one.<br>
+  ///    void * __attribute__((objc_gc(weak)))<br>
+  ///                                  ^~~~<br>
+  SourceLocation getAttrEnumOperandLoc() const {<br>
+    assert(hasAttrEnumOperand());<br>
+    return SourceLocation::getFromRawEncoding(getLocalData()->EnumOperandLoc);<br>
+  }<br>
+  void setAttrEnumOperandLoc(SourceLocation loc) {<br>
+    assert(hasAttrEnumOperand());<br>
+    getLocalData()->EnumOperandLoc = loc.getRawEncoding();<br>
+  }<br>
+<br>
+  /// The location of the parentheses around the operand, if there is<br>
+  /// an operand.<br>
+  ///    void * __attribute__((objc_gc(weak)))<br>
+  ///                                 ^    ^<br>
+  SourceRange getAttrOperandParensRange() const {<br>
+    assert(hasAttrOperand());<br>
+    return getLocalData()->OperandParens;<br>
+  }<br>
+  void setAttrOperandParensRange(SourceRange range) {<br>
+    assert(hasAttrOperand());<br>
+    getLocalData()->OperandParens = range;<br>
   }<br>
<br>
   SourceRange getLocalSourceRange() const {<br>
@@ -897,11 +954,21 @@ public:<br>
     //    ^~        ~~<br>
     // That enclosure doesn't necessarily belong to a single attribute<br>
     // anyway.<br>
-    return getAttr() ? getAttr()->getRange() : SourceRange();<br>
+    SourceRange range(getAttrNameLoc());<br>
+    if (hasAttrOperand())<br>
+      range.setEnd(getAttrOperandParensRange().getEnd());<br>
+    return range;<br>
   }<br>
<br>
   void initializeLocal(ASTContext &Context, SourceLocation loc) {<br>
-    setAttr(nullptr);<br>
+    setAttrNameLoc(loc);<br>
+    if (hasAttrExprOperand()) {<br>
+      setAttrOperandParensRange(SourceRange(loc));<br>
+      setAttrExprOperand(nullptr);<br>
+    } else if (hasAttrEnumOperand()) {<br>
+      setAttrOperandParensRange(SourceRange(loc));<br>
+      setAttrEnumOperandLoc(loc);<br>
+    }<br>
   }<br>
<br>
   QualType getInnerType() const {<br>
<br>
Modified: cfe/trunk/include/clang/Basic/Attr.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=339638&r1=339637&r2=339638&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=339638&r1=339637&r2=339638&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Basic/Attr.td (original)<br>
+++ cfe/trunk/include/clang/Basic/Attr.td Mon Aug 13 18:55:37 2018<br>
@@ -494,7 +494,10 @@ class Attr {<br>
 }<br>
<br>
 /// A type attribute is not processed on a declaration or a statement.<br>
-class TypeAttr : Attr;<br>
+class TypeAttr : Attr {<br>
+  // By default, type attributes do not get an AST node.<br>
+  let ASTNode = 0;<br>
+}<br>
<br>
 /// A stmt attribute is not processed on a declaration or a type.<br>
 class StmtAttr : Attr;<br>
@@ -564,8 +567,6 @@ def AddressSpace : TypeAttr {<br>
   let Spellings = [Clang<"address_space">];<br>
   let Args = [IntArgument<"AddressSpace">];<br>
   let Documentation = [Undocumented];<br>
-  // Represented as a qualifier or DependentAddressSpaceType instead.<br>
-  let ASTNode = 0;<br>
 }<br>
<br>
 def Alias : Attr {<br>
@@ -1223,7 +1224,7 @@ def LayoutVersion : InheritableAttr, Tar<br>
   let Documentation = [LayoutVersionDocs];<br>
 }<br>
<br>
-def LifetimeBound : DeclOrTypeAttr {<br>
+def LifetimeBound : InheritableAttr {<br>
   let Spellings = [Clang<"lifetimebound", 0>];<br>
   let Subjects = SubjectList<[ParmVar, ImplicitObjectParameter], ErrorDiag>;<br>
   let Documentation = [LifetimeBoundDocs];<br>
@@ -1326,16 +1327,12 @@ def NeonPolyVectorType : TypeAttr {<br>
   let Spellings = [Clang<"neon_polyvector_type">];<br>
   let Args = [IntArgument<"NumElements">];<br>
   let Documentation = [Undocumented];<br>
-  // Represented as VectorType instead.<br>
-  let ASTNode = 0;<br>
 }<br>
<br>
 def NeonVectorType : TypeAttr {<br>
   let Spellings = [Clang<"neon_vector_type">];<br>
   let Args = [IntArgument<"NumElements">];<br>
   let Documentation = [Undocumented];<br>
-  // Represented as VectorType instead.<br>
-  let ASTNode = 0;<br>
 }<br>
<br>
 def ReturnsTwice : InheritableAttr {<br>
@@ -1510,14 +1507,6 @@ def TypeNullUnspecified : TypeAttr {<br>
   let Documentation = [TypeNullUnspecifiedDocs];<br>
 }<br>
<br>
-// This is a marker used to indicate that an __unsafe_unretained qualifier was<br>
-// ignored because ARC is not enabled. The usual representation for this<br>
-// qualifier is as an ObjCOwnership attribute with Kind == "none".<br>
-def ObjCInertUnsafeUnretained : TypeAttr {<br>
-  let Spellings = [Keyword<"__unsafe_unretained">];<br>
-  let Documentation = [Undocumented];<br>
-}<br>
-<br>
 def ObjCKindOf : TypeAttr {<br>
   let Spellings = [Keyword<"__kindof">];<br>
   let Documentation = [Undocumented];<br>
@@ -1605,7 +1594,7 @@ def ObjCBridgeRelated : InheritableAttr<br>
   let Documentation = [Undocumented];<br>
 }<br>
<br>
-def NSReturnsRetained : DeclOrTypeAttr {<br>
+def NSReturnsRetained : InheritableAttr {<br>
   let Spellings = [Clang<"ns_returns_retained">];<br>
 //  let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;<br>
   let Documentation = [Undocumented];<br>
@@ -1790,8 +1779,6 @@ def Regparm : TypeAttr {<br>
   let Spellings = [GCC<"regparm">];<br>
   let Args = [UnsignedArgument<"NumParams">];<br>
   let Documentation = [RegparmDocs];<br>
-  // Represented as part of the enclosing function type.<br>
-  let ASTNode = 0;<br>
 }<br>
<br>
 def ReqdWorkGroupSize : InheritableAttr {<br>
@@ -2080,9 +2067,10 @@ def ObjCGC : TypeAttr {<br>
   let Documentation = [Undocumented];<br>
 }<br>
<br>
-def ObjCOwnership : DeclOrTypeAttr {<br>
+def ObjCOwnership : InheritableAttr {<br>
   let Spellings = [Clang<"objc_ownership">];<br>
   let Args = [IdentifierArgument<"Kind">];<br>
+  let ASTNode = 0;<br>
   let Documentation = [Undocumented];<br>
 }<br>
<br>
@@ -2120,8 +2108,6 @@ def VectorSize : TypeAttr {<br>
   let Spellings = [GCC<"vector_size">];<br>
   let Args = [ExprArgument<"NumBytes">];<br>
   let Documentation = [Undocumented];<br>
-  // Represented as VectorType instead.<br>
-  let ASTNode = 0;<br>
 }<br>
<br>
 def VecTypeHint : InheritableAttr {<br>
@@ -2216,7 +2202,7 @@ def AnyX86NoCallerSavedRegisters : Inher<br>
   let Documentation = [AnyX86NoCallerSavedRegistersDocs];<br>
 }<br>
<br>
-def AnyX86NoCfCheck : DeclOrTypeAttr, TargetSpecificAttr<TargetAnyX86>{<br>
+def AnyX86NoCfCheck : InheritableAttr, TargetSpecificAttr<TargetAnyX86>{<br>
   let Spellings = [GCC<"nocf_check">];<br>
   let Subjects = SubjectList<[FunctionLike]>;<br>
   let Documentation = [AnyX86NoCfCheckDocs];<br>
<br>
Modified: cfe/trunk/include/clang/Sema/Sema.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=339638&r1=339637&r2=339638&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=339638&r1=339637&r2=339638&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Sema/Sema.h (original)<br>
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Aug 13 18:55:37 2018<br>
@@ -1435,6 +1435,8 @@ public:<br>
<br>
   TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S);<br>
   TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType FromTy);<br>
+  TypeSourceInfo *GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,<br>
+                                               TypeSourceInfo *ReturnTypeInfo);<br>
<br>
   /// Package the given type and TSI into a ParsedType.<br>
   ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo);<br>
@@ -3376,6 +3378,30 @@ public:<br>
   /// Valid types should not have multiple attributes with different CCs.<br>
   const AttributedType *getCallingConvAttributedType(QualType T) const;<br>
<br>
+  /// Check whether a nullability type specifier can be added to the given<br>
+  /// type.<br>
+  ///<br>
+  /// \param type The type to which the nullability specifier will be<br>
+  /// added. On success, this type will be updated appropriately.<br>
+  ///<br>
+  /// \param nullability The nullability specifier to add.<br>
+  ///<br>
+  /// \param nullabilityLoc The location of the nullability specifier.<br>
+  ///<br>
+  /// \param isContextSensitive Whether this nullability specifier was<br>
+  /// written as a context-sensitive keyword (in an Objective-C<br>
+  /// method) or an Objective-C property attribute, rather than as an<br>
+  /// underscored type specifier.<br>
+  ///<br>
+  /// \param allowArrayTypes Whether to accept nullability specifiers on an<br>
+  /// array type (e.g., because it will decay to a pointer).<br>
+  ///<br>
+  /// \returns true if nullability cannot be applied, false otherwise.<br>
+  bool checkNullabilityTypeSpecifier(QualType &type, NullabilityKind nullability,<br>
+                                     SourceLocation nullabilityLoc,<br>
+                                     bool isContextSensitive,<br>
+                                     bool allowArrayTypes);<br>
+<br>
   /// Stmt attributes - this routine is the top level dispatcher.<br>
   StmtResult ProcessStmtAttributes(Stmt *Stmt,<br>
                                    const ParsedAttributesView &Attrs,<br>
@@ -8045,6 +8071,10 @@ public:<br>
                                SourceLocation ProtocolRAngleLoc,<br>
                                bool FailOnError = false);<br>
<br>
+  /// Check the application of the Objective-C '__kindof' qualifier to<br>
+  /// the given type.<br>
+  bool checkObjCKindOfType(QualType &type, SourceLocation loc);<br>
+<br>
   /// Ensure attributes are consistent with type.<br>
   /// \param [in, out] Attributes The attributes to check; they will<br>
   /// be modified to be consistent with \p PropertyTy.<br>
<br>
Modified: cfe/trunk/include/clang/Serialization/ASTReader.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=339638&r1=339637&r2=339638&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=339638&r1=339637&r2=339638&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Serialization/ASTReader.h (original)<br>
+++ cfe/trunk/include/clang/Serialization/ASTReader.h Mon Aug 13 18:55:37 2018<br>
@@ -2245,9 +2245,6 @@ public:<br>
   CXXTemporary *ReadCXXTemporary(ModuleFile &F, const RecordData &Record,<br>
                                  unsigned &Idx);<br>
<br>
-  /// Reads one attribute from the current stream position.<br>
-  Attr *ReadAttr(ModuleFile &M, const RecordData &Record, unsigned &Idx);<br>
-<br>
   /// Reads attributes from the current stream position.<br>
   void ReadAttributes(ASTRecordReader &Record, AttrVec &Attrs);<br>
<br>
@@ -2633,11 +2630,6 @@ public:<br>
     return ASTReader::ReadVersionTuple(Record, Idx);<br>
   }<br>
<br>
-  /// Reads one attribute from the current stream position, advancing Idx.<br>
-  Attr *readAttr() {<br>
-    return Reader->ReadAttr(*F, Record, Idx);<br>
-  }<br>
-<br>
   /// Reads attributes from the current stream position, advancing Idx.<br>
   void readAttributes(AttrVec &Attrs) {<br>
     return Reader->ReadAttributes(*this, Attrs);<br>
<br>
Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=339638&r1=339637&r2=339638&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=339638&r1=339637&r2=339638&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Serialization/ASTWriter.h (original)<br>
+++ cfe/trunk/include/clang/Serialization/ASTWriter.h Mon Aug 13 18:55:37 2018<br>
@@ -955,9 +955,6 @@ public:<br>
     return Writer->AddVersionTuple(Version, *Record);<br>
   }<br>
<br>
-  // Emit an attribute.<br>
-  void AddAttr(const Attr *A);<br>
-<br>
   /// Emit a list of attributes.<br>
   void AddAttributes(ArrayRef<const Attr*> Attrs);<br>
 };<br>
<br>
Modified: cfe/trunk/lib/ARCMigrate/TransGCAttrs.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/TransGCAttrs.cpp?rev=339638&r1=339637&r2=339638&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/TransGCAttrs.cpp?rev=339638&r1=339637&r2=339638&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/ARCMigrate/TransGCAttrs.cpp (original)<br>
+++ cfe/trunk/lib/ARCMigrate/TransGCAttrs.cpp Mon Aug 13 18:55:37 2018<br>
@@ -81,11 +81,10 @@ public:<br>
   }<br>
<br>
   bool handleAttr(AttributedTypeLoc TL, Decl *D = nullptr) {<br>
-    auto *OwnershipAttr = TL.getAttrAs<ObjCOwnershipAttr>();<br>
-    if (!OwnershipAttr)<br>
+    if (TL.getAttrKind() != AttributedType::attr_objc_ownership)<br>
       return false;<br>
<br>
-    SourceLocation Loc = OwnershipAttr->getLocation();<br>
+    SourceLocation Loc = TL.getAttrNameLoc();<br>
     unsigned RawLoc = Loc.getRawEncoding();<br>
     if (MigrateCtx.AttrSet.count(RawLoc))<br>
       return true;<br>
@@ -94,7 +93,13 @@ public:<br>
     SourceManager &SM = Ctx.getSourceManager();<br>
     if (Loc.isMacroID())<br>
       Loc = SM.getImmediateExpansionRange(Loc).getBegin();<br>
-    StringRef Spell = OwnershipAttr->getKind()->getName();<br>
+    SmallString<32> Buf;<br>
+    bool Invalid = false;<br>
+    StringRef Spell = Lexer::getSpelling(<br>
+                                  SM.getSpellingLoc(TL.getAttrEnumOperandLoc()),<br>
+                                  Buf, SM, Ctx.getLangOpts(), &Invalid);<br>
+    if (Invalid)<br>
+      return false;<br>
     MigrationContext::GCAttrOccurrence::AttrKind Kind;<br>
     if (Spell == "strong")<br>
       Kind = MigrationContext::GCAttrOccurrence::Strong;<br>
@@ -279,7 +284,7 @@ static void checkAllAtProps(MigrationCon<br>
   }<br>
<br>
   for (unsigned i = 0, e = ATLs.size(); i != e; ++i) {<br>
-    SourceLocation Loc = ATLs[i].first.getAttr()->getLocation();<br>
+    SourceLocation Loc = ATLs[i].first.getAttrNameLoc();<br>
     if (Loc.isMacroID())<br>
       Loc = MigrateCtx.Pass.Ctx.getSourceManager()<br>
                 .getImmediateExpansionRange(Loc)<br>
<br>
Modified: cfe/trunk/lib/ARCMigrate/Transforms.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/Transforms.cpp?rev=339638&r1=339637&r2=339638&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/Transforms.cpp?rev=339638&r1=339637&r2=339638&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/ARCMigrate/Transforms.cpp (original)<br>
+++ cfe/trunk/lib/ARCMigrate/Transforms.cpp Mon Aug 13 18:55:37 2018<br>
@@ -359,7 +359,7 @@ MigrationContext::~MigrationContext() {<br>
 bool MigrationContext::isGCOwnedNonObjC(QualType T) {<br>
   while (!T.isNull()) {<br>
     if (const AttributedType *AttrT = T->getAs<AttributedType>()) {<br>
-      if (AttrT->getAttrKind() == attr::ObjCOwnership)<br>
+      if (AttrT->getAttrKind() == AttributedType::attr_objc_ownership)<br>
         return !AttrT->getModifiedType()->isObjCRetainableType();<br>
     }<br>
<br>
<br>
Modified: cfe/trunk/lib/AST/ASTContext.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=339638&r1=339637&r2=339638&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=339638&r1=339637&r2=339638&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/ASTContext.cpp (original)<br>
+++ cfe/trunk/lib/AST/ASTContext.cpp Mon Aug 13 18:55:37 2018<br>
@@ -3876,7 +3876,7 @@ QualType ASTContext::getEnumType(const E<br>
   return QualType(newType, 0);<br>
 }<br>
<br>
-QualType ASTContext::getAttributedType(attr::Kind attrKind,<br>
+QualType ASTContext::getAttributedType(AttributedType::Kind attrKind,<br>
                                        QualType modifiedType,<br>
                                        QualType equivalentType) {<br>
   llvm::FoldingSetNodeID id;<br>
<br>
Modified: cfe/trunk/lib/AST/Type.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=339638&r1=339637&r2=339638&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=339638&r1=339637&r2=339638&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/Type.cpp (original)<br>
+++ cfe/trunk/lib/AST/Type.cpp Mon Aug 13 18:55:37 2018<br>
@@ -592,6 +592,28 @@ bool Type::isObjCClassOrClassKindOfType(<br>
   return OPT->isObjCClassType() || OPT->isObjCQualifiedClassType();<br>
 }<br>
<br>
+/// Was this type written with the special inert-in-MRC __unsafe_unretained<br>
+/// qualifier?<br>
+///<br>
+/// This approximates the answer to the following question: if this<br>
+/// translation unit were compiled in ARC, would this type be qualified<br>
+/// with __unsafe_unretained?<br>
+bool Type::isObjCInertUnsafeUnretainedType() const {<br>
+  const Type *cur = this;<br>
+  while (true) {<br>
+    if (const auto attributed = dyn_cast<AttributedType>(cur)) {<br>
+      if (attributed->getAttrKind() ==<br>
+            AttributedType::attr_objc_inert_unsafe_unretained)<br>
+        return true;<br>
+    }<br>
+<br>
+    // Single-step desugar until we run out of sugar.<br>
+    QualType next = cur->getLocallyUnqualifiedSingleStepDesugaredType();<br>
+    if (next.getTypePtr() == cur) return false;<br>
+    cur = next.getTypePtr();<br>
+  }<br>
+}<br>
+<br>
 ObjCTypeParamType::ObjCTypeParamType(const ObjCTypeParamDecl *D,<br>
                                      QualType can,<br>
                                      ArrayRef<ObjCProtocolDecl *> protocols)<br>
@@ -1619,16 +1641,6 @@ TagDecl *Type::getAsTagDecl() const {<br>
   return nullptr;<br>
 }<br>
<br>
-bool Type::hasAttr(attr::Kind AK) const {<br>
-  const Type *Cur = this;<br>
-  while (const auto *AT = Cur->getAs<AttributedType>()) {<br>
-    if (AT->getAttrKind() == AK)<br>
-      return true;<br>
-    Cur = AT->getEquivalentType().getTypePtr();<br>
-  }<br>
-  return false;<br>
-}<br>
-<br>
 namespace {<br>
<br>
   class GetContainedDeducedTypeVisitor :<br>
@@ -3155,58 +3167,105 @@ bool RecordType::hasConstFields() const<br>
 }<br>
<br>
 bool AttributedType::isQualifier() const {<br>
-  // FIXME: Generate this with TableGen.<br>
   switch (getAttrKind()) {<br>
   // These are type qualifiers in the traditional C sense: they annotate<br>
   // something about a specific value/variable of a type.  (They aren't<br>
   // always part of the canonical type, though.)<br>
-  case attr::ObjCGC:<br>
-  case attr::ObjCOwnership:<br>
-  case attr::ObjCInertUnsafeUnretained:<br>
-  case attr::TypeNonNull:<br>
-  case attr::TypeNullable:<br>
-  case attr::TypeNullUnspecified:<br>
-  case attr::LifetimeBound:<br>
-    return true;<br>
-<br>
-  // All other type attributes aren't qualifiers; they rewrite the modified<br>
-  // type to be a semantically different type.<br>
-  default:<br>
+  case AttributedType::attr_address_space:<br>
+  case AttributedType::attr_objc_gc:<br>
+  case AttributedType::attr_objc_ownership:<br>
+  case AttributedType::attr_objc_inert_unsafe_unretained:<br>
+  case AttributedType::attr_nonnull:<br>
+  case AttributedType::attr_nullable:<br>
+  case AttributedType::attr_null_unspecified:<br>
+  case AttributedType::attr_lifetimebound:<br>
+    return true;<br>
+<br>
+  // These aren't qualifiers; they rewrite the modified type to be a<br>
+  // semantically different type.<br>
+  case AttributedType::attr_regparm:<br>
+  case AttributedType::attr_vector_size:<br>
+  case AttributedType::attr_neon_vector_type:<br>
+  case AttributedType::attr_neon_polyvector_type:<br>
+  case AttributedType::attr_pcs:<br>
+  case AttributedType::attr_pcs_vfp:<br>
+  case AttributedType::attr_noreturn:<br>
+  case AttributedType::attr_cdecl:<br>
+  case AttributedType::attr_fastcall:<br>
+  case AttributedType::attr_stdcall:<br>
+  case AttributedType::attr_thiscall:<br>
+  case AttributedType::attr_regcall:<br>
+  case AttributedType::attr_pascal:<br>
+  case AttributedType::attr_swiftcall:<br>
+  case AttributedType::attr_vectorcall:<br>
+  case AttributedType::attr_inteloclbicc:<br>
+  case AttributedType::attr_preserve_most:<br>
+  case AttributedType::attr_preserve_all:<br>
+  case AttributedType::attr_ms_abi:<br>
+  case AttributedType::attr_sysv_abi:<br>
+  case AttributedType::attr_ptr32:<br>
+  case AttributedType::attr_ptr64:<br>
+  case AttributedType::attr_sptr:<br>
+  case AttributedType::attr_uptr:<br>
+  case AttributedType::attr_objc_kindof:<br>
+  case AttributedType::attr_ns_returns_retained:<br>
+  case AttributedType::attr_nocf_check:<br>
     return false;<br>
   }<br>
+  llvm_unreachable("bad attributed type kind");<br>
 }<br>
<br>
 bool AttributedType::isMSTypeSpec() const {<br>
-  // FIXME: Generate this with TableGen?<br>
   switch (getAttrKind()) {<br>
-  default: return false;<br>
-  case attr::Ptr32:<br>
-  case attr::Ptr64:<br>
-  case attr::SPtr:<br>
-  case attr::UPtr:<br>
+  default:  return false;<br>
+  case attr_ptr32:<br>
+  case attr_ptr64:<br>
+  case attr_sptr:<br>
+  case attr_uptr:<br>
     return true;<br>
   }<br>
   llvm_unreachable("invalid attr kind");<br>
 }<br>
<br>
 bool AttributedType::isCallingConv() const {<br>
-  // FIXME: Generate this with TableGen.<br>
   switch (getAttrKind()) {<br>
-  default: return false;<br>
-  case attr::Pcs:<br>
-  case attr::CDecl:<br>
-  case attr::FastCall:<br>
-  case attr::StdCall:<br>
-  case attr::ThisCall:<br>
-  case attr::RegCall:<br>
-  case attr::SwiftCall:<br>
-  case attr::VectorCall:<br>
-  case attr::Pascal:<br>
-  case attr::MSABI:<br>
-  case attr::SysVABI:<br>
-  case attr::IntelOclBicc:<br>
-  case attr::PreserveMost:<br>
-  case attr::PreserveAll:<br>
+  case attr_ptr32:<br>
+  case attr_ptr64:<br>
+  case attr_sptr:<br>
+  case attr_uptr:<br>
+  case attr_address_space:<br>
+  case attr_regparm:<br>
+  case attr_vector_size:<br>
+  case attr_neon_vector_type:<br>
+  case attr_neon_polyvector_type:<br>
+  case attr_objc_gc:<br>
+  case attr_objc_ownership:<br>
+  case attr_objc_inert_unsafe_unretained:<br>
+  case attr_noreturn:<br>
+  case attr_nonnull:<br>
+  case attr_ns_returns_retained:<br>
+  case attr_nullable:<br>
+  case attr_null_unspecified:<br>
+  case attr_objc_kindof:<br>
+  case attr_nocf_check:<br>
+  case attr_lifetimebound:<br>
+    return false;<br>
+<br>
+  case attr_pcs:<br>
+  case attr_pcs_vfp:<br>
+  case attr_cdecl:<br>
+  case attr_fastcall:<br>
+  case attr_stdcall:<br>
+  case attr_thiscall:<br>
+  case attr_regcall:<br>
+  case attr_swiftcall:<br>
+  case attr_vectorcall:<br>
+  case attr_pascal:<br>
+  case attr_ms_abi:<br>
+  case attr_sysv_abi:<br>
+  case attr_inteloclbicc:<br>
+  case attr_preserve_most:<br>
+  case attr_preserve_all:<br>
     return true;<br>
   }<br>
   llvm_unreachable("invalid attr kind");<br>
@@ -3649,18 +3708,23 @@ LinkageInfo Type::getLinkageAndVisibilit<br>
   return LinkageComputer{}.getTypeLinkageAndVisibility(this);<br>
 }<br>
<br>
-Optional<NullabilityKind><br>
-Type::getNullability(const ASTContext &Context) const {<br>
-  QualType Type(this, 0);<br>
-  while (const auto *AT = Type->getAs<AttributedType>()) {<br>
+Optional<NullabilityKind> Type::getNullability(const ASTContext &context) const {<br>
+  QualType type(this, 0);<br>
+  do {<br>
     // Check whether this is an attributed type with nullability<br>
     // information.<br>
-    if (auto Nullability = AT->getImmediateNullability())<br>
-      return Nullability;<br>
+    if (auto attributed = dyn_cast<AttributedType>(type.getTypePtr())) {<br>
+      if (auto nullability = attributed->getImmediateNullability())<br>
+        return nullability;<br>
+    }<br>
<br>
-    Type = AT->getEquivalentType();<br>
-  }<br>
-  return None;<br>
+    // Desugar the type. If desugaring does nothing, we're done.<br>
+    QualType desugared = type.getSingleStepDesugaredType(context);<br>
+    if (desugared.getTypePtr() == type.getTypePtr())<br>
+      return None;<br>
+<br>
+    type = desugared;<br>
+  } while (true);<br>
 }<br>
<br>
 bool Type::canHaveNullability(bool ResultIfUnknown) const {<br>
@@ -3773,13 +3837,12 @@ bool Type::canHaveNullability(bool Resul<br>
   llvm_unreachable("bad type kind!");<br>
 }<br>
<br>
-llvm::Optional<NullabilityKind><br>
-AttributedType::getImmediateNullability() const {<br>
-  if (getAttrKind() == attr::TypeNonNull)<br>
+llvm::Optional<NullabilityKind> AttributedType::getImmediateNullability() const {<br>
+  if (getAttrKind() == AttributedType::attr_nonnull)<br>
     return NullabilityKind::NonNull;<br>
-  if (getAttrKind() == attr::TypeNullable)<br>
+  if (getAttrKind() == AttributedType::attr_nullable)<br>
     return NullabilityKind::Nullable;<br>
-  if (getAttrKind() == attr::TypeNullUnspecified)<br>
+  if (getAttrKind() == AttributedType::attr_null_unspecified)<br>
     return NullabilityKind::Unspecified;<br>
   return None;<br>
 }<br>
<br>
Modified: cfe/trunk/lib/AST/TypeLoc.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypeLoc.cpp?rev=339638&r1=339637&r2=339638&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypeLoc.cpp?rev=339638&r1=339637&r2=339638&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/TypeLoc.cpp (original)<br>
+++ cfe/trunk/lib/AST/TypeLoc.cpp Mon Aug 13 18:55:37 2018<br>
@@ -404,11 +404,11 @@ TypeLoc TypeLoc::IgnoreParensImpl(TypeLo<br>
 }<br>
<br>
 SourceLocation TypeLoc::findNullabilityLoc() const {<br>
-  if (auto ATL = getAs<AttributedTypeLoc>()) {<br>
-    const Attr *A = ATL.getAttr();<br>
-    if (A && (isa<TypeNullableAttr>(A) || isa<TypeNonNullAttr>(A) ||<br>
-              isa<TypeNullUnspecifiedAttr>(A)))<br>
-      return A->getLocation();<br>
+  if (auto attributedLoc = getAs<AttributedTypeLoc>()) {<br>
+    if (attributedLoc.getAttrKind() == AttributedType::attr_nullable ||<br>
+        attributedLoc.getAttrKind() == AttributedType::attr_nonnull ||<br>
+        attributedLoc.getAttrKind() == AttributedType::attr_null_unspecified)<br>
+      return attributedLoc.getAttrNameLoc();<br>
   }<br>
<br>
   return {};<br>
<br>
Modified: cfe/trunk/lib/AST/TypePrinter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypePrinter.cpp?rev=339638&r1=339637&r2=339638&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypePrinter.cpp?rev=339638&r1=339637&r2=339638&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/TypePrinter.cpp (original)<br>
+++ cfe/trunk/lib/AST/TypePrinter.cpp Mon Aug 13 18:55:37 2018<br>
@@ -1354,14 +1354,12 @@ void TypePrinter::printPackExpansionAfte<br>
<br>
 void TypePrinter::printAttributedBefore(const AttributedType *T,<br>
                                         raw_ostream &OS) {<br>
-  // FIXME: Generate this with TableGen.<br>
-<br>
   // Prefer the macro forms of the GC and ownership qualifiers.<br>
-  if (T->getAttrKind() == attr::ObjCGC ||<br>
-      T->getAttrKind() == attr::ObjCOwnership)<br>
+  if (T->getAttrKind() == AttributedType::attr_objc_gc ||<br>
+      T->getAttrKind() == AttributedType::attr_objc_ownership)<br>
     return printBefore(T->getEquivalentType(), OS);<br>
<br>
-  if (T->getAttrKind() == attr::ObjCKindOf)<br>
+  if (T->getAttrKind() == AttributedType::attr_objc_kindof)<br>
     OS << "__kindof ";<br>
<br>
   printBefore(T->getModifiedType(), OS);<br>
@@ -1369,21 +1367,23 @@ void TypePrinter::printAttributedBefore(<br>
   if (T->isMSTypeSpec()) {<br>
     switch (T->getAttrKind()) {<br>
     default: return;<br>
-    case attr::Ptr32: OS << " __ptr32"; break;<br>
-    case attr::Ptr64: OS << " __ptr64"; break;<br>
-    case attr::SPtr: OS << " __sptr"; break;<br>
-    case attr::UPtr: OS << " __uptr"; break;<br>
+    case AttributedType::attr_ptr32: OS << " __ptr32"; break;<br>
+    case AttributedType::attr_ptr64: OS << " __ptr64"; break;<br>
+    case AttributedType::attr_sptr: OS << " __sptr"; break;<br>
+    case AttributedType::attr_uptr: OS << " __uptr"; break;<br>
     }<br>
     spaceBeforePlaceHolder(OS);<br>
   }<br>
<br>
   // Print nullability type specifiers.<br>
-  if (T->getImmediateNullability()) {<br>
-    if (T->getAttrKind() == attr::TypeNonNull)<br>
+  if (T->getAttrKind() == AttributedType::attr_nonnull ||<br>
+      T->getAttrKind() == AttributedType::attr_nullable ||<br>
+      T->getAttrKind() == AttributedType::attr_null_unspecified) {<br>
+    if (T->getAttrKind() == AttributedType::attr_nonnull)<br>
       OS << " _Nonnull";<br>
-    else if (T->getAttrKind() == attr::TypeNullable)<br>
+    else if (T->getAttrKind() == AttributedType::attr_nullable)<br>
       OS << " _Nullable";<br>
-    else if (T->getAttrKind() == attr::TypeNullUnspecified)<br>
+    else if (T->getAttrKind() == AttributedType::attr_null_unspecified)<br>
       OS << " _Null_unspecified";<br>
     else<br>
       llvm_unreachable("unhandled nullability");<br>
@@ -1393,11 +1393,9 @@ void TypePrinter::printAttributedBefore(<br>
<br>
 void TypePrinter::printAttributedAfter(const AttributedType *T,<br>
                                        raw_ostream &OS) {<br>
-  // FIXME: Generate this with TableGen.<br>
-<br>
   // Prefer the macro forms of the GC and ownership qualifiers.<br>
-  if (T->getAttrKind() == attr::ObjCGC ||<br>
-      T->getAttrKind() == attr::ObjCOwnership)<br>
+  if (T->getAttrKind() == AttributedType::attr_objc_gc ||<br>
+      T->getAttrKind() == AttributedType::attr_objc_ownership)<br>
     return printAfter(T->getEquivalentType(), OS);<br>
<br>
   // If this is a calling convention attribute, don't print the implicit CC from<br>
@@ -1408,74 +1406,107 @@ void TypePrinter::printAttributedAfter(c<br>
<br>
   // Some attributes are printed as qualifiers before the type, so we have<br>
   // nothing left to do.<br>
-  if (T->getAttrKind() == attr::ObjCKindOf ||<br>
-      T->isMSTypeSpec() || T->getImmediateNullability())<br>
+  if (T->getAttrKind() == AttributedType::attr_objc_kindof ||<br>
+      T->isMSTypeSpec() ||<br>
+      T->getAttrKind() == AttributedType::attr_nonnull ||<br>
+      T->getAttrKind() == AttributedType::attr_nullable ||<br>
+      T->getAttrKind() == AttributedType::attr_null_unspecified)<br>
     return;<br>
<br>
   // Don't print the inert __unsafe_unretained attribute at all.<br>
-  if (T->getAttrKind() == attr::ObjCInertUnsafeUnretained)<br>
+  if (T->getAttrKind() == AttributedType::attr_objc_inert_unsafe_unretained)<br>
     return;<br>
<br>
   // Don't print ns_returns_retained unless it had an effect.<br>
-  if (T->getAttrKind() == attr::NSReturnsRetained &&<br>
+  if (T->getAttrKind() == AttributedType::attr_ns_returns_retained &&<br>
       !T->getEquivalentType()->castAs<FunctionType>()<br>
                              ->getExtInfo().getProducesResult())<br>
     return;<br>
<br>
-  if (T->getAttrKind() == attr::LifetimeBound) {<br>
+  if (T->getAttrKind() == AttributedType::attr_lifetimebound) {<br>
     OS << " [[clang::lifetimebound]]";<br>
     return;<br>
   }<br>
<br>
   OS << " __attribute__((";<br>
   switch (T->getAttrKind()) {<br>
-#define TYPE_ATTR(NAME)<br>
-#define DECL_OR_TYPE_ATTR(NAME)<br>
-#define ATTR(NAME) case attr::NAME:<br>
-#include "clang/Basic/AttrList.inc"<br>
-    llvm_unreachable("non-type attribute attached to type");<br>
-<br>
-  case attr::OpenCLPrivateAddressSpace:<br>
-  case attr::OpenCLGlobalAddressSpace:<br>
-  case attr::OpenCLLocalAddressSpace:<br>
-  case attr::OpenCLConstantAddressSpace:<br>
-  case attr::OpenCLGenericAddressSpace:<br>
-    // FIXME: Update printAttributedBefore to print these once we generate<br>
-    // AttributedType nodes for them.<br>
-    break;<br>
-<br>
-  case attr::LifetimeBound:<br>
-  case attr::TypeNonNull:<br>
-  case attr::TypeNullable:<br>
-  case attr::TypeNullUnspecified:<br>
-  case attr::ObjCGC:<br>
-  case attr::ObjCInertUnsafeUnretained:<br>
-  case attr::ObjCKindOf:<br>
-  case attr::ObjCOwnership:<br>
-  case attr::Ptr32:<br>
-  case attr::Ptr64:<br>
-  case attr::SPtr:<br>
-  case attr::UPtr:<br>
+  case AttributedType::attr_lifetimebound:<br>
+  case AttributedType::attr_nonnull:<br>
+  case AttributedType::attr_nullable:<br>
+  case AttributedType::attr_null_unspecified:<br>
+  case AttributedType::attr_objc_gc:<br>
+  case AttributedType::attr_objc_inert_unsafe_unretained:<br>
+  case AttributedType::attr_objc_kindof:<br>
+  case AttributedType::attr_objc_ownership:<br>
+  case AttributedType::attr_ptr32:<br>
+  case AttributedType::attr_ptr64:<br>
+  case AttributedType::attr_sptr:<br>
+  case AttributedType::attr_uptr:<br>
     llvm_unreachable("This attribute should have been handled already");<br>
<br>
-  case attr::NSReturnsRetained:<br>
+  case AttributedType::attr_address_space:<br>
+    OS << "address_space(";<br>
+    // FIXME: printing the raw LangAS value is wrong. This should probably<br>
+    // use the same code as Qualifiers::print()<br>
+    OS << (unsigned)T->getEquivalentType().getAddressSpace();<br>
+    OS << ')';<br>
+    break;<br>
+<br>
+  case AttributedType::attr_vector_size:<br>
+    OS << "__vector_size__(";<br>
+    if (const auto *vector = T->getEquivalentType()->getAs<VectorType>()) {<br>
+      OS << vector->getNumElements();<br>
+      OS << " * sizeof(";<br>
+      print(vector->getElementType(), OS, StringRef());<br>
+      OS << ')';<br>
+    }<br>
+    OS << ')';<br>
+    break;<br>
+<br>
+  case AttributedType::attr_neon_vector_type:<br>
+  case AttributedType::attr_neon_polyvector_type: {<br>
+    if (T->getAttrKind() == AttributedType::attr_neon_vector_type)<br>
+      OS << "neon_vector_type(";<br>
+    else<br>
+      OS << "neon_polyvector_type(";<br>
+    const auto *vector = T->getEquivalentType()->getAs<VectorType>();<br>
+    OS << vector->getNumElements();<br>
+    OS << ')';<br>
+    break;<br>
+  }<br>
+<br>
+  case AttributedType::attr_regparm: {<br>
+    // FIXME: When Sema learns to form this AttributedType, avoid printing the<br>
+    // attribute again in printFunctionProtoAfter.<br>
+    OS << "regparm(";<br>
+    QualType t = T->getEquivalentType();<br>
+    while (!t->isFunctionType())<br>
+      t = t->getPointeeType();<br>
+    OS << t->getAs<FunctionType>()->getRegParmType();<br>
+    OS << ')';<br>
+    break;<br>
+  }<br>
+<br>
+  case AttributedType::attr_ns_returns_retained:<br>
     OS << "ns_returns_retained";<br>
     break;<br>
<br>
   // FIXME: When Sema learns to form this AttributedType, avoid printing the<br>
   // attribute again in printFunctionProtoAfter.<br>
-  case attr::AnyX86NoCfCheck: OS << "nocf_check"; break;<br>
-  case attr::CDecl: OS << "cdecl"; break;<br>
-  case attr::FastCall: OS << "fastcall"; break;<br>
-  case attr::StdCall: OS << "stdcall"; break;<br>
-  case attr::ThisCall: OS << "thiscall"; break;<br>
-  case attr::SwiftCall: OS << "swiftcall"; break;<br>
-  case attr::VectorCall: OS << "vectorcall"; break;<br>
-  case attr::Pascal: OS << "pascal"; break;<br>
-  case attr::MSABI: OS << "ms_abi"; break;<br>
-  case attr::SysVABI: OS << "sysv_abi"; break;<br>
-  case attr::RegCall: OS << "regcall"; break;<br>
-  case attr::Pcs: {<br>
+  case AttributedType::attr_noreturn: OS << "noreturn"; break;<br>
+  case AttributedType::attr_nocf_check: OS << "nocf_check"; break;<br>
+  case AttributedType::attr_cdecl: OS << "cdecl"; break;<br>
+  case AttributedType::attr_fastcall: OS << "fastcall"; break;<br>
+  case AttributedType::attr_stdcall: OS << "stdcall"; break;<br>
+  case AttributedType::attr_thiscall: OS << "thiscall"; break;<br>
+  case AttributedType::attr_swiftcall: OS << "swiftcall"; break;<br>
+  case AttributedType::attr_vectorcall: OS << "vectorcall"; break;<br>
+  case AttributedType::attr_pascal: OS << "pascal"; break;<br>
+  case AttributedType::attr_ms_abi: OS << "ms_abi"; break;<br>
+  case AttributedType::attr_sysv_abi: OS << "sysv_abi"; break;<br>
+  case AttributedType::attr_regcall: OS << "regcall"; break;<br>
+  case AttributedType::attr_pcs:<br>
+  case AttributedType::attr_pcs_vfp: {<br>
     OS << "pcs(";<br>
    QualType t = T->getEquivalentType();<br>
    while (!t->isFunctionType())<br>
@@ -1486,12 +1517,12 @@ void TypePrinter::printAttributedAfter(c<br>
    break;<br>
   }<br>
<br>
-  case attr::IntelOclBicc: OS << "inteloclbicc"; break;<br>
-  case attr::PreserveMost:<br>
+  case AttributedType::attr_inteloclbicc: OS << "inteloclbicc"; break;<br>
+  case AttributedType::attr_preserve_most:<br>
     OS << "preserve_most";<br>
     break;<br>
<br>
-  case attr::PreserveAll:<br>
+  case AttributedType::attr_preserve_all:<br>
     OS << "preserve_all";<br>
     break;<br>
   }<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=339638&r1=339637&r2=339638&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=339638&r1=339637&r2=339638&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Aug 13 18:55:37 2018<br>
@@ -5999,14 +5999,14 @@ static void checkAttributesAfterMerging(<br>
       // The [[lifetimebound]] attribute can be applied to the implicit object<br>
       // parameter of a non-static member function (other than a ctor or dtor)<br>
       // by applying it to the function type.<br>
-      if (const auto *A = ATL.getAttrAs<LifetimeBoundAttr>()) {<br>
+      if (ATL.getAttrKind() == AttributedType::attr_lifetimebound) {<br>
         const auto *MD = dyn_cast<CXXMethodDecl>(FD);<br>
         if (!MD || MD->isStatic()) {<br>
-          S.Diag(A->getLocation(), diag::err_lifetimebound_no_object_param)<br>
-              << !MD << A->getRange();<br>
+          S.Diag(ATL.getAttrNameLoc(), diag::err_lifetimebound_no_object_param)<br>
+              << !MD << ATL.getLocalSourceRange();<br>
         } else if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) {<br>
-          S.Diag(A->getLocation(), diag::err_lifetimebound_ctor_dtor)<br>
-              << isa<CXXDestructorDecl>(MD) << A->getRange();<br>
+          S.Diag(ATL.getAttrNameLoc(), diag::err_lifetimebound_ctor_dtor)<br>
+              << isa<CXXDestructorDecl>(MD) << ATL.getLocalSourceRange();<br>
         }<br>
       }<br>
     }<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=339638&r1=339637&r2=339638&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=339638&r1=339637&r2=339638&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Aug 13 18:55:37 2018<br>
@@ -14658,15 +14658,15 @@ static bool captureInBlock(BlockScopeInf<br>
   // Warn about implicitly autoreleasing indirect parameters captured by blocks.<br>
   if (const auto *PT = CaptureType->getAs<PointerType>()) {<br>
     // This function finds out whether there is an AttributedType of kind<br>
-    // attr::ObjCOwnership in Ty. The existence of AttributedType of kind<br>
-    // attr::ObjCOwnership implies __autoreleasing was explicitly specified<br>
+    // attr_objc_ownership in Ty. The existence of AttributedType of kind<br>
+    // attr_objc_ownership implies __autoreleasing was explicitly specified<br>
     // rather than being added implicitly by the compiler.<br>
     auto IsObjCOwnershipAttributedType = [](QualType Ty) {<br>
       while (const auto *AttrTy = Ty->getAs<AttributedType>()) {<br>
-        if (AttrTy->getAttrKind() == attr::ObjCOwnership)<br>
+        if (AttrTy->getAttrKind() == AttributedType::attr_objc_ownership)<br>
           return true;<br>
<br>
-        // Peel off AttributedTypes that are not of kind ObjCOwnership.<br>
+        // Peel off AttributedTypes that are not of kind objc_ownership.<br>
         Ty = AttrTy->getModifiedType();<br>
       }<br>
<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaInit.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=339638&r1=339637&r2=339638&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=339638&r1=339637&r2=339638&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaInit.cpp Mon Aug 13 18:55:37 2018<br>
@@ -6360,7 +6360,7 @@ static bool implicitObjectParamIsLifetim<br>
   for (TypeLoc TL = TSI->getTypeLoc();<br>
        (ATL = TL.getAsAdjusted<AttributedTypeLoc>());<br>
        TL = ATL.getModifiedLoc()) {<br>
-    if (ATL.getAttrAs<LifetimeBoundAttr>())<br>
+    if (ATL.getAttrKind() == AttributedType::attr_lifetimebound)<br>
       return true;<br>
   }<br>
   return false;<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=339638&r1=339637&r2=339638&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=339638&r1=339637&r2=339638&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaObjCProperty.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaObjCProperty.cpp Mon Aug 13 18:55:37 2018<br>
@@ -2384,7 +2384,7 @@ void Sema::ProcessPropertyDecl(ObjCPrope<br>
       QualType modifiedTy = resultTy;<br>
       if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)) {<br>
         if (*nullability == NullabilityKind::Unspecified)<br>
-          resultTy = Context.getAttributedType(attr::TypeNonNull,<br>
+          resultTy = Context.getAttributedType(AttributedType::attr_nonnull,<br>
                                                modifiedTy, modifiedTy);<br>
       }<br>
     }<br>
@@ -2458,7 +2458,7 @@ void Sema::ProcessPropertyDecl(ObjCPrope<br>
         QualType modifiedTy = paramTy;<br>
         if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)){<br>
           if (*nullability == NullabilityKind::Unspecified)<br>
-            paramTy = Context.getAttributedType(attr::TypeNullable,<br>
+            paramTy = Context.getAttributedType(AttributedType::attr_nullable,<br>
                                                 modifiedTy, modifiedTy);<br>
         }<br>
       }<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaType.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=339638&r1=339637&r2=339638&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=339638&r1=339637&r2=339638&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaType.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaType.cpp Mon Aug 13 18:55:37 2018<br>
@@ -172,16 +172,6 @@ namespace {<br>
     /// processing is complete.<br>
     SmallVector<ParsedAttr *, 2> ignoredTypeAttrs;<br>
<br>
-    /// Attributes corresponding to AttributedTypeLocs that we have not yet<br>
-    /// populated.<br>
-    // FIXME: The two-phase mechanism by which we construct Types and fill<br>
-    // their TypeLocs makes it hard to correctly assign these. We keep the<br>
-    // attributes in creation order as an attempt to make them line up<br>
-    // properly.<br>
-    using TypeAttrPair = std::pair<const AttributedType*, const Attr*>;<br>
-    SmallVector<TypeAttrPair, 8> AttrsForTypes;<br>
-    bool AttrsForTypesSorted = true;<br>
-<br>
   public:<br>
     TypeProcessingState(Sema &sema, Declarator &declarator)<br>
       : sema(sema), declarator(declarator),<br>
@@ -240,43 +230,6 @@ namespace {<br>
         diagnoseBadTypeAttribute(getSema(), *Attr, type);<br>
     }<br>
<br>
-    /// Get an attributed type for the given attribute, and remember the Attr<br>
-    /// object so that we can attach it to the AttributedTypeLoc.<br>
-    QualType getAttributedType(Attr *A, QualType ModifiedType,<br>
-                               QualType EquivType) {<br>
-      QualType T =<br>
-          sema.Context.getAttributedType(A->getKind(), ModifiedType, EquivType);<br>
-      AttrsForTypes.push_back({cast<AttributedType>(T.getTypePtr()), A});<br>
-      AttrsForTypesSorted = false;<br>
-      return T;<br>
-    }<br>
-<br>
-    /// Extract and remove the Attr* for a given attributed type.<br>
-    const Attr *takeAttrForAttributedType(const AttributedType *AT) {<br>
-      if (!AttrsForTypesSorted) {<br>
-        std::stable_sort(AttrsForTypes.begin(), AttrsForTypes.end(),<br>
-                         [](const TypeAttrPair &A, const TypeAttrPair &B) {<br>
-                           return A.first < B.first;<br>
-                         });<br>
-        AttrsForTypesSorted = true;<br>
-      }<br>
-<br>
-      // FIXME: This is quadratic if we have lots of reuses of the same<br>
-      // attributed type.<br>
-      for (auto It = std::partition_point(<br>
-               AttrsForTypes.begin(), AttrsForTypes.end(),<br>
-               [=](const TypeAttrPair &A) { return A.first < AT; });<br>
-           It != AttrsForTypes.end() && It->first == AT; ++It) {<br>
-        if (It->second) {<br>
-          const Attr *Result = It->second;<br>
-          It->second = nullptr;<br>
-          return Result;<br>
-        }<br>
-      }<br>
-<br>
-      llvm_unreachable("no Attr* for AttributedType*");<br>
-    }<br>
-<br>
     ~TypeProcessingState() {<br>
       if (trivial) return;<br>
<br>
@@ -3879,32 +3832,6 @@ static bool hasOuterPointerLikeChunk(con<br>
   return false;<br>
 }<br>
<br>
-template<typename AttrT><br>
-static AttrT *createSimpleAttr(ASTContext &Ctx, ParsedAttr &Attr) {<br>
-  Attr.setUsedAsTypeAttr();<br>
-  return ::new (Ctx)<br>
-      AttrT(Attr.getRange(), Ctx, Attr.getAttributeSpellingListIndex());<br>
-}<br>
-<br>
-static Attr *createNullabilityAttr(ASTContext &Ctx, ParsedAttr &Attr,<br>
-                                   NullabilityKind NK) {<br>
-  switch (NK) {<br>
-  case NullabilityKind::NonNull:<br>
-    return createSimpleAttr<TypeNonNullAttr>(Ctx, Attr);<br>
-<br>
-  case NullabilityKind::Nullable:<br>
-    return createSimpleAttr<TypeNullableAttr>(Ctx, Attr);<br>
-<br>
-  case NullabilityKind::Unspecified:<br>
-    return createSimpleAttr<TypeNullUnspecifiedAttr>(Ctx, Attr);<br>
-  }<br>
-  llvm_unreachable("unknown NullabilityKind");<br>
-}<br>
-<br>
-static TypeSourceInfo *<br>
-GetTypeSourceInfoForDeclarator(TypeProcessingState &State,<br>
-                               QualType T, TypeSourceInfo *ReturnTypeInfo);<br>
-<br>
 static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,<br>
                                                 QualType declSpecType,<br>
                                                 TypeSourceInfo *TInfo) {<br>
@@ -4257,8 +4184,9 @@ static TypeSourceInfo *GetFullTypeForDec<br>
                 pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(),<br>
                 D.getDeclSpec().getEndLoc(),<br>
                 D.getMutableDeclSpec().getAttributes())) {<br>
-          T = state.getAttributedType(<br>
-              createNullabilityAttr(Context, *attr, *inferNullability), T, T);<br>
+          T = Context.getAttributedType(<br>
+                AttributedType::getNullabilityAttrKind(*inferNullability),T,T);<br>
+          attr->setUsedAsTypeAttr();<br>
         }<br>
       }<br>
     }<br>
@@ -5097,7 +5025,7 @@ static TypeSourceInfo *GetFullTypeForDec<br>
   if (D.isInvalidType())<br>
     return Context.getTrivialTypeSourceInfo(T);<br>
<br>
-  return GetTypeSourceInfoForDeclarator(state, T, TInfo);<br>
+  return S.GetTypeSourceInfoForDeclarator(D, T, TInfo);<br>
 }<br>
<br>
 /// GetTypeForDeclarator - Convert the type for the specified<br>
@@ -5233,25 +5161,131 @@ TypeSourceInfo *Sema::GetTypeForDeclarat<br>
   return GetFullTypeForDeclarator(state, declSpecTy, ReturnTypeInfo);<br>
 }<br>
<br>
+/// Map an AttributedType::Kind to an ParsedAttr::Kind.<br>
+static ParsedAttr::Kind getAttrListKind(AttributedType::Kind kind) {<br>
+  switch (kind) {<br>
+  case AttributedType::attr_address_space:<br>
+    return ParsedAttr::AT_AddressSpace;<br>
+  case AttributedType::attr_regparm:<br>
+    return ParsedAttr::AT_Regparm;<br>
+  case AttributedType::attr_vector_size:<br>
+    return ParsedAttr::AT_VectorSize;<br>
+  case AttributedType::attr_neon_vector_type:<br>
+    return ParsedAttr::AT_NeonVectorType;<br>
+  case AttributedType::attr_neon_polyvector_type:<br>
+    return ParsedAttr::AT_NeonPolyVectorType;<br>
+  case AttributedType::attr_objc_gc:<br>
+    return ParsedAttr::AT_ObjCGC;<br>
+  case AttributedType::attr_objc_ownership:<br>
+  case AttributedType::attr_objc_inert_unsafe_unretained:<br>
+    return ParsedAttr::AT_ObjCOwnership;<br>
+  case AttributedType::attr_noreturn:<br>
+    return ParsedAttr::AT_NoReturn;<br>
+  case AttributedType::attr_nocf_check:<br>
+    return ParsedAttr::AT_AnyX86NoCfCheck;<br>
+  case AttributedType::attr_cdecl:<br>
+    return ParsedAttr::AT_CDecl;<br>
+  case AttributedType::attr_fastcall:<br>
+    return ParsedAttr::AT_FastCall;<br>
+  case AttributedType::attr_stdcall:<br>
+    return ParsedAttr::AT_StdCall;<br>
+  case AttributedType::attr_thiscall:<br>
+    return ParsedAttr::AT_ThisCall;<br>
+  case AttributedType::attr_regcall:<br>
+    return ParsedAttr::AT_RegCall;<br>
+  case AttributedType::attr_pascal:<br>
+    return ParsedAttr::AT_Pascal;<br>
+  case AttributedType::attr_swiftcall:<br>
+    return ParsedAttr::AT_SwiftCall;<br>
+  case AttributedType::attr_vectorcall:<br>
+    return ParsedAttr::AT_VectorCall;<br>
+  case AttributedType::attr_pcs:<br>
+  case AttributedType::attr_pcs_vfp:<br>
+    return ParsedAttr::AT_Pcs;<br>
+  case AttributedType::attr_inteloclbicc:<br>
+    return ParsedAttr::AT_IntelOclBicc;<br>
+  case AttributedType::attr_ms_abi:<br>
+    return ParsedAttr::AT_MSABI;<br>
+  case AttributedType::attr_sysv_abi:<br>
+    return ParsedAttr::AT_SysVABI;<br>
+  case AttributedType::attr_preserve_most:<br>
+    return ParsedAttr::AT_PreserveMost;<br>
+  case AttributedType::attr_preserve_all:<br>
+    return ParsedAttr::AT_PreserveAll;<br>
+  case AttributedType::attr_ptr32:<br>
+    return ParsedAttr::AT_Ptr32;<br>
+  case AttributedType::attr_ptr64:<br>
+    return ParsedAttr::AT_Ptr64;<br>
+  case AttributedType::attr_sptr:<br>
+    return ParsedAttr::AT_SPtr;<br>
+  case AttributedType::attr_uptr:<br>
+    return ParsedAttr::AT_UPtr;<br>
+  case AttributedType::attr_nonnull:<br>
+    return ParsedAttr::AT_TypeNonNull;<br>
+  case AttributedType::attr_nullable:<br>
+    return ParsedAttr::AT_TypeNullable;<br>
+  case AttributedType::attr_null_unspecified:<br>
+    return ParsedAttr::AT_TypeNullUnspecified;<br>
+  case AttributedType::attr_objc_kindof:<br>
+    return ParsedAttr::AT_ObjCKindOf;<br>
+  case AttributedType::attr_ns_returns_retained:<br>
+    return ParsedAttr::AT_NSReturnsRetained;<br>
+  case AttributedType::attr_lifetimebound:<br>
+    return ParsedAttr::AT_LifetimeBound;<br>
+  }<br>
+  llvm_unreachable("unexpected attribute kind!");<br>
+}<br>
+<br>
+static void setAttributedTypeLoc(AttributedTypeLoc TL, const ParsedAttr &attr) {<br>
+  TL.setAttrNameLoc(attr.getLoc());<br>
+  if (TL.hasAttrExprOperand()) {<br>
+    assert(attr.isArgExpr(0) && "mismatched attribute operand kind");<br>
+    TL.setAttrExprOperand(attr.getArgAsExpr(0));<br>
+  } else if (TL.hasAttrEnumOperand()) {<br>
+    assert((attr.isArgIdent(0) || attr.isArgExpr(0)) &&<br>
+           "unexpected attribute operand kind");<br>
+    if (attr.isArgIdent(0))<br>
+      TL.setAttrEnumOperandLoc(attr.getArgAsIdent(0)->Loc);<br>
+    else<br>
+      TL.setAttrEnumOperandLoc(attr.getArgAsExpr(0)->getExprLoc());<br>
+  }<br>
+<br>
+  // FIXME: preserve this information to here.<br>
+  if (TL.hasAttrOperand())<br>
+    TL.setAttrOperandParensRange(SourceRange());<br>
+}<br>
+<br>
 static void fillAttributedTypeLoc(AttributedTypeLoc TL,<br>
-                                  TypeProcessingState &State) {<br>
-  TL.setAttr(State.takeAttrForAttributedType(TL.getTypePtr()));<br>
+                                  const ParsedAttributesView &Attrs,<br>
+                                  const ParsedAttributesView &DeclAttrs) {<br>
+  // DeclAttrs and Attrs cannot be both empty.<br>
+  assert((!Attrs.empty() || !DeclAttrs.empty()) &&<br>
+         "no type attributes in the expected location!");<br>
+<br>
+  ParsedAttr::Kind parsedKind = getAttrListKind(TL.getAttrKind());<br>
+  // Try to search for an attribute of matching kind in Attrs list.<br>
+  for (const ParsedAttr &AL : Attrs)<br>
+    if (AL.getKind() == parsedKind)<br>
+      return setAttributedTypeLoc(TL, AL);<br>
+<br>
+  for (const ParsedAttr &AL : DeclAttrs)<br>
+    if (AL.isCXX11Attribute() || AL.getKind() == parsedKind)<br>
+      return setAttributedTypeLoc(TL, AL);<br>
+  llvm_unreachable("no matching type attribute in expected location!");<br>
 }<br>
<br>
 namespace {<br>
   class TypeSpecLocFiller : public TypeLocVisitor<TypeSpecLocFiller> {<br>
     ASTContext &Context;<br>
-    TypeProcessingState &State;<br>
     const DeclSpec &DS;<br>
<br>
   public:<br>
-    TypeSpecLocFiller(ASTContext &Context, TypeProcessingState &State,<br>
-                      const DeclSpec &DS)<br>
-        : Context(Context), State(State), DS(DS) {}<br>
+    TypeSpecLocFiller(ASTContext &Context, const DeclSpec &DS)<br>
+      : Context(Context), DS(DS) {}<br>
<br>
     void VisitAttributedTypeLoc(AttributedTypeLoc TL) {<br>
+      fillAttributedTypeLoc(TL, DS.getAttributes(), ParsedAttributesView{});<br>
       Visit(TL.getModifiedLoc());<br>
-      fillAttributedTypeLoc(TL, State);<br>
     }<br>
     void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {<br>
       Visit(TL.getUnqualifiedLoc());<br>
@@ -5408,13 +5442,11 @@ namespace {<br>
<br>
   class DeclaratorLocFiller : public TypeLocVisitor<DeclaratorLocFiller> {<br>
     ASTContext &Context;<br>
-    TypeProcessingState &State;<br>
     const DeclaratorChunk &Chunk;<br>
<br>
   public:<br>
-    DeclaratorLocFiller(ASTContext &Context, TypeProcessingState &State,<br>
-                        const DeclaratorChunk &Chunk)<br>
-        : Context(Context), State(State), Chunk(Chunk) {}<br>
+    DeclaratorLocFiller(ASTContext &Context, const DeclaratorChunk &Chunk)<br>
+      : Context(Context), Chunk(Chunk) {}<br>
<br>
     void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {<br>
       llvm_unreachable("qualified type locs not expected here!");<br>
@@ -5424,7 +5456,7 @@ namespace {<br>
     }<br>
<br>
     void VisitAttributedTypeLoc(AttributedTypeLoc TL) {<br>
-      fillAttributedTypeLoc(TL, State);<br>
+      fillAttributedTypeLoc(TL, Chunk.getAttrs(), ParsedAttributesView{});<br>
     }<br>
     void VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {<br>
       // nothing<br>
@@ -5581,13 +5613,10 @@ fillDependentAddressSpaceTypeLoc(Depende<br>
 /// up in the normal place in the declaration specifiers (such as a C++<br>
 /// conversion function), this pointer will refer to a type source information<br>
 /// for that return type.<br>
-static TypeSourceInfo *<br>
-GetTypeSourceInfoForDeclarator(TypeProcessingState &State,<br>
-                               QualType T, TypeSourceInfo *ReturnTypeInfo) {<br>
-  Sema &S = State.getSema();<br>
-  Declarator &D = State.getDeclarator();<br>
-<br>
-  TypeSourceInfo *TInfo = S.Context.CreateTypeSourceInfo(T);<br>
+TypeSourceInfo *<br>
+Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,<br>
+                                     TypeSourceInfo *ReturnTypeInfo) {<br>
+  TypeSourceInfo *TInfo = Context.CreateTypeSourceInfo(T);<br>
   UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc();<br>
<br>
   // Handle parameter packs whose type is a pack expansion.<br>
@@ -5597,6 +5626,7 @@ GetTypeSourceInfoForDeclarator(TypeProce<br>
   }<br>
<br>
   for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {<br>
+<br>
     if (DependentAddressSpaceTypeLoc DASTL =<br>
         CurrTL.getAs<DependentAddressSpaceTypeLoc>()) {<br>
       fillDependentAddressSpaceTypeLoc(DASTL, D.getTypeObject(i).getAttrs());<br>
@@ -5611,7 +5641,8 @@ GetTypeSourceInfoForDeclarator(TypeProce<br>
     }<br>
<br>
     while (AttributedTypeLoc TL = CurrTL.getAs<AttributedTypeLoc>()) {<br>
-      fillAttributedTypeLoc(TL, State);<br>
+      fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs(),<br>
+                            D.getAttributes());<br>
       CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();<br>
     }<br>
<br>
@@ -5619,7 +5650,7 @@ GetTypeSourceInfoForDeclarator(TypeProce<br>
     while (AdjustedTypeLoc TL = CurrTL.getAs<AdjustedTypeLoc>())<br>
       CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();<br>
<br>
-    DeclaratorLocFiller(S.Context, State, D.getTypeObject(i)).Visit(CurrTL);<br>
+    DeclaratorLocFiller(Context, D.getTypeObject(i)).Visit(CurrTL);<br>
     CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();<br>
   }<br>
<br>
@@ -5630,7 +5661,7 @@ GetTypeSourceInfoForDeclarator(TypeProce<br>
     assert(TL.getFullDataSize() == CurrTL.getFullDataSize());<br>
     memcpy(CurrTL.getOpaqueData(), TL.getOpaqueData(), TL.getFullDataSize());<br>
   } else {<br>
-    TypeSpecLocFiller(S.Context, State, D.getDeclSpec()).Visit(CurrTL);<br>
+    TypeSpecLocFiller(Context, D.getDeclSpec()).Visit(CurrTL);<br>
   }<br>
<br>
   return TInfo;<br>
@@ -5859,7 +5890,7 @@ static bool hasDirectOwnershipQualifier(<br>
   while (true) {<br>
     // __strong id<br>
     if (const AttributedType *attr = dyn_cast<AttributedType>(type)) {<br>
-      if (attr->getAttrKind() == attr::ObjCOwnership)<br>
+      if (attr->getAttrKind() == AttributedType::attr_objc_ownership)<br>
         return true;<br>
<br>
       type = attr->getModifiedType();<br>
@@ -6003,9 +6034,9 @@ static bool handleObjCOwnershipTypeAttr(<br>
   // the coexistence problems with __unsafe_unretained.<br>
   if (!S.getLangOpts().ObjCAutoRefCount &&<br>
       lifetime == Qualifiers::OCL_ExplicitNone) {<br>
-    type = state.getAttributedType(<br>
-        createSimpleAttr<ObjCInertUnsafeUnretainedAttr>(S.Context, attr),<br>
-        type, type);<br>
+    type = S.Context.getAttributedType(<br>
+                             AttributedType::attr_objc_inert_unsafe_unretained,<br>
+                                       type, type);<br>
     return true;<br>
   }<br>
<br>
@@ -6015,12 +6046,9 @@ static bool handleObjCOwnershipTypeAttr(<br>
<br>
   // If we have a valid source location for the attribute, use an<br>
   // AttributedType instead.<br>
-  if (AttrLoc.isValid()) {<br>
-    type = state.getAttributedType(::new (S.Context) ObjCOwnershipAttr(<br>
-                                       attr.getRange(), S.Context, II,<br>
-                                       attr.getAttributeSpellingListIndex()),<br>
-                                   origType, type);<br>
-  }<br>
+  if (AttrLoc.isValid())<br>
+    type = S.Context.getAttributedType(AttributedType::attr_objc_ownership,<br>
+                                       origType, type);<br>
<br>
   auto diagnoseOrDelay = [](Sema &S, SourceLocation loc,<br>
                             unsigned diagnostic, QualType type) {<br>
@@ -6120,10 +6148,8 @@ static bool handleObjCGCTypeAttr(TypePro<br>
<br>
   // Make an attributed type to preserve the source information.<br>
   if (attr.getLoc().isValid())<br>
-    type = state.getAttributedType(<br>
-        ::new (S.Context) ObjCGCAttr(attr.getRange(), S.Context, II,<br>
-                                     attr.getAttributeSpellingListIndex()),<br>
-        origType, type);<br>
+    type = S.Context.getAttributedType(AttributedType::attr_objc_gc,<br>
+                                       origType, type);<br>
<br>
   return true;<br>
 }<br>
@@ -6266,50 +6292,37 @@ namespace {<br>
 } // end anonymous namespace<br>
<br>
 static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,<br>
-                                             ParsedAttr &PAttr, QualType &Type) {<br>
+                                             ParsedAttr &Attr, QualType &Type) {<br>
   Sema &S = State.getSema();<br>
<br>
-  Attr *A;<br>
-  switch (PAttr.getKind()) {<br>
-  default: llvm_unreachable("Unknown attribute kind");<br>
-  case ParsedAttr::AT_Ptr32:<br>
-    A = createSimpleAttr<Ptr32Attr>(S.Context, PAttr);<br>
-    break;<br>
-  case ParsedAttr::AT_Ptr64:<br>
-    A = createSimpleAttr<Ptr64Attr>(S.Context, PAttr);<br>
-    break;<br>
-  case ParsedAttr::AT_SPtr:<br>
-    A = createSimpleAttr<SPtrAttr>(S.Context, PAttr);<br>
-    break;<br>
-  case ParsedAttr::AT_UPtr:<br>
-    A = createSimpleAttr<UPtrAttr>(S.Context, PAttr);<br>
-    break;<br>
-  }<br>
-<br>
-  attr::Kind NewAttrKind = A->getKind();<br>
+  ParsedAttr::Kind Kind = Attr.getKind();<br>
   QualType Desugared = Type;<br>
   const AttributedType *AT = dyn_cast<AttributedType>(Type);<br>
   while (AT) {<br>
-    attr::Kind CurAttrKind = AT->getAttrKind();<br>
+    AttributedType::Kind CurAttrKind = AT->getAttrKind();<br>
<br>
     // You cannot specify duplicate type attributes, so if the attribute has<br>
     // already been applied, flag it.<br>
-    if (NewAttrKind == CurAttrKind) {<br>
-      S.Diag(PAttr.getLoc(), diag::warn_duplicate_attribute_exact)<br>
-        << PAttr.getName();<br>
+    if (getAttrListKind(CurAttrKind) == Kind) {<br>
+      S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute_exact)<br>
+        << Attr.getName();<br>
       return true;<br>
     }<br>
<br>
     // You cannot have both __sptr and __uptr on the same type, nor can you<br>
     // have __ptr32 and __ptr64.<br>
-  </blockquote></div>