diff options
author | John McCall <rjmccall@apple.com> | 2010-08-25 02:50:31 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-08-25 02:50:31 +0000 |
commit | a8f28da6265950eea768f7e4ade15e4ebaddd56f (patch) | |
tree | 37bc9b569d8c54aad830b105c2aa4e79a1afbfd4 | |
parent | 911093e535ad16602b0a387b36039eeb5da685b4 (diff) |
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
-rw-r--r-- | lib/CodeGen/CGExprAgg.cpp | 12 | ||||
-rw-r--r-- | test/CodeGenCXX/volatile.cpp | 35 |
2 files changed, 45 insertions, 2 deletions
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 1b6254f192..89fea398d3 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -192,10 +192,18 @@ void AggExprEmitter::EmitGCMove(const Expr *E, RValue Src) { void AggExprEmitter::EmitFinalDestCopy(const Expr *E, RValue Src, bool Ignore) { assert(Src.isAggregate() && "value must be aggregate value!"); - // If the result is ignored, don't copy from the value. + // If DestPtr is null, then we're evaluating an aggregate expression + // in a context (like an expression statement) that doesn't care + // about the result. C says that an lvalue-to-rvalue conversion is + // performed in these cases; C++ says that it is not. In either + // case, we don't actually need to do anything unless the value is + // volatile. if (DestPtr == 0) { - if (!Src.isVolatileQualified() || (IgnoreResult && Ignore)) + if (!Src.isVolatileQualified() || + CGF.CGM.getLangOptions().CPlusPlus || + (IgnoreResult && Ignore)) return; + // If the source is volatile, we must read from it; to do that, we need // some place to put it. DestPtr = CGF.CreateMemTemp(E->getType(), "agg.tmp"); diff --git a/test/CodeGenCXX/volatile.cpp b/test/CodeGenCXX/volatile.cpp new file mode 100644 index 0000000000..58f433f1e1 --- /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; + } +} |