From d2b0c2f46b7bc450c5d15adab6bcb2048141340e Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Sun, 2 Aug 2009 05:39:59 +0000 Subject: [PATCH] Enum to int conversion. Bug 285368. --- .../core/parser/tests/ast2/AST2CPPTests.java | 31 ++++++++-- .../core/dom/parser/ASTEnumerator.java | 4 +- .../dom/parser/cpp/semantics/Conversions.java | 59 ++++++++++++++++++- 3 files changed, 83 insertions(+), 11 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index 3ef845904d5..613c3be658d 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -7122,7 +7122,7 @@ public class AST2CPPTests extends AST2BaseTest { // foo(L'a'); // } public void testWideCharacterLiteralTypes_Bug270892() throws Exception { - IASTTranslationUnit tu = parse( getAboveComment(), ParserLanguage.CPP ); + IASTTranslationUnit tu = parse(getAboveComment(), ParserLanguage.CPP); CPPNameCollector col = new CPPNameCollector(); tu.accept(col); @@ -7301,14 +7301,33 @@ public class AST2CPPTests extends AST2BaseTest { // void f(int t); // void f(unsigned int t); + // void f(long t); // - // enum E { e1 }; + // enum IntEnum { i1 }; + // enum UnsignedEnum { u1 = 0x7FFFFFFF, u2 }; + // enum LongEnum { l1 = -1, l2 = 0x7FFFFFFF, l3 }; // // void test() { - // f(e1); // problem on f + // f(i1); + // f(u1); + // f(l1); // } - public void _testEnumToIntConversion_285368() throws Exception { - final String code = getAboveComment(); - parseAndCheckBindings(code, ParserLanguage.CPP); + public void testEnumToIntConversion_285368() throws Exception { + BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true); + ICPPFunction f1 = ba.assertNonProblem("f(i1)", 1, ICPPFunction.class); + IType t1 = f1.getType().getParameterTypes()[0]; + assertTrue(t1 instanceof ICPPBasicType); + assertEquals(IBasicType.t_int, ((ICPPBasicType) t1).getType()); + assertEquals(0, ((ICPPBasicType) t1).getQualifierBits()); + ICPPFunction f2 = ba.assertNonProblem("f(u1)", 1, ICPPFunction.class); + IType t2 = f2.getType().getParameterTypes()[0]; + assertTrue(t2 instanceof ICPPBasicType); + assertEquals(IBasicType.t_int, ((ICPPBasicType) t2).getType()); + assertEquals(ICPPBasicType.IS_UNSIGNED, ((ICPPBasicType) t2).getQualifierBits()); + ICPPFunction f3 = ba.assertNonProblem("f(l1)", 1, ICPPFunction.class); + IType t3 = f3.getType().getParameterTypes()[0]; + assertTrue(t3 instanceof ICPPBasicType); + assertEquals(IBasicType.t_int, ((ICPPBasicType) t3).getType()); + assertEquals(ICPPBasicType.IS_LONG, ((ICPPBasicType) t3).getQualifierBits()); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTEnumerator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTEnumerator.java index d774d55cbf3..cd3a25b91ef 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTEnumerator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTEnumerator.java @@ -123,7 +123,7 @@ public abstract class ASTEnumerator extends ASTNode implements IASTEnumerator, I private void createEnumValues(IASTEnumerationSpecifier parent) { IASTEnumerator[] etors= parent.getEnumerators(); - int cv= -1; + long cv= -1; boolean isknown= true; for (IASTEnumerator etor : etors) { cv++; @@ -134,7 +134,7 @@ public abstract class ASTEnumerator extends ASTNode implements IASTEnumerator, I isknown= false; if (nv != null) { isknown= true; - cv= nv.intValue(); + cv= nv.longValue(); } } if (etor instanceof ASTEnumerator) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java index c6cdc8ad0b9..bfadd7b1814 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java @@ -24,11 +24,13 @@ import org.eclipse.cdt.core.dom.ast.IArrayType; import org.eclipse.cdt.core.dom.ast.IBasicType; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IEnumeration; +import org.eclipse.cdt.core.dom.ast.IEnumerator; import org.eclipse.cdt.core.dom.ast.IFunctionType; import org.eclipse.cdt.core.dom.ast.IPointerType; import org.eclipse.cdt.core.dom.ast.IProblemBinding; import org.eclipse.cdt.core.dom.ast.IQualifierType; import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; @@ -52,7 +54,9 @@ import org.eclipse.core.runtime.CoreException; */ public class Conversions { enum UDCMode {allowUDC, noUDC, deferUDC} - + private static final int IS_LONG = ICPPBasicType.IS_LONG; + private static final int IS_UNSIGNED = ICPPBasicType.IS_UNSIGNED; + /** * Computes the cost of an implicit conversion sequence * [over.best.ics] 13.3.3.1 @@ -669,7 +673,14 @@ public class Conversions { } } else if (src instanceof IEnumeration) { if (tType == IBasicType.t_int || tType == IBasicType.t_unspecified) { - canPromote= true; + if (trg instanceof ICPPBasicType) { + int qualifiers = getEnumIntType((IEnumeration) src); + if (qualifiers == ((ICPPBasicType) trg).getQualifierBits()) { + canPromote = true; + } + } else { + canPromote = true; + } } } } @@ -679,7 +690,7 @@ public class Conversions { } return false; } - + /** * Attempts conversions and returns whether the conversion succeeded. * [4.7] Integral conversions @@ -815,4 +826,46 @@ public class Conversions { return true; } + + /** + * Returns IS_LONG, IS_UNSIGNED qualifiers of the first of the following types that can represent + * all the values of an enumeration: int, unsigned int, long, or unsigned long. + * @param enumeration + * @return qualifiers of the corresponding integer type. + */ + private static int getEnumIntType(IEnumeration enumeration) { + long minValue = 0; + long maxValue = 0; + try { + IEnumerator[] enumerators = enumeration.getEnumerators(); + for (IEnumerator enumerator : enumerators) { + IValue value = enumerator.getValue(); + if (value != null) { + Long val = value.numericalValue(); + if (val != null) { + long v = val.longValue(); + if (minValue > v) { + minValue = v; + } + if (maxValue < v) { + maxValue = v; + } + } + } + } + } catch (DOMException e) { + return 0; + } + // TODO(sprigogin): Use values of __INT_MAX__ and __LONG_MAX__ macros + if (minValue >= Integer.MIN_VALUE && maxValue <= Integer.MAX_VALUE) { + return 0; + } else if (minValue >= 0 && maxValue <= 0xFFFFFFFFL) { + return IS_UNSIGNED; + } else if (minValue >= Long.MIN_VALUE && maxValue <= Long.MAX_VALUE) { + return IS_LONG; + } else { + // This branch is unreachable due to limitations of Java long type. + return IS_UNSIGNED | IS_LONG; + } + } }