[cfe-commits] r91050 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDecl.cpp lib/Sema/SemaInit.cpp lib/Sema/SemaInit.h test/CXX/dcl.decl/dcl.init/dcl.init.list/basic.cpp
Douglas Gregor
dgregor at apple.com
Thu Dec 10 09:56:55 PST 2009
Author: dgregor
Date: Thu Dec 10 11:56:55 2009
New Revision: 91050
URL: http://llvm.org/viewvc/llvm-project?rev=91050&view=rev
Log:
Move initialization via initializer list over to InitializationSequences.
Added:
cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/basic.cpp (with props)
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaInit.cpp
cfe/trunk/lib/Sema/SemaInit.h
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=91050&r1=91049&r2=91050&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Dec 10 11:56:55 2009
@@ -542,7 +542,11 @@
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<
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=91050&r1=91049&r2=91050&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Dec 10 11:56:55 2009
@@ -3499,7 +3499,8 @@
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 @@
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;
@@ -3524,8 +3526,7 @@
InitSeq.Diagnose(*this, Entity, Kind, &Init, 1);
VDecl->setInvalidDecl();
return;
- }
-
+ }
} else if (CheckInitializerTypes(Init, DclT, VDecl->getLocation(),
VDecl->getDeclName(), DirectInit))
VDecl->setInvalidDecl();
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=91050&r1=91049&r2=91050&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Thu Dec 10 11:56:55 2009
@@ -1968,6 +1968,7 @@
case SK_UserConversion:
case SK_QualificationConversionRValue:
case SK_QualificationConversionLValue:
+ case SK_ListInitialization:
break;
case SK_ConversionSequence:
@@ -2027,6 +2028,13 @@
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 @@
//===----------------------------------------------------------------------===//
/// \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 @@
// 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 @@
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 @@
}
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 @@
}
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 @@
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;
+ }
}
}
@@ -2865,7 +2958,27 @@
<< (Args[0]->isLvalue(S.Context) == Expr::LV_Valid)
<< Args[0]->getType()
<< Args[0]->getSourceRange();
- break;
+ 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;
Modified: cfe/trunk/lib/Sema/SemaInit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.h?rev=91050&r1=91049&r2=91050&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.h (original)
+++ cfe/trunk/lib/Sema/SemaInit.h Thu Dec 10 11:56:55 2009
@@ -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 @@
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 @@
/// \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 @@
/// \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 @@
/// \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.
///
@@ -501,7 +520,10 @@
/// \brief Add a new step that applies an implicit conversion sequence.
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;
Added: cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/basic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/basic.cpp?rev=91050&view=auto
==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/basic.cpp (added)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/basic.cpp Thu Dec 10 11:56:55 2009
@@ -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}}
+}
Propchange: cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/basic.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/basic.cpp
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/basic.cpp
------------------------------------------------------------------------------
svn:mime-type = text/plain
More information about the cfe-commits
mailing list