r340215 - Model type attributes as regular Attrs.

Mikael Holmén via cfe-commits cfe-commits at lists.llvm.org
Mon Aug 20 23:11:43 PDT 2018


Hi,

I get a warning with this:

[1/16] Building CXX object 
tools/clang/lib/Sema/CMakeFiles/clangSema.dir/SemaType.cpp.o
../tools/clang/lib/Sema/SemaType.cpp: In function 'bool 
handleFunctionTypeAttr({anonymous}::TypeProcessingState&, 
clang::ParsedAttr&, clang::QualType&)':
../tools/clang/lib/Sema/SemaType.cpp:6788:31: warning: unused variable 
'AT' [-Wunused-variable]
      if (const AttributedType *AT = S.getCallingConvAttributedType(type)) {
                                ^
/Mikael

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


More information about the cfe-commits mailing list