1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Implementation for ICPPClassType.getFriends() for PDOMCPPClassType, bug 250167.

This commit is contained in:
Markus Schorn 2008-10-24 14:23:08 +00:00
parent bbdc82b058
commit 65b3044dca
8 changed files with 242 additions and 10 deletions

View file

@ -28,6 +28,7 @@ import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
@ -898,4 +899,58 @@ public class IndexUpdateTests extends IndexTestBase {
checkValue("C::mem", null);
checkValue("e0", 0L);
}
//class A {};
//class B {friend class A;};
//class B {};
public void testFriendClass() throws Exception {
setupFile(2, true);
assertFriendRemoval("B", "A");
}
// class X {public: char* foo(int);};
// class Y {friend char* X::foo(int);};
// class Y {};
public void testFriendMethod() throws Exception {
setupFile(2, true);
assertFriendRemoval("Y", "X::foo");
}
// class X {friend void friend_set(X*, int);};
// void friend_set(X* p, int i) {}
// class X {};
public void testFriendFunction() throws Exception {
setupFile(2, true);
assertFriendRemoval("X", "friend_set");
}
private void assertFriendRemoval(String clientClassBinding, String supplierBinding) throws Exception {
fIndex.acquireReadLock();
try {
IBinding client = findBinding(clientClassBinding);
IBinding supplier = findBinding(supplierBinding);
assertNotNull("Unable to find binding with name \""+clientClassBinding+"\"", client);
assertTrue("Unable to find binding with name \""+clientClassBinding+"\"", client instanceof ICPPClassType);
assertNotNull("Unable to find binding with name \""+supplierBinding+"\"", supplier);
assertTrue(((ICPPClassType)client).getFriends().length == 1);
assertTrue(((ICPPClassType)client).getFriends()[0].equals(supplier));
} finally {
fIndex.releaseReadLock();
}
updateFile();
fIndex.acquireReadLock();
try {
IBinding client = findBinding(clientClassBinding);
assertNotNull("Unable to find binding with name \""+clientClassBinding+"\"", client);
assertTrue("Unable to find binding with name \""+clientClassBinding+"\"", client instanceof ICPPClassType);
assertTrue(((ICPPClassType)client).getFriends().length == 0);
} finally {
fIndex.releaseReadLock();
}
}
}

View file

@ -124,7 +124,7 @@ public class ClassTests extends PDOMTestBase {
}
/* Test friend relationships between classes */
public void _testFriend() throws Exception {
public void testFriend() throws Exception {
IBinding[] bindings = pdom.findBindings(Pattern.compile("ClassA"), true, IndexFilter.ALL_DECLARED, NPM);
assertEquals(1, bindings.length);
ICPPClassType classA = (ICPPClassType) bindings[0];

View file

@ -59,4 +59,5 @@ public interface IIndexCPPBindingConstants {
int CPP_UNKNOWN_CLASS_TYPE= IIndexBindingConstants.LAST_CONSTANT + 42;
int CPP_UNKNOWN_CLASS_INSTANCE= IIndexBindingConstants.LAST_CONSTANT + 43;
int CPP_TEMPLATE_NON_TYPE_PARAMETER= IIndexBindingConstants.LAST_CONSTANT + 44;
int CPP_FRIEND_DECLARATION = IIndexBindingConstants.LAST_CONSTANT + 45;
}

View file

@ -164,11 +164,12 @@ public class PDOM extends PlatformObject implements IPDOM {
* 72.1 - store flag for pure virtual methods.
* 73.0 - add values for variables and enumerations, bug 250788
* 74.0 - changes for proper template argument support, bug 242668
* 75.0 - support for friends, bug 250167
*/
private static int version(int major, int minor) {
return major << 16 + minor;
}
public static final int MAJOR_VERSION = 74;
public static final int MAJOR_VERSION = 75;
public static final int MINOR_VERSION = 0; // minor versions must be compatible
public static final int CURRENT_VERSION= version(MAJOR_VERSION, MINOR_VERSION);

View file

@ -52,9 +52,10 @@ public final class PDOMName implements IIndexFragmentName, IASTFileLocation {
public static final int IS_REFERENCE = IS_DECLARATION | IS_DEFINITION;
public static final int DECL_DEF_REF_MASK = IS_DECLARATION | IS_DEFINITION | IS_REFERENCE;
public static final int IS_INHERITANCE_SPEC = 0x04;
public static final int COULD_BE_POLYMORPHIC_METHOD_CALL = 0x08;
public static final int READ_ACCESS = 0x10;
public static final int WRITE_ACCESS = 0x20;
public static final int IS_FRIEND_SPEC = 0x08;
public static final int COULD_BE_POLYMORPHIC_METHOD_CALL = 0x10;
public static final int READ_ACCESS = 0x20;
public static final int WRITE_ACCESS = 0x40;
public PDOMName(PDOM pdom, IASTName name, PDOMFile file, PDOMBinding binding, PDOMName caller)
@ -209,6 +210,15 @@ public final class PDOMName implements IIndexFragmentName, IASTFileLocation {
return pdom.getDB().getByte(record + FLAGS) & mask;
}
public void setIsFriendSpecifier(boolean val) throws CoreException {
int flags= pdom.getDB().getByte(record + FLAGS) & 0xff;
if (val)
flags |= IS_FRIEND_SPEC;
else
flags &= ~IS_FRIEND_SPEC;
pdom.getDB().putByte(record + FLAGS, (byte) flags);
}
public void setIsBaseSpecifier(boolean val) throws CoreException {
int flags= pdom.getDB().getByte(record + FLAGS) & 0xff;
if (val)
@ -218,6 +228,10 @@ public final class PDOMName implements IIndexFragmentName, IASTFileLocation {
pdom.getDB().putByte(record + FLAGS, (byte) flags);
}
public boolean isFriendSpecifier() throws CoreException {
return getFlags(IS_FRIEND_SPEC) == IS_FRIEND_SPEC;
}
public boolean isBaseSpecifier() throws CoreException {
return getFlags(IS_INHERITANCE_SPEC) == IS_INHERITANCE_SPEC;
}

View file

@ -56,11 +56,13 @@ class PDOMCPPClassType extends PDOMCPPBinding implements IPDOMCPPClassType, IPDO
private static final int MEMBERLIST = PDOMCPPBinding.RECORD_SIZE + 4;
private static final int KEY = PDOMCPPBinding.RECORD_SIZE + 8; // byte
private static final int ANONYMOUS= PDOMCPPBinding.RECORD_SIZE + 9; // byte
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
@SuppressWarnings("hiding")
protected static final int RECORD_SIZE = PDOMCPPBinding.RECORD_SIZE + 10;
protected static final int RECORD_SIZE = PDOMCPPBinding.RECORD_SIZE + 14;
private ICPPClassScope fScope;
@ -182,6 +184,45 @@ class PDOMCPPClassType extends PDOMCPPBinding implements IPDOMCPPClassType, IPDO
base.delete();
}
}
public void addFriend(PDOMCPPFriend friend) throws CoreException {
PDOMCPPFriend firstFriend = getFirstFriend();
friend.setNextFriend(firstFriend);
setFirstFriend(friend);
}
private PDOMCPPFriend getFirstFriend() throws CoreException {
int rec = pdom.getDB().getInt(record + FIRSTFRIEND);
return rec != 0 ? new PDOMCPPFriend(pdom, rec) : null;
}
private void setFirstFriend(PDOMCPPFriend friend) throws CoreException {
int rec = friend != null ? friend.getRecord() : 0;
pdom.getDB().putInt(record + FIRSTFRIEND, rec);
}
public void removeFriend(PDOMName pdomName) throws CoreException {
PDOMCPPFriend friend = getFirstFriend();
PDOMCPPFriend predecessor= null;
int nameRec= pdomName.getRecord();
while (friend != null) {
PDOMName name = friend.getSpecifierName();
if (name != null && name.getRecord() == nameRec) {
break;
}
predecessor= friend;
friend= friend.getNextFriend();
}
if (friend != null) {
if (predecessor != null) {
predecessor.setNextFriend(friend.getNextFriend());
}
else {
setFirstFriend(friend.getNextFriend());
}
friend.delete();
}
}
public IScope getCompositeScope() throws DOMException {
if (fScope == null) {
@ -309,8 +350,15 @@ class PDOMCPPClassType extends PDOMCPPBinding implements IPDOMCPPClassType, IPDO
}
public IBinding[] getFriends() throws DOMException {
// not yet supported.
return IBinding.EMPTY_BINDING_ARRAY;
try {
final List<IBinding> list = new ArrayList<IBinding>();
for (PDOMCPPFriend friend = getFirstFriend();
friend != null; friend = friend.getNextFriend()) list.add(0,friend.getFriendSpecifier());
return list.toArray(new IBinding[list.size()]);
} catch (CoreException e) {
CCorePlugin.log(e);
return new IBinding[0];
}
}
public ICPPMethod[] getMethods() throws DOMException {

View file

@ -0,0 +1,75 @@
package org.eclipse.cdt.internal.core.pdom.dom.cpp;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.IBinding;
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.dom.PDOMName;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode;
import org.eclipse.core.runtime.CoreException;
class PDOMCPPFriend extends PDOMNode {
private static final int FRIEND_SPECIFIER = PDOMNode.RECORD_SIZE + 0;
private static final int NEXT_FRIEND = PDOMNode.RECORD_SIZE + 4;
@SuppressWarnings("hiding")
protected static final int RECORD_SIZE = PDOMNode.RECORD_SIZE + 8;
public PDOMCPPFriend(PDOM pdom, int record) {
super(pdom, record);
}
public PDOMCPPFriend(PDOM pdom, PDOMName friendSpec) throws CoreException {
super(pdom, null);
Database db = pdom.getDB();
int friendrec = friendSpec != null ? friendSpec.getRecord() : 0;
db.putInt(record + FRIEND_SPECIFIER, friendrec);
}
@Override
protected int getRecordSize() {
return RECORD_SIZE;
}
@Override
public int getNodeType() {
return IIndexCPPBindingConstants.CPP_FRIEND_DECLARATION;
}
public PDOMName getSpecifierName() throws CoreException {
int rec = pdom.getDB().getInt(record + FRIEND_SPECIFIER);
if (rec != 0) return new PDOMName(pdom, rec);
return null;
}
public IBinding getFriendSpecifier() {
PDOMName friendSpecName;
try {
friendSpecName = getSpecifierName();
if (friendSpecName != null) {
return friendSpecName.getBinding();
}
} catch (CoreException e) {
CCorePlugin.log(e);
}
return null;
}
public void setNextFriend(PDOMCPPFriend nextFriend) throws CoreException {
int rec = nextFriend != null ? nextFriend.getRecord() : 0;
pdom.getDB().putInt(record + NEXT_FRIEND, rec);
}
public PDOMCPPFriend getNextFriend() throws CoreException {
int rec = pdom.getDB().getInt(record + NEXT_FRIEND);
return rec != 0 ? new PDOMCPPFriend(pdom, rec) : null;
}
public void delete() throws CoreException {
pdom.getDB().free(record);
}
}

View file

@ -22,6 +22,7 @@ import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IEnumeration;
@ -31,6 +32,9 @@ import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective;
@ -908,6 +912,32 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
CCorePlugin.log(e);
}
}
else if (parentNode instanceof ICPPASTElaboratedTypeSpecifier) {
ICPPASTElaboratedTypeSpecifier elaboratedSpecifier = (ICPPASTElaboratedTypeSpecifier)parentNode;
if (elaboratedSpecifier.isFriend()) {
pdomName.setIsFriendSpecifier(true);
PDOMName enclClassName= (PDOMName) pdomName.getEnclosingDefinition();
PDOMBinding enclClassBinding= enclClassName.getBinding();
if (enclClassBinding instanceof PDOMCPPClassType) {
((PDOMCPPClassType)enclClassBinding).addFriend(new PDOMCPPFriend(pdom, pdomName));
}
}
}
else if (parentNode instanceof ICPPASTFunctionDeclarator) {
if (parentNode.getParent() instanceof IASTSimpleDeclaration) {
IASTSimpleDeclaration grandparentNode = (IASTSimpleDeclaration) parentNode.getParent();
if (grandparentNode.getDeclSpecifier() instanceof ICPPASTDeclSpecifier) {
if (((ICPPASTDeclSpecifier)grandparentNode.getDeclSpecifier()).isFriend()) {
pdomName.setIsFriendSpecifier(true);
PDOMName enclClassName= (PDOMName) pdomName.getEnclosingDefinition();
PDOMBinding enclClassBinding= enclClassName.getBinding();
if (enclClassBinding instanceof PDOMCPPClassType) {
((PDOMCPPClassType)enclClassBinding).addFriend(new PDOMCPPFriend(pdom, pdomName));
}
}
}
}
}
}
/* (non-Javadoc)
@ -946,6 +976,14 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
}
}
}
if (pdomName.isFriendSpecifier()) {
PDOMName enclClassName= (PDOMName) pdomName.getEnclosingDefinition();
PDOMBinding enclClassBinding= enclClassName.getBinding();
if (enclClassBinding instanceof PDOMCPPClassType) {
PDOMCPPClassType ownerClass = (PDOMCPPClassType)enclClassBinding;
ownerClass.removeFriend(pdomName);
}
}
}
@Override