зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
168319c81b
Коммит
3a45c0e61d
|
@ -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 {{}}
|
||||
|
||||
}
|
Загрузка…
Ссылка в новой задаче