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:
parent
bbdc82b058
commit
65b3044dca
8 changed files with 242 additions and 10 deletions
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue