commit 09652b2576206a5b709e6ea70cd2c4fe43c53d35
Author: Anastasia Stulova <anastasia.stulova@arm.com>
Date:   Tue Sep 29 17:22:22 2015 +0100

    test

diff --git a/lib/CodeGen/CGAtomic.cpp b/lib/CodeGen/CGAtomic.cpp
index 7c9f3da..ee40396 100644
--- a/lib/CodeGen/CGAtomic.cpp
+++ b/lib/CodeGen/CGAtomic.cpp
@@ -1023,8 +1023,12 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, Address Dest) {
   Address OrigDest = GetDest();
   Ptr = Builder.CreateBitCast(
       Ptr, ITy->getPointerTo(Ptr.getType()->getPointerAddressSpace()));
-  if (Val1.isValid()) Val1 = Builder.CreateBitCast(Val1, ITy->getPointerTo());
-  if (Val2.isValid()) Val2 = Builder.CreateBitCast(Val2, ITy->getPointerTo());
+  if (Val1.isValid())
+    Val1 = Builder.CreateBitCast(
+        Val1, ITy->getPointerTo(Val1.getType()->getPointerAddressSpace()));
+  if (Val2.isValid())
+    Val2 = Builder.CreateBitCast(
+        Val2, ITy->getPointerTo(Val2.getType()->getPointerAddressSpace()));
   if (Dest.isValid() && !E->isCmpXChg())
     Dest = Builder.CreateBitCast(Dest, ITy->getPointerTo());
 
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index ae7f6d6..8362327 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -1735,8 +1735,17 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult,
           Ty = ByValType;
         else if (Form == Arithmetic)
           Ty = Context.getPointerDiffType();
-        else
-          Ty = Context.getPointerType(ValType.getUnqualifiedType());
+        else {
+          Expr *ValArg = TheCall->getArg(i);
+          unsigned AS = 0;
+          // Keep address space of non-atomic pointer type.
+          if (const PointerType *PtrTy =
+                  ValArg->getType()->getAs<PointerType>()) {
+            AS = PtrTy->getPointeeType().getAddressSpace();
+          }
+          Ty = Context.getPointerType(
+              Context.getAddrSpaceQualType(ValType.getUnqualifiedType(), AS));
+        }
         break;
       case 2:
         // The third argument to compare_exchange / GNU exchange is a
diff --git a/test/CodeGen/atomic-ops.c b/test/CodeGen/atomic-ops.c
index d8f7d28..129d5dd 100644
--- a/test/CodeGen/atomic-ops.c
+++ b/test/CodeGen/atomic-ops.c
@@ -450,8 +450,9 @@ void failureOrder(_Atomic(int) *ptr, int *ptr2) {
   // CHECK: cmpxchg weak i32* {{%[0-9A-Za-z._]+}}, i32 {{%[0-9A-Za-z._]+}}, i32 {{%[0-9A-Za-z_.]+}} seq_cst
 }
 
+#define _AS1 __attribute__((address_space(1)))
 // CHECK-LABEL: @generalFailureOrder
-void generalFailureOrder(_Atomic(int) *ptr, int *ptr2, int success, int fail) {
+void generalFailureOrder(_Atomic(int) *ptr, int _AS1 *ptr2, int success, int fail) {
   __c11_atomic_compare_exchange_strong(ptr, ptr2, 42, success, fail);
   // CHECK: switch i32 {{.*}}, label %[[MONOTONIC:[0-9a-zA-Z._]+]] [
   // CHECK-NEXT: i32 1, label %[[ACQUIRE:[0-9a-zA-Z._]+]]
diff --git a/test/Sema/atomic-ops.c b/test/Sema/atomic-ops.c
index 71eaaa8..de6315e 100644
--- a/test/Sema/atomic-ops.c
+++ b/test/Sema/atomic-ops.c
@@ -85,6 +85,9 @@ _Static_assert(__atomic_always_lock_free(4, &i64), "");
 _Static_assert(!__atomic_always_lock_free(8, &i32), "");
 _Static_assert(__atomic_always_lock_free(8, &i64), "");
 
+#define _AS1 __attribute__((address_space(1)))
+#define _AS2 __attribute__((address_space(2)))
+
 void f(_Atomic(int) *i, _Atomic(int*) *p, _Atomic(float) *d,
        int *I, int **P, float *D, struct S *s1, struct S *s2) {
   __c11_atomic_init(I, 5); // expected-error {{pointer to _Atomic}}
@@ -164,6 +167,9 @@ void f(_Atomic(int) *i, _Atomic(int*) *p, _Atomic(float) *d,
   _Bool cmpexch_8 = __atomic_compare_exchange(I, P, I, 0, memory_order_seq_cst, memory_order_seq_cst); // expected-warning {{; dereference with *}}
   _Bool cmpexch_9 = __atomic_compare_exchange(I, I, I, 0, memory_order_seq_cst, memory_order_seq_cst);
 
+  // Pointers to different address spaces are allowed.
+  _Bool cmpexch_10 = __c11_atomic_compare_exchange_strong((_Atomic int _AS1 *)0x308, (int _AS2 *)0x309, 1, memory_order_seq_cst, memory_order_seq_cst);
+
   const volatile int flag_k = 0;
   volatile int flag = 0;
   (void)(int)__atomic_test_and_set(&flag_k, memory_order_seq_cst); // expected-warning {{passing 'const volatile int *' to parameter of type 'volatile void *'}}
