diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp index ba2fc80590..be61d735d7 100644 --- a/Sema/SemaDecl.cpp +++ b/Sema/SemaDecl.cpp @@ -936,6 +936,9 @@ Sema::DeclTy *Sema::ParseEnumConstant(Scope *S, DeclTy *theEnumDecl, llvm::APSInt EnumVal(32); QualType EltTy; if (Val) { + // Make sure to promote the operand type to int. + UsualUnaryConversions(Val); + // C99 6.7.2.2p2: Make sure we have an integer constant expression. SourceLocation ExpLoc; if (!Val->isIntegerConstantExpr(EnumVal, Context, &ExpLoc)) { @@ -952,17 +955,19 @@ Sema::DeclTy *Sema::ParseEnumConstant(Scope *S, DeclTy *theEnumDecl, // Assign the last value + 1. EnumVal = LastEnumConst->getInitVal(); ++EnumVal; - // FIXME: detect overflow! + + // Check for overflow on increment. + if (EnumVal < LastEnumConst->getInitVal()) + Diag(IdLoc, diag::warn_enum_value_overflow); + EltTy = LastEnumConst->getType(); } else { // First value, set to zero. EltTy = Context.IntTy; - // FIXME: Resize EnumVal to the size of int. + EnumVal.zextOrTrunc(Context.getTypeSize(EltTy, IdLoc)); } } - // TODO: Default promotions to int/uint. - // TODO: If the result value doesn't fit in an int, it must be a long or long // long value. ISO C does not support this, but GCC does as an extension, // emit a warning. diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index 6714854972..1ca8cf0b3a 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -285,6 +285,8 @@ DIAG(ext_mixed_decls_code, EXTENSION, DIAG(ext_empty_struct_union_enum, EXTENSION, "use of empty %0 extension") +DIAG(warn_enum_value_overflow, WARNING, + "overflow in enumeration value") DIAG(ext_ident_list_in_param, EXTENSION, "type-less parameter names in function declaration")