1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-05 00:36:16 +02:00

Bug 515417 - Improve handling of friend classes in PDOM

According to the standard, if a friend declaration is the only
declaration of a class type, then that class type is only
visible to argument-dependent lookup until another declaration
is encountered.

Bug 508338 attempted to implement this rule for PDOM class
types by not storing the class type in the index at all when
that first declaration is encountered. However, this meant
not recording the friend relationship either, which regressed
CompletionTests.testTypes_FriendClass (which was then disabled).

Bug 512932 implemented this rule for AST class types in a
different way, by keeping track of which names are visible to
ADL only.

This change reverts the fix for bug 508338, and extends the
approach from bug 512932 to PDOM class types. It also re-
enabled CompletionTests.testTypes_FriendClass which now passes.

Change-Id: I9a845fdba514339d86c0c3761a85cf34a17a5613
This commit is contained in:
Nathan Ridge 2017-09-24 16:17:38 -04:00
parent 10eb43465e
commit e7c64e785b
7 changed files with 45 additions and 13 deletions

View file

@ -19,6 +19,7 @@ import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IEnumerator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration;
import org.eclipse.cdt.core.index.IndexFilter;
import org.eclipse.cdt.internal.core.pdom.dom.cpp.IPDOMCPPClassType;
import org.eclipse.core.runtime.CoreException;
/**
@ -70,6 +71,13 @@ public final class BindingCollector extends NamedNodeCollector {
}
}
}
if (tBinding instanceof IPDOMCPPClassType) {
// Skip bindings that are visible to ADL only.
// TODO(nathanridge): Check if we're doing ADL, and accept it in that case.
if (((IPDOMCPPClassType) tBinding).isVisibleToAdlOnly()) {
return true;
}
}
if (filter == null || filter.acceptBinding((IBinding) tBinding)) {
return super.addNode(tBinding);
}

View file

@ -40,4 +40,11 @@ public interface IPDOMCPPClassType extends ICPPClassType, IPDOMBinding, IIndexTy
* @param visibility The visibility of the <code>member</code>.
*/
void addMember(PDOMNode member, int visibility) throws CoreException;
/**
* Returns true if this class type is visible to ADL only.
* A class type is visible to ADL only if it's only declaration so far
* is a friend declaration inside another class.
*/
default boolean isVisibleToAdlOnly() { return false; }
}

View file

@ -60,9 +60,10 @@ public class PDOMCPPClassTemplate extends PDOMCPPClassType
private volatile ICPPTemplateParameter[] params; // Cached template parameters.
public PDOMCPPClassTemplate(PDOMCPPLinkage linkage, PDOMNode parent, ICPPClassTemplate template)
public PDOMCPPClassTemplate(PDOMCPPLinkage linkage, PDOMNode parent, ICPPClassTemplate template,
boolean visibleToAdlOnly)
throws CoreException, DOMException {
super(linkage, parent, template);
super(linkage, parent, template, visibleToAdlOnly);
final Database db = getDB();
ICPPTemplateParameter[] origParams= template.getTemplateParameters();

View file

@ -49,7 +49,7 @@ class PDOMCPPClassTemplatePartialSpecialization extends PDOMCPPClassTemplate
public PDOMCPPClassTemplatePartialSpecialization(PDOMCPPLinkage linkage, PDOMNode parent,
ICPPClassTemplatePartialSpecialization partial, PDOMCPPClassTemplate primary)
throws CoreException, DOMException {
super(linkage, parent, partial);
super(linkage, parent, partial, false);
getDB().putRecPtr(record + PRIMARY, primary.getRecord());
primary.addPartial(this);

View file

@ -56,17 +56,20 @@ class PDOMCPPClassType extends PDOMCPPBinding implements IPDOMCPPClassType, IPDO
private static final int KEY = FIRSTFRIEND + 4; // byte
private static final int ANONYMOUS = KEY + 1; // byte
private static final int FINAL = ANONYMOUS + 1; // byte
private static final int VISIBLE_TO_ADL_ONLY = FINAL + 1; // byte
@SuppressWarnings("hiding")
protected static final int RECORD_SIZE = FINAL + 1;
protected static final int RECORD_SIZE = VISIBLE_TO_ADL_ONLY + 1;
private PDOMCPPClassScope fScope; // No need for volatile, all fields of PDOMCPPClassScope are final.
public PDOMCPPClassType(PDOMLinkage linkage, PDOMNode parent, ICPPClassType classType) throws CoreException {
public PDOMCPPClassType(PDOMLinkage linkage, PDOMNode parent, ICPPClassType classType,
boolean visibleToAdlOnly) throws CoreException {
super(linkage, parent, classType.getNameCharArray());
setKind(classType);
setAnonymous(classType);
setFinal(classType);
setVisibleToAdlOnly(visibleToAdlOnly);
// Linked list is initialized by storage being zero'd by malloc.
}
@ -106,6 +109,10 @@ class PDOMCPPClassType extends PDOMCPPBinding implements IPDOMCPPClassType, IPDO
private void setFinal(ICPPClassType ct) throws CoreException {
getDB().putByte(record + FINAL, (byte) (ct.isFinal() ? 1 : 0));
}
private void setVisibleToAdlOnly(boolean visibleToAdlOnly) throws CoreException {
getDB().putByte(record + VISIBLE_TO_ADL_ONLY, (byte) (visibleToAdlOnly ? 1 : 0));
}
@Override
public boolean mayHaveChildren() {
@ -268,6 +275,16 @@ class PDOMCPPClassType extends PDOMCPPBinding implements IPDOMCPPClassType, IPDO
return false;
}
}
@Override
public boolean isVisibleToAdlOnly() {
try {
return getDB().getByte(record + VISIBLE_TO_ADL_ONLY) != 0;
} catch (CoreException e) {
CCorePlugin.log(e);
return false;
}
}
@Override
public boolean isSameType(IType type) {

View file

@ -796,13 +796,12 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
// name is not found by name lookup until a matching declaration is provided in the innermost
// enclosing nonclass scope.
// See http://bugs.eclipse.org/508338
if (!(binding instanceof ICPPInternalBinding)
|| ASTInternal.hasNonFriendDeclaration((ICPPInternalBinding) binding)) {
if (binding instanceof ICPPClassTemplate) {
pdomBinding= new PDOMCPPClassTemplate(this, parent, (ICPPClassTemplate) binding);
} else {
pdomBinding= new PDOMCPPClassType(this, parent, (ICPPClassType) binding);
}
boolean visibleToAdlOnly = (binding instanceof ICPPInternalBinding)
&& !ASTInternal.hasNonFriendDeclaration((ICPPInternalBinding) binding);
if (binding instanceof ICPPClassTemplate) {
pdomBinding= new PDOMCPPClassTemplate(this, parent, (ICPPClassTemplate) binding, visibleToAdlOnly);
} else {
pdomBinding= new PDOMCPPClassType(this, parent, (ICPPClassType) binding, visibleToAdlOnly);
}
} else if (binding instanceof ICPPVariableTemplate) {
pdomBinding = new PDOMCPPVariableTemplate(this, parent, (ICPPVariableTemplate) binding);

View file

@ -220,7 +220,7 @@ public class CompletionTests extends CompletionTestBase {
}
//class _friend_class { C3* x; void m() {x->m/*cursor*/
public void DISABLED_Bug_515417_testTypes_FriendClass() throws Exception {
public void testTypes_FriendClass() throws Exception {
final String[] expected= {
"m123(void)", "m12(void)", "m13(void)", "m23(void)", "m1protected(void)",
"m2protected(void)", "m2private(void)"