aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-01-18 23:55:52 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-01-18 23:55:52 +0000
commit8ef7b203332b0c8d65876a1f5e6d1db4e6f40e4b (patch)
treedee9b186a48a66f3c8be5c56c4e774338408bece /lib/Sema/SemaDecl.cpp
parentd6c7c67313634b317a0d63c32be0511a121bb33d (diff)
constexpr: converted constant expression handling for enumerator values, case
values and non-type template arguments of integral and enumeration types. This change causes some legal C++98 code to no longer compile in C++11 mode, by enforcing the C++11 rule that narrowing integral conversions are not permitted in the final implicit conversion sequence for the above cases. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148439 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r--lib/Sema/SemaDecl.cpp46
1 files changed, 28 insertions, 18 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index f2af0a7075..9dc00c3625 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -9555,18 +9555,30 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
if (Enum->isDependentType() || Val->isTypeDependent())
EltTy = Context.DependentTy;
else {
- // C99 6.7.2.2p2: Make sure we have an integer constant expression.
SourceLocation ExpLoc;
- if (!Val->isValueDependent() &&
- VerifyIntegerConstantExpression(Val, &EnumVal)) {
+ if (getLangOptions().CPlusPlus0x && Enum->isFixed()) {
+ // C++11 [dcl.enum]p5: If the underlying type is fixed, [...] the
+ // constant-expression in the enumerator-definition shall be a converted
+ // constant expression of the underlying type.
+ EltTy = Enum->getIntegerType();
+ ExprResult Converted =
+ CheckConvertedConstantExpression(Val, EltTy, EnumVal,
+ CCEK_Enumerator);
+ if (Converted.isInvalid())
+ Val = 0;
+ else
+ Val = Converted.take();
+ } else if (!Val->isValueDependent() &&
+ VerifyIntegerConstantExpression(Val, &EnumVal)) {
+ // C99 6.7.2.2p2: Make sure we have an integer constant expression.
Val = 0;
- } else {
+ } else {
if (!getLangOptions().CPlusPlus) {
// C99 6.7.2.2p2:
// The expression that defines the value of an enumeration constant
- // shall be an integer constant expression that has a value
+ // shall be an integer constant expression that has a value
// representable as an int.
-
+
// Complain if the value is not representable in an int.
if (!isRepresentableIntegerValue(Context, EnumVal, Context.IntTy))
Diag(IdLoc, diag::ext_enum_value_not_int)
@@ -9577,25 +9589,24 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
Val = ImpCastExprToType(Val, Context.IntTy, CK_IntegralCast).take();
}
}
-
+
if (Enum->isFixed()) {
EltTy = Enum->getIntegerType();
- // C++0x [dcl.enum]p5:
- // ... if the initializing value of an enumerator cannot be
- // represented by the underlying type, the program is ill-formed.
+ // In Obj-C and Microsoft mode, require the enumeration value to be
+ // representable in the underlying type of the enumeration. In C++11,
+ // we perform a non-narrowing conversion as part of converted constant
+ // expression checking.
if (!isRepresentableIntegerValue(Context, EnumVal, EltTy)) {
if (getLangOptions().MicrosoftExt) {
Diag(IdLoc, diag::ext_enumerator_too_large) << EltTy;
Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).take();
- } else
- Diag(IdLoc, diag::err_enumerator_too_large)
- << EltTy;
+ } else
+ Diag(IdLoc, diag::err_enumerator_too_large) << EltTy;
} else
Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).take();
- }
- else {
- // C++0x [dcl.enum]p5:
+ } else {
+ // C++11 [dcl.enum]p5:
// If the underlying type is not fixed, the type of each enumerator
// is the type of its initializing value:
// - If an initializer is specified for an enumerator, the
@@ -9700,11 +9711,10 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
SourceLocation IdLoc, IdentifierInfo *Id,
AttributeList *Attr,
- SourceLocation EqualLoc, Expr *val) {
+ SourceLocation EqualLoc, Expr *Val) {
EnumDecl *TheEnumDecl = cast<EnumDecl>(theEnumDecl);
EnumConstantDecl *LastEnumConst =
cast_or_null<EnumConstantDecl>(lastEnumConst);
- Expr *Val = static_cast<Expr*>(val);
// The scope passed in may not be a decl scope. Zip up the scope tree until
// we find one that is.