|
@@ -1228,17 +1228,6 @@ Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep,
|
|
|
if (!TInfo)
|
|
|
TInfo = Context.getTrivialTypeSourceInfo(Ty, SourceLocation());
|
|
|
|
|
|
- // Handle errors like: int({0})
|
|
|
- if (exprs.size() == 1 && !canInitializeWithParenthesizedList(Ty) &&
|
|
|
- LParenLoc.isValid() && RParenLoc.isValid())
|
|
|
- if (auto IList = dyn_cast<InitListExpr>(exprs[0])) {
|
|
|
- Diag(TInfo->getTypeLoc().getLocStart(), diag::err_list_init_in_parens)
|
|
|
- << Ty << IList->getSourceRange()
|
|
|
- << FixItHint::CreateRemoval(LParenLoc)
|
|
|
- << FixItHint::CreateRemoval(RParenLoc);
|
|
|
- LParenLoc = RParenLoc = SourceLocation();
|
|
|
- }
|
|
|
-
|
|
|
auto Result = BuildCXXTypeConstructExpr(TInfo, LParenLoc, exprs, RParenLoc);
|
|
|
// Avoid creating a non-type-dependent expression that contains typos.
|
|
|
// Non-type-dependent expressions are liable to be discarded without
|
|
@@ -1295,46 +1284,51 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
|
|
|
}
|
|
|
|
|
|
// C++ [expr.type.conv]p1:
|
|
|
- // If the expression list is a single expression, the type conversion
|
|
|
- // expression is equivalent (in definedness, and if defined in meaning) to the
|
|
|
- // corresponding cast expression.
|
|
|
- if (Exprs.size() == 1 && !ListInitialization) {
|
|
|
+ // If the expression list is a parenthesized single expression, the type
|
|
|
+ // conversion expression is equivalent (in definedness, and if defined in
|
|
|
+ // meaning) to the corresponding cast expression.
|
|
|
+ if (Exprs.size() == 1 && !ListInitialization &&
|
|
|
+ !isa<InitListExpr>(Exprs[0])) {
|
|
|
Expr *Arg = Exprs[0];
|
|
|
return BuildCXXFunctionalCastExpr(TInfo, Ty, LParenLoc, Arg, RParenLoc);
|
|
|
}
|
|
|
|
|
|
- // C++14 [expr.type.conv]p2: The expression T(), where T is a
|
|
|
- // simple-type-specifier or typename-specifier for a non-array complete
|
|
|
- // object type or the (possibly cv-qualified) void type, creates a prvalue
|
|
|
- // of the specified type, whose value is that produced by value-initializing
|
|
|
- // an object of type T.
|
|
|
+ // For an expression of the form T(), T shall not be an array type.
|
|
|
QualType ElemTy = Ty;
|
|
|
if (Ty->isArrayType()) {
|
|
|
if (!ListInitialization)
|
|
|
- return ExprError(Diag(TyBeginLoc,
|
|
|
- diag::err_value_init_for_array_type) << FullRange);
|
|
|
+ return ExprError(Diag(TyBeginLoc, diag::err_value_init_for_array_type)
|
|
|
+ << FullRange);
|
|
|
ElemTy = Context.getBaseElementType(Ty);
|
|
|
}
|
|
|
|
|
|
- if (!ListInitialization && Ty->isFunctionType())
|
|
|
- return ExprError(Diag(TyBeginLoc, diag::err_value_init_for_function_type)
|
|
|
- << FullRange);
|
|
|
+ // There doesn't seem to be an explicit rule against this but sanity demands
|
|
|
+ // we only construct objects with object types.
|
|
|
+ if (Ty->isFunctionType())
|
|
|
+ return ExprError(Diag(TyBeginLoc, diag::err_init_for_function_type)
|
|
|
+ << Ty << FullRange);
|
|
|
|
|
|
+ // C++17 [expr.type.conv]p2:
|
|
|
+ // If the type is cv void and the initializer is (), the expression is a
|
|
|
+ // prvalue of the specified type that performs no initialization.
|
|
|
if (!Ty->isVoidType() &&
|
|
|
RequireCompleteType(TyBeginLoc, ElemTy,
|
|
|
diag::err_invalid_incomplete_type_use, FullRange))
|
|
|
return ExprError();
|
|
|
|
|
|
+ // Otherwise, the expression is a prvalue of the specified type whose
|
|
|
+ // result object is direct-initialized (11.6) with the initializer.
|
|
|
InitializationSequence InitSeq(*this, Entity, Kind, Exprs);
|
|
|
ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Exprs);
|
|
|
|
|
|
- if (Result.isInvalid() || !ListInitialization)
|
|
|
+ if (Result.isInvalid())
|
|
|
return Result;
|
|
|
|
|
|
Expr *Inner = Result.get();
|
|
|
if (CXXBindTemporaryExpr *BTE = dyn_cast_or_null<CXXBindTemporaryExpr>(Inner))
|
|
|
Inner = BTE->getSubExpr();
|
|
|
- if (!isa<CXXTemporaryObjectExpr>(Inner)) {
|
|
|
+ if (!isa<CXXTemporaryObjectExpr>(Inner) &&
|
|
|
+ !isa<CXXScalarValueInitExpr>(Inner)) {
|
|
|
// If we created a CXXTemporaryObjectExpr, that node also represents the
|
|
|
// functional cast. Otherwise, create an explicit cast to represent
|
|
|
// the syntactic form of a functional-style cast that was used here.
|
|
@@ -1590,20 +1584,8 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
|
|
|
return ExprError();
|
|
|
|
|
|
SourceRange DirectInitRange;
|
|
|
- if (ParenListExpr *List = dyn_cast_or_null<ParenListExpr>(Initializer)) {
|
|
|
+ if (ParenListExpr *List = dyn_cast_or_null<ParenListExpr>(Initializer))
|
|
|
DirectInitRange = List->getSourceRange();
|
|
|
- // Handle errors like: new int a({0})
|
|
|
- if (List->getNumExprs() == 1 &&
|
|
|
- !canInitializeWithParenthesizedList(AllocType))
|
|
|
- if (auto IList = dyn_cast<InitListExpr>(List->getExpr(0))) {
|
|
|
- Diag(TInfo->getTypeLoc().getLocStart(), diag::err_list_init_in_parens)
|
|
|
- << AllocType << List->getSourceRange()
|
|
|
- << FixItHint::CreateRemoval(List->getLocStart())
|
|
|
- << FixItHint::CreateRemoval(List->getLocEnd());
|
|
|
- DirectInitRange = SourceRange();
|
|
|
- Initializer = IList;
|
|
|
- }
|
|
|
- }
|
|
|
|
|
|
return BuildCXXNew(SourceRange(StartLoc, D.getLocEnd()), UseGlobal,
|
|
|
PlacementLParen,
|