From b7f6e086138567f04df1ca237a351c2d3fc5d915 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 29 Aug 2007 17:31:48 +0000 Subject: [PATCH] Implement GCC-compatible layout and typing of enum constants and enum decl. A small bit of codegen work is still pending. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41571 91177308-0d34-0410-b5e6-96231b3b80d8 --- Sema/SemaDecl.cpp | 75 ++++++++++++++++++++++++++++----- clang.xcodeproj/project.pbxproj | 2 +- 2 files changed, 65 insertions(+), 12 deletions(-) diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp index 425743aa32..9a781b9ce4 100644 --- a/Sema/SemaDecl.cpp +++ b/Sema/SemaDecl.cpp @@ -1053,19 +1053,21 @@ void Sema::ParseEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX, // Figure out the type that should be used for this enum. // FIXME: Support attribute(packed) on enums and -fshort-enums. QualType BestType; + unsigned BestWidth; 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) + if (NumNegativeBits <= IntWidth && NumPositiveBits < IntWidth) { BestType = Context.IntTy; - else { - unsigned LongWidth = Context.Target.getLongWidth(Enum->getLocation()); - if (NumNegativeBits <= LongWidth && NumPositiveBits < LongWidth) + BestWidth = IntWidth; + } else { + BestWidth = Context.Target.getLongWidth(Enum->getLocation()); + if (NumNegativeBits <= BestWidth && NumPositiveBits < BestWidth) BestType = Context.LongTy; else { - unsigned LLWidth = Context.Target.getLongLongWidth(Enum->getLocation()); - if (NumNegativeBits > LLWidth || NumPositiveBits >= LLWidth) + BestWidth = Context.Target.getLongLongWidth(Enum->getLocation()); + if (NumNegativeBits > BestWidth || NumPositiveBits >= BestWidth) Diag(Enum->getLocation(), diag::warn_enum_too_large); BestType = Context.LongLongTy; } @@ -1073,19 +1075,70 @@ void Sema::ParseEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX, } else { // If there is no negative value, figure out which of uint, ulong, ulonglong // fits. - if (NumPositiveBits <= IntWidth) + if (NumPositiveBits <= IntWidth) { BestType = Context.UnsignedIntTy; - else if (NumPositiveBits <=Context.Target.getLongWidth(Enum->getLocation())) + BestWidth = IntWidth; + } else if (NumPositiveBits <= + (BestWidth = Context.Target.getLongWidth(Enum->getLocation()))) BestType = Context.UnsignedLongTy; else { - assert(NumPositiveBits <= - Context.Target.getLongLongWidth(Enum->getLocation()) && + BestWidth = Context.Target.getLongLongWidth(Enum->getLocation()); + assert(NumPositiveBits <= BestWidth && "How could an initializer get larger than ULL?"); BestType = Context.UnsignedLongLongTy; } } - // FIXME: Install type in Enum and constant values. + // Loop over all of the enumerator constants, changing their types to match + // the type of the enum if needed. + for (unsigned i = 0; i != NumElements; ++i) { + EnumConstantDecl *ECD = + cast_or_null(static_cast(Elements[i])); + if (!ECD) continue; // Already issued a diagnostic. + + // Standard C says the enumerators have int type, but we allow, as an + // extension, the enumerators to be larger than int size. If each + // enumerator value fits in an int, type it as an int, otherwise type it the + // same as the enumerator decl itself. This means that in "enum { X = 1U }" + // that X has type 'int', not 'unsigned'. + if (ECD->getType() == Context.IntTy) + continue; // Already int type. + + // Determine whether the value fits into an int. + llvm::APSInt InitVal = ECD->getInitVal(); + bool FitsInInt; + if (InitVal.isUnsigned() || !InitVal.isNegative()) + FitsInInt = InitVal.getActiveBits() < IntWidth; + else + FitsInInt = InitVal.getMinSignedBits() <= IntWidth; + + // If it fits into an integer type, force it. Otherwise force it to match + // the enum decl type. + QualType NewTy; + unsigned NewWidth; + bool NewSign; + if (FitsInInt) { + NewTy = Context.IntTy; + NewWidth = IntWidth; + NewSign = true; + } else if (ECD->getType() == BestType) { + // Already the right type! + continue; + } else { + NewTy = BestType; + NewWidth = BestWidth; + NewSign = BestType->isSignedIntegerType(); + } + + // Adjust the APSInt value. + InitVal.extOrTrunc(NewWidth); + InitVal.setIsSigned(NewSign); + ECD->setInitVal(InitVal); + + // Adjust the Expr initializer and type. + ECD->setInitExpr(new ImplicitCastExpr(NewTy, ECD->getInitExpr())); + ECD->setType(NewTy); + } Enum->defineElements(EltList, BestType); } diff --git a/clang.xcodeproj/project.pbxproj b/clang.xcodeproj/project.pbxproj index cb6a73d08b..d86dfbb0ee 100644 --- a/clang.xcodeproj/project.pbxproj +++ b/clang.xcodeproj/project.pbxproj @@ -210,7 +210,7 @@ 35260CA40C7F75C000D66CE9 /* ExprCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ExprCXX.cpp; path = AST/ExprCXX.cpp; sourceTree = ""; }; 84D9A8870C1A57E100AC7ABC /* AttributeList.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = AttributeList.cpp; path = Parse/AttributeList.cpp; sourceTree = ""; }; 84D9A88B0C1A581300AC7ABC /* AttributeList.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AttributeList.h; path = clang/Parse/AttributeList.h; sourceTree = ""; }; - 8DD76F6C0486A84900D96B5E /* clang */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = clang; sourceTree = BUILT_PRODUCTS_DIR; }; + 8DD76F6C0486A84900D96B5E /* clang */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "compiled.mach-o.executable"; path = clang; sourceTree = BUILT_PRODUCTS_DIR; }; DE01DA480B12ADA300AC22CE /* PPCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PPCallbacks.h; sourceTree = ""; }; DE06756B0C051CFE00EBBFD8 /* ParseExprCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ParseExprCXX.cpp; path = Parse/ParseExprCXX.cpp; sourceTree = ""; }; DE06B73D0A8307640050E87E /* LangOptions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LangOptions.h; sourceTree = ""; }; -- 2.40.0