r214390 - PR18097: Support initializing an _Atomic(T) from an object of C++ class type T
Bill Wendling
isanbard at gmail.com
Mon Aug 4 11:28:54 PDT 2014
Done. Thanks!
-bw
On Jul 31, 2014, at 12:02 AM, Richard Smith <richard at metafoo.co.uk> wrote:
> This fixes a bug marked as being a release blocker and should be put on the 3.5 branch.
>
>
> On Wed, Jul 30, 2014 at 11:31 PM, Richard Smith <richard-llvm at metafoo.co.uk> wrote:
> Author: rsmith
> Date: Thu Jul 31 01:31:19 2014
> New Revision: 214390
>
> URL: http://llvm.org/viewvc/llvm-project?rev=214390&view=rev
> Log:
> PR18097: Support initializing an _Atomic(T) from an object of C++ class type T
> or a class derived from T. We already supported this when initializing
> _Atomic(T) from T for most (and maybe all) other reasonable values of T.
>
> Modified:
> cfe/trunk/include/clang/Sema/Initialization.h
> cfe/trunk/lib/AST/ExprConstant.cpp
> cfe/trunk/lib/CodeGen/CGExprAgg.cpp
> cfe/trunk/lib/CodeGen/CGExprConstant.cpp
> cfe/trunk/lib/Sema/SemaInit.cpp
> cfe/trunk/test/CodeGen/c11atomics.c
> cfe/trunk/test/CodeGenCXX/atomicinit.cpp
> cfe/trunk/test/SemaCXX/atomic-type.cpp
>
> Modified: cfe/trunk/include/clang/Sema/Initialization.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Initialization.h?rev=214390&r1=214389&r2=214390&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/Initialization.h (original)
> +++ cfe/trunk/include/clang/Sema/Initialization.h Thu Jul 31 01:31:19 2014
> @@ -663,6 +663,8 @@ public:
> SK_QualificationConversionXValue,
> /// \brief Perform a qualification conversion, producing an lvalue.
> SK_QualificationConversionLValue,
> + /// \brief Perform a conversion adding _Atomic to a type.
> + SK_AtomicConversion,
> /// \brief Perform a load from a glvalue, producing an rvalue.
> SK_LValueToRValue,
> /// \brief Perform an implicit conversion sequence.
> @@ -999,7 +1001,11 @@ public:
> /// given type.
> void AddQualificationConversionStep(QualType Ty,
> ExprValueKind Category);
> -
> +
> + /// \brief Add a new step that performs conversion from non-atomic to atomic
> + /// type.
> + void AddAtomicConversionStep(QualType Ty);
> +
> /// \brief Add a new step that performs a load of the given type.
> ///
> /// Although the term "LValueToRValue" is conventional, this applies to both
>
> Modified: cfe/trunk/lib/AST/ExprConstant.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=214390&r1=214389&r2=214390&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/ExprConstant.cpp (original)
> +++ cfe/trunk/lib/AST/ExprConstant.cpp Thu Jul 31 01:31:19 2014
> @@ -1353,6 +1353,11 @@ static bool CheckConstantExpression(Eval
> return false;
> }
>
> + // We allow _Atomic(T) to be initialized from anything that T can be
> + // initialized from.
> + if (const AtomicType *AT = Type->getAs<AtomicType>())
> + Type = AT->getValueType();
> +
> // Core issue 1454: For a literal constant expression of array or class type,
> // each subobject of its value shall have been initialized by a constant
> // expression.
>
> Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=214390&r1=214389&r2=214390&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Thu Jul 31 01:31:19 2014
> @@ -1137,6 +1137,16 @@ void AggExprEmitter::VisitInitListExpr(I
> return;
> }
>
> + if (E->getType()->isAtomicType()) {
> + // An _Atomic(T) object can be list-initialized from an expression
> + // of the same type.
> + assert(E->getNumInits() == 1 &&
> + CGF.getContext().hasSameUnqualifiedType(E->getInit(0)->getType(),
> + E->getType()) &&
> + "unexpected list initialization for atomic object");
> + return Visit(E->getInit(0));
> + }
> +
> assert(E->getType()->isRecordType() && "Only support structs/unions here!");
>
> // Do struct initialization; this code just sets each individual member
>
> Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=214390&r1=214389&r2=214390&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Thu Jul 31 01:31:19 2014
> @@ -1045,6 +1045,25 @@ llvm::Constant *CodeGenModule::EmitConst
> llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value,
> QualType DestType,
> CodeGenFunction *CGF) {
> + // For an _Atomic-qualified constant, we may need to add tail padding.
> + if (auto *AT = DestType->getAs<AtomicType>()) {
> + QualType InnerType = AT->getValueType();
> + auto *Inner = EmitConstantValue(Value, InnerType, CGF);
> +
> + uint64_t InnerSize = Context.getTypeSize(InnerType);
> + uint64_t OuterSize = Context.getTypeSize(DestType);
> + if (InnerSize == OuterSize)
> + return Inner;
> +
> + assert(InnerSize < OuterSize && "emitted over-large constant for atomic");
> + llvm::Constant *Elts[] = {
> + Inner,
> + llvm::ConstantAggregateZero::get(
> + llvm::ArrayType::get(Int8Ty, (OuterSize - InnerSize) / 8))
> + };
> + return llvm::ConstantStruct::getAnon(Elts);
> + }
> +
> switch (Value.getKind()) {
> case APValue::Uninitialized:
> llvm_unreachable("Constant expressions should be initialized.");
>
> Modified: cfe/trunk/lib/Sema/SemaInit.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=214390&r1=214389&r2=214390&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaInit.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaInit.cpp Thu Jul 31 01:31:19 2014
> @@ -2767,6 +2767,7 @@ void InitializationSequence::Step::Destr
> case SK_QualificationConversionRValue:
> case SK_QualificationConversionXValue:
> case SK_QualificationConversionLValue:
> + case SK_AtomicConversion:
> case SK_LValueToRValue:
> case SK_ListInitialization:
> case SK_UnwrapInitList:
> @@ -2919,6 +2920,13 @@ void InitializationSequence::AddQualific
> Steps.push_back(S);
> }
>
> +void InitializationSequence::AddAtomicConversionStep(QualType Ty) {
> + Step S;
> + S.Kind = SK_AtomicConversion;
> + S.Type = Ty;
> + Steps.push_back(S);
> +}
> +
> void InitializationSequence::AddLValueToRValueStep(QualType Ty) {
> assert(!Ty.hasQualifiers() && "rvalues may not have qualifiers");
>
> @@ -4174,12 +4182,11 @@ static void TryDefaultInitialization(Sem
> /// which enumerates all conversion functions and performs overload resolution
> /// to select the best.
> static void TryUserDefinedConversion(Sema &S,
> - const InitializedEntity &Entity,
> + QualType DestType,
> const InitializationKind &Kind,
> Expr *Initializer,
> InitializationSequence &Sequence,
> bool TopLevelOfInitList) {
> - QualType DestType = Entity.getType();
> assert(!DestType->isReferenceType() && "References are handled elsewhere");
> QualType SourceType = Initializer->getType();
> assert((DestType->isRecordType() || SourceType->isRecordType()) &&
> @@ -4596,7 +4603,6 @@ void InitializationSequence::InitializeF
> Initializer) ||
> S.ConversionToObjCStringLiteralCheck(DestType, Initializer))
> Args[0] = Initializer;
> -
> }
> if (!isa<InitListExpr>(Initializer))
> SourceType = Initializer->getType();
> @@ -4741,7 +4747,7 @@ void InitializationSequence::InitializeF
> (Context.hasSameUnqualifiedType(SourceType, DestType) ||
> S.IsDerivedFrom(SourceType, DestType))))
> TryConstructorInitialization(S, Entity, Kind, Args,
> - Entity.getType(), *this);
> + DestType, *this);
> // - Otherwise (i.e., for the remaining copy-initialization cases),
> // user-defined conversion sequences that can convert from the source
> // type to the destination type or (when a conversion function is
> @@ -4749,7 +4755,7 @@ void InitializationSequence::InitializeF
> // 13.3.1.4, and the best one is chosen through overload resolution
> // (13.3).
> else
> - TryUserDefinedConversion(S, Entity, Kind, Initializer, *this,
> + TryUserDefinedConversion(S, DestType, Kind, Initializer, *this,
> TopLevelOfInitList);
> return;
> }
> @@ -4763,9 +4769,22 @@ void InitializationSequence::InitializeF
> // - Otherwise, if the source type is a (possibly cv-qualified) class
> // type, conversion functions are considered.
> if (!SourceType.isNull() && SourceType->isRecordType()) {
> - TryUserDefinedConversion(S, Entity, Kind, Initializer, *this,
> + // For a conversion to _Atomic(T) from either T or a class type derived
> + // from T, initialize the T object then convert to _Atomic type.
> + bool NeedAtomicConversion = false;
> + if (const AtomicType *Atomic = DestType->getAs<AtomicType>()) {
> + if (Context.hasSameUnqualifiedType(SourceType, Atomic->getValueType()) ||
> + S.IsDerivedFrom(SourceType, Atomic->getValueType())) {
> + DestType = Atomic->getValueType();
> + NeedAtomicConversion = true;
> + }
> + }
> +
> + TryUserDefinedConversion(S, DestType, Kind, Initializer, *this,
> TopLevelOfInitList);
> MaybeProduceObjCObject(S, *this, Entity);
> + if (!Failed() && NeedAtomicConversion)
> + AddAtomicConversionStep(Entity.getType());
> return;
> }
>
> @@ -4774,16 +4793,16 @@ void InitializationSequence::InitializeF
> // conversions (Clause 4) will be used, if necessary, to convert the
> // initializer expression to the cv-unqualified version of the
> // destination type; no user-defined conversions are considered.
> -
> +
> ImplicitConversionSequence ICS
> - = S.TryImplicitConversion(Initializer, Entity.getType(),
> + = S.TryImplicitConversion(Initializer, DestType,
> /*SuppressUserConversions*/true,
> /*AllowExplicitConversions*/ false,
> /*InOverloadResolution*/ false,
> /*CStyle=*/Kind.isCStyleOrFunctionalCast(),
> allowObjCWritebackConversion);
> -
> - if (ICS.isStandard() &&
> +
> + if (ICS.isStandard() &&
> ICS.Standard.Second == ICK_Writeback_Conversion) {
> // Objective-C ARC writeback conversion.
>
> @@ -4804,7 +4823,7 @@ void InitializationSequence::InitializeF
> AddConversionSequenceStep(LvalueICS, ICS.Standard.getToType(0));
> }
>
> - AddPassByIndirectCopyRestoreStep(Entity.getType(), ShouldCopy);
> + AddPassByIndirectCopyRestoreStep(DestType, ShouldCopy);
> } else if (ICS.isBad()) {
> DeclAccessPair dap;
> if (isLibstdcxxPointerReturnFalseHack(S, Entity, Initializer)) {
> @@ -4816,7 +4835,7 @@ void InitializationSequence::InitializeF
> else
> SetFailed(InitializationSequence::FK_ConversionFailed);
> } else {
> - AddConversionSequenceStep(ICS, Entity.getType(), TopLevelOfInitList);
> + AddConversionSequenceStep(ICS, DestType, TopLevelOfInitList);
>
> MaybeProduceObjCObject(S, *this, Entity);
> }
> @@ -5772,6 +5791,7 @@ InitializationSequence::Perform(Sema &S,
> case SK_QualificationConversionLValue:
> case SK_QualificationConversionXValue:
> case SK_QualificationConversionRValue:
> + case SK_AtomicConversion:
> case SK_LValueToRValue:
> case SK_ConversionSequence:
> case SK_ConversionSequenceNoNarrowing:
> @@ -6062,6 +6082,13 @@ InitializationSequence::Perform(Sema &S,
> break;
> }
>
> + case SK_AtomicConversion: {
> + assert(CurInit.get()->isRValue() && "cannot convert glvalue to atomic");
> + CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type,
> + CK_NonAtomicToAtomic, VK_RValue);
> + break;
> + }
> +
> case SK_LValueToRValue: {
> assert(CurInit.get()->isGLValue() && "cannot load from a prvalue");
> CurInit = ImplicitCastExpr::Create(S.Context, Step->Type,
> @@ -7033,6 +7060,10 @@ void InitializationSequence::dump(raw_os
> OS << "qualification conversion (lvalue)";
> break;
>
> + case SK_AtomicConversion:
> + OS << "non-atomic-to-atomic conversion";
> + break;
> +
> case SK_LValueToRValue:
> OS << "load (lvalue to rvalue)";
> break;
>
> Modified: cfe/trunk/test/CodeGen/c11atomics.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/c11atomics.c?rev=214390&r1=214389&r2=214390&view=diff
> ==============================================================================
> --- cfe/trunk/test/CodeGen/c11atomics.c (original)
> +++ cfe/trunk/test/CodeGen/c11atomics.c Thu Jul 31 01:31:19 2014
> @@ -12,6 +12,9 @@
> // they're sufficiently rare that it's not worth making sure that the semantics
> // are correct.
>
> +// CHECK: @testStructGlobal = global {{.*}} { i16 1, i16 2, i16 3, i16 4 }
> +// CHECK: @testPromotedStructGlobal = global {{.*}} { %{{.*}} { i16 1, i16 2, i16 3 }, [2 x i8] zeroinitializer }
> +
> typedef int __attribute__((vector_size(16))) vector;
>
> _Atomic(_Bool) b;
> @@ -224,6 +227,7 @@ void testComplexFloat(_Atomic(_Complex f
> }
>
> typedef struct { short x, y, z, w; } S;
> +_Atomic S testStructGlobal = (S){1, 2, 3, 4};
> // CHECK: define arm_aapcscc void @testStruct([[S:.*]]*
> void testStruct(_Atomic(S) *fp) {
> // CHECK: [[FP:%.*]] = alloca [[S]]*, align 4
> @@ -272,6 +276,7 @@ void testStruct(_Atomic(S) *fp) {
> }
>
> typedef struct { short x, y, z; } PS;
> +_Atomic PS testPromotedStructGlobal = (PS){1, 2, 3};
> // CHECK: define arm_aapcscc void @testPromotedStruct([[APS:.*]]*
> void testPromotedStruct(_Atomic(PS) *fp) {
> // CHECK: [[FP:%.*]] = alloca [[APS]]*, align 4
>
> Modified: cfe/trunk/test/CodeGenCXX/atomicinit.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/atomicinit.cpp?rev=214390&r1=214389&r2=214390&view=diff
> ==============================================================================
> --- cfe/trunk/test/CodeGenCXX/atomicinit.cpp (original)
> +++ cfe/trunk/test/CodeGenCXX/atomicinit.cpp Thu Jul 31 01:31:19 2014
> @@ -1,4 +1,10 @@
> -// RUN: %clang_cc1 %s -emit-llvm -O1 -o - -triple=i686-apple-darwin9 | FileCheck %s
> +// RUN: %clang_cc1 %s -emit-llvm -O1 -o - -triple=i686-apple-darwin9 -std=c++11 | FileCheck %s
> +
> +// CHECK-DAG: @_ZN7PR180978constant1aE = global {{.*}} { i16 1, i8 6, i8 undef }, align 4
> +// CHECK-DAG: @_ZN7PR180978constant1bE = global {{.*}} { i16 2, i8 6, i8 undef }, align 4
> +// CHECK-DAG: @_ZN7PR180978constant1cE = global {{.*}} { i16 3, i8 6, i8 undef }, align 4
> +// CHECK-DAG: @_ZN7PR180978constant1yE = global {{.*}} { {{.*}} { i16 4, i8 6, i8 undef }, i32 5 }, align 4
> +
> struct A {
> _Atomic(int) i;
> A(int j);
> @@ -46,3 +52,51 @@ struct AtomicBoolMember {
> // CHECK-NEXT: ret void
> AtomicBoolMember::AtomicBoolMember(bool b) : ab(b) { }
>
> +namespace PR18097 {
> + namespace dynamic {
> + struct X {
> + X(int);
> + short n;
> + char c;
> + };
> +
> + // CHECK-LABEL: define {{.*}} @__cxx_global_var_init
> + // CHECK: call void @_ZN7PR180977dynamic1XC1Ei({{.*}}* @_ZN7PR180977dynamic1aE, i32 1)
> + _Atomic(X) a = X(1);
> +
> + // CHECK-LABEL: define {{.*}} @__cxx_global_var_init
> + // CHECK: call void @_ZN7PR180977dynamic1XC1Ei({{.*}}* @_ZN7PR180977dynamic1bE, i32 2)
> + _Atomic(X) b(X(2));
> +
> + // CHECK-LABEL: define {{.*}} @__cxx_global_var_init
> + // CHECK: call void @_ZN7PR180977dynamic1XC1Ei({{.*}}* @_ZN7PR180977dynamic1cE, i32 3)
> + _Atomic(X) c{X(3)};
> +
> + struct Y {
> + _Atomic(X) a;
> + _Atomic(int) b;
> + };
> + // CHECK-LABEL: define {{.*}} @__cxx_global_var_init
> + // CHECK: call void @_ZN7PR180977dynamic1XC1Ei({{.*}}* getelementptr inbounds ({{.*}}* @_ZN7PR180977dynamic1yE, i32 0, i32 0), i32 4)
> + // CHECK: store i32 5, i32* getelementptr inbounds ({{.*}}* @_ZN7PR180977dynamic1yE, i32 0, i32 1)
> + Y y = { X(4), 5 };
> + }
> +
> + // CHECKs at top of file.
> + namespace constant {
> + struct X {
> + constexpr X(int n) : n(n) {}
> + short n;
> + char c = 6;
> + };
> + _Atomic(X) a = X(1);
> + _Atomic(X) b(X(2));
> + _Atomic(X) c{X(3)};
> +
> + struct Y {
> + _Atomic(X) a;
> + _Atomic(int) b;
> + };
> + Y y = { X(4), 5 };
> + }
> +}
>
> Modified: cfe/trunk/test/SemaCXX/atomic-type.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/atomic-type.cpp?rev=214390&r1=214389&r2=214390&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/atomic-type.cpp (original)
> +++ cfe/trunk/test/SemaCXX/atomic-type.cpp Thu Jul 31 01:31:19 2014
> @@ -1,4 +1,5 @@
> -// RUN: %clang_cc1 -verify -pedantic %s
> +// RUN: %clang_cc1 -verify -pedantic %s -std=c++98
> +// RUN: %clang_cc1 -verify -pedantic %s -std=c++11
>
> template<typename T> struct atomic {
> _Atomic(T) value;
> @@ -56,3 +57,29 @@ typedef _Atomic(int &) atomic_reference_
> struct S {
> _Atomic union { int n; }; // expected-warning {{anonymous union cannot be '_Atomic'}}
> };
> +
> +namespace copy_init {
> + struct X {
> + X(int);
> + int n;
> + };
> + _Atomic(X) y = X(0);
> + _Atomic(X) z(X(0));
> + void f() { y = X(0); }
> +
> + _Atomic(X) e1(0); // expected-error {{cannot initialize}}
> +#if __cplusplus >= 201103L
> + _Atomic(X) e2{0}; // expected-error {{illegal initializer}}
> + _Atomic(X) a{X(0)};
> +#endif
> +
> + struct Y {
> + _Atomic(X) a;
> + _Atomic(int) b;
> + };
> + Y y1 = { X(0), 4 };
> + Y y2 = { 0, 4 }; // expected-error {{cannot initialize}}
> + // FIXME: It's not really clear if we should allow these. Generally, C++11
> + // allows extraneous braces around initializers.
> + Y y3 = { { X(0) }, { 4 } }; // expected-error 2{{illegal initializer type}}
> +}
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140804/0541fa0c/attachment.html>
More information about the cfe-commits
mailing list