aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td3
-rw-r--r--include/clang/Sema/Sema.h3
-rw-r--r--lib/Sema/SemaExprCXX.cpp12
-rw-r--r--lib/Sema/SemaOverload.cpp25
-rw-r--r--lib/Sema/SemaStmt.cpp3
-rw-r--r--test/SemaCXX/enum-scoped.cpp2
-rw-r--r--test/SemaCXX/new-delete.cpp4
7 files changed, 36 insertions, 16 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index ab724b53c4..2138d1de98 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3976,7 +3976,8 @@ def err_placement_new_non_placement_delete : Error<
"'new' expression with placement arguments refers to non-placement "
"'operator delete'">;
def err_array_size_not_integral : Error<
- "array size expression must have integral or enumerated type, not %0">;
+ "array size expression must have integral or %select{|unscoped }0"
+ "enumeration type, not %1">;
def err_array_size_incomplete_type : Error<
"array size expression has incomplete class type %0">;
def err_array_size_explicit_conversion : Error<
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 6a9384daec..2069dc9704 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -1443,7 +1443,8 @@ public:
const PartialDiagnostic &ExplicitConvNote,
const PartialDiagnostic &AmbigDiag,
const PartialDiagnostic &AmbigNote,
- const PartialDiagnostic &ConvDiag);
+ const PartialDiagnostic &ConvDiag,
+ bool AllowScopedEnumerations);
ExprResult PerformObjectMemberConversion(Expr *From,
NestedNameSpecifier *Qualifier,
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index a0fb6e44d9..158e02a450 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -995,12 +995,15 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
QualType ResultType = Context.getPointerType(AllocType);
- // C++ 5.3.4p6: "The expression in a direct-new-declarator shall have integral
- // or enumeration type with a non-negative value."
+ // C++98 5.3.4p6: "The expression in a direct-new-declarator shall have
+ // integral or enumeration type with a non-negative value."
+ // C++11 [expr.new]p6: The expression [...] shall be of integral or unscoped
+ // enumeration type, or a class type for which a single non-explicit
+ // conversion function to integral or unscoped enumeration type exists.
if (ArraySize && !ArraySize->isTypeDependent()) {
ExprResult ConvertedSize = ConvertToIntegralOrEnumerationType(
StartLoc, ArraySize,
- PDiag(diag::err_array_size_not_integral),
+ PDiag(diag::err_array_size_not_integral) << getLangOptions().CPlusPlus0x,
PDiag(diag::err_array_size_incomplete_type)
<< ArraySize->getSourceRange(),
PDiag(diag::err_array_size_explicit_conversion),
@@ -1009,7 +1012,8 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
PDiag(diag::note_array_size_conversion),
PDiag(getLangOptions().CPlusPlus0x ?
diag::warn_cxx98_compat_array_size_conversion :
- diag::ext_array_size_conversion));
+ diag::ext_array_size_conversion),
+ /*AllowScopedEnumerations*/ false);
if (ConvertedSize.isInvalid())
return ExprError();
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 98212454b8..9527c0f298 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -4763,6 +4763,13 @@ ExprResult Sema::PerformContextuallyConvertToObjCPointer(Expr *From) {
return ExprError();
}
+/// Determine whether the provided type is an integral type, or an enumeration
+/// type of a permitted flavor.
+static bool isIntegralOrEnumerationType(QualType T, bool AllowScopedEnum) {
+ return AllowScopedEnum ? T->isIntegralOrEnumerationType()
+ : T->isIntegralOrUnscopedEnumerationType();
+}
+
/// \brief Attempt to convert the given expression to an integral or
/// enumeration type.
///
@@ -4797,6 +4804,9 @@ ExprResult Sema::PerformContextuallyConvertToObjCPointer(Expr *From) {
/// \param ConvDiag The diagnostic to be emitted if we are calling a conversion
/// function, which may be an extension in this case.
///
+/// \param AllowScopedEnumerations Specifies whether conversions to scoped
+/// enumerations should be considered.
+///
/// \returns The expression, converted to an integral or enumeration type if
/// successful.
ExprResult
@@ -4807,7 +4817,8 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From,
const PartialDiagnostic &ExplicitConvNote,
const PartialDiagnostic &AmbigDiag,
const PartialDiagnostic &AmbigNote,
- const PartialDiagnostic &ConvDiag) {
+ const PartialDiagnostic &ConvDiag,
+ bool AllowScopedEnumerations) {
// We can't perform any more checking for type-dependent expressions.
if (From->isTypeDependent())
return Owned(From);
@@ -4821,7 +4832,7 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From,
// If the expression already has integral or enumeration type, we're golden.
QualType T = From->getType();
- if (T->isIntegralOrEnumerationType())
+ if (isIntegralOrEnumerationType(T, AllowScopedEnumerations))
return DefaultLvalueConversion(From);
// FIXME: Check for missing '()' if T is a function type?
@@ -4852,14 +4863,16 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From,
I != E;
++I) {
if (CXXConversionDecl *Conversion
- = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl()))
- if (Conversion->getConversionType().getNonReferenceType()
- ->isIntegralOrEnumerationType()) {
+ = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) {
+ if (isIntegralOrEnumerationType(
+ Conversion->getConversionType().getNonReferenceType(),
+ AllowScopedEnumerations)) {
if (Conversion->isExplicit())
ExplicitConversions.addDecl(I.getDecl(), I.getAccess());
else
ViableConversions.addDecl(I.getDecl(), I.getAccess());
}
+ }
}
switch (ViableConversions.size()) {
@@ -4947,7 +4960,7 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From,
return Owned(From);
}
- if (!From->getType()->isIntegralOrEnumerationType())
+ if (!isIntegralOrEnumerationType(From->getType(), AllowScopedEnumerations))
Diag(Loc, NotIntDiag)
<< From->getType() << From->getSourceRange();
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 6d5824a969..42b608e631 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -504,7 +504,8 @@ Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond,
PDiag(diag::note_switch_conversion),
PDiag(diag::err_switch_multiple_conversions),
PDiag(diag::note_switch_conversion),
- PDiag(0));
+ PDiag(0),
+ /*AllowScopedEnumerations*/ true);
if (CondResult.isInvalid()) return StmtError();
Cond = CondResult.take();
diff --git a/test/SemaCXX/enum-scoped.cpp b/test/SemaCXX/enum-scoped.cpp
index 791fcf153e..8938c8229c 100644
--- a/test/SemaCXX/enum-scoped.cpp
+++ b/test/SemaCXX/enum-scoped.cpp
@@ -34,7 +34,7 @@ int a1[Val2];
int a2[E1::Val1]; // expected-error{{size of array has non-integer type}}
int* p1 = new int[Val2];
-int* p2 = new int[E1::Val1]; // FIXME Expected-error{{must have integral}}
+int* p2 = new int[E1::Val1]; // expected-error{{array size expression must have integral or unscoped enumeration type, not 'E1'}}
enum class E4 {
e1 = -2147483648, // ok
diff --git a/test/SemaCXX/new-delete.cpp b/test/SemaCXX/new-delete.cpp
index 9cc290cbd7..45d4f3d0ec 100644
--- a/test/SemaCXX/new-delete.cpp
+++ b/test/SemaCXX/new-delete.cpp
@@ -65,7 +65,7 @@ void bad_news(int *ip)
(void)new; // expected-error {{expected a type}}
(void)new 4; // expected-error {{expected a type}}
(void)new () int; // expected-error {{expected expression}}
- (void)new int[1.1]; // expected-error {{array size expression must have integral or enumerated type, not 'double'}}
+ (void)new int[1.1]; // expected-error {{array size expression must have integral or enumeration type, not 'double'}}
(void)new int[1][i]; // expected-error {{only the first dimension}}
(void)new (int[1][i]); // expected-error {{only the first dimension}}
(void)new (int[i]); // expected-warning {{when type is in parentheses}}
@@ -78,7 +78,7 @@ void bad_news(int *ip)
// Undefined, but clang should reject it directly.
(void)new int[-1]; // expected-error {{array size is negative}}
(void)new int[2000000000]; // expected-error {{array is too large}}
- (void)new int[*(S*)0]; // expected-error {{array size expression must have integral or enumerated type, not 'S'}}
+ (void)new int[*(S*)0]; // expected-error {{array size expression must have integral or enumeration type, not 'S'}}
(void)::S::new int; // expected-error {{expected unqualified-id}}
(void)new (0, 0) int; // expected-error {{no matching function for call to 'operator new'}}
(void)new (0L) int; // expected-error {{call to 'operator new' is ambiguous}}