aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaType.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-02-04 09:53:13 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-02-04 09:53:13 +0000
commit282e7e66748cc6dd14d6f7f2cb52e5373c531e61 (patch)
tree65a943e4a9c8a0534b580dcbbbcb6791451b5a56 /lib/Sema/SemaType.cpp
parentf39aec17b89f8f0dd78e78c50ad2fa08f12272e3 (diff)
In C++11 mode, when an integral constant expression is desired and we have a
value of class type, look for a unique conversion operator converting to integral or unscoped enumeration type and use that. Implements [expr.const]p5. Sema::VerifyIntegerConstantExpression now performs the conversion and returns the converted result. Some important callers of Expr::isIntegralConstantExpr have been switched over to using it (including all of those required for C++11 conformance); this switch brings a side-benefit of improved diagnostics and, in several cases, simpler code. However, some language extensions and attributes have not been moved across and will not perform implicit conversions on constant expressions of literal class type where an ICE is required. In passing, fix static_assert to perform a contextual conversion to bool on its argument. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149776 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaType.cpp')
-rw-r--r--lib/Sema/SemaType.cpp56
1 files changed, 27 insertions, 29 deletions
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 684f355bfb..d613c395d3 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -1178,19 +1178,12 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
/// Check whether the specified array size makes the array type a VLA. If so,
/// return true, if not, return the size of the array in SizeVal.
-static bool isArraySizeVLA(Expr *ArraySize, llvm::APSInt &SizeVal, Sema &S) {
- // If the size is an ICE, it certainly isn't a VLA.
- if (ArraySize->isIntegerConstantExpr(SizeVal, S.Context))
- return false;
-
- // If we're in a GNU mode (like gnu99, but not c99) accept any evaluatable
- // value as an extension.
- if (S.LangOpts.GNUMode && ArraySize->EvaluateAsInt(SizeVal, S.Context)) {
- S.Diag(ArraySize->getLocStart(), diag::ext_vla_folded_to_constant);
- return false;
- }
-
- return true;
+static bool isArraySizeVLA(Sema &S, Expr *ArraySize, llvm::APSInt &SizeVal) {
+ // 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.
+ return S.VerifyIntegerConstantExpression(
+ ArraySize, &SizeVal, S.PDiag(), S.LangOpts.GNUMode,
+ S.PDiag(diag::ext_vla_folded_to_constant)).isInvalid();
}
@@ -1285,14 +1278,15 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
}
// C99 6.7.5.2p1: The size expression shall have integer type.
- // TODO: in theory, if we were insane, we could allow contextual
- // conversions to integer type here.
- if (ArraySize && !ArraySize->isTypeDependent() &&
+ // C++11 allows contextual conversions to such types.
+ if (!getLangOptions().CPlusPlus0x &&
+ ArraySize && !ArraySize->isTypeDependent() &&
!ArraySize->getType()->isIntegralOrUnscopedEnumerationType()) {
Diag(ArraySize->getLocStart(), diag::err_array_size_non_int)
<< ArraySize->getType() << ArraySize->getSourceRange();
return QualType();
}
+
llvm::APSInt ConstVal(Context.getTypeSize(Context.getSizeType()));
if (!ArraySize) {
if (ASM == ArrayType::Star)
@@ -1301,11 +1295,19 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
T = Context.getIncompleteArrayType(T, ASM, Quals);
} else if (ArraySize->isTypeDependent() || ArraySize->isValueDependent()) {
T = Context.getDependentSizedArrayType(T, ArraySize, ASM, Quals, Brackets);
- } else if (!T->isDependentType() && !T->isIncompleteType() &&
- !T->isConstantSizeType()) {
+ } else if ((!T->isDependentType() && !T->isIncompleteType() &&
+ !T->isConstantSizeType()) ||
+ isArraySizeVLA(*this, ArraySize, ConstVal)) {
+ // Even in C++11, don't allow contextual conversions in the array bound
+ // of a VLA.
+ if (getLangOptions().CPlusPlus0x &&
+ !ArraySize->getType()->isIntegralOrUnscopedEnumerationType()) {
+ Diag(ArraySize->getLocStart(), diag::err_array_size_non_int)
+ << ArraySize->getType() << ArraySize->getSourceRange();
+ return QualType();
+ }
+
// C99: an array with an element type that has a non-constant-size is a VLA.
- T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets);
- } else if (isArraySizeVLA(ArraySize, ConstVal, *this)) {
// C99: an array with a non-ICE size is a VLA. We accept any expression
// that we can fold to a non-zero positive value as an extension.
T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets);
@@ -2283,15 +2285,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
NoexceptExpr->getType()->getCanonicalTypeUnqualified() ==
Context.BoolTy) &&
"Parser should have made sure that the expression is boolean");
- SourceLocation ErrLoc;
- llvm::APSInt Dummy;
- if (!NoexceptExpr->isValueDependent() &&
- !NoexceptExpr->isIntegerConstantExpr(Dummy, Context, &ErrLoc,
- /*evaluated*/false))
- S.Diag(ErrLoc, diag::err_noexcept_needs_constant_expression)
- << NoexceptExpr->getSourceRange();
- else
- EPI.NoexceptExpr = NoexceptExpr;
+ if (!NoexceptExpr->isValueDependent())
+ NoexceptExpr = S.VerifyIntegerConstantExpression(NoexceptExpr, 0,
+ S.PDiag(diag::err_noexcept_needs_constant_expression),
+ /*AllowFold*/ false).take();
+ EPI.NoexceptExpr = NoexceptExpr;
}
} else if (FTI.getExceptionSpecType() == EST_None &&
ImplicitlyNoexcept && chunkIndex == 0) {