Implement value initialization in InitializationSequence; untested

WIP, yet again.

llvm-svn: 91368
This commit is contained in:
Douglas Gregor 2009-12-15 00:01:57 +00:00
parent 68943780a6
commit 7dc42e5d4c
2 changed files with 71 additions and 14 deletions

View File

@ -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<RecordType>();
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<RecordType>()) {
if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(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<Expr>());
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;
}
}
}

View File

@ -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,10 +544,13 @@ 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) {
SequenceKind = FailedSequence;