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.

llvm-svn: 340215
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 0a40ee5..098abf2 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -3876,7 +3876,7 @@
   return QualType(newType, 0);
 }
 
-QualType ASTContext::getAttributedType(AttributedType::Kind attrKind,
+QualType ASTContext::getAttributedType(attr::Kind attrKind,
                                        QualType modifiedType,
                                        QualType equivalentType) {
   llvm::FoldingSetNodeID id;
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 7dc01b2..2e1aed2 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -592,28 +592,6 @@
   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 @@
   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 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:
+  case attr::ObjCGC:
+  case attr::ObjCOwnership:
+  case attr::ObjCInertUnsafeUnretained:
+  case attr::TypeNonNull:
+  case attr::TypeNullable:
+  case attr::TypeNullUnspecified:
+  case 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:
+  // 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 @@
   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;
-    }
+    if (auto Nullability = AT->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;
-
-    type = desugared;
-  } while (true);
+    Type = AT->getEquivalentType();
+  }
+  return None;
 }
 
 bool Type::canHaveNullability(bool ResultIfUnknown) const {
@@ -3841,12 +3777,13 @@
   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;
 }
diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp
index e4fd6f1..b6dc679 100644
--- a/clang/lib/AST/TypeLoc.cpp
+++ b/clang/lib/AST/TypeLoc.cpp
@@ -404,11 +404,11 @@
 }
 
 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 {};
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 1cb5ff4..d86849f 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1354,12 +1354,14 @@
 
 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 @@
   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::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 @@
 
   // 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 @@
    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;
   }