diff options
Diffstat (limited to 'test/CodeGenCXX/bitfield.cpp')
-rw-r--r-- | test/CodeGenCXX/bitfield.cpp | 58 |
1 files changed, 55 insertions, 3 deletions
diff --git a/test/CodeGenCXX/bitfield.cpp b/test/CodeGenCXX/bitfield.cpp index 2c454b0c072c..fafeffe1ed23 100644 --- a/test/CodeGenCXX/bitfield.cpp +++ b/test/CodeGenCXX/bitfield.cpp @@ -298,7 +298,7 @@ namespace N4 { #endif unsigned read(Base* s) { // FIXME: We should widen this load as long as the function isn't being - // instrumented by thread-sanitizer. + // instrumented by ThreadSanitizer. // // CHECK-X86-64-LABEL: define i32 @_ZN2N44read // CHECK-X86-64: %[[gep:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1 @@ -378,8 +378,8 @@ namespace N6 { // Zero-length bitfields partition the memory locations of bitfields for the // purposes of the memory model. That means stores must not span zero-length // bitfields and loads may only span them when we are not instrumenting with - // thread sanitizer. - // FIXME: We currently don't widen loads even without thread sanitizer, even + // ThreadSanitizer. + // FIXME: We currently don't widen loads even without ThreadSanitizer, even // though we could. struct S { unsigned b1 : 24; @@ -426,3 +426,55 @@ namespace N6 { s->b2 = x; } } + +namespace N7 { + // Similar to N4 except that this adds a virtual base to the picture. (PR18430) + // Do NOT widen loads and stores to bitfields into padding at the end of + // a class which might end up with members inside of it when inside a derived + // class. + struct B1 { + virtual void f(); + unsigned b1 : 24; + }; + struct B2 : virtual B1 { + virtual ~B2(); + unsigned b : 24; + }; + // Imagine some other translation unit introduces: +#if 0 + struct Derived : public B2 { + char c; + }; +#endif + unsigned read(B2* s) { + // FIXME: We should widen this load as long as the function isn't being + // instrumented by ThreadSanitizer. + // + // CHECK-X86-64-LABEL: define i32 @_ZN2N74read + // CHECK-X86-64: %[[gep:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1 + // CHECK-X86-64: %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24* + // CHECK-X86-64: %[[val:.*]] = load i24* %[[ptr]] + // CHECK-X86-64: %[[ext:.*]] = zext i24 %[[val]] to i32 + // CHECK-X86-64: ret i32 %[[ext]] + // CHECK-PPC64-LABEL: define zeroext i32 @_ZN2N74read + // CHECK-PPC64: %[[gep:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1 + // CHECK-PPC64: %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24* + // CHECK-PPC64: %[[val:.*]] = load i24* %[[ptr]] + // CHECK-PPC64: %[[ext:.*]] = zext i24 %[[val]] to i32 + // CHECK-PPC64: ret i32 %[[ext]] + return s->b; + } + void write(B2* s, unsigned x) { + // CHECK-X86-64-LABEL: define void @_ZN2N75write + // CHECK-X86-64: %[[gep:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1 + // CHECK-X86-64: %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24* + // CHECK-X86-64: %[[new:.*]] = trunc i32 %{{.*}} to i24 + // CHECK-X86-64: store i24 %[[new]], i24* %[[ptr]] + // CHECK-PPC64-LABEL: define void @_ZN2N75write + // CHECK-PPC64: %[[gep:.*]] = getelementptr inbounds {{.*}}* %{{.*}}, i32 0, i32 1 + // CHECK-PPC64: %[[ptr:.*]] = bitcast [3 x i8]* %[[gep]] to i24* + // CHECK-PPC64: %[[new:.*]] = trunc i32 %{{.*}} to i24 + // CHECK-PPC64: store i24 %[[new]], i24* %[[ptr]] + s->b = x; + } +} |