]> granicus.if.org Git - clang/commitdiff
Clean up enum constants so that they're finally sane. Fixes PR3173 and a
authorEli Friedman <eli.friedman@gmail.com>
Thu, 10 Dec 2009 22:29:29 +0000 (22:29 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Thu, 10 Dec 2009 22:29:29 +0000 (22:29 +0000)
recently introduced crash.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91070 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/ASTContext.cpp
lib/AST/ExprConstant.cpp
lib/Sema/SemaDecl.cpp
test/CodeGenCXX/enum.cpp [new file with mode: 0644]

index 91fd166133873b46b42ae58d2c11c73ae3f94100..0d5567370b93d7d8e8d2589c1dba7445bb8ffcdb 100644 (file)
@@ -4522,7 +4522,7 @@ unsigned ASTContext::getIntWidth(QualType T) {
     return FWIT->getWidth();
   }
   if (EnumType *ET = dyn_cast<EnumType>(T))
-    T = ET->getDecl()->getPromotionType();
+    T = ET->getDecl()->getIntegerType();
   // For builtin types, just use the standard type sizing method
   return (unsigned)getTypeSize(T);
 }
index 670753ca15fa2faeb05d31363a6638db0f2a783e..ea30b193094a1aa241e10721fb45b5bbbc8b8a8d 100644 (file)
@@ -848,16 +848,8 @@ static bool EvaluateInteger(const Expr* E, APSInt &Result, EvalInfo &Info) {
 
 bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) {
   // Enums are integer constant exprs.
-  if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D)) {
-    // FIXME: This is an ugly hack around the fact that enums don't set their
-    // signedness consistently; see PR3173.
-    APSInt SI = ECD->getInitVal();
-    SI.setIsUnsigned(!E->getType()->isSignedIntegerType());
-    // FIXME: This is an ugly hack around the fact that enums don't
-    // set their width (!?!) consistently; see PR3173.
-    SI.extOrTrunc(Info.Ctx.getIntWidth(E->getType()));
-    return Success(SI, E);
-  }
+  if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D))
+    return Success(ECD->getInitVal(), E);
 
   // In C++, const, non-volatile integers initialized with ICEs are ICEs.
   // In C, they can also be folded, although they are not ICEs.
index 6574ad2e87d4923127781878fcee272a11a6bf0c..c7a47c98c9f01e860d584fc58919b84ba69484f5 100644 (file)
@@ -5694,6 +5694,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
       // First value, set to zero.
       EltTy = Context.IntTy;
       EnumVal.zextOrTrunc(static_cast<uint32_t>(Context.getTypeSize(EltTy)));
+      EnumVal.setIsSigned(true);
     }
   }
 
@@ -5908,19 +5909,8 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
     // 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) {
-      // Make sure the init value is signed.
-      llvm::APSInt IV = ECD->getInitVal();
-      IV.setIsSigned(true);
-      ECD->setInitVal(IV);
-
-      if (getLangOptions().CPlusPlus)
-        // C++ [dcl.enum]p4: Following the closing brace of an
-        // enum-specifier, each enumerator has the type of its
-        // enumeration.
-        ECD->setType(EnumType);
-      continue;  // Already int type.
-    }
+    if (!getLangOptions().CPlusPlus && ECD->getType() == Context.IntTy)
+      continue;
 
     // Determine whether the value fits into an int.
     llvm::APSInt InitVal = ECD->getInitVal();
@@ -5935,7 +5925,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
     QualType NewTy;
     unsigned NewWidth;
     bool NewSign;
-    if (FitsInInt) {
+    if (FitsInInt && !getLangOptions().CPlusPlus) {
       NewTy = Context.IntTy;
       NewWidth = IntWidth;
       NewSign = true;
diff --git a/test/CodeGenCXX/enum.cpp b/test/CodeGenCXX/enum.cpp
new file mode 100644 (file)
index 0000000..6ce04a3
--- /dev/null
@@ -0,0 +1,4 @@
+// RUN: clang-cc -emit-llvm-only -verify %s
+
+enum A { a } __attribute((packed));
+int func(A x) { return x==a; }