From eff6754c1270daf644e9c417270c34a689deae89 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Wed, 12 Dec 2007 12:15:07 +0000 Subject: [PATCH] Store information about potential polymorphic method calls in index, bug 156691. --- ...ingNamesTest.java => IndexNamesTests.java} | 69 +++++++++++++++++-- .../cdt/internal/index/tests/IndexTests.java | 2 +- .../eclipse/cdt/core/index/IIndexName.java | 9 ++- .../eclipse/cdt/internal/core/pdom/PDOM.java | 3 +- .../internal/core/pdom/dom/PDOMBinding.java | 10 +++ .../cdt/internal/core/pdom/dom/PDOMFile.java | 6 +- .../cdt/internal/core/pdom/dom/PDOMName.java | 53 +++++++------- .../core/pdom/dom/cpp/PDOMCPPConstructor.java | 10 ++- .../core/pdom/dom/cpp/PDOMCPPMethod.java | 37 +++++++++- 9 files changed, 161 insertions(+), 38 deletions(-) rename core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/{EnclosingNamesTest.java => IndexNamesTests.java} (76%) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EnclosingNamesTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexNamesTests.java similarity index 76% rename from core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EnclosingNamesTest.java rename to core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexNamesTests.java index e3fd17c8cf9..4468eb80d1e 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EnclosingNamesTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexNamesTests.java @@ -17,11 +17,14 @@ import java.util.regex.Pattern; import junit.framework.TestSuite; import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.dom.ILinkage; import org.eclipse.cdt.core.dom.IPDOMManager; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndexBinding; +import org.eclipse.cdt.core.index.IIndexFile; import org.eclipse.cdt.core.index.IIndexName; import org.eclipse.cdt.core.index.IndexFilter; +import org.eclipse.cdt.core.index.IndexLocationFactory; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.testplugin.CProjectHelper; import org.eclipse.cdt.core.testplugin.CTestPlugin; @@ -33,16 +36,16 @@ import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.Path; -public class EnclosingNamesTest extends BaseTestCase { +public class IndexNamesTests extends BaseTestCase { private ICProject fCProject; protected IIndex fIndex; - public EnclosingNamesTest(String name) { + public IndexNamesTests(String name) { super(name); } public static TestSuite suite() { - return suite(EnclosingNamesTest.class); + return suite(IndexNamesTests.class); } protected void setUp() throws CoreException { @@ -153,8 +156,6 @@ public class EnclosingNamesTest extends BaseTestCase { // func(); // var=1; // }; - - public void testNestingWithMethod() throws Exception { waitForIndexer(); String content= getContentsForTest(1)[0].toString(); @@ -220,4 +221,62 @@ public class EnclosingNamesTest extends BaseTestCase { } } + // class X { + // public: + // virtual void vm() { + // } + // }; + // + // class Y : public X { + // public: + // virtual void vm() { + // } + // void test(); + // }; + // void Y::test() { + // X* x= this; + // X& xr= *this; + // X xc= *this; + // + // vm(); // polymorphic + // X::vm(); // call to X::vm() + // x->vm(); // polymorphic + // x->X::vm(); // call to X::vm() + // xr.vm(); // polymorphic + // xr.X::vm(); // call to X::vm() + // xc.vm(); // call to X::vm() + // xc.X::vm(); // call to X::vm() + // } + public void testCouldBePolymorphicMethodCall_Bug156691() throws Exception { + waitForIndexer(); + String content= getContentsForTest(1)[0].toString(); + IFile file= createFile(getProject().getProject(), "test.cpp", content); + waitUntilFileIsIndexed(file, 4000); + + boolean[] couldbepolymorphic= {true, false, true, false, true, false, false, false}; + String[] container= {"Y", "X", "X", "X", "X", "X", "X", "X" }; + + fIndex.acquireReadLock(); + try { + IIndexFile ifile= fIndex.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file)); + IIndexName[] names= ifile.findNames(0, content.length()); + int j= 0; + for (int i = 0; i < names.length; i++) { + IIndexName indexName = names[i]; + if (indexName.isReference() && indexName.toString().equals("vm")) { + assertEquals(couldbepolymorphic[j], indexName.couldBePolymorphicMethodCall()); + assertEquals(container[j], fIndex.findBinding(indexName).getQualifiedName()[0]); + j++; + } + else { + assertEquals(false, indexName.couldBePolymorphicMethodCall()); + } + } + assertEquals(couldbepolymorphic.length, j); + } + finally { + fIndex.releaseReadLock(); + } + } + } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexTests.java index 412f7d3d1bb..6b3d23b37fd 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexTests.java @@ -27,7 +27,7 @@ public class IndexTests extends TestSuite { suite.addTest(IndexIncludeTest.suite()); suite.addTest(IndexUpdateTests.suite()); suite.addTest(IndexBugsTests.suite()); - suite.addTest(EnclosingNamesTest.suite()); + suite.addTest(IndexNamesTests.suite()); suite.addTest(TeamSharedIndexTest.suite()); suite.addTest(IndexProviderManagerTest.suite()); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexName.java index ab0efd73559..804a6efb415 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexName.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexName.java @@ -67,5 +67,12 @@ public interface IIndexName extends IName { * Returns whether a declaration is a base-class specifier. */ public boolean isBaseSpecifier() throws CoreException; - + + /** + * Returns whether this name potentially denotes a polymorphic method call. This is the case + * when the name is not qualified and denotes a method call and the method is accessed via a + * pointer or a reference to an object.

+ * No checks are performed whether the method is actually virtual or not. + */ + public boolean couldBePolymorphicMethodCall() throws CoreException; } 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 eae61ce4a6a..f9366ba3392 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 @@ -90,7 +90,7 @@ public class PDOM extends PlatformObject implements IPDOM { */ public static final String FRAGMENT_PROPERTY_VALUE_FORMAT_ID= "org.eclipse.cdt.internal.core.pdom.PDOM"; //$NON-NLS-1$ - public static final int CURRENT_VERSION = 52; + public static final int CURRENT_VERSION = 53; public static final int MIN_SUPPORTED_VERSION= CURRENT_VERSION; /** @@ -152,6 +152,7 @@ public class PDOM extends PlatformObject implements IPDOM { * 50 - support for complex, imaginary and long long (bug 209049). * 51 - modeling extern "C" (bug 191989) * 52 - files per linkage (bug 191989) + * 53 - polymorphic method calls (bug 156691) */ public static final int LINKAGES = Database.DATA_AREA; 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 aeb09e2c267..f812088d954 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 @@ -20,6 +20,7 @@ import java.util.List; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.IName; import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance; @@ -363,4 +364,13 @@ public abstract class PDOMBinding extends PDOMNamedNode implements IIndexFragmen final public void delete(PDOMLinkage linkage) throws CoreException { assert false; } + + /** + * Bindings may set additional flags for their occurrences + * Return a combination of flags defined in {@link PDOMName}. + * @since 5.0 + */ + public int getAdditionalNameFlags(int standardFlags, IASTName name) { + return 0; + } } \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java index e7346f46285..49f060a29bb 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java @@ -371,10 +371,8 @@ public class PDOMFile implements IIndexFragmentFile { for (PDOMName name= getFirstName(); name != null; name= name.getNextInFile()) { int nameOffset= name.getNodeOffset(); if (nameOffset >= offset) { - if (nameOffset == offset) { - if (name.getNodeLength() == length) { - result.add(name); - } + if (nameOffset + name.getNodeLength() <= offset+length) { + result.add(name); } else if (name.isReference()) { // names are ordered, but callers are inserted before diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMName.java index fa14a5eaca5..bb0ed01164f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMName.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMName.java @@ -6,8 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * QNX - Initial API and implementation - * Markus Schorn (Wind River Systems) + * QNX - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.dom; @@ -30,7 +30,7 @@ import org.eclipse.core.runtime.CoreException; * @author Doug Schaefer * */ -public class PDOMName implements IIndexFragmentName, IASTFileLocation { +public final class PDOMName implements IIndexFragmentName, IASTFileLocation { private final PDOM pdom; private final int record; @@ -42,16 +42,17 @@ public class PDOMName implements IIndexFragmentName, IASTFileLocation { private static final int BINDING_PREV_OFFSET = 16; private static final int BINDING_NEXT_OFFSET = 20; private static final int NODE_OFFSET_OFFSET = 24; - private static final int NODE_LENGTH_OFFSET = 28; // short - private static final int FLAGS = 30; // byte + private static final int NODE_LENGTH_OFFSET = 28; + private static final int FLAGS = 32; - private static final int RECORD_SIZE = 31; + private static final int RECORD_SIZE = 36; // actual memory usage is the same from 28 - 44 - private static final int IS_DECLARATION = 1; - private static final int IS_DEFINITION = 2; - private static final int IS_REFERENCE = 3; - private static final int DECL_DEF_REF_MASK= 3; - private static final int IS_INHERITANCE_SPEC = 4; + public static final int IS_DECLARATION = 1; + public static final int IS_DEFINITION = 2; + public static final int IS_REFERENCE = 3; + public static final int DECL_DEF_REF_MASK= 3; + public static final int IS_INHERITANCE_SPEC = 4; + public static final int COULD_BE_POLYMORPHIC_METHOD_CALL= 8; @@ -61,18 +62,20 @@ public class PDOMName implements IIndexFragmentName, IASTFileLocation { record = db.malloc(RECORD_SIZE); // What kind of name are we - byte flags = 0; + int flags = 0; if (name.isDefinition()) flags = IS_DEFINITION; else if (name.isDeclaration()) flags = IS_DECLARATION; else flags = IS_REFERENCE; - db.putByte(record + FLAGS, flags); + + flags |= binding.getAdditionalNameFlags(flags, name); + db.putInt(record + FLAGS, flags); // Hook us up to the binding if (binding != null) { - switch (flags) { + switch (flags & DECL_DEF_REF_MASK) { case IS_DEFINITION: binding.addDefinition(this); break; @@ -95,7 +98,7 @@ public class PDOMName implements IIndexFragmentName, IASTFileLocation { // Record our location in the file IASTFileLocation fileloc = name.getFileLocation(); db.putInt(record + NODE_OFFSET_OFFSET, fileloc.getNodeOffset()); - db.putShort(record + NODE_LENGTH_OFFSET, (short) fileloc.getNodeLength()); + db.putInt(record + NODE_LENGTH_OFFSET, fileloc.getNodeLength()); } public PDOMName(PDOM pdom, int nameRecord) { @@ -197,26 +200,30 @@ public class PDOMName implements IIndexFragmentName, IASTFileLocation { } } - private byte getFlags(int mask) throws CoreException { - return (byte) (pdom.getDB().getByte(record + FLAGS) & mask); + private int getFlags(int mask) throws CoreException { + return pdom.getDB().getInt(record + FLAGS) & mask; } public void setIsBaseSpecifier(boolean val) throws CoreException { - byte flags= getFlags(0xff); + int flags= pdom.getDB().getInt(record + FLAGS); if (val) flags |= IS_INHERITANCE_SPEC; else flags &= ~IS_INHERITANCE_SPEC; - pdom.getDB().putByte(record + FLAGS, flags); + pdom.getDB().putInt(record + FLAGS, flags); } public boolean isBaseSpecifier() throws CoreException { return getFlags(IS_INHERITANCE_SPEC) == IS_INHERITANCE_SPEC; } + public boolean couldBePolymorphicMethodCall() throws CoreException { + return getFlags(COULD_BE_POLYMORPHIC_METHOD_CALL) == COULD_BE_POLYMORPHIC_METHOD_CALL; + } + public boolean isDeclaration() { try { - byte flags = getFlags(DECL_DEF_REF_MASK); + int flags = getFlags(DECL_DEF_REF_MASK); return flags == IS_DECLARATION || flags == IS_DEFINITION; } catch (CoreException e) { CCorePlugin.log(e); @@ -226,7 +233,7 @@ public class PDOMName implements IIndexFragmentName, IASTFileLocation { public boolean isReference() { try { - byte flags = getFlags(DECL_DEF_REF_MASK); + int flags = getFlags(DECL_DEF_REF_MASK); return flags == IS_REFERENCE; } catch (CoreException e) { CCorePlugin.log(e); @@ -236,7 +243,7 @@ public class PDOMName implements IIndexFragmentName, IASTFileLocation { public boolean isDefinition() { try { - byte flags = getFlags(DECL_DEF_REF_MASK); + int flags = getFlags(DECL_DEF_REF_MASK); return flags == IS_DEFINITION; } catch (CoreException e) { CCorePlugin.log(e); @@ -281,7 +288,7 @@ public class PDOMName implements IIndexFragmentName, IASTFileLocation { public int getNodeLength() { try { - return pdom.getDB().getShort(record + NODE_LENGTH_OFFSET); + return pdom.getDB().getInt(record + NODE_LENGTH_OFFSET); } catch (CoreException e) { CCorePlugin.log(e); return 0; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPConstructor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPConstructor.java index 58d83a4ee79..79d80fbeace 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPConstructor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPConstructor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006 Wind River Systems, Inc. and others. + * Copyright (c) 2006, 2007 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 @@ -12,7 +12,9 @@ package org.eclipse.cdt.internal.core.pdom.dom.cpp; import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; import org.eclipse.cdt.internal.core.pdom.PDOM; import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; import org.eclipse.core.runtime.CoreException; @@ -32,6 +34,10 @@ class PDOMCPPConstructor extends PDOMCPPMethod implements ICPPConstructor { } public int getNodeType() { - return PDOMCPPLinkage.CPP_CONSTRUCTOR; + return IIndexCPPBindingConstants.CPP_CONSTRUCTOR; + } + + public int getAdditionalNameFlags(int standardFlags, IASTName name) { + return 0; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPMethod.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPMethod.java index 9fe02b3503a..5dcf6a6c634 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPMethod.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPMethod.java @@ -16,18 +16,25 @@ package org.eclipse.cdt.internal.core.pdom.dom.cpp; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression; +import org.eclipse.cdt.core.dom.ast.IASTIdExpression; 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.IScope; +import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPDelegate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType; import org.eclipse.cdt.internal.core.Util; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPMethod; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDelegateCreator; import org.eclipse.cdt.internal.core.pdom.PDOM; 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.PDOMName; import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; import org.eclipse.cdt.internal.core.pdom.dom.PDOMNotImplementedError; import org.eclipse.cdt.internal.core.pdom.dom.c.PDOMCAnnotation; @@ -159,5 +166,33 @@ class PDOMCPPMethod extends PDOMCPPFunction implements ICPPMethod, ICPPDelegateC public ICPPDelegate createDelegate(IASTName name) { return new CPPMethod.CPPMethodDelegate(name, this); } - + + public int getAdditionalNameFlags(int standardFlags, IASTName name) { + if ((standardFlags & PDOMName.IS_REFERENCE) == PDOMName.IS_REFERENCE) { + IASTNode parent= name.getParent(); + if (parent instanceof ICPPASTFieldReference) { + // the name is not qualified + ICPPASTFieldReference fr= (ICPPASTFieldReference) parent; + parent= parent.getParent(); + if (parent instanceof IASTFunctionCallExpression) { + // v->member() + if (fr.isPointerDereference()) { + return PDOMName.COULD_BE_POLYMORPHIC_METHOD_CALL; + } + // v.member() + IType type= fr.getFieldOwner().getExpressionType(); + if (type instanceof ICPPReferenceType) { + return PDOMName.COULD_BE_POLYMORPHIC_METHOD_CALL; + } + } + } + // calling a member from within a member + else if (parent instanceof IASTIdExpression) { + if (parent.getParent() instanceof IASTFunctionCallExpression) { + return PDOMName.COULD_BE_POLYMORPHIC_METHOD_CALL; + } + } + } + return 0; + } }