[cfe-commits] r41532 - in /cfe/trunk: Sema/SemaDecl.cpp include/clang/Basic/DiagnosticKinds.def include/clang/Basic/TargetInfo.h test/Sema/enum.c
Chris Lattner
sabre at nondot.org
Mon Aug 27 23:15:16 PDT 2007
Author: lattner
Date: Tue Aug 28 01:15:15 2007
New Revision: 41532
URL: http://llvm.org/viewvc/llvm-project?rev=41532&view=rev
Log:
compute the required destination type for an enum, emitting various warnings.
TODO: update the types of the constants and the enum.
Added:
cfe/trunk/test/Sema/enum.c
Modified:
cfe/trunk/Sema/SemaDecl.cpp
cfe/trunk/include/clang/Basic/DiagnosticKinds.def
cfe/trunk/include/clang/Basic/TargetInfo.h
Modified: cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaDecl.cpp?rev=41532&r1=41531&r2=41532&view=diff
==============================================================================
--- cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/Sema/SemaDecl.cpp Tue Aug 28 01:15:15 2007
@@ -987,10 +987,17 @@
// 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.
- unsigned IntWidth = Context.getTypeSize(Context.IntTy, Enum->getLocation());
+ unsigned IntWidth = Context.Target.getIntWidth(Enum->getLocation());
- // Verify that all the values are okay, and reverse the list.
+ // Verify that all the values are okay, compute the size of the values, and
+ // reverse the list.
+ unsigned NumNegativeBits = 0;
+ unsigned NumPositiveBits = 0;
+
+ // Keep track of whether all elements have type int.
+ bool AllElementsInt = true;
+
EnumConstantDecl *EltList = 0;
for (unsigned i = 0; i != NumElements; ++i) {
EnumConstantDecl *ECD =
@@ -1009,11 +1016,58 @@
Diag(ECD->getLocation(), diag::ext_enum_value_not_int,
InitVal.toString());
}
+
+ // Keep track of the size of positive and negative values.
+ if (InitVal.isUnsigned() || !InitVal.isNegative())
+ NumPositiveBits = std::max(NumPositiveBits, InitVal.getActiveBits());
+ else
+ NumNegativeBits = std::max(NumNegativeBits, InitVal.getMinSignedBits());
+ // Keep track of whether every enum element has type int (very commmon).
+ if (AllElementsInt)
+ AllElementsInt = ECD->getType() == Context.IntTy;
+
ECD->setNextDeclarator(EltList);
EltList = ECD;
}
+ // Figure out the type that should be used for this enum.
+ // FIXME: Support attribute(packed) on enums and -fshort-enums.
+ QualType BestType;
+
+ if (NumNegativeBits) {
+ // If there is a negative value, figure out the smallest integer type (of
+ // int/long/longlong) that fits.
+ if (NumNegativeBits <= IntWidth && NumPositiveBits < IntWidth)
+ BestType = Context.IntTy;
+ else {
+ unsigned LongWidth = Context.Target.getLongWidth(Enum->getLocation());
+ if (NumNegativeBits <= LongWidth && NumPositiveBits < LongWidth)
+ BestType = Context.LongTy;
+ else {
+ unsigned LLWidth = Context.Target.getLongLongWidth(Enum->getLocation());
+ if (NumNegativeBits > LLWidth || NumPositiveBits >= LLWidth)
+ Diag(Enum->getLocation(), diag::warn_enum_too_large);
+ BestType = Context.LongLongTy;
+ }
+ }
+ } else {
+ // If there is no negative value, figure out which of uint, ulong, ulonglong
+ // fits.
+ if (NumPositiveBits <= IntWidth)
+ BestType = Context.UnsignedIntTy;
+ else if (NumPositiveBits <=Context.Target.getLongWidth(Enum->getLocation()))
+ BestType = Context.UnsignedLongTy;
+ else {
+ assert(NumPositiveBits <=
+ Context.Target.getLongLongWidth(Enum->getLocation()) &&
+ "How could an initializer get larger than ULL?");
+ BestType = Context.UnsignedLongLongTy;
+ }
+ }
+
+ // FIXME: Install type in Enum and constant values.
+
Enum->defineElements(EltList);
}
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=41532&r1=41531&r2=41532&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Tue Aug 28 01:15:15 2007
@@ -522,6 +522,8 @@
"enumerator value for '%0' is not an integer constant")
DIAG(ext_enum_value_not_int, EXTENSION,
"ISO C restricts enumerator values to range of 'int' (%0 is too large)")
+DIAG(warn_enum_too_large, WARNING,
+ "enumeration values exceed range of largest integer")
DIAG(err_case_label_not_integer_constant_expr, ERROR,
"case label does not reduce to an integer constant")
DIAG(err_typecheck_illegal_vla, ERROR,
Modified: cfe/trunk/include/clang/Basic/TargetInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TargetInfo.h?rev=41532&r1=41531&r2=41532&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TargetInfo.h (original)
+++ cfe/trunk/include/clang/Basic/TargetInfo.h Tue Aug 28 01:15:15 2007
@@ -219,6 +219,17 @@
return Size;
}
+ unsigned getLongWidth(SourceLocation Loc) {
+ uint64_t Size; unsigned Align;
+ getLongInfo(Size, Align, Loc);
+ return Size;
+ }
+
+ unsigned getLongLongWidth(SourceLocation Loc) {
+ uint64_t Size; unsigned Align;
+ getLongLongInfo(Size, Align, Loc);
+ return Size;
+ }
private:
void ComputeWCharInfo(SourceLocation Loc);
};
Added: cfe/trunk/test/Sema/enum.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/enum.c?rev=41532&view=auto
==============================================================================
--- cfe/trunk/test/Sema/enum.c (added)
+++ cfe/trunk/test/Sema/enum.c Tue Aug 28 01:15:15 2007
@@ -0,0 +1,24 @@
+// RUN: clang %s -parse-ast-check -pedantic
+
+enum e {A,
+ B = 42LL << 32, // expected-warning {{ISO C restricts enumerator values to range of 'int'}}
+ C = -4, D = 12456 };
+
+enum f { a = -2147483648, b = 2147483647 }; // ok.
+
+enum g { // too negative
+ c = -2147483649, // expected-warning {{ISO C restricts enumerator values to range of 'int'}}
+ d = 2147483647 };
+enum h { e = -2147483648, // too pos
+ f = 2147483648 // expected-warning {{ISO C restricts enumerator values to range of 'int'}}
+};
+
+// minll maxull
+enum x // expected-warning {{enumeration values exceed range of largest integer}}
+{ y = -9223372036854775807LL-1, // expected-warning {{ISO C restricts enumerator values to range of 'int'}}
+z = 9223372036854775808ULL }; // expected-warning {{ISO C restricts enumerator values to range of 'int'}}
+
+int test() {
+ return sizeof(enum e) ;
+}
+
More information about the cfe-commits
mailing list