From: Douglas Gregor Date: Thu, 12 Apr 2012 20:42:30 +0000 (+0000) Subject: Fix some i1/i8 confusion within _Atomic(bool) in IR generation, both X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=47bfcca2d6972d98a1b25239cd1aa658b60680e2;p=clang Fix some i1/i8 confusion within _Atomic(bool) in IR generation, both in general (such an atomic has boolean representation) and specifically for IR generation of __c11_atomic_init. The latter also means actually using initialization semantics for this initialization, rather than just creating a store. On a related note, make sure we actually put in non-atomic-to-atomic conversions when performing an implicit conversion sequence. IR generation is far too kind here, but we still want the ASTs to make sense. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154612 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 147e7276bc..0c33fb5371 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -867,6 +867,9 @@ static bool hasBooleanRepresentation(QualType Ty) { if (const EnumType *ET = Ty->getAs()) return ET->getDecl()->getIntegerType()->isBooleanType(); + if (const AtomicType *AT = Ty->getAs()) + return hasBooleanRepresentation(AT->getValueType()); + return false; } @@ -1227,7 +1230,7 @@ void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst, // Get the source value, truncated to the width of the bit-field. llvm::Value *SrcVal = Src.getScalarVal(); - if (Dst.getType()->isBooleanType()) + if (hasBooleanRepresentation(Dst.getType())) SrcVal = Builder.CreateIntCast(SrcVal, ResLTy, /*IsSigned=*/false); SrcVal = Builder.CreateAnd(SrcVal, llvm::APInt::getLowBitsSet(ResSizeInBits, @@ -2843,10 +2846,11 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) { if (E->getOp() == AtomicExpr::AO__c11_atomic_init) { assert(!Dest && "Init does not return a value"); if (!hasAggregateLLVMType(E->getVal1()->getType())) { - llvm::StoreInst *Store = - Builder.CreateStore(EmitScalarExpr(E->getVal1()), Ptr); - Store->setAlignment(Size); - Store->setVolatile(E->isVolatile()); + QualType PointeeType + = E->getPtr()->getType()->getAs()->getPointeeType(); + EmitScalarInit(EmitScalarExpr(E->getVal1()), + LValue::MakeAddr(Ptr, PointeeType, alignChars, + getContext())); } else if (E->getType()->isAnyComplexType()) { EmitComplexExprIntoAddr(E->getVal1(), Ptr, E->isVolatile()); } else { diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp index b47da73c1d..41fd536b5c 100644 --- a/lib/CodeGen/CodeGenTypes.cpp +++ b/lib/CodeGen/CodeGenTypes.cpp @@ -556,7 +556,7 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { } case Type::Atomic: { - ResultType = ConvertTypeForMem(cast(Ty)->getValueType()); + ResultType = ConvertType(cast(Ty)->getValueType()); break; } } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 41f2116600..31a8115f0b 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2765,6 +2765,13 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, llvm_unreachable("Improper third standard conversion"); } + // If this conversion sequence involved a scalar -> atomic conversion, perform + // that conversion now. + if (const AtomicType *ToAtomic = ToType->getAs()) + if (Context.hasSameType(ToAtomic->getValueType(), From->getType())) + From = ImpCastExprToType(From, ToType, CK_NonAtomicToAtomic, VK_RValue, 0, + CCK).take(); + return Owned(From); } diff --git a/test/CodeGenCXX/atomicinit.cpp b/test/CodeGenCXX/atomicinit.cpp index 20e46131df..38d012e6a9 100644 --- a/test/CodeGenCXX/atomicinit.cpp +++ b/test/CodeGenCXX/atomicinit.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - -triple=i686-apple-darwin9 | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -O1 -o - -triple=i686-apple-darwin9 | FileCheck %s struct A { _Atomic(int) i; A(int j); @@ -21,5 +21,28 @@ _Atomic(B) b; // CHECK: define void @_Z11atomic_initR1Ai void atomic_init(A& a, int i) { // CHECK-NOT: atomic + // CHECK: tail call void @_ZN1BC1Ei __c11_atomic_init(&b, B(i)); + // CHECK-NEXT: ret void } + +// CHECK: define void @_Z16atomic_init_boolPU7_Atomicbb +void atomic_init_bool(_Atomic(bool) *ab, bool b) { + // CHECK-NOT: atomic + // CHECK: {{zext i1.*to i8}} + // CHECK-NEXT: store i8 + __c11_atomic_init(ab, b); + // CHECK-NEXT: ret void +} + +struct AtomicBoolMember { + _Atomic(bool) ab; + AtomicBoolMember(bool b); +}; + +// CHECK: define void @_ZN16AtomicBoolMemberC2Eb +// CHECK: {{zext i1.*to i8}} +// CHECK-NEXT: store i8 +// CHECK-NEXT: ret void +AtomicBoolMember::AtomicBoolMember(bool b) : ab(b) { } +