зеркало из https://github.com/microsoft/clang-1.git
Move initialization via initializer list over to InitializationSequences.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91050 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
9f54ad4381
Коммит
d87b61f639
|
@ -542,7 +542,11 @@ def err_reference_bind_drops_quals : Error<
|
|||
def err_reference_bind_failed : Error<
|
||||
"reference to type %0 could not bind to an %select{rvalue|lvalue}1 of type "
|
||||
"%2">;
|
||||
|
||||
def err_reference_bind_init_list : Error<
|
||||
"reference to type %0 cannot bind to an initializer list">;
|
||||
def err_init_list_bad_dest_type : Error<
|
||||
"%select{|non-aggregate }0type %1 cannot be initialized with an initializer "
|
||||
"list">;
|
||||
|
||||
// FIXME: passing in an English string as %1!
|
||||
def err_reference_init_drops_quals : Error<
|
||||
|
|
|
@ -3499,7 +3499,8 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
|
|||
Diag(VDecl->getLocation(), diag::err_block_extern_cant_init);
|
||||
VDecl->setInvalidDecl();
|
||||
} else if (!VDecl->isInvalidDecl()) {
|
||||
if (VDecl->getType()->isReferenceType()) {
|
||||
if (VDecl->getType()->isReferenceType()
|
||||
|| isa<InitListExpr>(Init)) {
|
||||
InitializedEntity Entity
|
||||
= InitializedEntity::InitializeVariable(VDecl);
|
||||
|
||||
|
@ -3513,7 +3514,8 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
|
|||
InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1);
|
||||
if (InitSeq) {
|
||||
OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind,
|
||||
MultiExprArg(*this, (void**)&Init, 1));
|
||||
MultiExprArg(*this, (void**)&Init, 1),
|
||||
&DclT);
|
||||
if (Result.isInvalid()) {
|
||||
VDecl->setInvalidDecl();
|
||||
return;
|
||||
|
@ -3525,7 +3527,6 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
|
|||
VDecl->setInvalidDecl();
|
||||
return;
|
||||
}
|
||||
|
||||
} else if (CheckInitializerTypes(Init, DclT, VDecl->getLocation(),
|
||||
VDecl->getDeclName(), DirectInit))
|
||||
VDecl->setInvalidDecl();
|
||||
|
|
|
@ -1968,6 +1968,7 @@ void InitializationSequence::Step::Destroy() {
|
|||
case SK_UserConversion:
|
||||
case SK_QualificationConversionRValue:
|
||||
case SK_QualificationConversionLValue:
|
||||
case SK_ListInitialization:
|
||||
break;
|
||||
|
||||
case SK_ConversionSequence:
|
||||
|
@ -2027,6 +2028,13 @@ void InitializationSequence::AddConversionSequenceStep(
|
|||
Steps.push_back(S);
|
||||
}
|
||||
|
||||
void InitializationSequence::AddListInitializationStep(QualType T) {
|
||||
Step S;
|
||||
S.Kind = SK_ListInitialization;
|
||||
S.Type = T;
|
||||
Steps.push_back(S);
|
||||
}
|
||||
|
||||
void InitializationSequence::SetOverloadFailure(FailureKind Failure,
|
||||
OverloadingResult Result) {
|
||||
SequenceKind = FailedSequence;
|
||||
|
@ -2039,16 +2047,51 @@ void InitializationSequence::SetOverloadFailure(FailureKind Failure,
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// \brief Attempt list initialization (C++0x [dcl.init.list])
|
||||
static bool TryListInitialization(Sema &S,
|
||||
static void TryListInitialization(Sema &S,
|
||||
const InitializedEntity &Entity,
|
||||
const InitializationKind &Kind,
|
||||
InitListExpr *InitList,
|
||||
InitializationSequence &Sequence) {
|
||||
// FIXME: For now, it is safe to assume that list initialization always
|
||||
// works. When we actually perform list initialization, we'll do all of the
|
||||
// necessary checking.
|
||||
// C++0x initializer lists will force us to perform more checking here.
|
||||
return true;
|
||||
// FIXME: We only perform rudimentary checking of list
|
||||
// initializations at this point, then assume that any list
|
||||
// initialization of an array, aggregate, or scalar will be
|
||||
// well-formed. We we actually "perform" list initialization, we'll
|
||||
// do all of the necessary checking. C++0x initializer lists will
|
||||
// force us to perform more checking here.
|
||||
Sequence.setSequenceKind(InitializationSequence::ListInitialization);
|
||||
|
||||
QualType DestType = Entity.getType().getType();
|
||||
|
||||
// C++ [dcl.init]p13:
|
||||
// If T is a scalar type, then a declaration of the form
|
||||
//
|
||||
// T x = { a };
|
||||
//
|
||||
// is equivalent to
|
||||
//
|
||||
// T x = a;
|
||||
if (DestType->isScalarType()) {
|
||||
if (InitList->getNumInits() > 1 && S.getLangOptions().CPlusPlus) {
|
||||
Sequence.SetFailed(InitializationSequence::FK_TooManyInitsForScalar);
|
||||
return;
|
||||
}
|
||||
|
||||
// Assume scalar initialization from a single value works.
|
||||
} else if (DestType->isAggregateType()) {
|
||||
// Assume aggregate initialization works.
|
||||
} else if (DestType->isVectorType()) {
|
||||
// Assume vector initialization works.
|
||||
} else if (DestType->isReferenceType()) {
|
||||
// FIXME: C++0x defines behavior for this.
|
||||
Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList);
|
||||
return;
|
||||
} else if (DestType->isRecordType()) {
|
||||
// FIXME: C++0x defines behavior for this
|
||||
Sequence.SetFailed(InitializationSequence::FK_InitListBadDestinationType);
|
||||
}
|
||||
|
||||
// Add a general "list initialization" step.
|
||||
Sequence.AddListInitializationStep(DestType);
|
||||
}
|
||||
|
||||
/// \brief Try a reference initialization that involves calling a conversion
|
||||
|
@ -2485,6 +2528,7 @@ InitializationSequence::InitializationSequence(Sema &S,
|
|||
// list-initialized (8.5.4).
|
||||
if (InitListExpr *InitList = dyn_cast_or_null<InitListExpr>(Initializer)) {
|
||||
TryListInitialization(S, Entity, Kind, InitList, *this);
|
||||
return;
|
||||
}
|
||||
|
||||
// - If the destination type is a reference type, see 8.5.3.
|
||||
|
@ -2578,7 +2622,8 @@ Action::OwningExprResult
|
|||
InitializationSequence::Perform(Sema &S,
|
||||
const InitializedEntity &Entity,
|
||||
const InitializationKind &Kind,
|
||||
Action::MultiExprArg Args) {
|
||||
Action::MultiExprArg Args,
|
||||
QualType *ResultType) {
|
||||
if (SequenceKind == FailedSequence) {
|
||||
unsigned NumArgs = Args.size();
|
||||
Diagnose(S, Entity, Kind, (Expr **)Args.release(), NumArgs);
|
||||
|
@ -2586,6 +2631,41 @@ InitializationSequence::Perform(Sema &S,
|
|||
}
|
||||
|
||||
if (SequenceKind == DependentSequence) {
|
||||
// If the declaration is a non-dependent, incomplete array type
|
||||
// that has an initializer, then its type will be completed once
|
||||
// the initializer is instantiated.
|
||||
if (ResultType && !Entity.getType().getType()->isDependentType() &&
|
||||
Args.size() == 1) {
|
||||
QualType DeclType = Entity.getType().getType();
|
||||
if (const IncompleteArrayType *ArrayT
|
||||
= S.Context.getAsIncompleteArrayType(DeclType)) {
|
||||
// FIXME: We don't currently have the ability to accurately
|
||||
// compute the length of an initializer list without
|
||||
// performing full type-checking of the initializer list
|
||||
// (since we have to determine where braces are implicitly
|
||||
// introduced and such). So, we fall back to making the array
|
||||
// type a dependently-sized array type with no specified
|
||||
// bound.
|
||||
if (isa<InitListExpr>((Expr *)Args.get()[0])) {
|
||||
SourceRange Brackets;
|
||||
// Scavange the location of the brackets from the entity, if we can.
|
||||
if (isa<IncompleteArrayTypeLoc>(Entity.getType())) {
|
||||
IncompleteArrayTypeLoc ArrayLoc
|
||||
= cast<IncompleteArrayTypeLoc>(Entity.getType());
|
||||
Brackets = ArrayLoc.getBracketsRange();
|
||||
}
|
||||
|
||||
*ResultType
|
||||
= S.Context.getDependentSizedArrayType(ArrayT->getElementType(),
|
||||
/*NumElts=*/0,
|
||||
ArrayT->getSizeModifier(),
|
||||
ArrayT->getIndexTypeCVRQualifiers(),
|
||||
Brackets);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (Kind.getKind() == InitializationKind::IK_Copy)
|
||||
return Sema::OwningExprResult(S, Args.release()[0]);
|
||||
|
||||
|
@ -2598,6 +2678,8 @@ InitializationSequence::Perform(Sema &S,
|
|||
}
|
||||
|
||||
QualType DestType = Entity.getType().getType().getNonReferenceType();
|
||||
if (ResultType)
|
||||
*ResultType = Entity.getType().getType();
|
||||
|
||||
Sema::OwningExprResult CurInit(S);
|
||||
// For copy initialization and any other initialization forms that
|
||||
|
@ -2754,6 +2836,17 @@ InitializationSequence::Perform(Sema &S,
|
|||
CurInit.release();
|
||||
CurInit = S.Owned(CurInitExpr);
|
||||
break;
|
||||
|
||||
case SK_ListInitialization: {
|
||||
InitListExpr *InitList = cast<InitListExpr>(CurInitExpr);
|
||||
QualType Ty = Step->Type;
|
||||
if (S.CheckInitList(InitList, ResultType? *ResultType : Ty))
|
||||
return S.ExprError();
|
||||
|
||||
CurInit.release();
|
||||
CurInit = S.Owned(InitList);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2866,6 +2959,26 @@ bool InitializationSequence::Diagnose(Sema &S,
|
|||
<< Args[0]->getType()
|
||||
<< Args[0]->getSourceRange();
|
||||
break;
|
||||
|
||||
case FK_TooManyInitsForScalar: {
|
||||
InitListExpr *InitList = cast<InitListExpr>(Args[0]);
|
||||
|
||||
S.Diag(Kind.getLocation(), diag::err_excess_initializers)
|
||||
<< /*scalar=*/2
|
||||
<< SourceRange(InitList->getInit(1)->getLocStart(),
|
||||
InitList->getLocEnd());
|
||||
break;
|
||||
}
|
||||
|
||||
case FK_ReferenceBindingToInitList:
|
||||
S.Diag(Kind.getLocation(), diag::err_reference_bind_init_list)
|
||||
<< DestType.getNonReferenceType() << Args[0]->getSourceRange();
|
||||
break;
|
||||
|
||||
case FK_InitListBadDestinationType:
|
||||
S.Diag(Kind.getLocation(), diag::err_init_list_bad_dest_type)
|
||||
<< (DestType->isRecordType()) << DestType << Args[0]->getSourceRange();
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//===--- SemaInit.h - Semantic Analysis for Initializers ------------------===//
|
||||
//===--- SemaInit.h - Semantic Analysis for Initializers --------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
|
@ -304,7 +304,10 @@ public:
|
|||
DependentSequence,
|
||||
|
||||
/// \brief A reference binding.
|
||||
ReferenceBinding
|
||||
ReferenceBinding,
|
||||
|
||||
/// \brief List initialization
|
||||
ListInitialization
|
||||
};
|
||||
|
||||
/// \brief Describes the kind of a particular step in an initialization
|
||||
|
@ -329,7 +332,9 @@ public:
|
|||
/// \brief Perform a qualification conversion, producing an lvalue.
|
||||
SK_QualificationConversionLValue,
|
||||
/// \brief Perform an implicit conversion sequence.
|
||||
SK_ConversionSequence
|
||||
SK_ConversionSequence,
|
||||
/// \brief Perform list-initialization
|
||||
SK_ListInitialization
|
||||
};
|
||||
|
||||
/// \brief A single step in the initialization sequence.
|
||||
|
@ -388,7 +393,14 @@ public:
|
|||
/// \brief Reference binding failed.
|
||||
FK_ReferenceInitFailed,
|
||||
/// \brief Implicit conversion failed.
|
||||
FK_ConversionFailed
|
||||
FK_ConversionFailed,
|
||||
/// \brief Too many initializers for scalar
|
||||
FK_TooManyInitsForScalar,
|
||||
/// \brief Reference initialization from an initializer list
|
||||
FK_ReferenceBindingToInitList,
|
||||
/// \brief Initialization of some unused destination type with an
|
||||
/// initializer list.
|
||||
FK_InitListBadDestinationType
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -437,13 +449,20 @@ public:
|
|||
/// \param Args the argument(s) provided for initialization, ownership of
|
||||
/// which is transfered into the routine.
|
||||
///
|
||||
/// \param ResultType if non-NULL, will be set to the type of the
|
||||
/// initialized object, which is the type of the declaration in most
|
||||
/// cases. However, when the initialized object is a variable of
|
||||
/// incomplete array type and the initializer is an initializer
|
||||
/// list, this type will be set to the completed array type.
|
||||
///
|
||||
/// \returns an expression that performs the actual object initialization, if
|
||||
/// the initialization is well-formed. Otherwise, emits diagnostics
|
||||
/// and returns an invalid expression.
|
||||
Action::OwningExprResult Perform(Sema &S,
|
||||
const InitializedEntity &Entity,
|
||||
const InitializationKind &Kind,
|
||||
Action::MultiExprArg Args);
|
||||
Action::MultiExprArg Args,
|
||||
QualType *ResultType = 0);
|
||||
|
||||
/// \brief Diagnose an potentially-invalid initialization sequence.
|
||||
///
|
||||
|
@ -502,6 +521,9 @@ public:
|
|||
void AddConversionSequenceStep(const ImplicitConversionSequence &ICS,
|
||||
QualType T);
|
||||
|
||||
/// \brief Add a list-initialiation step
|
||||
void AddListInitializationStep(QualType T);
|
||||
|
||||
/// \brief Note that this initialization sequence failed.
|
||||
void SetFailed(FailureKind Failure) {
|
||||
SequenceKind = FailedSequence;
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
|
||||
void f0() {
|
||||
int &ir = { 17 }; // expected-error{{reference to type 'int' cannot bind to an initializer list}}
|
||||
}
|
Загрузка…
Ссылка в новой задаче