forked from OSchip/llvm-project
Proper initializer list support for new expressions and type construct expressions. Array new still missing.
llvm-svn: 150346
This commit is contained in:
parent
1a22d2889b
commit
d74dd49065
|
@ -1232,6 +1232,8 @@ def err_auto_var_requires_init : Error<
|
|||
"declaration of variable %0 with type %1 requires an initializer">;
|
||||
def err_auto_new_requires_ctor_arg : Error<
|
||||
"new expression for type %0 requires a constructor argument">;
|
||||
def err_auto_new_requires_parens : Error<
|
||||
"new expression for type %0 cannot use list-initialization">;
|
||||
def err_auto_var_init_no_expression : Error<
|
||||
"initializer for variable %0 with type %1 is empty">;
|
||||
def err_auto_var_init_multiple_expressions : Error<
|
||||
|
@ -1257,6 +1259,10 @@ def err_implied_std_initializer_list_not_found : Error<
|
|||
"not found; include <initializer_list>">;
|
||||
def err_malformed_std_initializer_list : Error<
|
||||
"std::initializer_list must be a class template with a single type parameter">;
|
||||
def warn_dangling_std_initializer_list : Warning<
|
||||
"array backing the initializer list will be destroyed at the end of "
|
||||
"%select{the full-expression|the constructor}0">,
|
||||
InGroup<DiagGroup<"dangling-initializer-list">>;
|
||||
|
||||
// C++11 override control
|
||||
def override_keyword_only_allowed_on_virtual_member_functions : Error<
|
||||
|
|
|
@ -1151,10 +1151,13 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
|
|||
&& "Expected '(' or '{'!");
|
||||
|
||||
if (Tok.is(tok::l_brace)) {
|
||||
|
||||
// FIXME: Convert to a proper type construct expression.
|
||||
return ParseBraceInitializer();
|
||||
|
||||
ExprResult Init = ParseBraceInitializer();
|
||||
if (Init.isInvalid())
|
||||
return Init;
|
||||
Expr *InitList = Init.take();
|
||||
return Actions.ActOnCXXTypeConstructExpr(TypeRep, SourceLocation(),
|
||||
MultiExprArg(&InitList, 1),
|
||||
SourceLocation());
|
||||
} else {
|
||||
GreaterThanIsOperatorScope G(GreaterThanIsOperator, true);
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ namespace {
|
|||
void CheckReinterpretCast();
|
||||
void CheckStaticCast();
|
||||
void CheckDynamicCast();
|
||||
void CheckCXXCStyleCast(bool FunctionalCast);
|
||||
void CheckCXXCStyleCast(bool FunctionalCast, bool ListInitialization);
|
||||
void CheckCStyleCast();
|
||||
|
||||
/// Complete an apparently-successful cast operation that yields
|
||||
|
@ -190,15 +190,15 @@ static TryCastResult TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr,
|
|||
QualType DestType,
|
||||
Sema::CheckedConversionKind CCK,
|
||||
const SourceRange &OpRange,
|
||||
unsigned &msg,
|
||||
CastKind &Kind);
|
||||
unsigned &msg, CastKind &Kind,
|
||||
bool ListInitialization);
|
||||
static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
|
||||
QualType DestType,
|
||||
Sema::CheckedConversionKind CCK,
|
||||
const SourceRange &OpRange,
|
||||
unsigned &msg,
|
||||
CastKind &Kind,
|
||||
CXXCastPath &BasePath);
|
||||
unsigned &msg, CastKind &Kind,
|
||||
CXXCastPath &BasePath,
|
||||
bool ListInitialization);
|
||||
static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
|
||||
bool CStyle, unsigned &msg);
|
||||
static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
|
||||
|
@ -752,7 +752,7 @@ void CastOperation::CheckStaticCast() {
|
|||
unsigned msg = diag::err_bad_cxx_cast_generic;
|
||||
TryCastResult tcr
|
||||
= TryStaticCast(Self, SrcExpr, DestType, Sema::CCK_OtherCast, OpRange, msg,
|
||||
Kind, BasePath);
|
||||
Kind, BasePath, /*ListInitialization=*/false);
|
||||
if (tcr != TC_Success && msg != 0) {
|
||||
if (SrcExpr.isInvalid())
|
||||
return;
|
||||
|
@ -782,8 +782,8 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
|
|||
QualType DestType,
|
||||
Sema::CheckedConversionKind CCK,
|
||||
const SourceRange &OpRange, unsigned &msg,
|
||||
CastKind &Kind,
|
||||
CXXCastPath &BasePath) {
|
||||
CastKind &Kind, CXXCastPath &BasePath,
|
||||
bool ListInitialization) {
|
||||
// Determine whether we have the semantics of a C-style cast.
|
||||
bool CStyle
|
||||
= (CCK == Sema::CCK_CStyleCast || CCK == Sema::CCK_FunctionalCast);
|
||||
|
@ -808,23 +808,23 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
|
|||
// C++ 5.2.9p5, reference downcast.
|
||||
// See the function for details.
|
||||
// DR 427 specifies that this is to be applied before paragraph 2.
|
||||
tcr = TryStaticReferenceDowncast(Self, SrcExpr.get(), DestType, CStyle, OpRange,
|
||||
msg, Kind, BasePath);
|
||||
tcr = TryStaticReferenceDowncast(Self, SrcExpr.get(), DestType, CStyle,
|
||||
OpRange, msg, Kind, BasePath);
|
||||
if (tcr != TC_NotApplicable)
|
||||
return tcr;
|
||||
|
||||
// C++0x [expr.static.cast]p3:
|
||||
// A glvalue of type "cv1 T1" can be cast to type "rvalue reference to cv2
|
||||
// T2" if "cv2 T2" is reference-compatible with "cv1 T1".
|
||||
tcr = TryLValueToRValueCast(Self, SrcExpr.get(), DestType, CStyle, Kind, BasePath,
|
||||
msg);
|
||||
tcr = TryLValueToRValueCast(Self, SrcExpr.get(), DestType, CStyle, Kind,
|
||||
BasePath, msg);
|
||||
if (tcr != TC_NotApplicable)
|
||||
return tcr;
|
||||
|
||||
// C++ 5.2.9p2: An expression e can be explicitly converted to a type T
|
||||
// [...] if the declaration "T t(e);" is well-formed, [...].
|
||||
tcr = TryStaticImplicitCast(Self, SrcExpr, DestType, CCK, OpRange, msg,
|
||||
Kind);
|
||||
Kind, ListInitialization);
|
||||
if (SrcExpr.isInvalid())
|
||||
return TC_Failed;
|
||||
if (tcr != TC_NotApplicable)
|
||||
|
@ -1295,7 +1295,7 @@ TryCastResult
|
|||
TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
|
||||
Sema::CheckedConversionKind CCK,
|
||||
const SourceRange &OpRange, unsigned &msg,
|
||||
CastKind &Kind) {
|
||||
CastKind &Kind, bool ListInitialization) {
|
||||
if (DestType->isRecordType()) {
|
||||
if (Self.RequireCompleteType(OpRange.getBegin(), DestType,
|
||||
diag::err_bad_dynamic_cast_incomplete)) {
|
||||
|
@ -1304,15 +1304,13 @@ 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,
|
||||
InitList)
|
||||
ListInitialization)
|
||||
: (CCK == Sema::CCK_FunctionalCast)
|
||||
? InitializationKind::CreateFunctionalCast(OpRange, InitList)
|
||||
? InitializationKind::CreateFunctionalCast(OpRange, ListInitialization)
|
||||
: InitializationKind::CreateCast(OpRange);
|
||||
Expr *SrcExprRaw = SrcExpr.get();
|
||||
InitializationSequence InitSeq(Self, Entity, InitKind, &SrcExprRaw, 1);
|
||||
|
@ -1756,7 +1754,8 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
|
|||
return TC_Success;
|
||||
}
|
||||
|
||||
void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle) {
|
||||
void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
|
||||
bool ListInitialization) {
|
||||
// Handle placeholders.
|
||||
if (isPlaceholder()) {
|
||||
// C-style casts can resolve __unknown_any types.
|
||||
|
@ -1839,7 +1838,7 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle) {
|
|||
if (tcr == TC_NotApplicable) {
|
||||
// ... or if that is not possible, a static_cast, ignoring const, ...
|
||||
tcr = TryStaticCast(Self, SrcExpr, DestType, CCK, OpRange,
|
||||
msg, Kind, BasePath);
|
||||
msg, Kind, BasePath, ListInitialization);
|
||||
if (SrcExpr.isInvalid())
|
||||
return;
|
||||
|
||||
|
@ -2073,7 +2072,8 @@ ExprResult Sema::BuildCStyleCastExpr(SourceLocation LPLoc,
|
|||
Op.OpRange = SourceRange(LPLoc, CastExpr->getLocEnd());
|
||||
|
||||
if (getLangOptions().CPlusPlus) {
|
||||
Op.CheckCXXCStyleCast(/*FunctionalStyle=*/ false);
|
||||
Op.CheckCXXCStyleCast(/*FunctionalStyle=*/ false,
|
||||
isa<InitListExpr>(CastExpr));
|
||||
} else {
|
||||
Op.CheckCStyleCast();
|
||||
}
|
||||
|
@ -2090,11 +2090,14 @@ ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo,
|
|||
SourceLocation LPLoc,
|
||||
Expr *CastExpr,
|
||||
SourceLocation RPLoc) {
|
||||
bool ListInitialization = LPLoc.isInvalid();
|
||||
assert((!ListInitialization || isa<InitListExpr>(CastExpr)) &&
|
||||
"List initialization must have initializer list as expression.");
|
||||
CastOperation Op(*this, CastTypeInfo->getType(), CastExpr);
|
||||
Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange();
|
||||
Op.OpRange = SourceRange(Op.DestRange.getBegin(), CastExpr->getLocEnd());
|
||||
|
||||
Op.CheckCXXCStyleCast(/*FunctionalStyle=*/ true);
|
||||
Op.CheckCXXCStyleCast(/*FunctionalStyle=*/ true, ListInitialization);
|
||||
if (Op.SrcExpr.isInvalid())
|
||||
return ExprError();
|
||||
|
||||
|
|
|
@ -767,7 +767,6 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
|
|||
unsigned NumExprs = exprs.size();
|
||||
Expr **Exprs = (Expr**)exprs.get();
|
||||
SourceLocation TyBeginLoc = TInfo->getTypeLoc().getBeginLoc();
|
||||
SourceRange FullRange = SourceRange(TyBeginLoc, RParenLoc);
|
||||
|
||||
if (Ty->isDependentType() ||
|
||||
CallExpr::hasAnyTypeDependentArguments(Exprs, NumExprs)) {
|
||||
|
@ -779,6 +778,12 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
|
|||
RParenLoc));
|
||||
}
|
||||
|
||||
bool ListInitialization = LParenLoc.isInvalid();
|
||||
assert((!ListInitialization || (NumExprs == 1 && isa<InitListExpr>(Exprs[0])))
|
||||
&& "List initialization must have initializer list as expression.");
|
||||
SourceRange FullRange = SourceRange(TyBeginLoc,
|
||||
ListInitialization ? Exprs[0]->getSourceRange().getEnd() : RParenLoc);
|
||||
|
||||
if (Ty->isArrayType())
|
||||
return ExprError(Diag(TyBeginLoc,
|
||||
diag::err_value_init_for_array_type) << FullRange);
|
||||
|
@ -872,11 +877,24 @@ static bool doesUsualArrayDeleteWantSize(Sema &S, SourceLocation loc,
|
|||
return (del->getNumParams() == 2);
|
||||
}
|
||||
|
||||
/// ActOnCXXNew - Parsed a C++ 'new' expression (C++ 5.3.4), as in e.g.:
|
||||
/// \brief Parsed a C++ 'new' expression (C++ 5.3.4).
|
||||
|
||||
/// E.g.:
|
||||
/// @code new (memory) int[size][4] @endcode
|
||||
/// or
|
||||
/// @code ::new Foo(23, "hello") @endcode
|
||||
/// For the interpretation of this heap of arguments, consult the base version.
|
||||
///
|
||||
/// \param StartLoc The first location of the expression.
|
||||
/// \param UseGlobal True if 'new' was prefixed with '::'.
|
||||
/// \param PlacementLParen Opening paren of the placement arguments.
|
||||
/// \param PlacementArgs Placement new arguments.
|
||||
/// \param PlacementRParen Closing paren of the placement arguments.
|
||||
/// \param TypeIdParens If the type is in parens, the source range.
|
||||
/// \param D The type to be allocated, as well as array dimensions.
|
||||
/// \param ConstructorLParen Opening paren of the constructor args, empty if
|
||||
/// initializer-list syntax is used.
|
||||
/// \param ConstructorArgs Constructor/initialization arguments.
|
||||
/// \param ConstructorRParen Closing paren of the constructor args.
|
||||
ExprResult
|
||||
Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
|
||||
SourceLocation PlacementLParen, MultiExprArg PlacementArgs,
|
||||
|
@ -968,14 +986,18 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
|
|||
diag::err_auto_new_ctor_multiple_expressions)
|
||||
<< AllocType << TypeRange);
|
||||
}
|
||||
Expr *Deduce = ConstructorArgs.get()[0];
|
||||
if (ConstructorLParen.isInvalid()) {
|
||||
return ExprError(Diag(Deduce->getSourceRange().getBegin(),
|
||||
diag::err_auto_new_requires_parens)
|
||||
<< AllocType << TypeRange);
|
||||
}
|
||||
TypeSourceInfo *DeducedType = 0;
|
||||
if (DeduceAutoType(AllocTypeInfo, ConstructorArgs.get()[0], DeducedType) ==
|
||||
if (DeduceAutoType(AllocTypeInfo, Deduce, DeducedType) ==
|
||||
DAR_Failed)
|
||||
return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure)
|
||||
<< AllocType
|
||||
<< ConstructorArgs.get()[0]->getType()
|
||||
<< TypeRange
|
||||
<< ConstructorArgs.get()[0]->getSourceRange());
|
||||
<< AllocType << Deduce->getType()
|
||||
<< TypeRange << Deduce->getSourceRange());
|
||||
if (!DeducedType)
|
||||
return ExprError();
|
||||
|
||||
|
@ -998,6 +1020,17 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
|
|||
if (CheckAllocatedType(AllocType, TypeRange.getBegin(), TypeRange))
|
||||
return ExprError();
|
||||
|
||||
bool ListInitialization = ConstructorLParen.isInvalid() &&
|
||||
ConstructorArgs.size() > 0;
|
||||
assert((!ListInitialization || (ConstructorArgs.size() == 1 &&
|
||||
isa<InitListExpr>(ConstructorArgs.get()[0])))
|
||||
&& "List initialization means a braced-init-list for arguments.");
|
||||
if (ListInitialization && isStdInitializerList(AllocType, 0)) {
|
||||
Diag(AllocTypeInfo->getTypeLoc().getBeginLoc(),
|
||||
diag::warn_dangling_std_initializer_list)
|
||||
<< /*at end of FE*/0 << ConstructorArgs.get()[0]->getSourceRange();
|
||||
}
|
||||
|
||||
// In ARC, infer 'retaining' for the allocated
|
||||
if (getLangOptions().ObjCAutoRefCount &&
|
||||
AllocType.getObjCLifetime() == Qualifiers::OCL_None &&
|
||||
|
@ -1153,7 +1186,7 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
|
|||
}
|
||||
}
|
||||
|
||||
bool Init = ConstructorLParen.isValid();
|
||||
bool Init = ConstructorLParen.isValid() || ConstructorArgs.size() > 0;
|
||||
// --- Choosing a constructor ---
|
||||
CXXConstructorDecl *Constructor = 0;
|
||||
bool HadMultipleCandidates = false;
|
||||
|
@ -1172,7 +1205,7 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
|
|||
|
||||
if (!AllocType->isDependentType() &&
|
||||
!Expr::hasAnyTypeDependentArguments(ConsArgs, NumConsArgs)) {
|
||||
// C++0x [expr.new]p15:
|
||||
// C++11 [expr.new]p15:
|
||||
// A new-expression that creates an object of type T initializes that
|
||||
// object as follows:
|
||||
InitializationKind Kind
|
||||
|
@ -1182,9 +1215,12 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
|
|||
= !Init? InitializationKind::CreateDefault(TypeRange.getBegin())
|
||||
// - Otherwise, the new-initializer is interpreted according to the
|
||||
// initialization rules of 8.5 for direct-initialization.
|
||||
: InitializationKind::CreateDirect(TypeRange.getBegin(),
|
||||
ConstructorLParen,
|
||||
ConstructorRParen);
|
||||
: ListInitialization ? InitializationKind::CreateDirectList(
|
||||
TypeRange.getBegin())
|
||||
: InitializationKind::CreateDirect(
|
||||
TypeRange.getBegin(),
|
||||
ConstructorLParen,
|
||||
ConstructorRParen);
|
||||
|
||||
InitializedEntity Entity
|
||||
= InitializedEntity::InitializeNew(StartLoc, AllocType);
|
||||
|
|
|
@ -27,6 +27,13 @@ namespace aggregate {
|
|||
S s5{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; // expected-error {{cannot omit braces}}
|
||||
}
|
||||
|
||||
void bracing_new() {
|
||||
new S{ {1, 2}, {3, 4}, { {5}, {6} }, { {7, 8} } }; // completely braced
|
||||
new S{ 1, 2, 3, 4, 5, 6 }; // expected-error 5 {{cannot omit braces}}
|
||||
new S{ {1, 2}, {3, 4}, {5, 6}, { {7, 8} } }; // expected-error 2 {{cannot omit braces}}
|
||||
new S{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; // expected-error {{cannot omit braces}}
|
||||
}
|
||||
|
||||
struct String {
|
||||
String(const char*);
|
||||
};
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace integral {
|
|||
}
|
||||
|
||||
void inline_init() {
|
||||
(void) int{1};
|
||||
auto v = int{1};
|
||||
(void) new int{1};
|
||||
}
|
||||
|
||||
|
@ -59,5 +59,7 @@ namespace integral {
|
|||
void edge_cases() {
|
||||
// FIXME: very poor error message
|
||||
int a({0}); // expected-error {{cannot initialize}}
|
||||
(void) int({0}); // expected-error {{functional-style cast}}
|
||||
new int({0}); // expected-error {{cannot initialize}}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -122,3 +122,8 @@ void auto_deduction() {
|
|||
|
||||
for (int i : {1, 2, 3, 4}) {}
|
||||
}
|
||||
|
||||
void dangle() {
|
||||
new auto{1, 2, 3}; // expected-error {{cannot use list-initialization}}
|
||||
new std::initializer_list<int>{1, 2, 3}; // expected-warning {{at the end of the full-expression}}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,8 @@ void Lambda() {
|
|||
int InitList() {
|
||||
(void)new int {}; // expected-warning {{generalized initializer lists are incompatible with C++98}} \
|
||||
// expected-warning {{scalar initialized from empty initializer list is incompatible with C++98}}
|
||||
(void)int{}; // expected-warning {{generalized initializer lists are incompatible with C++98}}
|
||||
(void)int{}; // expected-warning {{generalized initializer lists are incompatible with C++98}} \
|
||||
// expected-warning {{scalar initialized from empty initializer list is incompatible with C++98}}
|
||||
int x { 0 }; // expected-warning {{generalized initializer lists are incompatible with C++98}}
|
||||
return { 0 }; // expected-warning {{generalized initializer lists are incompatible with C++98}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue