for array bounds, not "integer constant" rules.
For an array bound of class type, this causes us to perform an implicit
conversion to size_t, instead of looking for a unique conversion to
integral or unscoped enumeration type. This affects which cases are
valid when a class has multiple implicit conversion functions to
different types.
CCEK_CaseValue, ///< Expression in a case label.
CCEK_Enumerator, ///< Enumerator value with fixed underlying type.
CCEK_TemplateArg, ///< Value of a non-type template parameter.
- CCEK_NewExpr, ///< Constant expression in a noptr-new-declarator.
+ CCEK_ArrayBound, ///< Array bound in array declarator or new-expression.
CCEK_ConstexprIf, ///< Condition in a constexpr if statement.
CCEK_ExplicitBool ///< Condition in an explicit(bool) specifier.
};
// C++1y [expr.new]p6: Every constant-expression in a noptr-new-declarator
// shall be a converted constant expression (5.19) of type std::size_t
// and shall evaluate to a strictly positive value.
- unsigned IntWidth = Context.getTargetInfo().getIntWidth();
- assert(IntWidth && "Builtin type of size 0?");
- llvm::APSInt Value(IntWidth);
+ llvm::APSInt Value(Context.getIntWidth(Context.getSizeType()));
Array.NumElts
= CheckConvertedConstantExpression(NumElts, Context.getSizeType(), Value,
- CCEK_NewExpr)
+ CCEK_ArrayBound)
.get();
} else {
Array.NumElts
return Result;
// Check for a narrowing implicit conversion.
+ bool ReturnPreNarrowingValue = false;
APValue PreNarrowingValue;
QualType PreNarrowingType;
switch (SCS->getNarrowingKind(S.Context, Result.get(), PreNarrowingValue,
break;
case NK_Constant_Narrowing:
+ if (CCE == Sema::CCEK_ArrayBound &&
+ PreNarrowingType->isIntegralOrEnumerationType() &&
+ PreNarrowingValue.isInt()) {
+ // Don't diagnose array bound narrowing here; we produce more precise
+ // errors by allowing the un-narrowed value through.
+ ReturnPreNarrowingValue = true;
+ break;
+ }
S.Diag(From->getBeginLoc(), diag::ext_cce_narrowing)
<< CCE << /*Constant*/ 1
<< PreNarrowingValue.getAsString(S.Context, PreNarrowingType) << T;
break;
case NK_Type_Narrowing:
+ // FIXME: It would be better to diagnose that the expression is not a
+ // constant expression.
S.Diag(From->getBeginLoc(), diag::ext_cce_narrowing)
<< CCE << /*Constant*/ 0 << From->getType() << T;
break;
if (Notes.empty()) {
// It's a constant expression.
- return ConstantExpr::Create(S.Context, Result.get(), Value);
+ Expr *E = ConstantExpr::Create(S.Context, Result.get(), Value);
+ if (ReturnPreNarrowingValue)
+ Value = std::move(PreNarrowingValue);
+ return E;
}
}
static ExprResult checkArraySize(Sema &S, Expr *&ArraySize,
llvm::APSInt &SizeVal, unsigned VLADiag,
bool VLAIsError) {
+ if (S.getLangOpts().CPlusPlus14 &&
+ (VLAIsError ||
+ !ArraySize->getType()->isIntegralOrUnscopedEnumerationType())) {
+ // C++14 [dcl.array]p1:
+ // The constant-expression shall be a converted constant expression of
+ // type std::size_t.
+ //
+ // Don't apply this rule if we might be forming a VLA: in that case, we
+ // allow non-constant expressions and constant-folding. We only need to use
+ // the converted constant expression rules (to properly convert the source)
+ // when the source expression is of class type.
+ return S.CheckConvertedConstantExpression(
+ ArraySize, S.Context.getSizeType(), SizeVal, Sema::CCEK_ArrayBound);
+ }
+
// If the size is an ICE, it certainly isn't a VLA. If we're in a GNU mode
// (like gnu99, but not c99) accept any evaluatable value as an extension.
class VLADiagnoser : public Sema::VerifyICEDiagnoser {
-// RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only %s
-// RUN: %clang_cc1 -std=c++1y %s -verify -DCXX1Y
+// RUN: %clang_cc1 -std=c++11 -verify=expected,cxx11 -fsyntax-only -pedantic-errors %s
+// RUN: %clang_cc1 -std=c++14 -verify=expected,cxx14 -fsyntax-only -pedantic-errors %s -DCXX1Y
// Explicit member declarations behave as in C++11.
#endif
namespace extended_examples_array_bounds {
-
+
typedef decltype(sizeof(int)) size_t;
-
- struct Foo {
- operator size_t(); // @162
- operator unsigned short(); // @163
+
+ struct X {
+ constexpr operator size_t() const { return 1; } // cxx11-note 3{{conversion}}
+ constexpr operator unsigned short() const { return 0; } // cxx11-note 3{{conversion}}
};
- void bar() {
- Foo x;
- int *p = new int[x]; // @168
+ void f() {
+ X x;
+ int *p = new int[x]; // cxx11-error {{ambiguous}}
+
+ int arr[x]; // cxx11-error {{ambiguous}}
+ int (*q)[1] = new int[1][x]; // cxx11-error {{ambiguous}}
}
-}
-#ifdef CXX1Y
-#else
-//expected-error@168 {{ambiguous conversion of array size expression of type 'extended_examples_array_bounds::Foo' to an integral or enumeration type}}
-//expected-note@162 {{conversion to integral type 'extended_examples_array_bounds::size_t'}}
-//expected-note@163 {{conversion to integral type 'unsigned short' declared here}}
-#endif
+ struct Y {
+ constexpr operator float() const { return 0.0f; } // cxx14-note 3{{candidate}}
+ constexpr operator int() const { return 1; } // cxx14-note 3{{candidate}}
+ };
+
+ void g() {
+ Y y;
+ int *p = new int[y]; // cxx14-error {{ambiguous}}
+
+ int arr[y]; // cxx14-error {{ambiguous}}
+ int (*q)[1] = new int[1][y]; // cxx14-error {{ambiguous}}
+ }
+
+ template<int N> struct Z {
+ constexpr operator int() const { return N; }
+ };
+ void h() {
+ int arrA[Z<1>()];
+ int arrB[Z<0>()]; // expected-error {{zero size array}}
+ int arrC[Z<-1>()]; // expected-error {{'arrC' declared as an array with a negative size}}
+ }
+}