Expression statements undergo lvalue-to-rvalue conversion in C,
but not in C++, so don't emit aggregate loads of volatile references
in null context in C++.  Happens to have been caught by an assertion.
We do not get the scalar case right.  Volatiles are really broken.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112019 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/CodeGenCXX/volatile.cpp b/test/CodeGenCXX/volatile.cpp
new file mode 100644
index 0000000..58f433f
--- /dev/null
+++ b/test/CodeGenCXX/volatile.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+
+// Check that IR gen doesn't try to do an lvalue-to-rvalue conversion
+// on a volatile reference result.  rdar://problem/8338198
+namespace test0 {
+  struct A {
+    A(const A& t);
+    A& operator=(const A& t);
+    volatile A& operator=(const volatile A& t) volatile;
+  };
+
+  volatile A *array;
+
+  // CHECK: define void @_ZN5test04testENS_1AE(
+  void test(A t) {
+    // CHECK:      [[ARR:%.*]] = load [[A:%.*]]** @_ZN5test05arrayE, align 8
+    // CHECK-NEXT: [[IDX:%.*]] = getelementptr inbounds [[A]]* [[ARR]], i64 0
+    // CHECK-NEXT: [[TMP:%.*]] = call [[A]]* @_ZNV5test01AaSERVKS0_([[A]]* [[IDX]], [[A]]* [[T:%.*]])
+    // CHECK-NEXT: ret void
+    array[0] = t;
+  }
+}
+
+namespace test1 {
+  volatile int *x;
+
+  // CHECK: define void @_ZN5test14testEv()
+  void test() {
+    // CHECK:      [[TMP:%.*]] = load i32** @_ZN5test11xE, align 8
+    // *** FIXME: no! bad! should not be loaded! ***
+    // CHECK-NEXT: [[TMP1:%.*]] = volatile load i32* [[TMP]]
+    // CHECK-NEXT: ret void
+    *x;
+  }
+}