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

Bug 257293: Support specializations of using declarations.

This commit is contained in:
Markus Schorn 2011-09-15 14:43:55 +02:00
parent 8bc2b56358
commit ca59d810e3
13 changed files with 272 additions and 8 deletions

View file

@ -5481,4 +5481,29 @@ public class AST2TemplateTests extends AST2BaseTest {
public void testExplicitSpecializationOfForbiddenAsImplicit_356818() throws Exception { public void testExplicitSpecializationOfForbiddenAsImplicit_356818() throws Exception {
parseAndCheckBindings(); parseAndCheckBindings();
} }
// struct A {
// void f() { }
// };
// template <typename T> struct B : A {
// using A::f;
// void f(int) { }
// };
// template <typename T> struct C : B<T> {
// using B<T>::f;
// void f(int, int);
// };
//
// void test() {
// B<float> b;
// C<float> c;
// b.f();
// b.f(1);
// c.f();
// c.f(1);
// c.f(1,1);
// }
public void testSpecializationOfUsingDeclaration_357293() throws Exception {
parseAndCheckBindings();
}
} }

View file

@ -1866,4 +1866,35 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa
IBinding[] friends = ct.getFriends(); IBinding[] friends = ct.getFriends();
assertEquals(0, friends.length); // not yet supported assertEquals(0, friends.length); // not yet supported
} }
// struct A {
// void f() { }
// };
// template <typename T> struct B : A {
// using A::f;
// void f(int) { }
// };
// template <typename T> struct C : B<T> {
// using B<T>::f;
// void f(int, int);
// };
// B<float> b;
// C<float> c;
// #include "header.h"
// void test() {
// b.f();
// b.f(1);
// c.f( );
// c.f(2);
// c.f(2,1);
// }
public void testSpecializationOfUsingDeclaration_357293() throws Exception {
getBindingFromASTName("f()", 1, ICPPMethod.class);
getBindingFromASTName("f(1)", 1, ICPPMethod.class);
getBindingFromASTName("f( )", 1, ICPPMethod.class);
getBindingFromASTName("f(2)", 1, ICPPMethod.class);
getBindingFromASTName("f(2,1)", 1, ICPPMethod.class);
}
} }

View file

@ -0,0 +1,66 @@
/*******************************************************************************
* Copyright (c) 2011 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPFunctionSet;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
/**
* Specialization of a typedef in the context of a class-specialization.
*/
public class CPPUsingDeclarationSpecialization extends CPPSpecialization implements ICPPUsingDeclaration {
private IBinding[] fDelegates;
public CPPUsingDeclarationSpecialization(ICPPUsingDeclaration specialized, ICPPClassSpecialization owner,
ICPPTemplateParameterMap tpmap) {
super(specialized, owner, tpmap);
}
public IBinding[] getDelegates() {
if (fDelegates == null) {
fDelegates= specializeDelegates();
}
return fDelegates;
}
private IBinding[] specializeDelegates() {
IBinding[] origDelegates= ((ICPPUsingDeclaration) getSpecializedBinding()).getDelegates();
List<IBinding> result= new ArrayList<IBinding>();
ICPPClassSpecialization owner= (ICPPClassSpecialization) getOwner();
for (IBinding delegate : origDelegates) {
if (delegate instanceof ICPPUnknownBinding) {
try {
delegate= CPPTemplates.resolveUnknown((ICPPUnknownBinding) delegate,
owner.getTemplateParameterMap(), -1, null);
if (delegate instanceof CPPFunctionSet) {
for (IBinding b : ((CPPFunctionSet) delegate).getBindings()) {
result.add(b);
}
} else if (delegate != null) {
result.add(delegate);
}
} catch (DOMException e) {
}
} else {
result.add(delegate);
}
}
return result.toArray(new IBinding[result.size()]);
}
}

View file

@ -2465,7 +2465,7 @@ public class CPPSemantics {
boolean haveASTResult= false; boolean haveASTResult= false;
for (ICPPFunction f : fns) { for (ICPPFunction f : fns) {
// Use the ast binding // Use the ast binding
final boolean fromIndex = f instanceof IIndexBinding; final boolean fromIndex = isFromIndex(f);
if (haveASTResult && fromIndex) if (haveASTResult && fromIndex)
break; break;

View file

@ -89,6 +89,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTemplateParameter; 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.ICPPTemplateTypeParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArraySet; import org.eclipse.cdt.core.parser.util.CharArraySet;
@ -134,6 +135,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownClass; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownClass;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownClassInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownClassInstance;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownFunction; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownFunction;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUsingDeclarationSpecialization;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPASTInternalTemplateDeclaration; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPASTInternalTemplateDeclaration;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInstanceCache; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInstanceCache;
@ -794,6 +796,8 @@ public class CPPTemplates {
} else if (decl instanceof IEnumeration || decl instanceof IEnumerator) { } else if (decl instanceof IEnumeration || decl instanceof IEnumerator) {
// TODO(sprigogin): Deal with a case when an enumerator value depends on a template parameter. // TODO(sprigogin): Deal with a case when an enumerator value depends on a template parameter.
spec = decl; spec = decl;
} else if (decl instanceof ICPPUsingDeclaration) {
spec= new CPPUsingDeclarationSpecialization((ICPPUsingDeclaration) decl, owner, tpMap);
} }
return spec; return spec;
} }
@ -2294,7 +2298,7 @@ public class CPPTemplates {
/** /**
* Attempts to (partially) resolve an unknown binding with the given arguments. * Attempts to (partially) resolve an unknown binding with the given arguments.
*/ */
private static IBinding resolveUnknown(ICPPUnknownBinding unknown, ICPPTemplateParameterMap tpMap, public static IBinding resolveUnknown(ICPPUnknownBinding unknown, ICPPTemplateParameterMap tpMap,
int packOffset, ICPPClassSpecialization within) throws DOMException { int packOffset, ICPPClassSpecialization within) throws DOMException {
if (unknown instanceof ICPPDeferredClassInstance) { if (unknown instanceof ICPPDeferredClassInstance) {
return resolveDeferredClassInstance((ICPPDeferredClassInstance) unknown, tpMap, packOffset, within); return resolveDeferredClassInstance((ICPPDeferredClassInstance) unknown, tpMap, packOffset, within);

View file

@ -58,4 +58,5 @@ public interface IIndexCPPBindingConstants {
int CPP_TEMPLATE_TEMPLATE_PARAMETER= IIndexBindingConstants.LAST_CONSTANT + 46; int CPP_TEMPLATE_TEMPLATE_PARAMETER= IIndexBindingConstants.LAST_CONSTANT + 46;
int CPP_CLASS_TEMPLATE_PARTIAL_SPEC_SPEC = IIndexBindingConstants.LAST_CONSTANT + 47; int CPP_CLASS_TEMPLATE_PARTIAL_SPEC_SPEC = IIndexBindingConstants.LAST_CONSTANT + 47;
int CPP_UNKNOWN_BINDING = IIndexBindingConstants.LAST_CONSTANT + 48; int CPP_UNKNOWN_BINDING = IIndexBindingConstants.LAST_CONSTANT + 48;
int CPP_USING_DECLARATION_SPECIALIZATION= IIndexBindingConstants.LAST_CONSTANT + 49;
} }

View file

@ -293,6 +293,8 @@ public class CPPCompositesFactory extends AbstractCompositeFactory {
return new CompositeCPPParameterSpecialization(this, (ICPPParameter) binding); return new CompositeCPPParameterSpecialization(this, (ICPPParameter) binding);
} else if (binding instanceof ITypedef) { } else if (binding instanceof ITypedef) {
return new CompositeCPPTypedefSpecialization(this, (ICPPBinding) binding); return new CompositeCPPTypedefSpecialization(this, (ICPPBinding) binding);
} else if (binding instanceof ICPPUsingDeclaration) {
return new CompositeCPPUsingDeclarationSpecialization(this, (ICPPUsingDeclaration) binding);
} else { } else {
throw new CompositingNotImplementedError("composite binding unavailable for " + binding + " " + binding.getClass()); //$NON-NLS-1$ //$NON-NLS-2$ throw new CompositingNotImplementedError("composite binding unavailable for " + binding + " " + binding.getClass()); //$NON-NLS-1$ //$NON-NLS-2$
} }

View file

@ -0,0 +1,42 @@
/*******************************************************************************
* Copyright (c) 2011 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.core.index.composite.cpp;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
import org.eclipse.cdt.core.parser.util.ObjectMap;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateParameterMap;
import org.eclipse.cdt.internal.core.index.composite.ICompositesFactory;
class CompositeCPPUsingDeclarationSpecialization extends CompositeCPPUsingDeclaration implements ICPPSpecialization {
public CompositeCPPUsingDeclarationSpecialization(ICompositesFactory cf, ICPPUsingDeclaration delegate) {
super(cf, delegate);
}
public IBinding getSpecializedBinding() {
return TemplateInstanceUtil.getSpecializedBinding(cf, rbinding);
}
public ICPPTemplateParameterMap getTemplateParameterMap() {
IBinding owner= getOwner();
if (owner instanceof ICPPSpecialization) {
return ((ICPPSpecialization) owner).getTemplateParameterMap();
}
return CPPTemplateParameterMap.EMPTY;
}
@Deprecated
public ObjectMap getArgumentMap() {
return TemplateInstanceUtil.getArgumentMap(cf, rbinding);
}
}

View file

@ -209,10 +209,11 @@ public class PDOM extends PlatformObject implements IPDOM {
* *
* CDT 8.1 development (versions not supported on teh 8.0.x branch) * CDT 8.1 development (versions not supported on teh 8.0.x branch)
* 120.0 - Enumerators in global index, bug 356235 * 120.0 - Enumerators in global index, bug 356235
* 120.1 - Specializations of using declarations, bug 357293.
*/ */
private static final int MIN_SUPPORTED_VERSION= version(120, 0); private static final int MIN_SUPPORTED_VERSION= version(120, 0);
private static final int MAX_SUPPORTED_VERSION= version(120, Short.MAX_VALUE); private static final int MAX_SUPPORTED_VERSION= version(120, Short.MAX_VALUE);
private static final int DEFAULT_VERSION = version(120, 0); private static final int DEFAULT_VERSION = version(120, 1);
private static int version(int major, int minor) { private static int version(int major, int minor) {
return (major << 16) + minor; return (major << 16) + minor;

View file

@ -379,11 +379,11 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IIndexLinkage
} }
/** /**
* Usually bindings are added on behalf of a name, only. For unknown values we need to * Usually bindings are added on behalf of a name, only. For unknown values or using declarations
* add further bindings. * we need to add further bindings.
* @throws CoreException * @throws CoreException
*/ */
public PDOMBinding addUnknownValue(IBinding binding) throws CoreException { public PDOMBinding addPotentiallyUnknownBinding(IBinding binding) throws CoreException {
return null; return null;
} }

View file

@ -239,7 +239,7 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
} }
@Override @Override
public PDOMBinding addUnknownValue(IBinding binding) throws CoreException { public PDOMBinding addPotentiallyUnknownBinding(IBinding binding) throws CoreException {
return addBinding(binding, null); return addBinding(binding, null);
} }
@ -461,6 +461,8 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
result= new PDOMCPPClassSpecialization(this, parent, (ICPPClassType) special, orig); result= new PDOMCPPClassSpecialization(this, parent, (ICPPClassType) special, orig);
} else if (special instanceof ITypedef) { } else if (special instanceof ITypedef) {
result= new PDOMCPPTypedefSpecialization(this, parent, (ITypedef) special, orig); result= new PDOMCPPTypedefSpecialization(this, parent, (ITypedef) special, orig);
} else if (special instanceof ICPPUsingDeclaration) {
result= new PDOMCPPUsingDeclarationSpecialization(this, parent, (ICPPUsingDeclaration) special, orig);
} }
return result; return result;
@ -805,6 +807,8 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
return new PDOMCPPClassTemplateSpecialization(this, record); return new PDOMCPPClassTemplateSpecialization(this, record);
case CPP_TYPEDEF_SPECIALIZATION: case CPP_TYPEDEF_SPECIALIZATION:
return new PDOMCPPTypedefSpecialization(this, record); return new PDOMCPPTypedefSpecialization(this, record);
case CPP_USING_DECLARATION_SPECIALIZATION:
return new PDOMCPPUsingDeclarationSpecialization(this, record);
} }
assert false : "nodeid= " + nodeType; //$NON-NLS-1$ assert false : "nodeid= " + nodeType; //$NON-NLS-1$
return null; return null;

View file

@ -54,7 +54,7 @@ class PDOMCPPUsingDeclaration extends PDOMCPPBinding implements ICPPUsingDeclara
Set<PDOMBinding> targets= new LinkedHashSet<PDOMBinding>(); Set<PDOMBinding> targets= new LinkedHashSet<PDOMBinding>();
PDOMCPPUsingDeclaration last= null; PDOMCPPUsingDeclaration last= null;
for (IBinding delegate : using.getDelegates()) { for (IBinding delegate : using.getDelegates()) {
PDOMBinding target = getLinkage().adaptBinding(delegate); PDOMBinding target = getLinkage().addPotentiallyUnknownBinding(delegate);
if (target != null && targets.add(target)) { if (target != null && targets.add(target)) {
if (last == null) { if (last == null) {
setTargetBinding(linkage, target); setTargetBinding(linkage, target);

View file

@ -0,0 +1,88 @@
/*******************************************************************************
* Copyright (c) 2011 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom.cpp;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.cdt.core.dom.IPDOMNode;
import org.eclipse.cdt.core.dom.IPDOMVisitor;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants;
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.PDOMBinding;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode;
import org.eclipse.core.runtime.CoreException;
class PDOMCPPUsingDeclarationSpecialization extends PDOMCPPSpecialization implements ICPPUsingDeclaration {
private static final int TARGET_BINDINGS = PDOMCPPSpecialization.RECORD_SIZE;
@SuppressWarnings("hiding")
protected static final int RECORD_SIZE = TARGET_BINDINGS + Database.PTR_SIZE;
private volatile IBinding[] delegates;
public PDOMCPPUsingDeclarationSpecialization(PDOMLinkage linkage, PDOMNode parent, ICPPUsingDeclaration using, PDOMBinding specialized)
throws CoreException {
super(linkage, parent, (ICPPSpecialization) using, specialized);
Set<PDOMBinding> targets= new LinkedHashSet<PDOMBinding>();
PDOMNodeLinkedList list = new PDOMNodeLinkedList(getLinkage(), record + TARGET_BINDINGS);
for (IBinding delegate : using.getDelegates()) {
PDOMBinding target = getLinkage().adaptBinding(delegate);
if (target != null && targets.add(target)) {
list.addMember(target);
}
}
}
public PDOMCPPUsingDeclarationSpecialization(PDOMLinkage linkage, long record) {
super(linkage, record);
}
@Override
protected int getRecordSize() {
return RECORD_SIZE;
}
@Override
public int getNodeType() {
return IIndexCPPBindingConstants.CPP_USING_DECLARATION;
}
public IBinding[] getDelegates() {
if (delegates == null) {
PDOMNodeLinkedList list= new PDOMNodeLinkedList(getLinkage(), record+TARGET_BINDINGS);
final List<IBinding> result= new ArrayList<IBinding>();
try {
list.accept(new IPDOMVisitor() {
public boolean visit(IPDOMNode node) {
if (node instanceof IBinding) {
result.add((IBinding) node);
}
return true;
}
public void leave(IPDOMNode node) {
}
});
} catch (CoreException e) {
}
delegates = result.toArray(new IBinding[result.size()]);
}
return delegates;
}
}