[Sema] Iteratively strip sugar when removing address spaces.

ASTContext::removeAddrSpaceQualType does not properly deal
with sugar. QualTypes derive their ASes from the AS on the
canonical type, not the type itself. However,
removeAddrSpaceQualType only strips the outermost qualifiers,
which means that it can fail to remove addrspace qualifiers
if there is sugar in the way.

Change the function to desugar types until the address space
really no longer exists on the corresponding QualType. This
should guarantee the removal of the address space.

This fixes the erroneous behavior in D62574.

Reviewed By: rjmccall, svenvh

Differential Revision: https://reviews.llvm.org/D83325
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 7947de3..4d708d5 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -2934,14 +2934,27 @@
 }
 
 QualType ASTContext::removeAddrSpaceQualType(QualType T) const {
+  // If the type is not qualified with an address space, just return it
+  // immediately.
+  if (!T.hasAddressSpace())
+    return T;
+
   // If we are composing extended qualifiers together, merge together
   // into one ExtQuals node.
   QualifierCollector Quals;
-  const Type *TypeNode = Quals.strip(T);
+  const Type *TypeNode;
 
-  // If the qualifier doesn't have an address space just return it.
-  if (!Quals.hasAddressSpace())
-    return T;
+  while (T.hasAddressSpace()) {
+    TypeNode = Quals.strip(T);
+
+    // If the type no longer has an address space after stripping qualifiers,
+    // jump out.
+    if (!QualType(TypeNode, 0).hasAddressSpace())
+      break;
+
+    // There might be sugar in the way. Strip it and try again.
+    T = T.getSingleStepDesugaredType(*this);
+  }
 
   Quals.removeAddressSpace();
 
diff --git a/clang/test/CodeGenCXX/address-space-cast.cpp b/clang/test/CodeGenCXX/address-space-cast.cpp
index e0cf3c1..7b0792d 100644
--- a/clang/test/CodeGenCXX/address-space-cast.cpp
+++ b/clang/test/CodeGenCXX/address-space-cast.cpp
@@ -6,6 +6,16 @@
 void func_pvoid(__private__ void *x);
 void func_pint(__private__ int *x);
 
+class Base {
+};
+
+class Derived : public Base {
+};
+
+void fn(Derived *p) {
+  __private__ Base *b = (__private__ Base *)p;
+}
+
 void test_cast(char *gen_char_ptr, void *gen_void_ptr, int *gen_int_ptr) {
   // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)*
   // CHECK-NEXT: store i8 addrspace(5)* %[[cast]]