Change the way we store initialization kinds so that all direct inits can distinguish between list and parens form. This allows us to correctly diagnose the last test cases from litb.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150343 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Sebastian Redl 2012-02-12 16:37:36 +00:00
Родитель 168319c81b
Коммит 3a45c0e61d
9 изменённых файлов: 106 добавлений и 133 удалений

Просмотреть файл

@ -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]);
}

Просмотреть файл

@ -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);
@ -1302,12 +1304,15 @@ TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
}
}
// 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);

Просмотреть файл

@ -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(),
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);
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 =
InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(),
InitList ? InitializationKind::CreateDirectList(NameLoc)
: InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(),
InitRange.getEnd());
Expr **Args = &Init;
unsigned NumArgs = 1;
if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
Args = ParenList->getExprs();
NumArgs = ParenList->getNumExprs();
}
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),

Просмотреть файл

@ -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),

Просмотреть файл

@ -3970,12 +3970,14 @@ InitializationSequence::InitializationSequence(Sema &S,
SourceType = Initializer->getType();
}
// - If the initializer is a braced-init-list, the object is
// list-initialized (8.5.4).
// - 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.
if (DestType->isReferenceType()) {

Просмотреть файл

@ -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}}
}

Просмотреть файл

@ -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}}
}
}

Просмотреть файл

@ -55,4 +55,9 @@ namespace integral {
emptylist({});
emptylist({}, {}, {});
}
void edge_cases() {
// FIXME: very poor error message
int a({0}); // expected-error {{cannot initialize}}
}
}

Просмотреть файл

@ -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 {{}}
}