diff options
-rw-r--r-- | lib/AST/ASTContext.cpp | 2 | ||||
-rw-r--r-- | lib/AST/ExprConstant.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 18 | ||||
-rw-r--r-- | test/CodeGenCXX/enum.cpp | 4 |
4 files changed, 11 insertions, 25 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 91fd166133..0d5567370b 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -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); } diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 670753ca15..ea30b19309 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -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. diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 6574ad2e87..c7a47c98c9 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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 index 0000000000..6ce04a3a53 --- /dev/null +++ b/test/CodeGenCXX/enum.cpp @@ -0,0 +1,4 @@ +// RUN: clang-cc -emit-llvm-only -verify %s + +enum A { a } __attribute((packed)); +int func(A x) { return x==a; } |