diff options
-rw-r--r-- | include/clang/Sema/Initialization.h | 93 | ||||
-rw-r--r-- | lib/Sema/SemaCast.cpp | 15 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 50 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaInit.cpp | 12 | ||||
-rw-r--r-- | test/SemaCXX/cxx0x-initializer-aggregates.cpp | 2 | ||||
-rw-r--r-- | test/SemaCXX/cxx0x-initializer-references.cpp | 5 | ||||
-rw-r--r-- | test/SemaCXX/cxx0x-initializer-scalars.cpp | 5 | ||||
-rw-r--r-- | test/SemaCXX/generalized-initializers.cpp | 52 |
9 files changed, 105 insertions, 132 deletions
diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h index dde46a2ff4..3d8dfa4d5f 100644 --- a/include/clang/Sema/Initialization.h +++ b/include/clang/Sema/Initialization.h @@ -334,30 +334,27 @@ public: }; private: - /// \brief The kind of initialization that we're storing. - enum StoredInitKind { - SIK_Direct = IK_Direct, ///< Direct initialization - SIK_DirectList = IK_DirectList, ///< Direct list-initialization - SIK_Copy = IK_Copy, ///< Copy initialization - SIK_Default = IK_Default, ///< Default initialization - SIK_Value = IK_Value, ///< Value initialization - SIK_ImplicitValue, ///< Implicit value initialization - SIK_DirectCast, ///< Direct initialization due to a cast - /// \brief Direct initialization due to a C-style cast. - SIK_DirectCStyleCast, - /// \brief Direct initialization due to a functional-style cast. - SIK_DirectFunctionalCast + /// \brief The context of the initialization. + enum InitContext { + IC_Normal, ///< Normal context + IC_Implicit, ///< Implicit context (value initialization) + IC_StaticCast, ///< Static cast context + IC_CStyleCast, ///< C-style cast context + IC_FunctionalCast ///< Functional cast context }; /// \brief The kind of initialization being performed. - StoredInitKind Kind; + InitKind Kind : 8; + + /// \brief The context of the initialization. + InitContext Context : 8; /// \brief The source locations involved in the initialization. SourceLocation Locations[3]; - InitializationKind(StoredInitKind Kind, SourceLocation Loc1, + InitializationKind(InitKind Kind, InitContext Context, SourceLocation Loc1, SourceLocation Loc2, SourceLocation Loc3) - : Kind(Kind) + : Kind(Kind), Context(Context) { Locations[0] = Loc1; Locations[1] = Loc2; @@ -369,45 +366,50 @@ public: static InitializationKind CreateDirect(SourceLocation InitLoc, SourceLocation LParenLoc, SourceLocation RParenLoc) { - return InitializationKind(SIK_Direct, InitLoc, LParenLoc, RParenLoc); + return InitializationKind(IK_Direct, IC_Normal, + InitLoc, LParenLoc, RParenLoc); } static InitializationKind CreateDirectList(SourceLocation InitLoc) { - return InitializationKind(SIK_DirectList, InitLoc, InitLoc, InitLoc); + return InitializationKind(IK_DirectList, IC_Normal, + InitLoc, InitLoc, InitLoc); } /// \brief Create a direct initialization due to a cast that isn't a C-style /// or functional cast. static InitializationKind CreateCast(SourceRange TypeRange) { - return InitializationKind(SIK_DirectCast, - TypeRange.getBegin(), TypeRange.getBegin(), - TypeRange.getEnd()); + return InitializationKind(IK_Direct, IC_StaticCast, TypeRange.getBegin(), + TypeRange.getBegin(), TypeRange.getEnd()); } /// \brief Create a direct initialization for a C-style cast. static InitializationKind CreateCStyleCast(SourceLocation StartLoc, - SourceRange TypeRange) { - return InitializationKind(SIK_DirectCStyleCast, - StartLoc, TypeRange.getBegin(), + SourceRange TypeRange, + bool InitList) { + // C++ cast syntax doesn't permit init lists, but C compound literals are + // exactly that. + return InitializationKind(InitList ? IK_DirectList : IK_Direct, + IC_CStyleCast, StartLoc, TypeRange.getBegin(), TypeRange.getEnd()); } /// \brief Create a direct initialization for a functional cast. - static InitializationKind CreateFunctionalCast(SourceRange TypeRange) { - return InitializationKind(SIK_DirectFunctionalCast, - TypeRange.getBegin(), TypeRange.getBegin(), - TypeRange.getEnd()); + static InitializationKind CreateFunctionalCast(SourceRange TypeRange, + bool InitList) { + return InitializationKind(InitList ? IK_DirectList : IK_Direct, + IC_FunctionalCast, TypeRange.getBegin(), + TypeRange.getBegin(), TypeRange.getEnd()); } /// \brief Create a copy initialization. static InitializationKind CreateCopy(SourceLocation InitLoc, SourceLocation EqualLoc) { - return InitializationKind(SIK_Copy, InitLoc, EqualLoc, EqualLoc); + return InitializationKind(IK_Copy, IC_Normal, InitLoc, EqualLoc, EqualLoc); } /// \brief Create a default initialization. static InitializationKind CreateDefault(SourceLocation InitLoc) { - return InitializationKind(SIK_Default, InitLoc, InitLoc, InitLoc); + return InitializationKind(IK_Default, IC_Normal, InitLoc, InitLoc, InitLoc); } /// \brief Create a value initialization. @@ -415,46 +417,39 @@ public: SourceLocation LParenLoc, SourceLocation RParenLoc, bool isImplicit = false) { - return InitializationKind(isImplicit? SIK_ImplicitValue : SIK_Value, + return InitializationKind(IK_Value, isImplicit ? IC_Implicit : IC_Normal, InitLoc, LParenLoc, RParenLoc); } /// \brief Determine the initialization kind. InitKind getKind() const { - if (Kind > SIK_ImplicitValue) - return IK_Direct; - if (Kind == SIK_ImplicitValue) - return IK_Value; - - return (InitKind)Kind; + return Kind; } /// \brief Determine whether this initialization is an explicit cast. bool isExplicitCast() const { - return Kind == SIK_DirectCast || - Kind == SIK_DirectCStyleCast || - Kind == SIK_DirectFunctionalCast; + return Context >= IC_StaticCast; } /// \brief Determine whether this initialization is a C-style cast. bool isCStyleOrFunctionalCast() const { - return Kind == SIK_DirectCStyleCast || Kind == SIK_DirectFunctionalCast; + return Context >= IC_CStyleCast; } - /// brief Determine whether this is a C-style cast. + /// \brief Determine whether this is a C-style cast. bool isCStyleCast() const { - return Kind == SIK_DirectCStyleCast; + return Context == IC_CStyleCast; } - /// brief Determine whether this is a functional-style cast. + /// \brief Determine whether this is a functional-style cast. bool isFunctionalCast() const { - return Kind == SIK_DirectFunctionalCast; + return Context == IC_FunctionalCast; } /// \brief Determine whether this initialization is an implicit /// value-initialization, e.g., as occurs during aggregate /// initialization. - bool isImplicitValueInit() const { return Kind == SIK_ImplicitValue; } + bool isImplicitValueInit() const { return Context == IC_Implicit; } /// \brief Retrieve the location at which initialization is occurring. SourceLocation getLocation() const { return Locations[0]; } @@ -467,11 +462,11 @@ public: /// \brief Retrieve the location of the equal sign for copy initialization /// (if present). SourceLocation getEqualLoc() const { - assert(Kind == SIK_Copy && "Only copy initialization has an '='"); + assert(Kind == IK_Copy && "Only copy initialization has an '='"); return Locations[1]; } - bool isCopyInit() const { return Kind == SIK_Copy; } + bool isCopyInit() const { return Kind == IK_Copy; } /// \brief Retrieve whether this initialization allows the use of explicit /// constructors. @@ -480,7 +475,7 @@ public: /// \brief Retrieve the source range containing the locations of the open /// and closing parentheses for value and direct initializations. SourceRange getParenRange() const { - assert((getKind() == IK_Direct || Kind == SIK_Value) && + assert((Kind == IK_Direct || Kind == IK_Value) && "Only direct- and value-initialization have parentheses"); return SourceRange(Locations[1], Locations[2]); } diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp index 545305cfc4..c74bb9a067 100644 --- a/lib/Sema/SemaCast.cpp +++ b/lib/Sema/SemaCast.cpp @@ -320,11 +320,13 @@ static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT, if (!destType->isRecordType() && !srcType->isRecordType()) return false; + bool initList = isa<InitListExpr>(src); InitializedEntity entity = InitializedEntity::InitializeTemporary(destType); InitializationKind initKind = (CT == CT_CStyle)? InitializationKind::CreateCStyleCast(range.getBegin(), - range) - : (CT == CT_Functional)? InitializationKind::CreateFunctionalCast(range) + range, initList) + : (CT == CT_Functional)? InitializationKind::CreateFunctionalCast(range, + initList) : InitializationKind::CreateCast(/*type range?*/ range); InitializationSequence sequence(S, entity, initKind, &src, 1); @@ -1301,13 +1303,16 @@ TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, return TC_Failed; } } - + + // FIXME: doesn't correctly identify T({1}) + bool InitList = isa<InitListExpr>(SrcExpr.get()); InitializedEntity Entity = InitializedEntity::InitializeTemporary(DestType); InitializationKind InitKind = (CCK == Sema::CCK_CStyleCast) - ? InitializationKind::CreateCStyleCast(OpRange.getBegin(), OpRange) + ? InitializationKind::CreateCStyleCast(OpRange.getBegin(), OpRange, + InitList) : (CCK == Sema::CCK_FunctionalCast) - ? InitializationKind::CreateFunctionalCast(OpRange) + ? InitializationKind::CreateFunctionalCast(OpRange, InitList) : InitializationKind::CreateCast(OpRange); Expr *SrcExprRaw = SrcExpr.get(); InitializationSequence InitSeq(Self, Entity, InitKind, &SrcExprRaw, 1); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 72a8de2b71..467cf43797 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2150,18 +2150,22 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, // any of the arguments are type-dependent expressions. DiscardCleanupsInEvaluationContext(); } else { + bool InitList = false; + if (isa<InitListExpr>(Init)) { + InitList = true; + Args = &Init; + NumArgs = 1; + } + // Initialize the member. InitializedEntity MemberEntity = DirectMember ? InitializedEntity::InitializeMember(DirectMember, 0) : InitializedEntity::InitializeMember(IndirectMember, 0); InitializationKind Kind = - InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(), - InitRange.getEnd()); + InitList ? InitializationKind::CreateDirectList(IdLoc) + : InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(), + InitRange.getEnd()); - if (isa<InitListExpr>(Init)) { - Args = &Init; - NumArgs = 1; - } InitializationSequence InitSeq(*this, MemberEntity, Kind, Args, NumArgs); ExprResult MemberInit = InitSeq.Perform(*this, MemberEntity, Kind, MultiExprArg(*this, Args, NumArgs), @@ -2214,20 +2218,23 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init, << TInfo->getTypeLoc().getLocalSourceRange(); Diag(NameLoc, diag::warn_cxx98_compat_delegating_ctor); - SourceRange InitRange = Init->getSourceRange(); - // Initialize the object. - InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation( - QualType(ClassDecl->getTypeForDecl(), 0)); - InitializationKind Kind = - InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(), - InitRange.getEnd()); - + bool InitList = true; Expr **Args = &Init; unsigned NumArgs = 1; if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { + InitList = false; Args = ParenList->getExprs(); NumArgs = ParenList->getNumExprs(); } + + SourceRange InitRange = Init->getSourceRange(); + // Initialize the object. + InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation( + QualType(ClassDecl->getTypeForDecl(), 0)); + InitializationKind Kind = + InitList ? InitializationKind::CreateDirectList(NameLoc) + : InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(), + InitRange.getEnd()); InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args, NumArgs); ExprResult DelegationInit = InitSeq.Perform(*this, DelegationEntity, Kind, MultiExprArg(*this, Args,NumArgs), @@ -2341,18 +2348,21 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, BaseSpec = const_cast<CXXBaseSpecifier *>(VirtualBaseSpec); // Initialize the base. - InitializedEntity BaseEntity = - InitializedEntity::InitializeBase(Context, BaseSpec, VirtualBaseSpec); - InitializationKind Kind = - InitializationKind::CreateDirect(BaseLoc, InitRange.getBegin(), - InitRange.getEnd()); - + bool InitList = true; Expr **Args = &Init; unsigned NumArgs = 1; if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { + InitList = false; Args = ParenList->getExprs(); NumArgs = ParenList->getNumExprs(); } + + InitializedEntity BaseEntity = + InitializedEntity::InitializeBase(Context, BaseSpec, VirtualBaseSpec); + InitializationKind Kind = + InitList ? InitializationKind::CreateDirectList(BaseLoc) + : InitializationKind::CreateDirect(BaseLoc, InitRange.getBegin(), + InitRange.getEnd()); InitializationSequence InitSeq(*this, BaseEntity, Kind, Args, NumArgs); ExprResult BaseInit = InitSeq.Perform(*this, BaseEntity, Kind, MultiExprArg(*this, Args, NumArgs), diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 946b2a07af..ce5956ae2f 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -3809,7 +3809,8 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo, = InitializedEntity::InitializeTemporary(literalType); InitializationKind Kind = InitializationKind::CreateCStyleCast(LParenLoc, - SourceRange(LParenLoc, RParenLoc)); + SourceRange(LParenLoc, RParenLoc), + /*InitList=*/true); InitializationSequence InitSeq(*this, Entity, Kind, &LiteralExpr, 1); ExprResult Result = InitSeq.Perform(*this, Entity, Kind, MultiExprArg(*this, &LiteralExpr, 1), diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index c5d4913539..8376c0d66b 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -3970,11 +3970,13 @@ InitializationSequence::InitializationSequence(Sema &S, SourceType = Initializer->getType(); } - // - If the initializer is a braced-init-list, the object is - // list-initialized (8.5.4). - if (InitListExpr *InitList = dyn_cast_or_null<InitListExpr>(Initializer)) { - TryListInitialization(S, Entity, Kind, InitList, *this); - return; + // - If the initializer is a (non-parenthesized) braced-init-list, the + // object is list-initialized (8.5.4). + if (Kind.getKind() != InitializationKind::IK_Direct) { + 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. diff --git a/test/SemaCXX/cxx0x-initializer-aggregates.cpp b/test/SemaCXX/cxx0x-initializer-aggregates.cpp index d8b79deb62..b716d81834 100644 --- a/test/SemaCXX/cxx0x-initializer-aggregates.cpp +++ b/test/SemaCXX/cxx0x-initializer-aggregates.cpp @@ -56,4 +56,6 @@ namespace aggregate { // String is not default-constructible static_assert(sizeof(overloaded({1})) == sizeof(one), "bad overload"); } + + struct C { int a[2]; C():a({1, 2}) { } }; // expected-error {{array initializer must be an initializer list}} } diff --git a/test/SemaCXX/cxx0x-initializer-references.cpp b/test/SemaCXX/cxx0x-initializer-references.cpp index f84f1be7d5..fb962641de 100644 --- a/test/SemaCXX/cxx0x-initializer-references.cpp +++ b/test/SemaCXX/cxx0x-initializer-references.cpp @@ -71,4 +71,9 @@ namespace reference { static_assert(sizeof(h({1, 2})) == sizeof(two), "bad overload resolution"); } + void edge_cases() { + // FIXME: very poor error message + int const &b({0}); // expected-error {{could not bind}} + } + } diff --git a/test/SemaCXX/cxx0x-initializer-scalars.cpp b/test/SemaCXX/cxx0x-initializer-scalars.cpp index e0843c2246..7d2b5b3ab9 100644 --- a/test/SemaCXX/cxx0x-initializer-scalars.cpp +++ b/test/SemaCXX/cxx0x-initializer-scalars.cpp @@ -55,4 +55,9 @@ namespace integral { emptylist({}); emptylist({}, {}, {}); } + + void edge_cases() { + // FIXME: very poor error message + int a({0}); // expected-error {{cannot initialize}} + } } diff --git a/test/SemaCXX/generalized-initializers.cpp b/test/SemaCXX/generalized-initializers.cpp deleted file mode 100644 index 1228d300d1..0000000000 --- a/test/SemaCXX/generalized-initializers.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s -// XFAIL: * - -template <typename T, typename U> -struct same_type { static const bool value = false; }; -template <typename T> -struct same_type<T, T> { static const bool value = true; }; - -namespace std { - typedef decltype(sizeof(int)) size_t; - - // libc++'s implementation - template <class _E> - class initializer_list - { - const _E* __begin_; - size_t __size_; - - initializer_list(const _E* __b, size_t __s) - : __begin_(__b), - __size_(__s) - {} - - public: - typedef _E value_type; - typedef const _E& reference; - typedef const _E& const_reference; - typedef size_t size_type; - - typedef const _E* iterator; - typedef const _E* const_iterator; - - initializer_list() : __begin_(nullptr), __size_(0) {} - - size_t size() const {return __size_;} - const _E* begin() const {return __begin_;} - const _E* end() const {return __begin_ + __size_;} - }; -} - -namespace litb { - - // invalid - struct A { int a[2]; A():a({1, 2}) { } }; // expected-error {{}} - - // invalid - int a({0}); // expected-error {{}} - - // invalid - int const &b({0}); // expected-error {{}} - -} |