|
@@ -1663,7 +1663,7 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
|
|
|
SourceLocation PlacementLParen, MultiExprArg PlacementArgs,
|
|
|
SourceLocation PlacementRParen, SourceRange TypeIdParens,
|
|
|
Declarator &D, Expr *Initializer) {
|
|
|
- Expr *ArraySize = nullptr;
|
|
|
+ Optional<Expr *> ArraySize;
|
|
|
// If the specified type is an array, unwrap it and save the expression.
|
|
|
if (D.getNumTypeObjects() > 0 &&
|
|
|
D.getTypeObject(0).Kind == DeclaratorChunk::Array) {
|
|
@@ -1674,7 +1674,7 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
|
|
|
if (Chunk.Arr.hasStatic)
|
|
|
return ExprError(Diag(Chunk.Loc, diag::err_static_illegal_in_new)
|
|
|
<< D.getSourceRange());
|
|
|
- if (!Chunk.Arr.NumElts)
|
|
|
+ if (!Chunk.Arr.NumElts && !Initializer)
|
|
|
return ExprError(Diag(Chunk.Loc, diag::err_array_new_needs_size)
|
|
|
<< D.getSourceRange());
|
|
|
|
|
@@ -1787,7 +1787,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
|
|
|
SourceRange TypeIdParens,
|
|
|
QualType AllocType,
|
|
|
TypeSourceInfo *AllocTypeInfo,
|
|
|
- Expr *ArraySize,
|
|
|
+ Optional<Expr *> ArraySize,
|
|
|
SourceRange DirectInitRange,
|
|
|
Expr *Initializer) {
|
|
|
SourceRange TypeRange = AllocTypeInfo->getTypeLoc().getSourceRange();
|
|
@@ -1838,9 +1838,11 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
|
|
|
auto *Deduced = AllocType->getContainedDeducedType();
|
|
|
if (Deduced && isa<DeducedTemplateSpecializationType>(Deduced)) {
|
|
|
if (ArraySize)
|
|
|
- return ExprError(Diag(ArraySize->getExprLoc(),
|
|
|
- diag::err_deduced_class_template_compound_type)
|
|
|
- << /*array*/ 2 << ArraySize->getSourceRange());
|
|
|
+ return ExprError(
|
|
|
+ Diag(ArraySize ? (*ArraySize)->getExprLoc() : TypeRange.getBegin(),
|
|
|
+ diag::err_deduced_class_template_compound_type)
|
|
|
+ << /*array*/ 2
|
|
|
+ << (ArraySize ? (*ArraySize)->getSourceRange() : TypeRange));
|
|
|
|
|
|
InitializedEntity Entity
|
|
|
= InitializedEntity::InitializeNew(StartLoc, AllocType);
|
|
@@ -1906,8 +1908,9 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
|
|
|
|
|
|
QualType ResultType = Context.getPointerType(AllocType);
|
|
|
|
|
|
- if (ArraySize && ArraySize->getType()->isNonOverloadPlaceholderType()) {
|
|
|
- ExprResult result = CheckPlaceholderExpr(ArraySize);
|
|
|
+ if (ArraySize && *ArraySize &&
|
|
|
+ (*ArraySize)->getType()->isNonOverloadPlaceholderType()) {
|
|
|
+ ExprResult result = CheckPlaceholderExpr(*ArraySize);
|
|
|
if (result.isInvalid()) return ExprError();
|
|
|
ArraySize = result.get();
|
|
|
}
|
|
@@ -1919,19 +1922,19 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
|
|
|
// C++1y [expr.new]p6: The expression [...] is implicitly converted to
|
|
|
// std::size_t.
|
|
|
llvm::Optional<uint64_t> KnownArraySize;
|
|
|
- if (ArraySize && !ArraySize->isTypeDependent()) {
|
|
|
+ if (ArraySize && *ArraySize && !(*ArraySize)->isTypeDependent()) {
|
|
|
ExprResult ConvertedSize;
|
|
|
if (getLangOpts().CPlusPlus14) {
|
|
|
assert(Context.getTargetInfo().getIntWidth() && "Builtin type of size 0?");
|
|
|
|
|
|
- ConvertedSize = PerformImplicitConversion(ArraySize, Context.getSizeType(),
|
|
|
+ ConvertedSize = PerformImplicitConversion(*ArraySize, Context.getSizeType(),
|
|
|
AA_Converting);
|
|
|
|
|
|
if (!ConvertedSize.isInvalid() &&
|
|
|
- ArraySize->getType()->getAs<RecordType>())
|
|
|
+ (*ArraySize)->getType()->getAs<RecordType>())
|
|
|
// Diagnose the compatibility of this conversion.
|
|
|
Diag(StartLoc, diag::warn_cxx98_compat_array_size_conversion)
|
|
|
- << ArraySize->getType() << 0 << "'size_t'";
|
|
|
+ << (*ArraySize)->getType() << 0 << "'size_t'";
|
|
|
} else {
|
|
|
class SizeConvertDiagnoser : public ICEConvertDiagnoser {
|
|
|
protected:
|
|
@@ -1985,16 +1988,16 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
|
|
|
: diag::ext_array_size_conversion)
|
|
|
<< T << ConvTy->isEnumeralType() << ConvTy;
|
|
|
}
|
|
|
- } SizeDiagnoser(ArraySize);
|
|
|
+ } SizeDiagnoser(*ArraySize);
|
|
|
|
|
|
- ConvertedSize = PerformContextualImplicitConversion(StartLoc, ArraySize,
|
|
|
+ ConvertedSize = PerformContextualImplicitConversion(StartLoc, *ArraySize,
|
|
|
SizeDiagnoser);
|
|
|
}
|
|
|
if (ConvertedSize.isInvalid())
|
|
|
return ExprError();
|
|
|
|
|
|
ArraySize = ConvertedSize.get();
|
|
|
- QualType SizeType = ArraySize->getType();
|
|
|
+ QualType SizeType = (*ArraySize)->getType();
|
|
|
|
|
|
if (!SizeType->isIntegralOrUnscopedEnumerationType())
|
|
|
return ExprError();
|
|
@@ -2006,18 +2009,18 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
|
|
|
// Let's see if this is a constant < 0. If so, we reject it out of hand,
|
|
|
// per CWG1464. Otherwise, if it's not a constant, we must have an
|
|
|
// unparenthesized array type.
|
|
|
- if (!ArraySize->isValueDependent()) {
|
|
|
+ if (!(*ArraySize)->isValueDependent()) {
|
|
|
llvm::APSInt Value;
|
|
|
// We've already performed any required implicit conversion to integer or
|
|
|
// unscoped enumeration type.
|
|
|
// FIXME: Per CWG1464, we are required to check the value prior to
|
|
|
// converting to size_t. This will never find a negative array size in
|
|
|
// C++14 onwards, because Value is always unsigned here!
|
|
|
- if (ArraySize->isIntegerConstantExpr(Value, Context)) {
|
|
|
+ if ((*ArraySize)->isIntegerConstantExpr(Value, Context)) {
|
|
|
if (Value.isSigned() && Value.isNegative()) {
|
|
|
- return ExprError(Diag(ArraySize->getBeginLoc(),
|
|
|
+ return ExprError(Diag((*ArraySize)->getBeginLoc(),
|
|
|
diag::err_typecheck_negative_array_size)
|
|
|
- << ArraySize->getSourceRange());
|
|
|
+ << (*ArraySize)->getSourceRange());
|
|
|
}
|
|
|
|
|
|
if (!AllocType->isDependentType()) {
|
|
@@ -2025,15 +2028,15 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
|
|
|
ConstantArrayType::getNumAddressingBits(Context, AllocType, Value);
|
|
|
if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context))
|
|
|
return ExprError(
|
|
|
- Diag(ArraySize->getBeginLoc(), diag::err_array_too_large)
|
|
|
- << Value.toString(10) << ArraySize->getSourceRange());
|
|
|
+ Diag((*ArraySize)->getBeginLoc(), diag::err_array_too_large)
|
|
|
+ << Value.toString(10) << (*ArraySize)->getSourceRange());
|
|
|
}
|
|
|
|
|
|
KnownArraySize = Value.getZExtValue();
|
|
|
} else if (TypeIdParens.isValid()) {
|
|
|
// Can't have dynamic array size when the type-id is in parentheses.
|
|
|
- Diag(ArraySize->getBeginLoc(), diag::ext_new_paren_array_nonconst)
|
|
|
- << ArraySize->getSourceRange()
|
|
|
+ Diag((*ArraySize)->getBeginLoc(), diag::ext_new_paren_array_nonconst)
|
|
|
+ << (*ArraySize)->getSourceRange()
|
|
|
<< FixItHint::CreateRemoval(TypeIdParens.getBegin())
|
|
|
<< FixItHint::CreateRemoval(TypeIdParens.getEnd());
|
|
|
|
|
@@ -2056,10 +2059,10 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
|
|
|
AllocationFunctionScope Scope = UseGlobal ? AFS_Global : AFS_Both;
|
|
|
if (!AllocType->isDependentType() &&
|
|
|
!Expr::hasAnyTypeDependentArguments(PlacementArgs) &&
|
|
|
- FindAllocationFunctions(StartLoc,
|
|
|
- SourceRange(PlacementLParen, PlacementRParen),
|
|
|
- Scope, Scope, AllocType, ArraySize, PassAlignment,
|
|
|
- PlacementArgs, OperatorNew, OperatorDelete))
|
|
|
+ FindAllocationFunctions(
|
|
|
+ StartLoc, SourceRange(PlacementLParen, PlacementRParen), Scope, Scope,
|
|
|
+ AllocType, ArraySize.hasValue(), PassAlignment, PlacementArgs,
|
|
|
+ OperatorNew, OperatorDelete))
|
|
|
return ExprError();
|
|
|
|
|
|
// If this is an array allocation, compute whether the usual array
|
|
@@ -2152,6 +2155,22 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
|
|
|
FullInit = Binder->getSubExpr();
|
|
|
|
|
|
Initializer = FullInit.get();
|
|
|
+
|
|
|
+ // FIXME: If we have a KnownArraySize, check that the array bound of the
|
|
|
+ // initializer is no greater than that constant value.
|
|
|
+
|
|
|
+ if (ArraySize && !*ArraySize) {
|
|
|
+ auto *CAT = Context.getAsConstantArrayType(Initializer->getType());
|
|
|
+ if (CAT) {
|
|
|
+ // FIXME: Track that the array size was inferred rather than explicitly
|
|
|
+ // specified.
|
|
|
+ ArraySize = IntegerLiteral::Create(
|
|
|
+ Context, CAT->getSize(), Context.getSizeType(), TypeRange.getEnd());
|
|
|
+ } else {
|
|
|
+ Diag(TypeRange.getEnd(), diag::err_new_array_size_unknown_from_init)
|
|
|
+ << Initializer->getSourceRange();
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// Mark the new and delete operators as referenced.
|