From: Douglas Gregor Date: Tue, 15 Dec 2009 00:01:57 +0000 (+0000) Subject: Implement value initialization in InitializationSequence; untested X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=71d1740c94060b424bb745d6c6973ff27cfdee06;p=clang Implement value initialization in InitializationSequence; untested WIP, yet again. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91368 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index c7994a06c3..45184650eb 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -1970,6 +1970,7 @@ void InitializationSequence::Step::Destroy() { case SK_QualificationConversionLValue: case SK_ListInitialization: case SK_ConstructorInitialization: + case SK_ZeroInitialization: break; case SK_ConversionSequence: @@ -2048,6 +2049,13 @@ InitializationSequence::AddConstructorInitializationStep( Steps.push_back(S); } +void InitializationSequence::AddZeroInitializationStep(QualType T) { + Step S; + S.Kind = SK_ZeroInitialization; + S.Type = T; + Steps.push_back(S); +} + void InitializationSequence::SetOverloadFailure(FailureKind Failure, OverloadingResult Result) { SequenceKind = FailedSequence; @@ -2458,14 +2466,6 @@ static void TryStringLiteralInitialization(Sema &S, // FIXME: Implement! } -/// \brief Attempt value initialization (C++ [dcl.init]p7). -static void TryValueInitialization(Sema &S, - const InitializedEntity &Entity, - const InitializationKind &Kind, - InitializationSequence &Sequence) { - // FIXME: Implement! -} - /// \brief Attempt initialization by constructor (C++ [dcl.init]), which /// enumerates the constructors of the initialized entity and performs overload /// resolution to select the best. @@ -2473,6 +2473,7 @@ static void TryConstructorInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, Expr **Args, unsigned NumArgs, + QualType DestType, InitializationSequence &Sequence) { Sequence.setSequenceKind(InitializationSequence::ConstructorInitialization); @@ -2489,7 +2490,6 @@ static void TryConstructorInitialization(Sema &S, // The type we're converting to is a class type. Enumerate its constructors // to see if one is suitable. - QualType DestType = Entity.getType().getType(); const RecordType *DestRecordType = DestType->getAs(); assert(DestRecordType && "Constructor initialization requires record type"); CXXRecordDecl *DestRecordDecl @@ -2540,6 +2540,41 @@ static void TryConstructorInitialization(Sema &S, DestType); } +/// \brief Attempt value initialization (C++ [dcl.init]p7). +static void TryValueInitialization(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + InitializationSequence &Sequence) { + // C++ [dcl.init]p5: + // + // To value-initialize an object of type T means: + QualType T = Entity.getType().getType(); + + // -- if T is an array type, then each element is value-initialized; + while (const ArrayType *AT = S.Context.getAsArrayType(T)) + T = AT->getElementType(); + + if (const RecordType *RT = T->getAs()) { + if (CXXRecordDecl *ClassDecl = dyn_cast(RT->getDecl())) { + // -- if T is a class type (clause 9) with a user-declared + // constructor (12.1), then the default constructor for T is + // called (and the initialization is ill-formed if T has no + // accessible default constructor); + // + // FIXME: we really want to refer to a single subobject of the array, + // but Entity doesn't have a way to capture that (yet). + if (ClassDecl->hasUserDeclaredConstructor()) + return TryConstructorInitialization(S, Entity, Kind, 0, 0, T, Sequence); + + // FIXME: non-union class type w/ non-trivial default constructor gets + // zero-initialized, then constructor gets called. + } + } + + Sequence.AddZeroInitializationStep(Entity.getType().getType()); + Sequence.setSequenceKind(InitializationSequence::ZeroInitialization); +} + /// \brief Attempt a user-defined conversion between two types (C++ [dcl.init]), /// which enumerates all conversion functions and performs overload resolution /// to select the best. @@ -2776,7 +2811,8 @@ InitializationSequence::InitializationSequence(Sema &S, (Kind.getKind() == InitializationKind::IK_Copy && (Context.hasSameUnqualifiedType(SourceType, DestType) || S.IsDerivedFrom(SourceType, DestType)))) - TryConstructorInitialization(S, Entity, Kind, Args, NumArgs, *this); + TryConstructorInitialization(S, Entity, Kind, Args, NumArgs, + Entity.getType().getType(), *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 @@ -3067,6 +3103,16 @@ InitializationSequence::Perform(Sema &S, CurInit = S.MaybeBindToTemporary(CurInit.takeAs()); break; } + + case SK_ZeroInitialization: { + if (Kind.getKind() == InitializationKind::IK_Value) + CurInit = S.Owned(new (S.Context) CXXZeroInitValueExpr(Step->Type, + Kind.getRange().getBegin(), + Kind.getRange().getEnd())); + else + CurInit = S.Owned(new (S.Context) ImplicitValueInitExpr(Step->Type)); + break; + } } } diff --git a/lib/Sema/SemaInit.h b/lib/Sema/SemaInit.h index 2c05196fb1..2d4b01f26b 100644 --- a/lib/Sema/SemaInit.h +++ b/lib/Sema/SemaInit.h @@ -269,7 +269,7 @@ public: /// \brief Retrieve the source range that covers the initialization. SourceRange getRange() const { - return SourceRange(Locations[0], Locations[1]); + return SourceRange(Locations[0], Locations[2]); } /// \brief Retrieve the location of the equal sign for copy initialization @@ -293,6 +293,9 @@ public: class InitializationSequence { public: /// \brief Describes the kind of initialization sequence computed. + /// + /// FIXME: Much of this information is in the initialization steps... why is + /// it duplicated here? enum SequenceKind { /// \brief A failed initialization sequence. The failure kind tells what /// happened. @@ -313,7 +316,10 @@ public: ReferenceBinding, /// \brief List initialization - ListInitialization + ListInitialization, + + /// \brief Zero-initialization. + ZeroInitialization }; /// \brief Describes the kind of a particular step in an initialization @@ -342,7 +348,9 @@ public: /// \brief Perform list-initialization SK_ListInitialization, /// \brief Perform initialization via a constructor. - SK_ConstructorInitialization + SK_ConstructorInitialization, + /// \brief Zero-initialize the object + SK_ZeroInitialization }; /// \brief A single step in the initialization sequence. @@ -536,9 +544,12 @@ public: /// \brief Add a list-initialiation step void AddListInitializationStep(QualType T); - /// \brief Add a a constructor-initialization step. + /// \brief Add a constructor-initialization step. void AddConstructorInitializationStep(CXXConstructorDecl *Constructor, QualType T); + + /// \brief Add a zero-initialization step. + void AddZeroInitializationStep(QualType T); /// \brief Note that this initialization sequence failed. void SetFailed(FailureKind Failure) {