diff options
author | Markus Schorn | 2010-03-19 13:06:51 +0000 |
---|---|---|
committer | Markus Schorn | 2010-03-19 13:06:51 +0000 |
commit | b01672b1f37bdf0602f513c2f3d5fd85d0755ec3 (patch) | |
tree | 0df7a79e99e0fe7b32ea29b890a6618b67cb45dd /core | |
parent | 90f7d1a70295c7566d6306cd701bb2ea595e4bf5 (diff) | |
download | org.eclipse.cdt-b01672b1f37bdf0602f513c2f3d5fd85d0755ec3.tar.gz org.eclipse.cdt-b01672b1f37bdf0602f513c2f3d5fd85d0755ec3.tar.xz org.eclipse.cdt-b01672b1f37bdf0602f513c2f3d5fd85d0755ec3.zip |
Bug 305975: Strongly typed enums, forward declarations for enum.
Diffstat (limited to 'core')
42 files changed, 1457 insertions, 339 deletions
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2BaseTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2BaseTest.java index 07ac9f39c12..fb3ee4fbf29 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2BaseTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2BaseTest.java @@ -494,7 +494,7 @@ public class AST2BaseTest extends BaseTestCase { public IProblemBinding assertProblem(String section, int len) { if (len <= 0) - len= section.length()-len; + len= section.length()+len; IBinding binding= binding(section, len); assertTrue("Non-ProblemBinding for name: " + section.substring(0, len), binding instanceof IProblemBinding); 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 3fb6d5b0ae8..2cb8f63ff45 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 @@ -100,6 +100,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPBlockScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate; @@ -119,6 +120,7 @@ import org.eclipse.cdt.core.parser.ParserLanguage; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNameBase; import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; @@ -8332,5 +8334,166 @@ public class AST2CPPTests extends AST2BaseTest { assertEquals("int (* (int))(int)", ASTTypeUtil.getType(f.getType())); } + // enum class EScoped1 {a1}; + // enum class EScoped2 : short {a2}; + // enum class EScoped3; + // enum EUnscoped1 {b1}; + // enum EUnscoped2 : long {b2}; + // enum EUnscoped3 : int; + public void testScopedEnums_305975a() throws Exception { + String code= getAboveComment(); + BindingAssertionHelper bh= new BindingAssertionHelper(code, true); + + ICPPEnumeration e; + ICPPBinding ei; + e= bh.assertNonProblem("EScoped1", 0); + assertTrue(e.isScoped()); + assertEquals("int", ASTTypeUtil.getType(e.getFixedType())); + assertDefinition(e); + ei= bh.assertNonProblem("a1", 0); + assertSame(e, ei.getOwner()); + assertEquals(2, ei.getQualifiedName().length); + + e= bh.assertNonProblem("EScoped2", 0); + assertTrue(e.isScoped()); + assertEquals("short int", ASTTypeUtil.getType(e.getFixedType())); + assertDefinition(e); + ei= bh.assertNonProblem("a2", 0); + assertSame(e, ei.getOwner()); + assertEquals(2, ei.getQualifiedName().length); + + e= bh.assertNonProblem("EScoped3", 0); + assertTrue(e.isScoped()); + assertEquals("int", ASTTypeUtil.getType(e.getFixedType())); + assertDeclaration(e); + + e= bh.assertNonProblem("EUnscoped1", 0); + assertFalse(e.isScoped()); + assertNull(e.getFixedType()); + assertDefinition(e); + ei= bh.assertNonProblem("b1", 0); + assertSame(e, ei.getOwner()); + assertEquals(1, ei.getQualifiedName().length); + + e= bh.assertNonProblem("EUnscoped2", 0); + assertFalse(e.isScoped()); + assertEquals("long int", ASTTypeUtil.getType(e.getFixedType())); + assertDefinition(e); + ei= bh.assertNonProblem("b2", 0); + assertSame(e, ei.getOwner()); + assertEquals(1, ei.getQualifiedName().length); + + e= bh.assertNonProblem("EUnscoped3", 0); + assertFalse(e.isScoped()); + assertEquals("int", ASTTypeUtil.getType(e.getFixedType())); + assertDeclaration(e); + } + + private void assertDefinition(ICPPBinding b) { + assertTrue(((IASTName)((ICPPInternalBinding) b).getDefinition()).isDefinition()); + } + + private void assertDeclaration(ICPPBinding b) { + assertTrue(((IASTName)((ICPPInternalBinding) b).getDeclarations()[0]).isDeclaration()); + } + + // enum class E { a, b }; + // enum E x1 = E::a; // OK + // enum F { a, b }; + // enum F y1 = a; // OK + // enum E1 : int; // OK: E1 is un-scoped, underlying type is int + // enum class F1; // OK: F1 is scoped, underlying type is int + public void testScopedEnums_305975b() throws Exception { + String code= getAboveComment(); + parseAndCheckBindings(code); + } + + // enum class E x2 = E::a; // illegal (elaborated type specifier) + // enum class F y2 = a; // illegal + // enum E; // illegal + public void testScopedEnums_305975c() throws Exception { + String code= getAboveComment(); + IASTTranslationUnit tu= parse(code, ParserLanguage.CPP, true, false); + IASTDeclaration[] decls = tu.getDeclarations(); + assertEquals(3, decls.length); + assertInstance(decls[0], IASTProblemDeclaration.class); + assertInstance(decls[1], IASTProblemDeclaration.class); + assertInstance(decls[2], IASTProblemDeclaration.class); + } + + // enum class Col { red, yellow, green }; + // void fint(int); + // void fbool(bool); + // void fCol(Col); + // + // void test() { + // fCol(Col::red); + // fint(Col::red); // error: no conversion to int + // fbool(Col::red); // error: no Col to bool conversion + // } + public void testScopedEnums_305975d() throws Exception { + String code= getAboveComment(); + BindingAssertionHelper bh= new BindingAssertionHelper(code, true); + + bh.assertNonProblem("fCol(Col::red)", 4); + bh.assertProblem("fint(Col::red)", 4); + bh.assertProblem("fbool(Col::red)", 5); + } + + // enum direction { left='l', right='r'}; + // void g() { + // direction d; // OK + // d = left; // OK + // d = direction::right; // OK + // } + // + // enum class altitude { high=1, low=2 }; + // void h() { + // altitude a; // OK + // a = altitude::low; // OK + // } + // + // struct X { + // enum xdir { xl=1, xr=2 }; + // int f(int i) { return i==xl ? 0 : i==xr ? 1 : 2; } + // }; + // void g(X* p) { + // int i; + // i = p->f(X::xr); // OK + // i = p->f(p->xl); // OK + // } + public void testScopedEnums_305975e() throws Exception { + String code= getAboveComment(); + parseAndCheckBindings(code); + } + + // enum class altitude { high=1, low=2 }; + // struct X { + // enum xdir { xl=1, xr=2 }; + // int f(int i) { return i==xl ? 0 : i==xr ? 1 : 2; } + // }; + // void g(X* p) { + // altitude a= high; // error: high not in scope + // xdir d; // error: xdir not in scope + // xl; // error: not in scope + // } + public void testScopedEnums_305975f() throws Exception { + String code= getAboveComment(); + BindingAssertionHelper bh= new BindingAssertionHelper(code, true); + + bh.assertProblem("high;", -1); + bh.assertProblem("xdir d", -2); + bh.assertProblem("xl;", -1); + } + + // void f(int); + // enum class X {e1, e2= e1+2, e3}; + // enum class Y {e1, e2= f(e1)+2, e3}; + // enum A {e1, e2= e1+2, e3}; + // enum B {e1, e2= f(e1)+2, e3}; + public void testScopedEnums_305975g() throws Exception { + String code= getAboveComment(); + parseAndCheckBindings(code); + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexSearchTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexSearchTest.java index ef72bed2d4b..670ab8625dc 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexSearchTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexSearchTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2007 Wind River Systems, Inc. and others. + * Copyright (c) 2006, 2010 Wind River Systems, Inc. and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,7 +8,6 @@ * Contributors: * Markus Schorn - initial API and implementation *******************************************************************************/ - package org.eclipse.cdt.internal.index.tests; import java.util.LinkedList; @@ -217,13 +216,13 @@ public class IndexSearchTest extends IndexTestBase { checkIsEnumerator(bindings[0]); bindings= fIndex.findBindings(new Pattern[]{pEnumeration, pEnumerator}, true, INDEX_FILTER, NPM); - assertEquals(0, bindings.length); + assertEquals(1, bindings.length); bindings= fIndex.findBindings(new char[][]{sEnumeration, sEnumerator}, INDEX_FILTER, NPM); - assertEquals(0, bindings.length); + assertEquals(1, bindings.length); bindings= fIndex.findBindings(new Pattern[]{pEnumeration, pEnumerator}, false, INDEX_FILTER, NPM); - assertEquals(0, bindings.length); + assertEquals(1, bindings.length); bindings= fIndex.findBindings(pEnumeration, true, INDEX_FILTER, NPM); assertEquals(1, bindings.length); diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexUpdateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexUpdateTests.java index f92cfd9f630..54cb32245e4 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexUpdateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexUpdateTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2009 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -31,6 +31,7 @@ import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMember; @@ -1215,4 +1216,52 @@ public class IndexUpdateTests extends IndexTestBase { fIndex.releaseReadLock(); } } + + // enum E {e0}; + + // enum class E; + + // enum E : short {e1}; + + // enum class E {e2}; + + // enum class E : short {e1}; + + // enum E : int; + public void testEnumCPP() throws Exception { + setupFile(6, true); + checkEnum(false, null, "e0"); + updateFile(); + checkEnum(true, "int", null); + updateFile(); + checkEnum(false, "short int", "e1"); + updateFile(); + checkEnum(true, "int", "e2"); + updateFile(); + checkEnum(true, "short int", "e1"); + updateFile(); + checkEnum(false, "int", null); + } + + private void checkEnum(boolean scoped, String fixedType, String enumItem) throws Exception { + fIndex.acquireReadLock(); + try { + ICPPEnumeration enumType = (ICPPEnumeration) findBinding("E"); + assertEquals(scoped, enumType.isScoped()); + if (fixedType == null) { + assertNull(enumType.getFixedType()); + } else { + assertEquals(fixedType, ASTTypeUtil.getType(enumType.getFixedType())); + } + final IEnumerator[] enumItems = enumType.getEnumerators(); + if (enumItem == null) { + assertEquals(0, enumItems.length); + } else { + assertEquals(1, enumItems.length); + assertEquals(enumItem, enumItems[0].getName()); + } + } finally { + fIndex.releaseReadLock(); + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/EScopeKind.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/EScopeKind.java index 74f9cb8d13f..c9bfea87709 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/EScopeKind.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/EScopeKind.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008 Wind River Systems, Inc. and others. + * Copyright (c) 2008, 2010 Wind River Systems, Inc. and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -20,6 +20,10 @@ public enum EScopeKind { * function-prototype scope (parameters in function prototypes). */ eLocal, + /** + * @since 5.2 + */ + eEnumeration, eNamespace, /** * For classes, structs or unions. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IBinding.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IBinding.java index 7c90bf4015e..90eb7683513 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IBinding.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2009 IBM Corporation and others. + * Copyright (c) 2004, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -48,10 +48,11 @@ public interface IBinding extends IAdaptable { * Returns the binding that owns this binding, or <code>null</code> if there is no owner. * <p> * The owner is determined as follows: - * <br> {@link ICPPUsingDeclaration}: the owner depends on where the declaration is found, within a + * <br> {@link ICPPUsingDeclaration}: The owner depends on where the declaration is found, within a * function or method, a class-type, a namespace or on global scope. - * <br> {@link ICPPTemplateParameter}: the owner is the {@link ICPPTemplateDefinition}. - * <br> for all other bindings the owner depends on where the binding can be defined (it could be + * <br> {@link ICPPTemplateParameter}: The owner is the {@link ICPPTemplateDefinition}. + * <br> {@link IEnumerator}: The owner is the {@link IEnumeration}, independent of whether they are scoped or not. + * <br> For all other bindings: The owner depends on where the binding can be defined (it could be * declared else where). * <p> Possible owners are: * <br> {@link IFunction}: for parameters, local types, variables, enumerators, labels and using declarations; @@ -60,7 +61,8 @@ public interface IBinding extends IAdaptable { * <br> {@link ICompositeType}: for struct- and union-members, even if the composite type is anonymous; * also for anonymous structs or unions found within another struct; * <br> {@link ICPPNamespace}: for global types, functions, variables, enumerators, namespaces and using declarations; - * <br> <code>null</code>: for types, functions, variables, enumerators, namespaces and using declarations; + * <br> {@link IEnumeration}: for enumerators. + * <br> <code>null</code>: for types, functions, variables, namespaces and using declarations; * @since 5.1 */ public IBinding getOwner() throws DOMException; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTEnumerationSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTEnumerationSpecifier.java new file mode 100644 index 00000000000..78678e5240f --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTEnumerationSpecifier.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2010 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.core.dom.ast.cpp; + +import org.eclipse.cdt.core.dom.ast.ASTNodeProperty; +import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier; + +/** + * <code> enum struct : unsigned int {...}</code> + * + * @since 5.2 + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface ICPPASTEnumerationSpecifier extends IASTEnumerationSpecifier, ICPPASTDeclSpecifier { + + public static final ASTNodeProperty BASE_TYPE = new ASTNodeProperty( + "ICPPASTEnumerationSpecifier.BASE_TYPE [ICPPASTDeclSpecifier]"); //$NON-NLS-1$ + + public ICPPASTEnumerationSpecifier copy(); + + /** + * Not allowed on frozen ast. + */ + public void setIsScoped(boolean isScoped); + + /** + * An enum is scoped if it uses the enumeration head + * <code>enum class</code> or <code>enum struct</code> + */ + public boolean isScoped(); + + /** + * Not allowed on frozen ast. + */ + public void setIsOpaque(boolean isOpaque); + + /** + * An opaque specifier does not have a body. + */ + public boolean isOpaque(); + + /** + * Not allowed on frozen ast. + */ + public void setBaseType(ICPPASTDeclSpecifier baseType); + + /** + * Returns the base type for this enum or <code>null</code> if it was not specified. + */ + public ICPPASTDeclSpecifier getBaseType(); + + /** + * Returns the scope containing the enumerators of this enumeration, or <code>null</code> if the specifier + * is opaque. + */ + public ICPPScope getScope(); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPEnumeration.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPEnumeration.java new file mode 100644 index 00000000000..7cd598500e0 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPEnumeration.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2010 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.core.dom.ast.cpp; + +import org.eclipse.cdt.core.dom.ast.IEnumeration; +import org.eclipse.cdt.core.dom.ast.IType; + +/** + * C++ specific version of enumerations. + * + * @since 5.2 + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface ICPPEnumeration extends IEnumeration, ICPPBinding { + + /** + * Returns whether this enumeration is scoped. + * An enumeration can only be scoped in C++. + */ + boolean isScoped(); + + /** + * Returns the underlying type of the enumeration if it is fixed, or <code>null</code> otherwise. + * The underlying type can only be fixed in C++. + */ + IType getFixedType(); + + /** + * Returns the scope containing the enumerators. + * By the standard the scope is only defined for scoped enums, however it will be returned + * for any enum. In case the enum has no definition (just opaque declarations) an empty scope + * will be returned. + */ + ICPPScope asScope(); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java index a69eb686ad7..b29a6ce8219 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java @@ -99,6 +99,11 @@ public interface ICPPNodeFactory extends INodeFactory { public ICPPASTElaboratedTypeSpecifier newElaboratedTypeSpecifier(int kind, IASTName name); + /** + * @since 5.2 + */ + public ICPPASTEnumerationSpecifier newEnumerationSpecifier(boolean isScoped, IASTName name, ICPPASTDeclSpecifier baseType); + public ICPPASTExplicitTemplateInstantiation newExplicitTemplateInstantiation(IASTDeclaration declaration); /** diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java index 6a3767650c5..65ef81c1824 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java @@ -1451,8 +1451,13 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { final IASTEnumerationSpecifier result= nodeFactory.newEnumerationSpecifier(name); - boolean needComma= false; - int endOffset= consume().getEndOffset(); // IToken.tLBRACE + int endOffset= enumBody(result); + return setRange(result, offset, endOffset); + } + + protected int enumBody(final IASTEnumerationSpecifier result) throws EndOfFileException, BacktrackException { + boolean needComma= false; + int endOffset= consume(IToken.tLBRACE).getEndOffset(); // IToken.tLBRACE int problemOffset= endOffset; try { loop: while (true) { @@ -1504,9 +1509,8 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { IASTProblem problem= skipProblemEnumerator(problemOffset); throwBacktrack(problem, result); } - setRange(result, offset, endOffset); - return result; - } + return endOffset; + } protected abstract IASTStatement statement() throws EndOfFileException, BacktrackException; @@ -1556,7 +1560,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { return result; // support simple declarations without declarators - final boolean acceptEmpty = acceptCompoundWithoutDtor && specifiesCompound(result.fDeclSpec1); + final boolean acceptEmpty = acceptCompoundWithoutDtor && isLegalWithoutDtor(result.fDeclSpec1); if (acceptEmpty) { switch(lt1) { case 0: @@ -1615,7 +1619,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { return result.set(declspec2, dtor2, dtorMark2); } - protected boolean specifiesCompound(IASTDeclSpecifier declSpec) { + protected boolean isLegalWithoutDtor(IASTDeclSpecifier declSpec) { if (declSpec instanceof IASTCompositeTypeSpecifier) return true; if (declSpec instanceof IASTElaboratedTypeSpecifier) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ArithmeticConversion.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ArithmeticConversion.java index 47758ddc058..bd86e1eae97 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ArithmeticConversion.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ArithmeticConversion.java @@ -12,10 +12,11 @@ package org.eclipse.cdt.internal.core.dom.parser; import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; import org.eclipse.cdt.core.dom.ast.IBasicType; +import org.eclipse.cdt.core.dom.ast.IBasicType.Kind; import org.eclipse.cdt.core.dom.ast.IEnumeration; import org.eclipse.cdt.core.dom.ast.IType; -import org.eclipse.cdt.core.dom.ast.IBasicType.Kind; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration; /** * Arithmetic conversions as required to compute the type of unary or binary expressions. @@ -46,7 +47,7 @@ public abstract class ArithmeticConversion { * or 5.0.9 of C++ standard */ public final IType convertOperandTypes(int operator, IType op1, IType op2) { - if (!isArithmeticOrEnum(op1) || !isArithmeticOrEnum(op2)) { + if (!isArithmeticOrUnscopedEnum(op1) || !isArithmeticOrUnscopedEnum(op2)) { return null; } switch (operator) { @@ -76,17 +77,24 @@ public abstract class ArithmeticConversion { } public final IType promoteType(IType type) { - if (!isIntegralOrEnum(type)) + if (!isIntegralOrUnscopedEnum(type)) return null; return promote(type, getDomain(type)); } - private boolean isArithmeticOrEnum(IType op1) { - return op1 instanceof IBasicType || op1 instanceof IEnumeration; + private boolean isArithmeticOrUnscopedEnum(IType op1) { + if (op1 instanceof IBasicType) + return true; + if (op1 instanceof IEnumeration) { + if (op1 instanceof ICPPEnumeration && ((ICPPEnumeration) op1).isScoped()) + return false; + return true; + } + return false; } - private boolean isIntegralOrEnum(IType op1) { + private boolean isIntegralOrUnscopedEnum(IType op1) { if (op1 instanceof IEnumeration) return true; @@ -175,8 +183,16 @@ public abstract class ArithmeticConversion { private IBasicType promote(IType type, Domain domain) { if (type instanceof IEnumeration) { - return createBasicType(Kind.eInt, domain.getModifier() | getEnumIntTypeModifiers((IEnumeration) type)); - } else if (type instanceof IBasicType) { + IType fixedType= null; + if (type instanceof ICPPEnumeration) { + fixedType= ((ICPPEnumeration) type).getFixedType(); + } + if (fixedType == null) + return createBasicType(Kind.eInt, domain.getModifier() | getEnumIntTypeModifiers((IEnumeration) type)); + type= fixedType; + } + + if (type instanceof IBasicType) { final IBasicType bt = (IBasicType) type; final Kind kind = bt.getKind(); switch (kind) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/DeclarationOptions.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/DeclarationOptions.java index 31345c55536..0a986d15408 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/DeclarationOptions.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/DeclarationOptions.java @@ -27,13 +27,14 @@ public class DeclarationOptions { final public static int ALLOW_PARAMETER_PACKS= 0x400; final public static int REQUIRE_SIMPLE_NAME= 0x800; final public static int ALLOW_FOLLOWED_BY_BRACE= 0x1000; + final public static int ALLOW_OPAQUE_ENUM= 0x2000; public static final DeclarationOptions - GLOBAL= new DeclarationOptions(ALLOW_EMPTY_SPECIFIER), + GLOBAL= new DeclarationOptions(ALLOW_EMPTY_SPECIFIER | ALLOW_OPAQUE_ENUM), FUNCTION_STYLE_ASM= new DeclarationOptions(ALLOW_EMPTY_SPECIFIER | NO_INITIALIZER | ALLOW_ABSTRACT), C_MEMBER= new DeclarationOptions(ALLOW_BITFIELD | ALLOW_ABSTRACT), CPP_MEMBER= new DeclarationOptions(ALLOW_EMPTY_SPECIFIER | ALLOW_BITFIELD | NO_CTOR_STYLE_INITIALIZER), - LOCAL= new DeclarationOptions(0), + LOCAL= new DeclarationOptions(ALLOW_OPAQUE_ENUM), PARAMETER= new DeclarationOptions(ALLOW_ABSTRACT | ALLOW_PARAMETER_PACKS | REQUIRE_SIMPLE_NAME | NO_BRACED_INITIALIZER | NO_CTOR_STYLE_INITIALIZER), TYPEID= new DeclarationOptions(REQUIRE_ABSTRACT | NO_INITIALIZER), TYPEID_TRAILING_RETURN_TYPE= new DeclarationOptions(REQUIRE_ABSTRACT | NO_INITIALIZER | ALLOW_FOLLOWED_BY_BRACE), @@ -55,6 +56,7 @@ public class DeclarationOptions { final public boolean fAllowNested; final public boolean fAllowParameterPacks; final public boolean fRequireSimpleName; + final public boolean fAllowOpaqueEnum; public DeclarationOptions(int options) { fAllowEmptySpecifier= (options & ALLOW_EMPTY_SPECIFIER) != 0; @@ -69,5 +71,6 @@ public class DeclarationOptions { fAllowParameterPacks= (options & ALLOW_PARAMETER_PACKS) != 0; fRequireSimpleName= (options & REQUIRE_SIMPLE_NAME) != 0; fCanBeFollowedByBrace= fAllowBracedInitializer || (options & ALLOW_FOLLOWED_BY_BRACE) != 0; + fAllowOpaqueEnum= (options & ALLOW_OPAQUE_ENUM) != 0; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemBinding.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemBinding.java index 3d747f9bed1..b22d16fffe8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemBinding.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2009 IBM Corporation and others. + * Copyright (c) 2004, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -38,6 +38,8 @@ import org.eclipse.core.runtime.PlatformObject; * Implementation of problem bindings */ public class ProblemBinding extends PlatformObject implements IProblemBinding, IASTInternalScope { + public static ProblemBinding NOT_INITIALIZED= new ProblemBinding(null, 0); + protected final int id; protected char[] arg; protected IASTNode node; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CEnumerator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CEnumerator.java index feb7c24a701..7b19eeb589b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CEnumerator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CEnumerator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2008 IBM Corporation and others. + * Copyright (c) 2004, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -14,15 +14,14 @@ package org.eclipse.cdt.internal.core.dom.parser.c; import org.eclipse.cdt.core.dom.ILinkage; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; 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.IScope; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IValue; -import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator; import org.eclipse.cdt.internal.core.dom.Linkage; import org.eclipse.cdt.internal.core.dom.parser.ASTEnumerator; import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; @@ -76,18 +75,17 @@ public class CEnumerator extends PlatformObject implements IEnumerator { * @see org.eclipse.cdt.core.dom.ast.IEnumerator#getType() */ public IType getType() { - IASTEnumerator etor = (IASTEnumerator) enumeratorName.getParent(); - IASTEnumerationSpecifier enumSpec = (IASTEnumerationSpecifier) etor.getParent(); - IEnumeration enumeration = (IEnumeration) enumSpec.getName().resolveBinding(); - return enumeration; + return (IType) getOwner(); } public ILinkage getLinkage() { return Linkage.C_LINKAGE; } - public IBinding getOwner() throws DOMException { - return CVisitor.findEnclosingFunction(enumeratorName); + public IBinding getOwner() { + IASTEnumerator etor = (IASTEnumerator) enumeratorName.getParent(); + IASTEnumerationSpecifier enumSpec = (IASTEnumerationSpecifier) etor.getParent(); + return enumSpec.getName().resolveBinding(); } public IValue getValue() { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTEnumerationSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTEnumerationSpecifier.java index f4fb42ccffd..37bfb093d72 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTEnumerationSpecifier.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTEnumerationSpecifier.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2008 IBM Corporation and others. + * Copyright (c) 2004, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -13,6 +13,9 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTEnumerationSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.internal.core.dom.parser.IASTInternalEnumerationSpecifier; @@ -20,22 +23,34 @@ import org.eclipse.cdt.internal.core.dom.parser.IASTInternalEnumerationSpecifier * AST node for c++ enumeration specifiers. */ public class CPPASTEnumerationSpecifier extends CPPASTBaseDeclSpecifier - implements IASTInternalEnumerationSpecifier { + implements IASTInternalEnumerationSpecifier, ICPPASTEnumerationSpecifier { - private IASTName name; - private boolean valuesComputed= false; + private boolean fIsScoped; + private boolean fIsOpaque; + private IASTName fName; + private ICPPASTDeclSpecifier fBaseType; + + private IASTEnumerator[] fItems = null; + private int fItemPos=-1; + + private boolean fValuesComputed= false; + private CPPEnumScope fScope; - public CPPASTEnumerationSpecifier() { } - public CPPASTEnumerationSpecifier(IASTName name) { + public CPPASTEnumerationSpecifier(boolean isScoped, IASTName name, ICPPASTDeclSpecifier baseType) { + fIsScoped= isScoped; setName(name); + setBaseType(baseType); } public CPPASTEnumerationSpecifier copy() { - CPPASTEnumerationSpecifier copy = new CPPASTEnumerationSpecifier(name == null ? null : name.copy()); - for(IASTEnumerator enumerator : getEnumerators()) + CPPASTEnumerationSpecifier copy = new CPPASTEnumerationSpecifier(fIsScoped, + fName == null ? null : fName.copy(), + fBaseType == null ? null : fBaseType.copy()); + copy.fIsOpaque= fIsOpaque; + for (IASTEnumerator enumerator : getEnumerators()) copy.addEnumerator(enumerator == null ? null : enumerator.copy()); copyBaseDeclSpec(copy); return copy; @@ -43,10 +58,10 @@ public class CPPASTEnumerationSpecifier extends CPPASTBaseDeclSpecifier public boolean startValueComputation() { - if (valuesComputed) + if (fValuesComputed) return false; - valuesComputed= true; + fValuesComputed= true; return true; } @@ -55,24 +70,21 @@ public class CPPASTEnumerationSpecifier extends CPPASTBaseDeclSpecifier if (enumerator != null) { enumerator.setParent(this); enumerator.setPropertyInParent(ENUMERATOR); - enumerators = (IASTEnumerator[]) ArrayUtil.append( IASTEnumerator.class, enumerators, ++enumeratorsPos, enumerator ); + fItems = (IASTEnumerator[]) ArrayUtil.append( IASTEnumerator.class, fItems, ++fItemPos, enumerator ); } } public IASTEnumerator[] getEnumerators() { - if (enumerators == null) + if (fItems == null) return IASTEnumerator.EMPTY_ENUMERATOR_ARRAY; - enumerators = (IASTEnumerator[]) ArrayUtil.removeNullsAfter( IASTEnumerator.class, enumerators, enumeratorsPos ); - return enumerators; + + fItems = (IASTEnumerator[]) ArrayUtil.removeNullsAfter(IASTEnumerator.class, fItems, fItemPos); + return fItems; } - - private IASTEnumerator[] enumerators = null; - private int enumeratorsPos=-1; - public void setName(IASTName name) { assertNotFrozen(); - this.name = name; + fName = name; if (name != null) { name.setParent(this); name.setPropertyInParent(ENUMERATION_NAME); @@ -80,7 +92,7 @@ public class CPPASTEnumerationSpecifier extends CPPASTBaseDeclSpecifier } public IASTName getName() { - return name; + return fName; } @Override @@ -95,28 +107,67 @@ public class CPPASTEnumerationSpecifier extends CPPASTBaseDeclSpecifier break; } } - if (name != null) - if (!name.accept(action)) - return false; - IASTEnumerator[] enums = getEnumerators(); - for (int i = 0; i < enums.length; i++) - if (!enums[i].accept(action)) + if (fName != null && !fName.accept(action)) + return false; + + if (fBaseType != null && !fBaseType.accept(action)) { + return false; + } + + for (IASTEnumerator e : getEnumerators()) { + if (!e.accept(action)) return false; - - if( action.shouldVisitDeclSpecifiers ){ - switch( action.leave( this ) ){ - case ASTVisitor.PROCESS_ABORT : return false; - case ASTVisitor.PROCESS_SKIP : return true; - default : break; - } } + + if (action.shouldVisitDeclSpecifiers && action.leave(this) == ASTVisitor.PROCESS_ABORT) + return false; return true; } public int getRoleForName(IASTName n) { - if (name == n) - return r_definition; + if (fName == n) + return isOpaque() ? r_declaration : r_definition; return r_unclear; } + + public void setIsScoped(boolean isScoped) { + assertNotFrozen(); + fIsScoped= isScoped; + } + + public boolean isScoped() { + return fIsScoped; + } + + public void setBaseType(ICPPASTDeclSpecifier baseType) { + assertNotFrozen(); + fBaseType= baseType; + if (baseType != null) { + baseType.setParent(this); + baseType.setPropertyInParent(BASE_TYPE); + } + } + + public ICPPASTDeclSpecifier getBaseType() { + return fBaseType; + } + + public void setIsOpaque(boolean isOpaque) { + assertNotFrozen(); + fIsOpaque= isOpaque; + } + + public boolean isOpaque() { + return fIsOpaque; + } + + public ICPPScope getScope() { + if (isOpaque()) + return null; + if (fScope == null) { + fScope= new CPPEnumScope(this); + } + return fScope; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIdExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIdExpression.java index 3eb92576c84..ebeaec8ea0c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIdExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTIdExpression.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2009 IBM Corporation and others. + * Copyright (c) 2004, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -24,9 +24,11 @@ import org.eclipse.cdt.core.dom.ast.IProblemBinding; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; public class CPPASTIdExpression extends ASTNode implements IASTIdExpression, IASTCompletionContext { @@ -92,7 +94,21 @@ public class CPPASTIdExpression extends ASTNode implements IASTIdExpression, IAS if (binding instanceof IVariable) { return SemanticUtil.mapToAST(((IVariable) binding).getType(), this); } else if (binding instanceof IEnumerator) { - return ((IEnumerator) binding).getType(); + IType type= ((IEnumerator) binding).getType(); + if (type instanceof ICPPEnumeration) { + ICPPEnumeration enumType= (ICPPEnumeration) type; + if (enumType.asScope() == CPPVisitor.getContainingScope(this)) { + // C++0x: 7.2-5 + IType fixedType= enumType.getFixedType(); + if (fixedType != null) + return fixedType; + // This is a simplification, the actual type is determined + // - in an implementation dependent manner - by the value + // of the enumerator. + return CPPSemantics.INT_TYPE; + } + } + return type; } else if (binding instanceof IProblemBinding) { return (IType) binding; } else if (binding instanceof IFunction) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTName.java index 5b29f013e3d..ab54ddcfb9e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTName.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTName.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2008 IBM Corporation and others. + * Copyright (c) 2004, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -34,6 +34,8 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; * Unqualified name, also base class for operator and conversion name. */ public class CPPASTName extends CPPASTNameBase implements IASTCompletionContext { + public static IASTName NOT_INITIALIZED= new CPPASTName(null); + private char[] name; public CPPASTName(char[] name) { this.name = name; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPEnumScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPEnumScope.java new file mode 100644 index 00000000000..db69723d23a --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPEnumScope.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2010 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp; + +import org.eclipse.cdt.core.dom.IName; +import org.eclipse.cdt.core.dom.ast.EScopeKind; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTEnumerationSpecifier; + +/** + * Implementation of namespace scopes, including global scope. + */ +public class CPPEnumScope extends CPPScope { + public CPPEnumScope(ICPPASTEnumerationSpecifier specifier) { + super(specifier); + } + + public EScopeKind getKind() { + return EScopeKind.eNamespace; + } + + @Override + public IName getScopeName() { + ICPPASTEnumerationSpecifier node = (ICPPASTEnumerationSpecifier) getPhysicalNode(); + return node.getName(); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPEnumeration.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPEnumeration.java index 2eab4fe1c15..123b68ff3c4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPEnumeration.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPEnumeration.java @@ -14,18 +14,32 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ILinkage; import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; 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.IScope; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.IValue; +import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTEnumerationSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBlockScope; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope; +import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndexBinding; +import org.eclipse.cdt.core.parser.util.ArrayUtil; +import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.Linkage; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.core.runtime.PlatformObject; @@ -33,22 +47,87 @@ import org.eclipse.core.runtime.PlatformObject; /** * Enumerations in C++ */ -public class CPPEnumeration extends PlatformObject implements IEnumeration, ICPPInternalBinding { - private IASTName enumName; +public class CPPEnumeration extends PlatformObject implements ICPPEnumeration, ICPPInternalBinding { + private static final IASTName NOT_INITIALIZED = CPPASTName.NOT_INITIALIZED; + private static final IEnumerator[] EMPTY_ENUMERATORS = {}; + + private final boolean fIsScoped; + private final IType fFixedType; + private IASTName fDefinition= NOT_INITIALIZED; + private IASTName[] fDeclarations= IASTName.EMPTY_NAME_ARRAY; private Long fMaxValue; private Long fMinValue; - public CPPEnumeration(IASTName name) { - this.enumName = name; - name.setBinding(this); + private ICPPEnumeration fIndexBinding= null; + private boolean fSearchedIndex= false; + + public CPPEnumeration(ICPPASTEnumerationSpecifier spec, IType fixedType) { + final IASTName name = spec.getName(); + fIsScoped= spec.isScoped(); + fFixedType= fixedType; + if (spec.isOpaque()) { + addDeclaration(name); + } else { + addDefinition(name); + } + name.setBinding(this); } public IASTNode[] getDeclarations() { - return null; + fDeclarations= ArrayUtil.trim(fDeclarations); + return fDeclarations; } - public IASTNode getDefinition() { - return enumName; + private class FindDefinitionAction extends CPPASTVisitor { + private char[] nameArray = CPPEnumeration.this.getNameCharArray(); + public IASTName result = null; + + { + shouldVisitNames = true; + shouldVisitDeclarations = true; + shouldVisitDeclSpecifiers = true; + shouldVisitDeclarators = true; + } + + @Override + public int visit(IASTName name) { + if (name instanceof ICPPASTTemplateId || name instanceof ICPPASTQualifiedName) + return PROCESS_SKIP; + char[] c = name.getLookupKey(); + if (name.getParent() instanceof ICPPASTEnumerationSpecifier && CharArrayUtils.equals(c, nameArray)) { + IBinding binding = name.resolveBinding(); + if (binding == CPPEnumeration.this) { + result= name; + return PROCESS_ABORT; + } + } + return PROCESS_CONTINUE; + } + + @Override + public int visit(IASTDeclaration declaration) { + if (declaration instanceof IASTSimpleDeclaration) + return PROCESS_CONTINUE; + return PROCESS_SKIP; + } + @Override + public int visit(IASTDeclSpecifier declSpec) { + return (declSpec instanceof ICPPASTEnumerationSpecifier) ? PROCESS_CONTINUE : PROCESS_SKIP; + } + @Override + public int visit(IASTDeclarator declarator) { + return PROCESS_SKIP; + } + } + + public IASTName getDefinition() { + if (fDefinition == NOT_INITIALIZED) { + FindDefinitionAction action = new FindDefinitionAction(); + IASTNode node = CPPVisitor.getContainingBlockItem(getADeclaration()).getParent(); + node.accept(action); + fDefinition = action.result; + } + return fDefinition; } public String getName() { @@ -56,37 +135,22 @@ public class CPPEnumeration extends PlatformObject implements IEnumeration, ICPP } public char[] getNameCharArray() { - return enumName.getSimpleID(); + return getADeclaration().getSimpleID(); } - public IScope getScope() { - return CPPVisitor.getContainingScope(enumName); - } + private IASTName getADeclaration() { + if (fDefinition != null && fDefinition != NOT_INITIALIZED) + return fDefinition; + return fDeclarations[0]; + } - public IASTNode getPhysicalNode() { - return enumName; + public IScope getScope() { + return CPPVisitor.getContainingScope(getADeclaration()); } - + @Override public Object clone() { - IType t = null; - try { - t = (IType) super.clone(); - } catch (CloneNotSupportedException e) { - //not going to happen - } - return t; - } - - public IEnumerator[] getEnumerators() { - IASTEnumerationSpecifier.IASTEnumerator[] enums = - ((IASTEnumerationSpecifier) enumName.getParent()).getEnumerators(); - IEnumerator[] bindings = new IEnumerator[enums.length]; - - for (int i = 0; i < enums.length; i++) { - bindings[i] = (IEnumerator) enums[i].getName().resolveBinding(); - } - return bindings; + throw new IllegalArgumentException("Enums must not be cloned"); //$NON-NLS-1$ } public String[] getQualifiedName() { @@ -108,9 +172,17 @@ public class CPPEnumeration extends PlatformObject implements IEnumeration, ICPP } public void addDefinition(IASTNode node) { + assert fDefinition == null || fDefinition == NOT_INITIALIZED; + fDefinition= (IASTName) node; } public void addDeclaration(IASTNode node) { + assert node instanceof IASTName; + if (fDeclarations == null) { + fDeclarations= new IASTName[] {(IASTName) node}; + } else { + fDeclarations= ArrayUtil.append(fDeclarations, (IASTName) node); + } } public boolean isSameType(IType type) { @@ -126,7 +198,7 @@ public class CPPEnumeration extends PlatformObject implements IEnumeration, ICPP } public IBinding getOwner() throws DOMException { - return CPPVisitor.findDeclarationOwner(enumName, true); + return CPPVisitor.findDeclarationOwner(getADeclaration(), true); } @Override @@ -177,4 +249,56 @@ public class CPPEnumeration extends PlatformObject implements IEnumeration, ICPP fMaxValue= maxValue; return maxValue; } + + public boolean isScoped() { + return fIsScoped; + } + + public IType getFixedType() { + return fFixedType; + } + + public IEnumerator[] getEnumerators() { + final IASTName definition = getDefinition(); + if (definition == null) { + ICPPEnumeration typeInIndex= getIndexBinding(); + if (typeInIndex != null) { + try { + return typeInIndex.getEnumerators(); + } catch (DOMException e) { + } + } + return EMPTY_ENUMERATORS; + } + + IASTEnumerator[] enums = ((IASTEnumerationSpecifier) definition.getParent()).getEnumerators(); + IEnumerator[] bindings = new IEnumerator[enums.length]; + for (int i = 0; i < enums.length; i++) { + bindings[i] = (IEnumerator) enums[i].getName().resolveBinding(); + } + return bindings; + } + + private ICPPEnumeration getIndexBinding() { + if (!fSearchedIndex) { + final IASTTranslationUnit translationUnit = getADeclaration().getTranslationUnit(); + IIndex index= translationUnit.getIndex(); + if (index != null) { + fIndexBinding= (ICPPEnumeration) index.adaptBinding(this); + } + } + return fIndexBinding; + } + + public ICPPScope asScope() { + IASTName def = getDefinition(); + if (def == null) { + ICPPEnumeration indexBinding= getIndexBinding(); + if (indexBinding != null) { + return indexBinding.asScope(); + } + def= getADeclaration(); + } + return ((ICPPASTEnumerationSpecifier) def.getParent()).getScope(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java index 85c5e4d0b7d..4661f2afa41 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java @@ -24,7 +24,7 @@ import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement; import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTDefaultStatement; import org.eclipse.cdt.core.dom.ast.IASTDoStatement; -import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator; import org.eclipse.cdt.core.dom.ast.IASTEqualsInitializer; import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement; @@ -47,13 +47,13 @@ import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.IASTStatement; import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.IASTTypeIdInitializerExpression; -import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTArrayDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTArraySubscriptExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTBinaryExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCastExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName; @@ -61,6 +61,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTEnumerationSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExpressionList; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldDeclarator; @@ -103,7 +104,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisibilityLabel; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTWhileStatement; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNodeFactory; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression; import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTPointer; import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTPointerToMember; @@ -237,8 +237,13 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory { return new CPPASTElaboratedTypeSpecifier(kind, name); } - public IASTEnumerationSpecifier newEnumerationSpecifier(IASTName name) { - return new CPPASTEnumerationSpecifier(name); + public ICPPASTEnumerationSpecifier newEnumerationSpecifier(boolean isScoped, IASTName name, + ICPPASTDeclSpecifier baseType) { + return new CPPASTEnumerationSpecifier(isScoped, name, baseType); + } + + public ICPPASTEnumerationSpecifier newEnumerationSpecifier(IASTName name) { + return new CPPASTEnumerationSpecifier(false, name, null); } public IASTEnumerator newEnumerator(IASTName name, IASTExpression value) { @@ -261,7 +266,7 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory { public ICPPASTExpressionList newExpressionList() { return new CPPASTExpressionList(); } - + public IASTExpressionStatement newExpressionStatement(IASTExpression expression) { return new CPPASTExpressionStatement(expression); } @@ -269,15 +274,15 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory { public ICPPASTFieldDeclarator newFieldDeclarator(IASTName name, IASTExpression bitFieldSize) { return new CPPASTFieldDeclarator(name, bitFieldSize); } - + public ICPPASTFieldReference newFieldReference(IASTName name, IASTExpression owner) { return new CPPASTFieldReference(name, owner); } - + public ICPPASTForStatement newForStatement() { return new CPPASTForStatement(); } - + public ICPPASTForStatement newForStatement(IASTStatement init, IASTDeclaration condition, IASTExpression iterationExpression, IASTStatement body) { return new CPPASTForStatement(init, condition, iterationExpression, body); @@ -287,14 +292,14 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory { IASTExpression iterationExpr, IASTStatement body) { return new CPPASTForStatement(init, condition, iterationExpr, body); } - + @Deprecated public ICPPASTFunctionCallExpression newFunctionCallExpression(IASTExpression idExpr, IASTExpression argList) { CPPASTFunctionCallExpression result = new CPPASTFunctionCallExpression(idExpr, null); result.setParameterExpression(argList); return result; } - + public ICPPASTFunctionCallExpression newFunctionCallExpression(IASTExpression idExpr, IASTInitializerClause[] arguments) { return new CPPASTFunctionCallExpression(idExpr, arguments); } @@ -316,7 +321,7 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory { public IGNUASTCompoundStatementExpression newGNUCompoundStatementExpression(IASTCompoundStatement compoundStatement) { return new CPPASTCompoundStatementExpression(compoundStatement); } - + public IASTGotoStatement newGotoStatement(IASTName name) { return new CPPASTGotoStatement(name); } @@ -324,7 +329,7 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory { public IASTIdExpression newIdExpression(IASTName name) { return new CPPASTIdExpression(name); } - + public ICPPASTIfStatement newIfStatement() { return new CPPASTIfStatement(); } @@ -349,19 +354,19 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory { public IASTLabelStatement newLabelStatement(IASTName name, IASTStatement nestedStatement) { return new CPPASTLabelStatement(name, nestedStatement); } - + public ICPPASTLinkageSpecification newLinkageSpecification(String literal) { return new CPPASTLinkageSpecification(literal); } - + public ICPPASTLiteralExpression newLiteralExpression(int kind, String rep) { return new CPPASTLiteralExpression(kind, rep.toCharArray()); } - + public IASTName newName() { return new CPPASTName(); } - + public IASTName newName(char[] name) { return new CPPASTName(name); } @@ -409,11 +414,11 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory { public IGPPASTPointer newPointerGPP() { return new GPPASTPointer(); } - + public ICPPASTPointerToMember newPointerToMember(IASTName name) { return new CPPASTPointerToMember(name); } - + public IGPPASTPointerToMember newPointerToMemberGPP(IASTName name) { return new GPPASTPointerToMember(name); } @@ -457,11 +462,11 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory { public IASTReturnStatement newReturnStatement(IASTInitializerClause retValue) { return new CPPASTReturnStatement(retValue); } - + public IASTSimpleDeclaration newSimpleDeclaration(IASTDeclSpecifier declSpecifier) { return new CPPASTSimpleDeclaration(declSpecifier); } - + public ICPPASTSimpleDeclSpecifier newSimpleDeclSpecifier() { return new CPPASTSimpleDeclSpecifier(); } @@ -470,6 +475,11 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory { public org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTSimpleDeclSpecifier newSimpleDeclSpecifierGPP() { return new GPPASTSimpleDeclSpecifier(); } + + public ICPPASTSimpleTypeConstructorExpression newSimpleTypeConstructorExpression( + ICPPASTDeclSpecifier declSpec, IASTInitializer initializer) { + return new CPPASTSimpleTypeConstructorExpression(declSpec, initializer); + } @Deprecated public ICPPASTSimpleTypeConstructorExpression newSimpleTypeConstructorExpression(int type, IASTExpression expression) { @@ -478,11 +488,6 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory { result.setInitialValue(expression); return result; } - - public ICPPASTSimpleTypeConstructorExpression newSimpleTypeConstructorExpression( - ICPPASTDeclSpecifier declSpec, IASTInitializer initializer) { - return new CPPASTSimpleTypeConstructorExpression(declSpec, initializer); - } public ICPPASTSimpleTypeTemplateParameter newSimpleTypeTemplateParameter(int type, IASTName name, IASTTypeId typeId) { return new CPPASTSimpleTypeTemplateParameter(type, name, typeId); @@ -508,11 +513,11 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory { public ICPPASTTemplateDeclaration newTemplateDeclaration(IASTDeclaration declaration) { return new CPPASTTemplateDeclaration(declaration); } - + public ICPPASTTemplatedTypeTemplateParameter newTemplatedTypeTemplateParameter(IASTName name, IASTExpression defaultValue) { return new CPPASTTemplatedTypeTemplateParameter(name, defaultValue); } - + public ICPPASTTemplateId newTemplateId(IASTName templateName) { return new CPPASTTemplateId(templateName); } @@ -554,12 +559,12 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory { public IASTTypeIdInitializerExpression newTypeIdInitializerExpression(IASTTypeId typeId, IASTInitializer initializer) { return new CPPASTTypeIdInitializerExpression(typeId, initializer); } - + @Deprecated public org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTypenameExpression newTypenameExpression(IASTName qualifiedName, IASTExpression expr, boolean isTemplate) { return new CPPASTTypenameExpression(qualifiedName, expr); } - + public ICPPASTUnaryExpression newUnaryExpression(int operator, IASTExpression operand) { return new CPPASTUnaryExpression(operator, operand); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java index 88f5df13c79..da044f9075c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java @@ -72,6 +72,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTEnumerationSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference; @@ -1874,8 +1875,15 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return null; } + @Override + protected boolean isLegalWithoutDtor(IASTDeclSpecifier declSpec) { + if (declSpec instanceof IASTElaboratedTypeSpecifier) { + return ((IASTElaboratedTypeSpecifier) declSpec).getKind() != IASTElaboratedTypeSpecifier.k_enum; + } + return super.isLegalWithoutDtor(declSpec); + } - /** + /** * Parses a declaration with the given options. */ protected IASTDeclaration simpleDeclaration(DeclarationOptions declOption) throws BacktrackException, EndOfFileException { @@ -1905,7 +1913,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { dtor= addInitializer(lie, declOption); } catch (BacktrackException e) { IASTNode node= e.getNodeBeforeProblem(); - if (node instanceof IASTDeclSpecifier && specifiesCompound((IASTDeclSpecifier) node)) { + if (node instanceof IASTDeclSpecifier && isLegalWithoutDtor((IASTDeclSpecifier) node)) { IASTSimpleDeclaration d= nodeFactory.newSimpleDeclaration((IASTDeclSpecifier) node); setRange(d, node); throwBacktrack(e.getProblem(), d); @@ -1956,7 +1964,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { default: if (declOption != DeclarationOptions.LOCAL) { insertSemi= true; - if (specifiesCompound(declSpec) && markBeforDtor != null && !isOnSameLine(calculateEndOffset(declSpec), markBeforDtor.getOffset())) { + if (isLegalWithoutDtor(declSpec) && markBeforDtor != null && !isOnSameLine(calculateEndOffset(declSpec), markBeforDtor.getOffset())) { backup(markBeforDtor); declarators= IASTDeclarator.EMPTY_DECLARATOR_ARRAY; endOffset= calculateEndOffset(declSpec); @@ -2147,15 +2155,20 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { */ @Override protected Decl declSpecifierSeq(final DeclarationOptions option) throws BacktrackException, EndOfFileException { - return declSpecifierSeq(option.fAllowEmptySpecifier, false); + return declSpecifierSeq(option, false); } private ICPPASTDeclSpecifier simpleTypeSpecifier() throws BacktrackException, EndOfFileException { - Decl d= declSpecifierSeq(false, true); + Decl d= declSpecifierSeq(null, true); return (ICPPASTDeclSpecifier) d.fDeclSpec1; } - - private Decl declSpecifierSeq(final boolean allowEmpty, final boolean single) throws BacktrackException, EndOfFileException { + + private ICPPASTDeclSpecifier simpleTypeSpecifierSequence() throws BacktrackException, EndOfFileException { + Decl d= declSpecifierSeq(null, false); + return (ICPPASTDeclSpecifier) d.fDeclSpec1; + } + + private Decl declSpecifierSeq(final DeclarationOptions option, final boolean single) throws BacktrackException, EndOfFileException { int storageClass = IASTDeclSpecifier.sc_unspecified; int simpleType = IASTSimpleDeclSpecifier.t_unspecified; int options= 0; @@ -2350,7 +2363,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { if (encounteredRawType || encounteredTypename) break declSpecifiers; - if (allowEmpty && LT(1) != IToken.tCOMPLETION) { + if (option != null && option.fAllowEmptySpecifier && LT(1) != IToken.tCOMPLETION) { if ((options & FORBID_IN_EMPTY_DECLSPEC) == 0 && storageClass == IASTDeclSpecifier.sc_unspecified) { altResult= buildSimpleDeclSpec(storageClass, simpleType, options, isLong, typeofExpression, offset, endOffset); returnToken= mark(); @@ -2382,15 +2395,14 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { if (encounteredTypename || encounteredRawType) break declSpecifiers; try { - result= (ICPPASTDeclSpecifier) enumSpecifier(); + result= enumDeclaration(option != null && option.fAllowOpaqueEnum); } catch (BacktrackException bt) { if (bt.getNodeBeforeProblem() instanceof ICPPASTDeclSpecifier) { result= (ICPPASTDeclSpecifier) bt.getNodeBeforeProblem(); problem= bt.getProblem(); break declSpecifiers; - } else { - result= elaboratedTypeSpecifier(); - } + } + throw bt; } endOffset= calculateEndOffset(result); encounteredTypename= true; @@ -2450,7 +2462,8 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } // check for empty specification - if (!encounteredRawType && !encounteredTypename && LT(1) != IToken.tEOC && !allowEmpty) { + if (!encounteredRawType && !encounteredTypename && LT(1) != IToken.tEOC + && (option == null || !option.fAllowEmptySpecifier)) { throwBacktrack(LA(1)); } @@ -2526,6 +2539,65 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { declSpec.setRestrict((options & RESTRICT) != 0); } + private ICPPASTDeclSpecifier enumDeclaration(boolean allowOpaque) throws BacktrackException, EndOfFileException { + IToken mark= mark(); + final int offset= consume(IToken.t_enum).getOffset(); + int endOffset= 0; + boolean isScoped= false; + IASTName name= null; + ICPPASTDeclSpecifier baseType= null; + + try { + int lt1= LT(1); + if (lt1 == IToken.t_class || lt1 == IToken.t_struct) { + isScoped= true; + consume(); + } + // if __attribute__ or __declspec occurs after struct/union/class and before the identifier + __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers); + + if (isScoped || LT(1) == IToken.tIDENTIFIER) { + name= identifier(); + endOffset= calculateEndOffset(name); + } + + if (LT(1) == IToken.tCOLON) { + consume(); + baseType= simpleTypeSpecifierSequence(); + endOffset= calculateEndOffset(baseType); + } + } catch (BacktrackException e) { + backup(mark); + return elaboratedTypeSpecifier(); + } + + final int lt1= LT(1); + final boolean isDef= lt1 == IToken.tLBRACE || (lt1 == IToken.tEOC && baseType != null); + final boolean isOpaque= !isDef && allowOpaque && lt1 == IToken.tSEMI; + if (!isDef && !isOpaque) { + backup(mark); + return elaboratedTypeSpecifier(); + } + mark= null; + + if (isOpaque && !isScoped && baseType == null) + throwBacktrack(LA(1)); + + if (name == null) { + if (isOpaque) + throwBacktrack(LA(1)); + name= nodeFactory.newName(); + } + + final ICPPASTEnumerationSpecifier result= nodeFactory.newEnumerationSpecifier(isScoped, name, baseType); + result.setIsOpaque(isOpaque); + if (lt1 == IToken.tLBRACE) { + endOffset= enumBody(result); + } + assert endOffset != 0; + return setRange(result, offset, endOffset); + } + /** * Parse an elaborated type specifier. * @@ -2534,10 +2606,10 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { */ protected ICPPASTElaboratedTypeSpecifier elaboratedTypeSpecifier() throws BacktrackException, EndOfFileException { // this is an elaborated class specifier - IToken t = consume(); + final int lt1= LT(1); int eck = 0; - switch (t.getType()) { + switch (lt1) { case IToken.t_class: eck = ICPPASTElaboratedTypeSpecifier.k_class; break; @@ -2551,18 +2623,16 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { eck = IASTElaboratedTypeSpecifier.k_enum; break; default: - backup(t); - throwBacktrack(t.getOffset(), t.getLength()); + throwBacktrack(LA(1)); } + + final int offset= consume().getOffset(); // if __attribute__ or __declspec occurs after struct/union/class and before the identifier __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers); IASTName name = qualifiedName(CastExprCtx.eNotBExpr); - - ICPPASTElaboratedTypeSpecifier elaboratedTypeSpec = nodeFactory.newElaboratedTypeSpecifier(eck, name); - ((ASTNode) elaboratedTypeSpec).setOffsetAndLength(t.getOffset(), calculateEndOffset(name) - t.getOffset()); - return elaboratedTypeSpec; + return setRange(nodeFactory.newElaboratedTypeSpecifier(eck, name), offset, calculateEndOffset(name)); } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index da4c58662f1..f1ef7980e68 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -40,7 +40,6 @@ import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement; import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier; -import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier; import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator; import org.eclipse.cdt.core.dom.ast.IASTEqualsInitializer; import org.eclipse.cdt.core.dom.ast.IASTExpression; @@ -89,6 +88,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTEnumerationSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTForStatement; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; @@ -209,6 +209,7 @@ public class CPPSemantics { public static final char[] OPERATOR_ = new char[] {'o','p','e','r','a','t','o','r',' '}; private static final char[] CALL_FUNCTION = "call-function".toCharArray(); //$NON-NLS-1$ public static final IType VOID_TYPE = new CPPBasicType(Kind.eVoid, 0); + public static final IType INT_TYPE = new CPPBasicType(Kind.eInt, 0); // Set to true for debugging. public static boolean traceBindingResolution = false; @@ -814,7 +815,6 @@ public class CPPSemantics { * @param start either a scope or a name. */ static protected void lookup(LookupData data, IScope start) throws DOMException { - final IIndexFileSet fileSet= getIndexFileSet(data); if (data.astName == null) return; @@ -850,6 +850,7 @@ public class CPPSemantics { } } + final IIndexFileSet fileSet= getIndexFileSet(data); while (nextScope != null || nextTmplScope != null) { // when the non-template scope is no longer contained within the first template scope, // we use the template scope for the next iteration. @@ -1208,6 +1209,12 @@ public class CPPSemantics { } else { nodes= new IASTNode[] {initDeclaration}; } + } else if (parent instanceof ICPPASTEnumerationSpecifier) { + // The enumeration scope contains the enumeration items + for (IASTEnumerator enumerator : ((ICPPASTEnumerationSpecifier) parent).getEnumerators()) { + ASTInternal.addName(scope, enumerator.getName()); + } + return; } int idx = -1; @@ -1390,18 +1397,15 @@ public class CPPSemantics { populateCache(scope, decl); } } - } else if (declSpec instanceof IASTEnumerationSpecifier) { - IASTEnumerationSpecifier enumeration = (IASTEnumerationSpecifier) declSpec; + } else if (declSpec instanceof ICPPASTEnumerationSpecifier) { + ICPPASTEnumerationSpecifier enumeration = (ICPPASTEnumerationSpecifier) declSpec; specName = enumeration.getName(); - // Check enumerators too - IASTEnumerator[] list = enumeration.getEnumerators(); - IASTName tempName; - for (IASTEnumerator enumerator : list) { - if (enumerator == null) - break; - tempName = enumerator.getName(); - ASTInternal.addName(scope, tempName); + // Add unscoped enumerators to the enclosing scope + if (!enumeration.isScoped()) { + for (IASTEnumerator enumerator : enumeration.getEnumerators()) { + ASTInternal.addName(scope, enumerator.getName()); + } } } if (specName != null) { @@ -1422,6 +1426,7 @@ public class CPPSemantics { dtor.accept(visitor); } break; + case eEnumeration: case eClassType: case eTemplateDeclaration: break; @@ -1462,6 +1467,7 @@ public class CPPSemantics { break; case eClassType: case eTemplateDeclaration: + case eEnumeration: break; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java index a6d490161f5..0823ef86f3a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java @@ -88,6 +88,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTEnumerationSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; @@ -120,6 +121,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate; @@ -254,8 +256,8 @@ public class CPPVisitor extends ASTQueries { return createBinding((ICPPASTElaboratedTypeSpecifier) parent); } else if (parent instanceof IASTDeclaration) { return createBinding((IASTDeclaration) parent); - } else if (parent instanceof IASTEnumerationSpecifier) { - return createBinding((IASTEnumerationSpecifier) parent); + } else if (parent instanceof ICPPASTEnumerationSpecifier) { + return createBinding((ICPPASTEnumerationSpecifier) parent); } else if (parent instanceof IASTEnumerator) { return createBinding((IASTEnumerator) parent); } else if (parent instanceof IASTGotoStatement) { @@ -322,23 +324,48 @@ public class CPPVisitor extends ASTQueries { return enumtor; } - private static IBinding createBinding(IASTEnumerationSpecifier specifier) { + private static IBinding createBinding(ICPPASTEnumerationSpecifier specifier) { ICPPScope scope = (ICPPScope) getContainingScope(specifier); - IBinding enumeration; try { final IASTName name = specifier.getName(); - enumeration = scope.getBinding(name, false); - if (enumeration == null || !(enumeration instanceof IEnumeration)) { - enumeration = new CPPEnumeration(name); - } + IType fixedType= createEnumBaseType(specifier); + IBinding binding = scope.getBinding(name, false); + if (binding instanceof CPPEnumeration) { + CPPEnumeration e= (CPPEnumeration) binding; + if (e.isScoped() == specifier.isScoped()) { + IType ft2= e.getFixedType(); + if (fixedType == ft2 || (fixedType != null && fixedType.isSameType(ft2))) { + if (specifier.isOpaque()) { + e.addDeclaration(specifier); + } else if (e.getDefinition() == null) { + e.addDefinition(specifier); + } else { + return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_REDEFINITION); + } + return e; + } + } + return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_REDECLARATION); + } + return new CPPEnumeration(specifier, fixedType); } catch (DOMException e) { - enumeration = e.getProblem(); + return e.getProblem(); } - - return enumeration; } - private static IBinding createBinding(final ICPPASTElaboratedTypeSpecifier elabType) { + private static IType createEnumBaseType(ICPPASTEnumerationSpecifier specifier) { + ICPPASTDeclSpecifier declspec = specifier.getBaseType(); + if (declspec != null) { + IType type= createType(declspec); + return SemanticUtil.getNestedType(type, ALLCVQ); + } + if (specifier.isScoped()) { + return CPPSemantics.INT_TYPE; + } + return null; + } + + private static IBinding createBinding(final ICPPASTElaboratedTypeSpecifier elabType) { final IASTNode parent = elabType.getParent(); IBinding binding = null; boolean mustBeSimple = true; @@ -940,6 +967,18 @@ public class CPPVisitor extends ASTQueries { } return getContainingScope(n); + } else if (node instanceof IASTEnumerator) { + node= node.getParent(); + if (node instanceof ICPPASTEnumerationSpecifier) { + ICPPASTEnumerationSpecifier enumSpec= (ICPPASTEnumerationSpecifier) node; + IBinding binding = enumSpec.getName().resolveBinding(); + if (binding instanceof ICPPEnumeration) { + ICPPEnumeration enumType = (ICPPEnumeration) binding; + if (enumType.isScoped()) { + return enumType.asScope(); + } + } + } } node = node.getParent(); } @@ -1017,6 +1056,8 @@ public class CPPVisitor extends ASTQueries { scope= ((ICPPClassType) binding).getCompositeScope(); } else if (binding instanceof ICPPNamespace) { scope= ((ICPPNamespace) binding).getNamespaceScope(); + } else if (binding instanceof ICPPEnumeration) { + scope= ((ICPPEnumeration) binding).asScope(); } else if (binding instanceof ICPPUnknownBinding) { scope= ((ICPPUnknownBinding) binding).asScope(); } else if (binding instanceof IProblemBinding) { @@ -2144,6 +2185,9 @@ public class CPPVisitor extends ASTQueries { String[] ns = null; try { for (IBinding owner= binding.getOwner(); owner != null; owner= owner.getOwner()) { + if (owner instanceof ICPPEnumeration && !((ICPPEnumeration) owner).isScoped()) { + continue; + } String n= owner.getName(); if (n == null) break; @@ -2306,6 +2350,8 @@ public class CPPVisitor extends ASTQueries { isNonSimpleElabDecl= false; } } + } else if (node instanceof IASTEnumerator) { + break; } node= node.getParent(); } @@ -2348,6 +2394,10 @@ public class CPPVisitor extends ASTQueries { name= ((ICPPASTNamespaceDefinition) node).getName(); break; } + if (node instanceof ICPPASTEnumerationSpecifier) { + name= ((ICPPASTEnumerationSpecifier) node).getName(); + break; + } } if (name == null) return null; 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 7ea27c4cd8d..4909609fd68 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 @@ -26,6 +26,7 @@ import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IArrayType; import org.eclipse.cdt.core.dom.ast.IBasicType; +import org.eclipse.cdt.core.dom.ast.IBasicType.Kind; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IEnumeration; import org.eclipse.cdt.core.dom.ast.IFunctionType; @@ -34,11 +35,11 @@ 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.IBasicType.Kind; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace; @@ -903,7 +904,32 @@ public class Conversions { if (trg instanceof IBasicType) { IBasicType basicTgt = (IBasicType) trg; final Kind tKind = basicTgt.getKind(); - + + if (src instanceof ICPPEnumeration) { + final ICPPEnumeration enumType = (ICPPEnumeration) src; + if (enumType.isScoped()) { + return false; + } + IType fixedType= enumType.getFixedType(); + if (fixedType == null) { + if (tKind == Kind.eInt || tKind == Kind.eUnspecified) { + if (trg instanceof ICPPBasicType) { + int qualifiers = ArithmeticConversion.getEnumIntTypeModifiers((IEnumeration) src); + int targetModifiers = ((ICPPBasicType) trg).getModifiers(); + if (qualifiers == (targetModifiers & (IBasicType.IS_LONG | IBasicType.IS_LONG_LONG | IBasicType.IS_SHORT | IBasicType.IS_UNSIGNED))) { + canPromote = true; + } + } else { + canPromote = true; + } + } + } else { + if (fixedType.isSameType(trg)) + canPromote= true; + // Allow to further promote the fixed type + src= fixedType; + } + } if (src instanceof IBasicType) { final IBasicType basicSrc = (IBasicType) src; Kind sKind = basicSrc.getKind(); @@ -926,19 +952,7 @@ public class Conversions { } else if (tKind == Kind.eDouble && sKind == Kind.eFloat) { canPromote= true; } - } else if (src instanceof IEnumeration) { - if (tKind == Kind.eInt || tKind == Kind.eUnspecified) { - if (trg instanceof ICPPBasicType) { - int qualifiers = ArithmeticConversion.getEnumIntTypeModifiers((IEnumeration) src); - int targetModifiers = ((ICPPBasicType) trg).getModifiers(); - if (qualifiers == (targetModifiers & (IBasicType.IS_LONG | IBasicType.IS_LONG_LONG | IBasicType.IS_SHORT | IBasicType.IS_UNSIGNED))) { - canPromote = true; - } - } else { - canPromote = true; - } - } - } + } } if (canPromote) { cost.setRank(Rank.PROMOTION); @@ -963,9 +977,14 @@ public class Conversions { // 4.7 integral conversion // 4.8 floating point conversion // 4.9 floating-integral conversion - if (s instanceof IBasicType || s instanceof IEnumeration) { + if (s instanceof IBasicType) { // 4.7 An rvalue of an integer type can be converted to an rvalue of another integer type. - // An rvalue of an enumeration type can be converted to an rvalue of an integer type. + cost.setRank(Rank.CONVERSION); + cost.setCouldNarrow(); + return true; + } + if (s instanceof ICPPEnumeration && !((ICPPEnumeration) s).isScoped()) { + // 4.7 An rvalue of an enumeration type can be converted to an rvalue of an integer type. cost.setRank(Rank.CONVERSION); cost.setCouldNarrow(); return true; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java index 92a942f84fa..abeb51c1236 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2009 Symbian Software Systems and others. + * Copyright (c) 2007, 2010 Symbian Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -16,7 +16,6 @@ import org.eclipse.cdt.core.dom.ast.IASTName; 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.IPointerType; import org.eclipse.cdt.core.dom.ast.IQualifierType; @@ -30,6 +29,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecializationSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate; @@ -344,8 +344,8 @@ public class CPPCompositesFactory extends AbstractCompositeFactory { result = ns.length == 0 ? null : new CompositeCPPNamespace(this, ns); } else if (binding instanceof ICPPUsingDeclaration) { result = new CompositeCPPUsingDeclaration(this, (ICPPUsingDeclaration) binding); - } else if (binding instanceof IEnumeration) { - IEnumeration def = (IEnumeration) findOneBinding(binding); + } else if (binding instanceof ICPPEnumeration) { + ICPPEnumeration def = (ICPPEnumeration) findOneBinding(binding); result = def == null ? null : new CompositeCPPEnumeration(this, def); } else if (binding instanceof ICPPFunction) { result = new CompositeCPPFunction(this, (ICPPFunction) binding); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPEnumScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPEnumScope.java new file mode 100644 index 00000000000..3413928e38a --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPEnumScope.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2010 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.index.composite.cpp; + +import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.EScopeKind; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope; +import org.eclipse.cdt.core.index.IIndexBinding; +import org.eclipse.cdt.core.index.IIndexFileSet; +import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding; +import org.eclipse.cdt.internal.core.index.composite.CompositeScope; +import org.eclipse.cdt.internal.core.index.composite.ICompositesFactory; + +class CompositeCPPEnumScope extends CompositeScope implements ICPPScope { + public CompositeCPPEnumScope(ICompositesFactory cf, IIndexFragmentBinding rbinding) { + super(cf, rbinding); + } + + public EScopeKind getKind() { + return EScopeKind.eEnumeration; + } + + public IBinding getBinding(IASTName name, boolean resolve, IIndexFileSet fileSet) throws DOMException { + IBinding binding = ((ICPPEnumeration)rbinding).asScope().getBinding(name, resolve, fileSet); + return processUncertainBinding(binding); + } + + public IBinding[] getBindings(IASTName name, boolean resolve, boolean prefixLookup, IIndexFileSet fileSet) throws DOMException { + IBinding[] bindings = ((ICPPEnumeration)rbinding).asScope().getBindings(name, resolve, prefixLookup, fileSet); + return processUncertainBindings(bindings); + } + + public IBinding[] find(String name) throws DOMException { + IBinding[] preresult = ((ICPPEnumeration)rbinding).asScope().find(name); + return processUncertainBindings(preresult); + } + + public IIndexBinding getScopeBinding() { + return cf.getCompositeBinding(rbinding); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPEnumeration.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPEnumeration.java index 091b88c98df..75a7cbace78 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPEnumeration.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPEnumeration.java @@ -15,12 +15,14 @@ import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IEnumeration; import org.eclipse.cdt.core.dom.ast.IEnumerator; import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope; import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding; import org.eclipse.cdt.internal.core.index.IIndexType; import org.eclipse.cdt.internal.core.index.composite.ICompositesFactory; -class CompositeCPPEnumeration extends CompositeCPPBinding implements IEnumeration, IIndexType { - public CompositeCPPEnumeration(ICompositesFactory cf, IEnumeration rbinding) { +class CompositeCPPEnumeration extends CompositeCPPBinding implements ICPPEnumeration, IIndexType { + public CompositeCPPEnumeration(ICompositesFactory cf, ICPPEnumeration rbinding) { super(cf, rbinding); } @@ -49,4 +51,16 @@ class CompositeCPPEnumeration extends CompositeCPPBinding implements IEnumeratio public long getMaxValue() { return ((IEnumeration)rbinding).getMaxValue(); } + + public boolean isScoped() { + return ((ICPPEnumeration)rbinding).isScoped(); + } + + public IType getFixedType() { + return ((ICPPEnumeration)rbinding).getFixedType(); + } + + public ICPPScope asScope() { + return new CompositeCPPEnumScope(cf, rbinding); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java index 8c6049ef55e..88036473e75 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2009 QNX Software Systems and others. + * Copyright (c) 2005, 2010 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -46,6 +46,7 @@ import org.eclipse.cdt.core.dom.ast.IMacroBinding; import org.eclipse.cdt.core.dom.ast.IParameter; import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.IVariable; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable; import org.eclipse.cdt.core.index.IIndexBinding; @@ -181,9 +182,9 @@ public class PDOM extends PlatformObject implements IPDOM { * 81.0 - change to c++ function types, bug 264479 * 82.0 - offsets for using directives, bug 270806 * #83.0# - unconditionally store name in PDOMInclude, bug 272815 - <<CDT 6.0>> - * 84.0 - storing free record pointers as (ptr>>3) and allocated pointers as (ptr-2)>>3 RECPTR_DENSE_VERSION + * #84.0# - storing free record pointers as (ptr>>3), bug 279620 - <<CDT 6.0.1>> * - * CDT 6.1 development (versions not supported on the 6.0.x branch) + * CDT 7.0 development (versions not supported on the 6.0.x branch) * 90.0 - support for array sizes, bug 269926 * 91.0 - storing unknown bindings other than unknown class types, bug 284686. * 92.0 - simplification of basic types, bug 231859. @@ -192,10 +193,11 @@ public class PDOM extends PlatformObject implements IPDOM { * 95.0 - parameter packs, bug 294730. * 96.0 - storing pack expansions in the template parameter map, bug 294730. * 97.0 - storing file contents hash in PDOMFile, bug 302083. + * 98.0 - strongly typed enums, bug 305975. */ - private static final int MIN_SUPPORTED_VERSION= version(97, 0); - private static final int MAX_SUPPORTED_VERSION= version(97, Short.MAX_VALUE); - private static final int DEFAULT_VERSION = version(97, 0); + private static final int MIN_SUPPORTED_VERSION= version(98, 0); + private static final int MAX_SUPPORTED_VERSION= version(98, Short.MAX_VALUE); + private static final int DEFAULT_VERSION = version(98, 0); private static int version(int major, int minor) { return (major << 16) + minor; @@ -532,6 +534,11 @@ public class PDOM extends PlatformObject implements IPDOM { // check if we have a partial match if (nnode.mayHaveChildren()) { + // Avoid visiting unscoped enumerator items twice + if (pattern.length == 1 && nnode instanceof ICPPEnumeration + && !((ICPPEnumeration) nnode).isScoped()) { + return false; + } boolean visitNextLevel= false; BitSet updatedMatchesUpToLevel= new BitSet(); if (!isFullyQualified) { @@ -1065,6 +1072,8 @@ public class PDOM extends PlatformObject implements IPDOM { try { linkage.accept(visitor); if (!filescope) { + // Avoid adding unscoped enumerator items twice + visitor.setSkipGlobalEnumerators(true); linkage.getNestedBindingsIndex().accept(visitor); } } catch (OperationCanceledException e) { @@ -1104,8 +1113,11 @@ public class PDOM extends PlatformObject implements IPDOM { if (!isCaseSensitive) linkage.accept(visitor); - if (!filescope) + if (!filescope) { + // Avoid adding unscoped enumerator items twice + visitor.setSkipGlobalEnumerators(true); linkage.getNestedBindingsIndex().accept(visitor); + } PDOMBinding[] bindings = visitor.getBindings(); for (PDOMBinding binding : bindings) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/BindingCollector.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/BindingCollector.java index 650ef027b79..5aa74e415d6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/BindingCollector.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/BindingCollector.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2008 QNX Software Systems and others. + * Copyright (c) 2006, 2010 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -15,6 +15,8 @@ package org.eclipse.cdt.internal.core.pdom.dom; import java.util.List; import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IEnumerator; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration; import org.eclipse.cdt.core.index.IndexFilter; import org.eclipse.core.runtime.CoreException; @@ -24,6 +26,7 @@ import org.eclipse.core.runtime.CoreException; */ public final class BindingCollector extends NamedNodeCollector { private IndexFilter filter; + private boolean fSkipGlobalEnumerators; /** * Collects all bindings with given name. @@ -44,6 +47,15 @@ public final class BindingCollector extends NamedNodeCollector { @Override public boolean addNode(PDOMNamedNode tBinding) throws CoreException { if (tBinding instanceof PDOMBinding) { + if (fSkipGlobalEnumerators && tBinding instanceof IEnumerator) { + PDOMNode parent = tBinding.getParentNode(); + if (parent instanceof ICPPEnumeration) { + final ICPPEnumeration enumType = (ICPPEnumeration) parent; + if (parent.getParentNode() == null && !enumType.isScoped()) { + return true; + } + } + } if (filter == null || filter.acceptBinding((IBinding) tBinding)) { return super.addNode(tBinding); } @@ -55,4 +67,8 @@ public final class BindingCollector extends NamedNodeCollector { List<PDOMNamedNode> bindings= getNodeList(); return bindings.toArray(new PDOMBinding[bindings.size()]); } + + public void setSkipGlobalEnumerators(boolean b) { + fSkipGlobalEnumerators= b; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/FindBinding.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/FindBinding.java index 13beb3f0813..a9f7d5b52ab 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/FindBinding.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/FindBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2009 Symbian Software Systems and others. + * Copyright (c) 2006, 2010 Symbian Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -94,8 +94,8 @@ public class FindBinding { protected boolean matches(PDOMBinding nnode) throws CoreException { if (nnode.hasName(fName)) { int constant = nnode.getNodeType(); - for (int i=0; i<fConstants.length; i++) { - if (constant == fConstants[i]) { + for (int c : fConstants) { + if (constant == c) { return true; } } @@ -164,6 +164,7 @@ public class FindBinding { public static PDOMBinding findBinding(IPDOMNode node, final PDOMLinkage linkage, final char[] name, final int[] constants, long localToFileRec) throws CoreException { + // mstodo faster searches final DefaultFindBindingVisitor visitor = new DefaultFindBindingVisitor(linkage, name, constants, localToFileRec); try { node.accept(visitor); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMASTAdapter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMASTAdapter.java index 4f58960228b..f40e2d12b04 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMASTAdapter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMASTAdapter.java @@ -34,8 +34,10 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.parser.IToken; @@ -406,7 +408,7 @@ public class PDOMASTAdapter { } } - private static class AnonymousCPPEnumeration extends AnonymousCPPBinding implements IEnumeration { + private static class AnonymousCPPEnumeration extends AnonymousCPPBinding implements ICPPEnumeration { public AnonymousCPPEnumeration(char[] name, IEnumeration delegate) { super(name, (ICPPBinding) delegate); } @@ -426,6 +428,18 @@ public class PDOMASTAdapter { public long getMaxValue() { return ((IEnumeration)fDelegate).getMaxValue(); } + + public boolean isScoped() { + return ((ICPPEnumeration)fDelegate).isScoped(); + } + + public IType getFixedType() { + return ((ICPPEnumeration)fDelegate).getFixedType(); + } + + public ICPPScope asScope() { + return ((ICPPEnumeration)fDelegate).asScope(); + } } private static class AnonymousClassType extends AnonymousCPPBinding implements ICPPClassType { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMBinding.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMBinding.java index ac99f9808ba..3fb28f271c5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMBinding.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2009 QNX Software Systems and others. + * Copyright (c) 2005, 2010 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -26,6 +26,7 @@ import org.eclipse.cdt.core.dom.ast.IFunction; import org.eclipse.cdt.core.dom.ast.IFunctionType; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration; import org.eclipse.cdt.core.index.IIndexFileSet; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; @@ -209,14 +210,22 @@ public abstract class PDOMBinding extends PDOMNamedNode implements IPDOMBinding // The parent node in the binding hierarchy is the scope. try { IBinding parent= getParentBinding(); - if (parent instanceof ICPPClassType) { - return (IIndexScope) ((ICPPClassType) parent).getCompositeScope(); - } else if (parent instanceof ICPPUnknownBinding) { - return (IIndexScope) ((ICPPUnknownBinding) parent).asScope(); - } - - if (parent instanceof IIndexScope) { - return (IIndexScope) parent; + while (parent != null) { + if (parent instanceof ICPPClassType) { + return (IIndexScope) ((ICPPClassType) parent).getCompositeScope(); + } else if (parent instanceof ICPPUnknownBinding) { + return (IIndexScope) ((ICPPUnknownBinding) parent).asScope(); + } else if (parent instanceof ICPPEnumeration) { + final ICPPEnumeration enumeration = (ICPPEnumeration) parent; + if (enumeration.isScoped()) { + return (IIndexScope) enumeration.asScope(); + } + parent= ((PDOMNamedNode) parent).getParentBinding(); + } else if (parent instanceof IIndexScope) { + return (IIndexScope) parent; + } else { + return null; + } } } catch (DOMException e) { } catch (CoreException ce) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java index e4881124af9..2155ca7eec3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2009 QNX Software Systems and others. + * Copyright (c) 2005, 2010 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -306,7 +306,7 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IIndexLinkage * @throws CoreException * @since 4.0.1 */ - public void afterAddBinding(PDOMBinding pdomBinding) throws CoreException { + protected final void insertIntoNestedBindingsIndex(PDOMBinding pdomBinding) throws CoreException { if (pdomBinding.getParentNodeRec() != record) { getNestedBindingsIndex().insert(pdomBinding.getRecord()); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMNamedNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMNamedNode.java index 4810f34bbb2..92acdcf2456 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMNamedNode.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMNamedNode.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2009 QNX Software Systems and others. + * Copyright (c) 2006, 2010 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -11,7 +11,6 @@ * Andrew Ferguson (Symbian) * Markus Schorn (Wind River Systems) *******************************************************************************/ - package org.eclipse.cdt.internal.core.pdom.dom; import java.util.Arrays; @@ -128,7 +127,7 @@ public abstract class PDOMNamedNode extends PDOMNode { return null; } - public final IIndexFragmentBinding getOwner() { + public IIndexFragmentBinding getOwner() { try { return getParentBinding(); } catch (CoreException e) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCEnumerator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCEnumerator.java index 68a33392c04..554979910eb 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCEnumerator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCEnumerator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2009 QNX Software Systems and others. + * Copyright (c) 2006, 2010 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -18,6 +18,7 @@ import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.internal.core.dom.parser.Value; import org.eclipse.cdt.internal.core.index.IIndexCBindingConstants; +import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding; import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding; import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage; @@ -86,6 +87,10 @@ class PDOMCEnumerator extends PDOMBinding implements IEnumerator { } public IType getType() throws DOMException { + return getEnumeration(); + } + + private PDOMCEnumeration getEnumeration() { try { return new PDOMCEnumeration(getLinkage(), getDB().getRecPtr(record + ENUMERATION)); } catch (CoreException e) { @@ -93,6 +98,11 @@ class PDOMCEnumerator extends PDOMBinding implements IEnumerator { return null; } } + + @Override + public IIndexFragmentBinding getOwner() { + return getEnumeration(); + } public IValue getValue() { try { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCLinkage.java index 0a8904445c6..95f59a9c5da 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCLinkage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2009 QNX Software Systems and others. + * Copyright (c) 2006, 2010 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -141,7 +141,7 @@ class PDOMCLinkage extends PDOMLinkage implements IIndexCBindingConstants { if (pdomBinding != null) { pdomBinding.setLocalToFileRec(localToFile); parent.addChild(pdomBinding); - afterAddBinding(pdomBinding); + insertIntoNestedBindingsIndex(pdomBinding); } return pdomBinding; } @@ -215,6 +215,10 @@ class PDOMCLinkage extends PDOMLinkage implements IIndexCBindingConstants { } IBinding owner= binding.getOwner(); + // For plain c the enumeration type is not the parent of the enumeration item. + if (owner instanceof IEnumeration) { + owner= owner.getOwner(); + } if (owner == null) { return this; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/CPPFindBinding.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/CPPFindBinding.java index d21c232c538..621cdd74531 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/CPPFindBinding.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/CPPFindBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2009 Symbian Software Systems and others. + * Copyright (c) 2006, 2010 Symbian Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -104,6 +104,7 @@ public class CPPFindBinding extends FindBinding { public static PDOMBinding findBinding(PDOMNode node, PDOMLinkage linkage, char[] name, int constant, int sigHash, long localToFileRec) throws CoreException { + // mstodo faster searches CPPFindBindingVisitor visitor= new CPPFindBindingVisitor(linkage, name, constant, sigHash, localToFileRec); try { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/IPDOMCPPEnumType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/IPDOMCPPEnumType.java new file mode 100644 index 00000000000..2395d9b6e85 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/IPDOMCPPEnumType.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2010 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.pdom.dom.cpp; + +import org.eclipse.cdt.core.dom.ast.IEnumerator; +import org.eclipse.cdt.core.dom.ast.IScope; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration; +import org.eclipse.cdt.core.index.IIndexName; +import org.eclipse.cdt.core.parser.util.CharArrayMap; +import org.eclipse.cdt.internal.core.index.IIndexType; +import org.eclipse.cdt.internal.core.pdom.dom.IPDOMBinding; + +/** + * Interface that allows to implement a class-scope. + */ +public interface IPDOMCPPEnumType extends ICPPEnumeration, IPDOMBinding, IIndexType { + /** + * Return the scope name, for use in {@link IScope#getScopeName()} + */ + IIndexName getScopeName(); + + IEnumerator[] getEnumerators(); + + /** + * Called by the scope to access the enumerators. + */ + void loadEnumerators(CharArrayMap<PDOMCPPEnumerator> map); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumScope.java new file mode 100644 index 00000000000..83b1a99e351 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumScope.java @@ -0,0 +1,176 @@ +/******************************************************************************* + * Copyright (c) 2010 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.pdom.dom.cpp; + +import java.lang.ref.Reference; +import java.lang.ref.SoftReference; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.dom.IPDOMVisitor; +import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.EScopeKind; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IEnumerator; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope; +import org.eclipse.cdt.core.index.IIndexBinding; +import org.eclipse.cdt.core.index.IIndexFileSet; +import org.eclipse.cdt.core.index.IIndexName; +import org.eclipse.cdt.core.index.IndexFilter; +import org.eclipse.cdt.core.parser.util.CharArrayMap; +import org.eclipse.cdt.core.parser.util.CharArrayUtils; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; +import org.eclipse.cdt.internal.core.index.IIndexScope; +import org.eclipse.cdt.internal.core.pdom.PDOM; +import org.eclipse.core.runtime.CoreException; + +/** + * Represents the enum scope for an enum stored in the index. + */ +class PDOMCPPEnumScope implements ICPPScope, IIndexScope { + private IPDOMCPPEnumType fBinding; + + public PDOMCPPEnumScope(IPDOMCPPEnumType binding) { + fBinding= binding; + } + + public EScopeKind getKind() { + return EScopeKind.eEnumeration; + } + + public IBinding getBinding(IASTName name, boolean resolve) throws DOMException { + return getBinding(name, resolve, null); + } + + public IBinding[] getBindings(IASTName name, boolean resolve, boolean prefixLookup) throws DOMException { + return getBindings(name, resolve, prefixLookup, null); + } + + public IBinding getBinding(IASTName name, boolean resolve, IIndexFileSet fileSet) throws DOMException { + try { + CharArrayMap<PDOMCPPEnumerator> map= getBindingMap(fBinding); + return map.get(name.toCharArray()); + } catch (CoreException e) { + CCorePlugin.log(e); + return null; + } + } + + public IBinding[] getBindings(IASTName name, boolean resolve, boolean prefixLookup, IIndexFileSet fileSet) throws DOMException { + try { + CharArrayMap<PDOMCPPEnumerator> map= getBindingMap(fBinding); + if (prefixLookup) { + final List<IBinding> result= new ArrayList<IBinding>(); + final char[] nc= name.toCharArray(); + for (char[] key : map.keys()) { + if (CharArrayUtils.equals(key, 0, nc.length, nc, true)) { + result.add(map.get(key)); + } + } + return result.toArray(new IBinding[result.size()]); + } + IBinding b= map.get(name.toCharArray()); + if (b != null) { + return new IBinding[] {b}; + } + } catch (Exception e) { + CCorePlugin.log(e); + } + return IBinding.EMPTY_BINDING_ARRAY; + } + + public IBinding[] find(String name) throws DOMException { + return CPPSemantics.findBindings(this, name, false); + } + + public IIndexBinding getScopeBinding() { + return fBinding; + } + + public IIndexScope getParent() { + return fBinding.getScope(); + } + + public IIndexName getScopeName() { + return fBinding.getScopeName(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof PDOMCPPEnumScope) + return fBinding.equals(((PDOMCPPEnumScope) obj).fBinding); + return false; + } + + @Override + public int hashCode() { + return fBinding.hashCode(); + } + + private static CharArrayMap<PDOMCPPEnumerator> getBindingMap(IPDOMCPPEnumType enumeration) throws CoreException { + final Long key= enumeration.getRecord() + PDOMCPPLinkage.CACHE_MEMBERS; + final PDOM pdom = enumeration.getPDOM(); + @SuppressWarnings("unchecked") + Reference<CharArrayMap<PDOMCPPEnumerator>> cached= (Reference<CharArrayMap<PDOMCPPEnumerator>>) pdom.getCachedResult(key); + CharArrayMap<PDOMCPPEnumerator> map= cached == null ? null : cached.get(); + + if (map == null) { + // there is no cache, build it: + map= new CharArrayMap<PDOMCPPEnumerator>(); + enumeration.loadEnumerators(map); + pdom.putCachedResult(key, new SoftReference<CharArrayMap<?>>(map)); + } + return map; + } + + public static void updateCache(PDOMCPPEnumeration enumType, PDOMCPPEnumerator enumItem) { + final Long key= enumType.getRecord() + PDOMCPPLinkage.CACHE_MEMBERS; + final PDOM pdom = enumType.getPDOM(); + @SuppressWarnings("unchecked") + Reference<CharArrayMap<PDOMCPPEnumerator>> cached= (Reference<CharArrayMap<PDOMCPPEnumerator>>) pdom.getCachedResult(key); + CharArrayMap<PDOMCPPEnumerator> map= cached == null ? null : cached.get(); + if (map != null) { + map.put(enumType.getNameCharArray(), enumItem); + } + } + + public static IEnumerator[] getEnumerators(PDOMCPPEnumeration enumType) { + try { + CharArrayMap<PDOMCPPEnumerator> map = getBindingMap(enumType); + List<IEnumerator> result= new ArrayList<IEnumerator>(); + for (IEnumerator value : map.values()) { + if (IndexFilter.ALL_DECLARED.acceptBinding(value)) { + result.add(value); + } + } + Collections.reverse(result); + return result.toArray(new IEnumerator[result.size()]); + } catch (CoreException e) { + CCorePlugin.log(e); + } + return new IEnumerator[0]; + } + + public static void acceptViaCache(PDOMCPPEnumeration enumType, IPDOMVisitor visitor) { + try { + CharArrayMap<PDOMCPPEnumerator> map = getBindingMap(enumType); + for (PDOMCPPEnumerator enumItem : map.values()) { + visitor.visit(enumItem); + visitor.leave(enumItem); + } + } catch (CoreException e) { + CCorePlugin.log(e); + } + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumeration.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumeration.java index ddf18e6c844..c4c707c0cdc 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumeration.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumeration.java @@ -12,9 +12,9 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.dom.cpp; -import java.util.ArrayList; - import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.dom.IPDOMNode; +import org.eclipse.cdt.core.dom.IPDOMVisitor; import org.eclipse.cdt.core.dom.ast.ASTTypeUtil; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IBinding; @@ -22,36 +22,45 @@ import org.eclipse.cdt.core.dom.ast.IEnumeration; import org.eclipse.cdt.core.dom.ast.IEnumerator; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.ITypedef; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope; +import org.eclipse.cdt.core.parser.util.CharArrayMap; import org.eclipse.cdt.core.parser.util.CharArrayUtils; +import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; -import org.eclipse.cdt.internal.core.index.IIndexType; import org.eclipse.cdt.internal.core.pdom.db.Database; +import org.eclipse.cdt.internal.core.pdom.db.PDOMNodeLinkedList; +import org.eclipse.cdt.internal.core.pdom.dom.IPDOMMemberOwner; import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding; import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage; import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; -import org.eclipse.cdt.internal.core.pdom.dom.PDOMNotImplementedError; import org.eclipse.core.runtime.CoreException; /** * Enumerations in the index. */ -class PDOMCPPEnumeration extends PDOMCPPBinding implements IEnumeration, IIndexType { +class PDOMCPPEnumeration extends PDOMCPPBinding implements IPDOMCPPEnumType, IPDOMMemberOwner { - private static final int FIRST_ENUMERATOR = PDOMBinding.RECORD_SIZE; - private static final int OFFSET_MIN_VALUE= FIRST_ENUMERATOR + Database.PTR_SIZE; + private static final int OFFSET_ENUMERATOR_LIST = PDOMBinding.RECORD_SIZE; + private static final int OFFSET_MIN_VALUE= OFFSET_ENUMERATOR_LIST + Database.PTR_SIZE; private static final int OFFSET_MAX_VALUE= OFFSET_MIN_VALUE + 8; + private static final int OFFSET_FIXED_TYPE = OFFSET_MAX_VALUE + 8; + private static final int OFFSET_FLAGS = OFFSET_FIXED_TYPE + Database.TYPE_SIZE; @SuppressWarnings("hiding") - protected static final int RECORD_SIZE = OFFSET_MAX_VALUE + 8; + protected static final int RECORD_SIZE = OFFSET_FLAGS + 1; private Long fMinValue; private Long fMaxValue; + private IType fFixedType= ProblemBinding.NOT_INITIALIZED; + private PDOMCPPEnumScope fScope; - public PDOMCPPEnumeration(PDOMLinkage linkage, PDOMNode parent, IEnumeration enumeration) + public PDOMCPPEnumeration(PDOMLinkage linkage, PDOMNode parent, ICPPEnumeration enumeration) throws CoreException { super(linkage, parent, enumeration.getNameCharArray()); - storeValueBounds(enumeration); + storeProperties(enumeration); } public PDOMCPPEnumeration(PDOMLinkage linkage, long record) { @@ -60,17 +69,25 @@ class PDOMCPPEnumeration extends PDOMCPPBinding implements IEnumeration, IIndexT @Override public void update(PDOMLinkage linkage, IBinding newBinding) throws CoreException { - storeValueBounds((IEnumeration) newBinding); + storeProperties((ICPPEnumeration) newBinding); } - private void storeValueBounds(IEnumeration enumeration) throws CoreException { + private void storeProperties(ICPPEnumeration enumeration) throws CoreException { final Database db= getDB(); - final long minValue = enumeration.getMinValue(); - final long maxValue = enumeration.getMaxValue(); - db.putLong(record+ OFFSET_MIN_VALUE, minValue); - db.putLong(record+ OFFSET_MAX_VALUE, maxValue); - fMinValue= minValue; - fMaxValue= maxValue; + db.putByte(record + OFFSET_FLAGS, enumeration.isScoped() ? (byte) 1 : (byte) 0); + + getLinkage().storeType(record + OFFSET_FIXED_TYPE, enumeration.getFixedType()); + + if (enumeration instanceof ICPPInternalBinding) { + if (((ICPPInternalBinding) enumeration).getDefinition() != null) { + final long minValue = enumeration.getMinValue(); + final long maxValue = enumeration.getMaxValue(); + db.putLong(record+ OFFSET_MIN_VALUE, minValue); + db.putLong(record+ OFFSET_MAX_VALUE, maxValue); + fMinValue= minValue; + fMaxValue= maxValue; + } + } } @Override @@ -83,43 +100,29 @@ class PDOMCPPEnumeration extends PDOMCPPBinding implements IEnumeration, IIndexT return IIndexCPPBindingConstants.CPPENUMERATION; } - public IEnumerator[] getEnumerators() throws DOMException { - try { - ArrayList<PDOMCPPEnumerator> enums = new ArrayList<PDOMCPPEnumerator>(); - for (PDOMCPPEnumerator enumerator = getFirstEnumerator(); - enumerator != null; - enumerator = enumerator.getNextEnumerator()) { - enums.add(enumerator); - } - - IEnumerator[] enumerators = enums.toArray(new IEnumerator[enums.size()]); - - // Reverse the list since they are last in first out - int n = enumerators.length; - for (int i = 0; i < n / 2; ++i) { - IEnumerator tmp = enumerators[i]; - enumerators[i] = enumerators[n - 1 - i]; - enumerators[n - 1 - i] = tmp; - } - - return enumerators; - } catch (CoreException e) { - CCorePlugin.log(e); - return new IEnumerator[0]; - } + public IEnumerator[] getEnumerators() { + return PDOMCPPEnumScope.getEnumerators(this); + } + + @Override + public void accept(IPDOMVisitor visitor) throws CoreException { + PDOMCPPEnumScope.acceptViaCache(this, visitor); } - private PDOMCPPEnumerator getFirstEnumerator() throws CoreException { - long value = getDB().getRecPtr(record + FIRST_ENUMERATOR); - return value != 0 ? new PDOMCPPEnumerator(getLinkage(), value) : null; + @Override + public void addChild(PDOMNode node) throws CoreException { + if (node instanceof PDOMCPPEnumerator) { + PDOMNodeLinkedList list = new PDOMNodeLinkedList(getLinkage(), record + OFFSET_ENUMERATOR_LIST); + list.addMember(node); + PDOMCPPEnumScope.updateCache(this, (PDOMCPPEnumerator) node); + } } - - public void addEnumerator(PDOMCPPEnumerator enumerator) throws CoreException { - PDOMCPPEnumerator first = getFirstEnumerator(); - enumerator.setNextEnumerator(first); - getDB().putRecPtr(record + FIRST_ENUMERATOR, enumerator.getRecord()); + + @Override + public boolean mayHaveChildren() { + return true; } - + public boolean isSameType(IType type) { if (type instanceof ITypedef) { return type.isSameType(this); @@ -176,8 +179,57 @@ class PDOMCPPEnumeration extends PDOMCPPBinding implements IEnumeration, IIndexT return maxValue; } - @Override + @Override public Object clone() { - throw new PDOMNotImplementedError(); + throw new IllegalArgumentException("Enums must not be cloned"); //$NON-NLS-1$ + } + + public boolean isScoped() { + try { + return getDB().getByte(record + OFFSET_FLAGS) != 0; + } catch (CoreException e) { + return false; + } + } + + public IType getFixedType() { + if (fFixedType == ProblemBinding.NOT_INITIALIZED) { + fFixedType= loadFixedType(); + } + return fFixedType; + } + + private IType loadFixedType() { + try { + return getLinkage().loadType(record + OFFSET_FIXED_TYPE); + } catch (CoreException e) { + CCorePlugin.log(e); + return null; + } + } + + public ICPPScope asScope() { + if (fScope == null) { + fScope= new PDOMCPPEnumScope(this); + } + return fScope; + } + + public void loadEnumerators(final CharArrayMap<PDOMCPPEnumerator> map) { + try { + PDOMNodeLinkedList list = new PDOMNodeLinkedList(getLinkage(), record + OFFSET_ENUMERATOR_LIST); + list.accept(new IPDOMVisitor() { + public boolean visit(IPDOMNode node) throws CoreException { + if (node instanceof PDOMCPPEnumerator) { + final PDOMCPPEnumerator item = (PDOMCPPEnumerator) node; + map.put(item.getNameCharArray(), item); + } + return true; + } + public void leave(IPDOMNode node) {} + }); + } catch (CoreException e) { + CCorePlugin.log(e); + } } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumerator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumerator.java index 2c4faec0a1a..8640fc9828d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumerator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPEnumerator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2009 QNX Software Systems and others. + * Copyright (c) 2006, 2010 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -9,7 +9,6 @@ * Doug Schaefer (QNX) - Initial API and implementation * Markus Schorn (Wind River Systems) *******************************************************************************/ - package org.eclipse.cdt.internal.core.pdom.dom.cpp; import org.eclipse.cdt.core.CCorePlugin; @@ -20,8 +19,7 @@ import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.internal.core.dom.parser.Value; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; -import org.eclipse.cdt.internal.core.pdom.db.Database; -import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding; +import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding; import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage; import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; import org.eclipse.core.runtime.CoreException; @@ -30,22 +28,15 @@ import org.eclipse.core.runtime.CoreException; * Binding for a c++ enumerator in the index. */ class PDOMCPPEnumerator extends PDOMCPPBinding implements IEnumerator { - - private static final int ENUMERATION = PDOMBinding.RECORD_SIZE + 0; - private static final int NEXT_ENUMERATOR = PDOMBinding.RECORD_SIZE + 4; - private static final int VALUE= PDOMBinding.RECORD_SIZE + 8; + private static final int VALUE= PDOMCPPBinding.RECORD_SIZE; @SuppressWarnings("hiding") - protected static final int RECORD_SIZE = PDOMBinding.RECORD_SIZE + 12; + protected static final int RECORD_SIZE = VALUE + 4; - public PDOMCPPEnumerator(PDOMLinkage linkage, PDOMNode parent, IEnumerator enumerator, PDOMCPPEnumeration enumeration) + public PDOMCPPEnumerator(PDOMLinkage linkage, PDOMNode parent, IEnumerator enumerator) throws CoreException { super(linkage, parent, enumerator.getNameCharArray()); - - final Database db = getDB(); - db.putRecPtr(record + ENUMERATION, enumeration.getRecord()); - storeValue(db, enumerator); - enumeration.addEnumerator(this); + storeValue(enumerator); } public PDOMCPPEnumerator(PDOMLinkage linkage, long record) { @@ -62,37 +53,25 @@ class PDOMCPPEnumerator extends PDOMCPPBinding implements IEnumerator { return IIndexCPPBindingConstants.CPPENUMERATOR; } - private void storeValue(final Database db, IEnumerator enumerator) throws CoreException { + private void storeValue(IEnumerator enumerator) throws CoreException { IValue value= enumerator.getValue(); if (value != null) { Long val= value.numericalValue(); - db.putInt(record + VALUE, val == null ? -1 : val.intValue()); + getDB().putInt(record + VALUE, val == null ? -1 : val.intValue()); } } @Override public void update(PDOMLinkage linkage, IBinding newBinding) throws CoreException { if (newBinding instanceof IEnumerator) - storeValue(getDB(), (IEnumerator) newBinding); + storeValue((IEnumerator) newBinding); } - public PDOMCPPEnumerator getNextEnumerator() throws CoreException { - long value = getDB().getRecPtr(record + NEXT_ENUMERATOR); - return value != 0 ? new PDOMCPPEnumerator(getLinkage(), value) : null; - } - - public void setNextEnumerator(PDOMCPPEnumerator enumerator) throws CoreException { - long value = enumerator != null ? enumerator.getRecord() : 0; - getDB().putRecPtr(record + NEXT_ENUMERATOR, value); - } - public IType getType() throws DOMException { - try { - return new PDOMCPPEnumeration(getLinkage(), getDB().getRecPtr(record + ENUMERATION)); - } catch (CoreException e) { - CCorePlugin.log(e); - return null; - } + IIndexFragmentBinding owner = getOwner(); + if (owner instanceof IType) + return (IType) owner; + return null; } public IValue getValue() { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java index 15795a7516f..e752c99f450 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2009 QNX Software Systems and others. + * Copyright (c) 2005, 2010 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -31,6 +31,7 @@ import org.eclipse.cdt.core.dom.ast.IProblemBinding; import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.ITypedef; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; @@ -43,6 +44,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecializationSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate; @@ -62,7 +64,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDirective; import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.internal.core.Util; import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; @@ -299,6 +300,10 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { if (fromName.isDefinition()) { return true; } + // Update opaque enums. + if (pdomBinding instanceof ICPPEnumeration && fromName.isDeclaration()) { + return true; + } return !getPDOM().hasLastingDefinition(pdomBinding); } return false; @@ -306,6 +311,7 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { PDOMBinding createBinding(PDOMNode parent, IBinding binding, long fileLocalRec) throws CoreException, DOMException { PDOMBinding pdomBinding= null; + PDOMNode parent2= null; // template parameters are created directly by their owners. if (binding instanceof ICPPTemplateParameter) @@ -361,15 +367,15 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { pdomBinding = new PDOMCPPNamespace(this, parent, (ICPPNamespace) binding); } else if (binding instanceof ICPPUsingDeclaration) { pdomBinding = new PDOMCPPUsingDeclaration(this, parent, (ICPPUsingDeclaration) binding); - } else if (binding instanceof IEnumeration) { - pdomBinding = new PDOMCPPEnumeration(this, parent, (IEnumeration) binding); + } else if (binding instanceof ICPPEnumeration) { + pdomBinding = new PDOMCPPEnumeration(this, parent, (ICPPEnumeration) binding); } else if (binding instanceof IEnumerator) { - final IEnumerator etor = (IEnumerator) binding; - IType enumeration= etor.getType(); - if (enumeration instanceof IEnumeration) { - PDOMBinding pdomEnumeration = adaptBinding((IEnumeration) enumeration); - if (pdomEnumeration instanceof PDOMCPPEnumeration) { - pdomBinding = new PDOMCPPEnumerator(this, parent, etor, (PDOMCPPEnumeration)pdomEnumeration); + assert parent instanceof ICPPEnumeration; + pdomBinding = new PDOMCPPEnumerator(this, parent, (IEnumerator) binding); + if (parent instanceof ICPPEnumeration && !((ICPPEnumeration) parent).isScoped()) { + parent2= parent.getParentNode(); + if (parent2 == null) { + parent2= this; } } } else if (binding instanceof ITypedef) { @@ -379,7 +385,12 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { if (pdomBinding != null) { pdomBinding.setLocalToFileRec(fileLocalRec); parent.addChild(pdomBinding); - afterAddBinding(pdomBinding); + if (parent2 != null) { + parent2.addChild(pdomBinding); + } + if (parent2 != this) { + insertIntoNestedBindingsIndex(pdomBinding); + } } return pdomBinding; |