aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Sema/Initialization.h93
-rw-r--r--lib/Sema/SemaCast.cpp15
-rw-r--r--lib/Sema/SemaDeclCXX.cpp50
-rw-r--r--lib/Sema/SemaExpr.cpp3
-rw-r--r--lib/Sema/SemaInit.cpp12
-rw-r--r--test/SemaCXX/cxx0x-initializer-aggregates.cpp2
-rw-r--r--test/SemaCXX/cxx0x-initializer-references.cpp5
-rw-r--r--test/SemaCXX/cxx0x-initializer-scalars.cpp5
-rw-r--r--test/SemaCXX/generalized-initializers.cpp52
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 {{}}
-
-}