diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/VisibilityAsserts.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/VisibilityAsserts.java new file mode 100644 index 00000000000..86a857cd3a0 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/VisibilityAsserts.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2013 Institute for Software, HSR Hochschule fuer Technik + * Rapperswil, University of applied sciences 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: + * Thomas Corbat - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.core.parser.tests; + +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; +import junit.framework.Assert; + +public class VisibilityAsserts { + public static void assertVisibility(int expected, int actual) { + Assert.assertEquals(visibilityName(expected), visibilityName(actual)); + } + + public static String visibilityName(int visibility) { + switch (visibility) { + case ICPPClassType.v_private: + return "private"; + case ICPPClassType.v_protected: + return "protected"; + case ICPPClassType.v_public: + return "public"; + default: + throw new IllegalArgumentException("Illegal visibility: " + visibility); + } + } +} 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 a15414a8d23..0c0772ba1e9 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 @@ -20,6 +20,7 @@ package org.eclipse.cdt.core.parser.tests.ast2; import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE; import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.XVALUE; import static org.eclipse.cdt.core.parser.ParserLanguage.CPP; +import static org.eclipse.cdt.core.parser.tests.VisibilityAsserts.assertVisibility; import java.io.BufferedReader; import java.io.IOException; @@ -10267,10 +10268,60 @@ public class AST2CPPTests extends AST2TestBase { parseAndCheckBindings(code); BindingAssertionHelper bh = new BindingAssertionHelper(code, true); - ICPPNamespace NamespaceNS = bh.assertNonProblem("NS {", 2); ICPPClassType Inner = bh.assertNonProblem("Inner;", 5); assertEquals(NamespaceNS.getNamespaceScope(), Inner.getScope()); } + + // class AClass { + // int defaultMemberVariable; + // void defaultMemberFunction(); + // class defaultNestedClass {}; + // public: + // int publicMemberVariable; + // void publicMemberFunction(); + // class publicNestedClass {}; + // protected: + // int protectedMemberVariable; + // void protectedMemberFunction(); + // class protectedNestedClass {}; + // private: + // int privateMemberVariable; + // void privateMemberFunction(); + // class privateNestedClass {}; + // }; + public void testMemberAccessibilities() throws Exception { + BindingAssertionHelper bh = getAssertionHelper(); + + ICPPClassType aClass = bh.assertNonProblem("AClass"); + + ICPPField defaultMemberVariable = bh.assertNonProblem("defaultMemberVariable"); + assertVisibility(ICPPClassType.v_private, aClass.getVisibility(defaultMemberVariable)); + ICPPMethod defaultMemberFunction = bh.assertNonProblem("defaultMemberFunction"); + assertVisibility(ICPPClassType.v_private, aClass.getVisibility(defaultMemberFunction)); + ICPPClassType defaultNestedClass = bh.assertNonProblem("defaultNestedClass"); + assertVisibility(ICPPClassType.v_private, aClass.getVisibility(defaultNestedClass)); + + ICPPField publicMemberVariable = bh.assertNonProblem("publicMemberVariable"); + assertVisibility(ICPPClassType.v_public, aClass.getVisibility(publicMemberVariable)); + ICPPMethod publicMemberFunction = bh.assertNonProblem("publicMemberFunction"); + assertVisibility(ICPPClassType.v_public, aClass.getVisibility(publicMemberFunction)); + ICPPClassType publicNestedClass = bh.assertNonProblem("publicNestedClass"); + assertVisibility(ICPPClassType.v_public, aClass.getVisibility(publicNestedClass)); + + ICPPField protectedMemberVariable = bh.assertNonProblem("protectedMemberVariable"); + assertVisibility(ICPPClassType.v_protected, aClass.getVisibility(protectedMemberVariable)); + ICPPMethod protectedMemberFunction = bh.assertNonProblem("protectedMemberFunction"); + assertVisibility(ICPPClassType.v_protected, aClass.getVisibility(protectedMemberFunction)); + ICPPClassType protectedNestedClass = bh.assertNonProblem("protectedNestedClass"); + assertVisibility(ICPPClassType.v_protected, aClass.getVisibility(protectedNestedClass)); + + ICPPField privateMemberVariable = bh.assertNonProblem("privateMemberVariable"); + assertVisibility(ICPPClassType.v_private, aClass.getVisibility(privateMemberVariable)); + ICPPMethod privateMemberFunction = bh.assertNonProblem("privateMemberFunction"); + assertVisibility(ICPPClassType.v_private, aClass.getVisibility(privateMemberFunction)); + ICPPClassType privateNestedClass = bh.assertNonProblem("privateNestedClass"); + assertVisibility(ICPPClassType.v_private, aClass.getVisibility(privateNestedClass)); + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java index 484035bb24d..2371a96d05c 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java @@ -20,6 +20,7 @@ import static org.eclipse.cdt.core.parser.ParserLanguage.CPP; import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF; import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getNestedType; import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getUltimateType; +import static org.eclipse.cdt.core.parser.tests.VisibilityAsserts.assertVisibility; import java.io.IOException; @@ -7653,4 +7654,65 @@ public class AST2TemplateTests extends AST2TestBase { public void testTemplateBaseClassConstructorCall_402602() throws Exception { parseAndCheckBindings(); } + + // template + // class ATemplate { + // int defaultMemberVariable; + // public: + // int publicMemberVariable; + // protected: + // int protectedMemberVariable; + // private: + // int privateMemberVariable; + // }; + public void testTemplateMemberAccessibilities() throws Exception { + BindingAssertionHelper bh = getAssertionHelper(); + + ICPPClassTemplate aTemplate = bh.assertNonProblem("ATemplate"); + + ICPPField defaultMemberVariable = bh.assertNonProblem("defaultMemberVariable"); + assertVisibility(ICPPClassType.v_private, aTemplate.getVisibility(defaultMemberVariable)); + + ICPPField publicMemberVariable = bh.assertNonProblem("publicMemberVariable"); + assertVisibility(ICPPClassType.v_public, aTemplate.getVisibility(publicMemberVariable)); + + ICPPField protectedMemberVariable = bh.assertNonProblem("protectedMemberVariable"); + assertVisibility(ICPPClassType.v_protected, aTemplate.getVisibility(protectedMemberVariable)); + + ICPPField privateMemberVariable = bh.assertNonProblem("privateMemberVariable"); + assertVisibility(ICPPClassType.v_private, aTemplate.getVisibility(privateMemberVariable)); + } + + // template + // class ATemplate {}; + // + // class A{}; + // + // template<> + // class ATemplate { + // int specializedDefaultVariable; + // public: + // int specializedPublicVariable; + // protected: + // int specializedProtectedVariable; + // private: + // int specializedPrivateVariable; + // }; + public void testTemplateSpecializationMemberAccessibilities() throws Exception { + BindingAssertionHelper bh = getAssertionHelper(); + + ICPPClassSpecialization aTemplateSpecialization = bh.assertNonProblem("ATemplate"); + + ICPPField defaultMemberVariable = bh.assertNonProblem("specializedDefaultVariable"); + assertVisibility(ICPPClassType.v_private, aTemplateSpecialization.getVisibility(defaultMemberVariable)); + + ICPPField publicMemberVariable = bh.assertNonProblem("specializedPublicVariable"); + assertVisibility(ICPPClassType.v_public, aTemplateSpecialization.getVisibility(publicMemberVariable)); + + ICPPField protectedMemberVariable = bh.assertNonProblem("specializedProtectedVariable"); + assertVisibility(ICPPClassType.v_protected, aTemplateSpecialization.getVisibility(protectedMemberVariable)); + + ICPPField privateMemberVariable = bh.assertNonProblem("specializedPrivateVariable"); + assertVisibility(ICPPClassType.v_private, aTemplateSpecialization.getVisibility(privateMemberVariable)); + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java index 0fccd2ed7c8..4579f58225e 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java @@ -13,9 +13,6 @@ *******************************************************************************/ package org.eclipse.cdt.internal.index.tests; -import java.util.ArrayList; -import java.util.List; - import junit.framework.TestSuite; import org.eclipse.cdt.core.dom.ast.ASTTypeUtil; @@ -68,6 +65,9 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; import org.eclipse.cdt.internal.core.index.IIndexScope; import org.eclipse.core.runtime.CoreException; +import java.util.ArrayList; +import java.util.List; + /** * Tests for exercising resolution of template bindings against IIndex */ diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/CPPClassTemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/CPPClassTemplateTests.java index a96517f71b0..aa987d83a76 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/CPPClassTemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/CPPClassTemplateTests.java @@ -15,19 +15,18 @@ import java.util.Arrays; import junit.framework.Test; -import org.eclipse.cdt.core.dom.IPDOMManager; import org.eclipse.cdt.core.dom.ast.IBasicType; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IField; import org.eclipse.cdt.core.dom.ast.IFunctionType; import org.eclipse.cdt.core.dom.ast.IPointerType; import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPAliasTemplate; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPAliasTemplateInstance; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization; 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.ICPPSpecialization; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPAliasTemplate; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPAliasTemplateInstance; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; @@ -35,27 +34,16 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable; import org.eclipse.cdt.core.index.IndexFilter; -import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.parser.util.ObjectMap; -import org.eclipse.cdt.core.testplugin.CProjectHelper; -import org.eclipse.cdt.core.testplugin.CTestPlugin; -import org.eclipse.cdt.core.testplugin.util.TestSourceReader; -import org.eclipse.cdt.internal.core.CCoreInternals; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance; import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding; -import org.eclipse.cdt.internal.core.pdom.PDOM; -import org.eclipse.cdt.internal.core.pdom.indexer.IndexerPreferences; -import org.eclipse.core.resources.IFile; -import org.eclipse.core.runtime.Path; /** * Tests PDOM class template related bindings */ -public class CPPClassTemplateTests extends PDOMTestBase { - protected PDOM pdom; - protected ICProject cproject; +public class CPPClassTemplateTests extends PDOMInlineCodeTestBase { public static Test suite() { return suite(CPPClassTemplateTests.class); @@ -63,31 +51,10 @@ public class CPPClassTemplateTests extends PDOMTestBase { @Override public void setUp() throws Exception { - cproject= CProjectHelper.createCCProject("classTemplateTests"+System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER); + super.setUp(); setUpSections(1); } - protected void setUpSections(int sections) throws Exception { - CharSequence[] contents= TestSourceReader.getContentsForTest( - CTestPlugin.getDefault().getBundle(), "parser", getClass(), getName(), sections); - for (CharSequence content : contents) { - IFile file= TestSourceReader.createFile(cproject.getProject(), new Path("refs.cpp"), content.toString()); - } - IndexerPreferences.set(cproject.getProject(), IndexerPreferences.KEY_INDEXER_ID, IPDOMManager.ID_FAST_INDEXER); - waitForIndexer(cproject); - pdom= (PDOM) CCoreInternals.getPDOMManager().getPDOM(cproject); - pdom.acquireReadLock(); - } - - @Override - protected void tearDown() throws Exception { - if(pdom != null) { - pdom.releaseReadLock(); - } - pdom= null; - cproject.getProject().delete(true, npm()); - } - /*************************************************************************/ // template diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/CPPFieldTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/CPPFieldTests.java index dbe1cf3855f..c30816edc83 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/CPPFieldTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/CPPFieldTests.java @@ -79,19 +79,19 @@ public class CPPFieldTests extends PDOMTestBase { } public void testDefaultPrivateField() throws Exception { - assertVisibility(pdom, "Class1::defaultField", ICPPMember.v_private); + assertCPPMemberVisibility(pdom, "Class1::defaultField", ICPPMember.v_private); } public void testPrivateField() throws Exception { - assertVisibility(pdom, "Class1::privateField", ICPPMember.v_private); + assertCPPMemberVisibility(pdom, "Class1::privateField", ICPPMember.v_private); } public void testProtectedField() throws Exception { - assertVisibility(pdom, "Class1::protectedField", ICPPMember.v_protected); + assertCPPMemberVisibility(pdom, "Class1::protectedField", ICPPMember.v_protected); } public void testPublicField() throws Exception { - assertVisibility(pdom, "Class1::publicField", ICPPMember.v_public); + assertCPPMemberVisibility(pdom, "Class1::publicField", ICPPMember.v_public); } public void testMutableField() throws Exception { diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/CPPFunctionTemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/CPPFunctionTemplateTests.java index 82e8550af9d..123b5bd0850 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/CPPFunctionTemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/CPPFunctionTemplateTests.java @@ -16,59 +16,19 @@ import java.util.List; import junit.framework.Test; -import org.eclipse.cdt.core.CCorePlugin; -import org.eclipse.cdt.core.dom.IPDOMManager; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance; import org.eclipse.cdt.core.index.IndexFilter; -import org.eclipse.cdt.core.model.ICProject; -import org.eclipse.cdt.core.testplugin.CProjectHelper; -import org.eclipse.cdt.core.testplugin.CTestPlugin; -import org.eclipse.cdt.core.testplugin.util.TestSourceReader; -import org.eclipse.cdt.internal.core.CCoreInternals; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInstanceCache; import org.eclipse.cdt.internal.core.index.IIndexFragment; -import org.eclipse.cdt.internal.core.pdom.PDOM; -import org.eclipse.cdt.internal.core.pdom.indexer.IndexerPreferences; -import org.eclipse.core.resources.IFile; -import org.eclipse.core.runtime.Path; -public class CPPFunctionTemplateTests extends PDOMTestBase { - protected PDOM pdom; - protected ICProject cproject; +public class CPPFunctionTemplateTests extends PDOMInlineCodeTestBase { public static Test suite() { return suite(CPPFunctionTemplateTests.class); } - @Override - public void setUp() throws Exception { - cproject= CProjectHelper.createCCProject("functionTemplateTests"+System.currentTimeMillis(), "bin", IPDOMManager.ID_NO_INDEXER); - } - - protected void setUpSections(int sections) throws Exception { - StringBuilder[] contents= TestSourceReader.getContentsForTest( - CTestPlugin.getDefault().getBundle(), "parser", getClass(), getName(), sections); - for (StringBuilder content : contents) { - IFile file= TestSourceReader.createFile(cproject.getProject(), new Path("refs.cpp"), content.toString()); - } - IndexerPreferences.set(cproject.getProject(), IndexerPreferences.KEY_INDEXER_ID, IPDOMManager.ID_FAST_INDEXER); - CCorePlugin.getIndexManager().reindex(cproject); - waitForIndexer(cproject); - pdom= (PDOM) CCoreInternals.getPDOMManager().getPDOM(cproject); - pdom.acquireReadLock(); - } - - @Override - protected void tearDown() throws Exception { - if(pdom!=null) { - pdom.releaseReadLock(); - } - pdom= null; - cproject.getProject().delete(true, npm()); - } - /*************************************************************************/ // template diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/ClassMemberVisibilityTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/ClassMemberVisibilityTests.java new file mode 100644 index 00000000000..f36ac158af6 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/ClassMemberVisibilityTests.java @@ -0,0 +1,189 @@ +/******************************************************************************* + * Copyright (c) 2013 Institute for Software, HSR Hochschule fuer Technik + * Rapperswil, University of applied sciences. + * 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: + * Thomas Corbat (IFS) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.pdom.tests; + +import junit.framework.Test; + +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; +import org.eclipse.core.runtime.CoreException; + +import static org.eclipse.cdt.core.parser.tests.VisibilityAsserts.assertVisibility; + +/** + * @author Thomas Corbat + * + * Tests for ensuring the PDOM contains the correct visibility information for class members. + */ +public class ClassMemberVisibilityTests extends PDOMInlineCodeTestBase { + + public static Test suite() { + return suite(ClassMemberVisibilityTests.class); + } + + public void setUp() throws Exception { + super.setUp(); + setUpSections(1); + } + + // class A { + // void defaultMemFun(); + // public: + // void publicMemFun(); + // protected: + // void protectedMemFun(); + // private: + // void privateMemFun(); + // }; + public void testVisibilityDefaultMemberFunction() throws Exception { + IBinding[] defaultFunction = findQualifiedPossiblyImplicit(pdom, "A::defaultMemFun"); + assertVisibility(ICPPClassType.v_private, getMemberVisibility(defaultFunction[0])); + + IBinding[] publicFunction = findQualifiedPossiblyImplicit(pdom, "A::publicMemFun"); + assertVisibility(ICPPClassType.v_public, getMemberVisibility(publicFunction[0])); + + IBinding[] protectedFunction = findQualifiedPossiblyImplicit(pdom, "A::protectedMemFun"); + assertVisibility(ICPPClassType.v_protected, getMemberVisibility(protectedFunction[0])); + + IBinding[] privateFunction = findQualifiedPossiblyImplicit(pdom, "A::privateMemFun"); + assertVisibility(ICPPClassType.v_private, getMemberVisibility(privateFunction[0])); + } + + // class A { + // int defaultVariable; + // public: + // int publicVariable; + // protected: + // int protectedVariable; + // private: + // int privateVariable; + // }; + public void testVisibilityDefaultMemberVariable() throws Exception { + IBinding[] defaultVariable = findQualifiedPossiblyImplicit(pdom, "A::defaultVariable"); + assertVisibility(ICPPClassType.v_private, getMemberVisibility(defaultVariable[0])); + + IBinding[] publicVariable = findQualifiedPossiblyImplicit(pdom, "A::publicVariable"); + assertVisibility(ICPPClassType.v_public, getMemberVisibility(publicVariable[0])); + + IBinding[] protectedVariable = findQualifiedPossiblyImplicit(pdom, "A::protectedVariable"); + assertVisibility(ICPPClassType.v_protected, getMemberVisibility(protectedVariable[0])); + + IBinding[] privateVariable = findQualifiedPossiblyImplicit(pdom, "A::privateVariable"); + assertVisibility(ICPPClassType.v_private, getMemberVisibility(privateVariable[0])); + } + + // class A { + // class DefaultNested {}; + // public: + // class PublicNested {}; + // protected: + // class ProtectedNested {}; + // private: + // class PrivateNested {}; + // }; + public void testVisibilityDefaultNestedClass() throws Exception { + IBinding[] defaultNested = findQualifiedPossiblyImplicit(pdom, "A::DefaultNested"); + assertVisibility(ICPPClassType.v_private, getMemberVisibility(defaultNested[0])); + + IBinding[] publicNested = findQualifiedPossiblyImplicit(pdom, "A::PublicNested"); + assertVisibility(ICPPClassType.v_public, getMemberVisibility(publicNested[0])); + + IBinding[] protectedNested = findQualifiedPossiblyImplicit(pdom, "A::ProtectedNested"); + assertVisibility(ICPPClassType.v_protected, getMemberVisibility(protectedNested[0])); + + IBinding[] privateNested = findQualifiedPossiblyImplicit(pdom, "A::PrivateNested"); + assertVisibility(ICPPClassType.v_private, getMemberVisibility(privateNested[0])); + } + + // class A { + // }; + public void testVisibilityImplicitClassMembers() throws Exception { + IBinding[] memberBindings = findQualifiedPossiblyImplicit(pdom, "A::A"); + + assertVisibility(ICPPClassType.v_public, getMemberVisibility(memberBindings[0])); + assertVisibility(ICPPClassType.v_public, getMemberVisibility(memberBindings[1])); + } + + // template + // class Tpl { + // }; + // template<> + // class Tpl { + // }; + public void testVisibilityImplicitTemplateMembers() throws Exception { + IBinding[] memberBindings = findQualifiedPossiblyImplicit(pdom, "Tpl::Tpl"); + + assertVisibility(ICPPClassType.v_public, getMemberVisibility(memberBindings[0])); + assertVisibility(ICPPClassType.v_public, getMemberVisibility(memberBindings[1])); + assertVisibility(ICPPClassType.v_public, getMemberVisibility(memberBindings[2])); + assertVisibility(ICPPClassType.v_public, getMemberVisibility(memberBindings[3])); + + } + + // template + // class Tpl { + // }; + // template<> + // class Tpl { + // int specializedDefaultVariable; + // }; + public void testVisibilitySpecializedDefaultVariable() throws Exception { + IBinding[] memberBindings = findQualifiedPossiblyImplicit(pdom, "Tpl::specializedDefaultVariable"); + assertVisibility(ICPPClassType.v_private, getMemberVisibility(memberBindings[0])); + } + + // template + // class Tpl { + // }; + // template<> + // class Tpl { + // public: + // int specializedPublicVariable; + // }; + public void testVisibilitySpecializedPublicVariable() throws Exception { + IBinding[] memberBindings = findQualifiedPossiblyImplicit(pdom, "Tpl::specializedPublicVariable"); + assertVisibility(ICPPClassType.v_public, getMemberVisibility(memberBindings[0])); + } + + // template + // class Tpl { + // }; + // template<> + // class Tpl { + // protected: + // int specializedProtectedVariable; + // }; + public void testVisibilitySpecializedProtectedVariable() throws Exception { + IBinding[] memberBindings = findQualifiedPossiblyImplicit(pdom, "Tpl::specializedProtectedVariable"); + assertVisibility(ICPPClassType.v_protected, getMemberVisibility(memberBindings[0])); + } + + // template + // class Tpl { + // }; + // template<> + // class Tpl { + // private: + // int specializedPrivateVariable; + // }; + public void testVisibilitySpecializedPrivateVariable() throws Exception { + IBinding[] memberBinding = findQualifiedPossiblyImplicit(pdom, "Tpl::specializedPrivateVariable"); + assertVisibility(ICPPClassType.v_private, getMemberVisibility(memberBinding[0])); + } + + private int getMemberVisibility(IBinding memberBinding) throws CoreException { + IBinding owner = memberBinding.getOwner(); + assertInstance(owner, ICPPClassType.class); + ICPPClassType classBinding = (ICPPClassType) owner; + return classBinding.getVisibility(memberBinding); + } +} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/MethodTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/MethodTests.java index e47de9c7eaa..f8ee8f4d2d7 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/MethodTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/MethodTests.java @@ -163,19 +163,19 @@ public class MethodTests extends PDOMTestBase { } public void testDefaultPrivateMethod() throws Exception { - assertVisibility(pdom, "Class3::defaultMethod", ICPPMember.v_private); + assertCPPMemberVisibility(pdom, "Class3::defaultMethod", ICPPMember.v_private); } public void testPrivateMethod() throws Exception { - assertVisibility(pdom, "Class3::privateMethod", ICPPMember.v_private); + assertCPPMemberVisibility(pdom, "Class3::privateMethod", ICPPMember.v_private); } public void testProtectedMethod() throws Exception { - assertVisibility(pdom, "Class3::protectedMethod", ICPPMember.v_protected); + assertCPPMemberVisibility(pdom, "Class3::protectedMethod", ICPPMember.v_protected); } public void testPublicMethod() throws Exception { - assertVisibility(pdom, "Class3::publicMethod", ICPPMember.v_public); + assertCPPMemberVisibility(pdom, "Class3::publicMethod", ICPPMember.v_public); } public void testInlineMethod() throws Exception { diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMInlineCodeTestBase.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMInlineCodeTestBase.java new file mode 100644 index 00000000000..79a6f0966db --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMInlineCodeTestBase.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2013 Institute for Software, HSR Hochschule fuer Technik + * Rapperswil, University of applied sciences. + * 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: + * Thomas Corbat (IFS) - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.pdom.tests; + +import org.eclipse.cdt.core.dom.IPDOMManager; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.testplugin.CProjectHelper; +import org.eclipse.cdt.core.testplugin.CTestPlugin; +import org.eclipse.cdt.core.testplugin.util.TestSourceReader; +import org.eclipse.cdt.internal.core.CCoreInternals; +import org.eclipse.cdt.internal.core.pdom.PDOM; +import org.eclipse.cdt.internal.core.pdom.indexer.IndexerPreferences; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.Path; + +/** + * @author Thomas Corbat + * + * Base class for PDOM tests relying on code placed in comments in front + * of the test. + */ +public class PDOMInlineCodeTestBase extends PDOMTestBase { + protected PDOM pdom; + protected ICProject cproject; + + public void setUp() throws Exception { + cproject = CProjectHelper.createCCProject("classTemplateTests" + System.currentTimeMillis(), + "bin", IPDOMManager.ID_NO_INDEXER); + } + + protected void setUpSections(int sections) throws Exception { + CharSequence[] contents = TestSourceReader.getContentsForTest( + CTestPlugin.getDefault().getBundle(), "parser", getClass(), + getName(), sections); + for (CharSequence content : contents) { + IFile file = TestSourceReader.createFile(cproject.getProject(), + new Path("refs.cpp"), content.toString()); + } + IndexerPreferences + .set(cproject.getProject(), IndexerPreferences.KEY_INDEXER_ID, IPDOMManager.ID_FAST_INDEXER); + waitForIndexer(cproject); + pdom = (PDOM) CCoreInternals.getPDOMManager().getPDOM(cproject); + pdom.acquireReadLock(); + } + + @Override + protected void tearDown() throws Exception { + if (pdom != null) { + pdom.releaseReadLock(); + } + pdom = null; + cproject.getProject().delete(true, npm()); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMTestBase.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMTestBase.java index 26cce84ea6c..9b61ced1aed 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMTestBase.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMTestBase.java @@ -31,6 +31,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPMember; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IndexFilter; import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.parser.tests.VisibilityAsserts; import org.eclipse.cdt.core.testplugin.CProjectHelper; import org.eclipse.cdt.core.testplugin.CTestPlugin; import org.eclipse.cdt.core.testplugin.util.BaseTestCase; @@ -202,11 +203,11 @@ public class PDOMTestBase extends BaseTestCase { assertTrue(c.isAssignableFrom(bindings[0].getClass())); } - protected void assertVisibility(PDOM pdom, String name, int visibility) throws CoreException, DOMException { + protected void assertCPPMemberVisibility(PDOM pdom, String name, int visibility) throws CoreException, DOMException { IBinding[] bindings = findQualifiedName(pdom, name); assertEquals(1, bindings.length); ICPPMember member = (ICPPMember) bindings[0]; - assertEquals(visibility, member.getVisibility()); + VisibilityAsserts.assertVisibility(visibility, member.getVisibility()); } public static final void assertFunctionRefCount(PDOM pdom, Class[] args, IBinding[] bindingPool, int refCount) throws CoreException { diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMTests.java index 3640bbe7339..67222982b06 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/pdom/tests/PDOMTests.java @@ -50,6 +50,7 @@ public class PDOMTests extends TestSuite { suite.addTest(CPPFunctionTemplateTests.suite()); suite.addTest(MethodTests.suite()); suite.addTest(NamespaceTests.suite()); + suite.addTest(ClassMemberVisibilityTests.suite()); suite.addTest(CFunctionTests.suite()); suite.addTest(CVariableTests.suite()); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPClassType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPClassType.java index 6001441179a..dc82ed56408 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPClassType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPClassType.java @@ -24,6 +24,18 @@ import org.eclipse.cdt.core.dom.ast.IField; public interface ICPPClassType extends ICompositeType, ICPPBinding { public static final ICPPClassType[] EMPTY_CLASS_ARRAY = {}; public static final int k_class = ICPPASTCompositeTypeSpecifier.k_class; + /** + * @since 5.5 + */ + public static final int v_public = ICPPASTVisibilityLabel.v_public; + /** + * @since 5.5 + */ + public static final int v_protected = ICPPASTVisibilityLabel.v_protected; + /** + * @since 5.5 + */ + public static final int v_private = ICPPASTVisibilityLabel.v_private; /** * Returns an array of base class relationships. The returned array is empty if there @@ -107,4 +119,18 @@ public interface ICPPClassType extends ICompositeType, ICPPBinding { * @since 5.5 */ public boolean isFinal(); + + /** + * Gets the access specifier of the member. + * + * @param member The binding of the member to get the visibility for. + * member must be a member of this type. + * + * @return the visibility of the specified member. + * + * @throws IllegalArgumentException if member is not a member of this type. + * + * @since 5.5 + */ + public int getVisibility(IBinding member); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java index 6aa3c0be5c7..7d13ebbd670 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java @@ -447,4 +447,9 @@ public class CPPClassSpecialization extends CPPSpecialization } return false; } + + @Override + public int getVisibility(IBinding member) { + return ClassTypeHelper.getVisibility(this, member); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplate.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplate.java index fd1382816c9..3b56410dd6b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplate.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplate.java @@ -251,4 +251,9 @@ public class CPPClassTemplate extends CPPTemplateDefinition implements ICPPClass } return false; } + + @Override + public int getVisibility(IBinding member) { + return ClassTypeHelper.getVisibility(this, member); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java index 11fdfe55c6b..10fcdb8cea5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java @@ -109,6 +109,10 @@ public class CPPClassType extends PlatformObject implements ICPPInternalClassTyp public boolean isFinal() { return false; } + @Override + public int getVisibility(IBinding member) { + throw new IllegalArgumentException(member.getName() + " is not a member of " + getName()); //$NON-NLS-1$ + } } private IASTName definition; @@ -413,4 +417,9 @@ public class CPPClassType extends PlatformObject implements ICPPInternalClassTyp } return name; } + + @Override + public int getVisibility(IBinding member) { + return ClassTypeHelper.getVisibility(this, member); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClosureType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClosureType.java index 979cc8fd7b3..4dc9994da48 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClosureType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClosureType.java @@ -344,6 +344,10 @@ public class CPPClosureType extends PlatformObject implements ICPPClassType, ICP return false; } + @Override + public int getVisibility(IBinding member) { + throw new IllegalArgumentException(member.getName() + " is not a member of " + getName()); //$NON-NLS-1$ + } private final class ClassScope implements ICPPClassScope { @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredClassInstance.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredClassInstance.java index 605f88708d9..d94227451cd 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredClassInstance.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredClassInstance.java @@ -246,4 +246,9 @@ public class CPPDeferredClassInstance extends CPPUnknownBinding implements ICPPD } return new PDOMCPPDeferredClassInstance(fragment, (ICPPClassTemplate) template, args); } + + @Override + public int getVisibility(IBinding member) { + throw new IllegalArgumentException(member.getName() + " is not a member of " + getName()); //$NON-NLS-1$ + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateTemplateParameter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateTemplateParameter.java index 88d0455d02b..bf4e8442f61 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateTemplateParameter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateTemplateParameter.java @@ -246,4 +246,9 @@ public class CPPTemplateTemplateParameter extends CPPTemplateParameter implement public boolean isFinal() { return false; } + + @Override + public int getVisibility(IBinding member) { + throw new IllegalArgumentException(member.getName() + " is not a member of " + getName()); //$NON-NLS-1$ + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownMemberClass.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownMemberClass.java index 51231b0fa12..5ed49c9b025 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownMemberClass.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownMemberClass.java @@ -133,4 +133,9 @@ public class CPPUnknownMemberClass extends CPPUnknownMember implements ICPPUnkno public boolean isFinal() { return false; } + + @Override + public int getVisibility(IBinding member) { + throw new IllegalArgumentException(member.getName() + " is not a member of " + getName()); //$NON-NLS-1$ + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ClassTypeHelper.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ClassTypeHelper.java index 78de34c2458..b2cb6e9f2db 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ClassTypeHelper.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ClassTypeHelper.java @@ -16,20 +16,11 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; - import org.eclipse.cdt.core.dom.ast.ASTTypeUtil; 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.IASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; @@ -41,12 +32,16 @@ import org.eclipse.cdt.core.dom.ast.IQualifierType; 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.ICPPASTAliasDeclaration; 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.ICPPASTDeclSpecifier; 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.ICPPASTNamespaceDefinition; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisibilityLabel; 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.ICPPClassScope; @@ -72,6 +67,16 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; import org.eclipse.core.runtime.CoreException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + /** * Holds common implementation of methods for ICPPClassType implementations that have * a corresponding textual definition in the source code. @@ -885,6 +890,106 @@ public class ClassTypeHelper { return resultArray; } + /** + * Returns the visibility for a given member in the host. + * Throws an IllegalArgumentException if member is not a member of host + * + * @param classType The class to get the member's visibility specifier of. + * @return the visibility of the member. + */ + public static int getVisibility(ICPPInternalClassTypeMixinHost classType, IBinding member) { + if (classType.getDefinition() == null) { + classType.checkForDefinition(); + if (classType.getDefinition() == null) { + ICPPClassType backup = getBackupDefinition(classType); + if (backup != null) { + return backup.getVisibility(member); + } + return ICPPClassType.v_public; // Fallback visibility + } + } + + int visibility = + classType.getKey() == ICPPClassType.k_class ? ICPPClassType.v_private : ICPPClassType.v_public; + + IASTDeclaration[] hostMembers = classType.getCompositeTypeSpecifier().getMembers(); + for (IASTDeclaration hostMember : hostMembers) { + if (hostMember instanceof ICPPASTVisibilityLabel) { + visibility = ((ICPPASTVisibilityLabel) hostMember).getVisibility(); + } + while (hostMember instanceof ICPPASTTemplateDeclaration) { + hostMember = ((ICPPASTTemplateDeclaration) hostMember).getDeclaration(); + } + if (hostMember instanceof IASTSimpleDeclaration) { + IASTSimpleDeclaration memberDeclaration = (IASTSimpleDeclaration) hostMember; + for (IASTDeclarator memberDeclarator : memberDeclaration.getDeclarators()) { + IBinding memberBinding = + ASTQueries.findInnermostDeclarator(memberDeclarator).getName().resolveBinding(); + if (member.equals(memberBinding)){ + return visibility; + } + } + + IASTDeclSpecifier declSpec = memberDeclaration.getDeclSpecifier(); + if (declSpec instanceof ICPPASTCompositeTypeSpecifier) { + IBinding memberBinding = + ((ICPPASTCompositeTypeSpecifier) declSpec).getName().resolveBinding(); + if (member.equals(memberBinding)) { + return visibility; + } + if (member instanceof IType && memberBinding instanceof IType && + ((IType) member).isSameType((IType) memberBinding)) { + return visibility; + } + } else if (declSpec instanceof ICPPASTElaboratedTypeSpecifier + && memberDeclaration.getDeclarators().length == 0) { + IBinding memberBinding = + ((ICPPASTElaboratedTypeSpecifier) declSpec).getName().resolveBinding(); + if (member.equals(memberBinding)) { + return visibility; + } + } else if (declSpec instanceof ICPPASTEnumerationSpecifier) { + IBinding enumerationBinding = ((ICPPASTEnumerationSpecifier) declSpec).getName().resolveBinding(); + if (member.equals(enumerationBinding)) { + return visibility; + } + if (member instanceof IType && enumerationBinding instanceof IType && + ((IType) member).isSameType((IType) enumerationBinding)) { + return visibility; + } + } + } else if (hostMember instanceof IASTFunctionDefinition) { + IASTFunctionDeclarator declarator = ((IASTFunctionDefinition) hostMember).getDeclarator(); + IBinding functionBinding = declarator.getName().resolveBinding(); + if (member.equals(functionBinding)){ + return visibility; + } + } else if (hostMember instanceof ICPPASTAliasDeclaration) { + IBinding aliasBinding = ((ICPPASTAliasDeclaration) hostMember).getAlias().resolveBinding(); + if (member.equals(aliasBinding)) { + return visibility; + } + } else if (hostMember instanceof ICPPASTUsingDeclaration) { + IBinding usingBinding = ((ICPPASTUsingDeclaration) hostMember).getName().resolveBinding(); + if (member.equals(usingBinding)) { + return visibility; + } + } else if (hostMember instanceof ICPPASTNamespaceDefinition) { // Not valid but possible due to the parser + IBinding namespaceBinding = ((ICPPASTNamespaceDefinition) hostMember).getName().resolveBinding(); + if (member.equals(namespaceBinding)) { + return visibility; + } + } + } + ICPPMethod[] implicitMethods = getImplicitMethods(classType, null); + for (ICPPMethod implicitMethod : implicitMethods) { + if (member.equals(implicitMethod)) { + return ICPPClassType.v_public; + } + } + throw new IllegalArgumentException(member.getName() + " is not a member of " + classType.getName()); //$NON-NLS-1$ + } + private static Map> collectPureVirtualMethods(ICPPClassType classType, Map>> cache, IASTNode point) { Map> result = cache.get(classType); 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 af6cd8debcb..d9b1253d5b4 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 @@ -22,13 +22,6 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUti import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getNestedType; import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getUltimateTypeUptoPointers; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - import org.eclipse.cdt.core.dom.ast.ASTGenericVisitor; import org.eclipse.cdt.core.dom.ast.ASTNodeProperty; import org.eclipse.cdt.core.dom.ast.ASTVisitor; @@ -214,6 +207,13 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType; import org.eclipse.cdt.internal.core.index.IIndexScope; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + /** * Collection of methods to extract information from a C++ translation unit. */ @@ -2521,7 +2521,11 @@ public class CPPVisitor extends ASTQueries { } if (--i < 0) break; - return bindingToOwner(qn[i].resolveBinding()); + IBinding binding = qn[i].resolveBinding(); + if (binding instanceof IIndexBinding && binding instanceof ICPPClassType) { + binding = ((CPPASTTranslationUnit) name.getTranslationUnit()).mapToAST((ICPPClassType) binding, name); + } + return bindingToOwner(binding); } name= (IASTName) node; node= node.getParent(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPClassType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPClassType.java index ed9cb9031c8..78cfc1a576e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPClassType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPClassType.java @@ -17,7 +17,6 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUti import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getNestedType; import java.util.Arrays; - import org.eclipse.cdt.core.dom.IName; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IField; @@ -215,4 +214,9 @@ class CompositeCPPClassType extends CompositeCPPBinding implements ICPPClassType public boolean isFinal() { return ((ICPPClassType) rbinding).isFinal(); } + + @Override + public int getVisibility(IBinding member) { + return ((ICPPClassType) rbinding).getVisibility(member); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPTemplateTemplateParameter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPTemplateTemplateParameter.java index 6bc1614d334..fd26ba34c81 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPTemplateTemplateParameter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPTemplateTemplateParameter.java @@ -179,4 +179,9 @@ public class CompositeCPPTemplateTemplateParameter extends CompositeCPPBinding public boolean isFinal() { return false; } + + @Override + public int getVisibility(IBinding member) { + throw new IllegalArgumentException(member.getName() + " is not a member of " + getName()); //$NON-NLS-1$ + } } 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 38ec45e6351..50b54057034 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 @@ -16,20 +16,6 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom; -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.BitSet; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Pattern; - import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ILinkage; import org.eclipse.cdt.core.dom.IPDOMNode; @@ -97,6 +83,20 @@ import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.PlatformObject; import org.eclipse.core.runtime.Status; +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.BitSet; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Pattern; + /** * Database for storing semantic information for one project. */ @@ -237,6 +237,7 @@ public class PDOM extends PlatformObject implements IPDOM { * 143.0 - Store implied object type in EvalFunctionSet, bug 402409. * 144.0 - Add support for storing function sets with zero functions in EvalFunctionSet, bug 402498. * 145.0 - Changed marshalling of CPPBasicType to store the associated numerical value, bug 407808. + * 146.0 - Added visibility support on class type level, bug 402878. */ private static final int MIN_SUPPORTED_VERSION= version(145, 0); private static final int MAX_SUPPORTED_VERSION= version(145, Short.MAX_VALUE); 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 0ea282443f2..49eff3995a8 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 @@ -621,6 +621,11 @@ public class PDOMASTAdapter { public boolean isFinal() { return false; } + + @Override + public int getVisibility(IBinding member) { + return ((ICPPClassType) fDelegate).getVisibility(member); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/IPDOMCPPClassType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/IPDOMCPPClassType.java index e13a004544d..fc9669c1629 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/IPDOMCPPClassType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/IPDOMCPPClassType.java @@ -16,6 +16,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.index.IIndexName; import org.eclipse.cdt.internal.core.index.IIndexType; import org.eclipse.cdt.internal.core.pdom.dom.IPDOMBinding; +import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; import org.eclipse.core.runtime.CoreException; /** @@ -32,4 +33,11 @@ public interface IPDOMCPPClassType extends ICPPClassType, IPDOMBinding, IIndexTy * Returns the scope name, for use in {@link IScope#getScopeName()} */ IIndexName getScopeName(); + + /** + * Sets the visibility specifier of a given member. + * @param member The binding specifying the member. + * @param visibility The visibility of the member. + */ + void addMember(PDOMNode member, int visibility) throws CoreException; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassSpecialization.java index 70207f3a2ff..6ac641b80ba 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassSpecialization.java @@ -14,12 +14,6 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.dom.cpp; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.IPDOMVisitor; import org.eclipse.cdt.core.dom.ast.IASTNode; @@ -43,7 +37,6 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPClassSpecializationScope; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; -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; @@ -51,20 +44,26 @@ import org.eclipse.cdt.internal.core.pdom.dom.PDOMName; import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; import org.eclipse.core.runtime.CoreException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + /** * @author Bryan Wilkinson */ class PDOMCPPClassSpecialization extends PDOMCPPSpecialization implements ICPPClassSpecialization, IPDOMMemberOwner, IPDOMCPPClassType { private static final int FIRST_BASE = PDOMCPPSpecialization.RECORD_SIZE + 0; - private static final int MEMBER_LIST = PDOMCPPSpecialization.RECORD_SIZE + 4; - private static final int FINAL = PDOMCPPSpecialization.RECORD_SIZE + 8; // byte + private static final int MEMBERLIST = FIRST_BASE + 4; + private static final int FINAL = MEMBERLIST + PDOMCPPMemberBlock.RECORD_SIZE; // byte /** * The size in bytes of a PDOMCPPClassSpecialization record in the database. */ @SuppressWarnings("hiding") - protected static final int RECORD_SIZE = PDOMCPPSpecialization.RECORD_SIZE + 9; + protected static final int RECORD_SIZE = FINAL + 1; private volatile ICPPClassScope fScope; private ObjectMap specializationMap; // Obtained from the synchronized PDOM cache @@ -442,14 +441,13 @@ class PDOMCPPClassSpecialization extends PDOMCPPSpecialization implements @Override public void addChild(PDOMNode member) throws CoreException { - PDOMNodeLinkedList list = new PDOMNodeLinkedList(getLinkage(), record + MEMBER_LIST); - list.addMember(member); + throw new UnsupportedOperationException("addMember method should be called instead."); //$NON-NLS-1$ } @Override public void acceptUncached(IPDOMVisitor visitor) throws CoreException { - PDOMNodeLinkedList list = new PDOMNodeLinkedList(getLinkage(), record + MEMBER_LIST); - list.accept(visitor); + PDOMCPPMemberBlock members = new PDOMCPPMemberBlock(getLinkage(), record + MEMBERLIST); + members.accept(visitor); } @Override @@ -475,4 +473,32 @@ class PDOMCPPClassSpecialization extends PDOMCPPSpecialization implements private void setFinal(ICPPClassType ct) throws CoreException { getDB().putByte(record + FINAL, (byte) (ct.isFinal() ? 1 : 0)); } + + @Override + public void addMember(PDOMNode member, int visibility) { + try { + PDOMCPPMemberBlock members = new PDOMCPPMemberBlock(getLinkage(), record + MEMBERLIST); + members.addMember(member, visibility); + } catch (CoreException e) { + CCorePlugin.log(e); + } + } + + @Override + public int getVisibility(IBinding member) { + try { + PDOMCPPMemberBlock members = new PDOMCPPMemberBlock(getLinkage(), record + MEMBERLIST); + int visibility = members.getVisibility(member); + if (visibility < 0) { + if (member instanceof ICPPSpecialization) { + return getSpecializedBinding().getVisibility(((ICPPSpecialization) member).getSpecializedBinding()); + } + throw new IllegalArgumentException(member.getName() + " is not a member of " + getName()); //$NON-NLS-1$ + } + return visibility; + } catch (CoreException e) { + CCorePlugin.log(e); + return v_private; // Fallback visibility + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassType.java index e9779d0127f..e03c0502260 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassType.java @@ -35,7 +35,6 @@ 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.pdom.PDOM; 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.PDOMLinkage; import org.eclipse.cdt.internal.core.pdom.dom.PDOMName; @@ -50,14 +49,14 @@ import java.util.List; * @author Doug Schaefer */ class PDOMCPPClassType extends PDOMCPPBinding implements IPDOMCPPClassType, IPDOMMemberOwner { - private static final int FIRSTBASE = PDOMCPPBinding.RECORD_SIZE + 0; - private static final int MEMBERLIST = PDOMCPPBinding.RECORD_SIZE + 4; - private static final int FIRSTFRIEND = PDOMCPPBinding.RECORD_SIZE + 8; - private static final int KEY = PDOMCPPBinding.RECORD_SIZE + 12; // byte - private static final int ANONYMOUS= PDOMCPPBinding.RECORD_SIZE + 13; // byte - private static final int FINAL = PDOMCPPBinding.RECORD_SIZE + 14; // byte + private static final int FIRSTBASE = PDOMCPPBinding.RECORD_SIZE; + private static final int MEMBERLIST = FIRSTBASE + 4; + private static final int FIRSTFRIEND = MEMBERLIST + PDOMCPPMemberBlock.RECORD_SIZE; + private static final int KEY = FIRSTFRIEND + 4; // byte + private static final int ANONYMOUS = KEY + 1; // byte + private static final int FINAL = ANONYMOUS + 1; // byte @SuppressWarnings("hiding") - protected static final int RECORD_SIZE = PDOMCPPBinding.RECORD_SIZE + 15; + protected static final int RECORD_SIZE = FINAL + 1; private PDOMCPPClassScope fScope; // No need for volatile, all fields of PDOMCPPClassScope are final. @@ -114,9 +113,7 @@ class PDOMCPPClassType extends PDOMCPPBinding implements IPDOMCPPClassType, IPDO @Override public final void addChild(PDOMNode member) throws CoreException { - PDOMNodeLinkedList list = new PDOMNodeLinkedList(getLinkage(), record + MEMBERLIST); - list.addMember(member); - PDOMCPPClassScope.updateCache(this, member); + throw new UnsupportedOperationException("addMember method should be called instead."); //$NON-NLS-1$ } @Override @@ -130,7 +127,7 @@ class PDOMCPPClassType extends PDOMCPPBinding implements IPDOMCPPClassType, IPDO @Override public void acceptUncached(IPDOMVisitor visitor) throws CoreException { super.accept(visitor); - PDOMNodeLinkedList list = new PDOMNodeLinkedList(getLinkage(), record + MEMBERLIST); + PDOMCPPMemberBlock list = new PDOMCPPMemberBlock(getLinkage(), record + MEMBERLIST); list.accept(visitor); } @@ -143,7 +140,7 @@ class PDOMCPPClassType extends PDOMCPPBinding implements IPDOMCPPClassType, IPDO long rec = base != null ? base.getRecord() : 0; getDB().putRecPtr(record + FIRSTBASE, rec); } - + public void addBases(PDOMName classDefName, ICPPBase[] bases) throws CoreException { getPDOM().removeCachedResult(record + PDOMCPPLinkage.CACHE_BASES); final PDOMLinkage linkage = getLinkage(); @@ -192,7 +189,7 @@ class PDOMCPPClassType extends PDOMCPPBinding implements IPDOMCPPClassType, IPDO } } } - + public void addFriend(PDOMCPPFriend friend) throws CoreException { PDOMCPPFriend firstFriend = getFirstFriend(); friend.setNextFriend(firstFriend); @@ -255,7 +252,7 @@ class PDOMCPPClassType extends PDOMCPPBinding implements IPDOMCPPClassType, IPDO return getDB().getByte(record + ANONYMOUS) != 0; } catch (CoreException e) { CCorePlugin.log(e); - return false; + return false; } } @@ -263,7 +260,7 @@ class PDOMCPPClassType extends PDOMCPPBinding implements IPDOMCPPClassType, IPDO public boolean isFinal() { try { return getDB().getByte(record + FINAL) != 0; - } catch (CoreException e){ + } catch (CoreException e) { CCorePlugin.log(e); return false; } @@ -309,7 +306,7 @@ class PDOMCPPClassType extends PDOMCPPBinding implements IPDOMCPPClassType, IPDO ICPPBase[] bases= (ICPPBase[]) getPDOM().getCachedResult(key); if (bases != null) return bases; - + try { List list = new ArrayList(); for (PDOMCPPBase base = getFirstBase(); base != null; base = base.getNextBase()) @@ -388,7 +385,7 @@ class PDOMCPPClassType extends PDOMCPPBinding implements IPDOMCPPClassType, IPDO } @Override - public ICPPMethod[] getMethods() { + public ICPPMethod[] getMethods() { return ClassTypeHelper.getMethods(this, null); } @@ -396,23 +393,48 @@ class PDOMCPPClassType extends PDOMCPPBinding implements IPDOMCPPClassType, IPDO public ICPPMethod[] getAllDeclaredMethods() { return ClassTypeHelper.getAllDeclaredMethods(this, null); } - + @Override public IField[] getFields() { return ClassTypeHelper.getFields(this, null); } - + @Override public IField findField(String name) { return ClassTypeHelper.findField(this, name); } @Override - public Object clone() { + public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { } return null; } + + @Override + public void addMember(PDOMNode member, int visibility) { + try { + PDOMCPPMemberBlock members = new PDOMCPPMemberBlock(getLinkage(), record + MEMBERLIST); + members.addMember(member, visibility); + PDOMCPPClassScope.updateCache(this, member); + } catch (CoreException e) { + CCorePlugin.log(e); + } + } + + @Override + public int getVisibility(IBinding member) { + try { + PDOMCPPMemberBlock members = new PDOMCPPMemberBlock(getLinkage(), record + MEMBERLIST); + int visibility = members.getVisibility(member); + if (visibility < 0) + throw new IllegalArgumentException(member.getName() + " is not a member of " + getName()); //$NON-NLS-1$ + return visibility; + } catch (CoreException e) { + CCorePlugin.log(e); + return v_private; // Fallback visibility + } + } } 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 0f1c7b116a1..f5dd6fa3d09 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 @@ -14,10 +14,6 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.dom.cpp; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; - import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; @@ -87,6 +83,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClosureType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPDeferredClassInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunctionType; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPImplicitMethod; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPParameterPackType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerToMemberType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType; @@ -133,6 +130,10 @@ import org.eclipse.cdt.internal.core.pdom.dom.PDOMName; import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; import org.eclipse.core.runtime.CoreException; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + /** * Container for c++-entities. */ @@ -487,9 +488,9 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { if (pdomBinding != null) { pdomBinding.setLocalToFileRec(fileLocalRec); - parent.addChild(pdomBinding); + addChild(parent, pdomBinding, binding); if (parent2 != null) { - parent2.addChild(pdomBinding); + addChild(parent2, pdomBinding, binding); } if (parent != this && parent2 != this) { insertIntoNestedBindingsIndex(pdomBinding); @@ -499,6 +500,45 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { return pdomBinding; } + /** + * Returns visibility of the member binding in its containing class, or -1 if the binding is + * not a class member. + */ + private static int getVisibility(IBinding binding) { + while (binding instanceof ICPPSpecialization) { + binding = ((ICPPSpecialization) binding).getSpecializedBinding(); + } + if (binding instanceof CPPImplicitMethod) + return ICPPClassType.v_public; + + int visibility = -1; + + IBinding bindingOwner = binding.getOwner(); + + if (bindingOwner instanceof ICPPClassType) { + if (bindingOwner instanceof CPPClosureType) + return ICPPClassType.v_public; + visibility = ((ICPPClassType) bindingOwner).getVisibility(binding); + } + return visibility; + } + + private static void addChild(PDOMNode parent, PDOMBinding binding, IBinding originalBinding) + throws CoreException { + if (parent instanceof IPDOMCPPClassType) { + if (originalBinding instanceof IEnumerator) + originalBinding = originalBinding.getOwner(); + int visibility = getVisibility(originalBinding); + if (visibility >= 0) { + ((IPDOMCPPClassType) parent).addMember(binding, visibility); + return; + } + originalBinding.getOwner(); + visibility = getVisibility(originalBinding); + } + parent.addChild(binding); + } + @Override public void addChild(PDOMNode node) throws CoreException { super.addChild(node); @@ -972,7 +1012,7 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { file.setLastUsingDirective(ud.getRecord()); } } else if (parentNode instanceof ICPPASTElaboratedTypeSpecifier) { - ICPPASTElaboratedTypeSpecifier elaboratedSpecifier = (ICPPASTElaboratedTypeSpecifier)parentNode; + ICPPASTElaboratedTypeSpecifier elaboratedSpecifier = (ICPPASTElaboratedTypeSpecifier) parentNode; if (elaboratedSpecifier.isFriend()) { pdomName.setIsFriendSpecifier(); PDOMName enclClassName = (PDOMName) pdomName.getEnclosingDefinition(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPMemberBlock.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPMemberBlock.java new file mode 100644 index 00000000000..b6684cfb270 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPMemberBlock.java @@ -0,0 +1,197 @@ +/******************************************************************************* + * Copyright (c) 2013 Institute for Software, HSR Hochschule fuer Technik + * Rapperswil, University of applied sciences. + * 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: + * Thomas Corbat (IFS) - Initial API and implementation + * Sergey Prigogin (Google) + *******************************************************************************/ + +package org.eclipse.cdt.internal.core.pdom.dom.cpp; + +import org.eclipse.cdt.core.dom.IPDOMVisitor; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.internal.core.pdom.db.Database; +import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage; +import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; +import org.eclipse.core.runtime.CoreException; + +/** + * PDOMCPPMemberBlock stores the members of a composite type and maps every member to + * the corresponding visibility. + */ +public class PDOMCPPMemberBlock { + /* + * The MAX_MEMBER_COUNT was chosen empirically by comparing PDOM file sizes of a real-life + * project. Six members per block resulted in the most compact PDOM. + */ + private static final int MAX_MEMBER_COUNT = 6; + private static final int VISIBILITY_BITS = 2; + private static final int VISIBILITY_MASK = (1 << VISIBILITY_BITS) - 1; + private static final int VISIBILITY_VALUES_PER_BYTE = 8 / VISIBILITY_BITS; + + private static final int MEMBER_POINTERS = 0; + private static final int MEMBER_VISIBILITIES = + MEMBER_POINTERS + Database.PTR_SIZE * MAX_MEMBER_COUNT; + private static final int NEXT_MEMBER_BLOCK = + MEMBER_VISIBILITIES + (MAX_MEMBER_COUNT + VISIBILITY_VALUES_PER_BYTE - 1) / VISIBILITY_VALUES_PER_BYTE; + + protected static final int RECORD_SIZE = NEXT_MEMBER_BLOCK + Database.PTR_SIZE; + + static { + assert (MAX_MEMBER_COUNT > 0); + } + + private final PDOMLinkage linkage; + private final long record; + private int nextMemberPosition = -1; + + public PDOMCPPMemberBlock(PDOMLinkage linkage, long record) throws CoreException { + this.linkage = linkage; + this.record = record; + } + + public PDOMCPPMemberBlock(PDOMLinkage linkage) throws CoreException { + Database db = linkage.getDB(); + this.linkage = linkage; + this.record = db.malloc(RECORD_SIZE); + db.clearBytes(record, RECORD_SIZE); + } + + private int getNextPosition() throws CoreException { + if (nextMemberPosition < 0) { + nextMemberPosition = 0; + while (nextMemberPosition < MAX_MEMBER_COUNT && getMemberRecord(nextMemberPosition) != 0) { + nextMemberPosition++; + } + } + return nextMemberPosition; + } + + private Database getDB() { + return linkage.getDB(); + } + + public long getRecord() { + return record; + } + + public void setNextBlock(PDOMCPPMemberBlock nextBlock) throws CoreException { + long rec = nextBlock != null ? nextBlock.getRecord() : 0; + getDB().putRecPtr(record + NEXT_MEMBER_BLOCK, rec); + } + + public PDOMCPPMemberBlock getNextBlock() throws CoreException { + long rec = getDB().getRecPtr(record + NEXT_MEMBER_BLOCK); + return rec != 0 ? new PDOMCPPMemberBlock(linkage, rec) : null; + } + + public void addMember(PDOMNode member, int visibility) throws CoreException { + if (getNextPosition() == MAX_MEMBER_COUNT) { + PDOMCPPMemberBlock nextBlock = getNextBlock(); + if (nextBlock == null) { + nextBlock = new PDOMCPPMemberBlock(linkage); + setNextBlock(nextBlock); + } + nextBlock.addMember(member, visibility); + } else { + long memberLocationOffset = getMemberOffset(getNextPosition()); + long rec = member.getRecord(); + getDB().putRecPtr(memberLocationOffset, rec); + setVisibility(getNextPosition(), visibility); + nextMemberPosition++; + } + } + + public void accept(IPDOMVisitor visitor) throws CoreException { + PDOMCPPMemberBlock current = this; + do { + current.visitBlock(visitor); + } while ((current = current.getNextBlock()) != null); + } + + private void visitBlock(IPDOMVisitor visitor) throws CoreException { + if (record == 0) { + throw new NullPointerException(); + } + + int item = 0; + long memberRecord; + while (item < MAX_MEMBER_COUNT && (memberRecord = getMemberRecord(item++)) != 0) { + PDOMNode node = linkage.getNode(memberRecord); + if (visitor.visit(node) && node != null) { + node.accept(visitor); + } + visitor.leave(node); + } + } + + public void delete() throws CoreException { + getDB().free(record); + } + + private long getMemberRecord(int memberIndex) throws CoreException { + return getDB().getRecPtr(getMemberOffset(memberIndex)); + } + + private long getMemberOffset(int memberIndex) { + return record + MEMBER_POINTERS + Database.PTR_SIZE * memberIndex; + } + + private PDOMNode getMember(int memberIndex) throws CoreException { + if (memberIndex < getNextPosition() && memberIndex < MAX_MEMBER_COUNT) { + long memberRecord = getMemberRecord(memberIndex); + if (memberRecord != 0) { + PDOMNode node = linkage.getNode(memberRecord); + return node; + } + } + return null; + } + + private void setVisibility(int memberIndex, int newVisibility) throws CoreException { + newVisibility &= VISIBILITY_MASK; + + int visibilityBitOffset = memberIndex % VISIBILITY_VALUES_PER_BYTE; + long visibilityOffset = record + MEMBER_VISIBILITIES + memberIndex / VISIBILITY_VALUES_PER_BYTE; + int visibility = getDB().getByte(visibilityOffset); + // Resetting the previous visibility bits of the target member + visibility &= ~(VISIBILITY_MASK << visibilityBitOffset * VISIBILITY_BITS); + // Setting the new visibility bits of the target member + visibility |= newVisibility << visibilityBitOffset * VISIBILITY_BITS; + + getDB().putByte(visibilityOffset, (byte) visibility); + } + + /** + * Returns visibility of the member, or -1 if the given binding is not a member. + */ + public int getVisibility(IBinding member) throws CoreException { + for (PDOMCPPMemberBlock block = this; block != null; block = block.getNextBlock()) { + for (int memberIndex = 0; memberIndex < block.getNextPosition(); memberIndex++) { + PDOMNode candidate = block.getMember(memberIndex); + if (candidate == null) + return -1; + if (candidate.equals(member)) + return block.getVisibility(memberIndex); + } + } + return -1; + } + + private int getVisibility(int memberIndex) throws CoreException { + int visibilityBitOffset = memberIndex % VISIBILITY_VALUES_PER_BYTE; + long visibilityOffset = record + MEMBER_VISIBILITIES + memberIndex / VISIBILITY_VALUES_PER_BYTE; + int visibility = getDB().getByte(visibilityOffset); + + visibility >>>= visibilityBitOffset * VISIBILITY_BITS; + // Filtering the visibility bits of the target member + visibility &= VISIBILITY_MASK; + + return visibility; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPTemplateTemplateParameter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPTemplateTemplateParameter.java index 8f4ab194471..978fa27c1c5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPTemplateTemplateParameter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPTemplateTemplateParameter.java @@ -365,4 +365,9 @@ public class PDOMCPPTemplateTemplateParameter extends PDOMCPPBinding public ICPPDeferredClassInstance asDeferredInstance() { return null; } + + @Override + public int getVisibility(IBinding member) { + throw new IllegalArgumentException(member.getName() + " is not a member of " + getName()); //$NON-NLS-1$ + } }