Revert r339623 "Model type attributes as regular Attrs."
authorReid Kleckner <rnk@google.com>
Tue, 14 Aug 2018 01:55:37 +0000 (01:55 +0000)
committerReid Kleckner <rnk@google.com>
Tue, 14 Aug 2018 01:55:37 +0000 (01:55 +0000)
This breaks compiling atlwin.h in Chromium. I'm sure the code is invalid
in some way, but we put a lot of work into accepting it, and I'm sure
rejecting it was not an intended consequence of this refactoring. :)

llvm-svn: 339638

25 files changed:
clang/include/clang/AST/ASTContext.h
clang/include/clang/AST/Attr.h
clang/include/clang/AST/Type.h
clang/include/clang/AST/TypeLoc.h
clang/include/clang/Basic/Attr.td
clang/include/clang/Sema/Sema.h
clang/include/clang/Serialization/ASTReader.h
clang/include/clang/Serialization/ASTWriter.h
clang/lib/ARCMigrate/TransGCAttrs.cpp
clang/lib/ARCMigrate/Transforms.cpp
clang/lib/AST/ASTContext.cpp
clang/lib/AST/Type.cpp
clang/lib/AST/TypeLoc.cpp
clang/lib/AST/TypePrinter.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/SemaInit.cpp
clang/lib/Sema/SemaObjCProperty.cpp
clang/lib/Sema/SemaType.cpp
clang/lib/Sema/TreeTransform.h
clang/lib/Serialization/ASTReader.cpp
clang/lib/Serialization/ASTReaderDecl.cpp
clang/lib/Serialization/ASTWriter.cpp
clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
clang/utils/TableGen/ClangAttrEmitter.cpp

index 87f0e8f..ea07d5f 100644 (file)
@@ -31,7 +31,6 @@
 #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"
@@ -1423,7 +1422,7 @@ public:
 
   QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST) const;
 
-  QualType getAttributedType(attr::Kind attrKind,
+  QualType getAttributedType(AttributedType::Kind attrKind,
                              QualType modifiedType,
                              QualType equivalentType);
 
index 4ee0839..2092274 100644 (file)
@@ -113,19 +113,6 @@ 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,
index 9bc1a53..93dafc4 100644 (file)
@@ -21,7 +21,6 @@
 #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"
@@ -1871,16 +1870,7 @@ public:
   bool isObjCQualifiedClassType() const;        // Class<foo>
   bool isObjCObjectOrInterfaceType() const;
   bool isObjCIdType() const;                    // id
-
-  /// 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);
-  }
+  bool isObjCInertUnsafeUnretainedType() const;
 
   /// Whether the type is Objective-C 'id' or a __kindof type of an
   /// object type, e.g., __kindof NSView * or __kindof id
@@ -2094,10 +2084,6 @@ 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.
@@ -4207,7 +4193,56 @@ public:
 ///   - the canonical type is VectorType(16, int)
 class AttributedType : public Type, public llvm::FoldingSetNode {
 public:
-  using Kind = attr::Kind;
+  // 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,
+  };
 
 private:
   friend class ASTContext; // ASTContext creates these
@@ -4215,7 +4250,7 @@ private:
   QualType ModifiedType;
   QualType EquivalentType;
 
-  AttributedType(QualType canon, attr::Kind attrKind, QualType modified,
+  AttributedType(QualType canon, Kind attrKind, QualType modified,
                  QualType equivalent)
       : Type(Attributed, canon, equivalent->isDependentType(),
              equivalent->isInstantiationDependentType(),
@@ -4264,13 +4299,13 @@ public:
   static Kind getNullabilityAttrKind(NullabilityKind kind) {
     switch (kind) {
     case NullabilityKind::NonNull:
-      return attr::TypeNonNull;
+      return attr_nonnull;
 
     case NullabilityKind::Nullable:
-      return attr::TypeNullable;
+      return attr_nullable;
 
     case NullabilityKind::Unspecified:
-      return attr::TypeNullUnspecified;
+      return attr_null_unspecified;
     }
     llvm_unreachable("Unknown nullability kind.");
   }
index 7ac8ded..82e83ea 100644 (file)
@@ -15,7 +15,6 @@
 #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"
@@ -850,7 +849,16 @@ class SubstTemplateTypeParmPackTypeLoc :
 };
 
 struct AttributedLocInfo {
-  const Attr *TypeAttr;
+  union {
+    Expr *ExprOperand;
+
+    /// A raw SourceLocation.
+    unsigned EnumOperandLoc;
+  };
+
+  SourceRange OperandParens;
+
+  SourceLocation AttrLoc;
 };
 
 /// Type source information for an attributed type.
@@ -859,10 +867,24 @@ class AttributedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
                                                  AttributedType,
                                                  AttributedLocInfo> {
 public:
-  attr::Kind getAttrKind() const {
+  AttributedType::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();
   }
@@ -875,16 +897,51 @@ public:
     return getInnerTypeLoc();
   }
 
-  /// The type attribute.
-  const Attr *getAttr() const {
-    return getLocalData()->TypeAttr;
+  /// The location of the attribute name, i.e.
+  ///    __attribute__((regparm(1000)))
+  ///                   ^~~~~~~
+  SourceLocation getAttrNameLoc() const {
+    return getLocalData()->AttrLoc;
   }
-  void setAttr(const Attr *A) {
-    getLocalData()->TypeAttr = A;
+  void setAttrNameLoc(SourceLocation loc) {
+    getLocalData()->AttrLoc = loc;
   }
 
-  template<typename T> const T *getAttrAs() {
-    return dyn_cast_or_null<T>(getAttr());
+  /// 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;
   }
 
   SourceRange getLocalSourceRange() const {
@@ -897,11 +954,21 @@ public:
     //    ^~        ~~
     // That enclosure doesn't necessarily belong to a single attribute
     // anyway.
-    return getAttr() ? getAttr()->getRange() : SourceRange();
+    SourceRange range(getAttrNameLoc());
+    if (hasAttrOperand())
+      range.setEnd(getAttrOperandParensRange().getEnd());
+    return range;
   }
 
   void initializeLocal(ASTContext &Context, SourceLocation loc) {
-    setAttr(nullptr);
+    setAttrNameLoc(loc);
+    if (hasAttrExprOperand()) {
+      setAttrOperandParensRange(SourceRange(loc));
+      setAttrExprOperand(nullptr);
+    } else if (hasAttrEnumOperand()) {
+      setAttrOperandParensRange(SourceRange(loc));
+      setAttrEnumOperandLoc(loc);
+    }
   }
 
   QualType getInnerType() const {
index 736126b..7591635 100644 (file)
@@ -494,7 +494,10 @@ class Attr {
 }
 
 /// A type attribute is not processed on a declaration or a statement.
-class TypeAttr : Attr;
+class TypeAttr : Attr {
+  // By default, type attributes do not get an AST node.
+  let ASTNode = 0;
+}
 
 /// A stmt attribute is not processed on a declaration or a type.
 class StmtAttr : Attr;
@@ -564,8 +567,6 @@ 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 {
@@ -1223,7 +1224,7 @@ def LayoutVersion : InheritableAttr, TargetSpecificAttr<TargetMicrosoftCXXABI> {
   let Documentation = [LayoutVersionDocs];
 }
 
-def LifetimeBound : DeclOrTypeAttr {
+def LifetimeBound : InheritableAttr {
   let Spellings = [Clang<"lifetimebound", 0>];
   let Subjects = SubjectList<[ParmVar, ImplicitObjectParameter], ErrorDiag>;
   let Documentation = [LifetimeBoundDocs];
@@ -1326,16 +1327,12 @@ 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 {
@@ -1510,14 +1507,6 @@ 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];
@@ -1605,7 +1594,7 @@ def ObjCBridgeRelated : InheritableAttr {
   let Documentation = [Undocumented];
 }
 
-def NSReturnsRetained : DeclOrTypeAttr {
+def NSReturnsRetained : InheritableAttr {
   let Spellings = [Clang<"ns_returns_retained">];
 //  let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
   let Documentation = [Undocumented];
@@ -1790,8 +1779,6 @@ 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 {
@@ -2080,9 +2067,10 @@ def ObjCGC : TypeAttr {
   let Documentation = [Undocumented];
 }
 
-def ObjCOwnership : DeclOrTypeAttr {
+def ObjCOwnership : InheritableAttr {
   let Spellings = [Clang<"objc_ownership">];
   let Args = [IdentifierArgument<"Kind">];
+  let ASTNode = 0;
   let Documentation = [Undocumented];
 }
 
@@ -2120,8 +2108,6 @@ 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 {
@@ -2216,7 +2202,7 @@ def AnyX86NoCallerSavedRegisters : InheritableAttr,
   let Documentation = [AnyX86NoCallerSavedRegistersDocs];
 }
 
-def AnyX86NoCfCheck : DeclOrTypeAttr, TargetSpecificAttr<TargetAnyX86>{
+def AnyX86NoCfCheck : InheritableAttr, TargetSpecificAttr<TargetAnyX86>{
   let Spellings = [GCC<"nocf_check">];
   let Subjects = SubjectList<[FunctionLike]>;
   let Documentation = [AnyX86NoCfCheckDocs];
index c70e6dc..b3d1c96 100644 (file)
@@ -1435,6 +1435,8 @@ 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);
@@ -3376,6 +3378,30 @@ 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,
@@ -8045,6 +8071,10 @@ 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.
index 1efadc7..b959f59 100644 (file)
@@ -2245,9 +2245,6 @@ 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);
 
@@ -2633,11 +2630,6 @@ 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);
index 1a89a9e..7ff5d65 100644 (file)
@@ -955,9 +955,6 @@ 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);
 };
index 06f8a23..fb45cd9 100644 (file)
@@ -81,11 +81,10 @@ public:
   }
 
   bool handleAttr(AttributedTypeLoc TL, Decl *D = nullptr) {
-    auto *OwnershipAttr = TL.getAttrAs<ObjCOwnershipAttr>();
-    if (!OwnershipAttr)
+    if (TL.getAttrKind() != AttributedType::attr_objc_ownership)
       return false;
 
-    SourceLocation Loc = OwnershipAttr->getLocation();
+    SourceLocation Loc = TL.getAttrNameLoc();
     unsigned RawLoc = Loc.getRawEncoding();
     if (MigrateCtx.AttrSet.count(RawLoc))
       return true;
@@ -94,7 +93,13 @@ public:
     SourceManager &SM = Ctx.getSourceManager();
     if (Loc.isMacroID())
       Loc = SM.getImmediateExpansionRange(Loc).getBegin();
-    StringRef Spell = OwnershipAttr->getKind()->getName();
+    SmallString<32> Buf;
+    bool Invalid = false;
+    StringRef Spell = Lexer::getSpelling(
+                                  SM.getSpellingLoc(TL.getAttrEnumOperandLoc()),
+                                  Buf, SM, Ctx.getLangOpts(), &Invalid);
+    if (Invalid)
+      return false;
     MigrationContext::GCAttrOccurrence::AttrKind Kind;
     if (Spell == "strong")
       Kind = MigrationContext::GCAttrOccurrence::Strong;
@@ -279,7 +284,7 @@ static void checkAllAtProps(MigrationContext &MigrateCtx,
   }
 
   for (unsigned i = 0, e = ATLs.size(); i != e; ++i) {
-    SourceLocation Loc = ATLs[i].first.getAttr()->getLocation();
+    SourceLocation Loc = ATLs[i].first.getAttrNameLoc();
     if (Loc.isMacroID())
       Loc = MigrateCtx.Pass.Ctx.getSourceManager()
                 .getImmediateExpansionRange(Loc)
index a403744..4a7af28 100644 (file)
@@ -359,7 +359,7 @@ MigrationContext::~MigrationContext() {
 bool MigrationContext::isGCOwnedNonObjC(QualType T) {
   while (!T.isNull()) {
     if (const AttributedType *AttrT = T->getAs<AttributedType>()) {
-      if (AttrT->getAttrKind() == attr::ObjCOwnership)
+      if (AttrT->getAttrKind() == AttributedType::attr_objc_ownership)
         return !AttrT->getModifiedType()->isObjCRetainableType();
     }
 
index 45703cc..b96e24a 100644 (file)
@@ -3876,7 +3876,7 @@ QualType ASTContext::getEnumType(const EnumDecl *Decl) const {
   return QualType(newType, 0);
 }
 
-QualType ASTContext::getAttributedType(attr::Kind attrKind,
+QualType ASTContext::getAttributedType(AttributedType::Kind attrKind,
                                        QualType modifiedType,
                                        QualType equivalentType) {
   llvm::FoldingSetNodeID id;
index 333b07e..315844f 100644 (file)
@@ -592,6 +592,28 @@ bool Type::isObjCClassOrClassKindOfType() const {
   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)
@@ -1619,16 +1641,6 @@ 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 :
@@ -3155,58 +3167,105 @@ 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 attr::ObjCGC:
-  case attr::ObjCOwnership:
-  case attr::ObjCInertUnsafeUnretained:
-  case attr::TypeNonNull:
-  case attr::TypeNullable:
-  case attr::TypeNullUnspecified:
-  case attr::LifetimeBound:
+  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;
 
-  // All other type attributes aren't qualifiers; they rewrite the modified
-  // type to be a semantically different type.
-  default:
+  // 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:
     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()) {
-  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:
+  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:
     return true;
   }
   llvm_unreachable("invalid attr kind");
@@ -3649,18 +3708,23 @@ LinkageInfo Type::getLinkageAndVisibility() const {
   return LinkageComputer{}.getTypeLinkageAndVisibility(this);
 }
 
-Optional<NullabilityKind>
-Type::getNullability(const ASTContext &Context) const {
-  QualType Type(this, 0);
-  while (const auto *AT = Type->getAs<AttributedType>()) {
+Optional<NullabilityKind> Type::getNullability(const ASTContext &context) const {
+  QualType type(this, 0);
+  do {
     // Check whether this is an attributed type with nullability
     // information.
-    if (auto Nullability = AT->getImmediateNullability())
-      return Nullability;
+    if (auto attributed = dyn_cast<AttributedType>(type.getTypePtr())) {
+      if (auto nullability = attributed->getImmediateNullability())
+        return nullability;
+    }
 
-    Type = AT->getEquivalentType();
-  }
-  return None;
+    // Desugar the type. If desugaring does nothing, we're done.
+    QualType desugared = type.getSingleStepDesugaredType(context);
+    if (desugared.getTypePtr() == type.getTypePtr())
+      return None;
+
+    type = desugared;
+  } while (true);
 }
 
 bool Type::canHaveNullability(bool ResultIfUnknown) const {
@@ -3773,13 +3837,12 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
   llvm_unreachable("bad type kind!");
 }
 
-llvm::Optional<NullabilityKind>
-AttributedType::getImmediateNullability() const {
-  if (getAttrKind() == attr::TypeNonNull)
+llvm::Optional<NullabilityKind> AttributedType::getImmediateNullability() const {
+  if (getAttrKind() == AttributedType::attr_nonnull)
     return NullabilityKind::NonNull;
-  if (getAttrKind() == attr::TypeNullable)
+  if (getAttrKind() == AttributedType::attr_nullable)
     return NullabilityKind::Nullable;
-  if (getAttrKind() == attr::TypeNullUnspecified)
+  if (getAttrKind() == AttributedType::attr_null_unspecified)
     return NullabilityKind::Unspecified;
   return None;
 }
index b6dc679..e4fd6f1 100644 (file)
@@ -404,11 +404,11 @@ TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
 }
 
 SourceLocation TypeLoc::findNullabilityLoc() const {
-  if (auto ATL = getAs<AttributedTypeLoc>()) {
-    const Attr *A = ATL.getAttr();
-    if (A && (isa<TypeNullableAttr>(A) || isa<TypeNonNullAttr>(A) ||
-              isa<TypeNullUnspecifiedAttr>(A)))
-      return A->getLocation();
+  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();
   }
 
   return {};
index d86849f..1cb5ff4 100644 (file)
@@ -1354,14 +1354,12 @@ void TypePrinter::printPackExpansionAfter(const PackExpansionType *T,
 
 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() == attr::ObjCGC ||
-      T->getAttrKind() == attr::ObjCOwnership)
+  if (T->getAttrKind() == AttributedType::attr_objc_gc ||
+      T->getAttrKind() == AttributedType::attr_objc_ownership)
     return printBefore(T->getEquivalentType(), OS);
 
-  if (T->getAttrKind() == attr::ObjCKindOf)
+  if (T->getAttrKind() == AttributedType::attr_objc_kindof)
     OS << "__kindof ";
 
   printBefore(T->getModifiedType(), OS);
@@ -1369,21 +1367,23 @@ void TypePrinter::printAttributedBefore(const AttributedType *T,
   if (T->isMSTypeSpec()) {
     switch (T->getAttrKind()) {
     default: return;
-    case attr::Ptr32: OS << " __ptr32"; break;
-    case attr::Ptr64: OS << " __ptr64"; break;
-    case attr::SPtr: OS << " __sptr"; break;
-    case attr::UPtr: OS << " __uptr"; break;
+    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;
     }
     spaceBeforePlaceHolder(OS);
   }
 
   // Print nullability type specifiers.
-  if (T->getImmediateNullability()) {
-    if (T->getAttrKind() == attr::TypeNonNull)
+  if (T->getAttrKind() == AttributedType::attr_nonnull ||
+      T->getAttrKind() == AttributedType::attr_nullable ||
+      T->getAttrKind() == AttributedType::attr_null_unspecified) {
+    if (T->getAttrKind() == AttributedType::attr_nonnull)
       OS << " _Nonnull";
-    else if (T->getAttrKind() == attr::TypeNullable)
+    else if (T->getAttrKind() == AttributedType::attr_nullable)
       OS << " _Nullable";
-    else if (T->getAttrKind() == attr::TypeNullUnspecified)
+    else if (T->getAttrKind() == AttributedType::attr_null_unspecified)
       OS << " _Null_unspecified";
     else
       llvm_unreachable("unhandled nullability");
@@ -1393,11 +1393,9 @@ void TypePrinter::printAttributedBefore(const AttributedType *T,
 
 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() == attr::ObjCGC ||
-      T->getAttrKind() == attr::ObjCOwnership)
+  if (T->getAttrKind() == AttributedType::attr_objc_gc ||
+      T->getAttrKind() == AttributedType::attr_objc_ownership)
     return printAfter(T->getEquivalentType(), OS);
 
   // If this is a calling convention attribute, don't print the implicit CC from
@@ -1408,74 +1406,107 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
 
   // Some attributes are printed as qualifiers before the type, so we have
   // nothing left to do.
-  if (T->getAttrKind() == attr::ObjCKindOf ||
-      T->isMSTypeSpec() || T->getImmediateNullability())
+  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)
     return;
 
   // Don't print the inert __unsafe_unretained attribute at all.
-  if (T->getAttrKind() == attr::ObjCInertUnsafeUnretained)
+  if (T->getAttrKind() == AttributedType::attr_objc_inert_unsafe_unretained)
     return;
 
   // Don't print ns_returns_retained unless it had an effect.
-  if (T->getAttrKind() == attr::NSReturnsRetained &&
+  if (T->getAttrKind() == AttributedType::attr_ns_returns_retained &&
       !T->getEquivalentType()->castAs<FunctionType>()
                              ->getExtInfo().getProducesResult())
     return;
 
-  if (T->getAttrKind() == attr::LifetimeBound) {
+  if (T->getAttrKind() == AttributedType::attr_lifetimebound) {
     OS << " [[clang::lifetimebound]]";
     return;
   }
 
   OS << " __attribute__((";
   switch (T->getAttrKind()) {
-#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.
+  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:
+    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 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_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 attr::NSReturnsRetained:
+  case AttributedType::attr_ns_returns_retained:
     OS << "ns_returns_retained";
     break;
 
   // FIXME: When Sema learns to form this AttributedType, avoid printing the
   // attribute again in printFunctionProtoAfter.
-  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: {
+  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: {
     OS << "pcs(";
    QualType t = T->getEquivalentType();
    while (!t->isFunctionType())
@@ -1486,12 +1517,12 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
    break;
   }
 
-  case attr::IntelOclBicc: OS << "inteloclbicc"; break;
-  case attr::PreserveMost:
+  case AttributedType::attr_inteloclbicc: OS << "inteloclbicc"; break;
+  case AttributedType::attr_preserve_most:
     OS << "preserve_most";
     break;
 
-  case attr::PreserveAll:
+  case AttributedType::attr_preserve_all:
     OS << "preserve_all";
     break;
   }
index e62728c..abdeba6 100644 (file)
@@ -5999,14 +5999,14 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
       // 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 (const auto *A = ATL.getAttrAs<LifetimeBoundAttr>()) {
+      if (ATL.getAttrKind() == AttributedType::attr_lifetimebound) {
         const auto *MD = dyn_cast<CXXMethodDecl>(FD);
         if (!MD || MD->isStatic()) {
-          S.Diag(A->getLocation(), diag::err_lifetimebound_no_object_param)
-              << !MD << A->getRange();
+          S.Diag(ATL.getAttrNameLoc(), diag::err_lifetimebound_no_object_param)
+              << !MD << ATL.getLocalSourceRange();
         } else if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) {
-          S.Diag(A->getLocation(), diag::err_lifetimebound_ctor_dtor)
-              << isa<CXXDestructorDecl>(MD) << A->getRange();
+          S.Diag(ATL.getAttrNameLoc(), diag::err_lifetimebound_ctor_dtor)
+              << isa<CXXDestructorDecl>(MD) << ATL.getLocalSourceRange();
         }
       }
     }
index baa114b..1259d25 100644 (file)
@@ -14658,15 +14658,15 @@ static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var,
   // 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::ObjCOwnership in Ty. The existence of AttributedType of kind
-    // attr::ObjCOwnership implies __autoreleasing was explicitly specified
+    // attr_objc_ownership in Ty. The existence of AttributedType of kind
+    // attr_objc_ownership 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() == attr::ObjCOwnership)
+        if (AttrTy->getAttrKind() == AttributedType::attr_objc_ownership)
           return true;
 
-        // Peel off AttributedTypes that are not of kind ObjCOwnership.
+        // Peel off AttributedTypes that are not of kind objc_ownership.
         Ty = AttrTy->getModifiedType();
       }
 
index 0d3e3d4..766f23b 100644 (file)
@@ -6360,7 +6360,7 @@ static bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD) {
   for (TypeLoc TL = TSI->getTypeLoc();
        (ATL = TL.getAsAdjusted<AttributedTypeLoc>());
        TL = ATL.getModifiedLoc()) {
-    if (ATL.getAttrAs<LifetimeBoundAttr>())
+    if (ATL.getAttrKind() == AttributedType::attr_lifetimebound)
       return true;
   }
   return false;
index ab7b83c..3aad25b 100644 (file)
@@ -2384,7 +2384,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) {
       QualType modifiedTy = resultTy;
       if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)) {
         if (*nullability == NullabilityKind::Unspecified)
-          resultTy = Context.getAttributedType(attr::TypeNonNull,
+          resultTy = Context.getAttributedType(AttributedType::attr_nonnull,
                                                modifiedTy, modifiedTy);
       }
     }
@@ -2458,7 +2458,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) {
         QualType modifiedTy = paramTy;
         if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)){
           if (*nullability == NullabilityKind::Unspecified)
-            paramTy = Context.getAttributedType(attr::TypeNullable,
+            paramTy = Context.getAttributedType(AttributedType::attr_nullable,
                                                 modifiedTy, modifiedTy);
         }
       }
index bad6616..486d8ac 100644 (file)
@@ -172,16 +172,6 @@ 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),
@@ -240,43 +230,6 @@ 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;
 
@@ -3879,32 +3832,6 @@ static bool hasOuterPointerLikeChunk(const Declarator &D, unsigned endIndex) {
   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) {
@@ -4257,8 +4184,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
                 pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(),
                 D.getDeclSpec().getEndLoc(),
                 D.getMutableDeclSpec().getAttributes())) {
-          T = state.getAttributedType(
-              createNullabilityAttr(Context, *attr, *inferNullability), T, T);
+          T = Context.getAttributedType(
+                AttributedType::getNullabilityAttrKind(*inferNullability),T,T);
+          attr->setUsedAsTypeAttr();
         }
       }
     }
@@ -5097,7 +5025,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
   if (D.isInvalidType())
     return Context.getTrivialTypeSourceInfo(T);
 
-  return GetTypeSourceInfoForDeclarator(state, T, TInfo);
+  return S.GetTypeSourceInfoForDeclarator(D, T, TInfo);
 }
 
 /// GetTypeForDeclarator - Convert the type for the specified
@@ -5233,25 +5161,131 @@ TypeSourceInfo *Sema::GetTypeForDeclaratorCast(Declarator &D, QualType FromTy) {
   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,
-                                  TypeProcessingState &State) {
-  TL.setAttr(State.takeAttrForAttributedType(TL.getTypePtr()));
+                                  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!");
 }
 
 namespace {
   class TypeSpecLocFiller : public TypeLocVisitor<TypeSpecLocFiller> {
     ASTContext &Context;
-    TypeProcessingState &State;
     const DeclSpec &DS;
 
   public:
-    TypeSpecLocFiller(ASTContext &Context, TypeProcessingState &State,
-                      const DeclSpec &DS)
-        : Context(Context), State(State), DS(DS) {}
+    TypeSpecLocFiller(ASTContext &Context, const DeclSpec &DS)
+      : Context(Context), DS(DS) {}
 
     void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
+      fillAttributedTypeLoc(TL, DS.getAttributes(), ParsedAttributesView{});
       Visit(TL.getModifiedLoc());
-      fillAttributedTypeLoc(TL, State);
     }
     void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
       Visit(TL.getUnqualifiedLoc());
@@ -5408,13 +5442,11 @@ namespace {
 
   class DeclaratorLocFiller : public TypeLocVisitor<DeclaratorLocFiller> {
     ASTContext &Context;
-    TypeProcessingState &State;
     const DeclaratorChunk &Chunk;
 
   public:
-    DeclaratorLocFiller(ASTContext &Context, TypeProcessingState &State,
-                        const DeclaratorChunk &Chunk)
-        : Context(Context), State(State), Chunk(Chunk) {}
+    DeclaratorLocFiller(ASTContext &Context, const DeclaratorChunk &Chunk)
+      : Context(Context), Chunk(Chunk) {}
 
     void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
       llvm_unreachable("qualified type locs not expected here!");
@@ -5424,7 +5456,7 @@ namespace {
     }
 
     void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
-      fillAttributedTypeLoc(TL, State);
+      fillAttributedTypeLoc(TL, Chunk.getAttrs(), ParsedAttributesView{});
     }
     void VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {
       // nothing
@@ -5581,13 +5613,10 @@ fillDependentAddressSpaceTypeLoc(DependentAddressSpaceTypeLoc DASTL,
 /// 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.
-static TypeSourceInfo *
-GetTypeSourceInfoForDeclarator(TypeProcessingState &State,
-                               QualType T, TypeSourceInfo *ReturnTypeInfo) {
-  Sema &S = State.getSema();
-  Declarator &D = State.getDeclarator();
-
-  TypeSourceInfo *TInfo = S.Context.CreateTypeSourceInfo(T);
+TypeSourceInfo *
+Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
+                                     TypeSourceInfo *ReturnTypeInfo) {
+  TypeSourceInfo *TInfo = Context.CreateTypeSourceInfo(T);
   UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc();
 
   // Handle parameter packs whose type is a pack expansion.
@@ -5597,6 +5626,7 @@ GetTypeSourceInfoForDeclarator(TypeProcessingState &State,
   }
 
   for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
+
     if (DependentAddressSpaceTypeLoc DASTL =
         CurrTL.getAs<DependentAddressSpaceTypeLoc>()) {
       fillDependentAddressSpaceTypeLoc(DASTL, D.getTypeObject(i).getAttrs());
@@ -5611,7 +5641,8 @@ GetTypeSourceInfoForDeclarator(TypeProcessingState &State,
     }
 
     while (AttributedTypeLoc TL = CurrTL.getAs<AttributedTypeLoc>()) {
-      fillAttributedTypeLoc(TL, State);
+      fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs(),
+                            D.getAttributes());
       CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
     }
 
@@ -5619,7 +5650,7 @@ GetTypeSourceInfoForDeclarator(TypeProcessingState &State,
     while (AdjustedTypeLoc TL = CurrTL.getAs<AdjustedTypeLoc>())
       CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
 
-    DeclaratorLocFiller(S.Context, State, D.getTypeObject(i)).Visit(CurrTL);
+    DeclaratorLocFiller(Context, D.getTypeObject(i)).Visit(CurrTL);
     CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
   }
 
@@ -5630,7 +5661,7 @@ GetTypeSourceInfoForDeclarator(TypeProcessingState &State,
     assert(TL.getFullDataSize() == CurrTL.getFullDataSize());
     memcpy(CurrTL.getOpaqueData(), TL.getOpaqueData(), TL.getFullDataSize());
   } else {
-    TypeSpecLocFiller(S.Context, State, D.getDeclSpec()).Visit(CurrTL);
+    TypeSpecLocFiller(Context, D.getDeclSpec()).Visit(CurrTL);
   }
 
   return TInfo;
@@ -5859,7 +5890,7 @@ static bool hasDirectOwnershipQualifier(QualType type) {
   while (true) {
     // __strong id
     if (const AttributedType *attr = dyn_cast<AttributedType>(type)) {
-      if (attr->getAttrKind() == attr::ObjCOwnership)
+      if (attr->getAttrKind() == AttributedType::attr_objc_ownership)
         return true;
 
       type = attr->getModifiedType();
@@ -6003,9 +6034,9 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
   // the coexistence problems with __unsafe_unretained.
   if (!S.getLangOpts().ObjCAutoRefCount &&
       lifetime == Qualifiers::OCL_ExplicitNone) {
-    type = state.getAttributedType(
-        createSimpleAttr<ObjCInertUnsafeUnretainedAttr>(S.Context, attr),
-        type, type);
+    type = S.Context.getAttributedType(
+                             AttributedType::attr_objc_inert_unsafe_unretained,
+                                       type, type);
     return true;
   }
 
@@ -6015,12 +6046,9 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
 
   // If we have a valid source location for the attribute, use an
   // AttributedType instead.
-  if (AttrLoc.isValid()) {
-    type = state.getAttributedType(::new (S.Context) ObjCOwnershipAttr(
-                                       attr.getRange(), S.Context, II,
-                                       attr.getAttributeSpellingListIndex()),
-                                   origType, type);
-  }
+  if (AttrLoc.isValid())
+    type = S.Context.getAttributedType(AttributedType::attr_objc_ownership,
+                                       origType, type);
 
   auto diagnoseOrDelay = [](Sema &S, SourceLocation loc,
                             unsigned diagnostic, QualType type) {
@@ -6120,10 +6148,8 @@ static bool handleObjCGCTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
 
   // Make an attributed type to preserve the source information.
   if (attr.getLoc().isValid())
-    type = state.getAttributedType(
-        ::new (S.Context) ObjCGCAttr(attr.getRange(), S.Context, II,
-                                     attr.getAttributeSpellingListIndex()),
-        origType, type);
+    type = S.Context.getAttributedType(AttributedType::attr_objc_gc,
+                                       origType, type);
 
   return true;
 }
@@ -6266,50 +6292,37 @@ namespace {
 } // end anonymous namespace
 
 static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
-                                             ParsedAttr &PAttr, QualType &Type) {
+                                             ParsedAttr &Attr, QualType &Type) {
   Sema &S = State.getSema();
 
-  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();
+  ParsedAttr::Kind Kind = Attr.getKind();
   QualType Desugared = Type;
   const AttributedType *AT = dyn_cast<AttributedType>(Type);
   while (AT) {
-    attr::Kind CurAttrKind = AT->getAttrKind();
+    AttributedType::Kind CurAttrKind = AT->getAttrKind();
 
     // You cannot specify duplicate type attributes, so if the attribute has
     // already been applied, flag it.
-    if (NewAttrKind == CurAttrKind) {
-      S.Diag(PAttr.getLoc(), diag::warn_duplicate_attribute_exact)
-        << PAttr.getName();
+    if (getAttrListKind(CurAttrKind) == Kind) {
+      S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute_exact)
+        << Attr.getName();
       return true;
     }
 
     // You cannot have both __sptr and __uptr on the same type, nor can you
     // have __ptr32 and __ptr64.
-    if ((CurAttrKind == attr::Ptr32 && NewAttrKind == attr::Ptr64) ||
-        (CurAttrKind == attr::Ptr64 && NewAttrKind == attr::Ptr32)) {
-      S.Diag(PAttr.getLoc(), diag::err_attributes_are_not_compatible)
+    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)
         << "'__ptr32'" << "'__ptr64'";
       return true;
-    } else if ((CurAttrKind == attr::SPtr && NewAttrKind == attr::UPtr) ||
-               (CurAttrKind == attr::UPtr && NewAttrKind == attr::SPtr)) {
-      S.Diag(PAttr.getLoc(), diag::err_attributes_are_not_compatible)
+    } 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)
         << "'__sptr'" << "'__uptr'";
       return true;
     }
@@ -6320,64 +6333,41 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
 
   // 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(PAttr.getLoc(), diag::err_attribute_no_member_pointers) << PAttr;
+      S.Diag(Attr.getLoc(), diag::err_attribute_no_member_pointers) << Attr;
     else
-      S.Diag(PAttr.getLoc(), diag::err_attribute_pointers_only) << PAttr << 0;
+      S.Diag(Attr.getLoc(), diag::err_attribute_pointers_only) << Attr << 0;
     return true;
   }
 
-  Type = State.getAttributedType(A, Type, Type);
-  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");
+  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;
   }
-}
 
-/// 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();
+  Type = S.Context.getAttributedType(TAK, Type, Type);
+  return false;
+}
 
-  recordNullabilitySeen(S, nullabilityLoc);
+bool Sema::checkNullabilityTypeSpecifier(QualType &type,
+                                         NullabilityKind nullability,
+                                         SourceLocation nullabilityLoc,
+                                         bool isContextSensitive,
+                                         bool allowOnArrayType) {
+  recordNullabilitySeen(*this, nullabilityLoc);
 
   // Check for existing nullability attributes on the type.
   QualType desugared = type;
@@ -6386,7 +6376,7 @@ static bool checkNullabilityTypeSpecifier(TypeProcessingState &state,
     if (auto existingNullability = attributed->getImmediateNullability()) {
       // Duplicated nullability.
       if (nullability == *existingNullability) {
-        S.Diag(nullabilityLoc, diag::warn_nullability_duplicate)
+        Diag(nullabilityLoc, diag::warn_nullability_duplicate)
           << DiagNullabilityKind(nullability, isContextSensitive)
           << FixItHint::CreateRemoval(nullabilityLoc);
 
@@ -6394,7 +6384,7 @@ static bool checkNullabilityTypeSpecifier(TypeProcessingState &state,
       }
 
       // Conflicting nullability.
-      S.Diag(nullabilityLoc, diag::err_nullability_conflicting)
+      Diag(nullabilityLoc, diag::err_nullability_conflicting)
         << DiagNullabilityKind(nullability, isContextSensitive)
         << DiagNullabilityKind(*existingNullability, false);
       return true;
@@ -6407,9 +6397,9 @@ static bool checkNullabilityTypeSpecifier(TypeProcessingState &state,
   // 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(S.Context)) {
+  if (auto existingNullability = desugared->getNullability(Context)) {
     if (nullability != *existingNullability) {
-      S.Diag(nullabilityLoc, diag::err_nullability_conflicting)
+      Diag(nullabilityLoc, diag::err_nullability_conflicting)
         << DiagNullabilityKind(nullability, isContextSensitive)
         << DiagNullabilityKind(*existingNullability, false);
 
@@ -6420,7 +6410,7 @@ static bool checkNullabilityTypeSpecifier(TypeProcessingState &state,
         if (auto typedefNullability
               = AttributedType::stripOuterNullability(underlyingType)) {
           if (*typedefNullability == *existingNullability) {
-            S.Diag(typedefDecl->getLocation(), diag::note_nullability_here)
+            Diag(typedefDecl->getLocation(), diag::note_nullability_here)
               << DiagNullabilityKind(*existingNullability, false);
           }
         }
@@ -6433,7 +6423,7 @@ static bool checkNullabilityTypeSpecifier(TypeProcessingState &state,
   // If this definitely isn't a pointer type, reject the specifier.
   if (!desugared->canHaveNullability() &&
       !(allowOnArrayType && desugared->isArrayType())) {
-    S.Diag(nullabilityLoc, diag::err_nullability_nonpointer)
+    Diag(nullabilityLoc, diag::err_nullability_nonpointer)
       << DiagNullabilityKind(nullability, isContextSensitive) << type;
     return true;
   }
@@ -6451,10 +6441,10 @@ static bool checkNullabilityTypeSpecifier(TypeProcessingState &state,
     if (pointeeType->isAnyPointerType() ||
         pointeeType->isObjCObjectPointerType() ||
         pointeeType->isMemberPointerType()) {
-      S.Diag(nullabilityLoc, diag::err_nullability_cs_multilevel)
+      Diag(nullabilityLoc, diag::err_nullability_cs_multilevel)
         << DiagNullabilityKind(nullability, true)
         << type;
-      S.Diag(nullabilityLoc, diag::note_nullability_type_specifier)
+      Diag(nullabilityLoc, diag::note_nullability_type_specifier)
         << DiagNullabilityKind(nullability, false)
         << type
         << FixItHint::CreateReplacement(nullabilityLoc,
@@ -6464,21 +6454,16 @@ static bool checkNullabilityTypeSpecifier(TypeProcessingState &state,
   }
 
   // Form the attributed type.
-  type = state.getAttributedType(
-      createNullabilityAttr(S.Context, attr, nullability), type, type);
+  type = Context.getAttributedType(
+           AttributedType::getNullabilityAttrKind(nullability), type, type);
   return false;
 }
 
-/// 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();
-
+bool Sema::checkObjCKindOfType(QualType &type, SourceLocation loc) {
   if (isa<ObjCTypeParamType>(type)) {
     // Build the attributed type to record where __kindof occurred.
-    type = state.getAttributedType(
-        createSimpleAttr<ObjCKindOfAttr>(S.Context, attr), type, type);
+    type = Context.getAttributedType(AttributedType::attr_objc_kindof,
+                                     type, type);
     return false;
   }
 
@@ -6490,7 +6475,7 @@ static bool checkObjCKindOfType(TypeProcessingState &state, QualType &type,
   // If not, we can't apply __kindof.
   if (!objType) {
     // FIXME: Handle dependent types that aren't yet object types.
-    S.Diag(attr.getLoc(), diag::err_objc_kindof_nonobject)
+    Diag(loc, diag::err_objc_kindof_nonobject)
       << type;
     return true;
   }
@@ -6498,31 +6483,45 @@ static bool checkObjCKindOfType(TypeProcessingState &state, QualType &type,
   // 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 = S.Context.getObjCObjectType(
+  QualType equivType = 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 = 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);
+    equivType = Context.getObjCObjectPointerType(equivType);
+    if (auto nullability = type->getNullability(Context)) {
+      auto attrKind = AttributedType::getNullabilityAttrKind(*nullability);
+      equivType = Context.getAttributedType(attrKind, equivType, equivType);
     }
   }
 
   // Build the attributed type to record where __kindof occurred.
-  type = state.getAttributedType(
-      createSimpleAttr<ObjCKindOfAttr>(S.Context, attr), type, equivType);
+  type = Context.getAttributedType(AttributedType::attr_objc_kindof,
+                                   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.
@@ -6610,27 +6609,27 @@ static bool distributeNullabilityTypeAttr(TypeProcessingState &state,
   return false;
 }
 
-static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) {
+static AttributedType::Kind getCCTypeAttrKind(ParsedAttr &Attr) {
   assert(!Attr.isInvalid());
   switch (Attr.getKind()) {
   default:
     llvm_unreachable("not a calling convention attribute");
   case ParsedAttr::AT_CDecl:
-    return createSimpleAttr<CDeclAttr>(Ctx, Attr);
+    return AttributedType::attr_cdecl;
   case ParsedAttr::AT_FastCall:
-    return createSimpleAttr<FastCallAttr>(Ctx, Attr);
+    return AttributedType::attr_fastcall;
   case ParsedAttr::AT_StdCall:
-    return createSimpleAttr<StdCallAttr>(Ctx, Attr);
+    return AttributedType::attr_stdcall;
   case ParsedAttr::AT_ThisCall:
-    return createSimpleAttr<ThisCallAttr>(Ctx, Attr);
+    return AttributedType::attr_thiscall;
   case ParsedAttr::AT_RegCall:
-    return createSimpleAttr<RegCallAttr>(Ctx, Attr);
+    return AttributedType::attr_regcall;
   case ParsedAttr::AT_Pascal:
-    return createSimpleAttr<PascalAttr>(Ctx, Attr);
+    return AttributedType::attr_pascal;
   case ParsedAttr::AT_SwiftCall:
-    return createSimpleAttr<SwiftCallAttr>(Ctx, Attr);
+    return AttributedType::attr_swiftcall;
   case ParsedAttr::AT_VectorCall:
-    return createSimpleAttr<VectorCallAttr>(Ctx, Attr);
+    return AttributedType::attr_vectorcall;
   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,
@@ -6640,22 +6639,20 @@ static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) {
       Str = cast<StringLiteral>(Attr.getArgAsExpr(0))->getString();
     else
       Str = Attr.getArgAsIdent(0)->Ident->getName();
-    PcsAttr::PCSType Type;
-    if (!PcsAttr::ConvertStrToPCSType(Str, Type))
-      llvm_unreachable("already validated the attribute");
-    return ::new (Ctx) PcsAttr(Attr.getRange(), Ctx, Type,
-                               Attr.getAttributeSpellingListIndex());
+    return llvm::StringSwitch<AttributedType::Kind>(Str)
+        .Case("aapcs", AttributedType::attr_pcs)
+        .Case("aapcs-vfp", AttributedType::attr_pcs_vfp);
   }
   case ParsedAttr::AT_IntelOclBicc:
-    return createSimpleAttr<IntelOclBiccAttr>(Ctx, Attr);
+    return AttributedType::attr_inteloclbicc;
   case ParsedAttr::AT_MSABI:
-    return createSimpleAttr<MSABIAttr>(Ctx, Attr);
+    return AttributedType::attr_ms_abi;
   case ParsedAttr::AT_SysVABI:
-    return createSimpleAttr<SysVABIAttr>(Ctx, Attr);
+    return AttributedType::attr_sysv_abi;
   case ParsedAttr::AT_PreserveMost:
-    return createSimpleAttr<PreserveMostAttr>(Ctx, Attr);
+    return AttributedType::attr_preserve_most;
   case ParsedAttr::AT_PreserveAll:
-    return createSimpleAttr<PreserveAllAttr>(Ctx, Attr);
+    return AttributedType::attr_preserve_all;
   }
   llvm_unreachable("unexpected attribute kind!");
 }
@@ -6703,9 +6700,8 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
         = unwrapped.get()->getExtInfo().withProducesResult(true);
       type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
     }
-    type = state.getAttributedType(
-        createSimpleAttr<NSReturnsRetainedAttr>(S.Context, attr),
-        origType, type);
+    type = S.Context.getAttributedType(AttributedType::attr_ns_returns_retained,
+                                       origType, type);
     return true;
   }
 
@@ -6780,12 +6776,13 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
 
   const FunctionType *fn = unwrapped.get();
   CallingConv CCOld = fn->getCallConv();
-  Attr *CCAttr = getCCTypeAttr(S.Context, attr);
+  AttributedType::Kind CCAttrKind = getCCTypeAttrKind(attr);
 
   if (CCOld != CC) {
     // Error out on when there's already an attribute on the type
     // and the CCs don't match.
-    if (const AttributedType *AT = S.getCallingConvAttributedType(type)) {
+    const AttributedType *AT = S.getCallingConvAttributedType(type);
+    if (AT && AT->getAttrKind() != CCAttrKind) {
       S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
         << FunctionType::getNameForCallConv(CC)
         << FunctionType::getNameForCallConv(CCOld);
@@ -6839,7 +6836,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
     Equivalent =
       unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
   }
-  type = state.getAttributedType(CCAttr, type, Equivalent);
+  type = S.Context.getAttributedType(CCAttrKind, type, Equivalent);
   return true;
 }
 
@@ -7195,15 +7192,14 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State,
   T = State.getSema().Context.getAddrSpaceQualType(T, ImpAddr);
 }
 
-static void HandleLifetimeBoundAttr(TypeProcessingState &State,
-                                    QualType &CurType,
-                                    ParsedAttr &Attr) {
-  if (State.getDeclarator().isDeclarationOfFunction()) {
-    CurType = State.getAttributedType(
-        createSimpleAttr<LifetimeBoundAttr>(State.getSema().Context, Attr),
-        CurType, CurType);
+static void HandleLifetimeBoundAttr(QualType &CurType,
+                                    const ParsedAttr &Attr,
+                                    Sema &S, Declarator &D) {
+  if (D.isDeclarationOfFunction()) {
+    CurType = S.Context.getAttributedType(AttributedType::attr_lifetimebound,
+                                          CurType, CurType);
   } else {
-    Attr.diagnoseAppertainsTo(State.getSema(), nullptr);
+    Attr.diagnoseAppertainsTo(S, nullptr);
   }
 }
 
@@ -7313,8 +7309,11 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
       attr.setUsedAsTypeAttr();
       break;
     case ParsedAttr::AT_LifetimeBound:
-      if (TAL == TAL_DeclChunk)
-        HandleLifetimeBoundAttr(state, type, attr);
+      if (TAL == TAL_DeclChunk) {
+        HandleLifetimeBoundAttr(type, attr, state.getSema(),
+                                state.getDeclarator());
+        attr.setUsedAsTypeAttr();
+      }
       break;
 
     MS_TYPE_ATTRS_CASELIST:
@@ -7338,10 +7337,11 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
         bool allowOnArrayType =
             state.getDeclarator().isPrototypeContext() &&
             !hasOuterPointerLikeChunk(state.getDeclarator(), endIndex);
-        if (checkNullabilityTypeSpecifier(
-              state, 
+        if (state.getSema().checkNullabilityTypeSpecifier(
               type,
-              attr,
+              mapNullabilityAttrKind(attr.getKind()),
+              attr.getLoc(),
+              attr.isContextSensitiveKeywordAttribute(),
               allowOnArrayType)) {
           attr.setInvalid();
         }
@@ -7368,8 +7368,9 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
       }
 
       // Apply it regardless.
-      if (checkObjCKindOfType(state, type, attr))
+      if (state.getSema().checkObjCKindOfType(type, attr.getLoc()))
         attr.setInvalid();
+      attr.setUsedAsTypeAttr();
       break;
 
     FUNCTION_TYPE_ATTRS_CASELIST:
index 98256d6..d680e6b 100644 (file)
@@ -6058,11 +6058,6 @@ QualType TreeTransform<Derived>::TransformAttributedType(
   if (modifiedType.isNull())
     return QualType();
 
-  const Attr *oldAttr = TL.getAttr();
-  const Attr *newAttr = getDerived().TransformAttr(oldAttr);
-  if (!newAttr)
-    return QualType();
-
   QualType result = TL.getType();
 
   // FIXME: dependent operand expressions?
@@ -6079,20 +6074,26 @@ QualType TreeTransform<Derived>::TransformAttributedType(
     // type sugar, and therefore cannot be diagnosed in any other way.
     if (auto nullability = oldType->getImmediateNullability()) {
       if (!modifiedType->canHaveNullability()) {
-        SemaRef.Diag(TL.getAttr()->getLocation(),
-                     diag::err_nullability_nonpointer)
-            << DiagNullabilityKind(*nullability, false) << modifiedType;
+        SemaRef.Diag(TL.getAttrNameLoc(), diag::err_nullability_nonpointer)
+          << DiagNullabilityKind(*nullability, false) << modifiedType;
         return QualType();
       }
     }
 
-    result = SemaRef.Context.getAttributedType(newAttr->getKind(),
+    result = SemaRef.Context.getAttributedType(oldType->getAttrKind(),
                                                modifiedType,
                                                equivalentType);
   }
 
   AttributedTypeLoc newTL = TLB.push<AttributedTypeLoc>(result);
-  newTL.setAttr(newAttr);
+  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());
+
   return result;
 }
 
index a9acf4e..a6f624e 100644 (file)
@@ -6455,10 +6455,6 @@ class TypeLocReader : public TypeLocVisitor<TypeLocReader> {
     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)
@@ -6650,7 +6646,20 @@ void TypeLocReader::VisitEnumTypeLoc(EnumTypeLoc TL) {
 }
 
 void TypeLocReader::VisitAttributedTypeLoc(AttributedTypeLoc TL) {
-  TL.setAttr(ReadAttr());
+  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());
 }
 
 void TypeLocReader::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
index 8e7dc7c..2b8cfac 100644 (file)
@@ -2648,72 +2648,19 @@ void ASTDeclReader::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) {
 // Attribute Reading
 //===----------------------------------------------------------------------===//
 
-namespace {
-class AttrReader {
-  ModuleFile *F;
-  ASTReader *Reader;
-  const ASTReader::RecordData &Record;
-  unsigned &Idx;
-
-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);
-  }
-
-  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();
+/// 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();
 
 #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());
+    assert(New && "Unable to decode attribute?");
+    Attrs.push_back(New);
+  }
 }
 
 //===----------------------------------------------------------------------===//
index f2fde2c..ea3a75d 100644 (file)
@@ -770,7 +770,19 @@ void TypeLocWriter::VisitEnumTypeLoc(EnumTypeLoc TL) {
 }
 
 void TypeLocWriter::VisitAttributedTypeLoc(AttributedTypeLoc TL) {
-  Record.AddAttr(TL.getAttr());
+  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());
+  }
 }
 
 void TypeLocWriter::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
@@ -4469,21 +4481,16 @@ void ASTWriter::WriteModuleFileExtension(Sema &SemaRef,
 // General Serialization Routines
 //===----------------------------------------------------------------------===//
 
-void ASTRecordWriter::AddAttr(const Attr *A) {
+/// Emit the list of attributes to the specified record.
+void ASTRecordWriter::AddAttributes(ArrayRef<const Attr *> Attrs) {
   auto &Record = *this;
-  if (!A)
-    return Record.push_back(0);
-  Record.push_back(A->getKind() + 1); // FIXME: stable encoding, target attrs
-  Record.AddSourceRange(A->getRange());
+  Record.push_back(Attrs.size());
+  for (const auto *A : Attrs) {
+    Record.push_back(A->getKind()); // 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) {
index e73a22a..9d1ee75 100644 (file)
@@ -103,9 +103,9 @@ Nullability getNullabilityAnnotation(QualType Type) {
   const auto *AttrType = Type->getAs<AttributedType>();
   if (!AttrType)
     return Nullability::Unspecified;
-  if (AttrType->getAttrKind() == attr::TypeNullable)
+  if (AttrType->getAttrKind() == AttributedType::attr_nullable)
     return Nullability::Nullable;
-  else if (AttrType->getAttrKind() == attr::TypeNonNull)
+  else if (AttrType->getAttrKind() == AttributedType::attr_nonnull)
     return Nullability::Nonnull;
   return Nullability::Unspecified;
 }
index 5c6c7c3..71e003f 100644 (file)
@@ -2470,10 +2470,8 @@ 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" }
 };